Monorepo for Tangled tangled.org

appview: add personal pronouns to profile

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

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

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