Add full-screen restart overlay for better UX

- Shows overlay with spinner during container restart
- Displays status messages: stopping, waiting, reloading
- Shows elapsed time while waiting for server
- Extended timeout to 60 seconds
- Hides overlay and shows toast if timeout exceeded
This commit is contained in:
2026-02-03 15:06:38 -05:00
parent 3ddf51924b
commit 4c6406ef8f

View File

@@ -292,6 +292,43 @@
to { transform: translateX(0); opacity: 1; } to { transform: translateX(0); opacity: 1; }
} }
.restart-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--bg-primary);
z-index: 9999;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 20px;
}
.restart-overlay.active {
display: flex;
}
.restart-overlay .spinner-large {
width: 48px;
height: 48px;
border: 3px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
.restart-overlay h2 {
color: var(--text-primary);
font-size: 1.5rem;
}
.restart-overlay p {
color: var(--text-secondary);
}
.modal { .modal {
display: none; display: none;
position: fixed; position: fixed;
@@ -784,6 +821,13 @@
</div> </div>
</div> </div>
<!-- Restart Overlay -->
<div class="restart-overlay" id="restart-overlay">
<div class="spinner-large"></div>
<h2>Restarting Container</h2>
<p id="restart-status">Applying configuration changes...</p>
</div>
<script> <script>
// Current edit setting state // Current edit setting state
let currentEditKey = null; let currentEditKey = null;
@@ -1152,14 +1196,17 @@
} }
try { try {
showToast('Restarting container...', 'success');
const res = await fetch('/api/admin/restart', { method: 'POST' }); const res = await fetch('/api/admin/restart', { method: 'POST' });
const data = await res.json(); const data = await res.json();
if (res.ok) { if (res.ok) {
showToast('Container restarting... Page will reload shortly.', 'success'); // Show the restart overlay
document.getElementById('restart-overlay').classList.add('active');
document.getElementById('restart-status').textContent = 'Stopping container...';
// Wait a bit then start checking if the server is back // Wait a bit then start checking if the server is back
setTimeout(() => { setTimeout(() => {
document.getElementById('restart-status').textContent = 'Waiting for server to come back...';
checkServerAndReload(); checkServerAndReload();
}, 3000); }, 3000);
} else { } else {
@@ -1172,7 +1219,7 @@
async function checkServerAndReload() { async function checkServerAndReload() {
let attempts = 0; let attempts = 0;
const maxAttempts = 30; // Try for 30 seconds const maxAttempts = 60; // Try for 60 seconds
const checkHealth = async () => { const checkHealth = async () => {
try { try {
@@ -1181,7 +1228,8 @@
cache: 'no-store' cache: 'no-store'
}); });
if (res.ok) { if (res.ok) {
window.location.reload(); document.getElementById('restart-status').textContent = 'Server is back! Reloading...';
setTimeout(() => window.location.reload(), 500);
return; return;
} }
} catch (e) { } catch (e) {
@@ -1189,9 +1237,12 @@
} }
attempts++; attempts++;
document.getElementById('restart-status').textContent = `Waiting for server to come back... (${attempts}s)`;
if (attempts < maxAttempts) { if (attempts < maxAttempts) {
setTimeout(checkHealth, 1000); setTimeout(checkHealth, 1000);
} else { } else {
document.getElementById('restart-overlay').classList.remove('active');
showToast('Server may still be restarting. Please refresh manually.', 'warning'); showToast('Server may still be restarting. Please refresh manually.', 'warning');
} }
}; };