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/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