- Override aggressive word-break: break-word from base.css
with word-break: normal + overflow-wrap: break-word + hyphens: auto
on .tfe-title, .tfe-author, .tfe-meta-item
- Replace regular spaces before colons with in all meta labels
(French typographic rule: non-breaking space before double punctuation)
- Rebuild tfe.min.css
redirect internal metadata links from /repertoire to /search, add query param for search bar prefill, fix filter visibility on desktop
redirect metadata links from /repertoire to /search, prefill search bar, fix filter visibility
link metadata to /search, preserve keyword filter in form, show active keyword chip
Replace var(--step-5)/--step-3/--step-1 for h1/h2/h3 with explicit
clamp() values. New hierarchy: h1 ~2rem, h2 ~1.5rem, h3 ~1.2rem.
Also update .content-section-title to use direct clamp (was --step-3,
now matches h2). Mobile override swapped from --step-2 to explicit
clamp. Kept --step-0 for body text (consistent with site baseline).
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.
Remove the system that sorted valid (matched) filter entries to the top and
faded/disabled unmatched ones when any filter was active. Entries now stay in
their natural alphabetical/numeric order regardless of selection state.
- Drop usort calls that reordered entries by matched status
- Simplify repFilterEntry: remove anyActive and colHasMatch params
- Remove colHasMatches computation
- Remove rep-entry--faded CSS rule
- All filter buttons remain clickable at all times
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
getThesisById() filters by is_published=1, but theses submitted
via share links are unpublished. The recap page after submission
was showing 'TFE introuvable' because it couldn't find the
just-created unpublished thesis.
- 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
- 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
When a student-access share link specifies a locked_year, the Année field
in the student-facing form is now pre-filled with that year and rendered
as disabled+readonly, with a hidden input ensuring the value is submitted.
- renderShareLinkForm() exposes from ['locked_year']
- fieldset-academic.php checks for : if set, outputs a hidden
input plus the visible field locked to that value; otherwise falls back
to the normal editable field
- fixed padding in the tfe.php page
- fixed the layout in admin/index.php toolbar top
- the gap issued with the table theader
- rearranged button order in the toolbar top
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
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.
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.
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.
- 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
- 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
- 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)
- 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
- 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