diff --git a/app/templates/snapshots.html b/app/templates/snapshots.html index 5fcf759..830c920 100644 --- a/app/templates/snapshots.html +++ b/app/templates/snapshots.html @@ -18,8 +18,32 @@ .badge-age-warn { background: rgba(245,158,11,.20); color: #f59e0b; border: 1px solid #f59e0b; } .badge-age-fresh { background: rgba(34,197,94,.20); color: #22c55e; border: 1px solid #22c55e; } .filters-card label { display: flex; align-items: center; gap: 0.5rem; } + /* Overlay plein page pendant les actions async */ + #busy-overlay { + position: fixed; inset: 0; z-index: 9999; + background: rgba(10,14,23,0.75); backdrop-filter: blur(2px); + display: none; align-items: center; justify-content: center; + flex-direction: column; gap: 1rem; + } + #busy-overlay.active { display: flex; } + .spinner { + width: 64px; height: 64px; + border: 4px solid rgba(245,158,11,0.2); + border-top-color: #f59e0b; + border-radius: 50%; + animation: spin 0.9s linear infinite; + } + @keyframes spin { to { transform: rotate(360deg); } } + #busy-text { color: #f59e0b; font-size: 1.05rem; font-weight: 600; text-shadow: 0 0 12px rgba(245,158,11,0.6); } + #busy-sub { color: #9ca3af; font-size: 0.85rem; } +
+
+
Action en cours…
+
Ne ferme pas la page, ne navigue pas ailleurs.
+
+
@@ -199,8 +223,19 @@ btnDelete.textContent = n > 0 ? `✕ SUPPRIMER ${n} SNAPSHOT${n>1?'S':''}` : '✕ SUPPRIMER LA SÉLECTION'; } - function setBusy(msg, btn) { + // Overlay plein page : bloque toute interaction pendant les actions async. + // Empêche aussi la navigation accidentelle via beforeunload. + const overlay = document.getElementById('busy-overlay'); + const busyText = document.getElementById('busy-text'); + const busySub = document.getElementById('busy-sub'); + let busyActive = false; + + function setBusy(msg, btn, sub) { status.innerHTML = '⏳ ' + escapeHTML(msg) + ''; + busyText.textContent = '⏳ ' + msg; + busySub.textContent = sub || 'Ne ferme pas la page, ne navigue pas ailleurs.'; + overlay.classList.add('active'); + busyActive = true; if (btn) { btn.disabled = true; btn._origText = btn._origText || btn.textContent; @@ -208,11 +243,21 @@ } } function clearBusy(btn) { + overlay.classList.remove('active'); + busyActive = false; if (btn && btn._origText) { btn.disabled = false; btn.textContent = btn._origText; } } + // Avertit si l'utilisateur tente de quitter la page pendant une action + window.addEventListener('beforeunload', (e) => { + if (busyActive) { + e.preventDefault(); + e.returnValue = 'Une action est en cours. Quitter maintenant peut interrompre la requête.'; + return e.returnValue; + } + }); btnRefresh.addEventListener('click', async () => { setBusy('Recherche en cours… (peut prendre 10-30 s selon les vCenters)', btnRefresh);