Commit Graph

24 Commits

Author SHA1 Message Date
Pontoporeia
b56d073210 refactor: extract inline JS into app/ modules, remove dead overtype-webcomponent
- Remove overtype-webcomponent.min.js (zero references)
- Extract copyLogContent + fallbackCopy + HTMX tab-updater → app/admin-logs.js
  (removes duplicate from both system.php and parametres.php)
- Extract copyUrl → app/clipboard.js (shared by acces.php)
- Extract tag/language pill-search logic → app/pill-search.js
  Generalized with data-pill-search attributes, auto-inits via
  DOMContentLoaded + htmx:afterSwap
- Extract access-request form handler → app/access-request.js
  (was inline in templates/public/tfe.php)

Files created: admin-logs.js, clipboard.js, pill-search.js, access-request.js
Files modified: 9 templates/controllers to drop inline scripts and
  reference external JS files
2026-05-19 00:08:06 +02:00
Pontoporeia
c3f6e8a033 fix: upload progress bar not visible — collectFileNames checks FilePond instances; remove admin auth from progress poll endpoint 2026-05-19 00:08:06 +02:00
Pontoporeia
927ee2fe2a feat: upload progress bar — fieldset layout, accent colors, file name display, completion animation, 800ms redirect delay; decorelate formats from fichiers; server-side poll via token; bump PeerTube embed audio player 2026-05-19 00:08:06 +02:00
Pontoporeia
cdec3e96a6 fix PeerTube upload: final working solution — simple multipart POST with CURLFile; iterated through Google-resumable PATCH protocol debugging (HTTP version negotiation, chunk body encoding, off-by-one fixes) before settling on simpler POST approach 2026-05-19 00:08:06 +02:00
Pontoporeia
83a5a508ea feat: PeerTube integration — alternate audio/video labels, FilePond pools, shared SMTP credentials, channel by name, test button, resumable upload, embed improvements, fix alt labels/curl_close/deprecation 2026-05-19 00:08:06 +02:00
Pontoporeia
8db7b6e9eb feat: FilePond production hardening — extension-based validation, server-side size limits (2GB), annexe validation, drop accept attributes, FilePond file styling 2026-05-19 00:08:05 +02:00
Pontoporeia
7b5f3efe40 feat: add FilePond pools for couverture, note_intention, video, audio; refactor queue config 2026-05-19 00:08:05 +02:00
Pontoporeia
ecb559a18a refactor: decouple format extras from main fichiers block, scope FilePond destroy to individual slots, fix FilePond integration for decoupled extras 2026-05-19 00:08:05 +02:00
Pontoporeia
1aff5ff46d Replace custom file-upload-queue.js with FilePond
- Delete file-upload-queue.js (495 lines of custom queue logic)
- Delete sortable.min.js dependency
- Add file-upload-filepond.js: thin wrapper that upgrades .tfe-file-picker
  inputs to FilePond instances with storeAsFile:true for native multipart
  form submission (no form-submit interception needed)
- Update fichiers-fragment.php: replace queue container <ul> elements
  and empty-state <p> with bare <input> elements that FilePond upgrades;
  change name attributes to queue_file[tfe][] etc. for PHP compatibility
- Update add.php, edit.php, partage/index.php: swap JS/CSS refs
- Clean up form.css: remove .fq-* and .tfe-file-queue custom styles,
  add FilePond theme overrides matching xamxam design tokens
- Update dead-code fieldset-files.php for consistency

Server-side stays unchanged: PHP receives ['queue_file']['tfe'][]
exactly as before through native multipart submission.
2026-05-19 00:08:05 +02:00
Pontoporeia
223a15b397 chore: resolve rebase conflict markers in acces.php (no functional changes) 2026-05-19 00:08:05 +02:00
Pontoporeia
d5fee1acfb fix: repair form submission with queued files + add comprehensive debug logging
- Replace fetch(redirect:manual) with XMLHttpRequest in file-upload-queue.js.
  The previous fetch-based redirect detection was broken because opaque
  redirects hide the Location header. XHR's responseURL reliably exposes
  the final URL after server-side redirects.

- Add console.log tracing at every decision point in submit interception:
  entry, hasFiles check, enctype check, double-submit guard, XHR status,
  redirect detection, error fallback.

- Add error_log entry-point logging to all 16 admin action files plus
  the partage/index.php submission handler and password gate. Each logs:
  request method, content type/length, POST keys, file counts, and
  queue-specific file counts where applicable.

- Add double-submit guard (_xamxamActiveSubmit) to prevent duplicate
  XHR sends when the native submit handler fires after interception.
2026-05-19 00:08:05 +02:00
Pontoporeia
13d26ded66 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`
2026-05-19 00:08:05 +02:00
Pontoporeia
ca7707cd47 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.
2026-05-19 00:08:05 +02:00
Pontoporeia
e06a317499 fix: req annexes, add HTMX inline file validation (MIME/size)
- Annexes file input now required when 'has_annexes' checkbox is checked
- PHP-side validation: if has_annexes but no files, throw error
- HTMX inline file validation: POSTs to validate-file-fragment on file change
  - Validates MIME type against per-field whitelists (couverture, note_intention,
    tfe, annexes)
  - Validates file size with PDF-specific 100MB limit
  - Supports both single-file and multi-file inputs
  - Returns green ✓ or red ✕ inline validation messages
- Shared validation logic in src/Controllers/validate-file-fragment-shared.php
- Admin wrapper: admin/validate-file-fragment.php (with AdminAuth guard)
- Partage route: /partage/validate-file-fragment (dispatched via index.php)
- CSS: .file-validation-msg, .fv-ok (green), .fv-error (red)
- file-field.php: accepts $fieldName for per-input validation type,
  auto-detects admin/partage validate URL
2026-05-19 00:08:05 +02:00
Pontoporeia
cc0ae32df0 fix: resolve partage form submission issues
- Replace mb_strlen/mb_substr/mb_strtolower with strlen/substr/strtolower
  (mbstring extension missing on server, causing fatal error)
- Scope annexes checkbox HTMX swap to #annexes-input-block with hx-select
  (prevents duplicating entire page inside Fichiers fieldset)
- Split format+fichiers response: #format-fichiers-block (stable) and
  #format-extras-block (swappable, inside Fichiers fieldset). Format
  checkboxes use hx-select to extract only the extras, preserving file queue.
- Keep format extras inline in Fichiers fieldset (no sub-fieldsets). Remove
  website legend input (URL only).
- When PeerTube upload disabled, show direct file upload inputs for
  video/audio (name=files[]).
- Add "Glissez-déposez" sort hint below TFE file queue.
- Fix .fq-name overflow with width:0;min-width:100% chain.
- Remove legend placeholder from .fq-item.
- Merge "Récits et expérimentation" AP into "Narration Spéculative".
  Rename PACS to "Pratique de lart - outils critiques, arts et contexte
  simultanés".
- Remove président·e field from jury fieldset, form templates, and
  controller validation. Keep DB column and display logic for existing data.
2026-05-19 00:08:05 +02:00
Pontoporeia
21c2b55bfb style: normalize headers, overtype editor rounded corners, remove duplicate cover preview, thesis-add-header grid layout, subtitle below header with top gradient 2026-05-19 00:08:05 +02:00
Pontoporeia
77fd282e29 refactor: unify edit mode Format+Fichiers with add/partage HTMX fragment
- Edit mode now uses the same fichiers-fragment.php as add and partage,
  instead of duplicating the format checkboxes + new-file upload + website
  URL fieldsets.
- Edit-only elements (existing files list, cover replace) stay in
  a separate #edit-existing-files-block below the shared fragment.
- Removed .zip/.tar/.gz from the main TFE upload accept in both
  fichiers-fragment.php and fieldset-files.php. Archives go only
  in the Annexes file input.
- Removed admin/format-website-fragment.php dependency from edit
  (no longer needed — the shared fragment handles website too).

fix: jury repop crash + hx-preserve on file inputs, remove zip/tar from tfe accept

- Jury fieldset add-mode repopulation now handles both scalar (legacy)
  and array (new dynamic multi-row) values for jury_promoteur and
  jury_promoteur_ulb_name. htmlspecialchars() was choking on array value.
- All file inputs in fichiers-fragment.php wrapped in hx-preserve
  containers so HTMX swaps don't wipe user-selected files when toggling
  formats or the annexes checkbox.
- Removed .zip/.tar/.gz from main TFE file accept — archives only via
  annexes input (which already had multiple + correct accept).
- Edit mode now reuses the same fichiers-fragment.php fragment.

fix: file inputs re-initialize after HTMX swap via inline script

- Exposed window.XamxamInitFileUploads from file-upload-queue.js IIFE
  so HTMX fragments can trigger re-binding without a global listener.
- fichiers-fragment.php emits <script>XamxamInitFileUploads()</script>
  at the end of the #format-fichiers-block fragment.
- Removed hx-preserve wrappers — they prevented re-render after
  format/annexes toggles changed visible inputs.
- This also fixes .zip removal from TFE accept and jury repopulation
  array crash from the previous commit.

refactor: simplify file-upload-queue.js, remove file-preview.js

- file-upload-queue.js rewritten from ~250 lines to ~120 lines:
  no more DataTransfer machinery, no IIFE wrapper, uses .onchange
  instead of addEventListener for simpler HTMX re-init.
- window.XamxamInitFileUploads is the function itself (not an IIFE export).
- Merged file-preview.js functionality into file-upload-queue.js
  (single-file .data-preview handling). Deleted file-preview.js.
- fichiers-fragment.php inline script calls XamxamInitFileUploads()
  after every HTMX swap (same as before).

debug: add console.log to file-upload-queue.js for file input behavior

Adds logging at key points to diagnose why only one file is displayed:
- XamxamInitFileUploads called
- TFE queue picker init (id, multiple attribute state)
- onchange event (files count, names)
- fileArray post-concat length
- Single-file preview bindings (id, multiple attribute)

Remove after debug session.
2026-05-13 18:03:33 +02:00
Pontoporeia
e3896811c4 Fix migrations and deploy issues + errors + linting
- scan both pending/ and applied/ dirs so remote catch-up works
- fix remote 500s: run.php handles per-statement errors so VIEW rebuilds run after duplicate columns; replace mb_strimwidth with substr (no mbstring extension on server)
- add missing migration: 015_license_custom.sql (column existed in schema.sql but was never migrated)
- remote: fgetcsv enclosure single-char + AdminLogger permission-denied
guard + deploy always migrates
- fix admin-filters wrapping: restore flex-wrap, flex-basis on
inputs/selects, shrink-protect buttons
- fix phpstan: remove redundant ?? [] after isset guard in
ThesisEditController
- biome: exclude vendored min.js via includes patterns;
lint whole js dir; modernise beforeunload-guard.js
2026-05-08 22:58:05 +02:00
Pontoporeia
bdd95341b0 Extract shared TFE form partial — single source of truth for add/edit/partage
Created templates/partials/form/form.php as the unified form template driven by
$mode ('add'|'edit'|'partage') and boolean flags for optional sections.

The three calling templates (templates/admin/add.php, templates/admin/edit.php,
partage/index.php renderShareLinkForm) now only set variables then include the
shared partial. ~200 lines of duplicated fieldset HTML eliminated.
2026-05-07 23:39:41 +02:00
Pontoporeia
0a05f3911c Replace Psalm with PHPStan + PHP‑CS‑Fixer + Biome, add linting configs & cleanup
- Removed the `vimeo/psalm` dependency and all related files
(`psalm.xml`, `psalm‑baseline.xml`, suppress annotations).  
- Added **PHPStan** (v2.1.54) and **PHP‑CS‑Fixer** (v3.95.1) to
`vendor/bin/`.  
- Created `phpstan.neon` (level 5, bootstraps `app/bootstrap.php`,
scans `Parsedown.php`).  
- Created `phpstan‑baseline.neon` with 10 pre‑existing errors.  
- Added `.php‑cs‑fixer.dist.php` (PSR‑12 + PHP80Migration, targets
 `app/src` & `app/tests`).  
- Added `biome.json` and updated `justfile` to replace the old Psalm
recipes with `phpstan`, `cs‑check`, and `cs‑fix`.  
- Updated `.gitignore` to exclude PHPStan and PHP‑CS‑Fixer cache files.  
- Updated several JS files (`file‑preview.js`, `file‑upload‑queue.js`)
eand PHP controllers (`MediaController.php`, `SearchController.php`,
`SystemController.php`).  
- Minor adjustments to `TODO.md`, `app/src/Database.php`,
`app/src/Parsedown.php`, `app/src/ShareLink.php`, and
`app/src/SmtpRelay.php`.
2026-05-05 11:04:52 +02:00
Pontoporeia
a83dc1c74e feat: multi-type file upload with sort order, labels, and expanded MIME support
- DB migration 007: add sort_order + display_label to thesis_files
- Database: getThesisFiles ordered by sort_order; insertThesisFile accepts label/order;
  new reorderThesisFiles() and updateThesisFileLabel() methods
- ThesisCreateController + ThesisEditController: expand allowed MIME/exts to include
  audio (mp3/ogg/wav/flac/aac/m4a), video (webm/mov/ogv), image (gif/webp),
  archives (tar/gz), any-ext via octet-stream; max size raised to 500 MB;
  accept file_labels[] and file_orders[] POST fields; detectFileType() helper
- MediaController: expanded MIME allowlist; HTTP Range support for audio/video;
  force-download for unknown types; inline for known displayable types
- fieldset-files.php: sortable queue UI with SortableJS, per-file labels, 500 MB hint
- templates/admin/edit.php: existing files as sortable list with drag handles,
  type icons, label inputs, delete checkboxes, hidden sort-order fields
- file-upload-queue.js: new JS replacing file-preview.js — sortable new-file queue,
  per-file labels, hidden order fields on submit, backward-compat legacy preview
- tfe.php: renders audio (<audio>), all video formats, images, PDF, and
  download-only 'other' files; reads display_label; sorted by sort_order
- tfe.css + form.css: styles for audio player, download files, sortable queue,
  drag handles, file type badges, label inputs
- .htaccess + .user.ini: upload_max_filesize=512M / post_max_size=520M
2026-05-05 11:04:52 +02:00
Pontoporeia
43702542eb feat(admin): sortable form-help blocks with two-panel UI
- Migration 005: add sort_order column to form_help_blocks
- Database: getAllFormHelpBlocks orders by sort_order; new reorderFormHelpBlocks()
- actions/form-help-reorder.php: HTMX POST handler, CSRF-validated, 204 response
- templates/admin/contenus.php: replace flat table with two-panel layout
  - Left: SortableJS 1.15.2 + htmx drag-and-drop ordered block cards
  - Right: static form structure reference showing fieldsets and their inputs
- admin.css: .fhb-* styles for layout, cards, ghost/chosen/drag states, anchors
- schema.sql: updated form_help_blocks DDL with sort_order column
2026-04-29 21:45:55 +02:00
Pontoporeia
32a7509598 feat: add file display to forms and recap pages
- Live file preview on all file inputs (file-field partial, edit template):
  thumbnails for images, emoji icons for PDF/video/zip/vtt, filename + size
- New file-preview.js wired via $extraJs in add.php / edit.php and direct
  <script> in partage/index.php; $extraJs support added to head.php
- admin/recapitulatif.php: replace plain table with rich file list — image
  thumbnails linked to media.php, type badges, human-readable size, date
- partage/recapitulatif.php: full rewrite — shows thesis metadata + files
  list with same rich display (no media links for student privacy)
- form.css: new sections for .file-preview-list (live preview) and
  .recap-file-list / .recap-dl / .partage-recap (recap pages)
2026-04-27 20:52:27 +02:00
Pontoporeia
75f808bee4 feat: extract MediaController, wire into Dispatcher, delete media.php 2026-04-20 12:32:00 +02:00