Commit 2dd9add6d0

2dd9add6d0d3a8264418dd74b1b4d3d8dc62c440

parent: d906ddff2e

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-28 23:04 UTC

web: drop CLI commands from four empty states, per the register

issues, milestones, org milestones and releases named a gitbay
command in their empty state, missed when the rest of the pages
switched to the writer-gets-a-web-link-or-nothing register. Issues
links to issues/new for a signed-in viewer (issue create needs no
write access); milestones and org milestones have no web create form
yet, so they state the fact; releases already shows its create form
above the list for a writer with a free tag, so the empty note states
the fact too.

Ref #270

Layout: unified · split

internal/httpd/emptystates_test.go added +78
@@ -0,0 +1,78 @@
1package httpd
2
3import (
4 "html/template"
5 "strings"
6 "testing"
7
8 "gitbay.org/gitbay/internal/store"
9 "gitbay.org/gitbay/internal/web"
10)
11
12// A signed-in viewer with zero issues gets a link to open one; a
13// signed-out visitor gets only the fact, and no CLI command either way
14// (#270).
15func TestIssuesEmptyStateOffersOpenLinkForViewer(t *testing.T) {
16 render := func(viewer string) string {
17 var sb strings.Builder
18 p := testRepoPage()
19 p.Viewer = viewer
20 if err := web.Render(&sb, "issues.html", struct {
21 repoPage
22 State string
23 Label string
24 Query string
25 Filters []listFilter
26 Facets []facetGroup
27 Issues []store.Issue
28 LabelColors map[string]template.CSS
29 Older string
30 }{repoPage: p, State: "open"}); err != nil {
31 t.Fatalf("render: %v", err)
32 }
33 return sb.String()
34 }
35
36 anon := render("")
37 if !strings.Contains(anon, "no open issues") {
38 t.Errorf("missing empty-state fact:\n%s", anon)
39 }
40 if strings.Contains(anon, "issues/new") {
41 t.Error("signed-out visitor should not see an open-issue link")
42 }
43 if strings.Contains(anon, "gitbay issue create") {
44 t.Error("empty state should not name a CLI command")
45 }
46
47 viewer := render("alice")
48 if !strings.Contains(viewer, `href="/krz/gitbay/issues/new"`) {
49 t.Errorf("signed-in viewer missing the open-issue link:\n%s", viewer)
50 }
51}
52
53// An empty release list states the fact without a CLI command; the page
54// already offers the create form above when the viewer can write and a
55// tag is free to release (#270).
56func TestReleasesEmptyStateHasNoCLICommand(t *testing.T) {
57 var sb strings.Builder
58 if err := web.Render(&sb, "releases.html", struct {
59 repoPage
60 Releases []struct {
61 store.Release
62 NotesHTML template.HTML
63 }
64 FreeTags []string
65 CanWrite bool
66 Notice string
67 Draft *draft
68 }{repoPage: testRepoPage()}); err != nil {
69 t.Fatalf("render: %v", err)
70 }
71 out := sb.String()
72 if !strings.Contains(out, "no releases yet") {
73 t.Errorf("missing empty-state fact:\n%s", out)
74 }
75 if strings.Contains(out, "gitbay release create") {
76 t.Error("empty state should not name a CLI command")
77 }
78}
internal/web/templates/issues.html +1 −1
@@ -25,7 +25,7 @@
25 {{if eq $.State "all"}}<span class="chip {{if eq .State "open"}}chip-open{{else}}chip-done{{end}}">{{.State}}</span>{{end}} 25 {{if eq $.State "all"}}<span class="chip {{if eq .State "open"}}chip-open{{else}}chip-done{{end}}">{{.State}}</span>{{end}}
26</li> 26</li>
27{{else}}{{if .Query}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}issues matching “{{.Query}}”</li> 27{{else}}{{if .Query}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}issues matching “{{.Query}}”</li>
28{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}issues — open one with <code>gitbay issue create {{.Repo.OwnerName}}/{{.Repo.Name}} --title "..."</code></li>{{end}}{{end}} 28{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}issues{{if .Viewer}} — <a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/new">open one</a>{{end}}</li>{{end}}{{end}}
29</ul> 29</ul>
30{{if .Older}}<p class="pager"><a href="{{.Older}}">older →</a></p>{{end}} 30{{if .Older}}<p class="pager"><a href="{{.Older}}">older →</a></p>{{end}}
31</div> 31</div>
internal/web/templates/milestones.html +1 −1
@@ -17,6 +17,6 @@
17 <div class="progress"><div class="bar" style="width: {{.Percent}}%"></div></div> 17 <div class="progress"><div class="bar" style="width: {{.Percent}}%"></div></div>
18 </div> 18 </div>
19</li> 19</li>
20{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}milestones — create one with <code>gitbay milestone create {{.Repo.OwnerName}}/{{.Repo.Name}} "v1.0"</code></li>{{end}} 20{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}milestones</li>{{end}}
21</ul> 21</ul>
22{{end}} 22{{end}}
internal/web/templates/orgmilestones.html +1 −1
@@ -18,6 +18,6 @@
18 <div class="progress"><div class="bar" style="width: {{.Percent}}%"></div></div> 18 <div class="progress"><div class="bar" style="width: {{.Percent}}%"></div></div>
19 </div> 19 </div>
20</li> 20</li>
21{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}org milestones — create one with <code>gitbay org milestone create {{.Org}} "v1.0"</code></li>{{end}} 21{{else}}<li class="empty">no {{if ne .State "all"}}{{.State}} {{end}}org milestones</li>{{end}}
22</ul> 22</ul>
23{{end}} 23{{end}}
internal/web/templates/releases.html +1 −1
@@ -51,5 +51,5 @@
51 </tr>{{end}} 51 </tr>{{end}}
52 </table>{{end}} 52 </table>{{end}}
53</article> 53</article>
54{{else}}<p class="empty-note">no releases yet — tag a commit, push the tag, then <code>gitbay release create {{.Repo.OwnerName}}/{{.Repo.Name}} v1.0</code></p>{{end}} 54{{else}}<p class="empty-note">no releases yet</p>{{end}}
55{{end}} 55{{end}}