forked from tangled.org/core
Monorepo for Tangled

appview: add personal pronouns to profile

Signed-off-by: Shalabh Agarwal <me@serendipty01.dev>

fixes: https://tangled.org/@tangled.org/core/issues/224

authored by serendipty01.dev and committed by Tangled df2a0d82 1b21764c

Changed files
+64 -6
api
tangled
appview
db
models
pages
templates
state
lexicons
actor
+1
api/tangled/actorprofile.go
··· 28 // pinnedRepositories: Any ATURI, it is up to appviews to validate these fields. 29 PinnedRepositories []string `json:"pinnedRepositories,omitempty" cborgen:"pinnedRepositories,omitempty"` 30 Stats []string `json:"stats,omitempty" cborgen:"stats,omitempty"` 31 }
··· 28 // pinnedRepositories: Any ATURI, it is up to appviews to validate these fields. 29 PinnedRepositories []string `json:"pinnedRepositories,omitempty" cborgen:"pinnedRepositories,omitempty"` 30 Stats []string `json:"stats,omitempty" cborgen:"stats,omitempty"` 31 + Pronouns *string `json:"pronouns,omitempty" cborgen:"pronouns,omitempty"` 32 }
+7
appview/db/db.go
··· 1106 return err 1107 }) 1108 1109 return &DB{ 1110 db, 1111 logger,
··· 1106 return err 1107 }) 1108 1109 + runMigration(conn, logger, "add-pronouns-profile", func(tx *sql.Tx) error { 1110 + _, err := tx.Exec(` 1111 + alter table profile add column pronouns text; 1112 + `) 1113 + return err 1114 + }) 1115 + 1116 return &DB{ 1117 db, 1118 logger,
+26 -6
appview/db/profile.go
··· 129 did, 130 description, 131 include_bluesky, 132 - location 133 ) 134 - values (?, ?, ?, ?)`, 135 profile.Did, 136 profile.Description, 137 includeBskyValue, 138 profile.Location, 139 ) 140 141 if err != nil { ··· 216 did, 217 description, 218 include_bluesky, 219 - location 220 from 221 profile 222 %s`, ··· 231 for rows.Next() { 232 var profile models.Profile 233 var includeBluesky int 234 235 - err = rows.Scan(&profile.ID, &profile.Did, &profile.Description, &includeBluesky, &profile.Location) 236 if err != nil { 237 return nil, err 238 } 239 240 if includeBluesky != 0 { 241 profile.IncludeBluesky = true 242 } 243 244 profileMap[profile.Did] = &profile ··· 302 303 func GetProfile(e Execer, did string) (*models.Profile, error) { 304 var profile models.Profile 305 profile.Did = did 306 307 includeBluesky := 0 308 err := e.QueryRow( 309 - `select description, include_bluesky, location from profile where did = ?`, 310 did, 311 - ).Scan(&profile.Description, &includeBluesky, &profile.Location) 312 if err == sql.ErrNoRows { 313 profile := models.Profile{} 314 profile.Did = did ··· 321 322 if includeBluesky != 0 { 323 profile.IncludeBluesky = true 324 } 325 326 rows, err := e.Query(`select link from profile_links where did = ?`, did) ··· 412 // ensure description is not too long 413 if len(profile.Location) > 40 { 414 return fmt.Errorf("Entered location is too long.") 415 } 416 417 // ensure links are in order
··· 129 did, 130 description, 131 include_bluesky, 132 + location, 133 + pronouns 134 ) 135 + values (?, ?, ?, ?, ?)`, 136 profile.Did, 137 profile.Description, 138 includeBskyValue, 139 profile.Location, 140 + profile.Pronouns, 141 ) 142 143 if err != nil { ··· 218 did, 219 description, 220 include_bluesky, 221 + location, 222 + pronouns 223 from 224 profile 225 %s`, ··· 234 for rows.Next() { 235 var profile models.Profile 236 var includeBluesky int 237 + var pronouns sql.Null[string] 238 239 + err = rows.Scan(&profile.ID, &profile.Did, &profile.Description, &includeBluesky, &profile.Location, &pronouns) 240 if err != nil { 241 return nil, err 242 } 243 244 if includeBluesky != 0 { 245 profile.IncludeBluesky = true 246 + } 247 + 248 + if pronouns.Valid { 249 + profile.Pronouns = pronouns.V 250 } 251 252 profileMap[profile.Did] = &profile ··· 310 311 func GetProfile(e Execer, did string) (*models.Profile, error) { 312 var profile models.Profile 313 + var pronouns sql.Null[string] 314 + 315 profile.Did = did 316 317 includeBluesky := 0 318 + 319 err := e.QueryRow( 320 + `select description, include_bluesky, location, pronouns from profile where did = ?`, 321 did, 322 + ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns) 323 if err == sql.ErrNoRows { 324 profile := models.Profile{} 325 profile.Did = did ··· 332 333 if includeBluesky != 0 { 334 profile.IncludeBluesky = true 335 + } 336 + 337 + if pronouns.Valid { 338 + profile.Pronouns = pronouns.V 339 } 340 341 rows, err := e.Query(`select link from profile_links where did = ?`, did) ··· 427 // ensure description is not too long 428 if len(profile.Location) > 40 { 429 return fmt.Errorf("Entered location is too long.") 430 + } 431 + 432 + // ensure pronouns are not too long 433 + if len(profile.Pronouns) > 40 { 434 + return fmt.Errorf("Entered pronouns are too long.") 435 } 436 437 // ensure links are in order
+6
appview/ingester.go
··· 291 292 includeBluesky := record.Bluesky 293 294 location := "" 295 if record.Location != nil { 296 location = *record.Location ··· 325 Links: links, 326 Stats: stats, 327 PinnedRepos: pinned, 328 } 329 330 ddb, ok := i.Db.Execer.(*db.DB)
··· 291 292 includeBluesky := record.Bluesky 293 294 + pronouns := "" 295 + if record.Pronouns != nil { 296 + pronouns = *record.Pronouns 297 + } 298 + 299 location := "" 300 if record.Location != nil { 301 location = *record.Location ··· 330 Links: links, 331 Stats: stats, 332 PinnedRepos: pinned, 333 + Pronouns: pronouns, 334 } 335 336 ddb, ok := i.Db.Execer.(*db.DB)
+1
appview/models/profile.go
··· 19 Links [5]string 20 Stats [2]VanityStat 21 PinnedRepos [6]syntax.ATURI 22 } 23 24 func (p Profile) IsLinksEmpty() bool {
··· 19 Links [5]string 20 Stats [2]VanityStat 21 PinnedRepos [6]syntax.ATURI 22 + Pronouns string 23 } 24 25 func (p Profile) IsLinksEmpty() bool {
+11
appview/pages/templates/user/fragments/editBio.html
··· 20 </div> 21 22 <div class="flex flex-col gap-1"> 23 <label class="m-0 p-0" for="location">location</label> 24 <div class="flex items-center gap-2 w-full"> 25 {{ $location := "" }}
··· 20 </div> 21 22 <div class="flex flex-col gap-1"> 23 + <label class="m-0 p-0" for="pronouns">pronouns</label> 24 + <div class="flex items-center gap-2 w-full"> 25 + {{ $pronouns := "" }} 26 + {{ if and .Profile .Profile.Pronouns }} 27 + {{ $pronouns = .Profile.Pronouns }} 28 + {{ end }} 29 + <input type="text" class="py-1 px-1 w-full" name="pronouns" value="{{ $pronouns }}"> 30 + </div> 31 + </div> 32 + 33 + <div class="flex flex-col gap-1"> 34 <label class="m-0 p-0" for="location">location</label> 35 <div class="flex items-center gap-2 w-full"> 36 {{ $location := "" }}
+5
appview/pages/templates/user/fragments/profileCard.html
··· 12 class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap"> 13 {{ $userIdent }} 14 </p> 15 <a href="/{{ $userIdent }}/feed.atom">{{ i "rss" "size-4" }}</a> 16 </div> 17
··· 12 class="text-lg font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap"> 13 {{ $userIdent }} 14 </p> 15 + {{ with .Profile }} 16 + {{ if .Pronouns }} 17 + <p class="text-gray-500 dark:text-gray-400">{{ .Pronouns }}</p> 18 + {{ end }} 19 + {{ end }} 20 <a href="/{{ $userIdent }}/feed.atom">{{ i "rss" "size-4" }}</a> 21 </div> 22
+2
appview/state/profile.go
··· 538 profile.Description = r.FormValue("description") 539 profile.IncludeBluesky = r.FormValue("includeBluesky") == "on" 540 profile.Location = r.FormValue("location") 541 542 var links [5]string 543 for i := range 5 { ··· 652 Location: &profile.Location, 653 PinnedRepositories: pinnedRepoStrings, 654 Stats: vanityStats[:], 655 }}, 656 SwapRecord: cid, 657 })
··· 538 profile.Description = r.FormValue("description") 539 profile.IncludeBluesky = r.FormValue("includeBluesky") == "on" 540 profile.Location = r.FormValue("location") 541 + profile.Pronouns = r.FormValue("pronouns") 542 543 var links [5]string 544 for i := range 5 { ··· 653 Location: &profile.Location, 654 PinnedRepositories: pinnedRepoStrings, 655 Stats: vanityStats[:], 656 + Pronouns: &profile.Pronouns, 657 }}, 658 SwapRecord: cid, 659 })
+5
lexicons/actor/profile.json
··· 64 "type": "string", 65 "format": "at-uri" 66 } 67 } 68 } 69 }
··· 64 "type": "string", 65 "format": "at-uri" 66 } 67 + }, 68 + "pronouns": { 69 + "type": "string", 70 + "description": "Preferred gender pronouns.", 71 + "maxLength": 40 72 } 73 } 74 }