Commit Graph
68 Commits
Author SHA1 Message Date
Pontoporeia 3cecee10c9 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.
2026-07-10 16:29:04 +02:00
Pontoporeia ec9c140ba2 repertoire: HTMX OOB swaps for filter columns + fix fading edge cases
Switch from swapping the entire #repertoire-index block to targeted
hx-swap-oob swaps: only the <ul> list elements are replaced, while
section headers and accordion chrome stay in the DOM untouched.

- Filter column <ul>s get IDs (rep-list-years, rep-list-ap, etc.)
  and render with hx-swap-oob=true on HTMX requests
- Students <ul> gets id=rep-students as main swap target
- Filter buttons now target #rep-students instead of #repertoire-index
- Server sets $isOob=true when rendering HTMX partial responses
- Accordion re-init on swap no longer needed (headers never replaced)
- Scroll-restore updated to capture/restore per <ul> ID

Fading fixes:
- Restore rep-entry--faded class with simplified logic: any active
  filter fades entries whose matched flag is false (removed the
  $colHasMatch gate that prevented fading when a column had no matches)
- Add $noResults guard: when matched_ids is empty (zero theses match
  all active filters), force-fade all non-selected entries across ALL
  columns. This covers the keyword edge case where per-column matched
  is computed excluding the keyword filter (many-to-many), causing
  keywords to appear valid even though the full intersection is empty.
2026-07-10 12:59:12 +02:00
Pontoporeia 08a9b7309f fix: locked_year cleared on edit — populate edit dialog field
The openEditDialog JS function didn't populate the locked_year input
in the edit dialog, and the PHP template didn't pass locked_year as an
argument. Any edit to a link (even just changing the name) would clear
the locked academic year to NULL.

- Pass $linkLockedYear as 5th argument to openEditDialog in the template
- Accept and populate edit-locked-year input in the JS handler
2026-07-10 11:56:27 +02:00
Pontoporeia 22a49f7cb6 fix: unify CSV import/export columns, fix import JS error, fix createThesis VALUES
- Fix createThesis SQL: extra ? placeholder in VALUES (27 values for 26 columns)
- Add createThesis integration tests to catch column/value mismatches
- Add CSV_COLUMNS as single source of truth in ExportController, deriving
  csvHeaders() and positional fallback from it
- Add missing columns to export query + CSV: duration_pages, duration_minutes,
  has_annexes, license_custom, contact_visible, objet
- Add missing columns to import INSERT: license_id, license_custom, cc2r,
  exemplaire_baiu, exemplaire_erg, objet, contact_visible, duration_pages,
  duration_minutes, has_annexes
- Resolve license name → license_id during import
- Fix XamxamInitFilePonds: add file-upload-filepond.js to admin-entry.js
  so FilePond initialization code is available on the admin list page
- Add FilePond vendor CSS to admin.min.css bundle (import dialog styling)
- Generate .admin-file-hint from csvHeaders() instead of hardcoded stale list
- Use positional fallback from CSV_COLUMNS for import cell parsing
2026-07-10 11:56:27 +02:00
Pontoporeia 20873f94af pdf-viewer: various visual and usability changes
- fix page nav buttons, smaller default pages, violet bg

  - Build toolbar after renderAllPages so it queries existing canvases;
    query canvases fresh in the scroll handler so page tracking works
    after re-render (zoom in/out).
  - Default data-pdf-scale 0.85 (JS fallback 0.8) so pages are a bit
    smaller by default.
  - Add dark transparent violet background (accent-secondary 22%) to
    .pdf-expanded, behind the pages.

  - expand to fill column top-to-bottom via CSS flex

    Use a flex chain (.tfe-files flex:1, .tfe-file-item:has(.pdf-expanded)
    flex:1) so the expanded PDF wrapper fills the right column from under
    the header to the bottom of the viewport, instead of viewport-based
    clamp math that didn't account for the header height.

  - fill right column, center pages, freeze column on expand

  The expanded viewer now stays inside the right column instead of
  growing the page: the column switches to overflow:hidden while the
  PDF panel scrolls internally. Pages are centered horizontally via
  flexbox align-items: center.

  - fix toolbar not full-width, hide sibling file items

  The toolbar was constrained by the parent's align-items:center; fixed
  with align-self:stretch. Hiding sibling .tfe-file-item elements when
  a PDF is expanded prevents them from rendering above the overlay.

  - disable overscroll on expanded view

  - use overscroll-behavior-y on container, none on toolbar

  - disable body overscroll via .pdf-viewer-open class

  - mobile full-viewport, iframe matches pdf height

  - mobile overlay above everything via position:fixed

  - opaque dark-violet bg on mobile overlay

  - tfe: add 'Open in new tab' link above website iframes

  - trim column padding when expanded for more vertical space

  - 5% zoom increments, subtle padding on expanded column

  - prevent horizontal overflow/overscroll
2026-07-08 22:41:52 +02:00
Pontoporeia 82d8eff512 Fix lint: use IterableCallbackReturn — wrap forEach body in braces 2026-07-08 15:14:20 +02:00
Pontoporeia 033ea90684 Fix lint warnings: arrow functions in admin-acces.js, duplicate gap in admin.css, biome formatting 2026-07-08 13:50:03 +02:00
Pontoporeia 402799a412 Fix remaining JS functions missing from window global scope 2026-07-08 13:50:03 +02:00
Pontoporeia 83287cdcd8 Expose tag/langue/motscles JS functions on window to survive ESM tree-shaking 2026-07-08 13:50:03 +02:00
Pontoporeia 10df92b643 fix: load autosave-handler.js on about_page edit view, persist contact group deletion
Two fixes:

1. about_page edit was missing autosave-handler.js: the first if block
   (editType === 'page' || 'about_page') overrode $extraJs with only
   overtype.min.js, making the elseif that added autosave-handler.js
   unreachable for about_page. Added autosave-handler.js to the first
   block, removed dead 'about_page' from the elseif.

2. Deleting a contact group (Contacts 3/4/5) only removed the DOM
   element but never triggered htmx autosave. Dispatched a 'change'
   event on the form after removal+reindex so the hx-trigger fires.

Also expanded autosave-handler.js URL filter to accept apropos.php
so the status indicator (Enregistrement/Enregistré) works for contacts saves.
2026-07-05 14:14:13 +02:00
Pontoporeia 3c845f9d40 acces.php: remove Mot de passe column, add key icon copy button, reorder actions, switch URL icon to link-simple; fix dialog functions not on window; fix archive: move form into dialog (native submit); add caret icon to archived links details 2026-07-05 12:05:53 +02:00
Pontoporeia 3e93150c76 justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe
- Removed ambiguous aliases: phpstan, cs-check, syntax
- Split lint-biome into lint-css and lint-js with correct paths
- Added lint meta-recipe and fix recipe (biome --unsafe + php-cs-fixer)
- Fixed FormBootstrap dead null check, CSS shorthand override bug
- Updated phpstan baseline, suppressed noDescendingSpecificity/noInnerDeclarations
- Applied ~74 biome auto-fixes across CSS/JS
2026-07-05 11:07:41 +02:00
Pontoporeia a1f32acaa1 cleanup: sélection multiple + page dédiée (/admin/cleanup.php)
- cleanup-tmp.php: accepte les arrays filepond_dirs[] et trash_files[] pour suppression en lot
- cleanup-stats-fragment.php: ajout checkboxes + barre d'actions groupées + formulaire bulk HTMX
- admin-cleanup-bulk.js: module JS pour toggleAll, updateBulk, bulkDelete
- Nouvelle page /admin/cleanup.php remplace la modale (tmp-cleanup.php supprimé)
- Bouton Nettoyer dans index.php devient un lien vers la page dédiée
2026-07-03 17:06:23 +02:00
Pontoporeia 880d169e72 search: pagination and scroll, add range counter, mobile version 2026-07-03 16:53:16 +02:00
Pontoporeia 4fa57d592a refactor: combined duration (pages + minutes), has_annexes checkbox, remove Mo
- Remove Mo option from duration, keep only pages and minutes
- Redesign duration fieldset: separate Pages input + Durée h:m inputs, both can be set together
- Fix minutes input visibility: wider inputs (6ch), proper CSS layout
- Add has_annexes checkbox to fichiers fragment + DB column + controllers
- Display duration on admin backoffice recap page
- Display duration on public partage recap page
- Update public TFE page for new combined duration format
- Migration 041: add duration_pages, duration_minutes, has_annexes columns; migrate data; recreate views
2026-07-03 15:58:10 +02:00
Pontoporeia eb706214ce feat: scroll-position memory on repertoire HTMX swaps + swap transition polish
- Add repertoire-scroll-restore.js: snapshots scrollTop of each column <ul>
  before htmx:beforeSwap, restores after htmx:afterSwap (keyed by data-col)
- Add subtle opacity transition on #repertoire-index during htmx-swapping
- Tighten rep-indicator opacity transition to 0.1s for snappier feedback
- Import new module in public-entry.js
2026-06-24 14:45:55 +02:00
Pontoporeia 6ecd3d4540 Fix biome lint errors: remove duplicate CSS properties, apply safe auto-fixes
CSS:
- Remove duplicate 'background' fallbacks in base.css, header.css, search.css
  (solid color declared before gradient — gradient always wins)
- Remove duplicate 'padding' in admin.css .admin-import-log

JS (biome --write safe fixes applied):
- function() → arrow functions in all IIFEs and callbacks
- forEach/callback → arrow functions
- evaluePtrn → parseInt(x, 10) in admin-contacts-form.js
- Cleaned label text in build.mjs lint step

Remaining warnings are intentional: !important overrides, descending
specificity (admin.css cascade), noUnusedVariables (functions exported
to window/onclick), useTemplate style preference.
2026-06-24 13:57:00 +02:00
Pontoporeia 82d3dcb084 Fix repertoire column scrolling + admin TOC duplication
- repertoire.css: add min-height: 0 to column <ul> scroll containers so
  grid 1fr row shrinks below content and overflow-y: auto activates
- admin-toc.js: add __adminTocBuilt guard + nav.children check to prevent
  double population when loaded both via admin.min.js and direct <script>
- admin-toc.php: remove duplicate <script src="admin-toc.js"> tag —
  JS is already bundled in admin.min.js
2026-06-24 13:18:19 +02:00
Pontoporeia 20fe4b6c8c Add biome + rolldown + lightningcss build pipeline for JS/CSS bundling & minification
- package.json with biome, rolldown, lightningcss devDependencies  
- biome.json: add CSS formatter support
- scripts/build-css.mjs: lightningcss resolves @import chain, bundles/minifies CSS  
- scripts/build-js.mjs: rolldown per-entry JS bundling (no code splitting)
- scripts/build.mjs: orchestrator for both CSS + JS
- scripts/check-build.mjs: staleness checker for CI/deploy guard
- justfile: add build, build-css, build-js, build-install, build-check recipes
- justfile: deploy recipe now runs build before deploy-code
- head.php + form-page.php: use dist/base.min.css instead of style.css
- All controllers + FormBootstrap: reference dist/*.min.{css,js}
- admin footer: load admin.min.js for all admin pages
- repertoire: use public.min.js instead of individual app JS files
- Fix stray '}' syntax error in admin.css line 305
- .gitignore: add app/public/assets/dist/
2026-06-24 13:09:50 +02:00
Pontoporeia e74f9210c5 #gzip #extract-inline-js enable gzip in nginx + move ~730 lines of inline JS to 15 external files 2026-06-24 12:56:15 +02:00
Pontoporeia 03c9c3566f Add SQLite indexes for contenus page language/tag queries + WIP: Peertube orphans, dialogs, contact decoupling, context note, finality types 2026-06-21 16:36:34 +02:00
Pontoporeia 19bf9f101a Refactor apropos/charte/licence pages: shared layout, TOC anchors, and UI polish
Unify the three public pages (à propos, charte, licence) onto a single
grid layout (.page-content) with sticky TOC sidebar, replacing the old
separate  /  /  markup.

- Merge about.php, charte.php, licence.php templates into shared
  .page-content / .content-section structure
- Add CommonMark HeadingPermalinkExtension for stable heading anchors
- Use SlugNormalizer for TOC links so they match rendered heading IDs
- Standardize link styling across content blocks: bold black, accent on
  hover (consistent with global link style)
- Fix code block wrapping: use pre-wrap instead of pre, constrain grid
  columns with min-width:0, auto scrollbar
- Fix apropos page grid placement: force content-section into column 2
  so contacts and credits stay in the content area, not the sidebar

Also includes accumulated WIP changes:
- Header gradient: hardcoded purple-to-green (replaces CSS variables)
- Search placeholder font
- Duration field: replace minutes/sec/heures with h:m:s time inputs
- TFE file optional for formats 1,4,6 with client-side JS toggle
- Licence form: em-dash to hyphen, details/summary classes
- Pill search: block Enter key form submission when no results
- Draft autosave: remove CSRF rotation (broke concurrent FilePond uploads)
- Language pill: clear hints for excluded main languages
- Search results: gradient placeholder cards for items without covers
- TFE display: format durée values as XhYm instead of decimal
2026-06-19 19:40:05 +02:00
Pontoporeia a5db81a73d fix: change adminOld return type from string to string|array
The closure returned arrays when formData values were arrays (e.g.
jury_promoteur), but the PHP return type annotation was :string.
PHP 8.x enforces this strictly, causing a fatal TypeError in
jury-fieldset.php on add mode.
2026-06-15 16:17:29 +02:00
Pontoporeia d588ae004d Reintroduce TFE duration metadata: DB columns, form fields, controllers, views, and migration
Add 'unsafe-eval' to CSP script-src directives (htmx requires Function())
2026-06-15 15:56:52 +02:00
Pontoporeia cbd369bc72 Split form.css into form-base.css and form-admin.css, drop dead upload-progress code
Also introduces $extraCssAdmin support in head.php for admin-only
stylesheets (form-admin.css, filepond CSS, system.css). Admin pages
now use $extraCssAdmin for admin-only assets and $extraCss for
shared stylesheets like form-base.css.
2026-06-11 11:28:58 +02:00
Pontoporeia 99125cc8e3 Add autosave draft system for partage form with HTMX-based session persistence
- New fragment endpoint POST/GET /partage/fragments/draft.php:
  saves all form fields to PHP session, excludes file/csrf/slug fields
  GET returns JSON for JS hydration on page load
  rotates both global CSRF and share CSRF tokens in sync

- form.php accepts optional $formExtraAttrs and $showAutosaveStatus:
  allows injecting HTMX attributes and 'Brouillon enregistré' indicator

- renderShareLinkForm adds hx-post with change/input debounce trigger,
  loads autosave-handler.js, hydrate fields from draft on page load

- Draft cleared on successful form submission in handleShareLinkSubmission

- autosave-handler.js now also updates share_link_token hidden input
  when rotating CSRF token (partage form uses both csrf_token and share_link_token)

- Added .autosave-status CSS to form.css (was admin.css-only)

- Updated fragment routing to accept GET requests (needed for draft hydration)
2026-06-11 11:04:49 +02:00
Pontoporeia 4b37a05be3 Guard no-JS file uploads: disabled filepond_mode by default, server-side fallback
The partage/admin form had a hardcoded filepond_mode=1 hidden input,
so without JavaScript the server always entered the FilePond async
path — which found no hex IDs and silently dropped all files.

Three-layer fix:
1. HTML: filepond_mode input starts disabled with value=0; JS enables
   it and sets value=1 on DOMContentLoaded (and after HTMX swaps).
   Disabled inputs aren't submitted → server gets no filepond_mode
   → naturally falls to legacy  path.
2. JS: enableFilepondMode() called on page load and hx:afterSwap so
   FilePond-enhanced forms always send filepond_mode=1.
3. Server (defense-in-depth): ThesisFileHandler::hasFilePondQueueData()
   scans POST['queue_file'] for 32-char hex IDs; ThesisCreateController
   and ThesisEditController use it alongside filepond_mode, so even if
   the flag somehow arrives without async upload IDs, the  path
   takes over.
2026-06-11 10:32:50 +02:00
Pontoporeia fb752f5ba2 cleanup: remove _write guard — FilePond external API doesn't expose _write
ro=['fire','_read','_write'] is an exclusion list in Ee(), not an inclusion
list. The external pond object has none of these. The only safe interception
point is inside the closure (vendor patch), but the root-cause fix
(fileValidateSizeFilter .filename → .name) already prevents the crash.
2026-06-10 00:18:49 +02:00
Pontoporeia 2829d13a16 filepond: fix crash 'can't access property main, n.status is undefined'
Fixes three root causes of FilePond errors on TFE upload forms:

1. server.process.onerror accessed .status on a string (XHR response
   text body) — now extracts the body safely.

2. server.load was a bare URL string with no error handling — converted
   to object with onload/onerror to prevent FilePond internal _write
   crash when load.php returns HTTP errors.

3. destroyFilePondsIn now aborts in-flight processing before pond.destroy()
   to prevent stale XHR callbacks firing on a torn-down FilePond instance.

Server-side: FilepondHandler now emits Content-Type: text/plain on all
responses (PHP defaults to text/html on die(), confusing FilePond's
response parser).
2026-06-10 00:18:49 +02:00
Pontoporeia 38ef550397 feat: render actual elements in markdown cheatsheet instead of labels
Replace text labels (h1, bold, italic) with rendered HTML in the Rendu column:
headings, strong, em, del, code, links, blockquote, lists, hr, sup, small
2026-06-10 00:18:49 +02:00
Pontoporeia 1490c99268 Fix FilePond: maxFileSize as bytes + temp files survive page reload
1. maxFileSize bug: FileValidateSize plugin overrides core's maxFileSize
   setter. Core uses toBytes('1GB') = 1073741824, but plugin registers
   maxFileSize as [null, Type.INT] which calls toInt('1GB') = 1.
   Fix: all maxFileSize and perExtensionMaxSize values as raw bytes.
   Also fix option name: fileValidateSizeFilterItem → fileValidateSizeFilter.

2. Temp file persistence: files uploaded via FilePond went to
   tmp/filepond/ and vanished from the UI on page reload because
   data-existing-files only included DB-persisted files.
   Fix: session-track temp file_ids in handleProcess, inject via
   getSessionTempFiles() into data-existing-files, teach handleLoad
   to stream temp files from disk, and route JS remove → revert for hex IDs.
2026-06-10 00:18:49 +02:00
Pontoporeia c4a550f9d1 Rework contenus-edit: auto-save, OverType toolbar, dynamic sidebar links
- Auto-save: new autosave.js with 1.5s debounce, watches all forms with
  data-autosave, POSTs to form action with Accept: application/json, shows
  saving/saved/error status indicator
- All action handlers (page.php, apropos.php, form-help.php) now detect
  JSON Accept header and return {success, csrf_token} or {error} responses
- OverType toolbar enabled (toolbar:true) on all three markdown editors
  (page, about_page, form_help)
- Sidebar links: replaced fixed erg_site_url / source_code_url rows with
  dynamic sidebar_links array of {label, url} objects. Add/remove via JS.
  Fallback migration reads legacy keys if sidebar_links is empty.
- Updated AboutController and about.php template to render dynamic links
- Updated apropos.css: unified .apropos-toc-link replacing .apropos-toc-erg
  and .apropos-toc-source
- New CSS: autosave-status states, sidebar-link-row layout
- Removed all Enregistrer + Annuler buttons — auto-save and h1 back-arrow
  make them redundant
2026-06-10 00:18:40 +02:00
Pontoporeia 3d524226a1 formulaire: correctifs identifiant/année, contact, fichiers optionnels
- Identifiant: mise à jour automatique quand l'année change en back-office (updateThesis + ThesisEditController)
- Contact: hint enrichi (1 seul contact, formatage Instagram/Mastodon)
- Fichiers: TFE rendu optionnel pour Site web/Performance/Installation (note d'intention reste obligatoire)
2026-06-10 00:17:00 +02:00
Pontoporeia df70fba5d4 feat: convert all file inputs to FilePond for standardized uploading
- Add csv_import queue type (storeAsFile, no async upload) for CSV import dialog
- Convert file-field.php partial to FilePond with field-name→queue-type mapping
- Conditionally skip server config for storeAsFile queues in buildFilePondOptions
- Skip FilePond init for inputs inside closed <dialog> elements
- Trigger FilePond init when import dialog opens
- Load FilePond CSS/JS assets on admin index page
2026-06-09 13:12:22 +02:00
Pontoporeia 2bb520bb8c Fix: anchor vendor/ gitignore to root so app/public/assets/js/vendor/ is tracked (htmx, OverType, FilePond) 2026-06-08 10:12:39 +02:00
Pontoporeia 2e75a3b35c Fix beforeunload dialog appearing on edit.php when no changes made 2026-05-19 23:59:07 +02:00
Pontoporeia 7c30d1c55d Fix relink: close modal + HTMX refresh for immediate pool update
- After relink, always close the modal (even if FilePond input not found,
  e.g. page refreshed by live-reload during the fetch).
- After closing, re-fetch #format-fichiers-block via HTMX from
  /admin/fragments/fichiers.php?_thesis_id=N which loads thesis files
  from DB and re-renders the fragment with pre-populated FilePond pools.
  The afterSwap handler auto-reinitializes FilePond instances.
- Updated admin/fragments/fichiers.php to accept _thesis_id, load
  existing files from DB, build per-queue-type JSON, and render in
  edit mode.
2026-05-19 01:32:34 +02:00
Pontoporeia b77bc486e5 Fix relink: FilePond addFile API, yellow border, limbo type + await
- Fix addFile argument format: FilePond.addFile() takes (source, options)
  as two separate arguments, not a single {source, options} object.
- Change .filepond--file default border from accent-yellow to accent-green.
  Existing files loaded in edit mode have type 'local' and never reach
  processing-complete state, so they got the yellow border.
- Change relinked file add from type 'local' to 'limbo'. Limbo items
  go through DID_COMPLETE_ITEM_PROCESSING which triggers onprocessfile
  (ensures syncOrderInput runs with serverId available) and renders
  the green checkmark visual.
- Await addFile Promise and close modal in .then() instead of
  immediately, ensuring the item is created before cleanup.
- Remove duplicate modal.close() after the addFile block.
2026-05-19 01:13:17 +02:00
Pontoporeia 27e6abc7e4 feat: file browser + relink for orphaned files + htmx fix + header cleanup + fix relinked FilePond integration + resolve acces.php conflict markers 2026-05-19 00:08:06 +02:00
Pontoporeia 79eddf5d5a feat: fix file deletion on save + trash policy + documents/ prefix + relink browser
1. note_intention: Delete old file only when a genuinely new upload arrives
   (32-char hex file_id), not when the FilePond pool preserves an existing
   file by sending its DB integer ID.  Previously the DB integer ID
   triggered $hasNewNote=true, which deleted the existing note_intention
   from disk+DB, then handleFilePondSingleFile couldn't re-process it
   because the regex requires a hex pattern.  Same fix applied to cover.

2. All file deletions now use deleteThesisFileToTrash() which renames
   files to tmp/_trash/ instead of unlinking.  The trash preserves
   original filenames prefixed with DB id for traceability.  Skips
   website URLs and PeerTube refs (no disk file).

3. Storage prefix changed from theses/ to documents/ to reflect that
   the folder holds all document types (determined by file_type in DB).
   MediaController visibility gate supports both prefixes for backward
   compat with existing files.

4. File browser + relink feature for orphaned files:
   - /admin/fragments/file-browser.php — HTMX tree browser for
     storage/documents/ and storage/theses/
   - /admin/actions/filepond/relink.php — POST endpoint that inserts
     a thesis_files row pointing to existing on-disk file
   - Per-pool "📂 Relier" buttons (edit mode only)
   - JS: XamxamOpenFileBrowser / XamxamRelinkFile with FilePond integration
   - CSS: .relink-modal dialog + .file-browser tree styles
2026-05-19 00:08:06 +02:00
Pontoporeia 6f7a02244f maintenance: allow /partage through gate, fix fragment routing, add visibility table in admin
Extract shared filepond logic into src/FilepondHandler.php class.
Admin filepond endpoints delegate to the handler after AdminAuth check.
New partage filepond endpoints at /partage/actions/filepond/ verify
share_active session flag + CSRF token, no admin auth required.

JS reads filepond-base meta tag to determine endpoint path:
- Admin pages: /admin/actions/filepond (via head.php isAdmin check)
- Partage form: /partage/actions/filepond (explicit meta)

partage/index.php sets share_active = true on form render, cleans up on
successful submit. Partage process endpoint rate-limited to 30/5min per
session. No nginx changes needed — /partage/ location already handles
PHP without auth_basic.
2026-05-19 00:08:06 +02:00
Pontoporeia 9152b120e8 feat: mandatory auto-generated passwords for share links + admin password copy/regeneration + password gate rate limiting 2026-05-19 00:08:06 +02:00
Pontoporeia 6e7c0c00e3 refactor: merge video/audio FilePond pools into TFE input
- Remove separate video/audio/peertube_video/peertube_audio pools from UI
- TFE pool now accepts all file types including video/audio
- When PeerTube is enabled, video/audio dropped into TFE pool auto-upload
  to PeerTube (process.php detects MIME and uploads immediately)
- PeerTube return IDs now encode type: peertube:video:UUID or peertube:audio:UUID
- load.php returns placeholder SVG for PeerTube files so they appear in FilePond
- Edit mode: all existing files (including PeerTube) shown in TFE FilePond pool
- Remove legacy  video/audio/peertube_* handling from both controllers
- Remove unused vide/audio/peertube_* entries from JS QUEUE_CONFIG
2026-05-19 00:08:06 +02:00
Pontoporeia 2e9ebfc684 filepond: implement async server-ID upload architecture with nested queue support + PeerTube integration
Replace `storeAsFile:true` with a full async FilePond round-trip pipeline using opaque server-side file IDs.

* Added 4 new PHP endpoints under `/admin/actions/filepond/`:

  * `process.php` — upload/process single file and return opaque `file_id`
  * `revert.php` — delete pending tmp uploads before form submit
  * `load.php` — stream existing files by DB ID for FilePond preload
  * `remove.php` — soft-delete `thesis_files` rows
* `process.php` improvements:

  * accept arbitrary FilePond field names instead of hardcoded `file`
  * support PHP-nested multi-file queue inputs (`queue_file[tfe][]`)
  * explicit unwrapping of nested `$_FILES` structures
  * add `audio/mp3` to audio + `peertube_audio` MIME whitelists
  * immediate upload of `peertube_*` files to PeerTube, returning `peertube:{uuid}` IDs
  * extensive `error_log()` instrumentation for request, CSRF, MIME, upload, and save stages
* `revert.php` now accepts `peertube:` IDs without local cleanup
* `ThesisFileHandler`:

  * add `handleFilePondQueueFiles()` + `handleFilePondSingleFile()`
  * process async uploads from `storage/tmp/filepond/` via opaque `file_id`
  * inline handling of `peertube:{uuid}` IDs with direct `thesis_files` insertion
  * remove obsolete deferred PeerTube queue-processing flow
* `ThesisCreateController` + `ThesisEditController`:

  * gate async path behind `filepond_mode=1`
  * preserve legacy multipart flow as fallback
* `file-upload-filepond.js`:

  * remove `storeAsFile:true`
  * add `buildServerConfig()` for async endpoint wiring
  * fix `syncOrderInput()` to use `serverId`
  * add `onprocessfile` hook
  * add `fileValidateSizeFilterItem` for per-extension size caps
  * preload existing uploads via `data-existing-files` + `server.load`
  * replace static `INPUT_ID_TO_TYPE` map with `data-queue-type`
  * add extensive `console.log()` debugging across upload pipeline stages
* `upload-progress.js`:

  * block form submission while uploads are pending
  * update `collectFileNames()` to read processed FilePond items
* Templates/layout:

  * add `data-queue-type`
  * add `data-existing-files`
  * add global CSRF meta tag outside admin-only context
  * add `filepond_mode` hidden input
  * add CSRF token/meta support for partage pages
  * move website URL field below file upload block
* `.gitignore`: exclude `storage/tmp/` from version control
2026-05-19 00:08:06 +02:00
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