Refactor: Diagnose-Tab in Zentrale gemerged + Zentrale neu strukturiert

Diagnose war groesstenteils Dublette (Metriken/Temps schon in Zentrale; Logs/Restart/
Updates im Pflege-Drawer). Tab entfernt, zwei einzigartige Teile umverteilt.

- Zentrale neu in 3 Zonen: Live-Telemetrie (System-Status + Token-Durchsatz nebeneinander
  statt gestapelt), Stack-Status (Aktive Modelle / Rollen / Dienste), Betrieb & Wissen
  (Updates / Hermes / Gedaechtnis).
- Neue ServicesCard (Dienste-Health aus Diagnose) auf der Zentrale.
- TokenStatsCard ('Effizienz & Ersparnis') in TokenPerformanceCard gemerged (Input/Output
  + gespart) -> eine Karte weniger, keine Dublette.
- Backup/Snapshot in den System-Wartung-Drawer verschoben.
- nav.ts/App.tsx: 'system'-View entfernt (6 statt 7 Tabs); SystemView.tsx geloescht.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-27 16:57:16 +02:00
parent 35189fde0e
commit ec9488d94e
14 changed files with 630 additions and 792 deletions
+38 -1
View File
@@ -1,5 +1,5 @@
import { useEffect, useState, useRef } from "react"
import { X, RefreshCw, Terminal, Cpu, Server, Shield, Power, Eye, EyeOff, Key, Download, AlertTriangle } from "lucide-react"
import { X, RefreshCw, Terminal, Cpu, Server, Shield, Power, Eye, EyeOff, Key, Download, AlertTriangle, Save } from "lucide-react"
import { api, type Job, type UpdatesResp } from "@/lib/api"
import { cn } from "@/lib/utils"
import { CustomDialog } from "./CustomDialog"
@@ -35,6 +35,8 @@ export function SystemDrawer({ open, onClose, defaultTab = "maintenance" }: Syst
const [restartingServices, setRestartingServices] = useState<Record<string, boolean>>({})
const [activeTab, setActiveTab] = useState<"maintenance" | "logs" | "settings">("maintenance")
const [checkingUpdates, setCheckingUpdates] = useState(false)
const [backupMsg, setBackupMsg] = useState("")
const [backupRunning, setBackupRunning] = useState(false)
// Custom Dialog State
const [dialog, setDialog] = useState<{
@@ -222,6 +224,19 @@ export function SystemDrawer({ open, onClose, defaultTab = "maintenance" }: Syst
)
}
async function doBackup() {
setBackupRunning(true)
setBackupMsg("Snapshot wird erzeugt...")
try {
const r = await api<{ ok: boolean; snapshot: string; files: string[] }>("/api/system/backup", { method: "POST" })
setBackupMsg(r.ok ? `Snapshot erzeugt: ${r.snapshot} (${r.files.length} Dateien)` : "Keine Änderungen zu sichern.")
} catch (e: any) {
setBackupMsg(`Fehler: ${e.message}`)
} finally {
setBackupRunning(false)
}
}
async function restartService(serviceId: string) {
setRestartingServices(prev => ({ ...prev, [serviceId]: true }))
try {
@@ -384,6 +399,28 @@ export function SystemDrawer({ open, onClose, defaultTab = "maintenance" }: Syst
</button>
</div>
{/* Backup / Snapshot */}
<div className="space-y-3">
<h3 className="text-xs font-bold uppercase tracking-wider text-muted-foreground">System-Backup &amp; Snapshot</h3>
<div className="p-4 rounded-xl border border-border/60 bg-background/20 space-y-3">
<p className="text-[10px] text-muted-foreground leading-normal">
Git-Snapshot der aktuellen Konfigurationen und des System-Zustands erzeugen.
</p>
<button
onClick={doBackup}
disabled={backupRunning}
className="w-full h-9 flex items-center justify-center gap-1.5 rounded-lg bg-primary text-primary-foreground text-xs font-semibold hover:opacity-90 transition-all cursor-pointer disabled:opacity-50 shadow-md shadow-primary/10"
>
<Save className={cn("h-4 w-4", backupRunning && "animate-pulse")} /> Snapshot erstellen
</button>
{backupMsg && (
<div className="text-[10px] font-mono text-primary bg-primary/5 p-2 rounded-lg border border-primary/20 break-all leading-normal">
{backupMsg}
</div>
)}
</div>
</div>
{/* Modell Upgrades */}
{updates?.model_list && updates.model_list.length > 0 && (
<div className="space-y-3">