generated from Dicken/dickendock
Reset-Button, Service-Reorder, Port/HTTPS-Spalten, Healthcheck in Sidebar, Kategorien-Sync
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Button } from "@launchpad/ui";
|
||||
import { useBackendHealth } from "../../hooks/useBackendHealth.js";
|
||||
import { useTheme } from "../../hooks/useTheme.js";
|
||||
import { AdminPageHeader } from "./AdminPageHeader.js";
|
||||
@@ -11,6 +14,66 @@ function InfoRow({ label, value }: { label: string; value: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
async function resetEverything() {
|
||||
const res = await fetch("/api/reset", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ confirm: true }),
|
||||
});
|
||||
const body = await res.json();
|
||||
if (!res.ok) {
|
||||
throw new Error(body.error ?? `Reset fehlgeschlagen (HTTP ${res.status})`);
|
||||
}
|
||||
return body as { deletedDevices: number };
|
||||
}
|
||||
|
||||
function DangerZone() {
|
||||
const queryClient = useQueryClient();
|
||||
const [message, setMessage] = useState<string | null>(null);
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: resetEverything,
|
||||
onSuccess: (result) => {
|
||||
setMessage(`${result.deletedDevices} Gerät(e) und alle zugehörigen Dienste gelöscht.`);
|
||||
queryClient.invalidateQueries({ queryKey: ["devices"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["services"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["logs"] });
|
||||
},
|
||||
onError: (err: Error) => setMessage(err.message),
|
||||
});
|
||||
|
||||
function handleClick() {
|
||||
const firstConfirm = window.confirm(
|
||||
"Wirklich ALLE Geräte und Dienste unwiderruflich löschen? Kategorien bleiben erhalten."
|
||||
);
|
||||
if (!firstConfirm) return;
|
||||
|
||||
const secondConfirm = window.confirm(
|
||||
"Ganz sicher? Das kann nicht rückgängig gemacht werden."
|
||||
);
|
||||
if (!secondConfirm) return;
|
||||
|
||||
setMessage(null);
|
||||
mutation.mutate();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-2xl border border-red-500/20 p-5">
|
||||
<h2 className="mb-1 font-medium text-red-600 dark:text-red-400">Gefahrenzone</h2>
|
||||
<p className="mb-4 text-sm text-black/50 dark:text-white/50">
|
||||
Löscht alle Geräte und alle zugehörigen Dienste unwiderruflich. Kategorien und Logs
|
||||
bleiben erhalten.
|
||||
</p>
|
||||
<Button variant="danger" onClick={handleClick} disabled={mutation.isPending}>
|
||||
{mutation.isPending ? "Lösche …" : "Alle Geräte & Dienste löschen"}
|
||||
</Button>
|
||||
{message ? (
|
||||
<p className="mt-3 text-sm text-black/60 dark:text-white/60">{message}</p>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SettingsPage() {
|
||||
const { health, error } = useBackendHealth();
|
||||
const [theme, toggleTheme] = useTheme();
|
||||
@@ -49,6 +112,8 @@ export function SettingsPage() {
|
||||
<p className="text-sm text-black/40 dark:text-white/40">Lade …</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DangerZone />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user