diff --git a/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet b/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet
index c746406..7e02a41 100644
--- a/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet
+++ b/scripts/dossiers-ngi/caddy-dossiers-ngi.snippet
@@ -19,7 +19,10 @@
handle @use {
header Set-Cookie "tdpd_edition={re.use.1}; Path=/; Max-Age=31536000; SameSite=Lax"
header Cache-Control "private, no-store"
- redir * / 302
+ # Keep the caller's path (?next=). Never bounce to /. No next → bar page.
+ @next query_regexp next ^(/|/[^/].*)$
+ redir @next {query.next} 302
+ redir * /_cascade/ 302
}
handle /_cascade/* {
diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css
index d0a638e..feefe10 100644
--- a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css
+++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.css
@@ -118,3 +118,24 @@ a.cascade-tree-row.is-active:hover {
color: #8a96a3;
font-weight: 600;
}
+.cascade-hint {
+ width: 100%;
+ max-width: 45rem;
+ margin: 0.15rem auto 0;
+ box-sizing: border-box;
+ padding: 0.2rem 0.35rem;
+ color: #f0c674;
+ text-align: center;
+}
+.cascade-hint[hidden] {
+ display: none;
+}
+.cascade-missing-msg {
+ max-width: 45rem;
+ margin: 1.5rem auto;
+ padding: 0 0.75rem;
+ color: #c8d0d8;
+ font-family: ui-sans-serif, system-ui, sans-serif;
+ font-size: 1rem;
+ line-height: 1.4;
+}
diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html
index ed51952..d81564d 100644
--- a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html
+++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.html
@@ -1,5 +1,6 @@
diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js
index 8fe4765..8db6e4a 100644
--- a/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js
+++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/bar.js
@@ -25,6 +25,99 @@
}
}
+ function setEditionCookie(edition) {
+ document.cookie =
+ "tdpd_edition=" +
+ encodeURIComponent(edition) +
+ "; Path=/; Max-Age=31536000; SameSite=Lax";
+ }
+
+ function keepPath() {
+ return location.pathname + location.search;
+ }
+
+ function useHref(edition) {
+ var path = keepPath();
+ var href = "/_cascade/use/" + encodeURIComponent(edition);
+ if (!path || path.indexOf("/_cascade/use/") === 0) return href;
+ return href + "?next=" + encodeURIComponent(path);
+ }
+
+ function hintEl() {
+ return document.getElementById("cascade-hint");
+ }
+
+ function showHint(msg) {
+ var el = hintEl();
+ if (!el) {
+ var bar = document.getElementById("cascade-bar");
+ if (!bar) return;
+ el = document.createElement("div");
+ el.id = "cascade-hint";
+ el.className = "cascade-hint";
+ el.setAttribute("role", "status");
+ bar.appendChild(el);
+ }
+ el.hidden = false;
+ el.textContent = msg;
+ pinBar();
+ }
+
+ function clearHint() {
+ var el = hintEl();
+ if (!el) return;
+ el.hidden = true;
+ el.textContent = "";
+ pinBar();
+ }
+
+ function responseKeepsBar(res, text) {
+ if (res && res.ok) return true;
+ var body = text || "";
+ return (
+ body.indexOf("cascade-bar") !== -1 ||
+ body.indexOf("cascade-missing") !== -1
+ );
+ }
+
+ function switchEdition(edition, branchLabel) {
+ var prev = cookieEdition();
+ var here = keepPath() || "/";
+ var label = branchLabel || edition;
+ if (!edition) return;
+ if (edition === prev) {
+ clearHint();
+ return;
+ }
+ setEditionCookie(edition);
+ fetch(here, { cache: "no-store", credentials: "same-origin" })
+ .then(function (res) {
+ return res.text().then(function (text) {
+ return { res: res, text: text };
+ });
+ })
+ .then(function (got) {
+ if (responseKeepsBar(got.res, got.text)) {
+ location.replace(here + location.hash);
+ return;
+ }
+ setEditionCookie(prev);
+ showHint(
+ "This path is not in " +
+ label +
+ ". Choose another branch above."
+ );
+ })
+ .catch(function () {
+ setEditionCookie(prev);
+ showHint(
+ "This path is not in " +
+ label +
+ ". Choose another branch above."
+ );
+ });
+ }
+
function esc(s) {
return String(s)
.replace(/&/g, "&")
@@ -276,8 +369,8 @@
var parent = row.parent || "";
var isDefault = branch === defaultBranch;
html.push(
- 'flask' +
+ 'flask' +
' (branch-status unavailable)';
markActive(mount, cookieEdition());
pinBar();
@@ -341,6 +436,26 @@
});
}
+ document.addEventListener("click", function (ev) {
+ var a = ev.target.closest
+ ? ev.target.closest("a.cascade-tree-row[data-edition]")
+ : null;
+ if (!a || ev.defaultPrevented) return;
+ if (ev.button !== 0 || ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey)
+ return;
+ ev.preventDefault();
+ switchEdition(
+ a.getAttribute("data-edition"),
+ a.getAttribute("data-branch") || a.getAttribute("data-edition")
+ );
+ });
+
+ if (document.body && document.body.classList.contains("cascade-missing")) {
+ showHint(
+ "This path is not in the current branch. Choose another branch above."
+ );
+ }
+
loadStatus(false);
setInterval(function () {
loadStatus(true);
diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/index.html b/sites/dossiers.ngi.hacktivism.ch/_cascade/index.html
index 036ead3..db0bc96 100644
--- a/sites/dossiers.ngi.hacktivism.ch/_cascade/index.html
+++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/index.html
@@ -9,6 +9,7 @@
Stuck on an edition without a bar? Pick a build above, or reset to flask.
diff --git a/sites/dossiers.ngi.hacktivism.ch/_cascade/missing.html b/sites/dossiers.ngi.hacktivism.ch/_cascade/missing.html new file mode 100644 index 0000000..449d470 --- /dev/null +++ b/sites/dossiers.ngi.hacktivism.ch/_cascade/missing.html @@ -0,0 +1,17 @@ + + + + + +This address is not in the current branch. Choose another branch above.
+ + + diff --git a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.css b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.css index d0a638e..feefe10 100644 --- a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.css +++ b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.css @@ -118,3 +118,24 @@ a.cascade-tree-row.is-active:hover { color: #8a96a3; font-weight: 600; } +.cascade-hint { + width: 100%; + max-width: 45rem; + margin: 0.15rem auto 0; + box-sizing: border-box; + padding: 0.2rem 0.35rem; + color: #f0c674; + text-align: center; +} +.cascade-hint[hidden] { + display: none; +} +.cascade-missing-msg { + max-width: 45rem; + margin: 1.5rem auto; + padding: 0 0.75rem; + color: #c8d0d8; + font-family: ui-sans-serif, system-ui, sans-serif; + font-size: 1rem; + line-height: 1.4; +} diff --git a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.html b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.html index ed51952..d81564d 100644 --- a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.html +++ b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.html @@ -1,5 +1,6 @@ diff --git a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.js b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.js index 8fe4765..8db6e4a 100644 --- a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.js +++ b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/bar.js @@ -25,6 +25,99 @@ } } + function setEditionCookie(edition) { + document.cookie = + "tdpd_edition=" + + encodeURIComponent(edition) + + "; Path=/; Max-Age=31536000; SameSite=Lax"; + } + + function keepPath() { + return location.pathname + location.search; + } + + function useHref(edition) { + var path = keepPath(); + var href = "/_cascade/use/" + encodeURIComponent(edition); + if (!path || path.indexOf("/_cascade/use/") === 0) return href; + return href + "?next=" + encodeURIComponent(path); + } + + function hintEl() { + return document.getElementById("cascade-hint"); + } + + function showHint(msg) { + var el = hintEl(); + if (!el) { + var bar = document.getElementById("cascade-bar"); + if (!bar) return; + el = document.createElement("div"); + el.id = "cascade-hint"; + el.className = "cascade-hint"; + el.setAttribute("role", "status"); + bar.appendChild(el); + } + el.hidden = false; + el.textContent = msg; + pinBar(); + } + + function clearHint() { + var el = hintEl(); + if (!el) return; + el.hidden = true; + el.textContent = ""; + pinBar(); + } + + function responseKeepsBar(res, text) { + if (res && res.ok) return true; + var body = text || ""; + return ( + body.indexOf("cascade-bar") !== -1 || + body.indexOf("cascade-missing") !== -1 + ); + } + + function switchEdition(edition, branchLabel) { + var prev = cookieEdition(); + var here = keepPath() || "/"; + var label = branchLabel || edition; + if (!edition) return; + if (edition === prev) { + clearHint(); + return; + } + setEditionCookie(edition); + fetch(here, { cache: "no-store", credentials: "same-origin" }) + .then(function (res) { + return res.text().then(function (text) { + return { res: res, text: text }; + }); + }) + .then(function (got) { + if (responseKeepsBar(got.res, got.text)) { + location.replace(here + location.hash); + return; + } + setEditionCookie(prev); + showHint( + "This path is not in " + + label + + ". Choose another branch above." + ); + }) + .catch(function () { + setEditionCookie(prev); + showHint( + "This path is not in " + + label + + ". Choose another branch above." + ); + }); + } + function esc(s) { return String(s) .replace(/&/g, "&") @@ -276,8 +369,8 @@ var parent = row.parent || ""; var isDefault = branch === defaultBranch; html.push( - 'flask' +
+ 'flask' +
' (branch-status unavailable)';
markActive(mount, cookieEdition());
pinBar();
@@ -341,6 +436,26 @@
});
}
+ document.addEventListener("click", function (ev) {
+ var a = ev.target.closest
+ ? ev.target.closest("a.cascade-tree-row[data-edition]")
+ : null;
+ if (!a || ev.defaultPrevented) return;
+ if (ev.button !== 0 || ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey)
+ return;
+ ev.preventDefault();
+ switchEdition(
+ a.getAttribute("data-edition"),
+ a.getAttribute("data-branch") || a.getAttribute("data-edition")
+ );
+ });
+
+ if (document.body && document.body.classList.contains("cascade-missing")) {
+ showHint(
+ "This path is not in the current branch. Choose another branch above."
+ );
+ }
+
loadStatus(false);
setInterval(function () {
loadStatus(true);
diff --git a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/index.html b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/index.html
index 036ead3..db0bc96 100644
--- a/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/index.html
+++ b/sites/dossiers.ngi.hacktivism.ch/cascade/_cascade/index.html
@@ -9,6 +9,7 @@
Stuck on an edition without a bar? Pick a build above, or reset to flask.