diff --git a/app/(main)/ospf/page.tsx b/app/(main)/ospf/page.tsx index d4885c07..c9825098 100644 --- a/app/(main)/ospf/page.tsx +++ b/app/(main)/ospf/page.tsx @@ -46,13 +46,13 @@ interface OspfItem { serverId: string interfaceName: string area: string - cost: number - active: boolean + cost: number | null + active: boolean | null dataUnknown?: boolean - type?: string - useBfd?: boolean - helloInterval?: number - deadInterval?: number + type?: string | null + useBfd?: boolean | null + helloInterval?: number | null + deadInterval?: number | null } interface OspfNeighbor { @@ -75,7 +75,7 @@ interface OspfRoute { id: string destination: string type: "O" | "O IA" | "O E1" | "O E2" - cost: number + cost: number | null nextHop: string via: string serverId: string @@ -106,31 +106,10 @@ interface BfdSession { // ─── backend types ──────────────────────────────────────────────────────────── -interface BackendNeighbor { - id: string; serverId: number; serverName: string; serverSite: string; serverCountry: string - address: string; routerId: string; instance: string; area: string; areaId: string - interface: string; state: string; uptime: string | null; stateChanges: number | null; priority: number | null -} - -interface BackendInterface { - id: string; serverId: number; serverName: string; serverSite: string; serverCountry: string - instance: string; area: string; areaId: string; interface: string; cost: number - type: string; disabled: boolean; inactive: boolean; priority: number - helloInterval: number; deadInterval: number; useBfd: boolean -} - - -interface BackendBfdSession { - id: string; serverId: number; serverName: string; serverSite: string; serverCountry: string - localAddr: string; remoteAddr: string; interface: string; state: string; uptime: string | null - multihop: boolean; multiplier: number | null; txInterval: number | null; rxInterval: number | null; holdTime: number | null - packetsRx: number | null; packetsTx: number | null; stateChanges: number | null -} - -interface BackendOspfRoute { - id: string; serverId: number; serverName: string; serverSite: string - destination: string; type: OspfRoute["type"]; cost: number; nextHop: string; via: string; area: string -} +type BackendNeighbor = OspfCatalog["neighbors"][number] +type BackendInterface = OspfCatalog["interfaces"][number] +type BackendBfdSession = OspfCatalog["bfdSessions"][number] +type BackendOspfRoute = OspfCatalog["routes"][number] function isRefInterfaceName(name: string): boolean { @@ -168,7 +147,7 @@ function backendToItem(b: BackendInterface): OspfItem { interfaceName: b.interface, area: b.areaId, cost: b.cost, - active: !b.disabled && !b.inactive, + active: b.disabled === true || b.inactive === true ? false : b.disabled === false && b.inactive === false ? true : null, type: b.type, useBfd: b.useBfd, helloInterval: b.helloInterval, @@ -637,7 +616,7 @@ function NodeDetailPanel({ {iface.area === "0.0.0.0" ? "backbone" : `area ${iface.area}`} - cost {iface.cost} + cost {iface.cost ?? "—"} ))} @@ -696,7 +675,7 @@ function InterfacesTab({ return Object.values(byRouter).map(r => ({ ...r, areas: Object.entries(r.areas) - .map(([area, areaItems]) => ({ area, items: [...areaItems].sort((a, b) => a.cost - b.cost) })) + .map(([area, areaItems]) => ({ area, items: [...areaItems].sort((a, b) => (a.cost ?? Infinity) - (b.cost ?? Infinity)) })) .sort((a, b) => a.area.localeCompare(b.area)), })) }, [items]) @@ -765,7 +744,7 @@ function InterfacesTab({ function onDrop(routerKey: string, area: string, targetKey: string) { if (!dragging || dragging === targetKey) { setDragging(null); setDragOver(null); return } setItems(prev => { - const areaItems = prev.filter(i => i.routerKey === routerKey && i.area === area).sort((a, b) => a.cost - b.cost) + const areaItems = prev.filter(i => i.routerKey === routerKey && i.area === area).sort((a, b) => (a.cost ?? Infinity) - (b.cost ?? Infinity)) const fromIdx = areaItems.findIndex(i => i.key === dragging) const toIdx = areaItems.findIndex(i => i.key === targetKey) if (fromIdx < 0 || toIdx < 0) return prev @@ -785,6 +764,7 @@ function InterfacesTab({ return (
+ {isLive && filterServerId !== ALL_SERVERS_ID && !dataReady &&

Оптимизация недоступна до полного успешного опроса и подтверждения costs/состояний интерфейсов с правом записи.

} {operationError && Оптимизация OSPF не подтверждена{operationError}}