generated from Dicken/dickendock
round22: Startseite kompakter, Ping-Zeitstempel-Bug behoben, echte Favicon-Deduplizierung per Bildinhalt, automatischer Favicon-Abgleich aus Icon-Datenbank + Nachruest-Button
This commit is contained in:
@@ -503,6 +503,46 @@ function SortableHeader({
|
||||
);
|
||||
}
|
||||
|
||||
function BackfillFaviconsButton() {
|
||||
const queryClient = useQueryClient();
|
||||
const [message, setMessage] = useState<string | null>(null);
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
const res = await fetch("/api/services/backfill-favicons", { method: "POST" });
|
||||
if (!res.ok) throw new Error(`Fehlgeschlagen (HTTP ${res.status})`);
|
||||
return res.json() as Promise<{ checked: number; updated: number }>;
|
||||
},
|
||||
onSuccess: (result) => {
|
||||
setMessage(
|
||||
result.updated > 0
|
||||
? `${result.updated} von ${result.checked} Diensten mit einem passenden Favicon aus der Icon-Datenbank ergänzt.`
|
||||
: `Keine passenden Treffer gefunden (${result.checked} Dienste ohne Favicon geprüft).`
|
||||
);
|
||||
queryClient.invalidateQueries({ queryKey: ["services"] });
|
||||
},
|
||||
onError: () => setMessage("Fehlgeschlagen - ist die Icon-Datenbank erreichbar (Internetzugang)?"),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 pb-2">
|
||||
{message ? <span className="text-xs text-black/40 dark:text-white/40">{message}</span> : null}
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setMessage(null);
|
||||
mutation.mutate();
|
||||
}}
|
||||
disabled={mutation.isPending}
|
||||
title="Für alle Dienste ohne Favicon einen passenden Treffer aus der Icon-Datenbank suchen"
|
||||
>
|
||||
{mutation.isPending ? "Suche …" : "Fehlende Favicons ergänzen"}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ServicesPage() {
|
||||
const { data: services, isLoading, isError } = useServices();
|
||||
const { data: devices } = useDevices();
|
||||
@@ -633,27 +673,30 @@ export function ServicesPage() {
|
||||
description="Spaltenköpfe anklickbar zum Sortieren; Drag & Drop (⠿⠿) nur in der Standard-Reihenfolge. Name, Kategorie, Alias, IP/Port/Protokoll und Reihenfolge bleiben bei erneuten Scans erhalten."
|
||||
/>
|
||||
|
||||
<div className="mb-4 flex gap-1 border-b border-black/10 dark:border-white/10">
|
||||
<button
|
||||
onClick={() => setActiveTab("visible")}
|
||||
className={`px-3 py-2 text-sm font-medium ${
|
||||
activeTab === "visible"
|
||||
? "border-b-2 border-black text-black dark:border-white dark:text-white"
|
||||
: "text-black/40 hover:text-black/70 dark:text-white/40 dark:hover:text-white/70"
|
||||
}`}
|
||||
>
|
||||
Sichtbar ({visibleCount})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("hidden")}
|
||||
className={`px-3 py-2 text-sm font-medium ${
|
||||
activeTab === "hidden"
|
||||
? "border-b-2 border-black text-black dark:border-white dark:text-white"
|
||||
: "text-black/40 hover:text-black/70 dark:text-white/40 dark:hover:text-white/70"
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faEyeSlash} /> Ausgeblendet ({hiddenCount})
|
||||
</button>
|
||||
<div className="mb-4 flex items-center justify-between gap-2 border-b border-black/10 dark:border-white/10">
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
onClick={() => setActiveTab("visible")}
|
||||
className={`px-3 py-2 text-sm font-medium ${
|
||||
activeTab === "visible"
|
||||
? "border-b-2 border-black text-black dark:border-white dark:text-white"
|
||||
: "text-black/40 hover:text-black/70 dark:text-white/40 dark:hover:text-white/70"
|
||||
}`}
|
||||
>
|
||||
Sichtbar ({visibleCount})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("hidden")}
|
||||
className={`px-3 py-2 text-sm font-medium ${
|
||||
activeTab === "hidden"
|
||||
? "border-b-2 border-black text-black dark:border-white dark:text-white"
|
||||
: "text-black/40 hover:text-black/70 dark:text-white/40 dark:hover:text-white/70"
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faEyeSlash} /> Ausgeblendet ({hiddenCount})
|
||||
</button>
|
||||
</div>
|
||||
<BackfillFaviconsButton />
|
||||
</div>
|
||||
|
||||
{sortColumn ? (
|
||||
|
||||
Reference in New Issue
Block a user