// Navigation document.querySelectorAll('.nav-item').forEach(item => { item.addEventListener('click', () => { const page = item.dataset.page; document.querySelectorAll('.nav-item').forEach(nav => nav.classList.remove('active')); item.classList.add('active'); document.querySelectorAll('.page').forEach(p => p.style.display = 'none'); const pageElement = document.getElementById(page + '-page'); if (pageElement) pageElement.style.display = 'block'; const titles = {'dashboard': 'Dashboard Overview', 'restore': 'Restore Actions', 'backups': 'Backup Management', 'settings': 'Platform Settings'}; const titleElement = document.getElementById('page-title'); if (titleElement) titleElement.textContent = titles[page]; }); }); function checkServerStatus() { fetch('/server/status') .then(res => res.json()) .then(data => { const statusText = document.getElementById('server-status-text'); const statusDot = document.getElementById('server-status-dot'); if (statusText && statusDot) { if (data.status === 'online') { statusText.innerHTML = data.info; statusDot.className = 'status-dot online'; } else { statusText.innerHTML = 'Offline'; statusDot.className = 'status-dot offline'; } } }) .catch(() => { const statusText = document.getElementById('server-status-text'); const statusDot = document.getElementById('server-status-dot'); if (statusText) statusText.innerHTML = 'Connection Failed'; if (statusDot) statusDot.className = 'status-dot offline'; }); } // Backup functionality let backupEventSource = null; window.runBackupNow = function() { if(confirm('⚠️ Run backup now? This will take a few minutes.')) { const progressDiv = document.getElementById('backup-progress'); const progressBar = document.getElementById('backup-progress-bar'); const logDiv = document.getElementById('backup-log'); const runBtn = document.getElementById('runBackupBtn'); if (progressDiv) progressDiv.style.display = 'block'; if (runBtn) { runBtn.disabled = true; runBtn.innerHTML = ' Running Backup...'; } if (logDiv) logDiv.innerHTML = ''; fetch('/backup/run') .then(res => res.json()) .then(data => { if (data.error) throw new Error(data.error); if (backupEventSource) backupEventSource.close(); backupEventSource = new EventSource('/backup/stream'); backupEventSource.onmessage = function(event) { const data = JSON.parse(event.data); if (logDiv) { const line = document.createElement('div'); line.textContent = data.line; logDiv.appendChild(line); logDiv.scrollTop = logDiv.scrollHeight; } if (data.complete) { backupEventSource.close(); if (progressBar) progressBar.style.width = '100%'; setTimeout(() => { if (progressDiv) progressDiv.style.display = 'none'; if (runBtn) { runBtn.disabled = false; runBtn.innerHTML = ' Run Backup Now'; } refreshStatus(); }, 2000); } }; }) .catch(err => { if (logDiv) logDiv.innerHTML = `
🔄 Starting restore from local backup...
'; } fetch('/restore/local?backup=' + encodeURIComponent(backupValue)) .then(res => res.json()) .then(data => { if (statusDiv) { if (data.error) { statusDiv.className = 'restore-status error'; statusDiv.innerHTML = '❌ ' + data.error + '
'; } else { statusDiv.className = 'restore-status success'; statusDiv.innerHTML = '✅ ' + data.status + '
'; } } }) .catch(err => { if (statusDiv) { statusDiv.className = 'restore-status error'; statusDiv.innerHTML = '❌ Restore failed: ' + err + '
'; } }); } }; window.disasterRestore = function() { const backupFile = document.getElementById('vm-backup-select').value; const targetIp = document.getElementById('target-ip').value; const targetUser = document.getElementById('target-user').value || 'root'; const targetPassword = document.getElementById('target-password').value; if (!targetIp) { alert('Please enter target server IP'); return; } if(confirm(`⚠️ DISASTER RESTORE to ${targetIp}\n\nBackup: ${backupFile.split('/').pop()}\n\nThis will OVERWRITE containers on the target server! Continue?`)) { const statusDiv = document.getElementById('disaster-status'); if (statusDiv) { statusDiv.style.display = 'block'; statusDiv.className = 'restore-status warning'; statusDiv.innerHTML = '🔄 Starting disaster restore to ' + targetIp + '...
'; } fetch('/disaster/restore', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ backup_file: backupFile, target_ip: targetIp, target_user: targetUser, target_password: targetPassword }) }) .then(res => res.json()) .then(data => { if (statusDiv) { if (data.error) { statusDiv.className = 'restore-status error'; statusDiv.innerHTML = '❌ ' + data.error + '
'; } else { statusDiv.className = 'restore-status success'; statusDiv.innerHTML = '✅ ' + data.status + '
Target: ' + data.target + '
❌ Restore failed: ' + err + '
'; } }); } }; window.refreshStatus = function() { location.reload(); }; window.refreshAll = function() { fetch('/server/status').then(() => location.reload()); }; // Add backup panel to Backups page document.addEventListener('DOMContentLoaded', () => { checkServerStatus(); const backupsNav = document.querySelector('.nav-item[data-page="backups"]'); if (backupsNav) { backupsNav.addEventListener('click', () => { setTimeout(() => { if (document.getElementById('backup-panel')) return; const backupsPage = document.getElementById('backups-page'); if (backupsPage) { const backupPanel = document.createElement('div'); backupPanel.id = 'backup-panel'; backupPanel.className = 'card'; backupPanel.innerHTML = `Manually trigger a backup of all containers