From 13d26ded66e43ef4397c96338b8c22279bfa2f2e Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Sun, 10 May 2026 17:16:25 +0200 Subject: [PATCH] Replace HTMX+PHP file upload queues with client-side JS Drops the session-backed HTMX incremental upload system in favour of a single JS module that manages `File` objects client-side and injects them into `FormData` on submit. Key changes: * `file-upload-queue.js`: client-side queues with validation, reorder (SortableJS), removal, dirty-state tracking, and fetch-based submit with manual redirect handling * `fichiers-fragment.php`: empty queue containers for JS-managed queues; HTMX format switching still works with queue rehydration after swap; annexe uploads now support multiple files * Form UI cleanup: moved existing files and cover preview into the `Fichiers` fieldset (edit mode); removed redundant queue labels while keeping labels for single-file inputs (`couverture`, `note d'intention`); added delete buttons for existing files * `ThesisFileHandler.php`: added `handleTfeQueueFiles()`/`handleAnnexeQueueFiles()` reading from `$_FILES['queue_file']`; introduced `extractFilesSubArray()` for nested upload arrays; removed session-based queue handling * `ThesisCreateController.php` & `ThesisEditController.php`: switched to extracted `['queue_file']` uploads * `beforeunload-guard.js`: now also watches `window.__xamxamDirty` * Deleted obsolete PHP upload/remove/reorder queue endpoints for `partage` and `admin` * Cleaned up route dispatch in `partage/index.php` * Misc form and styling updates in templates/CSS * Added `docs/cms-migration-plan.html` --- TODO.md | 6 +- app/public/admin/add.php | 2 +- app/public/admin/edit.php | 2 +- app/public/admin/remove-tfe-file.php | 12 - app/public/admin/upload-tfe-file.php | 12 - app/public/assets/css/form.css | 19 + app/public/assets/js/beforeunload-guard.js | 5 +- app/public/assets/js/file-upload-queue.js | 479 ++++++- app/public/partage/fichiers-fragment.php | 316 ++-- app/public/partage/index.php | 15 +- app/public/partage/remove-tfe-file.php | 47 - app/public/partage/tfe-queue-helper.php | 78 - app/public/partage/upload-tfe-file.php | 119 -- .../Controllers/ThesisCreateController.php | 27 +- app/src/Controllers/ThesisEditController.php | 32 +- app/src/Controllers/ThesisFileHandler.php | 262 ++-- app/templates/admin/acces.php | 13 + .../partials/form/fieldset-files.php | 2 +- app/templates/partials/form/form.php | 102 -- docs/cms-migration-plan.html | 1266 +++++++++++++++++ 20 files changed, 2063 insertions(+), 753 deletions(-) delete mode 100644 app/public/admin/remove-tfe-file.php delete mode 100644 app/public/admin/upload-tfe-file.php delete mode 100644 app/public/partage/remove-tfe-file.php delete mode 100644 app/public/partage/tfe-queue-helper.php delete mode 100644 app/public/partage/upload-tfe-file.php create mode 100644 docs/cms-migration-plan.html diff --git a/TODO.md b/TODO.md index 2c0f2cc..7410efc 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,3 @@ # TODO -- [x] Fix cross-field validation contamination — wrap file-field.php in
to scope hx-include -- [x] Add inline MIME/size validation to upload-tfe-file.php -- [x] Add inline validation wrappers to PeerTube video/audio and direct video/audio inputs -- [x] Fix validator fallback: if field_name key missing in $_FILES, try first available file -- [x] Fix file-field.php admin_mode using $adminMode variable instead of undefined ADMIN_MODE constant +- [x] Replace HTMX+PHP file upload queues with client-side JS diff --git a/app/public/admin/add.php b/app/public/admin/add.php index 2584de0..96232bb 100644 --- a/app/public/admin/add.php +++ b/app/public/admin/add.php @@ -55,7 +55,7 @@ function wasSelected($key, $value) { $isAdmin = true; $bodyClass = 'admin-body'; $extraCss = ['/assets/css/form.css']; -$extraJs = ['/assets/js/file-upload-queue.js', '/assets/js/beforeunload-guard.js']; +$extraJs = ['/assets/js/sortable.min.js', '/assets/js/file-upload-queue.js', '/assets/js/beforeunload-guard.js']; require_once APP_ROOT . '/templates/head.php'; include APP_ROOT . '/templates/header.php'; include APP_ROOT . '/templates/admin/add.php'; diff --git a/app/public/admin/edit.php b/app/public/admin/edit.php index 10e88b5..9326cbf 100644 --- a/app/public/admin/edit.php +++ b/app/public/admin/edit.php @@ -40,7 +40,7 @@ try { $isAdmin = true; $bodyClass = 'admin-body'; $extraCss = ['/assets/css/form.css']; -$extraJs = ['/assets/js/file-upload-queue.js', '/assets/js/beforeunload-guard.js']; +$extraJs = ['/assets/js/sortable.min.js', '/assets/js/file-upload-queue.js', '/assets/js/beforeunload-guard.js']; require_once APP_ROOT . '/templates/head.php'; include APP_ROOT . '/templates/header.php'; include APP_ROOT . '/templates/admin/edit.php'; diff --git a/app/public/admin/remove-tfe-file.php b/app/public/admin/remove-tfe-file.php deleted file mode 100644 index e34a813..0000000 --- a/app/public/admin/remove-tfe-file.php +++ /dev/null @@ -1,12 +0,0 @@ - { @@ -13,11 +14,11 @@ for (const form of forms) { form.addEventListener('input', () => { dirty = true; }); form.addEventListener('change', () => { dirty = true; }); - form.addEventListener('submit', () => { dirty = false; }); + form.addEventListener('submit', () => { dirty = false; window.__xamxamDirty = false; }); } window.addEventListener('beforeunload', (e) => { - if (dirty) { + if (dirty || window.__xamxamDirty) { e.preventDefault(); } }); diff --git a/app/public/assets/js/file-upload-queue.js b/app/public/assets/js/file-upload-queue.js index 89f9374..713d31e 100644 --- a/app/public/assets/js/file-upload-queue.js +++ b/app/public/assets/js/file-upload-queue.js @@ -1,17 +1,31 @@ /** * file-upload-queue.js * - * Provides single-file previews for file inputs with the data-preview attribute - * (couverture, note_intention, annexes, etc.). + * Client-side file upload queues for TFE, Video, Audio, and Annexe files. + * Replaces the old HTMX+PHP session-backed queue system. * - * The multi-file TFE queue is rendered server-side via HTMX fragments - * (upload-tfe-file.php / remove-tfe-file.php). + * Queues: + * tfe — main thesis files (multi-format) + * video — video files (non-PeerTube path) + * audio — audio files (non-PeerTube path) + * annexe — annex files * - * Exposes window.XamxamInitFileUploads() so HTMX fragments can re-bind - * after swap without a global event listener. + * Architecture: + * 1. Intercept 'change' on all .tfe-file-picker inputs. + * 2. Validate MIME/extension/size client-side. + * 3. Store File objects in window.__xamxamQueues. + * 4. Render queue UI with SortableJS drag-to-reorder. + * 5. On form submit: inject all queued files into FormData and POST normally. + * + * The queue containers are rendered server-side by fichiers-fragment.php + * as empty