From 25f1f56bdebfeecc66f7b5df3a87e5962f303e26 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Mon, 20 Jul 2026 16:35:21 +0000 Subject: [PATCH] appview/pages: add spindle selector in repo/fork pages both pages now have an "advanced" section for users to configure spindles, the default selection is "No Spindle" Signed-off-by: oppiliappan --- appview/pages/pages.go | 4 +++- appview/repo/repo.go | 22 ++++++++++++++++++++++ appview/state/state.go | 24 ++++++++++++++++++++++++ appview/pages/templates/repo/fork.html | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- appview/pages/templates/repo/new.html | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 file(s) changed, 171 insertion(s)(+), 4 deletion(s)(-) diff --git a/appview/pages/pages.go b/appview/pages/pages.go --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -704,7 +704,8 @@ type NewRepoParams struct { BaseParams - Knots []string + Knots []string + Spindles []string } func (p *Pages) NewRepo(w io.Writer, params NewRepoParams) error { @@ -714,6 +715,7 @@ type ForkRepoParams struct { BaseParams Knots []string + Spindles []string RepoInfo repoinfo.RepoInfo } diff --git a/appview/repo/repo.go b/appview/repo/repo.go --- a/appview/repo/repo.go +++ b/appview/repo/repo.go @@ -1418,9 +1418,15 @@ user := rp.oauth.GetMultiAccountUser(r) knots := rp.acl.KnotsForUser(r.Context(), user.Did) + spindles, err := rp.enforcer.GetSpindlesForUser(user.Did) + if err != nil { + l.Error("failed to fetch spindles", "err", err) + } + rp.pages.ForkRepo(w, pages.ForkRepoParams{ BaseParams: pages.BaseParamsFromContext(r.Context()), Knots: knots, + Spindles: spindles, RepoInfo: rp.repoResolver.GetRepoInfo(r, user), }) @@ -1437,6 +1443,21 @@ if !rp.acl.IsRepoCreateAllowed(r.Context(), targetKnot, user.Did) { rp.pages.Notice(w, "repo", "You do not have permission to create a repo in this knot.") return + } + + // optional spindle selection; validate the user is a member if provided + spindle := r.FormValue("spindle") + if spindle != "" { + validSpindles, err := rp.enforcer.GetSpindlesForUser(user.Did) + if err != nil { + l.Error("failed to fetch spindles", "err", err) + rp.pages.Notice(w, "repo", "Failed to configure spindle. Try again later.") + return + } + if !slices.Contains(validSpindles, spindle) { + rp.pages.Notice(w, "repo", "Invalid spindle selection.") + return + } } // choose a name for a fork @@ -1530,6 +1551,7 @@ Rkey: rkey, Source: forkSource, Description: forkDescription, + Spindle: spindle, Created: time.Now(), Labels: rp.config.Label.DefaultLabelDefs, RepoDid: repoDid, diff --git a/appview/state/state.go b/appview/state/state.go --- a/appview/state/state.go +++ b/appview/state/state.go @@ -7,6 +7,7 @@ "fmt" "log/slog" "net/http" + "slices" "strings" "time" @@ -449,9 +450,15 @@ user := s.oauth.GetMultiAccountUser(r) knots := s.aclService.KnotsForUser(r.Context(), user.Did) + spindles, err := s.enforcer.GetSpindlesForUser(user.Did) + if err != nil { + s.logger.Error("failed to fetch spindles", "err", err) + } + s.pages.NewRepo(w, pages.NewRepoParams{ BaseParams: pages.BaseParamsFromContext(r.Context()), Knots: knots, + Spindles: spindles, }) case http.MethodPost: @@ -493,6 +500,22 @@ s.pages.Notice(w, "repo", "Description must be 140 characters or fewer.") return } + + // optional spindle selection; validate the user is a member if provided + spindle := r.FormValue("spindle") + if spindle != "" { + validSpindles, err := s.enforcer.GetSpindlesForUser(user.Did) + if err != nil { + l.Error("failed to fetch spindles", "err", err) + s.pages.Notice(w, "repo", "Failed to configure spindle. Try again later.") + return + } + if !slices.Contains(validSpindles, spindle) { + s.pages.Notice(w, "repo", "Invalid spindle selection.") + return + } + } + l = l.With("spindle", spindle) // ACL validation if !s.aclService.IsRepoCreateAllowed(r.Context(), domain, user.Did) { @@ -570,6 +593,7 @@ Knot: domain, Rkey: rkey, Description: description, + Spindle: spindle, Created: time.Now(), Labels: s.config.Label.DefaultLabelDefs, RepoDid: repoDid, diff --git a/appview/pages/templates/repo/fork.html b/appview/pages/templates/repo/fork.html --- a/appview/pages/templates/repo/fork.html +++ b/appview/pages/templates/repo/fork.html @@ -124,7 +124,63 @@ -
+ {{/* Step 3 — Advanced */}} +
+ +
+
+ {{ i "plus" "size-4" }} +
+
+
+

Advanced

+
+
+ +
+
+
+ + {{/* Spindle list */}} +
+ +
+
+ + +
+ {{ range .Spindles }} +
+ + +
+ {{ end }} +
+

+ A spindle runs your CI workflows. + You can also register your own spindle. +

+
+ +
+
+
+
+ +
-
+

Configuration

Repository settings and hosting.
@@ -73,6 +74,30 @@
+{{ end }} + +{{ define "step-3" }} +
+ +
+
+ {{ i "plus" "w-4 h-4" }} +
+
+ +
+

Advanced

+
+
+ +
+
+
+ {{ template "spindle" . }} +
+
+
+
{{ end }} {{ define "name" }} @@ -171,8 +196,46 @@ {{ end }} +{{ define "spindle" }} + +
+ +
+
+ + +
+ {{ range .Spindles }} +
+ + +
+ {{ end }} +
+

+ A spindle runs your CI workflows. + You can also register your own spindle. +

+
+{{ end }} + {{ define "numberCircle" }} -
+
{{.}}
{{ end }} -- tangled.sh