diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-29 15:06:57 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-29 15:06:57 +0200 |
| commit | ae8af86660243b75db1d54bb0c8d26431bd17f52 (patch) | |
| tree | e3b8c469017ab25b83fa3f67807804b955b67e4f /internal/web | |
| parent | cd8b2f25f390d9d6d5a4d5cb27c4cd2ed8ab4073 (diff) | |
| download | lectio-ae8af86660243b75db1d54bb0c8d26431bd17f52.tar.gz lectio-ae8af86660243b75db1d54bb0c8d26431bd17f52.zip | |
web: reader link to the left, downloads into a "pobierz" disclosure
Finish the top-bar rework. The reader entry point now leads the controls
bar on the far left (it was in the right-hand cluster); settings stays in
the top-right cluster.
The flat "download: txt md pdf · kalendarz" strip becomes a single
"pobierz" summary that opens a small floating panel with two rows:
- a month calendar with its own month + year <select> pickers (localised
month names, both pre-selected from the shown date) and a PDF button
that hits /calendar?month=YYYY-MM;
- the shown day's readings as txt/md/pdf, labelled with the date.
The panel is absolutely positioned under the link so opening it doesn't
reflow the bar. indexData gains MonthOpts/YearOpts (a calOpt list); the
year picker is a small window around the shown year.
Diffstat (limited to 'internal/web')
| -rw-r--r-- | internal/web/server.go | 32 | ||||
| -rw-r--r-- | internal/web/static/base.css | 31 | ||||
| -rw-r--r-- | internal/web/templates/index.html | 38 |
3 files changed, 88 insertions, 13 deletions
diff --git a/internal/web/server.go b/internal/web/server.go index 7d9dfe5..f02bc12 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -219,6 +219,10 @@ type indexData struct { Display string Mono bool Reading template.HTML + // MonthOpts/YearOpts populate the "pobierz" panel's month-calendar + // download pickers (localised month names + a year window around the + // shown date). + MonthOpts, YearOpts []calOpt // L holds the localised control labels (lectionary/layout/theme/...), // set from i18n.Get(cfg.UILanguage) -- index.html references its // fields (e.g. {{.L.Lectionary}}) instead of hardcoded Polish text. @@ -232,6 +236,13 @@ type versionOpt struct { Checked bool } +// calOpt is one <option> in the pobierz panel's month or year picker. +type calOpt struct { + Val int + Label string + Sel bool +} + type themeOpt struct { Name string Selected bool @@ -276,6 +287,23 @@ func indexHandler(cfg config.Config) http.HandlerFunc { themeOpts = append(themeOpts, themeOpt{Name: name, Selected: name == theme}) } + // Month/year pickers for the "pobierz" panel's month-calendar download. + // Selected from the shown date; the year list is a small window around + // it so the shown year is always present and pre-selected. + labels := i18n.Get(cfg.UILanguage) + selYear, selMonth := 0, 0 + if t, err := time.Parse("2006-01-02", date); err == nil { + selYear, selMonth = t.Year(), int(t.Month()) + } + monthOpts := make([]calOpt, 0, 12) + for i, name := range labels.Months { + monthOpts = append(monthOpts, calOpt{Val: i + 1, Label: name, Sel: i+1 == selMonth}) + } + yearOpts := make([]calOpt, 0, 6) + for y := selYear - 2; y <= selYear+3; y++ { + yearOpts = append(yearOpts, calOpt{Val: y, Label: strconv.Itoa(y), Sel: y == selYear}) + } + data := indexData{ Date: date, PrevDate: shiftDate(date, -1), @@ -288,7 +316,9 @@ func indexHandler(cfg config.Config) http.HandlerFunc { Display: display, Mono: queryBool(r, "mono", cfg.WebMono), Reading: reading, - L: i18n.Get(cfg.UILanguage), + MonthOpts: monthOpts, + YearOpts: yearOpts, + L: labels, Lang: cfg.UILanguage, } diff --git a/internal/web/static/base.css b/internal/web/static/base.css index 757e935..b5f4f13 100644 --- a/internal/web/static/base.css +++ b/internal/web/static/base.css @@ -322,9 +322,34 @@ a { gap: var(--space-2); } -/* Export links (download the readings). */ -.export { font-family: var(--font-ui); font-size: 0.85rem; } -.export a { margin: 0 0.15rem; } +/* "pobierz" disclosure: a summary styled as a nav link that reveals a small + * floating panel of download options (a month calendar with its own month/year + * pickers, and the shown day's txt/md/pdf export). The panel is absolutely + * positioned under the link so opening it never reflows the controls bar. + * Colour (border/background) is the theme's, via the shared --bg/--fg tokens. */ +.export { position: relative; font-family: var(--font-ui); font-size: 0.85rem; } +.export > summary { cursor: pointer; list-style: none; } +.export > summary::-webkit-details-marker { display: none; } +.export > summary::after { content: " \25be"; } /* down caret */ +.export[open] > summary::after { content: " \25b4"; } /* up caret */ +.export-panel { + position: absolute; + right: 0; + top: calc(100% + 0.35rem); + z-index: 10; + display: flex; + flex-direction: column; + gap: var(--space-1); + padding: var(--space-2); + border-width: 1px; + border-style: solid; + background: var(--bg); + white-space: nowrap; +} +.export-row { display: flex; align-items: center; gap: 0.5rem; } +.export-row .export-label { font-weight: 600; } +.export-panel select { font: inherit; } +.export-panel a { margin: 0; } /* Bookmark marker: a red "*" flagging a bookmarked verse in the reader. A fixed * semantic red (not a theme colour), visible on light and dark themes alike. */ diff --git a/internal/web/templates/index.html b/internal/web/templates/index.html index 3379dc1..b20131d 100644 --- a/internal/web/templates/index.html +++ b/internal/web/templates/index.html @@ -32,6 +32,8 @@ function stepDate(n){ <form id="controls" class="controls" hx-get="/readings" hx-target="#pane" hx-trigger="change"> <div class="controls-main"> + {{/* The reader entry point is the primary action, so it leads the bar. */}} + <a class="nav-link nav-reader" href="/reader">{{.L.NavReader}} →</a> {{/* Always-present marker so the server can tell a form submit with every version unchecked (show nothing) from a fresh visit (config default). */}} <input type="hidden" name="vset" value="1"> @@ -65,17 +67,35 @@ function stepDate(n){ </label> </div> - {{/* Utility links, pinned to the top-right (see #controls / .controls-side). - The export URLs are built from the live control values at click time. */}} + {{/* Utility cluster, pinned to the top-right (see #controls / .controls-side): + settings, then a "pobierz" disclosure that opens two download options -- + a month calendar (its own month/year pickers) and the shown day's + readings as txt/md/pdf. Both URLs are built from live values at click + time (the readings export from the whole control form, the calendar from + its own pickers plus the hidden lectionary field). */}} <span class="controls-side"> - <a class="nav-link nav-reader" href="/reader">{{.L.NavReader}} →</a> <a class="nav-link" href="/settings">{{.L.NavSettings}}</a> - <span class="export">{{.L.Export}}: - <a href="#" onclick="location='/export?fmt=txt&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">txt</a> - <a href="#" onclick="location='/export?fmt=md&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">md</a> - <a href="#" onclick="location='/export?fmt=pdf&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">pdf</a> - · <a href="#" onclick="var d=(document.querySelector('#controls [name=date]').value||'').slice(0,7);location='/calendar?month='+d+'&lectionary='+document.querySelector('#controls [name=lectionary]').value;return false;">{{.L.Calendar}}</a> - </span> + <details class="export"> + <summary class="nav-link">{{.L.Export}}</summary> + <div class="export-panel"> + <div class="export-row"> + <span class="export-label">{{.L.Calendar}}</span> + <select id="cal-month" aria-label="{{.L.Calendar}}"> + {{range .MonthOpts}}<option value="{{.Val}}"{{if .Sel}} selected{{end}}>{{.Label}}</option>{{end}} + </select> + <select id="cal-year"> + {{range .YearOpts}}<option value="{{.Val}}"{{if .Sel}} selected{{end}}>{{.Label}}</option>{{end}} + </select> + <a href="#" onclick="var m=document.getElementById('cal-month').value,y=document.getElementById('cal-year').value;location='/calendar?month='+y+'-'+('0'+m).slice(-2)+'&lectionary='+document.querySelector('#controls [name=lectionary]').value;return false;">PDF</a> + </div> + <div class="export-row"> + <span class="export-label">{{.Date}}</span> + <a href="#" onclick="location='/export?fmt=txt&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">txt</a> + <a href="#" onclick="location='/export?fmt=md&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">md</a> + <a href="#" onclick="location='/export?fmt=pdf&'+new URLSearchParams(new FormData(document.getElementById('controls'))).toString();return false;">pdf</a> + </div> + </div> + </details> </span> </form> |
