diff --git a/scripts/dossiers-ngi/README.md b/scripts/dossiers-ngi/README.md index 11da294..37f674a 100644 --- a/scripts/dossiers-ngi/README.md +++ b/scripts/dossiers-ngi/README.md @@ -40,3 +40,47 @@ Hourly JSON can sit next to the HTML once the timer is installed on koopa Hourly builder belongs in **kal** (this tree). Do **not** put `scripts/branch-status-hourly.py` back into tdpd. + +## Sticky cascade bar + +Stock Caddy `templates` renders `{% include "_cascade/bar.html" . %}` on each +HTML page. The include path has no leading slash. The dot passes the request, +so `.Req.URL.Path` marks the active link with `class="is-active"` and +`aria-current="page"`. Delimiters are `{%` `%}`, so a later `{{ }}` in real +dossier HTML stays literal. + +The bar lists cascade `/` plus the five branch paths. Seeded tips match +`branch-status.json`. `/_cascade/bar.js` refreshes `[data-tip]` from that JSON +(`cache: no-store`). CSS is `/_cascade/bar.css` (`position: sticky`). + +Enable templates before rsync. A page without the include does not grow the +bar. `{%` without the templates directive is shown as raw text. + +Templates apply is **host-local on koopa** (`~/bin/apply-dossiers-ngi-templates.sh`), +not tracked in this repo. It edits `~/koopa-caddy/Caddyfile` only (this host; +keeps `header Alt-Svc "clear"` and any `basic_auth`; leaves `.2` / `.3` +untouched). Then reload with the usual home→`/etc` helper: + +```bash +bash ~/bin/apply-dossiers-ngi-templates.sh +sudo ~/bin/caddy-apply +``` + +The stanza body for hand-check / re-seed lives in +`scripts/dossiers-ngi/caddy-dossiers-ngi.snippet`. +`scripts/caddy/caddy-apply.sh --snippet` leaves an existing block unchanged. +Leave `scripts/caddy/apply-goa-wdGet-full-replace.sh` and +`scripts/caddy/apply-dossiers-ngi-basicauth.sh` unused. No response-body +replace plugin. + +After validate and reload succeed, rsync from the laptop (Freigabe): + +```bash +rsync -avz --delete --exclude .DS_Store \ + "$HOME/git/admin-logs/local/koopa-admin-log/sites/dossiers.ngi.hacktivism.ch/" \ + hernani@koopa:/var/www/monitoring-sites/dossiers.ngi.hacktivism.ch/ +``` + +`--delete` removes `_cascade/` on the server when the source tree is an older +copy. The bar does not finish the dossier site. This section does not install +the hourly timer. diff --git a/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet b/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet new file mode 100644 index 0000000..1418403 --- /dev/null +++ b/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet @@ -0,0 +1,19 @@ +# Stanza body for dossiers.ngi.hacktivism.ch only (hand-check / re-seed). +# Templates apply is host-local on koopa (not in this repo): +# bash ~/bin/apply-dossiers-ngi-templates.sh +# sudo ~/bin/caddy-apply +# +# Keep the existing line: header Alt-Svc "clear" +# Keep any existing basic_auth in that same block. +# scripts/caddy/caddy-apply.sh --snippet reports an existing block and +# does not merge these lines. Leave that script unused for this change. +# Leave scripts/caddy/apply-goa-wdGet-full-replace.sh unused. +# Leave scripts/caddy/apply-dossiers-ngi-basicauth.sh unused. +# Stock Caddy templates only. No replace-response plugin. +# +# Tab-indented lines inserted after header Alt-Svc: + + templates { + mime text/html + between "{%" "%}" + } diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css new file mode 100644 index 0000000..0f9e1cc --- /dev/null +++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css @@ -0,0 +1,29 @@ +.cascade-bar { + position: sticky; + top: 0; + z-index: 10; + display: flex; + flex-wrap: wrap; + gap: 0.35rem 0.85rem; + align-items: baseline; + margin: -1.5rem -1.5rem 1rem; + padding: 0.55rem 1.5rem; + background: #10141a; + border-bottom: 1px solid #243040; +} +.cascade-bar a { + color: #7ec8ff; + text-decoration: none; +} +.cascade-bar a:hover { text-decoration: underline; } +.cascade-bar a.is-active { + color: #e8eef4; + text-decoration: none; + box-shadow: inset 0 -2px 0 #e8eef4; +} +.cascade-bar a.is-active:hover { text-decoration: none; } +.cascade-bar code { color: inherit; } +.cascade-bar .tip { + color: #8a96a3; + font-size: 12px; +} diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html new file mode 100644 index 0000000..d6ed145 --- /dev/null +++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html @@ -0,0 +1,11 @@ +{% $p := .Req.URL.Path %} + + + diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js new file mode 100644 index 0000000..9371535 --- /dev/null +++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js @@ -0,0 +1,24 @@ +(function () { + var nodes = document.querySelectorAll(".cascade-bar [data-tip]"); + if (!nodes.length) return; + fetch("/branch-status.json", { cache: "no-store" }) + .then(function (res) { + if (!res.ok) throw new Error("status"); + return res.json(); + }) + .then(function (data) { + var tips = {}; + var list = (data && data.branches) || []; + for (var i = 0; i < list.length; i++) { + var row = list[i]; + if (row && row.branch && row.tip) tips[row.branch] = row.tip; + } + for (var j = 0; j < nodes.length; j++) { + var el = nodes[j]; + var name = el.getAttribute("data-tip"); + var tip = tips[name]; + if (tip) el.textContent = name + " @ " + tip; + } + }) + .catch(function () {}); +})(); diff --git a/sites/dossiers.ngi.hacktivism.ch/feat-sm-content/index.html b/sites/dossiers.ngi.hacktivism.ch/feat-sm-content/index.html index bd25fd1..13f4285 100644 --- a/sites/dossiers.ngi.hacktivism.ch/feat-sm-content/index.html +++ b/sites/dossiers.ngi.hacktivism.ch/feat-sm-content/index.html @@ -17,8 +17,6 @@ a { color: #7ec8ff; text-decoration: none; } a:hover { text-decoration: underline; } h1 { font-size: 1.15rem; font-weight: 600; margin: 0 0 0.5rem; color: #e8eef4; } .meta { color: #8a96a3; margin: 0 0 1rem; } -.nav { margin: 0.5rem 0 1rem; } -.nav a { margin-right: 0.85rem; } ul.plain { padding-left: 1.2rem; margin: 0; } li { margin: 0.25rem 0; } .dim { color: #6a7682; } @@ -26,15 +24,8 @@ li { margin: 0.25rem 0; } +{% include "_cascade/bar.html" . %}

/feat-sm-content/

last-built: 2026-09-30T02:30:50+02:00 · feat/sm-content @ 089ef1f

- diff --git a/sites/dossiers.ngi.hacktivism.ch/feat-website-design/index.html b/sites/dossiers.ngi.hacktivism.ch/feat-website-design/index.html index d4a7fae..142b80e 100644 --- a/sites/dossiers.ngi.hacktivism.ch/feat-website-design/index.html +++ b/sites/dossiers.ngi.hacktivism.ch/feat-website-design/index.html @@ -17,8 +17,6 @@ a { color: #7ec8ff; text-decoration: none; } a:hover { text-decoration: underline; } h1 { font-size: 1.15rem; font-weight: 600; margin: 0 0 0.5rem; color: #e8eef4; } .meta { color: #8a96a3; margin: 0 0 1rem; } -.nav { margin: 0.5rem 0 1rem; } -.nav a { margin-right: 0.85rem; } ul.plain { padding-left: 1.2rem; margin: 0; } li { margin: 0.25rem 0; } .dim { color: #6a7682; } @@ -26,15 +24,8 @@ li { margin: 0.25rem 0; } +{% include "_cascade/bar.html" . %}

/feat-website-design/

last-built: 2026-09-30T02:30:50+02:00 · feat/website-design @ 2e26c80

- diff --git a/sites/dossiers.ngi.hacktivism.ch/feat-website-features/index.html b/sites/dossiers.ngi.hacktivism.ch/feat-website-features/index.html index ed90716..3271f8f 100644 --- a/sites/dossiers.ngi.hacktivism.ch/feat-website-features/index.html +++ b/sites/dossiers.ngi.hacktivism.ch/feat-website-features/index.html @@ -17,8 +17,6 @@ a { color: #7ec8ff; text-decoration: none; } a:hover { text-decoration: underline; } h1 { font-size: 1.15rem; font-weight: 600; margin: 0 0 0.5rem; color: #e8eef4; } .meta { color: #8a96a3; margin: 0 0 1rem; } -.nav { margin: 0.5rem 0 1rem; } -.nav a { margin-right: 0.85rem; } ul.plain { padding-left: 1.2rem; margin: 0; } li { margin: 0.25rem 0; } .dim { color: #6a7682; } @@ -26,15 +24,8 @@ li { margin: 0.25rem 0; } +{% include "_cascade/bar.html" . %}

/feat-website-features/

last-built: 2026-09-30T02:30:50+02:00 · feat/website-features @ 53a3176

- diff --git a/sites/dossiers.ngi.hacktivism.ch/feat-website-views/index.html b/sites/dossiers.ngi.hacktivism.ch/feat-website-views/index.html index 5bc14c7..5896890 100644 --- a/sites/dossiers.ngi.hacktivism.ch/feat-website-views/index.html +++ b/sites/dossiers.ngi.hacktivism.ch/feat-website-views/index.html @@ -17,8 +17,6 @@ a { color: #7ec8ff; text-decoration: none; } a:hover { text-decoration: underline; } h1 { font-size: 1.15rem; font-weight: 600; margin: 0 0 0.5rem; color: #e8eef4; } .meta { color: #8a96a3; margin: 0 0 1rem; } -.nav { margin: 0.5rem 0 1rem; } -.nav a { margin-right: 0.85rem; } ul.plain { padding-left: 1.2rem; margin: 0; } li { margin: 0.25rem 0; } .dim { color: #6a7682; } @@ -26,15 +24,8 @@ li { margin: 0.25rem 0; } +{% include "_cascade/bar.html" . %}

/feat-website-views/

last-built: 2026-09-30T02:30:50+02:00 · feat/website-views @ bbafc38

- diff --git a/sites/dossiers.ngi.hacktivism.ch/index.html b/sites/dossiers.ngi.hacktivism.ch/index.html index 7126152..4d40f7f 100644 --- a/sites/dossiers.ngi.hacktivism.ch/index.html +++ b/sites/dossiers.ngi.hacktivism.ch/index.html @@ -17,8 +17,6 @@ a { color: #7ec8ff; text-decoration: none; } a:hover { text-decoration: underline; } h1 { font-size: 1.15rem; font-weight: 600; margin: 0 0 0.5rem; color: #e8eef4; } .meta { color: #8a96a3; margin: 0 0 1rem; } -.nav { margin: 0.5rem 0 1rem; } -.nav a { margin-right: 0.85rem; } ul.plain { padding-left: 1.2rem; margin: 0; } li { margin: 0.25rem 0; } .dim { color: #6a7682; } @@ -26,16 +24,9 @@ li { margin: 0.25rem 0; } +{% include "_cascade/bar.html" . %}

cascade

last-built: 2026-09-30T02:30:50+02:00

-