round27: Ping-Regression rueckgaengig gemacht (Echo/Samsung-Geraete ignorieren ICMP), Aktualisiert-Text entfernt, Suchmaschinen-Hinweis+README, API-Scanner stark erweitert mit eigenem Reiter

This commit is contained in:
2026-07-24 09:24:57 +02:00
parent 0fc063b2a2
commit 430b79763c
10 changed files with 358 additions and 80 deletions

View File

@@ -0,0 +1,78 @@
import { useServices } from "../../hooks/useServices.js";
import { useDetectedApis, type DetectedApiEntry } from "../../hooks/useDetectedApis.js";
import { AdminPageHeader } from "./AdminPageHeader.js";
function formatDate(iso: string): string {
try {
return new Date(iso).toLocaleString("de-DE", { dateStyle: "medium", timeStyle: "short" });
} catch {
return iso;
}
}
export function ApisPage() {
const { data: services } = useServices();
const { data: apis, isLoading, isError } = useDetectedApis();
const serviceById = new Map((services ?? []).map((s) => [s.id, s]));
const groups = new Map<string, DetectedApiEntry[]>();
for (const entry of apis ?? []) {
const list = groups.get(entry.serviceId) ?? [];
list.push(entry);
groups.set(entry.serviceId, list);
}
return (
<div>
<AdminPageHeader
title="APIs"
description='Von einem eigenen, separaten Scan gefundene API-Endpunkte bekannter Dienste (siehe Admin -> Scanner -> "APIs jetzt scannen"). Läuft nie automatisch mit.'
/>
{isLoading ? (
<p className="text-sm text-black/40 dark:text-white/40">Lade </p>
) : isError ? (
<p className="text-sm text-red-500">Konnte nicht geladen werden.</p>
) : groups.size === 0 ? (
<p className="text-sm text-black/40 dark:text-white/40">
Noch keine APIs gefunden. Auf der Scanner-Seite einmal APIs jetzt scannen" ausführen.
</p>
) : (
<div className="space-y-4">
{Array.from(groups.entries()).map(([serviceId, entries]) => {
const service = serviceById.get(serviceId);
return (
<div key={serviceId} className="rounded-2xl border border-black/10 p-4 dark:border-white/10">
<div className="mb-2 flex items-center justify-between">
<h3 className="font-medium text-black dark:text-white">
{service?.displayName ?? "Unbekannter Dienst"}
</h3>
<span className="text-xs text-black/30 dark:text-white/30">
zuletzt geprüft: {formatDate(entries[0].detectedAt)}
</span>
</div>
<ul className="flex flex-wrap gap-2">
{entries.map((e) => (
<li key={e.id}>
<a
href={`${service?.url ?? ""}${e.path}`}
target="_blank"
rel="noopener noreferrer"
title={`HTTP ${e.status}`}
className="flex items-center gap-1.5 rounded-full bg-black/5 px-2.5 py-1 text-xs
text-black/70 hover:bg-black/10 dark:bg-white/10 dark:text-white/70
dark:hover:bg-white/20"
>
{e.type} · {e.path}
</a>
</li>
))}
</ul>
</div>
);
})}
</div>
)}
</div>
);
}