feat: file browser + relink for orphaned files + htmx fix + header cleanup + fix relinked FilePond integration + resolve acces.php conflict markers

This commit is contained in:
Pontoporeia
2026-05-18 17:39:01 +02:00
parent 79eddf5d5a
commit 27e6abc7e4
10 changed files with 268 additions and 205866 deletions

View File

@@ -524,12 +524,21 @@
FilePond.registerPlugin(FilePondPluginImageExifOrientation);
}
if (window.htmx) {
// ── HTMX integration (register later once htmx is loaded) ───────────
// Note: htmx.min.js loads at the end of <body> (admin/footer.php),
// after this script. Use DOM polling or a listener to wire up.
function tryRegisterHtmx() {
if (!window.htmx) {
setTimeout(tryRegisterHtmx, 50);
return;
}
console.log('[filepond] htmx detected, registering swap listeners');
window.htmx.on("htmx:beforeSwap", onHtmxBeforeSwap);
window.htmx.on("htmx:afterSwap", () => {
window.XamxamInitFilePonds();
});
}
tryRegisterHtmx();
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
@@ -553,51 +562,14 @@
// ── Relink file browser ──────────────────────────────────────────
/**
* Open the file browser modal for a specific queue type.
* Triggered by the "📂 Relier un fichier" button.
*/
window.XamxamOpenFileBrowser = (btn) => {
var queueType = btn.dataset.queueType;
var thesisId = btn.dataset.thesisId;
// Store context for the relink callback
window.__xamxamRelinkCtx = {
queueType: queueType,
thesisId: thesisId,
};
var modal = document.getElementById('relink-modal');
if (!modal) {
console.error('[relink] modal #relink-modal not found');
return;
}
var body = document.getElementById('relink-modal-body');
body.innerHTML = '<p class="file-browser-loading">Chargement…</p>';
modal.showModal();
// Load the file browser via HTMX (or fetch if htmx not available)
if (window.htmx) {
window.htmx.ajax('GET', '/admin/fragments/file-browser.php', {
target: '#relink-modal-body',
swap: 'innerHTML',
});
} else {
fetch('/admin/fragments/file-browser.php')
.then(r => r.text())
.then(html => { body.innerHTML = html; })
.catch(() => { body.innerHTML = '<p class="file-browser-error">Erreur de chargement.</p>'; });
}
};
/**
* Relink a selected file to the thesis.
* Triggered when a file is clicked in the file browser.
* Called from the onclick handler on file-browser entries.
* The file browser is loaded inside #relink-modal-body via HTMX.
*/
window.XamxamRelinkFile = (el) => {
var li = el.closest('.file-browser-entry');
console.log('[relink] XamxamRelinkFile called | el=', el, '| li=', li);
if (!li) return;
var ctx = window.__xamxamRelinkCtx || {};
@@ -609,6 +581,8 @@
var fileSize = parseInt(li.dataset.fileSize, 10) || 0;
var ext = li.dataset.fileExt || '';
console.log('[relink] data | thesisId=' + thesisId + ' | queueType=' + queueType + ' | filePath=' + filePath + ' | fileName=' + fileName + ' | ext=' + ext);
if (!filePath || !thesisId || !queueType) {
console.error('[relink] missing data', { filePath, thesisId, queueType });
return;
@@ -626,6 +600,7 @@
var mimeType = mimeMap[ext] || 'application/octet-stream';
var csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '';
console.log('[relink] csrfToken=' + (csrfToken ? csrfToken.substring(0, 8) + '...' : 'MISSING'));
var bodyEl = document.getElementById('relink-modal-body');
if (bodyEl) bodyEl.innerHTML = '<p class="file-browser-loading">Reliage en cours…</p>';
@@ -647,22 +622,41 @@
})
.then(r => r.json().then(data => ({ ok: r.ok, status: r.status, data })))
.then(({ ok, status, data }) => {
if (!ok) {
if (bodyEl) bodyEl.innerHTML = `<p class="file-browser-error">Erreur : ${data}</p>`;
if (!ok || (data && data.ok === false)) {
var msg = (data && data.error) ? data.error : (typeof data === 'string' ? data : 'Erreur ' + status);
if (bodyEl) bodyEl.innerHTML = `<p class="file-browser-error">Erreur : ${msg}</p>`;
return;
}
console.log('[relink] success | new_id=' + data.id);
// Add the new file to the FilePond pool
var input = document.querySelector(`.tfe-file-picker[data-queue-type="${queueType}"]`);
console.log('[relink] looking for input | selector=' + `.tfe-file-picker[data-queue-type="${queueType}"]` + ' | found=' + !!input);
if (input) {
var pond = FilePond.find(input);
console.log('[relink] looking for pond | found=' + !!pond);
if (pond) {
pond.addFile({
source: String(data.id),
options: { type: 'local' },
});
try {
pond.addFile({
source: String(data.id),
options: {
type: 'local',
file: {
name: fileName,
size: fileSize,
type: mimeType
}
},
});
console.log('[relink] addFile called successfully | source=' + String(data.id) + ' | queueType=' + queueType);
} catch (e) {
console.error('[relink] addFile error', e);
}
} else {
console.error('[relink] FilePond.find returned null for input', input);
}
} else {
console.error('[relink] input not found | queueType=' + queueType);
}
// Close modal