diff --git a/TODO.md b/TODO.md index 6c599a9..1afd4ab 100644 --- a/TODO.md +++ b/TODO.md @@ -1,12 +1,18 @@ # TODO > Last updated: 2026-06-21 -> Context: nettoyage modal styling fixes + inline SVG → icon files migration +> Context: Migrate all -based icons to inline SVG via PHP helper so CSS color cascade works -## In Progress -- [ ] #inline-svg-to-icons Move all inline SVGs to asset icon files, ensure correct fill colors `(24 icon files, 22 PHP/HTML files updated)` +## Pending +- [ ] #icon-color-verify Verify icon colors render correctly across all pages (header, admin tables, forms, dialogs, cleanup modal) ## Completed +- [x] #inline-icon-helper Create `icon()` PHP helper + auto-load in bootstrap `(src/icon.php, bootstrap.php)` ✓ +- [x] #icon-fill-currentcolor Ensure all 36 icon SVGs use fill="currentColor" or stroke="currentColor" `(assets/icons/*.svg)` ✓ +- [x] #migrate-all-img-icons Replace all remaining `` with `` across 26 template files ✓ +- [x] #icon-css-cleanup Remove `` filter hacks from admin.css, add explicit sizes for header nav + public search icons `(admin.css, search.css)` ✓ +- [x] #icon-em-sizing Set icon helper to output width="1em" height="1em" so icons scale with parent font-size `(icon.php)` ✓ +- [x] #inline-svg-to-icons Move all inline SVGs to asset icon files, ensure currentColor fill for proper color inheritance `(33 icons, 22 files, 67+ inline SVGs replaced, 2 dynamic SVGs remain)` ✓ - [x] #cleanup-modal-fixes Fix nettoyage modal: SVG caret icons, margin→padding, BBBDMSans summary `(admin.css, details.css)` ✓ - [x] #structure-formulaire-page Move "Structure du Formulaire" from contenus.php to its own dedicated page with back button `(structure-formulaire.php [new], contenus.php)` ✓ - [x] #contenus-indexes Add index on thesis_languages(language_id) + tags(deleted_at, name); fix count queries to exclude soft-deleted theses `(Database.php, DatabaseMigrations.php, schema.sql, migrations/applied/041_thesis_languages_index.sql)` ✓ @@ -22,7 +28,6 @@ - [x] #context-note-synopsis Display contextual note above synopsis (italic) instead of in meta column on TFE page `(tfe.php, tfe.css)` ✓ - [x] #decouple-contacts Decouple contact_visible (public) & contact_interne (private email): backend already decoupled; made contact_public checkbox functional in admin add/edit forms; contact_public now controls TFE page visibility `(FormBootstrap.php, ThesisCreateController.php, ThesisEditController.php, tfe.php, form.php)` ✓ - [x] #csrf-rotation-race Stop CSRF token rotation in draft.php + remove hx-post from
— both broke FilePond uploads and form submission `(admin/actions/draft.php, partage/fragments/draft.php, FormBootstrap.php, pill-search.js)` ✓ -- [x] ~~#filepond-csrf-stale~~ (superseded by #csrf-rotation-race) - [x] #adminold-return-type Fix adminOld closure return type from `:string` to `:string|array` `(FormBootstrap.php)` ✓ - [x] #duration-integer-units Make duration field: integer for pages/Mo, dedicated h/m/s time inputs `(form.php, ThesisCreateController.php, tfe.php, form-base.css)` ✓ - [x] #licence-svg-fix Fix licence details/summary SVG: width 1rem, inline-flex layout `(fieldset-licence-explanation.php, form-base.css)` ✓ @@ -53,11 +58,4 @@ - [x] #split-form-css Split `form.css` into `form-base.css` and `form-admin.css` ✓ - [x] #extra-css-admin Update `head.php` to support `$extraCssAdmin` for admin-only stylesheets `(head.php)` ✓ -## Pending -- [ ] #overtype-analysis Analyse and fix OverType editor reliability on contenus-edit.php -- [ ] #contact-test-manual Test contact decoupling end-to-end: student submission → admin edit → public TFE display -- [ ] #aria-test-manual Test WCAG changes with VoiceOver and NVDA on full add/edit/partage form flows -- [ ] #nojs-upload-test Test end-to-end: submit partage form with JS disabled, verify files arrive via `$_FILES` -- [ ] #csp-media-iframe-deploy Deploy nginx config fix to server, test PDF iframe on /tfe?id=221 - ## Deferred / Blocked diff --git a/app/bootstrap.php b/app/bootstrap.php index 016b2bd..a4c60f1 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -40,6 +40,7 @@ if (php_sapi_name() === 'cli-server') { // Central application helper (boot, auth guard, CSRF, flash, render) require_once APP_ROOT . '/src/App.php'; +require_once APP_ROOT . '/src/icon.php'; // Maintenance mode gate — block public pages; allow /admin/ through. // The flag file lives in storage/ (outside webroot) to avoid web exposure. diff --git a/app/public/admin/actions/cleanup-stats-fragment.php b/app/public/admin/actions/cleanup-stats-fragment.php index ab64930..2a2782f 100644 --- a/app/public/admin/actions/cleanup-stats-fragment.php +++ b/app/public/admin/actions/cleanup-stats-fragment.php @@ -45,7 +45,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
- + Fichiers temporaires

✓ Aucun fichier temporaire.

@@ -56,13 +56,13 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
- + Fichiers temporaires 0): ?>

- + Téléversements abandonnés

@@ -80,7 +80,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?> hx-target="#tmp-cleanup-stats-wrapper" hx-swap="outerHTML" hx-indicator="#tmp-cleanup-stats-wrapper"> - + Supprimer @@ -92,7 +92,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?> 0): ?>

- + Corbeille

@@ -110,7 +110,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?> hx-target="#tmp-cleanup-stats-wrapper" hx-swap="outerHTML" hx-indicator="#tmp-cleanup-stats-wrapper"> - + Supprimer diff --git a/app/public/admin/actions/peertube-orphans-fragment.php b/app/public/admin/actions/peertube-orphans-fragment.php index dd8e0b5..c6baa65 100644 --- a/app/public/admin/actions/peertube-orphans-fragment.php +++ b/app/public/admin/actions/peertube-orphans-fragment.php @@ -20,7 +20,7 @@ if (!($d['configured'] ?? false)): ?>
- + Vidéos PeerTube orphelines
@@ -34,7 +34,7 @@ if (!($d['configured'] ?? false)): ?>
- + Vidéos PeerTube orphelines
@@ -47,7 +47,7 @@ if (!($d['configured'] ?? false)): ?>
- + Vidéos PeerTube orphelines vidéos orphelines
@@ -70,7 +70,7 @@ if (!($d['configured'] ?? false)): ?> hx-swap="outerHTML" hx-trigger="click" hx-indicator="#peertube-orphans-wrapper"> - + Supprimer @@ -87,7 +87,7 @@ if (!($d['configured'] ?? false)): ?> 0): ?>
- + Références DB obsolètes

Ces UUID sont référencés en base de données mais n'existent plus sur la chaîne PeerTube. Les TFE liés affichent des liens morts.

diff --git a/app/public/admin/contenus-langues-fragment.php b/app/public/admin/contenus-langues-fragment.php index 11155a2..905683f 100644 --- a/app/public/admin/contenus-langues-fragment.php +++ b/app/public/admin/contenus-langues-fragment.php @@ -28,19 +28,19 @@ try { 0 langue(s) sélectionnée(s)
@@ -74,7 +74,7 @@ try {
@@ -87,7 +87,7 @@ try { diff --git a/app/public/admin/contenus-motscles-fragment.php b/app/public/admin/contenus-motscles-fragment.php index 486a08f..d9aba9f 100644 --- a/app/public/admin/contenus-motscles-fragment.php +++ b/app/public/admin/contenus-motscles-fragment.php @@ -28,19 +28,19 @@ try { 0 mot(s)-clé(s) sélectionné(s)
@@ -74,7 +74,7 @@ try { @@ -87,7 +87,7 @@ try { diff --git a/app/public/admin/fragments/file-browser.php b/app/public/admin/fragments/file-browser.php index 4395808..29306bd 100644 --- a/app/public/admin/fragments/file-browser.php +++ b/app/public/admin/fragments/file-browser.php @@ -88,18 +88,18 @@ $rootDirs = ['tfe', 'these', 'frart', 'documents', 'theses']; function fileIcon(string $ext): string { $ext = strtolower($ext); if ($ext === 'pdf') { - return ''; + return icon('file-text-audio'); } if (in_array($ext, ['zip', 'tar', 'gz', 'bz2', 'xz', '7z', 'rar'], true)) { - return ''; + return icon('file-doc'); } // Default text-file icon for all other extensions - return ''; + return icon('file-lines'); } // SVG folder icon (same for all directories) function folderIcon(): string { - return ''; + return icon('folder'); } ?>
diff --git a/app/public/admin/fragments/peertube-browser.php b/app/public/admin/fragments/peertube-browser.php index ba2772f..d5e80c8 100644 --- a/app/public/admin/fragments/peertube-browser.php +++ b/app/public/admin/fragments/peertube-browser.php @@ -98,7 +98,7 @@ if (empty($orphans)) { > - + diff --git a/app/public/admin/markdown-cheatsheet-fragment.php b/app/public/admin/markdown-cheatsheet-fragment.php index f79d6a4..7cddb9e 100644 --- a/app/public/admin/markdown-cheatsheet-fragment.php +++ b/app/public/admin/markdown-cheatsheet-fragment.php @@ -95,7 +95,7 @@ $rows = [ onclick="this.closest('dialog').close()" title="Fermer" aria-label="Fermer"> - +
diff --git a/app/public/admin/tags-fragment.php b/app/public/admin/tags-fragment.php index 9e033f3..c39bb4c 100644 --- a/app/public/admin/tags-fragment.php +++ b/app/public/admin/tags-fragment.php @@ -32,7 +32,7 @@ try { @@ -65,7 +65,7 @@ try { @@ -77,7 +77,7 @@ try { diff --git a/app/public/assets/css/admin.css b/app/public/assets/css/admin.css index 939462d..6d131b1 100644 --- a/app/public/assets/css/admin.css +++ b/app/public/assets/css/admin.css @@ -30,6 +30,8 @@ } .admin-body header nav ul [data-nav-logout] a svg { display: block; + width: 20px; + height: 20px; } /* Public-site link icon in admin nav */ @@ -40,6 +42,11 @@ column-gap: 0.4em; } +.admin-body header nav .nav-logo svg { + width: 16px; + height: 16px; +} + .admin-body main { flex: 1; diff --git a/app/public/assets/css/components/search.css b/app/public/assets/css/components/search.css index c4aac58..a892452 100644 --- a/app/public/assets/css/components/search.css +++ b/app/public/assets/css/components/search.css @@ -3,6 +3,21 @@ Root class: .header-search-wrap ============================================================ */ +/* Public search bar icon (in partials/search-bar.php) */ +/* Scoped to forms that are NOT inside .header-search-wrap */ +form[role="search"]:not(.header-search-form) > svg { + width: 20px; + height: 20px; + flex-shrink: 0; + fill: var(--text-tertiary); + margin-right: var(--space-2xs); +} + +form[role="search"]:not(.header-search-form) { + display: flex; + align-items: center; +} + .header-search-wrap { padding: 0; flex-shrink: 0; @@ -23,7 +38,7 @@ left: var(--space-s); width: 18px; height: 18px; - stroke: var(--accent-primary); + fill: var(--accent-primary); pointer-events: none; } diff --git a/app/public/assets/icons/caret-down.svg b/app/public/assets/icons/caret-down.svg index 42f37b7..0fca5a9 100644 --- a/app/public/assets/icons/caret-down.svg +++ b/app/public/assets/icons/caret-down.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/public/assets/icons/caret-right.svg b/app/public/assets/icons/caret-right.svg index 81658b0..c028357 100644 --- a/app/public/assets/icons/caret-right.svg +++ b/app/public/assets/icons/caret-right.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/public/assets/icons/circle-i.svg b/app/public/assets/icons/circle-i.svg index 5a19a75..9ec47aa 100644 --- a/app/public/assets/icons/circle-i.svg +++ b/app/public/assets/icons/circle-i.svg @@ -1 +1 @@ - + diff --git a/app/public/assets/icons/paint-brush-household.svg b/app/public/assets/icons/paint-brush-household.svg index d67ecb3..6c60a3a 100644 --- a/app/public/assets/icons/paint-brush-household.svg +++ b/app/public/assets/icons/paint-brush-household.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/public/assets/icons/plus-circle.svg b/app/public/assets/icons/plus-circle.svg new file mode 100644 index 0000000..5df2479 --- /dev/null +++ b/app/public/assets/icons/plus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/public/assets/icons/search.svg b/app/public/assets/icons/search.svg index 2ff8c5d..7970b57 100644 --- a/app/public/assets/icons/search.svg +++ b/app/public/assets/icons/search.svg @@ -1 +1 @@ - + diff --git a/app/public/assets/icons/trash.svg b/app/public/assets/icons/trash.svg index 0504592..758cbb3 100644 --- a/app/public/assets/icons/trash.svg +++ b/app/public/assets/icons/trash.svg @@ -1 +1 @@ - + diff --git a/app/public/assets/icons/tray-arrow-up.svg b/app/public/assets/icons/tray-arrow-up.svg new file mode 100644 index 0000000..6da71ff --- /dev/null +++ b/app/public/assets/icons/tray-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/public/assets/icons/video.svg b/app/public/assets/icons/video.svg index d711517..da78fa9 100644 --- a/app/public/assets/icons/video.svg +++ b/app/public/assets/icons/video.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/public/assets/icons/warning-diamond.svg b/app/public/assets/icons/warning-diamond.svg index fb1346d..78533d8 100644 --- a/app/public/assets/icons/warning-diamond.svg +++ b/app/public/assets/icons/warning-diamond.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/icon.php b/app/src/icon.php new file mode 100644 index 0000000..0fcd6da --- /dev/null +++ b/app/src/icon.php @@ -0,0 +1,35 @@ + + * + */ +function icon(string $name, int $size = 0, string $class = ''): string { + $path = APP_ROOT . "/public/assets/icons/{$name}.svg"; + if (!file_exists($path)) { + return ""; + } + $svg = file_get_contents($path); + // Normalise width/height to 1em so icons scale with font-size + $svg = preg_replace('/\bwidth="[^"]*"/', 'width="1em"', $svg); + $svg = preg_replace('/\bheight="[^"]*"/', 'height="1em"', $svg); + // Ensure aria-hidden by default (icons are decorative when used via this helper) + if (!str_contains($svg, 'aria-hidden')) { + $svg = str_replace(' diff --git a/app/templates/admin/add.php b/app/templates/admin/add.php index 8d131ff..01336c4 100644 --- a/app/templates/admin/add.php +++ b/app/templates/admin/add.php @@ -1,5 +1,5 @@
-

Ajouter un TFE

+

Ajouter un TFE

">+ Ajouter une entrée @@ -88,7 +88,7 @@ data-key="">+ Ajouter une entrée diff --git a/app/templates/admin/contenus-edit.php b/app/templates/admin/contenus-edit.php index 9f90acf..c6b5ffa 100644 --- a/app/templates/admin/contenus-edit.php +++ b/app/templates/admin/contenus-edit.php @@ -1,5 +1,5 @@
-

Éditer :

+

Éditer :

@@ -63,7 +63,7 @@ @@ -87,7 +87,7 @@ diff --git a/app/templates/admin/contenus.php b/app/templates/admin/contenus.php index 64ba9ce..3381811 100644 --- a/app/templates/admin/contenus.php +++ b/app/templates/admin/contenus.php @@ -38,7 +38,7 @@
@@ -309,10 +309,10 @@ function languesStartRename(id) { + '' + '' + '' + ''; cell.querySelector('input').focus(); } @@ -321,7 +321,7 @@ function languesCancelRename(id) { var cell = document.getElementById('lang-name-' + id); cell.innerHTML = '' + cell.getAttribute('data-name') + '' + ''; } @@ -488,10 +488,10 @@ function motsclesStartRename(id) { + '' + '' + '' + ''; cell.querySelector('input').focus(); } @@ -500,7 +500,7 @@ function motsclesCancelRename(id) { var cell = document.getElementById('motscles-name-' + id); cell.innerHTML = '' + cell.getAttribute('data-name') + '' + ''; } diff --git a/app/templates/admin/edit.php b/app/templates/admin/edit.php index 428d2fc..db13351 100644 --- a/app/templates/admin/edit.php +++ b/app/templates/admin/edit.php @@ -1,5 +1,5 @@
-

Modifier un TFE

+

Modifier un TFE

- +
@@ -95,12 +95,12 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string { @@ -109,7 +109,7 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string {
diff --git a/app/templates/admin/index-trash.php b/app/templates/admin/index-trash.php index e5297e2..22d70ca 100644 --- a/app/templates/admin/index-trash.php +++ b/app/templates/admin/index-trash.php @@ -2,7 +2,7 @@
-

Corbeille

+

Corbeille

TFE(s)
@@ -60,7 +60,7 @@
diff --git a/app/templates/admin/index.php b/app/templates/admin/index.php index 7ef86d4..9898a4c 100644 --- a/app/templates/admin/index.php +++ b/app/templates/admin/index.php @@ -33,7 +33,7 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input diff --git a/app/templates/admin/partials/dialogs/tmp-cleanup.php b/app/templates/admin/partials/dialogs/tmp-cleanup.php index f6d661d..dff1b13 100644 --- a/app/templates/admin/partials/dialogs/tmp-cleanup.php +++ b/app/templates/admin/partials/dialogs/tmp-cleanup.php @@ -15,7 +15,7 @@ hx-indicator="#tmp-cleanup-stats-wrapper">
- + Fichiers temporaires

Chargement…

diff --git a/app/templates/admin/recapitulatif.php b/app/templates/admin/recapitulatif.php index 41f8213..4e23e1a 100644 --- a/app/templates/admin/recapitulatif.php +++ b/app/templates/admin/recapitulatif.php @@ -28,7 +28,7 @@ -

Récapitulatif TFE

+

Récapitulatif TFE

diff --git a/app/templates/admin/tags.php b/app/templates/admin/tags.php index 5d7d5d1..6322857 100644 --- a/app/templates/admin/tags.php +++ b/app/templates/admin/tags.php @@ -52,10 +52,10 @@ function tagsStartRename(id) { + '' + '' + '' + ''; cell.querySelector('input').focus(); } @@ -64,7 +64,7 @@ function tagsCancelRename(id) { var cell = document.getElementById('tag-name-' + id); cell.innerHTML = '' + cell.getAttribute('data-name') + '' + ''; } @@ -90,7 +90,7 @@ document.addEventListener('htmx:afterSwap', function(evt) {
-

Mots-clés

+

Mots-clés

diff --git a/app/templates/header.php b/app/templates/header.php index 8504715..7aaba58 100644 --- a/app/templates/header.php +++ b/app/templates/header.php @@ -15,7 +15,7 @@ $_thesisId = $_GET['id'] ?? null; @@ -90,7 +90,7 @@ $_thesisId = $_GET['id'] ?? null;
- +

Section administrateur

L'administration n'est pas accessible sur mobile. Veuillez utiliser un ordinateur.

@@ -106,7 +106,7 @@ $searchBarValue = $searchBarValue ?? $_GET['query'] ?? ''; role="search" aria-label="Recherche" class="header-search-form">
- + - Relier un fichier existant + Relier un fichier existant
@@ -128,7 +128,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? ''); hx-swap="innerHTML" hx-trigger="click" onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'note_intention', thesisId: '' };"> - Relier un fichier existant + Relier un fichier existant
@@ -166,7 +166,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? ''); hx-swap="innerHTML" hx-trigger="click" onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'tfe', thesisId: '' };"> - Relier un fichier existant + Relier un fichier existant @@ -207,7 +207,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? ''); hx-swap="innerHTML" hx-trigger="click" onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'annexe', thesisId: '' };"> - Relier un fichier existant + Relier un fichier existant diff --git a/app/templates/partials/form/fieldset-licence-explanation.php b/app/templates/partials/form/fieldset-licence-explanation.php index 8347b36..313a859 100644 --- a/app/templates/partials/form/fieldset-licence-explanation.php +++ b/app/templates/partials/form/fieldset-licence-explanation.php @@ -65,7 +65,7 @@ $adminMode = $adminMode ?? false;
- Info + Info

Mon TFE est en libre accès à tout le monde sur la plateforme des TFE ainsi que dans la bibliothèque de l'erg. Je suis conscient des responsabilités et obligations légales qui viennent avec une diffusion externe – et acquiesce avoir lu la documentation prévue à cet effet par l'erg, ainsi qu'avoir discuté des enjeux d'une publication avec l'équipe pédagogique. J'accepte de partager mes droits de diffusion avec l'erg, ce uniquement dans le cadre d'une diffusion sur la plateforme xamxam.

@@ -86,7 +86,7 @@ $adminMode = $adminMode ?? false;
- Info + Info

Mon TFE et ma note d'intention ne sont accessibles que sur place en physique ainsi que sur la plateforme xamxam par la communauté erg. Une note descriptive est disponible sur le site à toustes. J'autorise une (ré-)utilisation et diffusion dans un contexte académique et didactique au sein de l'erg.

@@ -109,7 +109,7 @@ $adminMode = $adminMode ?? false;
- Info + Info

Mon TFE n'est pas disponible en physique ni sur le site. Une note descriptive est disponible sur le site.

diff --git a/app/templates/partials/form/language-search.php b/app/templates/partials/form/language-search.php index f0afe1b..737f108 100644 --- a/app/templates/partials/form/language-search.php +++ b/app/templates/partials/form/language-search.php @@ -45,7 +45,7 @@ $langCount = count($selectedLanguages); diff --git a/app/templates/partials/form/tag-search.php b/app/templates/partials/form/tag-search.php index 3e3a86b..123ab1e 100644 --- a/app/templates/partials/form/tag-search.php +++ b/app/templates/partials/form/tag-search.php @@ -48,7 +48,7 @@ $belowMin = $required && $tagCount < $minTags; diff --git a/app/templates/partials/search-bar.php b/app/templates/partials/search-bar.php index b17f3ce..5c0bf00 100644 --- a/app/templates/partials/search-bar.php +++ b/app/templates/partials/search-bar.php @@ -6,7 +6,7 @@ $_sbValue = $searchBarValue ?? $_GET['query'] ?? '';
- +
- +