Files
xamxam/app/public/assets/js/app/admin-logs.js
Pontoporeia 99125cc8e3 Add autosave draft system for partage form with HTMX-based session persistence
- New fragment endpoint POST/GET /partage/fragments/draft.php:
  saves all form fields to PHP session, excludes file/csrf/slug fields
  GET returns JSON for JS hydration on page load
  rotates both global CSRF and share CSRF tokens in sync

- form.php accepts optional $formExtraAttrs and $showAutosaveStatus:
  allows injecting HTMX attributes and 'Brouillon enregistré' indicator

- renderShareLinkForm adds hx-post with change/input debounce trigger,
  loads autosave-handler.js, hydrate fields from draft on page load

- Draft cleared on successful form submission in handleShareLinkSubmission

- autosave-handler.js now also updates share_link_token hidden input
  when rotating CSRF token (partage form uses both csrf_token and share_link_token)

- Added .autosave-status CSS to form.css (was admin.css-only)

- Updated fragment routing to accept GET requests (needed for draft hydration)
2026-06-11 11:04:49 +02:00

71 lines
2.1 KiB
JavaScript

/**
* admin-logs.js — log viewer utilities shared by system.php and parametres.php.
*
* Provides:
* - copyLogContent(btn) — copy visible log lines to clipboard
* - HTMX afterSwap handler to update active tab class on #sys-tab-panel
*/
(() => {
window.copyLogContent = (btn) => {
var logOut = document.querySelector("#log-output");
if (!logOut) return;
var text = Array.from(logOut.querySelectorAll(".log-line"))
.map((el) => el.textContent)
.join("\n");
if (navigator.clipboard?.writeText) {
navigator.clipboard.writeText(text).then(() => {
btn.textContent = "\u2713 Copi\u00e9";
btn.classList.add("copied");
setTimeout(() => {
btn.textContent = "Copier";
btn.classList.remove("copied");
}, 2000);
});
} else {
window._fallbackCopy(text, btn);
}
};
window._fallbackCopy = (text, btn) => {
var ta = document.createElement("textarea");
ta.value = text;
ta.style.cssText = "position:fixed;opacity:0";
document.body.appendChild(ta);
ta.select();
try {
document.execCommand("copy");
btn.textContent = "\u2713 Copi\u00e9";
btn.classList.add("copied");
setTimeout(() => {
btn.textContent = "Copier";
btn.classList.remove("copied");
}, 2000);
} catch (_e) {}
document.body.removeChild(ta);
};
// Update active tab class after each HTMX swap on #sys-tab-panel
document.body.addEventListener("htmx:afterSwap", (evt) => {
if (!(evt.detail.target && evt.detail.target.id === "sys-tab-panel"))
return;
var rc = evt.detail.requestConfig;
var tab = null;
// Tab clicks carry ?tab=… in the path
var qIdx = rc.path.indexOf("?");
if (qIdx !== -1) {
tab = new URLSearchParams(rc.path.substring(qIdx + 1)).get("tab");
}
// Line-count form sends tab via hx-vals in parameters
if (!tab && rc.parameters && rc.parameters.tab) {
tab = rc.parameters.tab;
}
if (!tab) return;
document.querySelectorAll(".sys-tabs .sys-tab").forEach((a) => {
var isActive = a.getAttribute("data-tab") === tab;
a.classList.toggle("active", isActive);
if (isActive) a.setAttribute("aria-current", "page");
else a.removeAttribute("aria-current");
});
});
})();