feat(admin): Bulk-Wipe inkl. Notruf-Protokolle + Statistik-Tabelle alphabetisch

- wipe_all_user_data loescht zusaetzlich emergency_events (Notruf-Protokolle).
  Audit-Log bleibt unberuehrt (Logger-Stream, kein DB-Eintrag).
- Nutzungsstatistik-Tabelle alphabetisch (case-insensitive); die "Anfragen je
  Nutzer"-Balken bleiben bewusst nach Aktivitaet sortiert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-30 18:56:35 +02:00
commit ce9ada63c9
3 changed files with 7 additions and 3 deletions

View file

@ -1182,7 +1182,7 @@ $("#btn-wipe-all").addEventListener("click", async () => {
if (!confirm("Letzte Warnung: Alle Nutzerdaten werden jetzt gelöscht. Fortfahren?")) return;
const res = await adminFetch("/api/admin/user-data", "DELETE");
if (res) {
alert(`Gelöscht: ${res.messages ?? 0} Nachrichten, ${res.sessions ?? 0} Sessions, ${res.stats ?? 0} Statistik-Zeilen, ${res.memories ?? 0} Erinnerungen.`);
alert(`Gelöscht: ${res.messages ?? 0} Nachrichten, ${res.sessions ?? 0} Sessions, ${res.stats ?? 0} Statistik-Zeilen, ${res.memories ?? 0} Erinnerungen, ${res.emergencies ?? 0} Notruf-Protokolle.`);
loadAdminUsers();
}
});
@ -1881,6 +1881,9 @@ async function loadMetrics() {
const totalEstimated = data.reduce((s, u) => s + (u.month_cost_estimated_usd || 0), 0);
const fmtUsd = (n) => "$" + (Number(n) || 0).toFixed(4);
const maxReq = Math.max(...data.map((u) => u.total_requests || 0), 1);
// Tabelle alphabetisch (case-insensitive); die Balken bleiben nach Aktivität.
const tableData = [...data].sort((a, b) =>
(a.display_name || "").toLowerCase().localeCompare((b.display_name || "").toLowerCase()));
const bars = data.map((u) => {
const pct = Math.round(((u.total_requests || 0) / maxReq) * 100);
@ -1909,7 +1912,7 @@ async function loadMetrics() {
</tr>
</thead>
<tbody class="divide-y divide-slate-100 dark:divide-slate-800 bg-white dark:bg-slate-800">
${data.map((u) => `
${tableData.map((u) => `
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/40 transition-colors">
<td class="px-4 py-2.5 font-medium">${escHtml(u.display_name)}</td>
<td class="px-4 py-2.5 text-right font-mono text-xs">${u.total_requests ?? 0}</td>