"use client" import { useMemo } from "react" import { type ColumnDef, getCoreRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table" import type { Server, VxlanTunnel } from "@/lib/data" import { Flag } from "@/components/flag" import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" 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 { CodeXmlIcon, MoreHorizontalIcon, NetworkIcon, PencilIcon, PowerIcon, Trash2Icon, } from "lucide-react" interface VxlanDataGridProps { tunnels: VxlanTunnel[] servers: Server[] onExport: (tunnel: VxlanTunnel) => void } function VxlanDataGrid({ tunnels, servers, onExport }: VxlanDataGridProps) { const serverMap = useMemo( () => new Map(servers.map((s) => [s.id, s])), [servers], ) const columns = useMemo[]>( () => [ { id: "name", accessorKey: "name", header: ({ column }) => ( ), cell: ({ row }) => { const t = row.original return (

{t.name}

VTEP: {t.vtepIp}

) }, meta: { headerTitle: "Имя / VTEP", headerClassName: DATA_GRID_CELL_PAD_FIRST, cellClassName: DATA_GRID_CELL_PAD_FIRST, }, }, { id: "server", accessorKey: "serverId", header: ({ column }) => , cell: ({ row }) => { const srv = serverMap.get(row.original.serverId) if (!srv) return return (
{srv.name}
) }, meta: { headerTitle: "Сервер", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "vni", accessorKey: "vni", header: ({ column }) => , cell: ({ row }) => {row.original.vni}, meta: { headerTitle: "VNI", headerClassName: DATA_GRID_CELL_PAD, cellClassName: cn(DATA_GRID_CELL_PAD, "text-center"), }, }, { id: "dstPort", accessorKey: "dstPort", header: ({ column }) => , cell: ({ row }) => {row.original.dstPort}, meta: { headerTitle: "Port", headerClassName: DATA_GRID_CELL_PAD, cellClassName: cn(DATA_GRID_CELL_PAD, "text-center"), }, }, { id: "remoteVteps", header: () => ( Remote ), enableSorting: false, cell: ({ row }) => ( {row.original.remoteVteps.length} ), meta: { headerTitle: "Remote", headerClassName: DATA_GRID_CELL_PAD, cellClassName: cn(DATA_GRID_CELL_PAD, "text-center"), }, }, { id: "arpProxy", accessorKey: "arpProxy", header: () => ARP, enableSorting: false, cell: ({ row }) => ( ARP {row.original.arpProxy ? "✓" : "✗"} ), meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD }, }, { id: "macLearning", accessorKey: "macLearning", header: () => MAC, enableSorting: false, cell: ({ row }) => ( MAC {row.original.macLearning ? "✓" : "✗"} ), meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD }, }, { id: "status", accessorKey: "status", header: ({ column }) => , cell: ({ row }) => ( {row.original.status === "up" ? "UP" : "DOWN"} ), meta: { headerTitle: "Статус", headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD, }, }, { id: "actions", header: () => Действия, cell: ({ row }) => { const tunnel = row.original return (
} /> onExport(tunnel)}> Экспорт .rsc Редактировать {tunnel.enabled ? "Отключить" : "Включить"} Удалить
) }, enableSorting: false, size: 56, meta: { headerClassName: DATA_GRID_CELL_PAD_LAST, cellClassName: DATA_GRID_CELL_PAD_LAST, }, }, ], [onExport, serverMap], ) const table = useReactTable({ data: tunnels, columns, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getRowId: (row) => row.id, }) if (tunnels.length === 0) { return ( } title="Нет VXLAN-туннелей" description="Добавьте туннель или измените поиск" className="border-0 py-16" /> ) } return ( ) } export { VxlanDataGrid, type VxlanDataGridProps }