refactor: session-based incremental TFE upload via HTMX, drop SortableJS

Replace the client-side FileArray + Sortable drag-to-reorder with a
server-side session-based upload flow:

- New endpoints: /partage/upload-tfe-file, /partage/remove-tfe-file
  (and /admin/ variants) — single-file incremental upload via HTMX
  multipart/form-data with progress bar support
- Session storage: uploaded files go to STORAGE_ROOT/uploads/{session_id}/
  with metadata in $_SESSION['tfe_uploads']
- file-upload-queue.js reduced to single-file previews only (couverture,
  note_intention, annexes thumbnails)
- ThesisFileHandler gains handleTfeFilesFromSession + writeTfeFileFromSrc
  + cleanupSessionUploads for final commit from session temp
- Sortable.min.js removed from all script tags; drag handles and ghost
  CSS removed
- No file_orders[]/file_labels[] hidden field injection needed
- Upload queue survives page refresh (server-owned list)

This eliminates the SortableJS dependency entirely while keeping the
same UX: pick files, see them in a queue, remove individual files.
This commit is contained in:
Pontoporeia
2026-05-10 16:19:46 +02:00
parent e06a317499
commit ca7707cd47
20 changed files with 606 additions and 255 deletions

53
TODO.md
View File

@@ -1,41 +1,16 @@
# TODO
- [x] Fix language-search-fragment: use searchLanguages() like tag fragment, remove broken predefined exclusion logic
- [x] Both fragments now follow identical patterns
- [x] Fix "Créer" button not appearing on language search: both language and tag inputs used name="q" in the same form, causing HTMX to submit the wrong (empty) value — renamed to unique names (language_search_q / tag_search_q)
- [x] Exclude Français, Anglais, Néerlandais from language-search suggestions (handled by the checkbox list)
- [x] Refactor file upload naming convention
- [x] Create shared ThesisFileHandler trait (src/Controllers/ThesisFileHandler.php)
- [x] New pattern: theses/{YYYY}/{YYYY}_{AUTHORS}_{TITLE_SLUG}/
- [x] COUVERTURE: single cover image in thesis folder (covers/ directory deprecated)
- [x] NOTE_INTENTION: single PDF in thesis folder
- [x] TFE_{XX}: main files, contiguous numbering 01+, hierarchy PDF > video > audio > subtitles > images > other
- [x] Subtitles (VTT) placed immediately after their associated video in TFE sequence
- [x] ANNEXE_{XX}: annex files, separate numbering 01+
- [x] Two-digit zero-padded numbering (sprintf('%02d', ...))
- [x] Update ThesisCreateController.php: use trait, new file handling
- [x] Update ThesisEditController.php: use trait, new file handling
- [x] Remove duplicate methods (generateAuthorSlug, sanitizeFilename, etc.) from both controllers
- [x] Update Database.php: deprecate handleCoverUpload, remove banner_path from queries
- [x] Update SystemController.php: remove banners/ stats
- [x] Update schema.sql: remove banner_path column and view field
- [x] Create migration 027_drop_banner_path.sql
- [x] Update PureLogicTest.php: adapt detectFileType call signature
- [x] All pure logic tests pass
- [x] Fix license validation: only require license for non-admin when access_type_id=1 (Libre), not for Interne (2) or Interdit (3) — fixes share link submissions failing with "Veuillez sélectionner une licence"
- [x] Add xamxam@erg.be mailto link at top of student (partage) form
- [x] On validation error, append "envoyez un e-mail à xamxam@erg.be" to flash error message
- [x] Preserve uploaded file names across validation redirects: store in session, display as warning on re-render so the student knows which files to re-select
- [x] Obfuscate all email addresses and mailto: links as HTML decimal entities site-wide (EmailObfuscator class, applied in templates + Parsedown post-processing)
- [x] Fix TFE and annexes files not saved in ThesisCreateController::submit(): call handleAnnexeFiles, fix file input name mapping
- [x] Apply ALLOWED_MIME_TYPES/ALLOWED_EXTENSIONS validation in handleAnnexeFiles (same as handleTfeFiles)
- [x] Fix handleAnnexeFiles to use correct $_FILES key ('annexes' not 'files')
- [x] Add annexe handling in ThesisEditController::save()
- [x] Relax 3-keyword minimum: admin mode (create) requires 1+, edit requires 1+, student (partage) requires 3
- [x] Add CSS for file preview items (.fp-item, .fp-thumb, .fp-icon, .fp-meta, .fp-name, .fp-size) so annexes/cover/note-intention previews wrap and display correctly
- [x] Fix TFE file input accept attribute to include video/audio/archive extensions
- [x] Make annexes file input required when "Ce TFE comporte des annexes" is checked
- [x] Add PHP-side validation: if has_annexes checked but no annexe files provided, throw error
- [x] Add HTMX inline file validation: MIME type + file size checked on change via validate-file-fragment endpoint
- [x] Create shared validation logic (validate-file-fragment-shared.php) used by both admin and partage
- [x] Add CSS for .file-validation-msg, .fv-ok, .fv-error inline validation messages
- [x] Simplify file-upload-queue.js — drop Sortable, keep only single-file previews
- [x] Create session-based upload flow (upload-tfe-file.php, remove-tfe-file.php, tfe-queue-helper.php)
- [x] Create admin wrappers for upload/remove endpoints
- [x] Register new routes in partage/index.php
- [x] Update fichiers-fragment.php — HTMX-powered file input + server-rendered queue + progress bar
- [x] Update ThesisCreateController — read TFE files from session temp
- [x] Update ThesisEditController — read TFE files from session temp
- [x] Add handleTfeFilesFromSession + writeTfeFileFromSrc + cleanupSessionUploads to ThesisFileHandler trait
- [x] Remove sortable.min.js script tags from add.php, edit.php, index.php
- [x] Clean up form.php — remove drag handles, sortable hints
- [x] Clean up fieldset-files.php — remove sortable references
- [x] Clean up CSS — remove .fq-drag-handle, .fq-ghost, .sortable-ghost
- [x] Fix closure syntax (use before return type) in tfe-queue-helper.php
- [x] Commit