Say what each action did in a one-line notice (closes #383)
check / check (push) Successful in 3m15s

Every action on the webhook pages, and signing out, redirects with a
fixed notice code in the URL, and the page it lands on shows one line
saying what was done. noticeFor maps codes to fixed text and an
unknown code shows nothing, so nothing from the URL is echoed. One
partial, templates/notice.html, shows the line under the navbar on
every page; the error page shows none.

Replay and resubmit use the same codes and partial in place of their
own query parameters and event log banners.

Model: opus-5-5
This commit is contained in:
2026-10-02 08:16:21 +00:00
committed by sneak
parent b78abdc9da
commit 929bb35bb0
15 changed files with 327 additions and 216 deletions
+17 -8
View File
@@ -97,10 +97,10 @@ type Handlers struct {
// parsePageTemplate parses a page-specific template set from the
// embedded FS. Each page template is combined with the shared
// base, htmlheader, and navbar templates, and with any further files
// the page includes. The page file must be listed first so that its
// root action ({{template "base" .}}) becomes the template set's entry
// point.
// base, htmlheader, navbar and notice templates, and with any further
// files the page includes. The page file must be listed first so that
// its root action ({{template "base" .}}) becomes the template set's
// entry point.
func parsePageTemplate(
pageFile string, included ...string,
) *template.Template {
@@ -109,6 +109,7 @@ func parsePageTemplate(
"base.html",
"htmlheader.html",
"navbar.html",
"notice.html",
}, included...)
return template.Must(
@@ -209,11 +210,13 @@ func (s *Handlers) renderError(
// served outside the routes where NoCache runs.
w.Header().Set("Cache-Control", "no-store")
// No notice: one would say an action worked above a page saying
// the request failed.
data := s.pageData(r, map[string]any{
"Status": status,
"StatusText": http.StatusText(status),
"Message": errorPageText(status),
})
}, nil)
var buf bytes.Buffer
@@ -267,6 +270,7 @@ type templateDataWrapper struct {
User *UserInfo
CSRFToken string
Version string
Notice *notice
Data any
}
@@ -311,12 +315,15 @@ func (s *Handlers) renderTemplate(
return
}
s.executeTemplate(w, r, tmpl, s.pageData(r, data))
s.executeTemplate(w, r, tmpl, s.pageData(r, data, noticeFor(r)))
}
// pageData adds the fields the shared layout renders to a page's own
// data.
func (s *Handlers) pageData(r *http.Request, data any) any {
// data. The layout shows the notice, when there is one, above the
// page.
func (s *Handlers) pageData(
r *http.Request, data any, pageNotice *notice,
) any {
userInfo := s.getUserInfo(r)
csrfToken := middleware.CSRFToken(r)
@@ -330,6 +337,7 @@ func (s *Handlers) pageData(r *http.Request, data any) any {
m["User"] = userInfo
m["CSRFToken"] = csrfToken
m["Version"] = version
m["Notice"] = pageNotice
return m
}
@@ -338,6 +346,7 @@ func (s *Handlers) pageData(r *http.Request, data any) any {
User: userInfo,
CSRFToken: csrfToken,
Version: version,
Notice: pageNotice,
Data: data,
}
}