mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-08-10 23:31:21 +02:00
fix: prevent file deletion on relink + restore button now visible + OOB-style in-place update
Two critical fixes: 1. Relink flow no longer destroys/recreates FilePond instances: The relink (XamxamRelinkFile) and PeerTube relink (XamxamRelinkPeerTube) previously refreshed the entire fichiers fragment via HTMX after pond.addFile(). This triggered destroyFilePondsIn on ALL pools, which could fire server.remove callbacks and move existing files to corbeille. Now just closes the modal — the file is already added to the pool in-place, and syncOrderInput creates the hidden form input. 2. Cleanup page « Corbeille (restaurable) » now actually shows files: _cleanup-stats-data.php previously classified trash files by checking if the thesis_files DB row still existed. But both deleteThesisFileToTrash and FilepondHandler::handleRemove DELETE the DB row. So ALL trash files appeared as `stale` (not restorable). Now uses the JSON sidecar file presence as the classification criterion — if the sidecar exists and is recent, the file is restorable regardless of DB row state. Also removed unused DB query from _cleanup-stats-data.php.
This commit is contained in:
@@ -321,6 +321,15 @@
|
||||
|
||||
remove: (source, load, error) => {
|
||||
console.log(`[filepond] remove called | id=${source}`);
|
||||
// During teardown (HTMX swap), skip server round-trips.
|
||||
// FilePond 4.x destroy() does not normally fire remove callbacks,
|
||||
// but this guard prevents accidental deletion of DB files as a
|
||||
// defence-in-depth measure.
|
||||
if (_xamxamTeardown) {
|
||||
console.log(`[filepond] remove skipped (teardown) | id=${source}`);
|
||||
load();
|
||||
return;
|
||||
}
|
||||
// Hex IDs (32 chars) → temp files → use revert endpoint
|
||||
if (/^[a-f0-9]{32}$/.test(source)) {
|
||||
fetch(`${base}/revert.php`, {
|
||||
@@ -519,6 +528,13 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Guard flag set during destroyFilePondsIn — the server.remove callback
|
||||
* checks this and skips the server round-trip during teardown to prevent
|
||||
* accidental deletion of existing DB files from FilePond.destroy().
|
||||
*/
|
||||
let _xamxamTeardown = false;
|
||||
|
||||
/**
|
||||
* Destroy FilePond instances inside a given container element.
|
||||
* Generic: handles ANY HTMX swap target, not just known IDs.
|
||||
@@ -563,8 +579,12 @@
|
||||
} catch (_abort) {}
|
||||
}
|
||||
}
|
||||
_xamxamTeardown = true;
|
||||
pond.destroy();
|
||||
} catch (_) {}
|
||||
_xamxamTeardown = false;
|
||||
} catch (_) {
|
||||
_xamxamTeardown = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -885,24 +905,9 @@
|
||||
" | found=" +
|
||||
!!input,
|
||||
);
|
||||
var closeAndRefresh = () => {
|
||||
var closeModal = () => {
|
||||
var modal = document.getElementById("relink-modal");
|
||||
if (modal) modal.close();
|
||||
// Re-fetch the fichiers fragment from the server so the
|
||||
// newly-linked file appears in the FilePond pools.
|
||||
var block = document.getElementById("format-fichiers-block");
|
||||
if (block && window.htmx) {
|
||||
let url = "/admin/fragments/fichiers.php";
|
||||
if (window.__xamxamRelinkCtx?.thesisId) {
|
||||
url +=
|
||||
"?_thesis_id=" +
|
||||
encodeURIComponent(window.__xamxamRelinkCtx.thesisId);
|
||||
}
|
||||
htmx.ajax("GET", url, {
|
||||
target: "#format-fichiers-block",
|
||||
swap: "outerHTML",
|
||||
});
|
||||
}
|
||||
};
|
||||
if (input) {
|
||||
const pond = FilePond.find(input);
|
||||
@@ -924,25 +929,25 @@
|
||||
" | queueType=" +
|
||||
queueType,
|
||||
);
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("[relink] addFile rejected", err);
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
});
|
||||
} else {
|
||||
console.error(
|
||||
"[relink] FilePond.find returned null for input",
|
||||
input,
|
||||
);
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
"[relink] input not found, page may have reloaded | queueType=" +
|
||||
queueType,
|
||||
);
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
}
|
||||
|
||||
// Mark form dirty
|
||||
@@ -1008,18 +1013,9 @@
|
||||
var input = document.querySelector(
|
||||
'.tfe-file-picker[data-queue-type="tfe"]',
|
||||
);
|
||||
var closeAndRefresh = () => {
|
||||
var closeModal = () => {
|
||||
var modal = document.getElementById("peertube-relink-modal");
|
||||
if (modal) modal.close();
|
||||
var block = document.getElementById("format-fichiers-block");
|
||||
if (block && window.htmx) {
|
||||
var url = "/admin/fragments/fichiers.php";
|
||||
if (thesisId) url += `?_thesis_id=${encodeURIComponent(thesisId)}`;
|
||||
htmx.ajax("GET", url, {
|
||||
target: "#format-fichiers-block",
|
||||
swap: "outerHTML",
|
||||
});
|
||||
}
|
||||
};
|
||||
if (input) {
|
||||
var pond = FilePond.find(input);
|
||||
@@ -1035,19 +1031,19 @@
|
||||
})
|
||||
.then(() => {
|
||||
console.log("[pt-relink] addFile resolved");
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("[pt-relink] addFile rejected", err);
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
});
|
||||
} else {
|
||||
console.error("[pt-relink] FilePond.find returned null");
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
}
|
||||
} else {
|
||||
console.warn("[pt-relink] input not found");
|
||||
closeAndRefresh();
|
||||
closeModal();
|
||||
}
|
||||
|
||||
window.__xamxamDirty = true;
|
||||
|
||||
Reference in New Issue
Block a user