Migrate all <img>-based icons to inline SVG via PHP helper

Replace every <img src="/assets/icons/..."> with <?= icon('name') ?>
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 <img> filter: brightness(0) invert(1) hacks from admin.css
This commit is contained in:
Pontoporeia
2026-06-21 17:23:37 +02:00
parent b1774e6e97
commit dfde88eaa5
42 changed files with 166 additions and 108 deletions

20
TODO.md
View File

@@ -1,12 +1,18 @@
# TODO # TODO
> Last updated: 2026-06-21 > Last updated: 2026-06-21
> Context: nettoyage modal styling fixes + inline SVG → icon files migration > Context: Migrate all <img>-based icons to inline SVG via PHP helper so CSS color cascade works
## In Progress ## Pending
- [ ] #inline-svg-to-icons Move all inline SVGs to asset icon files, ensure correct fill colors `(24 icon files, 22 PHP/HTML files updated)` - [ ] #icon-color-verify Verify icon colors render correctly across all pages (header, admin tables, forms, dialogs, cleanup modal)
## Completed ## 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 `<img src="/assets/icons/">` with `<?= icon() ?>` across 26 template files ✓
- [x] #icon-css-cleanup Remove `<img>` 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] #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] #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)` - [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] #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] #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 <form> — both broke FilePond uploads and form submission `(admin/actions/draft.php, partage/fragments/draft.php, FormBootstrap.php, pill-search.js)` - [x] #csrf-rotation-race Stop CSRF token rotation in draft.php + remove hx-post from <form> — 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] #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] #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)` - [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] #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)` - [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 ## Deferred / Blocked

View File

@@ -40,6 +40,7 @@ if (php_sapi_name() === 'cli-server') {
// Central application helper (boot, auth guard, CSRF, flash, render) // Central application helper (boot, auth guard, CSRF, flash, render)
require_once APP_ROOT . '/src/App.php'; require_once APP_ROOT . '/src/App.php';
require_once APP_ROOT . '/src/icon.php';
// Maintenance mode gate — block public pages; allow /admin/ through. // Maintenance mode gate — block public pages; allow /admin/ through.
// The flag file lives in storage/ (outside webroot) to avoid web exposure. // The flag file lives in storage/ (outside webroot) to avoid web exposure.

View File

@@ -45,7 +45,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
<div id="tmp-cleanup-stats-wrapper"> <div id="tmp-cleanup-stats-wrapper">
<details class="n-section" open> <details class="n-section" open>
<summary> <summary>
<img src="/assets/icons/paint-brush-household.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('paint-brush-household') ?>
Fichiers temporaires Fichiers temporaires
</summary> </summary>
<p style="margin:0;color:var(--accent-green)">✓ Aucun fichier temporaire.</p> <p style="margin:0;color:var(--accent-green)">✓ Aucun fichier temporaire.</p>
@@ -56,13 +56,13 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
<div id="tmp-cleanup-stats-wrapper"> <div id="tmp-cleanup-stats-wrapper">
<details class="n-section" open> <details class="n-section" open>
<summary> <summary>
<img src="/assets/icons/paint-brush-household.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('paint-brush-household') ?>
Fichiers temporaires <span class="n-meta"><?= htmlspecialchars($summaryMeta) ?></span> Fichiers temporaires <span class="n-meta"><?= htmlspecialchars($summaryMeta) ?></span>
</summary> </summary>
<?php if ($fpStale > 0): ?> <?php if ($fpStale > 0): ?>
<p class="n-heading"> <p class="n-heading">
<img src="/assets/icons/paint-brush-household.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('paint-brush-household') ?>
Téléversements abandonnés Téléversements abandonnés
</p> </p>
<table class="n-table"> <table class="n-table">
@@ -80,7 +80,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
hx-target="#tmp-cleanup-stats-wrapper" hx-target="#tmp-cleanup-stats-wrapper"
hx-swap="outerHTML" hx-swap="outerHTML"
hx-indicator="#tmp-cleanup-stats-wrapper"> hx-indicator="#tmp-cleanup-stats-wrapper">
<img src="/assets/icons/trash.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('trash') ?>
Supprimer Supprimer
</button> </button>
</td> </td>
@@ -92,7 +92,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
<?php if ($trStale > 0): ?> <?php if ($trStale > 0): ?>
<p class="n-heading"> <p class="n-heading">
<img src="/assets/icons/trash.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('trash') ?>
Corbeille Corbeille
</p> </p>
<table class="n-table"> <table class="n-table">
@@ -110,7 +110,7 @@ if ($totalStale === 0 && $totalFiles === 0): ?>
hx-target="#tmp-cleanup-stats-wrapper" hx-target="#tmp-cleanup-stats-wrapper"
hx-swap="outerHTML" hx-swap="outerHTML"
hx-indicator="#tmp-cleanup-stats-wrapper"> hx-indicator="#tmp-cleanup-stats-wrapper">
<img src="/assets/icons/trash.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('trash') ?>
Supprimer Supprimer
</button> </button>
</td> </td>

View File

@@ -20,7 +20,7 @@ if (!($d['configured'] ?? false)): ?>
<div id="peertube-orphans-wrapper"> <div id="peertube-orphans-wrapper">
<details id="peertube-orphans-col" class="n-section" open> <details id="peertube-orphans-col" class="n-section" open>
<summary> <summary>
<img src="/assets/icons/video.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('video') ?>
Vidéos PeerTube orphelines Vidéos PeerTube orphelines
</summary> </summary>
<div id="peertube-orphans-stats"> <div id="peertube-orphans-stats">
@@ -34,7 +34,7 @@ if (!($d['configured'] ?? false)): ?>
<div id="peertube-orphans-wrapper"> <div id="peertube-orphans-wrapper">
<details id="peertube-orphans-col" class="n-section" open> <details id="peertube-orphans-col" class="n-section" open>
<summary> <summary>
<img src="/assets/icons/video.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('video') ?>
Vidéos PeerTube orphelines Vidéos PeerTube orphelines
</summary> </summary>
<div id="peertube-orphans-stats"> <div id="peertube-orphans-stats">
@@ -47,7 +47,7 @@ if (!($d['configured'] ?? false)): ?>
<div id="peertube-orphans-wrapper"> <div id="peertube-orphans-wrapper">
<details id="peertube-orphans-col" class="n-section" open> <details id="peertube-orphans-col" class="n-section" open>
<summary> <summary>
<img src="/assets/icons/video.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('video') ?>
Vidéos PeerTube orphelines <span class="n-meta"><?= (int)($d['orphan_count'] ?? 0) ?> vidéos orphelines</span> Vidéos PeerTube orphelines <span class="n-meta"><?= (int)($d['orphan_count'] ?? 0) ?> vidéos orphelines</span>
</summary> </summary>
<div id="peertube-orphans-stats"> <div id="peertube-orphans-stats">
@@ -70,7 +70,7 @@ if (!($d['configured'] ?? false)): ?>
hx-swap="outerHTML" hx-swap="outerHTML"
hx-trigger="click" hx-trigger="click"
hx-indicator="#peertube-orphans-wrapper"> hx-indicator="#peertube-orphans-wrapper">
<img src="/assets/icons/trash.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('trash') ?>
Supprimer Supprimer
</button> </button>
</td> </td>
@@ -87,7 +87,7 @@ if (!($d['configured'] ?? false)): ?>
<?php if (($d['stale_count'] ?? 0) > 0): ?> <?php if (($d['stale_count'] ?? 0) > 0): ?>
<details id="peertube-stale-section" class="n-section" open> <details id="peertube-stale-section" class="n-section" open>
<summary> <summary>
<img src="/assets/icons/warning-diamond.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('warning-diamond') ?>
Références DB obsolètes <span class="n-meta"><?= $d['stale_count'] ?></span> Références DB obsolètes <span class="n-meta"><?= $d['stale_count'] ?></span>
</summary> </summary>
<p style="margin:0 0 var(--space-sm) 0;font-size:0.85em;color:var(--text-secondary)">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.</p> <p style="margin:0 0 var(--space-sm) 0;font-size:0.85em;color:var(--text-secondary)">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.</p>

View File

@@ -28,19 +28,19 @@ try {
<strong><span id="langues-selected-count">0</span> langue(s) sélectionnée(s)</strong> <strong><span id="langues-selected-count">0</span> langue(s) sélectionnée(s)</strong>
<div class="admin-bulk-btns"> <div class="admin-bulk-btns">
<button type="button" class="btn btn--sm btn--secondary" onclick="languesCancelSelection()" title="Annuler la sélection"> <button type="button" class="btn btn--sm btn--secondary" onclick="languesCancelSelection()" title="Annuler la sélection">
<img src="/assets/icons/x-close.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('x-close') ?>
Annuler Annuler
</button> </button>
<button type="button" class="btn btn--sm btn--red admin-btn-delete" <button type="button" class="btn btn--sm btn--red admin-btn-delete"
onclick="languesConfirmBulkDelete()" onclick="languesConfirmBulkDelete()"
title="Supprimer les langues sélectionnées"> title="Supprimer les langues sélectionnées">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
Supprimer Supprimer
</button> </button>
<button type="button" class="btn btn--sm btn--warning admin-btn-merge" <button type="button" class="btn btn--sm btn--warning admin-btn-merge"
onclick="languesConfirmBulkMerge()" onclick="languesConfirmBulkMerge()"
title="Fusionner les langues sélectionnées"> title="Fusionner les langues sélectionnées">
<img src="/assets/icons/link-chain.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('link-chain') ?>
Fusionner Fusionner
</button> </button>
</div> </div>
@@ -74,7 +74,7 @@ try {
<span class="tag-name-cell"><?= htmlspecialchars($lang['name']) ?></span> <span class="tag-name-cell"><?= htmlspecialchars($lang['name']) ?></span>
<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" <button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer"
onclick="languesStartRename(<?= (int)$lang['id'] ?>)"> onclick="languesStartRename(<?= (int)$lang['id'] ?>)">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</button> </button>
</td> </td>
<td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$lang['thesis_count'] ?></td> <td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$lang['thesis_count'] ?></td>
@@ -87,7 +87,7 @@ try {
<input type="hidden" name="language_id" value="<?= (int)$lang['id'] ?>"> <input type="hidden" name="language_id" value="<?= (int)$lang['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="languesConfirmDelete(this, <?= htmlspecialchars(json_encode($lang['name']), ENT_QUOTES) ?>)"> onclick="languesConfirmDelete(this, <?= htmlspecialchars(json_encode($lang['name']), ENT_QUOTES) ?>)">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -28,19 +28,19 @@ try {
<strong><span id="motscles-selected-count">0</span> mot(s)-clé(s) sélectionné(s)</strong> <strong><span id="motscles-selected-count">0</span> mot(s)-clé(s) sélectionné(s)</strong>
<div class="admin-bulk-btns"> <div class="admin-bulk-btns">
<button type="button" class="btn btn--sm btn--secondary" onclick="motsclesCancelSelection()" title="Annuler la sélection"> <button type="button" class="btn btn--sm btn--secondary" onclick="motsclesCancelSelection()" title="Annuler la sélection">
<img src="/assets/icons/x-close.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('x-close') ?>
Annuler Annuler
</button> </button>
<button type="button" class="btn btn--sm btn--red admin-btn-delete" <button type="button" class="btn btn--sm btn--red admin-btn-delete"
onclick="motsclesConfirmBulkDelete()" onclick="motsclesConfirmBulkDelete()"
title="Supprimer les mots-clés sélectionnés"> title="Supprimer les mots-clés sélectionnés">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
Supprimer Supprimer
</button> </button>
<button type="button" class="btn btn--sm btn--warning admin-btn-merge" <button type="button" class="btn btn--sm btn--warning admin-btn-merge"
onclick="motsclesConfirmBulkMerge()" onclick="motsclesConfirmBulkMerge()"
title="Fusionner les mots-clés sélectionnés"> title="Fusionner les mots-clés sélectionnés">
<img src="/assets/icons/link-chain.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('link-chain') ?>
Fusionner Fusionner
</button> </button>
</div> </div>
@@ -74,7 +74,7 @@ try {
<span class="tag-name-cell"><?= htmlspecialchars($tag['name']) ?></span> <span class="tag-name-cell"><?= htmlspecialchars($tag['name']) ?></span>
<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" <button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer"
onclick="motsclesStartRename(<?= (int)$tag['id'] ?>)"> onclick="motsclesStartRename(<?= (int)$tag['id'] ?>)">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</button> </button>
</td> </td>
<td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$tag['thesis_count'] ?></td> <td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$tag['thesis_count'] ?></td>
@@ -87,7 +87,7 @@ try {
<input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>"> <input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="motsclesConfirmDelete(this, <?= htmlspecialchars(json_encode($tag['name']), ENT_QUOTES) ?>)"> onclick="motsclesConfirmDelete(this, <?= htmlspecialchars(json_encode($tag['name']), ENT_QUOTES) ?>)">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -88,18 +88,18 @@ $rootDirs = ['tfe', 'these', 'frart', 'documents', 'theses'];
function fileIcon(string $ext): string { function fileIcon(string $ext): string {
$ext = strtolower($ext); $ext = strtolower($ext);
if ($ext === 'pdf') { if ($ext === 'pdf') {
return '<img src="/assets/icons/file-text-audio.svg" width="24" height="24" alt="" aria-hidden="true">'; return icon('file-text-audio');
} }
if (in_array($ext, ['zip', 'tar', 'gz', 'bz2', 'xz', '7z', 'rar'], true)) { if (in_array($ext, ['zip', 'tar', 'gz', 'bz2', 'xz', '7z', 'rar'], true)) {
return '<img src="/assets/icons/file-doc.svg" width="24" height="24" alt="" aria-hidden="true">'; return icon('file-doc');
} }
// Default text-file icon for all other extensions // Default text-file icon for all other extensions
return '<img src="/assets/icons/file-lines.svg" width="24" height="24" alt="" aria-hidden="true">'; return icon('file-lines');
} }
// SVG folder icon (same for all directories) // SVG folder icon (same for all directories)
function folderIcon(): string { function folderIcon(): string {
return '<img src="/assets/icons/folder.svg" width="24" height="24" alt="" aria-hidden="true">'; return icon('folder');
} }
?> ?>
<div id="file-browser-container" class="file-browser"> <div id="file-browser-container" class="file-browser">

View File

@@ -98,7 +98,7 @@ if (empty($orphans)) {
<?= $v['linkedTo'] !== null ? 'disabled title="Déjà liée au TFE ' . htmlspecialchars($v['linkedTo']) . '"' : '' ?> <?= $v['linkedTo'] !== null ? 'disabled title="Déjà liée au TFE ' . htmlspecialchars($v['linkedTo']) . '"' : '' ?>
> >
<span class="file-browser-icon"> <span class="file-browser-icon">
<img src="/assets/icons/arrow-circle-left.svg" width="24" height="24" alt="" aria-hidden="true"> <?= icon('arrow-circle-left') ?>
</span> </span>
<span class="file-browser-name"><?= htmlspecialchars($v['name']) ?></span> <span class="file-browser-name"><?= htmlspecialchars($v['name']) ?></span>
<span class="file-browser-size"><?= !empty($v['createdAt']) ? substr($v['createdAt'], 0, 10) : '' ?></span> <span class="file-browser-size"><?= !empty($v['createdAt']) ? substr($v['createdAt'], 0, 10) : '' ?></span>

View File

@@ -95,7 +95,7 @@ $rows = [
onclick="this.closest('dialog').close()" onclick="this.closest('dialog').close()"
title="Fermer" title="Fermer"
aria-label="Fermer"> aria-label="Fermer">
<img src="/assets/icons/x-circle.svg" width="24" height="24" alt="" aria-hidden="true"> <?= icon('x-circle') ?>
</button> </button>
</div> </div>

View File

@@ -32,7 +32,7 @@ try {
<button type="button" class="btn btn--sm btn--warning admin-btn-merge" <button type="button" class="btn btn--sm btn--warning admin-btn-merge"
onclick="tagsConfirmBulkMerge()" onclick="tagsConfirmBulkMerge()"
title="Fusionner les mots-clés sélectionnés"> title="Fusionner les mots-clés sélectionnés">
<img src="/assets/icons/link-chain.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('link-chain') ?>
Fusionner Fusionner
</button> </button>
</div> </div>
@@ -65,7 +65,7 @@ try {
<span class="tag-name-cell"><?= htmlspecialchars($tag['name']) ?></span> <span class="tag-name-cell"><?= htmlspecialchars($tag['name']) ?></span>
<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" <button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer"
onclick="tagsStartRename(<?= (int)$tag['id'] ?>)"> onclick="tagsStartRename(<?= (int)$tag['id'] ?>)">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</button> </button>
</td> </td>
<td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$tag['thesis_count'] ?></td> <td class="admin-tags-count" style="width:1%;white-space:nowrap"><?= (int)$tag['thesis_count'] ?></td>
@@ -77,7 +77,7 @@ try {
<input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>"> <input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="tagsConfirmDelete(this, <?= htmlspecialchars(json_encode($tag['name']), ENT_QUOTES) ?>)"> onclick="tagsConfirmDelete(this, <?= htmlspecialchars(json_encode($tag['name']), ENT_QUOTES) ?>)">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -30,6 +30,8 @@
} }
.admin-body header nav ul [data-nav-logout] a svg { .admin-body header nav ul [data-nav-logout] a svg {
display: block; display: block;
width: 20px;
height: 20px;
} }
/* Public-site link icon in admin nav */ /* Public-site link icon in admin nav */
@@ -40,6 +42,11 @@
column-gap: 0.4em; column-gap: 0.4em;
} }
.admin-body header nav .nav-logo svg {
width: 16px;
height: 16px;
}
.admin-body main { .admin-body main {
flex: 1; flex: 1;

View File

@@ -3,6 +3,21 @@
Root class: .header-search-wrap 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 { .header-search-wrap {
padding: 0; padding: 0;
flex-shrink: 0; flex-shrink: 0;
@@ -23,7 +38,7 @@
left: var(--space-s); left: var(--space-s);
width: 18px; width: 18px;
height: 18px; height: 18px;
stroke: var(--accent-primary); fill: var(--accent-primary);
pointer-events: none; pointer-events: none;
} }

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path></svg>

Before

Width:  |  Height:  |  Size: 238 B

After

Width:  |  Height:  |  Size: 243 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path></svg>

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 248 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1rem" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="1rem" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z"></path></svg>

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 368 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M230.64,25.36a32,32,0,0,0-45.26,0q-.21.21-.42.45L131.55,88.22,121,77.64a24,24,0,0,0-33.95,0l-76.69,76.7a8,8,0,0,0,0,11.31l80,80a8,8,0,0,0,11.31,0L178.36,169a24,24,0,0,0,0-33.95l-10.58-10.57L230.19,71c.15-.14.31-.28.45-.43A32,32,0,0,0,230.64,25.36ZM96,228.69,79.32,212l22.34-22.35a8,8,0,0,0-11.31-11.31L68,200.68,55.32,188l22.34-22.35a8,8,0,0,0-11.31-11.31L44,176.68,27.31,160,72,115.31,140.69,184ZM219.52,59.1l-68.71,58.81a8,8,0,0,0-.46,11.74L167,146.34a8,8,0,0,1,0,11.31l-15,15L83.32,104l15-15a8,8,0,0,1,11.31,0l16.69,16.69a8,8,0,0,0,11.74-.46L196.9,36.48A16,16,0,0,1,219.52,59.1Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M230.64,25.36a32,32,0,0,0-45.26,0q-.21.21-.42.45L131.55,88.22,121,77.64a24,24,0,0,0-33.95,0l-76.69,76.7a8,8,0,0,0,0,11.31l80,80a8,8,0,0,0,11.31,0L178.36,169a24,24,0,0,0,0-33.95l-10.58-10.57L230.19,71c.15-.14.31-.28.45-.43A32,32,0,0,0,230.64,25.36ZM96,228.69,79.32,212l22.34-22.35a8,8,0,0,0-11.31-11.31L68,200.68,55.32,188l22.34-22.35a8,8,0,0,0-11.31-11.31L44,176.68,27.31,160,72,115.31,140.69,184ZM219.52,59.1l-68.71,58.81a8,8,0,0,0-.46,11.74L167,146.34a8,8,0,0,1,0,11.31l-15,15L83.32,104l15-15a8,8,0,0,1,11.31,0l16.69,16.69a8,8,0,0,0,11.74-.46L196.9,36.48A16,16,0,0,1,219.52,59.1Z"></path></svg>

Before

Width:  |  Height:  |  Size: 705 B

After

Width:  |  Height:  |  Size: 710 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H136v32a8,8,0,0,1-16,0V136H88a8,8,0,0,1,0-16h32V88a8,8,0,0,1,16,0v32h32A8,8,0,0,1,176,128Z"></path></svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path></svg>

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 273 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"></path></svg>

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 421 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,16V152h-28.7A15.86,15.86,0,0,0,168,156.69L148.69,176H107.31L88,156.69A15.86,15.86,0,0,0,76.69,152H48V48Zm0,160H48V168H76.69L96,187.31A15.86,15.86,0,0,0,107.31,192h41.38A15.86,15.86,0,0,0,160,187.31L179.31,168H208v40ZM90.34,109.66a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,0l32,32a8,8,0,0,1-11.32,11.32L136,91.31V152a8,8,0,0,1-16,0V91.31l-18.34,18.35A8,8,0,0,1,90.34,109.66Z"></path></svg>

After

Width:  |  Height:  |  Size: 598 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M164.44,105.34l-48-32A8,8,0,0,0,104,80v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,129.05V95l25.58,17ZM216,40H40A16,16,0,0,0,24,56V168a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,128H40V56H216V168Zm16,40a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M164.44,105.34l-48-32A8,8,0,0,0,104,80v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,129.05V95l25.58,17ZM216,40H40A16,16,0,0,0,24,56V168a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,128H40V56H216V168Zm16,40a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Z"></path></svg>

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 417 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,72a8,8,0,0,1,8,8v56a8,8,0,0,1-16,0V80A8,8,0,0,1,128,72ZM116,172a12,12,0,1,0,12-12A12,12,0,0,0,116,172Zm124-44a15.85,15.85,0,0,1-4.67,11.28l-96.05,96.06a16,16,0,0,1-22.56,0h0l-96-96.06a16,16,0,0,1,0-22.56l96.05-96.06a16,16,0,0,1,22.56,0l96.05,96.06A15.85,15.85,0,0,1,240,128Zm-16,0L128,32,32,128,128,224h0Z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,72a8,8,0,0,1,8,8v56a8,8,0,0,1-16,0V80A8,8,0,0,1,128,72ZM116,172a12,12,0,1,0,12-12A12,12,0,0,0,116,172Zm124-44a15.85,15.85,0,0,1-4.67,11.28l-96.05,96.06a16,16,0,0,1-22.56,0h0l-96-96.06a16,16,0,0,1,0-22.56l96.05-96.06a16,16,0,0,1,22.56,0l96.05,96.06A15.85,15.85,0,0,1,240,128Zm-16,0L128,32,32,128,128,224h0Z"></path></svg>

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 439 B

35
app/src/icon.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
/**
* Inline SVG icon helper.
*
* Returns the SVG markup for an icon from /assets/icons/{name}.svg.
* The SVG is inlined into the DOM so CSS `color` / `fill` cascade naturally.
* Width/height are set to 1em by default; override via CSS on the parent.
*
* Usage: <?= icon('trash') ?>
* <?= icon('search', 0, 'header-search-icon') ?>
*/
function icon(string $name, int $size = 0, string $class = ''): string {
$path = APP_ROOT . "/public/assets/icons/{$name}.svg";
if (!file_exists($path)) {
return "<!-- icon not found: {$name} -->";
}
$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('<svg', '<svg aria-hidden="true"', $svg);
}
// Inject CSS class if provided
if ($class !== '') {
if (str_contains($svg, 'class="')) {
$svg = str_replace('class="', 'class="' . $class . ' ', $svg);
} else {
$svg = str_replace('<svg', '<svg class="' . $class . '"', $svg);
}
}
return $svg;
}

View File

@@ -73,11 +73,11 @@
<div class="admin-actions"> <div class="admin-actions">
<a href="/partage/<?= urlencode($link['slug']) ?>" target="_blank" rel="noopener" <a href="/partage/<?= urlencode($link['slug']) ?>" target="_blank" rel="noopener"
class="admin-icon-btn admin-icon-btn--view" title="Visiter le formulaire"> class="admin-icon-btn admin-icon-btn--view" title="Visiter le formulaire">
<img src="/assets/icons/play-triangle.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('play-triangle') ?>
</a> </a>
<button type="button" class="admin-icon-btn admin-icon-btn--copy" title="Copier l'URL" <button type="button" class="admin-icon-btn admin-icon-btn--copy" title="Copier l'URL"
onclick="copyUrl(<?= $link['id'] ?>)"> onclick="copyUrl(<?= $link['id'] ?>)">
<img src="/assets/icons/copy-duplicate.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('copy-duplicate') ?>
</button> </button>
<form method="post" action="actions/acces-etudiante.php" class="publish-form"> <form method="post" action="actions/acces-etudiante.php" class="publish-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
@@ -87,15 +87,15 @@
class="admin-icon-btn <?= $link['is_active'] ? 'admin-icon-btn--unpublish' : 'admin-icon-btn--publish' ?>" class="admin-icon-btn <?= $link['is_active'] ? 'admin-icon-btn--unpublish' : 'admin-icon-btn--publish' ?>"
title="<?= $link['is_active'] ? 'Désactiver' : 'Activer' ?>"> title="<?= $link['is_active'] ? 'Désactiver' : 'Activer' ?>">
<?php if ($link['is_active']): ?> <?php if ($link['is_active']): ?>
<img src="/assets/icons/columns.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('columns') ?>
<?php else: ?> <?php else: ?>
<img src="/assets/icons/play-triangle.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('play-triangle') ?>
<?php endif; ?> <?php endif; ?>
</button> </button>
</form> </form>
<button type="button" class="admin-icon-btn admin-icon-btn--key" title="Modifier le mot de passe" <button type="button" class="admin-icon-btn admin-icon-btn--key" title="Modifier le mot de passe"
onclick="openPasswordDialog(<?= $link['id'] ?>, <?= $hasPassword ? 'true' : 'false' ?>)"> onclick="openPasswordDialog(<?= $link['id'] ?>, <?= $hasPassword ? 'true' : 'false' ?>)">
<img src="/assets/icons/fingerprint.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('fingerprint') ?>
</button> </button>
<form method="post" action="actions/acces-etudiante.php" class="publish-form" <form method="post" action="actions/acces-etudiante.php" class="publish-form"
id="delete-link-form-<?= $link['id'] ?>"> id="delete-link-form-<?= $link['id'] ?>">
@@ -104,7 +104,7 @@
<input type="hidden" name="id" value="<?= $link['id'] ?>"> <input type="hidden" name="id" value="<?= $link['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="openDeleteLinkDialog(<?= $link['id'] ?>)"> onclick="openDeleteLinkDialog(<?= $link['id'] ?>)">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -86,7 +86,7 @@
<button type="button" class="admin-icon-btn" title="Copier le mot de passe" <button type="button" class="admin-icon-btn" title="Copier le mot de passe"
onclick="event.stopPropagation(); copyTextToClipboard(document.getElementById('pwd-<?= $link['id'] ?>').value)" onclick="event.stopPropagation(); copyTextToClipboard(document.getElementById('pwd-<?= $link['id'] ?>').value)"
style="width:24px;height:24px;"> style="width:24px;height:24px;">
<img src="/assets/icons/copy-duplicate.svg" width="16" height="16" alt="" aria-hidden="true"> <?= icon('copy-duplicate') ?>
</button> </button>
</div> </div>
<?php else: ?> <?php else: ?>
@@ -100,11 +100,11 @@
<div class="admin-actions"> <div class="admin-actions">
<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Éditer" <button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Éditer"
onclick="event.stopPropagation(); openEditDialog(<?= $link['id'] ?>, <?= htmlspecialchars(json_encode($linkName), ENT_QUOTES) ?>, <?= $hasLinkPassword ? 'true' : 'false' ?>, <?= htmlspecialchars(json_encode($linkExpiresVal), ENT_QUOTES) ?>)"> onclick="event.stopPropagation(); openEditDialog(<?= $link['id'] ?>, <?= htmlspecialchars(json_encode($linkName), ENT_QUOTES) ?>, <?= $hasLinkPassword ? 'true' : 'false' ?>, <?= htmlspecialchars(json_encode($linkExpiresVal), ENT_QUOTES) ?>)">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</button> </button>
<button type="button" class="admin-icon-btn admin-icon-btn--copy" title="Copier l'URL" <button type="button" class="admin-icon-btn admin-icon-btn--copy" title="Copier l'URL"
onclick="event.stopPropagation(); copyUrl(<?= $link['id'] ?>)"> onclick="event.stopPropagation(); copyUrl(<?= $link['id'] ?>)">
<img src="/assets/icons/copy-duplicate.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('copy-duplicate') ?>
</button> </button>
<form method="post" action="actions/acces-etudiante.php" class="publish-form" onclick="event.stopPropagation()"> <form method="post" action="actions/acces-etudiante.php" class="publish-form" onclick="event.stopPropagation()">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
@@ -114,9 +114,9 @@
class="admin-icon-btn <?= $link['is_active'] ? 'admin-icon-btn--unpublish' : 'admin-icon-btn--publish' ?>" class="admin-icon-btn <?= $link['is_active'] ? 'admin-icon-btn--unpublish' : 'admin-icon-btn--publish' ?>"
title="<?= $link['is_active'] ? 'Désactiver' : 'Activer' ?>"> title="<?= $link['is_active'] ? 'Désactiver' : 'Activer' ?>">
<?php if ($link['is_active']): ?> <?php if ($link['is_active']): ?>
<img src="/assets/icons/columns.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('columns') ?>
<?php else: ?> <?php else: ?>
<img src="/assets/icons/play-triangle.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('play-triangle') ?>
<?php endif; ?> <?php endif; ?>
</button> </button>
</form> </form>
@@ -127,7 +127,7 @@
<input type="hidden" name="id" value="<?= $link['id'] ?>"> <input type="hidden" name="id" value="<?= $link['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--archive" title="Archiver" <button type="button" class="admin-icon-btn admin-icon-btn--archive" title="Archiver"
onclick="openArchiveLinkDialog(<?= $link['id'] ?>)"> onclick="openArchiveLinkDialog(<?= $link['id'] ?>)">
<img src="/assets/icons/monitor.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('monitor') ?>
</button> </button>
</form> </form>
</div> </div>
@@ -179,7 +179,7 @@
<td class="admin-actions-col"> <td class="admin-actions-col">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="openDeleteArchivedLinkDialog(<?= $link['id'] ?>)"> onclick="openDeleteArchivedLinkDialog(<?= $link['id'] ?>)">
<img src="/assets/icons/trash.svg" width="16" height="16" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</td> </td>
</tr> </tr>

View File

@@ -1,5 +1,5 @@
<main id="main-content"> <main id="main-content">
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Ajouter un TFE</h1> <h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><?= icon('arrow-left-circle') ?></a> Ajouter un TFE</h1>
<?php <?php
// All form variables are already in scope from FormBootstrap::adminFormVariables(). // All form variables are already in scope from FormBootstrap::adminFormVariables().

View File

@@ -51,7 +51,7 @@
data-key="<?= $aproposKey ?>">+ Ajouter une entrée</button> data-key="<?= $aproposKey ?>">+ Ajouter une entrée</button>
<button type="button" class="admin-icon-btn admin-icon-btn--delete delete-group-btn-f" <button type="button" class="admin-icon-btn admin-icon-btn--delete delete-group-btn-f"
data-key="<?= $aproposKey ?>" title="Supprimer ce contact"> data-key="<?= $aproposKey ?>" title="Supprimer ce contact">
<img src="/assets/icons/trash-slash.svg" width="20" height="20" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</fieldset> </fieldset>
<?php endforeach; ?> <?php endforeach; ?>
@@ -88,7 +88,7 @@
data-key="<?= $aproposKey ?>">+ Ajouter une entrée</button> data-key="<?= $aproposKey ?>">+ Ajouter une entrée</button>
<button type="button" class="admin-icon-btn admin-icon-btn--delete delete-group-btn-f" <button type="button" class="admin-icon-btn admin-icon-btn--delete delete-group-btn-f"
data-key="<?= $aproposKey ?>" title="Supprimer ce contact"> data-key="<?= $aproposKey ?>" title="Supprimer ce contact">
<img src="/assets/icons/trash-slash.svg" width="20" height="20" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</fieldset> </fieldset>
</template> </template>

View File

@@ -1,5 +1,5 @@
<main id="main-content" class="full-editor-page"> <main id="main-content" class="full-editor-page">
<h1><a href="/admin/contenus.php" class="admin-back-btn" title="Retour"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Éditer : <?= htmlspecialchars($editTitle) ?></h1> <h1><a href="/admin/contenus.php" class="admin-back-btn" title="Retour"><?= icon('arrow-left-circle') ?></a> Éditer : <?= htmlspecialchars($editTitle) ?></h1>
<?php if ($editType === 'about_page'): ?> <?php if ($editType === 'about_page'): ?>
@@ -63,7 +63,7 @@
</div> </div>
<button type="button" class="admin-icon-btn admin-icon-btn--delete remove-sidebar-link-btn" <button type="button" class="admin-icon-btn admin-icon-btn--delete remove-sidebar-link-btn"
title="Supprimer ce lien"> title="Supprimer ce lien">
<img src="/assets/icons/trash-slash.svg" width="20" height="20" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
@@ -87,7 +87,7 @@
</div> </div>
<button type="button" class="admin-icon-btn admin-icon-btn--delete remove-sidebar-link-btn" <button type="button" class="admin-icon-btn admin-icon-btn--delete remove-sidebar-link-btn"
title="Supprimer ce lien"> title="Supprimer ce lien">
<img src="/assets/icons/trash-slash.svg" width="20" height="20" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</div> </div>
</template> </template>

View File

@@ -38,7 +38,7 @@
<td> <td>
<a href="/admin/contenus-edit.php?slug=<?= urlencode($p['slug']) ?>" <a href="/admin/contenus-edit.php?slug=<?= urlencode($p['slug']) ?>"
class="admin-icon-btn admin-icon-btn--edit" title="Éditer"> class="admin-icon-btn admin-icon-btn--edit" title="Éditer">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</a> </a>
</td> </td>
</tr> </tr>
@@ -309,10 +309,10 @@ function languesStartRename(id) {
+ '<input type="hidden" name="language_id" value="' + id + '">' + '<input type="hidden" name="language_id" value="' + id + '">'
+ '<input type="text" name="new_name" value="' + cell.getAttribute('data-name') + '" required class="admin-input--inline">' + '<input type="text" name="new_name" value="' + cell.getAttribute('data-name') + '" required class="admin-input--inline">'
+ '<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Valider">' + '<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Valider">'
+ '<img src="/assets/icons/check-circle.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('check-circle') ?>'
+ '</button>' + '</button>'
+ '<button type="button" class="admin-icon-btn admin-icon-btn--delete" onclick="languesCancelRename(' + id + ')" title="Annuler">' + '<button type="button" class="admin-icon-btn admin-icon-btn--delete" onclick="languesCancelRename(' + id + ')" title="Annuler">'
+ '<img src="/assets/icons/x-close.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('x-close') ?>'
+ '</button></form>'; + '</button></form>';
cell.querySelector('input').focus(); cell.querySelector('input').focus();
} }
@@ -321,7 +321,7 @@ function languesCancelRename(id) {
var cell = document.getElementById('lang-name-' + id); var cell = document.getElementById('lang-name-' + id);
cell.innerHTML = '<span class="tag-name-cell">' + cell.getAttribute('data-name') + '</span>' cell.innerHTML = '<span class="tag-name-cell">' + cell.getAttribute('data-name') + '</span>'
+ '<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" onclick="languesStartRename(' + id + ')">' + '<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" onclick="languesStartRename(' + id + ')">'
+ '<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('pencil-note') ?>'
+ '</button>'; + '</button>';
} }
@@ -488,10 +488,10 @@ function motsclesStartRename(id) {
+ '<input type="hidden" name="tag_id" value="' + id + '">' + '<input type="hidden" name="tag_id" value="' + id + '">'
+ '<input type="text" name="new_name" value="' + cell.getAttribute('data-name') + '" required class="admin-input--inline">' + '<input type="text" name="new_name" value="' + cell.getAttribute('data-name') + '" required class="admin-input--inline">'
+ '<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Valider">' + '<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Valider">'
+ '<img src="/assets/icons/check-circle.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('check-circle') ?>'
+ '</button>' + '</button>'
+ '<button type="button" class="admin-icon-btn admin-icon-btn--delete" onclick="motsclesCancelRename(' + id + ')" title="Annuler">' + '<button type="button" class="admin-icon-btn admin-icon-btn--delete" onclick="motsclesCancelRename(' + id + ')" title="Annuler">'
+ '<img src="/assets/icons/x-close.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('x-close') ?>'
+ '</button></form>'; + '</button></form>';
cell.querySelector('input').focus(); cell.querySelector('input').focus();
} }
@@ -500,7 +500,7 @@ function motsclesCancelRename(id) {
var cell = document.getElementById('motscles-name-' + id); var cell = document.getElementById('motscles-name-' + id);
cell.innerHTML = '<span class="tag-name-cell">' + cell.getAttribute('data-name') + '</span>' cell.innerHTML = '<span class="tag-name-cell">' + cell.getAttribute('data-name') + '</span>'
+ '<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" onclick="motsclesStartRename(' + id + ')">' + '<button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Renommer" onclick="motsclesStartRename(' + id + ')">'
+ '<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true">' + '<?= icon('pencil-note') ?>'
+ '</button>'; + '</button>';
} }

View File

@@ -1,5 +1,5 @@
<main id="main-content"> <main id="main-content">
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Modifier un TFE</h1> <h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><?= icon('arrow-left-circle') ?></a> Modifier un TFE</h1>
<?php <?php
// All form variables are already in scope from FormBootstrap::adminFormVariables(). // All form variables are already in scope from FormBootstrap::adminFormVariables().

View File

@@ -87,7 +87,7 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string {
<td class="admin-actions-col"> <td class="admin-actions-col">
<div class="admin-actions"> <div class="admin-actions">
<a href="/admin/edit.php?id=<?= $thesis['id'] ?>" class="admin-icon-btn admin-icon-btn--edit" title="Éditer" onclick="event.stopPropagation()"> <a href="/admin/edit.php?id=<?= $thesis['id'] ?>" class="admin-icon-btn admin-icon-btn--edit" title="Éditer" onclick="event.stopPropagation()">
<img src="/assets/icons/pencil-note.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('pencil-note') ?>
</a> </a>
<form method="post" action="actions/publish.php" class="publish-form" onclick="event.stopPropagation()"> <form method="post" action="actions/publish.php" class="publish-form" onclick="event.stopPropagation()">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
@@ -95,12 +95,12 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string {
<?php if ($thesis['is_published']): ?> <?php if ($thesis['is_published']): ?>
<input type="hidden" name="action" value="unpublish"> <input type="hidden" name="action" value="unpublish">
<button type="submit" class="admin-icon-btn admin-icon-btn--unpublish" title="Dépublier"> <button type="submit" class="admin-icon-btn admin-icon-btn--unpublish" title="Dépublier">
<img src="/assets/icons/eye-slash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('eye-slash') ?>
</button> </button>
<?php else: ?> <?php else: ?>
<input type="hidden" name="action" value="publish"> <input type="hidden" name="action" value="publish">
<button type="submit" class="admin-icon-btn admin-icon-btn--publish" title="Publier"> <button type="submit" class="admin-icon-btn admin-icon-btn--publish" title="Publier">
<img src="/assets/icons/eye.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('eye') ?>
</button> </button>
<?php endif; ?> <?php endif; ?>
</form> </form>
@@ -109,7 +109,7 @@ $sortArrow = function(string $col) use ($sortCol, $sortDir): string {
<input type="hidden" name="thesis_id" value="<?= $thesis['id'] ?>"> <input type="hidden" name="thesis_id" value="<?= $thesis['id'] ?>">
<button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer" <button type="button" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer"
onclick="event.stopPropagation(); confirmDelete(<?= $thesis['id'] ?>, <?= htmlspecialchars(json_encode($thesis['title']), ENT_QUOTES) ?>)"> onclick="event.stopPropagation(); confirmDelete(<?= $thesis['id'] ?>, <?= htmlspecialchars(json_encode($thesis['title']), ENT_QUOTES) ?>)">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -2,7 +2,7 @@
<div class="admin-list-toolbar admin-list-toolbar--list"> <div class="admin-list-toolbar admin-list-toolbar--list">
<div class="admin-toolbar-top"> <div class="admin-toolbar-top">
<div class="admin-toolbar-title-row"> <div class="admin-toolbar-title-row">
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Corbeille</h1> <h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><?= icon('arrow-left-circle') ?></a> Corbeille</h1>
<span class="admin-stat admin-stat--inline" style="margin-left:auto"><?= count($trashedTheses) ?> TFE(s)</span> <span class="admin-stat admin-stat--inline" style="margin-left:auto"><?= count($trashedTheses) ?> TFE(s)</span>
</div> </div>
</div> </div>
@@ -60,7 +60,7 @@
<input type="hidden" name="action" value="restore"> <input type="hidden" name="action" value="restore">
<input type="hidden" name="thesis_id" value="<?= (int)$t['id'] ?>"> <input type="hidden" name="thesis_id" value="<?= (int)$t['id'] ?>">
<button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Restaurer"> <button type="submit" class="admin-icon-btn admin-icon-btn--edit" title="Restaurer">
<img src="/assets/icons/archive-box.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('archive-box') ?>
</button> </button>
</form> </form>
<form method="post" action="actions/corbeille.php" class="admin-inline-form" style="display:inline" <form method="post" action="actions/corbeille.php" class="admin-inline-form" style="display:inline"
@@ -69,7 +69,7 @@
<input type="hidden" name="action" value="hard_delete"> <input type="hidden" name="action" value="hard_delete">
<input type="hidden" name="thesis_id" value="<?= (int)$t['id'] ?>"> <input type="hidden" name="thesis_id" value="<?= (int)$t['id'] ?>">
<button type="submit" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer définitivement"> <button type="submit" class="admin-icon-btn admin-icon-btn--delete" title="Supprimer définitivement">
<img src="/assets/icons/trash.svg" width="32" height="32" alt="" aria-hidden="true"> <?= icon('trash') ?>
</button> </button>
</form> </form>
</div> </div>

View File

@@ -33,7 +33,7 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input
</div> </div>
</div> </div>
<div class="admin-btn-group"> <div class="admin-btn-group">
<a href="/admin/add.php" class="btn btn--primary btn--sm">+ Ajouter un TFE</a> <a href="/admin/add.php" class="btn btn--primary btn--sm"><?= icon('plus-circle') ?> Ajouter un TFE</a>
<?php if ($trashCount > 0): ?> <?php if ($trashCount > 0): ?>
<a href="/admin/index.php?tab=trash" class="btn btn--sm <?= $tab === 'trash' ? 'btn--primary' : 'btn--secondary' ?>"> <a href="/admin/index.php?tab=trash" class="btn btn--sm <?= $tab === 'trash' ? 'btn--primary' : 'btn--secondary' ?>">
Corbeille (<?= $trashCount ?>) Corbeille (<?= $trashCount ?>)
@@ -42,12 +42,12 @@ document.addEventListener('htmx:afterSwap',()=>{document.querySelectorAll('input
<?php if ($tmpTotalCount > 0): ?> <?php if ($tmpTotalCount > 0): ?>
<button type="button" class="btn btn--sm btn--secondary" id="tmp-cleanup-btn" <button type="button" class="btn btn--sm btn--secondary" id="tmp-cleanup-btn"
onclick="document.getElementById('tmp-cleanup-dialog').showModal(); htmx.trigger('#tmp-cleanup-stats-wrapper','loadStats'); htmx.trigger('#peertube-orphans-wrapper','loadPeertube')"> onclick="document.getElementById('tmp-cleanup-dialog').showModal(); htmx.trigger('#tmp-cleanup-stats-wrapper','loadStats'); htmx.trigger('#peertube-orphans-wrapper','loadPeertube')">
Nettoyer (<?= $tmpTotalCount ?>) <?= icon('trash') ?> Nettoyer (<?= $tmpTotalCount ?>)
</button> </button>
<?php endif; ?> <?php endif; ?>
<button type="button" class="btn btn--primary btn--sm" id="import-dialog-btn" <button type="button" class="btn btn--primary btn--sm" id="import-dialog-btn"
onclick="document.getElementById('import-dialog').showModal(); window.XamxamInitFilePonds()"> onclick="document.getElementById('import-dialog').showModal(); window.XamxamInitFilePonds()">
Importer <?= icon('tray-arrow-up') ?> Importer
</button> </button>
</div> </div>
</div> </div>

View File

@@ -15,7 +15,7 @@
hx-indicator="#tmp-cleanup-stats-wrapper"> hx-indicator="#tmp-cleanup-stats-wrapper">
<details class="n-section" open> <details class="n-section" open>
<summary> <summary>
<img src="/assets/icons/paint-brush-household.svg" width="14" height="14" alt="" aria-hidden="true"> <?= icon('paint-brush-household') ?>
Fichiers temporaires Fichiers temporaires
</summary> </summary>
<p style="margin:0;color:var(--text-secondary)">Chargement…</p> <p style="margin:0;color:var(--text-secondary)">Chargement…</p>

View File

@@ -28,7 +28,7 @@
<?php else: ?> <?php else: ?>
<!-- ═══════════════════ ADMIN MODE: Recap page ═══════════════════ --> <!-- ═══════════════════ ADMIN MODE: Recap page ═══════════════════ -->
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Récapitulatif TFE</h1> <h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><?= icon('arrow-left-circle') ?></a> Récapitulatif TFE</h1>
<?php if ($error): ?> <?php if ($error): ?>
<p class="toast" role="alert" data-type="error">⚠ <?= htmlspecialchars($error) ?></p> <p class="toast" role="alert" data-type="error">⚠ <?= htmlspecialchars($error) ?></p>

View File

@@ -52,10 +52,10 @@ function tagsStartRename(id) {
+ '<input type=\"hidden\" name=\"tag_id\" value=\"' + id + '\">' + '<input type=\"hidden\" name=\"tag_id\" value=\"' + id + '\">'
+ '<input type=\"text\" name=\"new_name\" value=\"' + cell.getAttribute('data-name') + '\" required class=\"admin-input--inline\">' + '<input type=\"text\" name=\"new_name\" value=\"' + cell.getAttribute('data-name') + '\" required class=\"admin-input--inline\">'
+ '<button type=\"submit\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Valider\">' + '<button type=\"submit\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Valider\">'
+ '<img src=\"/assets/icons/check-circle.svg\" width=\"32\" height=\"32\" alt=\"\" aria-hidden=\"true\">' + '<?= icon("check-circle") ?>'
+ '</button>' + '</button>'
+ '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--delete\" onclick=\"tagsCancelRename(' + id + ')\" title=\"Annuler\">' + '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--delete\" onclick=\"tagsCancelRename(' + id + ')\" title=\"Annuler\">'
+ '<img src=\"/assets/icons/x-close.svg\" width=\"32\" height=\"32\" alt=\"\" aria-hidden=\"true\">' + '<?= icon("x-close") ?>'
+ '</button></form>'; + '</button></form>';
cell.querySelector('input').focus(); cell.querySelector('input').focus();
} }
@@ -64,7 +64,7 @@ function tagsCancelRename(id) {
var cell = document.getElementById('tag-name-' + id); var cell = document.getElementById('tag-name-' + id);
cell.innerHTML = '<span class=\"tag-name-cell\">' + cell.getAttribute('data-name') + '</span>' cell.innerHTML = '<span class=\"tag-name-cell\">' + cell.getAttribute('data-name') + '</span>'
+ '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Renommer\" onclick=\"tagsStartRename(' + id + ')\">' + '<button type=\"button\" class=\"admin-icon-btn admin-icon-btn--edit\" title=\"Renommer\" onclick=\"tagsStartRename(' + id + ')\">'
+ '<img src=\"/assets/icons/pencil-note.svg\" width=\"32\" height=\"32\" alt=\"\" aria-hidden=\"true\">' + '<?= icon("pencil-note") ?>'
+ '</button>'; + '</button>';
} }
@@ -90,7 +90,7 @@ document.addEventListener('htmx:afterSwap', function(evt) {
<div class="admin-list-toolbar admin-list-toolbar--list" style="margin-bottom:var(--space-s)"> <div class="admin-list-toolbar admin-list-toolbar--list" style="margin-bottom:var(--space-s)">
<div class="admin-toolbar-top"> <div class="admin-toolbar-top">
<div class="admin-toolbar-title-row"> <div class="admin-toolbar-title-row">
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><img src="/assets/icons/arrow-left-circle.svg" width="32" height="32" alt="" aria-hidden="true"></a> Mots-clés</h1> <h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><?= icon('arrow-left-circle') ?></a> Mots-clés</h1>
<span id="tags-total-count" class="admin-stat admin-stat--inline" style="margin-left:auto"></span> <span id="tags-total-count" class="admin-stat admin-stat--inline" style="margin-left:auto"></span>
</div> </div>
</div> </div>

View File

@@ -15,7 +15,7 @@ $_thesisId = $_GET['id'] ?? null;
<nav aria-label="Navigation admin"> <nav aria-label="Navigation admin">
<ul class="nav-left-links"> <ul class="nav-left-links">
<li><a href="/" target="_blank" rel="noopener noreferrer" class="nav-logo"> <li><a href="/" target="_blank" rel="noopener noreferrer" class="nav-logo">
<img src="/assets/icons/sign-out.svg" width="16" height="16" alt="" aria-hidden="true">XAMXAM<span class="sr-only"> (site public, nouvel onglet)</span> <?= icon('sign-out') ?>XAMXAM<span class="sr-only"> (site public, nouvel onglet)</span>
</a></li> </a></li>
</ul> </ul>
<ul class="nav-right-links"> <ul class="nav-right-links">
@@ -29,7 +29,7 @@ $_thesisId = $_GET['id'] ?? null;
</a></li> </a></li>
<li><a href="/admin/parametres.php" <?= in_array($_currentPage, ['parametres.php', 'system.php', 'status.php', 'logs.php']) ? 'aria-current="page"' : '' ?>>Paramètres</a></li> <li><a href="/admin/parametres.php" <?= in_array($_currentPage, ['parametres.php', 'system.php', 'status.php', 'logs.php']) ? 'aria-current="page"' : '' ?>>Paramètres</a></li>
<?php if ($_isAdmin && AdminAuth::hasPassword()): ?> <?php if ($_isAdmin && AdminAuth::hasPassword()): ?>
<li data-nav-logout><a href="/admin/logout.php" aria-label="Déconnexion"><img src="/assets/icons/sign-in.svg" width="20" height="20" alt="" aria-hidden="true"><span class="sr-only">Déconnexion</span></a></li> <li data-nav-logout><a href="/admin/logout.php" aria-label="Déconnexion"><?= icon('sign-in') ?><span class="sr-only">Déconnexion</span></a></li>
<?php endif; ?> <?php endif; ?>
</ul> </ul>
</nav> </nav>
@@ -90,7 +90,7 @@ $_thesisId = $_GET['id'] ?? null;
<?php if ($_isAdmin && !$_isLogin): ?> <?php if ($_isAdmin && !$_isLogin): ?>
<div class="admin-mobile-block"> <div class="admin-mobile-block">
<img src="/assets/icons/desktop-monitor.svg" width="48" height="48" alt="" aria-hidden="true"> <?= icon('desktop-monitor') ?>
<h2>Section administrateur</h2> <h2>Section administrateur</h2>
<p>L'administration n'est pas accessible sur mobile. Veuillez utiliser un ordinateur.</p> <p>L'administration n'est pas accessible sur mobile. Veuillez utiliser un ordinateur.</p>
</div> </div>
@@ -106,7 +106,7 @@ $searchBarValue = $searchBarValue ?? $_GET['query'] ?? '';
role="search" aria-label="Recherche" class="header-search-form"> role="search" aria-label="Recherche" class="header-search-form">
<label for="site-search-input" class="sr-only">Recherche</label> <label for="site-search-input" class="sr-only">Recherche</label>
<div class="header-search-input-wrap"> <div class="header-search-input-wrap">
<img src="/assets/icons/search.svg" width="24" height="24" alt="" aria-hidden="true" class="header-search-icon"> <?= icon('search', 0, 'header-search-icon') ?>
<input <input
id="site-search-input" id="site-search-input"
type="text" type="text"

View File

@@ -100,7 +100,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
hx-swap="innerHTML" hx-swap="innerHTML"
hx-trigger="click" hx-trigger="click"
onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'cover', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };"> onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'cover', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };">
<img src="/assets/icons/magic-wand.svg" width="16" height="16" alt="" aria-hidden="true" style="vertical-align:-2px;margin-right:var(--space-3xs)"> Relier un fichier existant <?= icon('magic-wand') ?> Relier un fichier existant
</button> </button>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -128,7 +128,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
hx-swap="innerHTML" hx-swap="innerHTML"
hx-trigger="click" hx-trigger="click"
onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'note_intention', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };"> onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'note_intention', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };">
<img src="/assets/icons/magic-wand.svg" width="16" height="16" alt="" aria-hidden="true" style="vertical-align:-2px;margin-right:var(--space-3xs)"> Relier un fichier existant <?= icon('magic-wand') ?> Relier un fichier existant
</button> </button>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -166,7 +166,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
hx-swap="innerHTML" hx-swap="innerHTML"
hx-trigger="click" hx-trigger="click"
onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'tfe', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };"> onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'tfe', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };">
<img src="/assets/icons/magic-wand.svg" width="16" height="16" alt="" aria-hidden="true" style="vertical-align:-2px;margin-right:var(--space-3xs)"> Relier un fichier existant <?= icon('magic-wand') ?> Relier un fichier existant
</button> </button>
<?php if ($peerTubeEnabled): ?> <?php if ($peerTubeEnabled): ?>
<button type="button" class="btn btn--sm btn--ghost peertube-browser-trigger" <button type="button" class="btn btn--sm btn--ghost peertube-browser-trigger"
@@ -177,7 +177,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
hx-trigger="click" hx-trigger="click"
onclick="document.getElementById('peertube-relink-modal').showModal(); window.__xamxamPeertubeRelinkCtx = { thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };" onclick="document.getElementById('peertube-relink-modal').showModal(); window.__xamxamPeertubeRelinkCtx = { thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };"
> >
<img src="/assets/icons/magic-wand.svg" width="16" height="16" alt="" aria-hidden="true" style="vertical-align:-2px;margin-right:var(--space-3xs)"> Relier une vidéo PeerTube <?= icon('magic-wand') ?> Relier une vidéo PeerTube
</button> </button>
<?php endif; ?> <?php endif; ?>
<?php endif; ?> <?php endif; ?>
@@ -207,7 +207,7 @@ $websiteLabel = htmlspecialchars($_POST['website_label'] ?? '');
hx-swap="innerHTML" hx-swap="innerHTML"
hx-trigger="click" hx-trigger="click"
onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'annexe', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };"> onclick="document.getElementById('relink-modal').showModal(); window.__xamxamRelinkCtx = { queueType: 'annexe', thesisId: '<?= htmlspecialchars((string)($thesisId ?? $_GET['id'] ?? '')) ?>' };">
<img src="/assets/icons/magic-wand.svg" width="16" height="16" alt="" aria-hidden="true" style="vertical-align:-2px;margin-right:var(--space-3xs)"> Relier un fichier existant <?= icon('magic-wand') ?> Relier un fichier existant
</button> </button>
<?php endif; ?> <?php endif; ?>
</div> </div>

View File

@@ -65,7 +65,7 @@ $adminMode = $adminMode ?? false;
<br> <br>
</label> </label>
<details class="licence-details"> <details class="licence-details">
<summary class="licence-summary"> <img src="/assets/icons/circle-i.svg" width="1rem" height="16" alt="" aria-hidden="true"> Info</summary> <summary class="licence-summary"> <?= icon('circle-i') ?> Info</summary>
<p> <p>
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. 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.
</p> </p>
@@ -86,7 +86,7 @@ $adminMode = $adminMode ?? false;
</label> </label>
<br> <br>
<details class="licence-details"> <details class="licence-details">
<summary class="licence-summary"> <img src="/assets/icons/circle-i.svg" width="1rem" height="16" alt="" aria-hidden="true"> Info</summary> <summary class="licence-summary"> <?= icon('circle-i') ?> Info</summary>
<p> <p>
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. 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.
</p> </p>
@@ -109,7 +109,7 @@ $adminMode = $adminMode ?? false;
</label> </label>
<br> <br>
<details class="licence-details"> <details class="licence-details">
<summary class="licence-summary"> <img src="/assets/icons/circle-i.svg" width="1rem" height="16" alt="" aria-hidden="true"> Info</summary> <summary class="licence-summary"> <?= icon('circle-i') ?> Info</summary>
<p> <p>
Mon TFE n'est pas disponible en physique ni sur le site. Une note descriptive est disponible sur le site. Mon TFE n'est pas disponible en physique ni sur le site. Une note descriptive est disponible sur le site.
</p> </p>

View File

@@ -45,7 +45,7 @@ $langCount = count($selectedLanguages);
<input type="hidden" name="<?= htmlspecialchars($name) ?>[]" value="<?= htmlspecialchars($lang['name']) ?>"> <input type="hidden" name="<?= htmlspecialchars($name) ?>[]" value="<?= htmlspecialchars($lang['name']) ?>">
<span class="tag-pill-name"><?= htmlspecialchars($lang['name']) ?></span> <span class="tag-pill-name"><?= htmlspecialchars($lang['name']) ?></span>
<button type="button" class="tag-pill-remove" title="Retirer «&nbsp;<?= htmlspecialchars($lang['name']) ?>&nbsp;»" aria-label="Retirer <?= htmlspecialchars($lang['name']) ?>"> <button type="button" class="tag-pill-remove" title="Retirer «&nbsp;<?= htmlspecialchars($lang['name']) ?>&nbsp;»" aria-label="Retirer <?= htmlspecialchars($lang['name']) ?>">
<img src="/assets/icons/trash-slash.svg" width="16" height="16" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</span> </span>
<?php endforeach; ?> <?php endforeach; ?>

View File

@@ -48,7 +48,7 @@ $belowMin = $required && $tagCount < $minTags;
<input type="hidden" name="<?= htmlspecialchars($name) ?>[]" value="<?= htmlspecialchars($tag['name']) ?>"> <input type="hidden" name="<?= htmlspecialchars($name) ?>[]" value="<?= htmlspecialchars($tag['name']) ?>">
<span class="tag-pill-name"><?= htmlspecialchars($tag['name']) ?></span> <span class="tag-pill-name"><?= htmlspecialchars($tag['name']) ?></span>
<button type="button" class="tag-pill-remove" title="Retirer «&nbsp;<?= htmlspecialchars($tag['name']) ?>&nbsp;»" aria-label="Retirer <?= htmlspecialchars($tag['name']) ?>"> <button type="button" class="tag-pill-remove" title="Retirer «&nbsp;<?= htmlspecialchars($tag['name']) ?>&nbsp;»" aria-label="Retirer <?= htmlspecialchars($tag['name']) ?>">
<img src="/assets/icons/trash-slash.svg" width="16" height="16" alt="" aria-hidden="true"> <?= icon('trash-slash') ?>
</button> </button>
</span> </span>
<?php endforeach; ?> <?php endforeach; ?>

View File

@@ -6,7 +6,7 @@ $_sbValue = $searchBarValue ?? $_GET['query'] ?? '';
<form method="GET" action="/search" <form method="GET" action="/search"
role="search" aria-label="Recherche"> role="search" aria-label="Recherche">
<label for="site-search-input" class="sr-only">Recherche</label> <label for="site-search-input" class="sr-only">Recherche</label>
<img src="/assets/icons/search.svg" width="24" height="24" alt="" aria-hidden="true"> <?= icon('search') ?>
<input <input
id="site-search-input" id="site-search-input"
type="text" type="text"