Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/state: Moved /knots & /spindle to /settings

Signed-off-by: 5jiji <git@5jiji.com>
Signed-off-by: Seongmin Lee <git@boltless.me>

authored by

5jiji and committed by
Seongmin Lee
ca41f242 4cafba2a

+246 -106
+18 -1
appview/knots/knots.go
··· 39 39 Knotstream *eventconsumer.Consumer 40 40 } 41 41 42 + type tab = map[string]any 43 + 44 + var ( 45 + knotsTabs []tab = []tab{ 46 + {"Name": "profile", "Icon": "user"}, 47 + {"Name": "keys", "Icon": "key"}, 48 + {"Name": "emails", "Icon": "mail"}, 49 + {"Name": "notifications", "Icon": "bell"}, 50 + {"Name": "knots", "Icon": "volleyball"}, 51 + {"Name": "spindles", "Icon": "spool"}, 52 + } 53 + ) 54 + 42 55 func (k *Knots) Router() http.Handler { 43 56 r := chi.NewRouter() 44 57 ··· 83 70 k.Pages.Knots(w, pages.KnotsParams{ 84 71 LoggedInUser: user, 85 72 Registrations: registrations, 73 + Tabs: knotsTabs, 74 + Tab: "knots", 86 75 }) 87 76 } 88 77 ··· 147 132 Members: members, 148 133 Repos: repoMap, 149 134 IsOwner: true, 135 + Tabs: knotsTabs, 136 + Tab: "knots", 150 137 }) 151 138 } 152 139 ··· 613 596 } 614 597 615 598 // success 616 - k.Pages.HxRedirect(w, fmt.Sprintf("/knots/%s", domain)) 599 + k.Pages.HxRedirect(w, fmt.Sprintf("/settings/knots/%s", domain)) 617 600 } 618 601 619 602 func (k *Knots) removeMember(w http.ResponseWriter, r *http.Request) {
+10
appview/pages/pages.go
··· 407 407 type KnotsParams struct { 408 408 LoggedInUser *oauth.User 409 409 Registrations []models.Registration 410 + Tabs []map[string]any 411 + Tab string 410 412 } 411 413 412 414 func (p *Pages) Knots(w io.Writer, params KnotsParams) error { ··· 421 419 Members []string 422 420 Repos map[string][]models.Repo 423 421 IsOwner bool 422 + Tabs []map[string]any 423 + Tab string 424 424 } 425 425 426 426 func (p *Pages) Knot(w io.Writer, params KnotParams) error { ··· 440 436 type SpindlesParams struct { 441 437 LoggedInUser *oauth.User 442 438 Spindles []models.Spindle 439 + Tabs []map[string]any 440 + Tab string 443 441 } 444 442 445 443 func (p *Pages) Spindles(w io.Writer, params SpindlesParams) error { ··· 450 444 451 445 type SpindleListingParams struct { 452 446 models.Spindle 447 + Tabs []map[string]any 448 + Tab string 453 449 } 454 450 455 451 func (p *Pages) SpindleListing(w io.Writer, params SpindleListingParams) error { ··· 463 455 Spindle models.Spindle 464 456 Members []string 465 457 Repos map[string][]models.Repo 458 + Tabs []map[string]any 459 + Tab string 466 460 } 467 461 468 462 func (p *Pages) SpindleDashboard(w io.Writer, params SpindleDashboardParams) error {
+23 -7
appview/pages/templates/knots/dashboard.html
··· 1 - {{ define "title" }}{{ .Registration.Domain }} &middot; knots{{ end }} 1 + {{ define "title" }}{{ .Registration.Domain }} &middot; {{ .Tab }} settings{{ end }} 2 2 3 3 {{ define "content" }} 4 - <div class="px-6 py-4"> 4 + <div class="p-6"> 5 + <p class="text-xl font-bold dark:text-white">Settings</p> 6 + </div> 7 + <div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 8 + <section class="w-full grid grid-cols-1 md:grid-cols-4 gap-6"> 9 + <div class="col-span-1"> 10 + {{ template "user/settings/fragments/sidebar" . }} 11 + </div> 12 + <div class="col-span-1 md:col-span-3 flex flex-col gap-6"> 13 + {{ template "knotDash" . }} 14 + </div> 15 + </section> 16 + </div> 17 + {{ end }} 18 + 19 + {{ define "knotDash" }} 20 + <div> 5 21 <div class="flex justify-between items-center"> 6 - <h1 class="text-xl font-bold dark:text-white">{{ .Registration.Domain }}</h1> 22 + <h2 class="text-sm pb-2 uppercase font-bold">{{ .Tab }} &middot; {{ .Registration.Domain }}</h2> 7 23 <div id="right-side" class="flex gap-2"> 8 24 {{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }} 9 25 {{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Registration.ByDid) }} ··· 51 35 </div> 52 36 53 37 {{ if .Members }} 54 - <section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 38 + <section class="bg-white dark:bg-gray-800 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 55 39 <div class="flex flex-col gap-2"> 56 40 {{ block "member" . }} {{ end }} 57 41 </div> ··· 95 79 <button 96 80 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 97 81 title="Delete knot" 98 - hx-delete="/knots/{{ .Domain }}" 82 + hx-delete="/settings/knots/{{ .Domain }}" 99 83 hx-swap="outerHTML" 100 84 hx-confirm="Are you sure you want to delete the knot '{{ .Domain }}'?" 101 85 hx-headers='{"shouldRedirect": "true"}' ··· 111 95 <button 112 96 class="btn gap-2 group" 113 97 title="Retry knot verification" 114 - hx-post="/knots/{{ .Domain }}/retry" 98 + hx-post="/settings/knots/{{ .Domain }}/retry" 115 99 hx-swap="none" 116 100 hx-headers='{"shouldRefresh": "true"}' 117 101 > ··· 129 113 <button 130 114 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 131 115 title="Remove member" 132 - hx-post="/knots/{{ $root.Registration.Domain }}/remove" 116 + hx-post="/settings/knots/{{ $root.Registration.Domain }}/remove" 133 117 hx-swap="none" 134 118 hx-vals='{"member": "{{$member}}" }' 135 119 hx-confirm="Are you sure you want to remove {{ $memberHandle }} from this knot?"
+1 -1
appview/pages/templates/knots/fragments/addMemberModal.html
··· 22 22 23 23 {{ define "addKnotMemberPopover" }} 24 24 <form 25 - hx-post="/knots/{{ .Domain }}/add" 25 + hx-post="/settings/knots/{{ .Domain }}/add" 26 26 hx-indicator="#spinner" 27 27 hx-swap="none" 28 28 class="flex flex-col gap-2"
+3 -3
appview/pages/templates/knots/fragments/knotListing.html
··· 7 7 8 8 {{ define "knotLeftSide" }} 9 9 {{ if .Registered }} 10 - <a href="/knots/{{ .Domain }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]"> 10 + <a href="/settings/knots/{{ .Domain }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]"> 11 11 {{ i "hard-drive" "w-4 h-4" }} 12 12 <span class="hover:underline"> 13 13 {{ .Domain }} ··· 56 56 <button 57 57 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 58 58 title="Delete knot" 59 - hx-delete="/knots/{{ .Domain }}" 59 + hx-delete="/settings/knots/{{ .Domain }}" 60 60 hx-swap="outerHTML" 61 61 hx-target="#knot-{{.Id}}" 62 62 hx-confirm="Are you sure you want to delete the knot '{{ .Domain }}'?" ··· 72 72 <button 73 73 class="btn gap-2 group" 74 74 title="Retry knot verification" 75 - hx-post="/knots/{{ .Domain }}/retry" 75 + hx-post="/settings/knots/{{ .Domain }}/retry" 76 76 hx-swap="none" 77 77 hx-target="#knot-{{.Id}}" 78 78 >
+42 -11
appview/pages/templates/knots/index.html
··· 1 - {{ define "title" }}knots{{ end }} 1 + {{ define "title" }}{{ .Tab }} settings{{ end }} 2 2 3 3 {{ define "content" }} 4 - <div class="px-6 py-4 flex items-center justify-between gap-4 align-bottom"> 5 - <h1 class="text-xl font-bold dark:text-white">Knots</h1> 6 - <span class="flex items-center gap-1"> 7 - {{ i "book" "w-3 h-3" }} 8 - <a href="https://tangled.org/@tangled.org/core/blob/master/docs/knot-hosting.md">docs</a> 9 - </span> 10 - </div> 4 + <div class="p-6"> 5 + <p class="text-xl font-bold dark:text-white">Settings</p> 6 + </div> 7 + <div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 8 + <section class="w-full grid grid-cols-1 md:grid-cols-4 gap-6"> 9 + <div class="col-span-1"> 10 + {{ template "user/settings/fragments/sidebar" . }} 11 + </div> 12 + <div class="col-span-1 md:col-span-3 flex flex-col gap-6"> 13 + {{ template "knotsList" . }} 14 + </div> 15 + </section> 16 + </div> 17 + {{ end }} 11 18 12 - <section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 19 + {{ define "knotsList" }} 20 + <div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center"> 21 + <div class="col-span-1 md:col-span-2"> 22 + <h2 class="text-sm pb-2 uppercase font-bold">Knots</h2> 23 + {{ block "about" . }} {{ end }} 24 + </div> 25 + <div class="col-span-1 md:col-span-1 md:justify-self-end"> 26 + {{ template "docsButton" . }} 27 + </div> 28 + </div> 29 + 30 + <section> 13 31 <div class="flex flex-col gap-6"> 14 - {{ block "about" . }} {{ end }} 15 32 {{ block "list" . }} {{ end }} 16 33 {{ block "register" . }} {{ end }} 17 34 </div> ··· 67 50 <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a knot</h2> 68 51 <p class="mb-2 dark:text-gray-300">Enter the hostname of your knot to get started.</p> 69 52 <form 70 - hx-post="/knots/register" 53 + hx-post="/settings/knots/register" 71 54 class="max-w-2xl mb-2 space-y-4" 72 55 hx-indicator="#register-button" 73 56 hx-swap="none" ··· 100 83 </form> 101 84 102 85 </section> 86 + {{ end }} 87 + 88 + {{ define "docsButton" }} 89 + <a 90 + class="btn flex items-center gap-2" 91 + href="https://tangled.org/@tangled.org/core/blob/master/docs/spindle/hosting.md"> 92 + {{ i "book" "size-4" }} 93 + docs 94 + </a> 95 + <div 96 + id="add-email-modal" 97 + popover 98 + class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50"> 99 + </div> 103 100 {{ end }}
-2
appview/pages/templates/layouts/fragments/topbar.html
··· 61 61 <a href="/{{ $user }}">profile</a> 62 62 <a href="/{{ $user }}?tab=repos">repositories</a> 63 63 <a href="/{{ $user }}?tab=strings">strings</a> 64 - <a href="/knots">knots</a> 65 - <a href="/spindles">spindles</a> 66 64 <a href="/settings">settings</a> 67 65 <a href="#" 68 66 hx-post="/logout"
+1 -1
appview/pages/templates/repo/fork.html
··· 34 34 {{ end }} 35 35 </div> 36 36 </div> 37 - <p class="text-sm text-gray-500 dark:text-gray-400">A knot hosts repository data. <a href="/knots" class="underline">Learn how to register your own knot.</a></p> 37 + <p class="text-sm text-gray-500 dark:text-gray-400">A knot hosts repository data. <a href="/settings/knots" class="underline">Learn how to register your own knot.</a></p> 38 38 </fieldset> 39 39 40 40 <div class="space-y-2">
+1 -1
appview/pages/templates/repo/new.html
··· 165 165 </div> 166 166 <p class="text-sm text-gray-500 dark:text-gray-400 mt-1"> 167 167 A knot hosts repository data and handles Git operations. 168 - You can also <a href="/knots" class="underline">register your own knot</a>. 168 + You can also <a href="/settings/knots" class="underline">register your own knot</a>. 169 169 </p> 170 170 </div> 171 171 {{ end }}
+22 -6
appview/pages/templates/spindles/dashboard.html
··· 1 - {{ define "title" }}{{.Spindle.Instance}} &middot; spindles{{ end }} 1 + {{ define "title" }}{{.Spindle.Instance}} &middot; {{ .Tab }} settings{{ end }} 2 2 3 3 {{ define "content" }} 4 - <div class="px-6 py-4"> 4 + <div class="p-6"> 5 + <p class="text-xl font-bold dark:text-white">Settings</p> 6 + </div> 7 + <div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 8 + <section class="w-full grid grid-cols-1 md:grid-cols-4 gap-6"> 9 + <div class="col-span-1"> 10 + {{ template "user/settings/fragments/sidebar" . }} 11 + </div> 12 + <div class="col-span-1 md:col-span-3 flex flex-col gap-6"> 13 + {{ template "spindleDash" . }} 14 + </div> 15 + </section> 16 + </div> 17 + {{ end }} 18 + 19 + {{ define "spindleDash" }} 20 + <div> 5 21 <div class="flex justify-between items-center"> 6 - <h1 class="text-xl font-bold dark:text-white">{{ .Spindle.Instance }}</h1> 22 + <h2 class="text-sm pb-2 uppercase font-bold">{{ .Tab }} &middot; {{ .Spindle.Instance }}</h2> 7 23 <div id="right-side" class="flex gap-2"> 8 24 {{ $style := "px-2 py-1 rounded flex items-center flex-shrink-0 gap-2" }} 9 25 {{ $isOwner := and .LoggedInUser (eq .LoggedInUser.Did .Spindle.Owner) }} ··· 87 71 <button 88 72 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 89 73 title="Delete spindle" 90 - hx-delete="/spindles/{{ .Instance }}" 74 + hx-delete="/settings/spindles/{{ .Instance }}" 91 75 hx-swap="outerHTML" 92 76 hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?" 93 77 hx-headers='{"shouldRedirect": "true"}' ··· 103 87 <button 104 88 class="btn gap-2 group" 105 89 title="Retry spindle verification" 106 - hx-post="/spindles/{{ .Instance }}/retry" 90 + hx-post="/settings/spindles/{{ .Instance }}/retry" 107 91 hx-swap="none" 108 92 hx-headers='{"shouldRefresh": "true"}' 109 93 > ··· 120 104 <button 121 105 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 122 106 title="Remove member" 123 - hx-post="/spindles/{{ $root.Spindle.Instance }}/remove" 107 + hx-post="/settings/spindles/{{ $root.Spindle.Instance }}/remove" 124 108 hx-swap="none" 125 109 hx-vals='{"member": "{{$member}}" }' 126 110 hx-confirm="Are you sure you want to remove {{ resolve $member }} from this instance?"
+1 -1
appview/pages/templates/spindles/fragments/addMemberModal.html
··· 22 22 23 23 {{ define "addSpindleMemberPopover" }} 24 24 <form 25 - hx-post="/spindles/{{ .Instance }}/add" 25 + hx-post="/settings/spindles/{{ .Instance }}/add" 26 26 hx-indicator="#spinner" 27 27 hx-swap="none" 28 28 class="flex flex-col gap-2"
+3 -3
appview/pages/templates/spindles/fragments/spindleListing.html
··· 7 7 8 8 {{ define "spindleLeftSide" }} 9 9 {{ if .Verified }} 10 - <a href="/spindles/{{ .Instance }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]"> 10 + <a href="/settings/spindles/{{ .Instance }}" class="hover:no-underline flex items-center gap-2 min-w-0 max-w-[60%]"> 11 11 {{ i "hard-drive" "w-4 h-4" }} 12 12 <span class="hover:underline"> 13 13 {{ .Instance }} ··· 50 50 <button 51 51 class="btn text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 gap-2 group" 52 52 title="Delete spindle" 53 - hx-delete="/spindles/{{ .Instance }}" 53 + hx-delete="/settings/spindles/{{ .Instance }}" 54 54 hx-swap="outerHTML" 55 55 hx-target="#spindle-{{.Id}}" 56 56 hx-confirm="Are you sure you want to delete the spindle '{{ .Instance }}'?" ··· 66 66 <button 67 67 class="btn gap-2 group" 68 68 title="Retry spindle verification" 69 - hx-post="/spindles/{{ .Instance }}/retry" 69 + hx-post="/settings/spindles/{{ .Instance }}/retry" 70 70 hx-swap="none" 71 71 hx-target="#spindle-{{.Id}}" 72 72 >
+90 -59
appview/pages/templates/spindles/index.html
··· 1 - {{ define "title" }}spindles{{ end }} 1 + {{ define "title" }}{{ .Tab }} settings{{ end }} 2 2 3 3 {{ define "content" }} 4 - <div class="px-6 py-4 flex items-center justify-between gap-4 align-bottom"> 5 - <h1 class="text-xl font-bold dark:text-white">Spindles</h1> 6 - <span class="flex items-center gap-1"> 7 - {{ i "book" "w-3 h-3" }} 8 - <a href="https://tangled.org/@tangled.org/core/blob/master/docs/spindle/hosting.md">docs</a> 9 - </span> 4 + <div class="p-6"> 5 + <p class="text-xl font-bold dark:text-white">Settings</p> 6 + </div> 7 + <div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 8 + <section class="w-full grid grid-cols-1 md:grid-cols-4 gap-6"> 9 + <div class="col-span-1"> 10 + {{ template "user/settings/fragments/sidebar" . }} 11 + </div> 12 + <div class="col-span-1 md:col-span-3 flex flex-col gap-6"> 13 + {{ template "spindleList" . }} 14 + </div> 15 + </section> 16 + </div> 17 + {{ end }} 18 + 19 + {{ define "spindleList" }} 20 + <div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center"> 21 + <div class="col-span-1 md:col-span-2"> 22 + <h2 class="text-sm pb-2 uppercase font-bold">Spindle</h2> 23 + {{ block "about" . }} {{ end }} 24 + </div> 25 + <div class="col-span-1 md:col-span-1 md:justify-self-end"> 26 + {{ template "docsButton" . }} 27 + </div> 10 28 </div> 11 29 12 - <section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"> 30 + <section> 13 31 <div class="flex flex-col gap-6"> 14 - {{ block "about" . }} {{ end }} 15 32 {{ block "list" . }} {{ end }} 16 33 {{ block "register" . }} {{ end }} 17 34 </div> ··· 37 20 38 21 {{ define "about" }} 39 22 <section class="rounded flex items-center gap-2"> 40 - <p class="text-gray-500 dark:text-gray-400"> 41 - Spindles are small CI runners. 42 - </p> 23 + <p class="text-gray-500 dark:text-gray-400"> 24 + Spindles are small CI runners. 25 + </p> 43 26 </section> 44 27 {{ end }} 45 28 46 29 {{ define "list" }} 47 - <section class="rounded w-full flex flex-col gap-2"> 48 - <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your spindles</h2> 49 - <div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full"> 50 - {{ range $spindle := .Spindles }} 51 - {{ template "spindles/fragments/spindleListing" . }} 52 - {{ else }} 53 - <div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500"> 54 - no spindles registered yet 55 - </div> 56 - {{ end }} 30 + <section class="rounded w-full flex flex-col gap-2"> 31 + <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">your spindles</h2> 32 + <div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 w-full"> 33 + {{ range $spindle := .Spindles }} 34 + {{ template "spindles/fragments/spindleListing" . }} 35 + {{ else }} 36 + <div class="flex items-center justify-center p-2 border-b border-gray-200 dark:border-gray-700 text-gray-500"> 37 + no spindles registered yet 57 38 </div> 58 - <div id="operation-error" class="text-red-500 dark:text-red-400"></div> 59 - </section> 39 + {{ end }} 40 + </div> 41 + <div id="operation-error" class="text-red-500 dark:text-red-400"></div> 42 + </section> 60 43 {{ end }} 61 44 62 45 {{ define "register" }} 63 - <section class="rounded w-full lg:w-fit flex flex-col gap-2"> 64 - <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a spindle</h2> 65 - <p class="mb-2 dark:text-gray-300">Enter the hostname of your spindle to get started.</p> 66 - <form 67 - hx-post="/spindles/register" 68 - class="max-w-2xl mb-2 space-y-4" 69 - hx-indicator="#register-button" 70 - hx-swap="none" 71 - > 72 - <div class="flex gap-2"> 73 - <input 74 - type="text" 75 - id="instance" 76 - name="instance" 77 - placeholder="spindle.example.com" 78 - required 79 - class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" 80 - > 81 - <button 82 - type="submit" 83 - id="register-button" 84 - class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group" 85 - > 86 - <span class="inline-flex items-center gap-2"> 87 - {{ i "plus" "w-4 h-4" }} 88 - register 89 - </span> 90 - <span class="pl-2 hidden group-[.htmx-request]:inline"> 91 - {{ i "loader-circle" "w-4 h-4 animate-spin" }} 92 - </span> 93 - </button> 94 - </div> 46 + <section class="rounded w-full lg:w-fit flex flex-col gap-2"> 47 + <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">register a spindle</h2> 48 + <p class="mb-2 dark:text-gray-300">Enter the hostname of your spindle to get started.</p> 49 + <form 50 + hx-post="/settings/spindles/register" 51 + class="max-w-2xl mb-2 space-y-4" 52 + hx-indicator="#register-button" 53 + hx-swap="none" 54 + > 55 + <div class="flex gap-2"> 56 + <input 57 + type="text" 58 + id="instance" 59 + name="instance" 60 + placeholder="spindle.example.com" 61 + required 62 + class="flex-1 w-full dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:placeholder-gray-400 px-3 py-2 border rounded" 63 + > 64 + <button 65 + type="submit" 66 + id="register-button" 67 + class="btn rounded flex items-center py-2 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 group" 68 + > 69 + <span class="inline-flex items-center gap-2"> 70 + {{ i "plus" "w-4 h-4" }} 71 + register 72 + </span> 73 + <span class="pl-2 hidden group-[.htmx-request]:inline"> 74 + {{ i "loader-circle" "w-4 h-4 animate-spin" }} 75 + </span> 76 + </button> 77 + </div> 95 78 96 - <div id="register-error" class="dark:text-red-400"></div> 97 - </form> 79 + <div id="register-error" class="dark:text-red-400"></div> 80 + </form> 98 81 99 - </section> 82 + </section> 83 + {{ end }} 84 + 85 + {{ define "docsButton" }} 86 + <a 87 + class="btn flex items-center gap-2" 88 + href="https://tangled.org/@tangled.org/core/blob/master/docs/spindle/hosting.md"> 89 + {{ i "book" "size-4" }} 90 + docs 91 + </a> 92 + <div 93 + id="add-email-modal" 94 + popover 95 + class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50"> 96 + </div> 100 97 {{ end }}
+2
appview/settings/settings.go
··· 43 43 {"Name": "keys", "Icon": "key"}, 44 44 {"Name": "emails", "Icon": "mail"}, 45 45 {"Name": "notifications", "Icon": "bell"}, 46 + {"Name": "knots", "Icon": "volleyball"}, 47 + {"Name": "spindles", "Icon": "spool"}, 46 48 } 47 49 ) 48 50
+19 -2
appview/spindles/spindles.go
··· 38 38 Logger *slog.Logger 39 39 } 40 40 41 + type tab = map[string]any 42 + 43 + var ( 44 + spindlesTabs []tab = []tab{ 45 + {"Name": "profile", "Icon": "user"}, 46 + {"Name": "keys", "Icon": "key"}, 47 + {"Name": "emails", "Icon": "mail"}, 48 + {"Name": "notifications", "Icon": "bell"}, 49 + {"Name": "knots", "Icon": "volleyball"}, 50 + {"Name": "spindles", "Icon": "spool"}, 51 + } 52 + ) 53 + 41 54 func (s *Spindles) Router() http.Handler { 42 55 r := chi.NewRouter() 43 56 ··· 82 69 s.Pages.Spindles(w, pages.SpindlesParams{ 83 70 LoggedInUser: user, 84 71 Spindles: all, 72 + Tabs: spindlesTabs, 73 + Tab: "spindles", 85 74 }) 86 75 } 87 76 ··· 142 127 Spindle: spindle, 143 128 Members: members, 144 129 Repos: repoMap, 130 + Tabs: spindlesTabs, 131 + Tab: "spindles", 145 132 }) 146 133 } 147 134 ··· 382 365 383 366 shouldRedirect := r.Header.Get("shouldRedirect") 384 367 if shouldRedirect == "true" { 385 - s.Pages.HxRedirect(w, "/spindles") 368 + s.Pages.HxRedirect(w, "/settings/spindles") 386 369 return 387 370 } 388 371 ··· 598 581 } 599 582 600 583 // success 601 - s.Pages.HxRedirect(w, fmt.Sprintf("/spindles/%s", instance)) 584 + s.Pages.HxRedirect(w, fmt.Sprintf("/settings/spindles/%s", instance)) 602 585 } 603 586 604 587 func (s *Spindles) removeMember(w http.ResponseWriter, r *http.Request) {
+4 -2
appview/state/router.go
··· 166 166 167 167 r.Mount("/settings", s.SettingsRouter()) 168 168 r.Mount("/strings", s.StringsRouter(mw)) 169 - r.Mount("/knots", s.KnotsRouter()) 170 - r.Mount("/spindles", s.SpindlesRouter()) 169 + 170 + r.Mount("/settings/knots", s.KnotsRouter()) 171 + r.Mount("/settings/spindles", s.SpindlesRouter()) 172 + 171 173 r.Mount("/notifications", s.NotificationsRouter(mw)) 172 174 173 175 r.Mount("/signup", s.SignupRouter())
+2 -2
docs/hacking.md
··· 121 121 with `ssh` exposed on port 2222. 122 122 123 123 Once the services are running, head to 124 - http://localhost:3000/knots and hit verify. It should 124 + http://localhost:3000/settings/knots and hit verify. It should 125 125 verify the ownership of the services instantly if everything 126 126 went smoothly. 127 127 ··· 146 146 ### running a spindle 147 147 148 148 The above VM should already be running a spindle on 149 - `localhost:6555`. Head to http://localhost:3000/spindles and 149 + `localhost:6555`. Head to http://localhost:3000/settings/spindles and 150 150 hit verify. You can then configure each repository to use 151 151 this spindle and run CI jobs. 152 152
+1 -1
docs/knot-hosting.md
··· 131 131 132 132 You should now have a running knot server! You can finalize 133 133 your registration by hitting the `verify` button on the 134 - [/knots](https://tangled.org/knots) page. This simply creates 134 + [/settings/knots](https://tangled.org/settings/knots) page. This simply creates 135 135 a record on your PDS to announce the existence of the knot. 136 136 137 137 ### custom paths
+3 -3
docs/migrations.md
··· 14 14 For knots: 15 15 16 16 - Upgrade to latest tag (v1.9.0 or above) 17 - - Head to the [knot dashboard](https://tangled.org/knots) and 17 + - Head to the [knot dashboard](https://tangled.org/settings/knots) and 18 18 hit the "retry" button to verify your knot 19 19 20 20 For spindles: 21 21 22 22 - Upgrade to latest tag (v1.9.0 or above) 23 23 - Head to the [spindle 24 - dashboard](https://tangled.org/spindles) and hit the 24 + dashboard](https://tangled.org/settings/spindles) and hit the 25 25 "retry" button to verify your spindle 26 26 27 27 ## Upgrading from v1.7.x ··· 41 41 [settings](https://tangled.org/settings) page. 42 42 - Restart your knot once you have replaced the environment 43 43 variable 44 - - Head to the [knot dashboard](https://tangled.org/knots) and 44 + - Head to the [knot dashboard](https://tangled.org/settings/knots) and 45 45 hit the "retry" button to verify your knot. This simply 46 46 writes a `sh.tangled.knot` record to your PDS. 47 47