SIDEL_ScriptsManager/app/templates/admin/backup.html

338 lines
16 KiB
HTML

{% extends "base.html" %}
{% block title %}Backup Management - {{ t.app_title }}{% endblock %}
{% block content %}
<div class="container-fluid mt-4">
<!-- Header -->
<div class="row mb-4">
<div class="col-md-8">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{{ url_for('dashboard') }}">
<i class="bi bi-house"></i>
</a>
</li>
<li class="breadcrumb-item">
<a href="{{ url_for('admin_users') }}">Administration</a>
</li>
<li class="breadcrumb-item active">Backup Management</li>
</ol>
</nav>
<div class="d-flex align-items-center">
<h1 class="h3 mb-0">
<i class="bi bi-archive text-primary"></i>
Backup Management
</h1>
</div>
<p class="text-muted mb-0">Create and manage system data backups</p>
</div>
<div class="col-md-4 text-end">
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createBackupModal">
<i class="bi bi-plus-circle"></i>
Create Backup
</button>
</div>
</div>
<!-- Backup Status -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="bi bi-speedometer2"></i>
Backup Status
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
<div class="d-flex align-items-center">
<div class="stat-icon bg-primary text-white me-3">
<i class="bi bi-files"></i>
</div>
<div>
<h5 class="mb-0">{{ backup_status.total_backups or 0 }}</h5>
<small class="text-muted">Total Backups</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<div class="stat-icon bg-info text-white me-3">
<i class="bi bi-hdd"></i>
</div>
<div>
<h5 class="mb-0">{{ "%.1f"|format((backup_status.total_size or 0) / 1024 / 1024) }} MB</h5>
<small class="text-muted">Total Size</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<div class="stat-icon bg-success text-white me-3">
<i class="bi bi-calendar-check"></i>
</div>
<div>
<h5 class="mb-0">
{% if backup_status.last_backup %}
{{ backup_status.last_backup.backup_date }}
{% else %}
Never
{% endif %}
</h5>
<small class="text-muted">Last Backup</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="d-flex align-items-center">
<div class="stat-icon bg-warning text-white me-3">
<i class="bi bi-clock"></i>
</div>
<div>
<h5 class="mb-0">
{% if backup_status.next_scheduled_backup %}
{{ backup_status.next_scheduled_backup[:10] }}
{% else %}
Disabled
{% endif %}
</h5>
<small class="text-muted">Next Scheduled</small>
</div>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-6">
<h6><i class="bi bi-gear"></i> Configuration</h6>
<ul class="list-unstyled small">
<li><strong>Status:</strong>
{% if backup_status.enabled %}
<span class="badge bg-success">Enabled</span>
{% else %}
<span class="badge bg-danger">Disabled</span>
{% endif %}
</li>
<li><strong>Retention:</strong> {{ backup_status.retention_days or 30 }} days</li>
<li><strong>Data Path:</strong> <code>{{ backup_status.data_path }}</code></li>
</ul>
</div>
<div class="col-md-6">
<h6><i class="bi bi-folder"></i> Storage</h6>
<ul class="list-unstyled small">
<li><strong>Backup Path:</strong> <code>{{ backup_status.backup_path }}</code></li>
<li><strong>Available Space:</strong> <span class="text-success">{{ "%.1f"|format((backup_status.total_size or 0) / 1024 / 1024) }} MB used</span></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Backup List -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="bi bi-list-ul"></i>
Available Backups
{% if backups %}
<span class="badge bg-primary ms-2">{{ backups|length }}</span>
{% endif %}
</h5>
</div>
<div class="card-body">
{% if backups %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Size</th>
<th>Type</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for backup in backups %}
<tr>
<td>
<strong>{{ backup.backup_date }}</strong>
</td>
<td>
<small class="text-muted">{{ backup.backup_time or 'Unknown' }}</small>
</td>
<td>
<span class="badge bg-light text-dark">
{{ "%.1f"|format((backup.backup_size or 0) / 1024 / 1024) }} MB
</span>
</td>
<td>
{% if backup.get('type') == 'manual' %}
<span class="badge bg-info">Manual</span>
{% else %}
<span class="badge bg-secondary">Scheduled</span>
{% endif %}
</td>
<td>
{% if backup.get('status') == 'success' %}
<span class="badge bg-success">
<i class="bi bi-check-circle"></i>
Success
</span>
{% elif backup.get('status') == 'failed' %}
<span class="badge bg-danger">
<i class="bi bi-x-circle"></i>
Failed
</span>
{% else %}
<span class="badge bg-secondary">Unknown</span>
{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-primary btn-sm"
data-bs-toggle="tooltip" title="View Details"
onclick="showBackupDetails('{{ backup.backup_date }}')">
<i class="bi bi-eye"></i>
</button>
<button type="button" class="btn btn-outline-danger btn-sm"
data-bs-toggle="tooltip" title="Delete Backup"
onclick="confirmDeleteBackup('{{ backup.backup_date }}')">
<i class="bi bi-trash"></i>
</button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="bi bi-inbox display-4 text-muted"></i>
<h5 class="mt-3 text-muted">No backups found</h5>
<p class="text-muted">Create your first backup to get started.</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- Create Backup Modal -->
<div class="modal fade" id="createBackupModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-plus-circle"></i>
Create New Backup
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST" action="{{ url_for('admin_backup_create') }}">
<div class="modal-body">
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<input type="text" class="form-control" id="description" name="description"
placeholder="Enter backup description (optional)">
<div class="form-text">Optional description for this backup</div>
</div>
<div class="alert alert-info">
<h6><i class="bi bi-info-circle"></i> Backup Information</h6>
<ul class="mb-0 small">
<li>This will create a compressed backup of all user data</li>
<li>The backup will be stored in the backup directory</li>
<li>Large datasets may take several minutes to backup</li>
<li>You can continue working during the backup process</li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success">
<i class="bi bi-download"></i>
Create Backup
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteBackupModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title text-danger">
<i class="bi bi-exclamation-triangle"></i>
Confirm Deletion
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the backup for <strong id="deleteBackupDate"></strong>?</p>
<p class="text-danger">
<i class="bi bi-exclamation-triangle"></i>
This action cannot be undone. The backup files will be permanently removed.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<form method="POST" id="deleteBackupForm" style="display: inline;">
<button type="submit" class="btn btn-danger">
<i class="bi bi-trash"></i>
Delete Backup
</button>
</form>
</div>
</div>
</div>
</div>
<script>
function showBackupDetails(backupDate) {
// Could implement a details modal here
alert('Backup details for ' + backupDate + ' - Feature coming soon!');
}
function confirmDeleteBackup(backupDate) {
document.getElementById('deleteBackupDate').textContent = backupDate;
document.getElementById('deleteBackupForm').action = '{{ url_for("admin_backup_delete", backup_date="") }}' + backupDate;
new bootstrap.Modal(document.getElementById('deleteBackupModal')).show();
}
// Initialize tooltips
document.addEventListener('DOMContentLoaded', function() {
var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltips.map(function(tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
});
</script>
<style>
.stat-icon {
width: 48px;
height: 48px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
}
</style>
{% endblock %}