Add pagination to public endpoints, Pangolin site picker, and docs editor toolbar
- Paginate public APIs: campaigns, petitions, shifts, products, pages, shop - Add safety caps (take limits) to gallery ads, cuts, plans, donation pages - Add Pangolin connect-site endpoint with .env writer and site ID validation - Add formatting toolbar + keyboard shortcuts to shared doc editor - Fix Dockerfile to support su-exec privilege dropping for mounted volumes - Fix duplicate WebSocket headers in nginx API location block - Update MkDocs site build and social card assets Bunker Admin
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="../assets/favicon.png">
|
||||
<link rel="icon" href="../assets/favicon.svg">
|
||||
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
|
||||
|
||||
|
||||
@@ -67,67 +67,6 @@
|
||||
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
// API URL injected from MkDocs config.extra (set by env_config_hook.py)
|
||||
var apiUrl = "https://api.cmlite.org";
|
||||
if (!apiUrl) return;
|
||||
|
||||
var trackUrl = apiUrl + "/api/docs-analytics/track";
|
||||
|
||||
// Anonymous session UUID (sessionStorage — dies with tab close, no cookies)
|
||||
function getSessionHash() {
|
||||
var key = "__docs_sh";
|
||||
var hash = sessionStorage.getItem(key);
|
||||
if (!hash) {
|
||||
hash = crypto.randomUUID
|
||||
? crypto.randomUUID()
|
||||
: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||
var r = (Math.random() * 16) | 0;
|
||||
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
||||
});
|
||||
sessionStorage.setItem(key, hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function trackPageView(path) {
|
||||
var payload = JSON.stringify({
|
||||
path: path,
|
||||
referrer: document.referrer || undefined,
|
||||
sessionHash: getSessionHash(),
|
||||
});
|
||||
|
||||
// Prefer sendBeacon for reliability (works during tab close)
|
||||
if (navigator.sendBeacon) {
|
||||
navigator.sendBeacon(trackUrl, new Blob([payload], { type: "application/json" }));
|
||||
} else {
|
||||
fetch(trackUrl, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: payload,
|
||||
keepalive: true,
|
||||
}).catch(function () {});
|
||||
}
|
||||
}
|
||||
|
||||
// Track initial page load
|
||||
trackPageView(location.pathname);
|
||||
|
||||
// Subscribe to Material's SPA navigation observable (instant loading)
|
||||
if (typeof document$ !== "undefined") {
|
||||
document$.subscribe(function () {
|
||||
trackPageView(location.pathname);
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script>if("undefined"!=typeof __md_analytics){var consent=__md_get("__consent");consent&&consent.analytics&&__md_analytics()}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1159,7 +1098,7 @@ body.cm-search-active .md-header--cm-hidden .md-search__output {
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href=".." title="Changemaker Lite" class="md-nav__button md-logo" aria-label="Changemaker Lite" data-md-component="logo">
|
||||
|
||||
<img src="../assets/logo.png" alt="logo">
|
||||
<img src="../assets/logo.svg" alt="logo">
|
||||
|
||||
</a>
|
||||
Changemaker Lite
|
||||
@@ -1416,8 +1355,6 @@ body.cm-search-active .md-header--cm-hidden .md-search__output {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1453,6 +1390,11 @@ body.cm-search-active .md-header--cm-hidden .md-search__output {
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1488,71 +1430,6 @@ body.cm-search-active .md-header--cm-hidden .md-search__output {
|
||||
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
|
||||
|
||||
|
||||
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
|
||||
<div class="md-consent__overlay"></div>
|
||||
<aside class="md-consent__inner">
|
||||
<form class="md-consent__form md-grid md-typeset" name="consent">
|
||||
|
||||
|
||||
|
||||
|
||||
<h4>Cookie consent</h4>
|
||||
<p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation. With your consent, you help us improve.
|
||||
</p>
|
||||
<input class="md-toggle" type="checkbox" id="__settings" >
|
||||
<div class="md-consent__settings">
|
||||
<ul class="task-list">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="task-list-item">
|
||||
<label class="task-list-control">
|
||||
<input type="checkbox" name="analytics" checked>
|
||||
<span class="task-list-indicator"></span>
|
||||
Google Analytics
|
||||
</label>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="md-consent__controls">
|
||||
|
||||
|
||||
<button class="md-button md-button--primary">Accept</button>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button type="reset" class="md-button md-button--primary">Reject</button>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label class="md-button" for="__settings">Manage settings</label>
|
||||
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</aside>
|
||||
</div>
|
||||
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user