monitoring/backup-monitor/templates/index.html

201 lines
8.3 KiB
HTML
Raw Permalink 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="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark">
<title>The Sentinel · Backup-Monitor</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' rx='10' fill='%23171917'/><path d='M18 20h28M18 32h28M18 44h18' stroke='%237abf8a' stroke-width='5' stroke-linecap='round'/></svg>">
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<header class="site-header">
<div class="topbar">
<a class="brand" href="#dashboard" onclick="showPage('dashboard'); return false;" aria-label="The Sentinel Startseite">
<span class="brand-mark" aria-hidden="true">S</span>
<span>
<strong>The Sentinel</strong>
<small>Backup-Monitor</small>
</span>
</a>
<nav class="main-nav" aria-label="Hauptnavigation">
<a href="#dashboard" onclick="showPage('dashboard'); return false;" id="nav-dashboard" class="is-active" aria-current="page">Übersicht</a>
<a href="#alerts" onclick="showPage('alerts'); return false;" id="nav-alerts">Meldungen</a>
<a href="#hosts" onclick="showPage('hosts'); return false;" id="nav-hosts">Hosts</a>
<a href="#config" onclick="showPage('config'); return false;" id="nav-config">Einstellungen</a>
</nav>
<div class="topbar-actions">
<div id="sysStatus" class="system-state status--ok" aria-live="polite">
<span class="status-dot status--ok" aria-hidden="true"></span>
<span>Betriebsbereit</span>
</div>
<button type="button" class="icon-button" onclick="loadAll()" aria-label="Daten aktualisieren" title="Aktualisieren"></button>
<button type="button" class="icon-button" onclick="openAddHost()" aria-label="Host hinzufügen" title="Host hinzufügen"></button>
</div>
</div>
</header>
<main class="app-shell">
<section id="page-dashboard" class="page" aria-labelledby="dashboard-title">
<header class="page-header">
<div>
<p class="eyebrow">Borgmatic-Infrastruktur</p>
<h1 id="dashboard-title">Backup-Übersicht</h1>
<p class="lede">Der aktuelle Stand aller gemeldeten Sicherungen.</p>
</div>
<div class="scan-state">
<span>Letzte Aktualisierung</span>
<time id="lastScan"></time>
</div>
</header>
<section class="metric-strip" id="metricCards" aria-label="Zusammenfassung">
<article class="metric">
<span class="metric-label">Hosts in Ordnung</span>
<strong id="mOk"></strong>
</article>
<article class="metric">
<span class="metric-label">Heute gesichert</span>
<strong id="mSize"></strong>
</article>
<article class="metric">
<span class="metric-label">Letzte Sicherung</span>
<strong id="mLatest"></strong>
<small id="mLatestHost"></small>
</article>
<article class="metric metric--issue" id="mWarnCard">
<span class="metric-label">Auffälligkeiten</span>
<strong id="mWarn">0</strong>
<button type="button" class="text-button" onclick="showPage('alerts')">Meldungen öffnen</button>
</article>
</section>
<div class="dashboard-grid">
<section class="panel panel--chart" aria-labelledby="volume-title">
<header class="panel-header">
<div>
<h2 id="volume-title">Gesichertes Datenvolumen</h2>
<p>Summe der letzten 30 Tage, über die zehn zuerst gemeldeten Hosts.</p>
</div>
</header>
<div class="chart" id="volumeChart">
<svg id="chartSvg" role="img" aria-label="Backup-Volumen der letzten 30 Tage" viewBox="0 0 100 100" preserveAspectRatio="none"></svg>
</div>
</section>
<section class="panel panel--hosts" aria-labelledby="host-status-title">
<header class="panel-header">
<h2 id="host-status-title">Host-Status</h2>
</header>
<div id="clusterList" class="cluster-list"></div>
</section>
</div>
<section class="panel" aria-labelledby="stream-title">
<header class="panel-header panel-header--split">
<h2 id="stream-title">Letzte Meldungen</h2>
<span class="quiet-note">automatisch alle 30 Sekunden</span>
</header>
<div id="liveStream" class="event-list" aria-live="polite"></div>
</section>
</section>
<section id="page-alerts" class="page hidden" aria-labelledby="alerts-title">
<header class="page-header">
<div>
<p class="eyebrow">Prüfbedarf</p>
<h1 id="alerts-title">Meldungen</h1>
<p class="lede">Fehlgeschlagene oder überfällige Sicherungen.</p>
</div>
<dl class="inline-counts">
<div><dt>Fehler</dt><dd id="aCrit">0</dd></div>
<div><dt>Überfällig</dt><dd id="aStale">0</dd></div>
</dl>
</header>
<div id="alertList" class="alert-list">
<p class="empty-state">Keine offenen Meldungen.</p>
</div>
</section>
<section id="page-hosts" class="page hidden" aria-labelledby="hosts-title">
<header class="page-header">
<div>
<p class="eyebrow">Inventar</p>
<h1 id="hosts-title">Backup-Hosts</h1>
<p class="lede">Alle registrierten Endpunkte und ihre letzten Sicherungen.</p>
</div>
<button type="button" class="button button--primary" onclick="openAddHost()">Host hinzufügen</button>
</header>
<div id="hostGrid" class="host-grid"></div>
</section>
<section id="page-config" class="page hidden" aria-labelledby="config-title">
<header class="page-header">
<div>
<p class="eyebrow">Schnittstellen</p>
<h1 id="config-title">Einstellungen</h1>
<p class="lede">Die Endpunkte, über die Sentinel Daten annimmt und ausliefert.</p>
</div>
</header>
<dl class="settings-list">
<div>
<dt>Backup-Meldungen</dt>
<dd><code>POST /api/push</code></dd>
</div>
<div>
<dt>Prometheus</dt>
<dd><code>GET /metrics</code></dd>
</div>
<div>
<dt>API-Schlüssel</dt>
<dd>{{ 'Aktiviert (Umgebungsvariable API_KEY)' if api_key_required else 'Deaktiviert' }}</dd>
</div>
</dl>
</section>
</main>
<div id="drawerBg" class="backdrop is-hidden" onclick="closeDrawer()"></div>
<aside id="drawer" class="drawer is-closed" aria-labelledby="drawerTitle" aria-hidden="true">
<header class="overlay-header">
<div>
<span class="eyebrow">Host-Details</span>
<h2 id="drawerTitle">Host</h2>
</div>
<button type="button" class="icon-button" onclick="closeDrawer()" aria-label="Details schließen">×</button>
</header>
<div id="drawerBody" class="drawer-body"></div>
</aside>
<div id="modalBg" class="backdrop is-hidden" onclick="closeModal()"></div>
<section id="modal" class="modal is-closed" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-hidden="true">
<header class="overlay-header">
<h2 id="modalTitle">Host hinzufügen</h2>
<button type="button" class="icon-button" onclick="closeModal()" aria-label="Dialog schließen">×</button>
</header>
<form id="hostForm" onsubmit="saveHost(event)" class="form-stack">
<input type="hidden" id="formMode" value="add">
<label>
<span>Hostname</span>
<input type="text" id="formName" required placeholder="zum Beispiel arrapps">
</label>
<label>
<span>Uptime-Kuma Push-URL</span>
<input type="url" id="formKumaUrl" placeholder="https://status.example.com/api/push/…">
</label>
<label class="checkbox-row">
<input type="checkbox" id="formEnabled" checked>
<span>Host überwachen</span>
</label>
<div class="form-actions">
<button type="button" class="button" onclick="closeModal()">Abbrechen</button>
<button type="submit" class="button button--primary">Speichern</button>
</div>
</form>
</section>
<div id="toasts" class="toast-stack" aria-live="polite"></div>
<script src="/static/js/app.js"></script>
</body>
</html>