import { Plus, Search, Server } from "lucide-react"; import type { Metadata } from "next"; import Link from "next/link"; import { adresseMitPort, HostKeyBadge } from "@/components/hosts/Anzeige"; import { Badge } from "@/components/ui/Badge"; import { Button } from "@/components/ui/Button"; import { Auswahlliste, Feld } from "@/components/ui/Feld"; import { Karte } from "@/components/ui/Karte"; import { Leerzustand } from "@/components/ui/Leerzustand"; import { Seitenkopf } from "@/components/ui/Seitenkopf"; import { Statuspunkt } from "@/components/ui/Statuspunkt"; import { Tabelle, TabellenZeile, TabellenZelle } from "@/components/ui/Tabelle"; import { datumZeit, relativ } from "@/lib/format"; import { darf } from "@/server/auth/rechte"; import { sitzungErforderlich } from "@/server/auth/sitzungspflicht"; import { gruppenAuswahl, hostListe, type HostListenEintrag } from "@/server/queries/hosts"; export const metadata: Metadata = { title: "Hosts" }; type Suchparameter = Promise>; function einzeln(wert: string | string[] | undefined): string { return (Array.isArray(wert) ? wert[0] : wert)?.trim() ?? ""; } function statusText(h: HostListenEintrag): string | undefined { if (h.status !== "drift" || h.offeneAbweichungen === 0) return undefined; return h.offeneAbweichungen === 1 ? "1 Abweichung" : `${h.offeneAbweichungen} Abweichungen`; } function Abgleich({ wert, jetzt }: { wert: Date | null; jetzt: Date }) { if (!wert) return <>noch nie; return ( ); } /** Hostliste mit Suche und Gruppenfilter (#008). Filter per GET, damit Links teilbar sind. */ export default async function Hosts({ searchParams }: { searchParams: Suchparameter }) { // Jede Seite prueft selbst; die Huelle ist nur das zweite Netz (CLAUDE.md). const { benutzer } = await sitzungErforderlich("lesen", "/hosts"); const parameter = await searchParams; const q = einzeln(parameter["q"]); const gruppeId = einzeln(parameter["gruppe"]); const [hosts, gruppen] = await Promise.all([ hostListe({ q, gruppeId: gruppeId || undefined }), gruppenAuswahl(), ]); const verwalten = darf(benutzer.rolle, "hostsVerwalten"); const gefiltert = q !== "" || gruppeId !== ""; const jetzt = new Date(); return (
}> Host anlegen ) } />
{gruppen.map((g) => ( ))}
{gefiltert && ( )}
{hosts.length === 0 ? ( gefiltert ? ( } titel="Keine Treffer" text="Kein Host passt zu Suche und Gruppe." aktion={} /> ) : ( } titel="Noch keine Hosts" text="Legen Sie den ersten Server an. Danach ruft sshkv seinen Host-Key ab und richtet den Zugang ein." aktion={ verwalten && ( ) } /> ) ) : ( {/* Unter md eine Liste statt der Tabelle: sechs Spalten passen nicht auf 390 px, und Status und Host-Key sollen ohne seitliches Wischen sichtbar sein (#008). */}
    {hosts.map((h) => (
  • {h.name} {adresseMitPort(h.adresse, h.port)} {h.gruppen.map((g) => ( {g.name} ))} Letzter Abgleich:
  • ))}
{hosts.map((h) => ( {h.name} {adresseMitPort(h.adresse, h.port)} {h.gruppen.length === 0 ? ( – ) : ( {h.gruppen.map((g) => ( {g.name} ))} )} ))}
)}
); }