templates/base.html
Rama main · réplica de lectura del repositorio original.
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Unraid Config Guardian{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<style>
.navbar-brand {
font-weight: bold;
}
.status-running { color: #28a745; }
.status-exited { color: #dc3545; }
.status-paused { color: #ffc107; }
.card-stat {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.progress-container {
display: none;
}
.progress-container.active {
display: block;
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">
<i class="bi bi-shield-check"></i> Unraid Config Guardian
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/"><i class="bi bi-speedometer2"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/containers"><i class="bi bi-box"></i> Containers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/backups"><i class="bi bi-archive"></i> Backups</a>
</li>
</ul>
<span class="navbar-text">
<small class="me-3 text-muted">v{{ stats.system_info.get('guardian_version', 'unknown') if stats and stats.system_info else 'unknown' }}</small>
<span id="status-indicator" class="badge bg-secondary">Ready</span>
</span>
</div>
</div>
</nav>
<!-- Main Content -->
<div class="container mt-4">
{% block content %}{% endblock %}
</div>
<!-- Progress Modal -->
<div class="modal fade" id="progressModal" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Backup Progress</h5>
</div>
<div class="modal-body">
<div class="progress mb-3">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated"
role="progressbar" style="width: 0%"></div>
</div>
<div id="progress-message">Starting backup...</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Auto-refresh status indicator
function updateStatus() {
fetch('/api/backup/status')
.then(response => response.json())
.then(data => {
const indicator = document.getElementById('status-indicator');
if (data.running) {
indicator.className = 'badge bg-warning';
indicator.textContent = 'Running';
} else if (data.last_error) {
indicator.className = 'badge bg-danger';
indicator.textContent = 'Error';
} else {
indicator.className = 'badge bg-success';
indicator.textContent = 'Ready';
}
})
.catch(err => console.log('Status update failed:', err));
}
// Update status every 30 minutes
setInterval(updateStatus, 1800000);
updateStatus();
// Progress modal handling
let progressModal;
let progressInterval;
function startBackup() {
const formData = new FormData();
formData.append('output_dir', '/output');
fetch('/api/backup/start', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.error) {
alert('Error: ' + data.error);
return;
}
// Show progress modal
progressModal = new bootstrap.Modal(document.getElementById('progressModal'));
progressModal.show();
// Start polling for progress
progressInterval = setInterval(updateProgress, 3000);
})
.catch(err => {
console.error('Backup failed:', err);
alert('Failed to start backup');
});
}
function updateProgress() {
fetch('/api/backup/status')
.then(response => response.json())
.then(data => {
const progressBar = document.getElementById('progress-bar');
const message = document.getElementById('progress-message');
progressBar.style.width = data.progress + '%';
progressBar.setAttribute('aria-valuenow', data.progress);
message.textContent = data.message;
if (!data.running) {
clearInterval(progressInterval);
setTimeout(() => {
if (progressModal) progressModal.hide();
if (data.last_error) {
alert('Backup failed: ' + data.last_error);
} else {
location.reload(); // Refresh to show new data
}
}, 2000);
}
});
}
// Make startBackup available globally
window.startBackup = startBackup;
</script>
{% block scripts %}{% endblock %}
</body>
</html>