fix: merge corbeille lists + bulk restore button in cleanup

- Single unified 'Corbeille' table replaces the two separate lists
  (stale/orphelin + restorable). Each row has a Statut column showing
  '↺ Restaurable' or 'Orphelin', plus a checkbox for bulk ops.

- Checkboxes on restorable rows carry data-restorable='1' attribute
  so the bulk JS can distinguish them.

- Bulk actions bar now has both 'Supprimer la sélection' and
  '↺ Restaurer la sélection' buttons. The restore button only appears
  when at least one restorable item is checked.

- New cleanupBulkRestore() JS function populates a dedicated hidden
  form and confirms before submitting. Only restorable items are sent.

- restore-trash.php refactored to handle both single (trash_file) and
  bulk (trash_files[]) inputs via a loop, accumulating restored/skipped
  counts and re-rendering the fragment on HTMX requests.
This commit is contained in:
Pontoporeia
2026-07-10 16:33:06 +02:00
parent 3cecee10c9
commit 7013f79fc0
5 changed files with 180 additions and 152 deletions
+42 -4
View File
@@ -1,7 +1,7 @@
/**
* admin-cleanup-bulk.js — Bulk selection and deletion for the temp files cleanup dialog.
* admin-cleanup-bulk.js — Bulk selection, deletion, and restore for the temp files cleanup dialog.
*
* Provides: cleanupToggleAll, cleanupUpdateBulk, cleanupBulkDelete.
* Provides: cleanupToggleAll, cleanupUpdateBulk, cleanupBulkDelete, cleanupBulkRestore.
* All functions are attached to `window` for onclick handlers in PHP templates.
*/
(() => {
@@ -19,13 +19,25 @@
function cleanupUpdateBulk() {
const bar = document.getElementById("cleanup-bulk-actions");
const countEl = document.getElementById("cleanup-selected-count");
const restoreBtn = document.getElementById("cleanup-bulk-restore-btn");
if (!bar || !countEl) return;
const n = document.querySelectorAll(
const allChecked = document.querySelectorAll(
'input[name="filepond_dirs[]"]:checked, input[name="trash_files[]"]:checked',
).length;
);
const n = allChecked.length;
// Count how many checked items are restorable
let nRestorable = 0;
allChecked.forEach((cb) => {
if (cb.dataset.restorable === "1") nRestorable++;
});
countEl.textContent = n;
bar.style.display = n > 0 ? "flex" : "none";
if (restoreBtn) {
restoreBtn.style.display = nRestorable > 0 ? "" : "none";
}
}
function cleanupBulkDelete() {
@@ -51,6 +63,31 @@
htmx.trigger(form, "submit");
}
function cleanupBulkRestore() {
const form = document.getElementById("cleanup-bulk-restore-form");
const container = document.getElementById("cleanup-bulk-restore-checkboxes");
if (!form || !container) return;
container.innerHTML = "";
let count = 0;
document
.querySelectorAll('input[name="trash_files[]"]:checked[data-restorable="1"]')
.forEach((cb) => {
const inp = document.createElement("input");
inp.type = "hidden";
inp.name = "trash_files[]";
inp.value = cb.value;
container.appendChild(inp);
count++;
});
if (count === 0) return;
if (!confirm(`Restaurer ${count} fichier(s) vers leur(s) TFE associé(s) ?`)) return;
htmx.trigger(form, "submit");
}
function reattachListeners() {
document
.querySelectorAll(
@@ -73,4 +110,5 @@
window.cleanupToggleAll = cleanupToggleAll;
window.cleanupUpdateBulk = cleanupUpdateBulk;
window.cleanupBulkDelete = cleanupBulkDelete;
window.cleanupBulkRestore = cleanupBulkRestore;
})();