Replace browser alert/confirm dialogs with <dialog> modals

- 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
This commit is contained in:
Pontoporeia
2026-05-04 17:52:30 +02:00
parent ca5983075d
commit ae6d9b86b3
10 changed files with 313 additions and 31 deletions

View File

@@ -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 `<dialog>` modals
- [x] `admin/index.php``alert()` (no selection) → `<dialog id="no-selection-dialog">`; `confirm()` bulk publish/unpublish → `<dialog id="bulk-confirm-dialog">`; `confirm()` bulk delete → `<dialog id="bulk-delete-dialog">`; `confirm()` single delete → `<dialog id="delete-thesis-dialog">`; inline `confirm()` on Dépublier button removed (no confirmation needed for reversible action)
- [x] `admin/tags.php``confirm()` merge → `<dialog id="merge-tag-dialog">`; `confirm()` delete → `<dialog id="delete-tag-dialog">`
- [x] `admin/acces-etudiante.php``confirm()` delete link → `<dialog id="delete-link-dialog">`
- [x] `admin/acces.php``confirm()` archive link → `<dialog id="archive-link-dialog">`
- [x] `admin/parametres.php``confirm()` enable maintenance → `<dialog id="enable-maintenance-dialog">`; `confirm()` delete all TFE → `<dialog id="delete-all-tfe-dialog">`; 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

View File

@@ -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;

View File

@@ -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"}

View File

@@ -0,0 +1 @@
2026-05-04T15:36:30+00:00

View File

@@ -95,11 +95,12 @@
🔑
</button>
<form method="post" action="actions/acces-etudiante.php" class="publish-form"
onsubmit="return confirm('Supprimer ce lien ? Les soumissions via ce lien seront bloquées.')">
id="delete-link-form-<?= $link['id'] ?>">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= $link['id'] ?>">
<button type="submit" class="admin-btn-sm admin-btn-delete" title="Supprimer">
<button type="button" class="admin-btn-sm admin-btn-delete" title="Supprimer"
onclick="openDeleteLinkDialog(<?= $link['id'] ?>)">
🗑
</button>
</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();
}
</script>
<!-- Delete link confirm -->
<dialog id="delete-link-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="delete-link-title">
<div class="admin-dialog__header">
<h2 id="delete-link-title">Supprimer ce lien</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Supprimer ce lien ? Les soumissions via ce lien seront bloquées.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--danger" onclick="this.closest('dialog').close(); _executeDeleteLink()">Supprimer</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>

View File

@@ -15,7 +15,7 @@
</div>
<?php if (empty($links)): ?>
<p class="admin-empty">Aucun lien d'accès créé. Cliquez sur «Créer un lien» pour générer un lien partageable.</p>
<p class="admin-empty">Aucun lien d'accès créé. Cliquez sur « Créer un lien » pour générer un lien partageable.</p>
<?php else: ?>
<table>
<thead>
@@ -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']);
?>
<tr>
@@ -92,11 +92,12 @@
🔑
</button>
<form method="post" action="actions/acces-etudiante.php" class="publish-form"
onsubmit="return confirm('Archiver ce lien? Il ne sera plus accessible, mais les statistiques seront conservées.')">
id="archive-link-form-<?= $link['id'] ?>">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="action" value="archive">
<input type="hidden" name="id" value="<?= $link['id'] ?>">
<button type="submit" class="admin-btn-sm admin-btn-delete" title="Archiver">
<button type="button" class="admin-btn-sm admin-btn-delete" title="Archiver"
onclick="openArchiveLinkDialog(<?= $link['id'] ?>)">
🗄
</button>
</form>
@@ -127,7 +128,7 @@
<?php foreach ($archivedLinks as $link): ?>
<?php
$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'])) : '-';
?>
<tr>
<td>
@@ -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();
}
</script>
<!-- Archive link confirm -->
<dialog id="archive-link-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="archive-link-title">
<div class="admin-dialog__header">
<h2 id="archive-link-title">Archiver ce lien</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Archiver ce lien ? Il ne sera plus accessible, mais les statistiques seront conservées.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--warning" onclick="this.closest('dialog').close(); _executeArchiveLink()">Archiver</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>

View File

@@ -74,6 +74,7 @@
dépendra uniquement de l'authentification nginx Basic Auth si elle est configurée.
</small>
</p>
<?php /* TODO: replace this browser confirm() with a proper <dialog> modal like the other confirmations */ ?>
<form method="post" action="/admin/actions/account.php"
onsubmit="return confirm('Supprimer le 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']) ?>">

View File

@@ -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'; }
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', () => {
<input type="hidden" name="thesis_id" value="<?= $thesis['id'] ?>">
<?php if ($thesis['is_published']): ?>
<input type="hidden" name="action" value="unpublish">
<button type="submit" class="admin-btn-sm admin-btn-unpublish"
onclick="return confirm('Retirer de la publication ?')">Dépublier</button>
<button type="submit" class="admin-btn-sm admin-btn-unpublish">Dépublier</button>
<?php else: ?>
<input type="hidden" name="action" value="publish">
<button type="submit" class="admin-btn-sm admin-btn-publish">Publier</button>
@@ -236,6 +266,73 @@ document.addEventListener('DOMContentLoaded', () => {
?>
</main>
<!-- ══════════════════════════════════════════════════════════════
CONFIRM DIALOGS (replacing browser alert/confirm)
══════════════════════════════════════════════════════════════ -->
<!-- No-selection alert -->
<dialog id="no-selection-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="no-sel-title">
<div class="admin-dialog__header">
<h2 id="no-sel-title">Aucune sélection</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Sélectionnez au moins un TFE avant d'effectuer une action groupée.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn" onclick="this.closest('dialog').close()">OK</button>
</div>
</dialog>
<!-- Bulk publish/unpublish confirm -->
<dialog id="bulk-confirm-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="bulk-confirm-title">
<div class="admin-dialog__header">
<h2 id="bulk-confirm-title">Confirmation</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p><span id="bulk-confirm-word"></span> <span id="bulk-confirm-count"></span> TFE(s) ?</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn" onclick="this.closest('dialog').close(); _executeBulkAction()">Confirmer</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>
<!-- Bulk delete confirm -->
<dialog id="bulk-delete-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="bulk-delete-title">
<div class="admin-dialog__header">
<h2 id="bulk-delete-title">Supprimer des TFE</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Supprimer définitivement <strong><span id="bulk-delete-count"></span> TFE(s)</strong> ? Cette action est irréversible.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--danger" onclick="this.closest('dialog').close(); _executeBulkAction()">Supprimer</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>
<!-- Single thesis delete confirm -->
<dialog id="delete-thesis-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="delete-thesis-title-label">
<div class="admin-dialog__header">
<h2 id="delete-thesis-title-label">Supprimer ce TFE</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Supprimer « <strong id="delete-thesis-title"></strong> » ? Cette action est irréversible.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--danger" onclick="this.closest('dialog').close(); _executeDeleteThesis()">Supprimer</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>
<!-- ══════════════════════════════════════════════════════════════
IMPORT DIALOG
══════════════════════════════════════════════════════════════ -->

View File

@@ -20,12 +20,12 @@
</form>
<?php else: ?>
<p>Site public : <strong>en ligne</strong></p>
<form method="post" action="actions/maintenance.php">
<form method="post" action="actions/maintenance.php" id="enable-maintenance-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="action" value="enable_maintenance">
<input type="hidden" name="redirect" value="/admin/parametres.php">
<button type="submit" class="param-btn-warning"
onclick="return confirm('Mettre le site en maintenance ? Les visiteurs verront une page 503.')">
<button type="button" class="param-btn-warning"
onclick="document.getElementById('enable-maintenance-dialog').showModal()">
Activer la maintenance
</button>
</form>
@@ -50,11 +50,13 @@
Supprime définitivement tous les TFE de la base de données, y compris auteurs,
promoteurs, tags, fichiers associés. Cette action est <strong>irréversible</strong>.
</p>
<form method="post" action="actions/delete.php"
onsubmit="return confirm('⚠ Supprimer définitivement TOUS les TFE ? Cette action est IRRÉVERSIBLE.')">
<form method="post" action="actions/delete.php" id="delete-all-tfe-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<input type="hidden" name="delete_all" value="1">
<button type="submit" class="param-btn-danger">Supprimer tous les TFE (<?= $stats['total'] ?? '?' ?>)</button>
<button type="button" class="param-btn-danger"
onclick="document.getElementById('delete-all-tfe-dialog').showModal()">
Supprimer tous les TFE (<?= $stats['total'] ?? '?' ?>)
</button>
</form>
</fieldset>
</section>
@@ -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.
</p>
<?php /* TODO: replace this browser confirm() with a proper <dialog> modal like the other confirmations */ ?>
<form method="post" action="/admin/actions/account.php"
onsubmit="return confirm('Supprimer le mot de passe PHP ? L\'accès admin ne sera protégé que par nginx Basic Auth.')">>
onsubmit="return confirm('Supprimer le 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']) ?>">
<input type="hidden" name="action" value="remove_credentials">
<input type="hidden" name="redirect" value="/admin/parametres.php">
@@ -584,3 +587,41 @@ document.body.addEventListener('htmx:afterSwap', function(evt) {
}
});
</script>
<!-- Enable maintenance confirm -->
<dialog id="enable-maintenance-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="enable-maint-title">
<div class="admin-dialog__header">
<h2 id="enable-maint-title">Activer la maintenance</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Mettre le site en maintenance ? Les visiteurs verront une page 503.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--warning"
onclick="this.closest('dialog').close(); document.getElementById('enable-maintenance-form').submit()">
Activer
</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>
<!-- Delete all TFE confirm -->
<dialog id="delete-all-tfe-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="delete-all-title">
<div class="admin-dialog__header">
<h2 id="delete-all-title">Supprimer tous les TFE</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>⚠️ Supprimer définitivement <strong>TOUS les TFE</strong> ? Cette action est <strong>IRRÉVERSIBLE</strong>.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--danger"
onclick="this.closest('dialog').close(); document.getElementById('delete-all-tfe-form').submit()">
Supprimer tout
</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>

View File

@@ -1,3 +1,28 @@
<script>
let _pendingTagForm = null;
function confirmMergeTag(btn) {
const form = btn.closest('form');
const select = form.querySelector('select[name="target_id"]');
const targetName = select.options[select.selectedIndex]?.text ?? '';
if (!select.value) { return true; } // let HTML validation handle empty
_pendingTagForm = form;
document.getElementById('merge-target-name').textContent = targetName;
document.getElementById('merge-tag-dialog').showModal();
return false;
}
function confirmDeleteTag(btn, name) {
_pendingTagForm = btn.closest('form');
document.getElementById('delete-tag-name').textContent = name;
document.getElementById('delete-tag-dialog').showModal();
}
function _submitPendingTagForm() {
if (_pendingTagForm) _pendingTagForm.submit();
}
</script>
<main id="main-content">
<h1>Mots-clés (<?= count($tags) ?>)</h1>
@@ -38,8 +63,8 @@
<?php endif; ?>
<?php endforeach; ?>
</select>
<button type="submit" class="admin-btn admin-btn--sm admin-btn--warning"
onclick="return confirm('Fusionner ce tag dans la cible ? Le tag source sera supprimé.')">
<button type="button" class="admin-btn admin-btn--sm admin-btn--warning"
onclick="return confirmMergeTag(this)">
Fusionner
</button>
</form>
@@ -49,8 +74,8 @@
<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'] ?>">
<button type="submit" class="admin-btn admin-btn--sm admin-btn--danger"
onclick="return confirm('Supprimer le tag « <?= htmlspecialchars(addslashes($tag['name'])) ?> » ? Cette action est irréversible.')">
<button type="button" class="admin-btn admin-btn--sm admin-btn--danger"
onclick="confirmDeleteTag(this, <?= htmlspecialchars(json_encode($tag['name']), ENT_QUOTES) ?>)">
Supprimer
</button>
</form>
@@ -60,3 +85,35 @@
</tbody>
</table>
</main>
<!-- Merge tag confirm -->
<dialog id="merge-tag-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="merge-tag-title">
<div class="admin-dialog__header">
<h2 id="merge-tag-title">Fusionner le tag</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Fusionner ce tag dans « <strong id="merge-target-name"></strong> » ? Le tag source sera supprimé.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--warning" onclick="this.closest('dialog').close(); _submitPendingTagForm()">Fusionner</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>
<!-- Delete tag confirm -->
<dialog id="delete-tag-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="delete-tag-title">
<div class="admin-dialog__header">
<h2 id="delete-tag-title">Supprimer le tag</h2>
<button type="button" class="admin-dialog__close" aria-label="Fermer"
onclick="this.closest('dialog').close()">&#x2715;</button>
</div>
<div class="admin-dialog__alert">
<p>Supprimer « <strong id="delete-tag-name"></strong> » ? Cette action est irréversible.</p>
</div>
<div class="admin-dialog__footer">
<button type="button" class="admin-btn admin-btn--danger" onclick="this.closest('dialog').close(); _submitPendingTagForm()">Supprimer</button>
<button type="button" class="admin-btn-secondary" onclick="this.closest('dialog').close()">Annuler</button>
</div>
</dialog>