v0.4.5: Add dedicated Backup page (Biztonsági mentés)
New /backups page with full backup system visibility: - Status overview cards (local/remote backup, DB count, repo size) - Schedule section with next-run times and retention policy - Database table with type, size, validation (table count), status - Snapshot history table with per-snapshot stats - Repository info card with paths, integrity status, remote placeholder - "Mentés most" button with auto-refresh polling - Empty state when backup not configured Backend: SnapshotRecord history (ring buffer), DumpValidation, ListDumpFiles, ListSnapshots, GetFullStatus, restic check tracking. Server accepts scheduler for next-run time calculation. Sidebar nav updated with 3rd item, dashboard backup card title clickable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1226,6 +1226,257 @@ a.stat-card:hover {
|
||||
.backup-status-fail { color: var(--red); }
|
||||
.backup-status-none { color: var(--text-muted); }
|
||||
|
||||
/* Dashboard backup card link */
|
||||
.backup-card-link {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.backup-card-link:hover {
|
||||
color: var(--accent-light);
|
||||
}
|
||||
|
||||
/* --- Backup page --- */
|
||||
.backup-page-cards {
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
}
|
||||
|
||||
.backup-empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
.backup-empty-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.backup-empty-state h3 {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
.backup-empty-state p {
|
||||
color: var(--text-secondary);
|
||||
font-size: .9rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.schedule-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.25rem;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.schedule-card h3 {
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.schedule-rows {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.schedule-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: .4rem 0;
|
||||
font-size: .85rem;
|
||||
border-bottom: 1px solid rgba(48, 54, 61, 0.5);
|
||||
}
|
||||
.schedule-row:last-child { border-bottom: none; }
|
||||
.schedule-task {
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
min-width: 160px;
|
||||
}
|
||||
.schedule-time {
|
||||
color: var(--accent-light);
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: .8rem;
|
||||
min-width: 80px;
|
||||
}
|
||||
.schedule-next {
|
||||
color: var(--text-secondary);
|
||||
font-size: .8rem;
|
||||
}
|
||||
.schedule-summary {
|
||||
border-top: 1px solid var(--border-color);
|
||||
padding-top: .75rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.schedule-summary-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: .25rem 0;
|
||||
font-size: .85rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.schedule-summary-value {
|
||||
color: var(--text-primary);
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: .8rem;
|
||||
}
|
||||
.schedule-actions {
|
||||
padding-top: .5rem;
|
||||
}
|
||||
|
||||
.backup-section-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.25rem;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.backup-section-card h3 {
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
|
||||
.backup-table-wrap {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.db-table, .snapshot-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: .85rem;
|
||||
}
|
||||
.db-table th, .snapshot-table th {
|
||||
text-align: left;
|
||||
padding: .5rem .75rem;
|
||||
color: var(--text-muted);
|
||||
font-size: .75rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .5px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.db-table td, .snapshot-table td {
|
||||
padding: .5rem .75rem;
|
||||
color: var(--text-primary);
|
||||
border-bottom: 1px solid rgba(48, 54, 61, 0.3);
|
||||
}
|
||||
.db-table tr:nth-child(even), .snapshot-table tr:nth-child(even) {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
.db-table tr:nth-child(odd), .snapshot-table tr:nth-child(odd) {
|
||||
background: var(--bg-card);
|
||||
}
|
||||
.db-table td.mono, .snapshot-table td.mono {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.db-type-badge {
|
||||
display: inline-block;
|
||||
padding: .1rem .5rem;
|
||||
border-radius: 999px;
|
||||
font-size: .75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.db-type-postgres {
|
||||
background: rgba(0, 136, 204, 0.15);
|
||||
color: var(--accent-light);
|
||||
}
|
||||
.db-type-mariadb {
|
||||
background: rgba(210, 153, 34, 0.15);
|
||||
color: var(--yellow);
|
||||
}
|
||||
|
||||
.validation-badge {
|
||||
display: inline-block;
|
||||
padding: .1rem .5rem;
|
||||
border-radius: 999px;
|
||||
font-size: .75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.validation-ok {
|
||||
background: var(--green-bg);
|
||||
color: var(--green);
|
||||
}
|
||||
.validation-fail {
|
||||
background: var(--red-bg);
|
||||
color: var(--red);
|
||||
cursor: help;
|
||||
}
|
||||
.validation-na {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.snapshot-footer {
|
||||
padding: .75rem .75rem 0;
|
||||
font-size: .8rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.backup-table-empty {
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-size: .85rem;
|
||||
}
|
||||
|
||||
.repo-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.25rem;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.repo-card h3 {
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.repo-info-rows {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.repo-info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: .3rem 0;
|
||||
font-size: .85rem;
|
||||
}
|
||||
.repo-label {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.repo-value {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.repo-value.mono {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: .8rem;
|
||||
}
|
||||
.repo-paths {
|
||||
border-top: 1px solid var(--border-color);
|
||||
padding-top: .75rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.repo-path-list {
|
||||
list-style: disc;
|
||||
padding-left: 1.5rem;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
.repo-path-list li {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: .8rem;
|
||||
color: var(--text-secondary);
|
||||
padding: .15rem 0;
|
||||
}
|
||||
.repo-remote {
|
||||
border-top: 1px solid var(--border-color);
|
||||
padding-top: .75rem;
|
||||
}
|
||||
.repo-remote-status {
|
||||
margin-top: .25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .15rem;
|
||||
}
|
||||
|
||||
.relative-time {
|
||||
color: var(--text-muted);
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media(max-width: 768px) {
|
||||
.sidebar { width: 100%; height: auto; position: relative; border-right: none; border-bottom: 1px solid var(--border-color); }
|
||||
|
||||
Reference in New Issue
Block a user