"use client" import { dataGridFeatures, type DataGridFeatures } from "@/components/reui/data-grid" import { useMemo } from "react" import { type ColumnDef, useTable, } from "@tanstack/react-table" import type { BfdState } from "@/lib/ospf-state" import { cn } from "@/lib/utils" import { DataGridShell } from "@/components/data-grids/shared/data-grid-shell" import { DATA_GRID_CELL_PAD, DATA_GRID_CELL_PAD_FIRST, DATA_GRID_CELL_PAD_LAST, } from "@/components/data-grids/shared/data-grid-layout" import { DataGridSortHeader } from "@/components/data-grids/shared/data-grid-sort-header" import { EmptyState } from "@/components/empty-state" import { ActivityIcon } from "lucide-react" export interface BfdSessionRow { id: string dataUnknown?: boolean serverId: string serverLabel: string localAddr: string remoteAddr: string state: BfdState interval: number | null multiplier: number | null iface: string uptime: string | null multihop: boolean | null rxInterval: number | null holdTime: number | null packetsRx: number | null packetsTx: number | null stateChanges: number | null } function stateClass(state: BfdSessionRow["state"]) { if (state === "Unknown") return "bg-muted text-muted-foreground border-border" if (state === "Up") return "bg-[var(--status-online-bg)] text-[var(--status-online-fg)] border-current/25" if (state === "Init") return "bg-[var(--status-degraded-bg)] text-[var(--status-degraded-fg)] border-current/25" return "bg-[var(--status-offline-bg)] text-[var(--status-offline-fg)] border-current/25" } function Chip({ children, color }: { children: React.ReactNode; color?: string }) { return ( {children} ) } function fmtMs(ms: number | null) { if (ms === null) return "—" if (ms < 1000) return `${ms}ms` return `${(ms / 1000).toFixed(1)}s` } interface OspfBfdDataGridProps { sessions: BfdSessionRow[] } function OspfBfdDataGrid({ sessions }: OspfBfdDataGridProps) { const columns = useMemo[]>( () => [ { id: "serverLabel", accessorKey: "serverLabel", header: ({ column }) => ( ), cell: ({ row }) => { const b = row.original return (
{b.serverLabel} {b.multihop === null && Режим неизвестен} {b.multihop === true && ( multihop )}
) }, meta: { headerTitle: "Роутер", headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST, }, }, { id: "iface", accessorKey: "iface", header: ({ column }) => , cell: ({ row }) => ( {row.original.iface || "—"} ), meta: { headerTitle: "Интерфейс", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "localAddr", accessorKey: "localAddr", header: ({ column }) => , cell: ({ row }) => ( {row.original.localAddr} ), meta: { headerTitle: "Локальный", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "remoteAddr", accessorKey: "remoteAddr", header: ({ column }) => , cell: ({ row }) => ( {row.original.remoteAddr} ), meta: { headerTitle: "Удалённый", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "state", accessorKey: "state", header: ({ column }) => , cell: ({ row }) => ( {row.original.dataUnknown || row.original.state === "Unknown" ? "Неизвестно" : row.original.state} ), meta: { headerTitle: "Состояние", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "uptime", accessorKey: "uptime", header: ({ column }) => , cell: ({ row }) => ( {row.original.uptime ?? "—"} ), meta: { headerTitle: "Uptime", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "intervals", header: () => TX факт / RX минимум, enableSorting: false, cell: ({ row }) => { const b = row.original return ( {fmtMs(b.interval)} / {fmtMs(b.rxInterval)} ) }, meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD }, }, { id: "holdTime", accessorKey: "holdTime", header: ({ column }) => , cell: ({ row }) => ( {fmtMs(row.original.holdTime)} ), meta: { headerTitle: "Hold", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "multiplier", accessorKey: "multiplier", header: ({ column }) => , cell: ({ row }) => ( {row.original.multiplier ?? "—"} ), meta: { headerTitle: "Mult", headerClassName: DATA_GRID_CELL_PAD, cellClassName: cn(DATA_GRID_CELL_PAD, "text-center"), }, }, { id: "packetsRx", accessorKey: "packetsRx", header: ({ column }) => ( ), cell: ({ row }) => ( {row.original.packetsRx?.toLocaleString() ?? "—"} ), meta: { headerTitle: "Пакеты Rx", headerClassName: cn(DATA_GRID_CELL_PAD, "text-right"), cellClassName: cn(DATA_GRID_CELL_PAD, "text-right"), }, }, { id: "packetsTx", accessorKey: "packetsTx", header: ({ column }) => ( ), cell: ({ row }) => ( {row.original.packetsTx?.toLocaleString() ?? "—"} ), meta: { headerTitle: "Пакеты Tx", headerClassName: DATA_GRID_CELL_PAD, cellClassName: cn(DATA_GRID_CELL_PAD, "text-right"), }, }, { id: "stateChanges", accessorKey: "stateChanges", header: ({ column }) => ( ), cell: ({ row }) => ( {row.original.stateChanges ?? "—"} ), meta: { headerTitle: "Переходы", headerClassName: DATA_GRID_CELL_PAD_LAST, cellClassName: cn(DATA_GRID_CELL_PAD_LAST, "text-right"), }, }, ], [], ) const table = useTable({ features: dataGridFeatures, manualPagination: true, data: sessions, columns, getRowId: (row) => row.id, }) if (sessions.length === 0) { return ( } title="BFD-сессий не обнаружено" className="border-0 py-10" /> ) } return ( ) } export { OspfBfdDataGrid, type OspfBfdDataGridProps }