import { useState, useEffect, useMemo } from "react"; import { Graph, type GraphData, type GraphNode, type GraphLink, } from "@/modules/graph"; import { agentApiService } from "@/modules/agent/api/agent.api.service"; import { FaSpinner } from "react-icons/fa"; import { useAgentStore } from "@/app/providers/layout/store/agent.store"; const buildGraphFromApi = (apiData: any, agents: any[]): GraphData => { const nodes: GraphNode[] = []; const links: GraphLink[] = []; // Build a map of service statuses from agents const serviceStatusMap = new Map(); agents.forEach((agent) => { const services = agent.services || []; services.forEach((svc: string) => { // Parse "serviceName:up" or "serviceName:down" const parts = svc.split(":"); const svcName = parts[0]; const status = parts[1] === "down" ? "down" : "up"; serviceStatusMap.set(`${agent.label}-${svcName}`, status); }); }); if (!apiData?.nodes) return { nodes, links }; Object.entries(apiData.nodes).forEach( ([agentLabel, agentNode]: [string, any]) => { // Агент как узел nodes.push({ id: agentLabel, name: agentLabel, type: "agent", val: 8, description: `Агент: ${agentLabel}`, }); // Сервисы агента const services = agentNode?.services || {}; Object.entries(services).forEach( ([serviceName, serviceNode]: [string, any]) => { const serviceId = `${agentLabel}-${serviceName}`; const status = serviceStatusMap.get(serviceId) || "up"; nodes.push({ id: serviceId, name: serviceName, type: "service", val: 12, description: `Сервис: ${serviceName}`, status, }); // Связь агент → сервис links.push({ source: agentLabel, target: serviceId, type: "hosts", }); // Зависимости между сервисами const dependencies = serviceNode?.dependencies || []; dependencies.forEach((dep: any) => { const targetServiceName = dep?.target?.name; if (targetServiceName) { const targetServiceId = `${agentLabel}-${targetServiceName}`; links.push({ source: serviceId, target: targetServiceId, type: dep.condition || "dependency", }); } }); }, ); }, ); return { nodes, links }; }; export const GraphsPage = () => { const agents = useAgentStore((s) => s.agents); const [graphData, setGraphData] = useState({ nodes: [], links: [], }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchGraph = async () => { setLoading(true); setError(null); try { const apiData = await agentApiService.getGraph(); const data = buildGraphFromApi(apiData, agents); setGraphData(data); } catch (e) { console.error("Failed to fetch graph:", e); setError(e instanceof Error ? e.message : "Failed to load graph"); setGraphData({ nodes: [], links: [] }); } finally { setLoading(false); } }; fetchGraph(); const interval = setInterval(fetchGraph, 30000); return () => clearInterval(interval); }, [agents]); if (loading) { return (

Загрузка графа...

); } if (error && graphData.nodes.length === 0) { return (

{error}

); } return (
); };