mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
admin: semantic HTML pass — checkbox fieldset, landmarks, dl/dt, autocomplete, inline styles
checkbox-list.php partial:
- Replace outer <div>/<label> with <div>/<span class="admin-row-label"> + inner
<fieldset class="admin-checkbox-group"><legend class="sr-only"> to satisfy
WCAG 1.3.1 (group label for multi-checkbox rows without duplicating visible text)
- Replace <div class="admin-checkbox-list"> with <ul>; each checkbox wrapped in <li>
admin.css:
- Drop .admin-checkbox-list; add .admin-body fieldset.admin-checkbox-group rules
(border/padding reset so it doesn't inherit jury-fieldset box styling)
- Extend form-row label rule to span.admin-row-label
- .admin-inline-form + .admin-inline-form { margin-top:.35rem } replaces inline style
- .admin-input--inline / .admin-select--inline get width:160px (was inline style)
- .admin-tags-count + table th sizing via :has() replaces th inline styles
login.php: wrap content in <main id="main-content"> (missing landmark)
account.php:
- <div class="admin-account-status"> → <dl>; __label <span> → <dt>
- <div class="admin-danger-zone__description"> → <p>
index.php: <div class="admin-maintenance-bar"> → <aside role="status" aria-label="Statut du site">
add.php / edit.php: autocomplete="name" on author field, autocomplete="email" on
contact field (WCAG 1.3.5 / input purpose)
tags.php: all inline style= attributes removed (width, text-align, margin-top,
display:inline); all moved to CSS classes
This commit is contained in:
@@ -23,15 +23,17 @@ if (empty($_SESSION['csrf_token'])) {
|
||||
<?php include APP_ROOT . '/templates/partials/flash-messages.php'; ?>
|
||||
|
||||
<!-- Status info -->
|
||||
<div class="admin-account-status">
|
||||
<dl class="admin-account-status">
|
||||
<div class="admin-account-status__row">
|
||||
<span class="admin-account-status__label">Authentification PHP</span>
|
||||
<?php $badgeType = 'ok'; $badgeValue = $hasPassword; $badgeOkLabel = 'Active'; $badgeWarnLabel = 'Non configurée'; include APP_ROOT . '/templates/partials/status-badge.php'; ?>
|
||||
<dt class="admin-account-status__label">Authentification PHP</dt>
|
||||
<dd><?php $badgeType = 'ok'; $badgeValue = $hasPassword; $badgeOkLabel = 'Active'; $badgeWarnLabel = 'Non configurée'; include APP_ROOT . '/templates/partials/status-badge.php'; ?></dd>
|
||||
</div>
|
||||
<div class="admin-account-status__row">
|
||||
<span class="admin-account-status__label">Fichier de configuration</span>
|
||||
<code class="admin-account-status__code">config/admin_credentials.php</code>
|
||||
<?php $badgeType = 'ok'; $badgeValue = file_exists($credentialsFile); $badgeOkLabel = 'Présent'; $badgeWarnLabel = 'Absent'; include APP_ROOT . '/templates/partials/status-badge.php'; ?>
|
||||
<dt class="admin-account-status__label">Fichier de configuration</dt>
|
||||
<dd>
|
||||
<code class="admin-account-status__code">config/admin_credentials.php</code>
|
||||
<?php $badgeType = 'ok'; $badgeValue = file_exists($credentialsFile); $badgeOkLabel = 'Présent'; $badgeWarnLabel = 'Absent'; include APP_ROOT . '/templates/partials/status-badge.php'; ?>
|
||||
</dd>
|
||||
</div>
|
||||
<?php if (!$hasPassword): ?>
|
||||
<p class="admin-account-status__note">
|
||||
@@ -39,7 +41,7 @@ if (empty($_SESSION['csrf_token'])) {
|
||||
<code>config/admin_credentials.php</code> avec un hash bcrypt.
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<!-- Password change form -->
|
||||
<h2 class="admin-section-title"><?= $hasPassword ? 'Changer le mot de passe' : 'Définir le mot de passe' ?></h2>
|
||||
@@ -86,13 +88,13 @@ if (empty($_SESSION['csrf_token'])) {
|
||||
<!-- Danger zone: remove password -->
|
||||
<h2 class="admin-section-title admin-section-title--danger">Zone de danger</h2>
|
||||
<div class="admin-danger-zone">
|
||||
<div class="admin-danger-zone__description">
|
||||
<p class="admin-danger-zone__description">
|
||||
<strong>Supprimer la configuration du mot de passe PHP</strong><br>
|
||||
<small>
|
||||
Supprime <code>config/admin_credentials.php</code>. L'accès admin
|
||||
dépendra uniquement de l'authentification nginx Basic Auth si elle est configurée.
|
||||
</small>
|
||||
</div>
|
||||
</p>
|
||||
<form method="post" action="/admin/actions/account.php"
|
||||
onsubmit="return confirm('Supprimer le fichier de mot de passe PHP ? L\'accès admin ne sera protégé que par nginx Basic Auth.')">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
|
||||
@@ -52,8 +52,8 @@ function wasSelected($key, $value) {
|
||||
|
||||
<?php $name = 'titre'; $label = 'Titre :'; $value = old('titre'); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'subtitle'; $label = 'Sous-titre (si applicable) :'; $value = old('subtitle'); $required = false; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = old('auteurice'); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = old('mail'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = old('auteurice'); $required = true; $attrs = ['autocomplete' => 'name']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = old('mail'); $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<?php require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?>
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ try {
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="thesis_id" value="<?= $thesisId ?>">
|
||||
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = htmlspecialchars($thesis['authors']); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact :'; $value = ''; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = htmlspecialchars($thesis['authors']); $required = true; $attrs = ['autocomplete' => 'name']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact :'; $value = ''; $attrs = ['autocomplete' => 'email']; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<?php
|
||||
$name = 'année'; $label = 'Année :'; $value = htmlspecialchars((string)$thesis['year']); $required = true;
|
||||
|
||||
@@ -71,7 +71,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
<!-- Maintenance mode toggle -->
|
||||
<?php $maintenanceOn = file_exists(APP_ROOT . '/storage/maintenance.flag'); ?>
|
||||
<div class="admin-maintenance-bar <?= $maintenanceOn ? 'admin-maintenance-bar--active' : '' ?>">
|
||||
<aside role="status" class="admin-maintenance-bar <?= $maintenanceOn ? 'admin-maintenance-bar--active' : '' ?>" aria-label="Statut du site">
|
||||
<?php if ($maintenanceOn): ?>
|
||||
<span>⚠ Mode maintenance <strong>activé</strong> — le site public est inaccessible.</span>
|
||||
<form method="post" action="actions/maintenance.php" style="display:inline;">
|
||||
@@ -90,7 +90,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Stats (always reflects full DB, independent of active filters) -->
|
||||
<dl class="admin-stats">
|
||||
|
||||
@@ -26,6 +26,7 @@ $pageTitle = 'Connexion';
|
||||
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
|
||||
<?php include APP_ROOT . '/templates/header.php'; ?>
|
||||
|
||||
<main id="main-content">
|
||||
<div class="admin-login-wrap">
|
||||
<div class="admin-login-box">
|
||||
<h2>Administration</h2>
|
||||
@@ -43,5 +44,6 @@ $pageTitle = 'Connexion';
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|
||||
|
||||
@@ -31,16 +31,16 @@ try {
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style="width:40%;">Nom</th>
|
||||
<th scope="col" style="width:12%;text-align:center;">TFE associés</th>
|
||||
<th scope="col" style="width:48%;">Actions</th>
|
||||
<th scope="col">Nom</th>
|
||||
<th scope="col">TFE associés</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tags as $tag): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($tag['name']) ?></td>
|
||||
<td style="text-align:center;"><?= (int)$tag['thesis_count'] ?></td>
|
||||
<td class="admin-tags-count"><?= (int)$tag['thesis_count'] ?></td>
|
||||
<td>
|
||||
<!-- Rename -->
|
||||
<form method="post" action="actions/tag.php" class="admin-inline-form">
|
||||
@@ -48,16 +48,16 @@ try {
|
||||
<input type="hidden" name="action" value="rename">
|
||||
<input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>">
|
||||
<input class="admin-input--inline" type="text" name="new_name"
|
||||
value="<?= htmlspecialchars($tag['name']) ?>" required style="width:160px;">
|
||||
value="<?= htmlspecialchars($tag['name']) ?>" required>
|
||||
<button type="submit" class="admin-btn admin-btn--sm">Renommer</button>
|
||||
</form>
|
||||
|
||||
<!-- Merge into another tag -->
|
||||
<form method="post" action="actions/tag.php" class="admin-inline-form" style="margin-top:.35rem;">
|
||||
<form method="post" action="actions/tag.php" class="admin-inline-form">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="action" value="merge">
|
||||
<input type="hidden" name="source_id" value="<?= (int)$tag['id'] ?>">
|
||||
<select name="target_id" class="admin-select--inline" style="width:160px;" required>
|
||||
<select name="target_id" class="admin-select--inline" required>
|
||||
<option value="">— Fusionner dans… —</option>
|
||||
<?php foreach ($tags as $other): ?>
|
||||
<?php if ($other['id'] !== $tag['id']): ?>
|
||||
@@ -72,7 +72,7 @@ try {
|
||||
</form>
|
||||
|
||||
<!-- Delete -->
|
||||
<form method="post" action="actions/tag.php" class="admin-inline-form" style="margin-top:.35rem;display:inline;">
|
||||
<form method="post" action="actions/tag.php" class="admin-inline-form">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="tag_id" value="<?= (int)$tag['id'] ?>">
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
border-bottom: 1px solid var(--border-primary);
|
||||
}
|
||||
|
||||
.admin-form > div:not(.admin-submit-wrap) > label {
|
||||
.admin-form > div:not(.admin-submit-wrap) > label,
|
||||
.admin-form > div:not(.admin-submit-wrap) > span.admin-row-label {
|
||||
font-size: 0.92rem;
|
||||
padding-top: 0.5rem;
|
||||
font-weight: 400;
|
||||
@@ -140,12 +141,28 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Checkboxes */
|
||||
.admin-checkbox-list {
|
||||
/* Checkbox group fieldset (languages, formats)
|
||||
Wraps the <ul> of checkboxes; the visible label is a sibling <span>
|
||||
in the grid row. The <legend> repeats the label text for AT only (sr-only).
|
||||
.admin-body scope ensures this overrides the generic .admin-body fieldset rule. */
|
||||
.admin-body fieldset.admin-checkbox-group {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.admin-body fieldset.admin-checkbox-group > ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding-top: 0.3rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
padding-top: 0.3rem;
|
||||
}
|
||||
|
||||
.admin-body fieldset.admin-checkbox-group > ul > li {
|
||||
display: contents; /* let the inner label handle layout */
|
||||
}
|
||||
|
||||
.admin-checkbox-label {
|
||||
@@ -754,13 +771,26 @@
|
||||
.admin-input--inline,
|
||||
.admin-inline-form input[type="text"] {
|
||||
font-size: 0.82rem;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.admin-select--inline,
|
||||
.admin-inline-form select {
|
||||
font-size: 0.82rem;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
/* Stack secondary forms (merge, delete) below the rename form */
|
||||
.admin-inline-form + .admin-inline-form {
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
/* Tags table column sizing */
|
||||
.admin-body table:has(.admin-tags-count) th:nth-child(1) { width: 40%; }
|
||||
.admin-body table:has(.admin-tags-count) th:nth-child(2) { width: 12%; }
|
||||
.admin-body table:has(.admin-tags-count) th:nth-child(3) { width: 48%; }
|
||||
.admin-tags-count { text-align: center; }
|
||||
|
||||
/* ── Banner preview ─────────────────────────────────────────────────────── */
|
||||
.admin-banner-preview img {
|
||||
max-width: 320px;
|
||||
|
||||
Reference in New Issue
Block a user