Monorepo for Tangled tangled.org

appview: allows a default knot to be configured #858

closed opened by willdot.net targeting master from [deleted fork]: master

This follows on from the work carried out in #836

I've added a select box in the Knots settings page which pulls in the users knots and also adds in knot1.tangled.sh. When the user selects one of these options, it will save to their profile in the database. NOTE: I haven't yet implemented adding that to the AT record because I'm not sure on how the lexicon setup works yet!

Then when users go to create a new repo / fork, if there is a value in their profile for the default knot, then that will pre select the knot to use for the new repo / fork.

Labels

None yet.

assignee

None yet.

Participants 2
AT URI
at://did:plc:dadhhalkfcq3gucaq25hjqon/sh.tangled.repo.pull/3m7glmp44b322
+115 -6
Diff #3
+7
appview/db/db.go
··· 1174 1174 return err 1175 1175 }) 1176 1176 1177 + runMigration(conn, logger, "add-default-knot-profile", func(tx *sql.Tx) error { 1178 + _, err := tx.Exec(` 1179 + alter table profile add column default_knot text; 1180 + `) 1181 + return err 1182 + }) 1183 + 1177 1184 return &DB{ 1178 1185 db, 1179 1186 logger,
+11 -4
appview/db/profile.go
··· 130 130 description, 131 131 include_bluesky, 132 132 location, 133 - pronouns 133 + pronouns, 134 + default_knot 134 135 ) 135 - values (?, ?, ?, ?, ?)`, 136 + values (?, ?, ?, ?, ?, ?)`, 136 137 profile.Did, 137 138 profile.Description, 138 139 includeBskyValue, 139 140 profile.Location, 140 141 profile.Pronouns, 142 + profile.DefaultKnot, 141 143 ) 142 144 143 145 if err != nil { ··· 311 313 func GetProfile(e Execer, did string) (*models.Profile, error) { 312 314 var profile models.Profile 313 315 var pronouns sql.Null[string] 316 + var defaultKnot sql.Null[string] 314 317 315 318 profile.Did = did 316 319 317 320 includeBluesky := 0 318 321 319 322 err := e.QueryRow( 320 - `select description, include_bluesky, location, pronouns from profile where did = ?`, 323 + `select description, include_bluesky, location, pronouns, default_knot from profile where did = ?`, 321 324 did, 322 - ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns) 325 + ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns, &defaultKnot) 323 326 if err == sql.ErrNoRows { 324 327 profile := models.Profile{} 325 328 profile.Did = did ··· 338 341 profile.Pronouns = pronouns.V 339 342 } 340 343 344 + if defaultKnot.Valid { 345 + profile.DefaultKnot = defaultKnot.V 346 + } 347 + 341 348 rows, err := e.Query(`select link from profile_links where did = ?`, did) 342 349 if err != nil { 343 350 return nil, err
+10
appview/knots/knots.go
··· 80 80 return 81 81 } 82 82 83 + defaultKnot := "" 84 + profile, err := db.GetProfile(k.Db, user.Did) 85 + if err != nil { 86 + k.Logger.Warn("gettings user profile to get default knot", "error", err) 87 + } 88 + if profile != nil { 89 + defaultKnot = profile.DefaultKnot 90 + } 91 + 83 92 k.Pages.Knots(w, pages.KnotsParams{ 84 93 LoggedInUser: user, 85 94 Registrations: registrations, 86 95 Tabs: knotsTabs, 87 96 Tab: "knots", 97 + DefaultKnot: defaultKnot, 88 98 }) 89 99 } 90 100
+1
appview/models/profile.go
··· 20 20 Stats [2]VanityStat 21 21 PinnedRepos [6]syntax.ATURI 22 22 Pronouns string 23 + DefaultKnot string 23 24 } 24 25 25 26 func (p Profile) IsLinksEmpty() bool {
+3
appview/pages/pages.go
··· 409 409 Registrations []models.Registration 410 410 Tabs []map[string]any 411 411 Tab string 412 + DefaultKnot string 412 413 } 413 414 414 415 func (p *Pages) Knots(w io.Writer, params KnotsParams) error { ··· 474 475 type NewRepoParams struct { 475 476 LoggedInUser *oauth.User 476 477 Knots []string 478 + DefaultKnot string 477 479 } 478 480 479 481 func (p *Pages) NewRepo(w io.Writer, params NewRepoParams) error { ··· 484 486 LoggedInUser *oauth.User 485 487 Knots []string 486 488 RepoInfo repoinfo.RepoInfo 489 + DefaultKnot string 487 490 } 488 491 489 492 func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error {
+24
appview/pages/templates/knots/index.html
··· 31 31 <div class="flex flex-col gap-6"> 32 32 {{ block "list" . }} {{ end }} 33 33 {{ block "register" . }} {{ end }} 34 + {{ block "default-knot" . }} {{ end }} 34 35 </div> 35 36 </section> 36 37 {{ end }} ··· 62 63 </section> 63 64 {{ end }} 64 65 66 + {{ define "default-knot" }} 67 + <section class="rounded w-full flex flex-col gap-2"> 68 + <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">default knot</h2> 69 + <select id="default-knot" name="default-knot" 70 + class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700" 71 + hx-post="/profile/default-knot" 72 + hx-swap="none" 73 + name="default-knot"> 74 + <option value="" > 75 + Choose a default Knot 76 + </option> 77 + <option value="knot1.tangled.sh" {{if eq $.DefaultKnot "knot1.tangled.sh"}}selected{{end}} > 78 + knot1.tangled.sh 79 + </option> 80 + {{ range $registration := .Registrations }} 81 + <option value="{{ .Domain }}" class="py-1" {{if eq $.DefaultKnot .Domain}}selected{{end}}> 82 + {{ .Domain }} 83 + </option> 84 + {{ end }} 85 + </select> 86 + </section> 87 + {{ end }} 88 + 65 89 {{ define "register" }} 66 90 <section class="rounded w-full lg:w-fit flex flex-col gap-2"> 67 91 <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a knot</h2>
+3 -1
appview/pages/templates/repo/fork.html
··· 25 25 value="{{ . }}" 26 26 class="mr-2" 27 27 id="domain-{{ . }}" 28 - {{if eq (len $.Knots) 1}}checked{{end}} 28 + {{if eq (len $.Knots) 1}}checked 29 + {{else if eq $.DefaultKnot . }}checked 30 + {{end}} 29 31 /> 30 32 <label for="domain-{{ . }}" class="dark:text-white">{{ . }}</label> 31 33 </div>
+3 -1
appview/pages/templates/repo/new.html
··· 155 155 class="mr-2" 156 156 id="domain-{{ . }}" 157 157 required 158 - {{if eq (len $.Knots) 1}}checked{{end}} 158 + {{if eq (len $.Knots) 1}}checked 159 + {{else if eq $.DefaultKnot . }}checked 160 + {{end}} 159 161 /> 160 162 <label for="domain-{{ . }}" class="dark:text-white lowercase">{{ . }}</label> 161 163 </div>
+10
appview/repo/repo.go
··· 1003 1003 return 1004 1004 } 1005 1005 1006 + defaultKnot := "" 1007 + profile, err := db.GetProfile(rp.db, user.Did) 1008 + if err != nil { 1009 + rp.logger.Warn("gettings user profile to get default knot", "error", err) 1010 + } 1011 + if profile != nil { 1012 + defaultKnot = profile.DefaultKnot 1013 + } 1014 + 1006 1015 rp.pages.ForkRepo(w, pages.ForkRepoParams{ 1007 1016 LoggedInUser: user, 1008 1017 Knots: knots, 1009 1018 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1019 + DefaultKnot: defaultKnot, 1010 1020 }) 1011 1021 1012 1022 case http.MethodPost:
+32
appview/state/profile.go
··· 613 613 s.updateProfile(profile, w, r) 614 614 } 615 615 616 + func (s *State) UpdateProfileDefaultKnot(w http.ResponseWriter, r *http.Request) { 617 + err := r.ParseForm() 618 + if err != nil { 619 + log.Println("invalid profile update form", err) 620 + return 621 + } 622 + user := s.oauth.GetUser(r) 623 + 624 + profile, err := db.GetProfile(s.db, user.Did) 625 + if err != nil { 626 + log.Printf("getting profile data for %s: %s", user.Did, err) 627 + } 628 + 629 + if profile == nil { 630 + return 631 + } 632 + 633 + profile.DefaultKnot = r.Form.Get("default-knot") 634 + 635 + tx, err := s.db.BeginTx(r.Context(), nil) 636 + if err != nil { 637 + log.Println("failed to start transaction", err) 638 + return 639 + } 640 + 641 + err = db.UpsertProfile(tx, profile) 642 + if err != nil { 643 + log.Println("failed to update profile", err) 644 + return 645 + } 646 + } 647 + 616 648 func (s *State) updateProfile(profile *models.Profile, w http.ResponseWriter, r *http.Request) { 617 649 user := s.oauth.GetUser(r) 618 650 tx, err := s.db.BeginTx(r.Context(), nil)
+1
appview/state/router.go
··· 162 162 r.Get("/edit-pins", s.EditPinsFragment) 163 163 r.Post("/bio", s.UpdateProfileBio) 164 164 r.Post("/pins", s.UpdateProfilePins) 165 + r.Post("/default-knot", s.UpdateProfileDefaultKnot) 165 166 }) 166 167 167 168 r.Mount("/settings", s.SettingsRouter())
+10
appview/state/state.go
··· 453 453 return 454 454 } 455 455 456 + defaultKnot := "" 457 + profile, err := db.GetProfile(s.db, user.Did) 458 + if err != nil { 459 + s.logger.Warn("gettings user profile to get default knot", "error", err) 460 + } 461 + if profile != nil { 462 + defaultKnot = profile.DefaultKnot 463 + } 464 + 456 465 s.pages.NewRepo(w, pages.NewRepoParams{ 457 466 LoggedInUser: user, 458 467 Knots: knots, 468 + DefaultKnot: defaultKnot, 459 469 }) 460 470 461 471 case http.MethodPost:

History

4 rounds 8 comments
sign up or login to add to the discussion
1 commit
expand
ead0762e
appview: allows a default knot to be configured
expand 2 comments

I've fucked up @oppi.li

I had to delete my fork last week because I messed it up badly 馃檲 And now I can't fix the merge conflicts.

Is there an easy way to rectify changing this PR to my new fork or should I just cut my losses and start the PR from scratch (fixing the merge conflicts by doing so)

im afraid there is no way to do that right now, probably best to open a new PR!

closed without merging
3 commits
expand
fe49521e
appview: allows a default knot to be configured
48ed4260
undo flake.lock change
3eae6087
appview: nil check when getting profile
expand 6 comments

valuable addition!

this strikes me more as a preference, i don't think this should go into the profile record however.

Do you mean the AT record or the database record?

I鈥檓 now doubting storing it in AT record because the default knot1.tangled.sh is only available in the tangled app view, not a 3rd party app view!

thanks for the work on this. comments:

  • can we squash all of this work into just one commit?
  • the PR also touches a few other template files, are these changes relevant to this addition? could we extract that to a different PR/commit?

will give this a quick test!

Oh I鈥檓 not sure why those files have changed. I鈥檒l revert them. Probably my IDE autoformat.

Ok squashed the commits into a single commit, which also removed the random files that had been changed from the diff 馃ぃ

2 commits
expand
fe49521e
appview: allows a default knot to be configured
48ed4260
undo flake.lock change
expand 0 comments
1 commit
expand
fe49521e
appview: allows a default knot to be configured
expand 0 comments