Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Unify the web UI's empty states

c7b9094f5cc912efc16e337123d32d51fe99e1d6 · Keenan Nemetz · 1d ago · parent 6ce635a8

Unify the web UI's empty states

Use one .empty-state shape for lists and panes that have nothing to show,
and keep .muted for the compact lines inside sidebars, cards, trees, and
table cells so the page does not fill with dashed boxes.

Drop the CLI command from an empty discussion: the composer is on the page,
so the reader does not need a clone to comment. Remove empty-state links
that repeated the filter row above them, including the merged/closed change
links, the closed-issue link, the clear-filter buttons, the users' "Show
everyone" link, and the signed-out home page's duplicate sign-in buttons.

server/integration_test.go +17−10

@@ -781,10 +781,13 @@ func TestIssuePushedThenRendered(t *testing.T) {
781 781 if !strings.Contains(body, "<code>code</code>") {
782 782 t.Fatal("inline code was not rendered")
783 783 }
784 // An empty thread prints the command that fills it: the web has no comment, so
785 // telling somebody "no comments" and stopping is a dead end.
786 if !strings.Contains(body, "vole issue comment "+testIssueID) {
787 t.Fatalf("the empty comment state does not print the command:\n%s", body)
784 // An empty thread says so, and leaves the reader at the composer rather than
785 // sending them to a clone for a command the page can take.
786 if !strings.Contains(body, "No comments yet.") {
787 t.Fatalf("the empty comment state does not say it is empty:\n%s", body)
788 }
789 if strings.Contains(body, "vole issue comment") {
790 t.Fatalf("the empty comment state prints a CLI command:\n%s", body)
788 791 }
789 792 // The repo page advertises the count.
790 793 if _, body := f.get("/r/" + f.repo); !strings.Contains(body, "Issues") {
@@ -1358,9 +1361,9 @@ func TestAURLRemoteIsFetchedBeforeWriting(t *testing.T) {
1358 1361 }
1359 1362 }
1360 1363
1361 // TestEmptyStatesPrintAWorkingCommand: every empty page is somebody's first
1362 // minute with the instance, and four of the five things they might want to do are
1363 // writes the web cannot take. The page has to hand them the command.
1364 // TestEmptyStatesPrintAWorkingCommand: opening an issue or a change is a write
1365 // the web cannot take from an empty list, so those pages hand over the command.
1366 // A discussion has a composer on the page and does not need one.
1364 1367 func TestEmptyStatesPrintAWorkingCommand(t *testing.T) {
1365 1368 t.Parallel()
1366 1369 f := newFixture(t)
@@ -1516,13 +1519,17 @@ func TestRequestDiscussionIsPushedAndOwned(t *testing.T) {
1516 1519 t.Fatalf("request push: %v", err)
1517 1520 }
1518 1521
1519 // An empty discussion prints the command that fills it.
1522 // An empty discussion says so, and leaves the reader at the composer rather
1523 // than sending them to a clone for a command the page can take.
1520 1524 code, body := f.get("/r/" + f.repo + "/changes/" + reqID)
1521 1525 if code != 200 {
1522 1526 t.Fatalf("request page: %d", code)
1523 1527 }
1524 if !strings.Contains(body, "vole change comment "+reqID) {
1525 t.Fatalf("the empty discussion state does not print the command:\n%s", body)
1528 if !strings.Contains(body, "No discussion yet.") {
1529 t.Fatalf("the empty discussion state does not say it is empty:\n%s", body)
1530 }
1531 if strings.Contains(body, "vole change comment") {
1532 t.Fatalf("the empty discussion state prints a CLI command:\n%s", body)
1526 1533 }
1527 1534
1528 1535 // The author comments through the CLI, and the id is printed so the editing