Commit c600d4a8ab
c600d4a8abb941cb373ca24defb41c6c23869b9d
parent: 92c816c58e
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-21 20:38 UTC
explore: name the filter, its count and a way out
A search showed a shorter list and nothing else: no count, no restatement
of the query outside the input, and no way back to the unfiltered view
except emptying the field. The page carries the line the builds page
already has — count, active query, clear — and an empty filtered list
says nothing matched rather than that the instance has no public
repositories.
Closes #243
internal/httpd/explorepage_test.go
added
+56
| @@ -0,0 +1,56 @@ |
| 1 | package httpd |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | |
| 7 | "gitbay.org/gitbay/internal/store" |
| 8 | "gitbay.org/gitbay/internal/web" |
| 9 | ) |
| 10 | |
| 11 | // A filtered explore showed a shorter list and nothing else: no count, no |
| 12 | // restatement of the query, and no way back to the unfiltered view (#243). |
| 13 | func TestExplorePageSummarisesTheFilter(t *testing.T) { |
| 14 | repos := []describedRepo{ |
| 15 | {Repo: store.Repo{OwnerName: "krz", Name: "gitbay"}, Desc: "A CLI-first git forge."}, |
| 16 | } |
| 17 | out := renderExplore(t, "forge", repos) |
| 18 | for _, want := range []string{"1 repository", "matching <strong>forge</strong>", `href="/explore"`, "clear filter"} { |
| 19 | if !strings.Contains(out, want) { |
| 20 | t.Errorf("explore.html missing %q:\n%s", want, out) |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | // Nothing to clear when nothing is filtered. |
| 25 | if out := renderExplore(t, "", repos); strings.Contains(out, "clear filter") { |
| 26 | t.Errorf("unfiltered explore offers a clear:\n%s", out) |
| 27 | } else if !strings.Contains(out, "1 repository") { |
| 28 | t.Errorf("unfiltered explore has no count:\n%s", out) |
| 29 | } |
| 30 | |
| 31 | // A filter that matched nothing says so rather than claiming the |
| 32 | // instance has no public repositories. |
| 33 | out = renderExplore(t, "nothing", nil) |
| 34 | if !strings.Contains(out, "nothing matches that filter") { |
| 35 | t.Errorf("empty filtered list reads as an empty instance:\n%s", out) |
| 36 | } |
| 37 | if !strings.Contains(out, "0 repositories") { |
| 38 | t.Errorf("empty filtered list has no count:\n%s", out) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | func renderExplore(t *testing.T, q string, repos []describedRepo) string { |
| 43 | t.Helper() |
| 44 | var sb strings.Builder |
| 45 | err := web.Render(&sb, "explore.html", struct { |
| 46 | basePage |
| 47 | Tab string |
| 48 | Query string |
| 49 | Facets []facetGroup |
| 50 | Repos []describedRepo |
| 51 | }{basePage{Site: "gitbay"}, "explore", q, nil, repos}) |
| 52 | if err != nil { |
| 53 | t.Fatalf("render: %v", err) |
| 54 | } |
| 55 | return sb.String() |
| 56 | } |
internal/web/templates/explore.html
+2 −1
| @@ -12,9 +12,10 @@ |
| 12 | 12 | </form> |
| 13 | 13 | <span class="spacer"></span> |
| 14 | 14 | </div> |
| 15 | <p class="meta">{{len .Repos}} repositor{{if eq (len .Repos) 1}}y{{else}}ies{{end}}{{if .Query}} matching <strong>{{.Query}}</strong>, <a href="/explore">clear filter</a>{{end}}</p> |
| 15 | 16 | <ul class="repolist rows"> |
| 16 | 17 | {{range .Repos}}{{template "reporow" .}} |
| 17 | | {{else}}<li class="empty">no public repositories yet</li>{{end}} |
| 18 | {{else}}<li class="empty">{{if .Query}}nothing matches that filter{{else}}no public repositories yet{{end}}</li>{{end}} |
| 18 | 19 | </ul> |
| 19 | 20 | </div> |
| 20 | 21 | </div> |