From ae6d9b86b32a2744de8c7c5e620d33e39270f782 Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Mon, 4 May 2026 17:52:30 +0200 Subject: [PATCH] Replace browser alert/confirm dialogs with modals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - admin/index.php: alert() → no-selection dialog; confirm() bulk actions → bulk-confirm/bulk-delete dialogs; confirm() single delete → delete-thesis dialog; removed redundant confirm on Dépublier (reversible action) - admin/tags.php: confirm() merge/delete → merge-tag/delete-tag dialogs - admin/acces-etudiante.php: confirm() delete link → delete-link dialog - admin/acces.php: confirm() archive link → archive-link dialog - admin/parametres.php: confirm() maintenance/delete-all → enable-maintenance/delete-all-tfe dialogs; admin password confirm() kept with TODO comment - admin/account.php: admin password confirm() kept with TODO comment - admin.css: add .admin-dialog--sm, .admin-dialog__alert, .admin-dialog__footer styles --- TODO.md | 9 ++ app/public/assets/css/admin.css | 21 +++++ app/storage/logs/admin.log | 1 + app/storage/maintenance.flag | 1 + app/templates/admin/acces-etudiante.php | 31 ++++++- app/templates/admin/acces.php | 37 +++++++- app/templates/admin/account.php | 1 + app/templates/admin/index.php | 117 ++++++++++++++++++++++-- app/templates/admin/parametres.php | 61 ++++++++++-- app/templates/admin/tags.php | 65 ++++++++++++- 10 files changed, 313 insertions(+), 31 deletions(-) create mode 100644 app/storage/logs/admin.log create mode 100644 app/storage/maintenance.flag diff --git a/TODO.md b/TODO.md index 4c9253a..5c5c76a 100644 --- a/TODO.md +++ b/TODO.md @@ -36,6 +36,15 @@ - [x] `templates/admin/acces.php` — archive button, archived links collapsible section - [x] `scripts/setup-server.sh` — provision `/var/log/xamxam.log` with correct ownership +## Replace browser dialogs with `` modals +- [x] `admin/index.php` — `alert()` (no selection) → ``; `confirm()` bulk publish/unpublish → ``; `confirm()` bulk delete → ``; `confirm()` single delete → ``; inline `confirm()` on Dépublier button removed (no confirmation needed for reversible action) +- [x] `admin/tags.php` — `confirm()` merge → ``; `confirm()` delete → `` +- [x] `admin/acces-etudiante.php` — `confirm()` delete link → `` +- [x] `admin/acces.php` — `confirm()` archive link → `` +- [x] `admin/parametres.php` — `confirm()` enable maintenance → ``; `confirm()` delete all TFE → ``; admin password `confirm()` kept with `TODO` comment +- [x] `admin/account.php` — admin password `confirm()` kept with `TODO` comment +- [x] `admin.css` — added `.admin-dialog--sm`, `.admin-dialog__alert`, `.admin-dialog__footer` styles + ## Duplicate warning display fixes - [x] `toast-fragment.php` — 204 guard now also checks `warning`; warning was silently discarded before - [x] `partage/index.php` — warning stored as plain text (no pre-escaping); `htmlspecialchars()` applied once at render; was double-encoded before diff --git a/app/public/assets/css/admin.css b/app/public/assets/css/admin.css index 8d64998..8800b1e 100644 --- a/app/public/assets/css/admin.css +++ b/app/public/assets/css/admin.css @@ -915,6 +915,27 @@ padding-bottom: var(--space-m); } +/* Small/confirmation dialog variant */ +.admin-dialog--sm { + max-width: 420px; +} + +.admin-dialog__alert { + padding: var(--space-m) var(--space-l); + font-size: var(--step--1); + line-height: 1.6; +} + +.admin-dialog__alert p { + margin: 0; +} + +.admin-dialog__footer { + display: flex; + gap: var(--space-xs); + padding: 0 var(--space-l) var(--space-m); +} + /* ── Import results log ─────────────────────────────────────────────── */ .admin-import-log { list-style: none; diff --git a/app/storage/logs/admin.log b/app/storage/logs/admin.log new file mode 100644 index 0000000..e6a8d9e --- /dev/null +++ b/app/storage/logs/admin.log @@ -0,0 +1 @@ +{"timestamp":"2026-05-04T15:36:30+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0","resource":"system","action":"maintenance_on","status":"success"} diff --git a/app/storage/maintenance.flag b/app/storage/maintenance.flag new file mode 100644 index 0000000..cb8489c --- /dev/null +++ b/app/storage/maintenance.flag @@ -0,0 +1 @@ +2026-05-04T15:36:30+00:00 \ No newline at end of file diff --git a/app/templates/admin/acces-etudiante.php b/app/templates/admin/acces-etudiante.php index b2ae72d..b3d39d8 100644 --- a/app/templates/admin/acces-etudiante.php +++ b/app/templates/admin/acces-etudiante.php @@ -95,11 +95,12 @@ 🔑
+ id="delete-link-form-"> -
@@ -180,6 +181,16 @@ document.getElementById('open-create-dialog').addEventListener('click', () => { document.getElementById('create-dialog').showModal(); }); +let _pendingDeleteLinkId = null; +function openDeleteLinkDialog(id) { + _pendingDeleteLinkId = id; + document.getElementById('delete-link-dialog').showModal(); +} +function _executeDeleteLink() { + const form = document.getElementById('delete-link-form-' + _pendingDeleteLinkId); + if (form) form.submit(); +} + function copyUrl(id) { const input = document.getElementById('url-' + id); navigator.clipboard.writeText(input.value).then(() => { @@ -199,3 +210,19 @@ function openPasswordDialog(id, hasPassword) { document.getElementById('password-dialog').showModal(); } + + + +
+ + +
+
+

Supprimer ce lien ? Les soumissions via ce lien seront bloquées.

+
+ +
diff --git a/app/templates/admin/acces.php b/app/templates/admin/acces.php index 510d916..9cdfbbe 100644 --- a/app/templates/admin/acces.php +++ b/app/templates/admin/acces.php @@ -15,7 +15,7 @@ -

Aucun lien d'accès créé. Cliquez sur « Créer un lien » pour générer un lien partageable.

+

Aucun lien d'accès créé. Cliquez sur « Créer un lien » pour générer un lien partageable.

@@ -38,7 +38,7 @@ $statusLabel = $isExpired ? 'Expiré' : ($link['is_active'] ? 'Actif' : 'Désactivé'); $fullUrl = $baseUrl . '/partage/' . htmlspecialchars($link['slug']); $created = date('d/m/Y H:i', strtotime($link['created_at'])); - $expires = $link['expires_at'] ? date('d/m/Y', strtotime($link['expires_at'])) : '—'; + $expires = $link['expires_at'] ? date('d/m/Y', strtotime($link['expires_at'])) : '-'; $hasLinkPassword = !empty($link['password_hash']); ?> @@ -92,11 +92,12 @@ 🔑 + id="archive-link-form-"> - @@ -127,7 +128,7 @@
@@ -433,4 +434,30 @@ function openRejectDialog(requestId) { document.getElementById('reject-request-id').value = requestId; document.getElementById('reject-dialog').showModal(); } + +let _pendingArchiveLinkId = null; +function openArchiveLinkDialog(id) { + _pendingArchiveLinkId = id; + document.getElementById('archive-link-dialog').showModal(); +} +function _executeArchiveLink() { + const form = document.getElementById('archive-link-form-' + _pendingArchiveLinkId); + if (form) form.submit(); +} + + + +
+ + +
+
+

Archiver ce lien ? Il ne sera plus accessible, mais les statistiques seront conservées.

+
+ +
diff --git a/app/templates/admin/account.php b/app/templates/admin/account.php index e689c96..8dce07a 100644 --- a/app/templates/admin/account.php +++ b/app/templates/admin/account.php @@ -74,6 +74,7 @@ dépendra uniquement de l'authentification nginx Basic Auth si elle est configurée.

+ modal like the other confirmations */ ?>
diff --git a/app/templates/admin/index.php b/app/templates/admin/index.php index 0d506c3..71d1cb0 100644 --- a/app/templates/admin/index.php +++ b/app/templates/admin/index.php @@ -9,19 +9,40 @@ function updateBulk() { document.getElementById('selected-count').textContent = checked.length; bulk.style.display = checked.length > 0 ? 'flex' : 'none'; } + +// Pending bulk action state +let _pendingBulkAction = null; + function bulkAction(action) { const checked = document.querySelectorAll('input[name="selected_theses[]"]:checked'); - if (!checked.length) { alert('Sélectionnez au moins un TFE.'); return; } + if (!checked.length) { + document.getElementById('no-selection-dialog').showModal(); + return; + } + _pendingBulkAction = action; let word, endpoint; - if (action === 'publish') { word = 'publier'; endpoint = 'actions/publish.php'; } - else if (action === 'unpublish') { word = 'dépublier'; endpoint = 'actions/publish.php'; } - else if (action === 'delete') { word = 'supprimer'; endpoint = 'actions/delete.php'; } + if (action === 'publish') { word = 'publier'; endpoint = 'actions/publish.php'; } + else if (action === 'unpublish') { word = 'dépublier'; endpoint = 'actions/publish.php'; } + else if (action === 'delete') { word = 'supprimer'; endpoint = 'actions/delete.php'; } else return; if (action === 'delete') { - if (!confirm(`Supprimer définitivement ${checked.length} TFE(s) ? Cette action est irréversible.`)) return; + document.getElementById('bulk-delete-count').textContent = checked.length; + document.getElementById('bulk-delete-dialog').showModal(); } else { - if (!confirm(`${word.charAt(0).toUpperCase()+word.slice(1)} ${checked.length} TFE(s) ?`)) return; + document.getElementById('bulk-confirm-word').textContent = word.charAt(0).toUpperCase() + word.slice(1); + document.getElementById('bulk-confirm-count').textContent = checked.length; + document.getElementById('bulk-confirm-dialog').showModal(); } +} + +function _executeBulkAction() { + const action = _pendingBulkAction; + if (!action) return; + let endpoint; + if (action === 'publish' || action === 'unpublish') { endpoint = 'actions/publish.php'; } + else if (action === 'delete') { endpoint = 'actions/delete.php'; } + else return; + const checked = document.querySelectorAll('input[name="selected_theses[]"]:checked'); document.getElementById('bulk-action-input').value = action; document.getElementById('bulk-form').action = endpoint; const container = document.getElementById('bulk-checkboxes'); @@ -33,11 +54,21 @@ function bulkAction(action) { }); document.getElementById('bulk-form').submit(); } + +// Pending single-delete state +let _pendingDeleteId = null; + function deleteThesis(id, title) { - if (!confirm(`Supprimer « ${title} » ?\nCette action est irréversible.`)) return; - const form = document.getElementById('delete-form-' + id); + _pendingDeleteId = id; + document.getElementById('delete-thesis-title').textContent = title; + document.getElementById('delete-thesis-dialog').showModal(); +} + +function _executeDeleteThesis() { + const form = document.getElementById('delete-form-' + _pendingDeleteId); if (form) form.submit(); } + document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('input[name="selected_theses[]"]').forEach(cb => cb.addEventListener('change', updateBulk)); }); @@ -202,8 +233,7 @@ document.addEventListener('DOMContentLoaded', () => { - + @@ -236,6 +266,73 @@ document.addEventListener('DOMContentLoaded', () => { ?> + + + + +
+

Aucune sélection

+ +
+
+

Sélectionnez au moins un TFE avant d'effectuer une action groupée.

+
+ +
+ + + +
+

Confirmation

+ +
+
+

TFE(s) ?

+
+ +
+ + + +
+

Supprimer des TFE

+ +
+
+

Supprimer définitivement TFE(s) ? Cette action est irréversible.

+
+ +
+ + + +
+

Supprimer ce TFE

+ +
+
+

Supprimer «  » ? Cette action est irréversible.

+
+ +
+ diff --git a/app/templates/admin/parametres.php b/app/templates/admin/parametres.php index 52587b4..0044005 100644 --- a/app/templates/admin/parametres.php +++ b/app/templates/admin/parametres.php @@ -20,12 +20,12 @@

Site public : en ligne

-
+ -
@@ -50,12 +50,14 @@ Supprime définitivement tous les TFE de la base de données, y compris auteurs, promoteurs, tags, fichiers associés. Cette action est irréversible.

-
- - - -
+
+ + + +
@@ -377,8 +379,9 @@ Supprime le hash de la base de données. L'accès admin dépendra uniquement de l'authentification nginx Basic Auth si elle est configurée.

+ modal like the other confirmations */ ?>
> + onsubmit="return confirm('Supprimer le mot de passe PHP ? L\'accès admin ne sera protégé que par nginx Basic Auth.')"> @@ -584,3 +587,41 @@ document.body.addEventListener('htmx:afterSwap', function(evt) { } }); + + + +
+

Activer la maintenance

+ +
+
+

Mettre le site en maintenance ? Les visiteurs verront une page 503.

+
+ +
+ + + +
+

Supprimer tous les TFE

+ +
+
+

⚠️ Supprimer définitivement TOUS les TFE ? Cette action est IRRÉVERSIBLE.

+
+ +
diff --git a/app/templates/admin/tags.php b/app/templates/admin/tags.php index 0b490a2..f1cedd2 100644 --- a/app/templates/admin/tags.php +++ b/app/templates/admin/tags.php @@ -1,3 +1,28 @@ + +

Mots-clés ()

@@ -38,8 +63,8 @@ - @@ -49,8 +74,8 @@ - @@ -60,3 +85,35 @@
+ + + +
+

Fusionner le tag

+ +
+
+

Fusionner ce tag dans «  » ? Le tag source sera supprimé.

+
+ +
+ + + +
+

Supprimer le tag

+ +
+
+

Supprimer «  » ? Cette action est irréversible.

+
+ +