diff --git a/TODO.md b/TODO.md
index d22e9c1..44cf614 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,5 +1,10 @@
# TODO
+## HTMX Toast Feedback for Settings Checkboxes (contenus.php)
+
+- [x] Add `hx-target` response divs to the three fieldsets in contenus.php
+- [x] Update settings.php to return HTML toast on HTMX requests
+
## SQLite Backup & Data Integrity (docs/backup-plan.md)
### Phase 1 — WAL Mode
diff --git a/app/public/admin/actions/settings.php b/app/public/admin/actions/settings.php
index 1133418..367200f 100644
--- a/app/public/admin/actions/settings.php
+++ b/app/public/admin/actions/settings.php
@@ -22,13 +22,37 @@ $isHxRequest = (isset($_SERVER['HTTP_HX_REQUEST']) && $_SERVER['HTTP_HX_REQUEST'
$section = $_POST['section'] ?? '';
error_log('[settings.php] PROCESS | section=' . $section . ' | post_keys=' . implode(',', array_keys($_POST)));
+/**
+ * Return an HTML toast fragment for HTMX responses and exit.
+ * The fragment auto-dismisses after 3 seconds via a script at the end.
+ */
+function hxToastSuccess(string $message): never {
+ http_response_code(200);
+ echo '
' .
+ '✓ ' .
+ htmlspecialchars($message) . '
' .
+ '';
+ exit;
+}
+
+function hxToastError(string $message): never {
+ http_response_code(200);
+ echo '' .
+ '⚠ ' .
+ htmlspecialchars($message) . '
' .
+ '';
+ exit;
+}
+
if ($section === 'formulaire_restrictions') {
// HTMX may not send unchecked checkboxes even with hidden 0-value inputs;
// missing key means unchecked → treat as '0'.
$newValues = ['restricted_files_enabled' => empty($_POST['restricted_files_enabled']) ? '0' : '1'];
$db->setSetting('restricted_files_enabled', $newValues['restricted_files_enabled']);
$logger->logFormSettingsUpdate($newValues);
- if (!$isHxRequest) {
+ if ($isHxRequest) {
+ hxToastSuccess('Restrictions d\'accès aux fichiers mises à jour.');
+ } else {
App::flash('success', "Paramètres mis à jour.");
}
} elseif ($section === 'formulaire_acces') {
@@ -44,7 +68,9 @@ if ($section === 'formulaire_restrictions') {
$newValues[$key] = $value;
}
$logger->logFormSettingsUpdate($newValues);
- if (!$isHxRequest) {
+ if ($isHxRequest) {
+ hxToastSuccess("Degrés d'ouverture mis à jour.");
+ } else {
App::flash('success', "Degrés d'ouverture mis à jour.");
}
} elseif ($section === 'objet_types') {
@@ -55,7 +81,9 @@ if ($section === 'formulaire_restrictions') {
$db->setSetting('objet_these_enabled', $newValues['objet_these_enabled']);
$db->setSetting('objet_frart_enabled', $newValues['objet_frart_enabled']);
$logger->logObjetTypesUpdate($newValues);
- if (!$isHxRequest) {
+ if ($isHxRequest) {
+ hxToastSuccess('Types de travaux mis à jour.');
+ } else {
App::flash('success', "Types de travaux mis à jour.");
}
} elseif ($section === 'smtp') {
@@ -109,9 +137,9 @@ if ($section === 'formulaire_restrictions') {
App::flash('error', "Section inconnue.");
}
+// Centralised HTMX response — each section above already called hxToast* and exited.
+// If we get here as an HTMX request from an unhandled section, return empty 200.
if ($isHxRequest) {
- // Auto-save from contenus.php — no CSRF rotation needed (token reused until full page load).
- // Return empty 200 so hx-swap="none" is a no-op.
http_response_code(200);
exit;
}
diff --git a/app/templates/admin/acces.php b/app/templates/admin/acces.php
index ab619bf..585b967 100644
--- a/app/templates/admin/acces.php
+++ b/app/templates/admin/acces.php
@@ -727,6 +727,19 @@
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\ to: sstzwlpk 0e83e8f7 "feat(deploy): upload deploy-server.sh, run migrations, fix migrate.sh server layout" (rebased revision)
++ $linkName = $link['name'] ?? '';
+++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: sstzwlpk 0e83e8f7 "feat(deploy): upload deploy-server.sh, run migrations, fix migrate.sh server layout" (rebased revision)
+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+- $linkName = $link['name'] ?? '';
+- $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
+\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: rxpvwzkt 8a49f872 "feat(admin): add htmx toast feedback for settings checkboxes in contenus.php" (rebased revision)
+ $linkName = $link['name'] ?? '';
+ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
+ $linkLockedYear = $link['locked_year'] ?? null;
++%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
++\\\\\\\ to: rxpvwzkt 7fac18bc "feat(admin): add htmx toast feedback for settings checkboxes in contenus.php" (rebased revision)
+++ $linkName = $link['name'] ?? '';
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
?>
diff --git a/app/templates/admin/contenus.php b/app/templates/admin/contenus.php
index 9d9d6b4..51de3fd 100644
--- a/app/templates/admin/contenus.php
+++ b/app/templates/admin/contenus.php
@@ -93,12 +93,12 @@
+
+