feat(filters, recursive-routes): enhance configuration history and live data handling
- Introduced configuration history management in Filters and Recursive Routes pages, allowing users to view and restore previous configurations. - Updated state management to handle live data loading and error states more effectively, improving user experience during data fetching. - Added new components for displaying configuration history and integrated them into existing pages. - Enhanced API interactions to support fetching and applying configuration revisions, ensuring data consistency across the application. - Updated tests to cover new functionalities and ensure reliability. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -11,7 +11,6 @@ import type { FilterRule, GreTunnel, Server } from "@/lib/data"
|
||||
import { Flag } from "@/components/flag"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { DataGridShell } from "@/components/data-grids/shared/data-grid-shell"
|
||||
import {
|
||||
DATA_GRID_CELL_PAD,
|
||||
@@ -22,21 +21,15 @@ import { DataGridSortHeader } from "@/components/data-grids/shared/data-grid-sor
|
||||
import { EmptyState } from "@/components/empty-state"
|
||||
import {
|
||||
AlertCircleIcon,
|
||||
AlertTriangleIcon,
|
||||
CheckCircle2Icon,
|
||||
ChevronDownIcon,
|
||||
ChevronUpIcon,
|
||||
CircleDashedIcon,
|
||||
PencilIcon,
|
||||
RouteIcon,
|
||||
StarIcon,
|
||||
TrashIcon,
|
||||
XCircleIcon,
|
||||
FilterIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
export type FilterRouterSyncStatus = "synced" | "drift" | "missing"
|
||||
|
||||
export interface RecursiveRouteLite {
|
||||
id: string
|
||||
dstAddress: string
|
||||
@@ -47,42 +40,6 @@ export interface RecursiveRouteLite {
|
||||
disabled: boolean
|
||||
}
|
||||
|
||||
function RouterSyncMarker({
|
||||
status,
|
||||
}: {
|
||||
status: FilterRouterSyncStatus | null | "skip"
|
||||
}) {
|
||||
if (status === "skip") {
|
||||
return <span className="size-3.5 shrink-0 block" aria-hidden />
|
||||
}
|
||||
const icon =
|
||||
status === "synced"
|
||||
? <CheckCircle2Icon className="size-3.5 text-emerald-600 dark:text-emerald-500 shrink-0" />
|
||||
: status === "drift"
|
||||
? <AlertTriangleIcon className="size-3.5 text-amber-500 shrink-0" />
|
||||
: status === "missing"
|
||||
? <XCircleIcon className="size-3.5 text-destructive shrink-0" />
|
||||
: <CircleDashedIcon className="size-3.5 text-muted-foreground/35 shrink-0" />
|
||||
const title =
|
||||
status === "synced"
|
||||
? "Совпадает с цепочкой bgp-in на MikroTik"
|
||||
: status === "drift"
|
||||
? "В БД и на роутере разное действие (gateway, blackhole или out-interface)"
|
||||
: status === "missing"
|
||||
? "Эта community не найдена в правиле bgp-in на роутере"
|
||||
: "Не проверено — нажмите «Сверить с роутером»"
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger className="inline-flex cursor-default border-0 bg-transparent p-0">
|
||||
{icon}
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" className="max-w-xs">
|
||||
{title}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
function innerIpToGateway(ip: string) {
|
||||
return ip.split("/")[0]
|
||||
}
|
||||
@@ -234,8 +191,6 @@ interface FiltersDataGridProps {
|
||||
serversList: Server[]
|
||||
communityNameMap: Record<string, string>
|
||||
recursiveRoutes: RecursiveRouteLite[]
|
||||
routerSyncByCommunity?: Record<string, FilterRouterSyncStatus> | null
|
||||
isLive?: boolean
|
||||
enableSorting?: boolean
|
||||
onEdit: (rule: FilterRule) => void
|
||||
onDelete: (id: string) => void
|
||||
@@ -249,8 +204,6 @@ function FiltersDataGrid({
|
||||
serversList,
|
||||
communityNameMap,
|
||||
recursiveRoutes,
|
||||
routerSyncByCommunity,
|
||||
isLive,
|
||||
enableSorting = false,
|
||||
onEdit,
|
||||
onDelete,
|
||||
@@ -308,33 +261,6 @@ function FiltersDataGrid({
|
||||
size: 28,
|
||||
meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
|
||||
},
|
||||
{
|
||||
id: "routerSync",
|
||||
header: () => (
|
||||
<Tooltip>
|
||||
<TooltipTrigger className="cursor-help font-mono text-xs text-muted-foreground border-0 bg-transparent p-0">
|
||||
MT
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" className="max-w-xs">
|
||||
Совпадение с MikroTik (bgp-in)
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
),
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => (
|
||||
<RouterSyncMarker
|
||||
status={
|
||||
!isLive
|
||||
? "skip"
|
||||
: !routerSyncByCommunity
|
||||
? null
|
||||
: routerSyncByCommunity[row.original.community.trim()] ?? null
|
||||
}
|
||||
/>
|
||||
),
|
||||
size: 32,
|
||||
meta: { headerClassName: DATA_GRID_CELL_PAD, cellClassName: DATA_GRID_CELL_PAD },
|
||||
},
|
||||
{
|
||||
id: "community",
|
||||
accessorKey: "community",
|
||||
@@ -413,13 +339,11 @@ function FiltersDataGrid({
|
||||
[
|
||||
communityNameMap,
|
||||
enableSorting,
|
||||
isLive,
|
||||
onDelete,
|
||||
onEdit,
|
||||
onMoveDown,
|
||||
onMoveUp,
|
||||
recursiveRoutes,
|
||||
routerSyncByCommunity,
|
||||
serversList,
|
||||
tunnelsList,
|
||||
],
|
||||
@@ -454,4 +378,4 @@ function FiltersDataGrid({
|
||||
)
|
||||
}
|
||||
|
||||
export { FiltersDataGrid, RouterSyncMarker, type FiltersDataGridProps }
|
||||
export { FiltersDataGrid, type FiltersDataGridProps }
|
||||
|
||||
Reference in New Issue
Block a user