aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web
diff options
context:
space:
mode:
Diffstat (limited to 'internal/web')
-rw-r--r--internal/web/handlers_blog.go12
-rw-r--r--internal/web/handlers_pages.go3
-rw-r--r--internal/web/templates/dashboard/design.html1
-rw-r--r--internal/web/templates/dashboard/page_form.html1
-rw-r--r--internal/web/templates/dashboard/sections.html2
-rw-r--r--internal/web/theme.go4
-rw-r--r--internal/web/web_test.go16
7 files changed, 36 insertions, 3 deletions
diff --git a/internal/web/handlers_blog.go b/internal/web/handlers_blog.go
index c26adfa..c1afedb 100644
--- a/internal/web/handlers_blog.go
+++ b/internal/web/handlers_blog.go
@@ -63,6 +63,10 @@ func (s *Server) blogView(r *http.Request) (map[string]any, error) {
return v, nil
}
+// noNotices stands in for the placed announcements on pages that hide them
+// (typed, so the layout's index lookups still work).
+var noNotices = map[string][]store.Section{}
+
// pageNum reads the ?p= of a paginated listing (1 when absent or silly).
func pageNum(r *http.Request) int {
n, _ := strconv.Atoi(r.URL.Query().Get("p"))
@@ -109,6 +113,9 @@ func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, page *store.
last := (total + per - 1) / per
fillExcerpts(v["theme"].(Theme), posts)
v["page"], v["posts"], v["pageNum"], v["lastPage"] = page, posts, n, last
+ if !page.ShowNotices {
+ v["notices"] = noNotices
+ }
// The pager appends ?p=N to base: no trailing slash, which /{page} would not match.
v["base"] = "/" + page.Slug
if page.IsHome {
@@ -195,6 +202,11 @@ func (s *Server) handleBlogPost(w http.ResponseWriter, r *http.Request) {
return
}
v["page"], v["post"] = page, post
+ // A post shows the announcements only when its page does and the theme
+ // wants them on posts at all.
+ if !page.ShowNotices || !v["theme"].(Theme).PostNotices {
+ v["notices"] = noNotices
+ }
s.render(w, r, "blog/post.html", v)
}
diff --git a/internal/web/handlers_pages.go b/internal/web/handlers_pages.go
index 8dc0f5f..b085b82 100644
--- a/internal/web/handlers_pages.go
+++ b/internal/web/handlers_pages.go
@@ -39,7 +39,7 @@ func (s *Server) loadPage(w http.ResponseWriter, r *http.Request) *store.Page {
}
func (s *Server) handlePageForm(w http.ResponseWriter, r *http.Request) {
- p := &store.Page{ShowInNav: true}
+ p := &store.Page{ShowInNav: true, ShowNotices: true}
if r.PathValue("id") != "" {
if p = s.loadPage(w, r); p == nil {
return
@@ -62,6 +62,7 @@ func (s *Server) handlePageSave(w http.ResponseWriter, r *http.Request) {
p.OutroMD = strings.ReplaceAll(r.FormValue("outro"), "\r\n", "\n")
p.Format = pick(r.FormValue("format"), store.FormatMarkdown, store.FormatHTML)
p.ShowInNav = r.FormValue("show_in_nav") == "on"
+ p.ShowNotices = r.FormValue("show_notices") == "on"
autoSlug := p.Slug == ""
if autoSlug {
p.Slug = slug.Make(p.Title)
diff --git a/internal/web/templates/dashboard/design.html b/internal/web/templates/dashboard/design.html
index fea1b92..476e311 100644
--- a/internal/web/templates/dashboard/design.html
+++ b/internal/web/templates/dashboard/design.html
@@ -188,6 +188,7 @@
<h3>{{t "Posts"}}</h3>
<label class="check"><input type="checkbox" name="show_dates"{{if $t.ShowDates}} checked{{end}}> {{t "Show the date on posts"}}</label>
<label class="check"><input type="checkbox" name="tag_hash"{{if $t.TagHash}} checked{{end}}> {{t "Show tags with a # in front"}} <span class="muted">(#garden)</span></label>
+ <label class="check"><input type="checkbox" name="post_notices"{{if $t.PostNotices}} checked{{end}}> {{t "Show announcements on post pages"}} <span class="muted">({{t "each page has its own switch"}})</span></label>
<div class="row">
<label>{{t "Rule under titles"}}<br><select name="title_rule">
<option value="none"{{if eq $t.TitleRule "none"}} selected{{end}}>{{t "None"}}</option>
diff --git a/internal/web/templates/dashboard/page_form.html b/internal/web/templates/dashboard/page_form.html
index 18b0a86..4ee720b 100644
--- a/internal/web/templates/dashboard/page_form.html
+++ b/internal/web/templates/dashboard/page_form.html
@@ -12,6 +12,7 @@
<label for="ed-outro">{{t "Closing text"}} <span class="muted">({{t "shown after the posts, in the same format; optional"}})</span></label>
{{template "editor" (dict "name" "outro" "value" .Data.page.OutroMD "format" .Data.page.Format "formatof" "intro" "rows" 8 "tall" false "upload" (print "/b/" .Blog.Subdomain "/files/upload") "preview" (print "/b/" .Blog.Subdomain "/preview") "csrf" .CSRF)}}
<label class="check"><input type="checkbox" name="show_in_nav"{{if .Data.page.ShowInNav}} checked{{end}}> {{t "Show in menu"}}</label>
+ <label class="check"><input type="checkbox" name="show_notices"{{if .Data.page.ShowNotices}} checked{{end}}> {{t "Show announcements on this page"}}</label>
<p class="actionrow">
<button type="submit">{{t "Save"}}</button>
{{if .Data.page.ID}}<a class="btn secondary" href="{{.BlogURL}}{{if .Data.page.IsHome}}/{{else}}/{{.Data.page.Slug}}{{end}}" target="_blank">{{t "View page"}} &#8599;</a>{{end}}
diff --git a/internal/web/templates/dashboard/sections.html b/internal/web/templates/dashboard/sections.html
index 9f0e314..2767921 100644
--- a/internal/web/templates/dashboard/sections.html
+++ b/internal/web/templates/dashboard/sections.html
@@ -4,7 +4,7 @@
<div class="pagehead">
<h1>{{t "Announcements"}}</h1>
<div class="actions"><a class="btn" href="{{$u}}/new">+ {{t "New announcement"}}</a></div>
- <p class="lead muted">{{t "Notices shown on every page and post of your blog — the next meeting, this month's book, a holiday closure. Hide one instead of deleting it if you will need it again."}}</p>
+ <p class="lead muted">{{t "Notices shown on every page and post of your blog — the next meeting, this month's book, a holiday closure. Hide one instead of deleting it if you will need it again. A page can opt out on its form, and the Design tab can keep them off post pages."}}</p>
</div>
<div class="card">
{{if .Data.sections}}
diff --git a/internal/web/theme.go b/internal/web/theme.go
index 676a01e..0437f51 100644
--- a/internal/web/theme.go
+++ b/internal/web/theme.go
@@ -55,6 +55,7 @@ type Theme struct {
PostImage string `json:"post_image"` // where the post page shows the featured image: top | bottom | list (listings only)
TitleRule string `json:"title_rule"` // none | line | dots | dots2 | stripes, drawn under page and post titles in the link colour
TagHash bool `json:"tag_hash"` // tags are listed as #name
+ PostNotices bool `json:"post_notices"` // announcements are shown on post pages too, not only on listings
FooterBg string `json:"footer_bg"`
FooterColor string `json:"footer_color"`
@@ -108,7 +109,7 @@ func DefaultTheme() Theme {
Font: "sans", HeadingFont: "same", FontSize: "normal",
HeaderImageHeight: "medium", HeaderAlign: "left", HeaderBg: "#2f3a4a", HeaderText: "#ffffff", TitleSize: "normal", HeaderRule: "none",
NavAlign: "left", NavStyle: "normal", NavBg: "#ffffff", NavText: "#222222",
- ShowDates: true, DateFormat: "long", PostsPerPage: postsPerPageChoices[0], ListStyle: "full", PostImage: "top", TitleRule: "none",
+ ShowDates: true, DateFormat: "long", PostsPerPage: postsPerPageChoices[0], ListStyle: "full", PostImage: "top", TitleRule: "none", PostNotices: true,
FooterBg: "#2f3a4a", FooterColor: "#d0d5dc", FooterAlign: "center",
LogoSize: "medium",
HeaderOn: true, LeftOn: true, RightOn: true, FooterOn: true, LeftWidth: 25, RightWidth: 25, PageAlign: "center",
@@ -269,6 +270,7 @@ func ThemeFromForm(cur Theme, f url.Values) Theme {
t.PostImage = get("post_image")
t.TitleRule = get("title_rule")
t.TagHash = on("tag_hash")
+ t.PostNotices = on("post_notices")
t.FooterBg = get("footer_bg")
t.FooterColor = get("footer_color")
t.FooterAlign = get("footer_align")
diff --git a/internal/web/web_test.go b/internal/web/web_test.go
index a7c189f..34ec057 100644
--- a/internal/web/web_test.go
+++ b/internal/web/web_test.go
@@ -138,6 +138,22 @@ func TestThemeNormalizeAndCSS(t *testing.T) {
}
}
+// Announcements on post pages are on by default (the look blogs had before
+// the switch) and, like every checkbox, off when the box is unticked; stored
+// themes from before the option get the default too.
+func TestPostNotices(t *testing.T) {
+ if !DefaultTheme().PostNotices || !ParseTheme([]byte(`{"show_dates":false}`)).PostNotices {
+ t.Error("post notices should default to on")
+ }
+ th := ThemeFromForm(DefaultTheme(), url.Values{"post_notices": {"on"}})
+ if !th.PostNotices {
+ t.Errorf("ticked: %+v", th)
+ }
+ if th = ThemeFromForm(th, url.Values{"show_dates": {"on"}}); th.PostNotices {
+ t.Errorf("unticked: %+v", th)
+ }
+}
+
// The rule under titles is a body class blog.css draws from, coloured by the
// theme CSS; the tag hash is a plain flag the templates read.
func TestTitleRuleAndTagHash(t *testing.T) {