import { Handle, Position, type Node, type NodeProps } from "@xyflow/react"; import type { ComponentRole, Criticality, HealthStatus, ServiceKind, } from "../api"; export type ServiceNodeData = { name: string; status: HealthStatus; kind: ServiceKind; latency: number | null; dependencyCount: number; rootCause: boolean; impacted: boolean; group: string | null; criticality: Criticality; flapping: boolean; category: string; application?: string; applicationNode?: boolean; memberIds?: string[]; nodeKind?: "domain" | "application" | "component"; role?: ComponentRole; roles?: ComponentRole[]; explanation?: string; monitoredComponents?: number; unmonitoredComponents?: number; domainId?: string; }; export type ServiceNode = Node; const statusLabel = (status: HealthStatus) => status === "unmonitored" ? "Not monitored" : status[0].toUpperCase() + status.slice(1); const statusIcon = (status: HealthStatus) => ({ healthy: "✓", degraded: "△", down: "!", recovering: "↻", maintenance: "Ⅱ", unknown: "?", unmonitored: "○", })[status]; export function ServiceNodeView({ data }: NodeProps) { const targetLabel = data.nodeKind === "domain" ? `${data.memberIds?.length ?? 0} components` : data.applicationNode ? `${data.monitoredComponents ?? 0} resolved · ${data.unmonitoredComponents ?? 0} unresolved` : data.latency != null ? `${data.latency} ms · ${data.kind.toUpperCase()}` : data.kind.toUpperCase(); return ( <>
{data.rootCause && ( ROOT CAUSE )} {!data.rootCause && data.impacted && ( IMPACTED )} {data.flapping && ( FLAPPING )}
{data.nodeKind === "domain" && ( DOMAIN · {data.memberIds?.length ?? 0} components )} {data.applicationNode && ( APPLICATION · {data.memberIds?.length ?? 0} components )} {data.applicationNode && data.roles?.length ? ( {data.roles.slice(0, 5).map((role) => ( {role.slice(0, 1).toUpperCase()} ))} ) : null} {data.nodeKind === "component" && ( {data.role ?? data.category} )} {data.name} {" "} {statusLabel(data.status)} {targetLabel} · {data.criticality} {data.explanation ?? `${data.category.replace("_", " ")} · ${data.dependencyCount} ${data.dependencyCount === 1 ? "dependency" : "dependencies"}`}
); }