vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Simplify the home page around the instance introduction
ff9870f1a26a17d54c21d411000a6c7d58ab5c0d · Keenan Nemetz · 1d ago · parent 6ce635a8
Simplify the home page around the instance introduction Drop the page header and its hero actions. The instance name and sign-in links already live in the top bar, and the introduction is the place to say what the forge is. Move New repository into the Repositories heading, where it sits with the list it creates. Remove the introduction card header and its in-page editor. The introduction is profile/README.md in the instance repository, so it is read and pushed like every other customization. The POST / handler and its editor code go with it; an instance admin without an instance repository still gets the setup hint.
server/home_test.go +27−12
| @@ -11,15 +11,12 @@ import ( | |||
| 11 | 11 | "testing" | |
| 12 | 12 | "time" | |
| 13 | 13 | ||
| 14 | "github.com/rodent-software/vole/forge/config" | ||
| 15 | 14 | "github.com/rodent-software/vole/metadata" | |
| 16 | 15 | ) | |
| 17 | 16 | ||
| 18 | 17 | func TestHomeIsALandingPage(t *testing.T) { | |
| 19 | 18 | t.Parallel() | |
| 20 | f := newFixtureWith(t, func(c *config.Config) { | ||
| 21 | c.InstanceName = "Acme Forge" | ||
| 22 | }) | ||
| 19 | f := newFixture(t) | ||
| 23 | 20 | f.publish(f.repo) | |
| 24 | 21 | f.instanceRepo(t, map[string][]byte{"profile/README.md": []byte("What this forge is for.")}) | |
| 25 | 22 | ||
| @@ -28,27 +25,45 @@ func TestHomeIsALandingPage(t *testing.T) { | |||
| 28 | 25 | t.Fatalf("home = %d", code) | |
| 29 | 26 | } | |
| 30 | 27 | for _, want := range []string{ | |
| 31 | `class="hero"`, "<h1>Acme Forge</h1>", | ||
| 32 | `readme-card`, `class="md readme-body"`, | ||
| 28 | `readme-card`, `class="md readme-body"`, "What this forge is for.", | ||
| 33 | 29 | "Repositories", `class="repo-card"`, `href="/r/demo"`, | |
| 34 | "Latest", | ||
| 35 | 30 | "Latest", `href="/activity"`, | |
| 36 | 31 | } { | |
| 37 | 32 | if !strings.Contains(body, want) { | |
| 38 | 33 | t.Fatalf("home is missing %q:\n%s", want, body) | |
| 39 | 34 | } | |
| 40 | 35 | } | |
| 36 | for _, unwanted := range []string{ | ||
| 37 | `class="hero"`, `class="readme-head"`, `class="readme-name"`, | ||
| 38 | `href="/?edit=1`, `name="intro"`, | ||
| 39 | } { | ||
| 40 | if strings.Contains(body, unwanted) { | ||
| 41 | t.Fatalf("home still has the old page header or editor %q:\n%s", unwanted, body) | ||
| 42 | } | ||
| 43 | } | ||
| 41 | 44 | if strings.Contains(body, "Recent activity") { | |
| 42 | 45 | t.Fatalf("home still leads with the feed:\n%s", body) | |
| 43 | 46 | } | |
| 47 | if !strings.Contains(body, `<h2>Repositories</h2>`) { | ||
| 48 | t.Fatalf("home has no repository list heading:\n%s", body) | ||
| 49 | } | ||
| 44 | 50 | } | |
| 45 | 51 | ||
| 46 | func TestHomeHeadingFallsBackToVole(t *testing.T) { | ||
| 52 | func TestHomePutsNewRepositoryInTheListHeading(t *testing.T) { | ||
| 47 | 53 | t.Parallel() | |
| 48 | f := newFixture(t) | ||
| 49 | _, body := f.get("/") | ||
| 50 | if !strings.Contains(body, "<h1>Vole</h1>") { | ||
| 51 | t.Fatalf("home has no fallback heading:\n%s", body) | ||
| 54 | f := browserFixture(t) | ||
| 55 | f.publish(f.repo) | ||
| 56 | if _, err := f.srv.Identity.SetAdmin(f.ownerID, true, "test"); err != nil { | ||
| 57 | t.Fatal(err) | ||
| 58 | } | ||
| 59 | _, cookie := f.browserSession(t, f.ownerID) | ||
| 60 | _, body := f.browserGet(t, "/", cookie) | ||
| 61 | |||
| 62 | heading := strings.Index(body, `<h2>Repositories</h2>`) | ||
| 63 | button := strings.Index(body, `href="/repos/new"`) | ||
| 64 | grid := strings.Index(body, `class="repo-grid"`) | ||
| 65 | if heading < 0 || button < 0 || grid < 0 || heading > button || button > grid { | ||
| 66 | t.Fatalf("the New repository action is not in the repository heading (heading=%d button=%d grid=%d):\n%s", heading, button, grid, body) | ||
| 52 | 67 | } | |
| 53 | 68 | } | |
| 54 | 69 | ||