fix(api): сохранять достоверные параметры рекурсивных маршрутов
This commit is contained in:
1 parent
50fad3ac80
commit
54ef752a5b
17 files changed
+198
-45
No files matched your search
@@ -7,7 +7,6 @@ import { PageHeader } from "@/components/page-header"
|
||||
import {
|
||||
RecursiveRoutesDataGrid,
|
||||
type RecursiveRouteGroup,
|
||||
inferCountry,
|
||||
} from "@/components/data-grids/recursive-routes-data-grid"
|
||||
import { FormField, SectionTitle } from "@/components/form-kit"
|
||||
import { DataPageCard } from "@/components/data-page-card"
|
||||
@@ -47,7 +46,7 @@ interface GatewayOption {
|
||||
id: string
|
||||
name: string
|
||||
ip: string
|
||||
status: "up" | "down"
|
||||
status: "active" | "inactive" | "unknown"
|
||||
}
|
||||
|
||||
const COUNTRY_OPTIONS = [
|
||||
@@ -100,6 +99,7 @@ interface RouteForm {
|
||||
|
||||
interface RouteEndpointForm {
|
||||
id: string
|
||||
disabled: boolean
|
||||
gateway: string
|
||||
distance: number
|
||||
scope: number | null
|
||||
@@ -110,6 +110,7 @@ interface RouteEndpointForm {
|
||||
|
||||
const newEndpoint = (): RouteEndpointForm => ({
|
||||
id: `ep-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
||||
disabled: false,
|
||||
gateway: "",
|
||||
distance: 1,
|
||||
scope: null,
|
||||
@@ -241,7 +242,7 @@ function RouteSheet({
|
||||
<div key={ep.id} className="rounded-lg border border-border bg-muted/20 p-3 flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
||||
Endpoint {idx + 1}
|
||||
Endpoint {idx + 1}{ep.disabled ? " · отключён" : ""}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
@@ -282,7 +283,6 @@ function RouteSheet({
|
||||
{gateways.map((g) => {
|
||||
const value = `${g.ip}%${g.name}`
|
||||
const selected = ep.gateway === value
|
||||
const country = inferCountry(g.name)
|
||||
return (
|
||||
<button
|
||||
key={`${ep.id}-${g.id}`}
|
||||
@@ -296,9 +296,9 @@ function RouteSheet({
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={cn("size-1.5 rounded-full shrink-0", g.status === "up" ? "bg-emerald-500" : "bg-red-500")} />
|
||||
{country && <Flag code={country} className="shrink-0" />}
|
||||
<span className={cn("size-1.5 rounded-full shrink-0", g.status === "active" ? "bg-success" : "bg-muted-foreground")} />
|
||||
<span className="font-mono text-xs font-semibold flex-1 truncate">{g.name}</span>
|
||||
<span className="text-xs text-muted-foreground">{g.status === "active" ? "Активный маршрут" : g.status === "inactive" ? "Неактивный маршрут" : "Статус неизвестен"}</span>
|
||||
{selected && <CheckIcon className="size-3.5 text-primary shrink-0" />}
|
||||
</div>
|
||||
<div className="mt-1.5 grid grid-cols-[auto_auto_1fr] items-start gap-2 text-[11px] text-muted-foreground font-mono">
|
||||
@@ -466,7 +466,7 @@ function RecursiveRoutesContent({ mode, backendUrl, context, patchUrl, beginWrit
|
||||
const epoch = ++readEpoch.current
|
||||
setOpError(null); setBusy("load"); setLiveStale(true)
|
||||
try {
|
||||
const parsed = recursiveReadSchema.safeParse(await apiFetch<unknown>(`/api/recursive-routes?serverId=${encodeURIComponent(selectedServerId)}`))
|
||||
const parsed = recursiveReadSchema.safeParse(await apiFetch<unknown>(`/api/recursive-routes/catalog?serverId=${encodeURIComponent(selectedServerId)}`))
|
||||
if (!parsed.success) throw new Error("Некорректный снимок маршрутов в ответе API")
|
||||
const res = parsed.data
|
||||
if (String(res.serverId) !== selectedServerId) throw new Error("Маршруты принадлежат другому устройству")
|
||||
@@ -486,7 +486,7 @@ function RecursiveRoutesContent({ mode, backendUrl, context, patchUrl, beginWrit
|
||||
if (!isLive || !liveServerListReady || !selectedServerId || context.error || !servers.some(s => s.id === selectedServerId)) return
|
||||
const epoch = ++gatewayEpoch.current
|
||||
try {
|
||||
const parsed = recursiveGatewaysSchema.safeParse(await apiFetch<unknown>(`/api/recursive-routes/gateways?serverId=${encodeURIComponent(selectedServerId)}`))
|
||||
const parsed = recursiveGatewaysSchema.safeParse(await apiFetch<unknown>(`/api/recursive-routes/gateways/catalog?serverId=${encodeURIComponent(selectedServerId)}`))
|
||||
if (!parsed.success) throw new Error("Некорректный список шлюзов в ответе API")
|
||||
const res = parsed.data
|
||||
if (String(res.serverId) !== selectedServerId) throw new Error("Шлюзы принадлежат другому устройству")
|
||||
@@ -596,6 +596,7 @@ function RecursiveRoutesContent({ mode, backendUrl, context, patchUrl, beginWrit
|
||||
comment: group.comment,
|
||||
endpoints: endpoints.map(ep => ({
|
||||
id: ep.id,
|
||||
disabled: ep.disabled,
|
||||
gateway: ep.gateway,
|
||||
distance: ep.distance,
|
||||
scope: ep.scope,
|
||||
@@ -617,8 +618,8 @@ function RecursiveRoutesContent({ mode, backendUrl, context, patchUrl, beginWrit
|
||||
routingTable: v.routingTable,
|
||||
checkGateway: ep.checkGateway,
|
||||
comment: v.comment,
|
||||
disabled: false,
|
||||
country: ep.country || inferCountry(ep.gateway) || "",
|
||||
disabled: ep.disabled,
|
||||
country: ep.country || "",
|
||||
})
|
||||
let next: RecursiveRouteRow[]
|
||||
if (sheetMode === "create") {
|
||||
|
||||
Reference in new issue
Block a user