feat(3a): Admin-Struktur aufgeräumt + Restart nach „Wartung"

- 4 ruhige Top-Tabs: Übersicht · Nutzer · System · Konfiguration.
- „Notrufe" wandert unter System; „Metriken" → „Nutzungs-Statistik" unter
  Nutzer einsortiert.
- Status ist jetzt rein lesend (Wartung + DB-Backup raus).
- Neuer „Wartung"-Abschnitt unter Konfiguration mit prominentem
  „Gateway neu starten" + DB-Backup. app.js v=46.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 04:52:09 +02:00
commit 5b1a36c976
2 changed files with 41 additions and 27 deletions

View file

@ -872,10 +872,9 @@ $("#admin-close").addEventListener("click", () => $("#admin-panel").classList.ad
// Abschnitten bekommen eine Sub-Navigation.
const ADMIN_TABS = {
overview: [["overview", "Übersicht"]],
users: [["users", "Verwalten"], ["chat", "Gespräche"]],
emergency: [["emergency", "Notrufe"]],
system: [["status", "Status"], ["metrics", "Metriken"], ["log", "Log"]],
config: [["settings", "Einstellungen"], ["words", "Wörterbuch"]],
users: [["users", "Verwalten"], ["chat", "Gespräche"], ["metrics", "Nutzungs-Statistik"]],
system: [["status", "Status"], ["log", "Log"], ["emergency", "Notrufe"]],
config: [["settings", "Einstellungen"], ["words", "Wörterbuch"], ["maintenance", "Wartung"]],
};
const SECTION_LOADER = {
overview: () => loadOverview(),
@ -886,6 +885,7 @@ const SECTION_LOADER = {
metrics: () => loadMetrics(),
words: () => loadWoerterbuch(),
settings: () => loadSettings(),
maintenance: () => loadMaintenance(),
log: () => {}, // Log: Nutzer verbindet manuell
};
@ -1415,16 +1415,6 @@ async function loadStatus() {
</dl>
</div>
<!-- Wartung -->
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<h3 class="font-semibold text-sm mb-1">Wartung</h3>
<p class="text-xs text-slate-400 mb-3">Startet den Gateway-Dienst neu (z. B. nach Einstellungen, die einen Neustart erfordern).</p>
<div class="flex flex-wrap items-center gap-2">
<button id="gw-restart-btn" class="rounded-lg border border-amber-300 dark:border-amber-700 text-amber-700 dark:text-amber-300 text-sm px-3 py-1.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 transition-colors">Gateway neu starten</button>
<span id="llm-ctrl-msg" class="text-xs text-slate-400"></span>
</div>
</div>
<!-- Laufzeit-Metriken -->
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<h3 class="font-semibold text-sm mb-3">Laufzeit-Metriken</h3>
@ -1443,24 +1433,39 @@ async function loadStatus() {
${providerRow("TTS", (cfg.available?.tts_providers || []).join(", "))}
</dl>
</div>
<!-- Datenbank-Export -->
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<h3 class="font-semibold text-sm mb-1">Datenbank-Backup</h3>
<p class="text-xs text-slate-400 mb-3">SQLite-Datenbank als Datei herunterladen (Backup / Migration).</p>
<a href="/api/admin/db-export" download="voice-assistant.db"
class="inline-flex items-center gap-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-xs px-4 py-2 font-medium transition-colors">
voice-assistant.db herunterladen
</a>
</div>
`;
wireRestart(); // Buttons der LLM-Karte verdrahten (nach dem Rendern)
} catch (e) {
console.error("loadStatus error:", e);
container.innerHTML = '<p class="text-sm text-red-500">Fehler beim Laden.</p>';
}
}
// ════════════════════════════════════════
// TAB: WARTUNG (Konfiguration)
// ════════════════════════════════════════
async function loadMaintenance() {
const c = $("#maintenance-content");
c.innerHTML = `
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<h3 class="font-semibold text-sm mb-1">Gateway neu starten</h3>
<p class="text-xs text-slate-400 mb-3">Nötig nach Einstellungen, die einen Neustart erfordern (Hinweis erscheint dort).</p>
<div class="flex flex-wrap items-center gap-2">
<button id="gw-restart-btn" class="rounded-lg border border-amber-300 dark:border-amber-700 text-amber-700 dark:text-amber-300 text-sm px-3 py-1.5 hover:bg-amber-50 dark:hover:bg-amber-900/20 transition-colors">Gateway neu starten</button>
<span id="llm-ctrl-msg" class="text-xs text-slate-400"></span>
</div>
</div>
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<h3 class="font-semibold text-sm mb-1">Datenbank-Backup</h3>
<p class="text-xs text-slate-400 mb-3">SQLite-Datenbank als Datei herunterladen (Backup / Migration).</p>
<a href="/api/admin/db-export" download="voice-assistant.db"
class="inline-flex items-center gap-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-xs px-4 py-2 font-medium transition-colors">
voice-assistant.db herunterladen
</a>
</div>
`;
wireRestart();
}
// ════════════════════════════════════════
// TAB: METRIKEN
// ════════════════════════════════════════