Files
xamxam/app/public/assets/js/app/autosave-handler.js
T
Pontoporeia 10df92b643 fix: load autosave-handler.js on about_page edit view, persist contact group deletion
Two fixes:

1. about_page edit was missing autosave-handler.js: the first if block
   (editType === 'page' || 'about_page') overrode $extraJs with only
   overtype.min.js, making the elseif that added autosave-handler.js
   unreachable for about_page. Added autosave-handler.js to the first
   block, removed dead 'about_page' from the elseif.

2. Deleting a contact group (Contacts 3/4/5) only removed the DOM
   element but never triggered htmx autosave. Dispatched a 'change'
   event on the form after removal+reindex so the hx-trigger fires.

Also expanded autosave-handler.js URL filter to accept apropos.php
so the status indicator (Enregistrement/Enregistré) works for contacts saves.
2026-07-05 14:14:13 +02:00

81 lines
2.8 KiB
JavaScript

/**
* Shared HTMX after-request handler for autosave forms.
*
* Reads the JSON response, updates the CSRF token, and surfaces
* parse errors instead of silently swallowing them (unlike the
* old autosave.js .catch(() => {}) pattern).
*/
function handleAutosaveResponse(event) {
// Only handle responses from autosave endpoints (draft.php).
// The htmx:afterRequest event bubbles, so child elements'
// HTMX requests (e.g. licence fragment, pill-search) also
// reach this handler. We filter by URL to avoid mixing them.
const url = event.detail.requestConfig?.path || "";
if (!url.includes("draft.php") && !url.includes("apropos.php")) return;
const form = event.target.closest("form");
const status = form ? form.querySelector("[data-autosave-status]") : null;
if (!event.detail.successful) {
if (status) {
status.textContent = "Erreur !";
status.className = "autosave-status autosave-status--error";
}
return;
}
try {
const data = JSON.parse(event.detail.xhr.responseText);
// Rotate CSRF token in the form, any share_link_token fields, and the meta tag
if (data.csrf_token) {
const csrfInput = form.querySelector('input[name="csrf_token"]');
if (csrfInput) csrfInput.value = data.csrf_token;
const shareTokenInput = form.querySelector(
'input[name="share_link_token"]',
);
if (shareTokenInput) shareTokenInput.value = data.csrf_token;
const meta = document.querySelector('meta[name="csrf-token"]');
if (meta) meta.content = data.csrf_token;
}
if (status) {
if (data.success) {
status.textContent = "Enregistré ✓";
status.className = "autosave-status autosave-status--saved";
} else {
status.textContent = "Erreur !";
status.className = "autosave-status autosave-status--error";
}
}
} catch {
// JSON parse failed (e.g. PHP warning in output) — surface it
if (status) {
status.textContent = "Erreur !";
status.className = "autosave-status autosave-status--error";
}
console.warn(
"Autosave: could not parse response",
event.detail.xhr.responseText,
);
}
}
// Expose globally for HTMX hx-on::after-request inlines (bundles wrap in IIFE)
window.handleAutosaveResponse = handleAutosaveResponse;
// Show saving indicator while request is in flight
document.body.addEventListener("htmx:beforeRequest", (e) => {
const url = e.detail.requestConfig?.path || "";
if (!url.includes("draft.php") && !url.includes("apropos.php")) return;
// The autosave request comes from the hidden probe div, so find
// the status indicator by searching the closest form.
const el = e.target;
const form = el?.closest?.("form");
const status = form?.querySelector?.("[data-autosave-status]");
if (status) {
status.textContent = "Enregistrement…";
status.className = "autosave-status autosave-status--saving";
}
});