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.
This commit is contained in:
Pontoporeia
2026-07-05 14:14:13 +02:00
parent 1e714982d3
commit 10df92b643
10 changed files with 54 additions and 38 deletions
@@ -65,6 +65,8 @@
if (fieldset) {
fieldset.remove();
reindexGroups();
// Trigger htmx autosave so deletion is persisted
form.dispatchEvent(new Event('change', { bubbles: true }));
}
});
}
+2 -2
View File
@@ -11,7 +11,7 @@ function handleAutosaveResponse(event) {
// 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")) return;
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;
@@ -67,7 +67,7 @@ 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")) return;
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;
@@ -47,7 +47,7 @@
labelFileTypeNotAllowed: "Format non accepté",
fileValidateTypeLabelExpectedTypes:
"PDF, Images, Vidéos, Audio, VTT, Archives",
maxFileSize: 1073741824, // 1 GB
maxFileSize: 524288000, // 500 MB
labelMaxFileSizeExceeded: "Fichier trop volumineux",
labelMaxFileSize: "Taille max: {filesize}",
allowMultiple: true,
@@ -57,17 +57,17 @@
// parseInt("1GB") = 1 byte inside the plugin).
perExtensionMaxSize: {
pdf: 104857600, // 100 MB
mp4: 8589934592, // 8 GB
webm: 8589934592,
ogv: 8589934592,
mov: 8589934592,
mp3: 8589934592,
ogg: 8589934592,
oga: 8589934592,
wav: 8589934592,
flac: 8589934592,
aac: 8589934592,
m4a: 8589934592,
mp4: 5368709120, // 5 GB
webm: 5368709120,
ogv: 5368709120,
mov: 5368709120,
mp3: 5368709120,
ogg: 5368709120,
oga: 5368709120,
wav: 5368709120,
flac: 5368709120,
aac: 5368709120,
m4a: 5368709120,
},
},
annexe: {
@@ -79,7 +79,7 @@
],
labelFileTypeNotAllowed: "Format non accepté",
fileValidateTypeLabelExpectedTypes: "PDF, ZIP, TAR, GZ",
maxFileSize: 1073741824, // 1 GB
maxFileSize: 524288000, // 500 MB
labelMaxFileSizeExceeded: "Fichier trop volumineux",
labelMaxFileSize: "Taille max: {filesize}",
allowMultiple: true,
@@ -407,21 +407,25 @@
labelButtonRetryItemLoad: "Réessayer",
labelButtonProcessItem: "Charger",
// Per-extension size validation via FileValidateSize plugin hook.
// Falls back to beforeAddFile for silent rejection (the plugin shows the error).
// Per-extension size validation: skip the global maxFileSize check
// for files with per-extension caps — beforeAddFile enforces those.
// fileValidateSizeFilter is a gate: return false to skip the
// built-in maxFileSize check; return true to proceed with it.
fileValidateSizeFilter: (item) => {
// item may be a raw File/Blob (.name) or a FilePond item wrapper (.filename)
var ext = getExt(item.filename || item.name);
// For files with per-extension caps, skip the global check.
// beforeAddFile enforces the per-extension limit.
if (ext && perExtMax[ext]) {
return parseSize(perExtMax[ext]); // per-extension cap for this item
return false;
}
return parseSize(cfg.maxFileSize); // queue default
// For files without per-extension caps, use the global maxFileSize.
return true;
},
// Fallback: beforeAddFile enforces per-extension limits (silent rejection).
// beforeAddFile: primary per-extension size enforcement.
// For files with per-extension caps, this is the authority.
// The global maxFileSize handles files without per-ext caps.
beforeAddFile: (item) => {
// This check is redundant if fileValidateSizeFilter works,
// but serves as a fallback.
if (typeof item.file === "undefined") return true;
var f = item.file;
var ext = getExt(f.name);