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/web/home.go +15−42

@@ -2,11 +2,12 @@ package web
2 2
3 3 // The landing page and the instance-wide activity feed.
4 4 //
5 // The landing page is a heading named by the instance, an introduction card an
6 // instance admin can edit in place, and then the repository grid beside a rail
7 // of what is happening and what the code is written in. The cards and the rail
8 // come from one read per repository, so listing a repository does not cost a
9 // second walk over its history.
5 // The landing page is the instance introduction, then the repository grid beside
6 // a rail of what is happening and what the code is written in. The introduction
7 // is read from the instance repository like every other customization, so there
8 // is no second copy of the instance name or an editor to keep in sync. The cards
9 // and the rail come from one read per repository, so listing a repository does
10 // not cost a second walk over its history.
10 11
11 12 import (
12 13 "html/template"
@@ -51,15 +52,9 @@ type repoCard struct {
51 52
52 53 type homeData struct {
53 54 Page
54 // InstanceName is the landing page heading.
55 InstanceName string
56 // Intro is the rendered, sanitized introduction. Empty means the card has no
57 // body; an instance admin still sees it, with an invitation to write one.
55 // Intro is the rendered, sanitized introduction. Empty means there is no
56 // introduction to show.
58 57 Intro template.HTML
59 // IntroText is the markdown shown in the edit form, and Editing says whether
60 // that form is open. Only an instance admin ever gets both.
61 IntroText string
62 Editing bool
63 58 // RepoReady reports that the instance repository has a usable snapshot, so
64 59 // the page can be customized at all.
65 60 RepoReady bool
@@ -80,7 +75,7 @@ type instanceActivityData struct {
80 75 // repository rather than a table row.
81 76 func (w *Web) IndexPage(rw http.ResponseWriter, r *http.Request) {
82 77 query := strings.TrimSpace(r.URL.Query().Get("q"))
83 data, err := w.homeView(r, query, r.URL.Query().Get("edit") == "1", nil, "")
78 data, err := w.homeView(r, query)
84 79 if err != nil {
85 80 w.serverError(rw, r, "index unavailable: "+err.Error())
86 81 return
@@ -88,24 +83,17 @@ func (w *Web) IndexPage(rw http.ResponseWriter, r *http.Request) {
88 83 w.render(rw, "index", data, 0)
89 84 }
90 85
91 // homeView builds the landing page. A save that failed passes its text back in
92 // submitted so the editor reopens with the paragraph still in it; msg is the
93 // error the page shows above it.
94 func (w *Web) homeView(r *http.Request, query string, wantEdit bool, submitted *string, msg string) (homeData, error) {
86 // homeView builds the landing page: the introduction, the repository grid, and
87 // the activity rail.
88 func (w *Web) homeView(r *http.Request, query string) (homeData, error) {
95 89 entries, err := w.visibleRepos(r, query)
96 90 if err != nil {
97 91 return homeData{}, err
98 92 }
99 93 page := w.page(r, "Repositories")
100 94 page.Query = query
101 page.Error = msg
102 // Only an instance admin can edit, so ?edit=1 from anybody else is ignored
103 // rather than refused: the page they asked for is the page they get.
104 editing := wantEdit && page.InstanceAdmin
105 95 data := homeData{
106 96 Page: page,
107 InstanceName: w.instanceName(),
108 Editing: editing,
109 97 OpenRegistration: w.Cfg != nil && w.Cfg.OpenRegistration,
110 98 }
111 99 var snap *instancerepo.Snapshot
@@ -113,31 +101,16 @@ func (w *Web) homeView(r *http.Request, query string, wantEdit bool, submitted *
113 101 snap = w.InstanceRepo.Current()
114 102 }
115 103 data.RepoReady = snap != nil
116 var readme string
117 104 if snap != nil {
118 readme = string(snap.Readme)
119 }
120 if !data.RepoReady {
121 editing = false
122 data.Editing = false
123 }
124 if editing {
125 // The editor always writes the public file. A private README is for
126 // signed-in readers, not a second editing surface.
127 data.IntroText = strings.TrimSpace(readme)
128 } else if snap != nil {
129 105 // A signed-in viewer sees the member-only README when one exists.
130 shown := readme
106 shown := snap.Readme
131 107 if page.LoggedIn && len(snap.PrivateReadme) > 0 {
132 shown = string(snap.PrivateReadme)
108 shown = snap.PrivateReadme
133 109 }
134 if text := strings.TrimSpace(shown); text != "" {
110 if text := strings.TrimSpace(string(shown)); text != "" {
135 111 data.Intro = w.renderInstanceMarkdown(text)
136 112 }
137 113 }
138 if editing && submitted != nil {
139 data.IntroText = *submitted
140 }
141 114
142 115 var events []activityEvent
143 116 memo := memoOf(r)