Commit Graph
315 Commits
Author SHA1 Message Date
Pontoporeia 58fb4142b7 relabel: Promoteur·ice ULB → Promoteur·ice université in all UI labels
Pure label change across 6 template/controller files — no DB schema change.
Migration 043 added to track the change.
2026-07-06 19:51:42 +02:00
Pontoporeia 6573dd5452 tfe: add scrollbar=0 to PDF iframe embed params 2026-07-06 19:51:42 +02:00
Pontoporeia fa6d19f767 tfe: rework desktop layout to 35/65 flex columns, independent scrolling, no horizontal overflow
Switched from grid to flex for two-column layout
Left column (flex: 0 0 35%): author, title, meta, synopsis — scrolls independently  
Right column (flex: 1): files/media — scrolls independently
Added .tfe-file-iframe class to PDF/website iframes, scoped width/height constraints
All media gets width:100% + max-width:100% to prevent overflow
Mobile (<900px): reverts to single-column page-level scrolling
2026-07-06 19:51:42 +02:00
Pontoporeia 0979267c68 stretch heading scale (h1→step-5, h3→step-1) + reduce heading bottom margin (space-l → space-m) 2026-07-06 19:51:20 +02:00
Pontoporeia 148ffe79f0 fix: search bar icon/placeholder overlap caused by specificity conflict
The base input rule uses a high-specificity :not() chain (0,8,1) that
overpowered .header-search-input-wrap input (0,1,1). The base padding
won, so the search input's padding-left (which makes room for the icon)
was overridden. Switched to #site-search-input (1,0,0) to win the
specificity battle.
2026-07-05 15:00:47 +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 1e714982d3 fix: restore contact_interne/contact_public column names in v_theses_full
Migration 041 accidentally renamed contact_interne → author_email and
contact_public → author_show_contact, but all application code still
references the old names. Migration 042 rebuilds the views with the
correct column aliases. Also updated schema.sql to match.
2026-07-05 14:04:29 +02:00
Pontoporeia 8e309bbcb7 Remove public contact visibility checkbox from admin add/edit forms 2026-07-05 14:04:29 +02:00
Pontoporeia ec6c939f4e Fix CC2r: uncheck not persisting + want_license hiding cc2r when active
Issue 1 — hidden seeds overriding user input:
Removed all hidden seed inputs (cc2r, want_license, license_id,
license_custom). The .licence-license-choice div is now rendered
directly from $formData on page load instead of via HTMX load
trigger. This eliminates stale-seed interference on both HTMX
radio changes and full form submits.

Issue 2 — Interne want_license uncheck clearing CC2r:
When want_license is unchecked, CC2r and licence selections are
cleared (section hidden). Added hidden want_license=0 so the
fragment handler can distinguish "arriving from another access
type" (no want_license in POST → preserve values) from "explicit
Interne toggle" (want_license present → clear CC2r if off).

CC2r is independently toggleable within the visible section.
Licence dropdown placeholder changed to 'Aucune licence' for
an explicit no-licence choice.
2026-07-05 14:04:05 +02:00
Pontoporeia 83e9dd0bc2 structure-formulaire.php: replace ← text back link with arrow-left-circle icon + admin-back-btn class 2026-07-05 12:51:44 +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 34b5d3e585 justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe
- Removed ambiguous aliases: phpstan, cs-check (both pointed to lint-php which
  also ran php-cs-fixer, making the names misleading)
- Removed syntax (php -l) — redundant, phpstan already catches parse errors
- Split lint-biome into lint-css and lint-js with correct paths
- Added lint meta-recipe that runs all three linters
- Added fix recipe: biome check --write (CSS/JS format+lint) + php-cs-fixer fix (PHP)
- Updated build-lint to delegate to lint-css + lint-js
2026-07-05 10:50:42 +02:00
Pontoporeia 786eef6df5 cleanup: remplacer <details> par <fieldset>/<legend> (comme contenus.php) 2026-07-03 17:12:15 +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 a5f658ce0c retirer l'orientation des cartes de résultats de recherche 2026-07-03 16:58:29 +02:00
Pontoporeia 880d169e72 search: pagination and scroll, add range counter, mobile version 2026-07-03 16:53:16 +02:00
Pontoporeia e607833b2e style: remove border-top from admin-form grid rows 2026-07-03 16:01:54 +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 42c4e78df6 toc: add independent scrollbar for desktop TOC sidebar
- Added max-height, overflow-y: auto, overscroll-behavior: contain,
  and scrollbar-width: thin to .toc in the desktop media query (toc.css)
- This gives the TOC its own scrollbar when its content exceeds the
  viewport height, scrolling independently from the main content
- Affects both public pages (about, charte, licence via .page-content)
  and admin pages (acces, parametres, contenus via .admin-main--toc)
2026-07-03 15:29:05 +02:00
Pontoporeia e6a989bb36 fix: add missing bootstrap require in markdown-cheatsheet-fragment.php, add bottom padding to dialog 2026-07-03 15:24:07 +02:00
Pontoporeia a790ddc02a Fix admin login heading: prevent 'Administration' from hyphenating or overflowing box 2026-06-24 14:57:28 +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 0062b29678 Fix security issues from audit: gate partage fragments on share_active session, add CSRF to retry-email POST, remove dead App::verifyCsrf() 2026-06-24 14:17:24 +02:00
Pontoporeia 84869ad968 Fix open redirect in tag.php + language.php: reject protocol-relative URLs (//evil.com) by also checking for // prefix 2026-06-24 14:15:25 +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 3c786b037a Sort all filter columns: matched entries first, then unmatched, both alphabetical 2026-06-24 11:32:13 +02:00
Pontoporeia 982d91345d Sort keywords column: matched entries first, then unmatched, both alphabetical
When filters are active, viable (matched) keywords now appear at the top
of the Mots-clés column so users don't have to scroll past faded entries
to find clickable tags. Both groups maintain alphabetical order internally.
2026-06-24 11:28:26 +02:00
Pontoporeia 654c884fed Remove mobile filter chip bar from repertoire page
The sticky chip bar added noise: users already see their active
filters highlighted in the accordion columns (with rep-entry--selected
styling and the active-count badge on each toggle). Removing chips
shifts focus back to the accordions, consistent with the expectation
that users return to the dropdowns to adjust filters.
2026-06-24 11:20:47 +02:00
Pontoporeia bb3bb80567 Fix accordion re-init after HTMX outerHTML swap on repertoire page
The htmx:afterSwap handler was calling initAccordions(e.detail.target)
but after an outerHTML swap, e.detail.target references the old detached
DOM element, not the new live element. This meant accordion click
handlers were never attached to the new filter column toggles after
applying or removing a filter — breaking all subsequent interaction.

Fix: query the live DOM with document.querySelector() instead.
2026-06-24 11:13:08 +02:00
Pontoporeia ecb90ba5dd Add accordion + active-filter chip bar for mobile repertoire
- repertoire-index.php: wrap each filter column in rep-accordion with toggle
  button, chevron, badge (active filter count); add rep-chip-bar with
  removable active-filter chips above the columns
- repertoire.css: mobile (≤640px) accordion mode — columns collapse to
  single-open accordion sections with 48px touch targets; chip bar becomes
  sticky; desktop/tablet layout unchanged via display:none on toggle elements
- repertoire.php: JS for single-accordion-open behavior on mobile, HTMX
  re-init after swap, resize-breakpoint cleanup
- docs/repertoire-mobile-propositions.md: analysis + 4 architecture proposals
2026-06-22 16:32:26 +02:00
Pontoporeia cca3d08f05 Replace apropos/licence/charte sticky nav with responsive details/summary TOC
- Convert .apropos-toc <nav> to <details class="toc" open> in all three templates
- Add caret-down icon to summary (visible only on mobile via media queries)
- Desktop (≥768px): sticky sidebar via CSS grid, force-open via pointer-events:none, hide caret
- Mobile (≤767px): single column, collapsible TOC with rotating caret, margin-top below search bar
- Rename .apropos-toc-link to .toc-sidebar-link
- Merge 900px and 600px breakpoints into single 600px mobile media query
- Rename apropos.css → content-page.css; update 3 controller references
2026-06-22 15:33:47 +02:00
Pontoporeia 0a2b4781d1 Fix search icon wrong color 2026-06-21 18:12:47 +02:00
Pontoporeia 6aee5ec131 Clean up cleanup dialog
- Remove duplicate 'Téléversements abandonnés' heading already communicated by the summary
- Replace #peertube-orphans-wrapper with display:contents wrapper so PeerTube details sit as direct grid siblings
- Add hx-confirm to all delete buttons (filepond, trash, PeerTube orphans)
2026-06-21 18:09:22 +02:00
Pontoporeia dfde88eaa5 Migrate all &lt;img&gt;-based icons to inline SVG via PHP helper
Replace every &lt;img src="/assets/icons/..."&gt; with &lt;?= icon('name') ?&gt;
across 26 template files. The PHP helper inlines the SVG markup into the
DOM so CSS color cascades naturally through fill="currentColor".

- Add src/icon.php helper: reads SVG file, sets width/height to 1em,
  injects aria-hidden, supports optional CSS class
- Fix 12 icon SVGs that had hardcoded fill="#000000" or missing fill attr
- Replace search.svg with Phosphor fill-based magnifying glass
- Add explicit SVG sizes for admin header nav icons (16px/20px)
- Scope public search icon CSS to form[role=search]:not(.header-search-form)
  to avoid breaking admin header layout; change stroke to fill
- Remove &lt;img&gt; filter: brightness(0) invert(1) hacks from admin.css
2026-06-21 17:52:27 +02:00
Pontoporeia b1774e6e97 Replace all inline SVGs with icon files, ensure currentColor fill for proper color inheritance on buttons 2026-06-21 17:11:45 +02:00
Pontoporeia 71a92d682b Fix nettoyage modal: SVG icon files, padding/margin consistency, BBBDMSans font, fix HTMX trigger, nested details cleanup 2026-06-21 17:04:37 +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 0d5e9dac19 fix: make sticky TOC work for full scroll height and fix heading anchor links 2026-06-20 14:08:16 +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 c8af3bf869 fix: remove leftover debug console.log that crashed HTMX with new FormData(fieldset)
The htmx:beforeSend listener in admin/footer.php was a debugging
leftover that called new FormData(e.target.closest('fieldset')).
FormData only accepts HTMLFormElement or nothing — passing a
<fieldset> throws 'Argument 1 does not implement interface
HTMLFormElement'.  Removed the serialization call; kept the
minimal debug log.
2026-06-15 16:27:35 +02:00
Pontoporeia 2633cb13b5 fix: increase PHP upload limits to support large video files
Raised upload_max_filesize from 512M to 8192M (8G) and post_max_size
from 520M to 8704M to match the JS-side per-extension size caps that
allow up to 8GB for video files (mp4, webm, mov, etc.).  Also raised
memory_limit to 512M and max_input_time to 600s.
2026-06-15 16:26:48 +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 00fed5f0e3 Add periodic cleanup of orphaned drafts: cleanup job, just command, deploy cron 2026-06-11 13:05:34 +02:00
Pontoporeia a19e9e1454 Extract FormBootstrap helper to eliminate bootstrap duplication across add/edit form pages 2026-06-11 12:23:55 +02:00
Pontoporeia f4a3e26901 Add thesis status column for two-phase commit lifecycle tracking 2026-06-11 12:09:43 +02:00