Files
mek-tech-consulting/views/backup.ejs
T

130 lines
8.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Backup & Herstel — Mek-Tech</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/neon.css">
<link rel="stylesheet" href="/css/dynamic.css">
<script src="https://unpkg.com/lucide@latest"></script>
<style>
.bk-wrap{max-width:900px;margin:2rem auto;padding:0 1.5rem 3rem}
.bk-wrap h1{font-size:1.4rem;font-weight:800;margin:0 0 .2rem;display:flex;align-items:center;gap:.45rem}
.bk-wrap .sub{color:var(--text-muted);font-size:.78rem;margin-bottom:1.25rem}
.section{background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:1.1rem 1.2rem;margin-bottom:1rem}
.section h2{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);margin:0 0 .75rem;display:flex;align-items:center;gap:.35rem}
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:.45rem;margin-bottom:.5rem}
.stat-card{background:var(--bg);border:1px solid var(--border-light);border-radius:8px;padding:.55rem .65rem;text-align:center}
.stat-card .num{font-size:1.25rem;font-weight:800;color:var(--accent)}
.stat-card .lbl{font-size:.58rem;color:var(--text-muted);text-transform:uppercase;margin-top:.1rem}
.bk-actions{display:flex;gap:.45rem;flex-wrap:wrap;margin-top:.75rem}
.bk-table{width:100%;border-collapse:collapse;font-size:.75rem}
.bk-table th{text-align:left;padding:.45rem .5rem;font-size:.62rem;color:var(--text-muted);text-transform:uppercase;border-bottom:1px solid var(--border)}
.bk-table td{padding:.45rem .5rem;border-bottom:1px solid var(--border-light)}
.bk-table tr:hover td{background:var(--border-light)}
.alert{background:var(--green-bg);border:1px solid var(--green);color:var(--green);padding:.55rem .75rem;border-radius:8px;font-size:.76rem;margin-bottom:1rem}
.alert-warn{background:var(--orange-bg);border-color:var(--orange);color:var(--orange)}
.alert-err{background:var(--red-bg);border-color:var(--red);color:var(--red)}
.restore-box{border:1px dashed var(--border);border-radius:8px;padding:1rem;margin-top:.5rem}
.restore-box p{font-size:.72rem;color:var(--text-muted);margin:0 0 .65rem;line-height:1.45}
.restore-box input[type=file]{font-size:.72rem;margin-bottom:.5rem;width:100%}
.info-list{font-size:.72rem;color:var(--text-muted);margin:.35rem 0 0;padding-left:1.1rem;line-height:1.5}
</style>
</head>
<body>
<nav class="navbar"><div class="nav-inner">
<a href="/" class="nav-brand"><img src="/img/logo.svg" class="nav-logo" alt="Mek-Tech"></a>
<div style="display:flex;gap:.4rem;align-items:center">
<a href="/settings" class="nav-icon-btn"><i data-lucide="settings" style="width:15px;height:15px"></i> Instellingen</a>
<a href="/" class="nav-icon-btn"><i data-lucide="layout-dashboard" style="width:15px;height:15px"></i></a>
<a href="/auth/logout" class="nav-icon-btn" style="color:var(--red)"><i data-lucide="log-out" style="width:15px;height:15px"></i></a>
</div></div></nav>
<div class="bk-wrap">
<a href="/settings" class="back-link"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg> Terug naar instellingen</a>
<h1><i data-lucide="database-backup" style="width:22px;height:22px;color:var(--accent)"></i> Backup & Herstel</h1>
<p class="sub">Volledige backup van database, sessies, uploads en alle cliëntdata.</p>
<% if (created) { %><div class="alert"><i data-lucide="check-circle" style="width:14px;height:14px"></i> Backup succesvol aangemaakt op de server.</div><% } %>
<% if (restored) { %><div class="alert"><i data-lucide="check-circle" style="width:14px;height:14px"></i> Herstel voltooid. Vernieuw het dashboard — bij problemen herstart de container.</div><% } %>
<% if (deleted) { %><div class="alert">Backup verwijderd.</div><% } %>
<% if (error) { %><div class="alert alert-err"><%= error %></div><% } %>
<div class="section">
<h2><i data-lucide="bar-chart-2" style="width:14px;height:14px"></i> Huidige data</h2>
<div class="stat-grid">
<div class="stat-card"><div class="num"><%= stats.counts.clients || 0 %></div><div class="lbl">Cliënten</div></div>
<div class="stat-card"><div class="num"><%= stats.counts.engagements || 0 %></div><div class="lbl">Engagements</div></div>
<div class="stat-card"><div class="num"><%= stats.counts.racks || 0 %></div><div class="lbl">Racks</div></div>
<div class="stat-card"><div class="num"><%= stats.counts.data_diagrams || 0 %></div><div class="lbl">Diagrammen</div></div>
<div class="stat-card"><div class="num"><%= stats.counts.projects || 0 %></div><div class="lbl">Projecten</div></div>
<div class="stat-card"><div class="num"><%= stats.counts.invoices || 0 %></div><div class="lbl">Facturen</div></div>
</div>
<p style="font-size:.68rem;color:var(--text-dim);margin:0">
Database: <%= formatBytes(stats.dbSizeBytes) %>
<% if (stats.uploadFiles) { %> · Uploads: <%= stats.uploadFiles %> bestanden (<%= formatBytes(stats.uploadsBytes) %>)<% } %>
<% if (diskFree) { %> · Schijf vrij: <%= diskFree %><% } %>
</p>
</div>
<div class="section">
<h2><i data-lucide="download" style="width:14px;height:14px"></i> Nieuwe backup maken</h2>
<p style="font-size:.74rem;color:var(--text-muted);margin:0 0 .5rem">Maakt een .tar.gz archief met:</p>
<ul class="info-list">
<li><strong>consulting.db</strong> — alle cliënten, racks, diagrammen, facturen, instellingen</li>
<li><strong>sessions.db</strong> — actieve sessies</li>
<li><strong>uploads/</strong> — geüploade data quality bestanden</li>
</ul>
<div class="bk-actions">
<form method="POST" action="/backup/create?download=1" style="display:inline"><button type="submit" class="btn btn-accent btn-small"><i data-lucide="download" style="width:14px;height:14px"></i> Backup maken & downloaden</button></form>
<form method="POST" action="/backup/create" style="display:inline"><button type="submit" class="btn btn-secondary btn-small"><i data-lucide="save" style="width:14px;height:14px"></i> Opslaan op server</button></form>
</div>
</div>
<div class="section">
<h2><i data-lucide="archive" style="width:14px;height:14px"></i> Backups op server (<%= backups.length %>)</h2>
<% if (backups.length === 0) { %>
<p style="font-size:.74rem;color:var(--text-muted)">Nog geen backups opgeslagen op de server.</p>
<% } else { %>
<table class="bk-table">
<thead><tr><th>Bestand</th><th>Grootte</th><th>Datum</th><th></th></tr></thead>
<tbody>
<% backups.forEach(function(b) { %>
<tr>
<td><strong><%= b.filename %></strong></td>
<td><%= b.sizeLabel %></td>
<td><%= new Date(b.created_at).toLocaleString('nl-NL') %></td>
<td style="white-space:nowrap">
<a href="/backup/download/<%= b.filename %>" class="btn btn-secondary btn-small">Download</a>
<form method="POST" action="/backup/restore/<%= b.filename %>" style="display:inline" onsubmit="return confirm('WAARSCHUWING: Alle huidige data wordt overschreven. Er wordt eerst automatisch een veiligheidsbackup gemaakt. Doorgaan?')">
<button type="submit" class="btn btn-secondary btn-small">Herstellen</button>
</form>
<form method="POST" action="/backup/delete/<%= b.filename %>" style="display:inline" onsubmit="return confirm('Backup verwijderen?')">
<button type="submit" class="btn btn-secondary btn-small" style="color:var(--red)">×</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% } %>
</div>
<div class="section">
<h2><i data-lucide="upload" style="width:14px;height:14px"></i> Herstellen vanaf bestand</h2>
<div class="restore-box">
<p><strong>Let op:</strong> Herstellen overschrijft alle huidige data. Vóór herstel wordt automatisch een veiligheidsbackup gemaakt op de server.</p>
<form method="POST" action="/backup/restore" enctype="multipart/form-data" onsubmit="return confirm('Weet je zeker dat je wilt herstellen? Huidige data wordt overschreven.')">
<input type="file" name="backup_file" accept=".tar.gz,.tgz,application/gzip" required>
<button type="submit" class="btn btn-accent btn-small"><i data-lucide="upload" style="width:14px;height:14px"></i> Backup uploaden & herstellen</button>
</form>
</div>
</div>
</div>
<script>lucide.createIcons();</script>
<script src="/js/theme.js"></script>
</body>
</html>