fix(ui): восстанавливать фильтры WireGuard из ссылки

This commit is contained in:
Denozordec committed 2026-10-04 12:30:43 +07:00
1 parent c6702efcc4
commit e51964b4d2
8 files changed
+103 -13

No files matched your search

+12 -12
View File
@@ -3,6 +3,8 @@
import { Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react"
import Link from "next/link"
import { useRouter, useSearchParams } from "next/navigation"
import { useWireGuardUrlState } from "@/hooks/use-wireguard-url-state"
import type { WireGuardTab as WgWorkspaceTab } from "@/lib/wireguard-url-state"
import { PageHeader } from "@/components/page-header"
import { servers as mockServers } from "@/lib/data"
import type { Server } from "@/lib/data"
@@ -69,8 +71,6 @@ import {
Trash2Icon, CodeXmlIcon, AlertCircleIcon, HistoryIcon,
} from "lucide-react"
type WgWorkspaceTab = "interfaces" | "peers" | "cli"
type WgStatusFilter = "all" | "up" | "down"
type WgFailure = { serverId: string; serverName?: string; error: string }
type PendingDelete =
| { kind: "iface"; iface: WgIfaceWithServer }
@@ -192,9 +192,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
const [togglePending, setTogglePending] = useState<string | null>(null)
const [toggleError, setToggleError] = useState<string | null>(null)
const [workspaceTab, setWorkspaceTab] = useState<WgWorkspaceTab>("interfaces")
const [statusFilter, setStatusFilter] = useState<WgStatusFilter>("all")
const [search, setSearch] = useState("")
const { tab: workspaceTab, setTab: setWorkspaceTab, status: statusFilter, setStatus: setStatusFilter, search, setSearch, error: urlError, resetFilters } = useWireGuardUrlState()
const [createOpen, setCreateOpen] = useState(false)
const [importOpen, setImportOpen] = useState(false)
const formLock = useRef(false)
@@ -271,7 +269,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
const displayServers = isLive ? liveServers : mockServers.filter((s) => s.enabled)
const effectiveServerId = selectedServerId
const selectedSourceError = isLive && (loadError || failures.some(f => f.serverId === selectedServerId))
const selectedSourceError = !!urlError || isLive && (loadError || failures.some(f => f.serverId === selectedServerId))
const historyServerId = effectiveServerId === ALL_SERVERS_ID ? null : effectiveServerId
@@ -315,10 +313,11 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}, [isLive, historyServerId, backendUrl, loadLive, loadRevisions])
const scopedIfaces = useMemo(() => {
if (urlError) return []
if (selectedInterfaceId !== null) return displayIfaces.filter(i => i.serverId === effectiveServerId && i.id === selectedInterfaceId)
if (effectiveServerId === ALL_SERVERS_ID) return displayIfaces
return displayIfaces.filter((i) => i.serverId === effectiveServerId)
}, [displayIfaces, effectiveServerId, selectedInterfaceId])
}, [displayIfaces, effectiveServerId, selectedInterfaceId, urlError])
const selectedInterface = selectedInterfaceId === null ? undefined : scopedIfaces[0]
@@ -418,7 +417,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}, [displayServers, displayIfaces])
async function handleCreate(form: WgCreateFormState) {
if (formLock.current) return
if (urlError || formLock.current) return
if (!isLive) {
toast.info("Создание на роутер доступно только в live-режиме")
return
@@ -502,7 +501,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}
function sourceUnavailable(serverId: string | undefined) {
const unavailable = isLive && (loadError || failures.some(f => f.serverId === serverId))
const unavailable = !!urlError || isLive && (loadError || failures.some(f => f.serverId === serverId))
if (unavailable) toast.error("Обновите данные сервера перед изменением объекта")
return unavailable
}
@@ -652,7 +651,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}
const emptyCreateAction = (
<Button size="sm" onClick={() => { setCreateError(null); setCreateOpen(true) }}>
<Button size="sm" disabled={!!urlError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
<PlusIcon className="size-4" />
Новый интерфейс
</Button>
@@ -700,11 +699,11 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
</Button>
</>
)}
<Button size="sm" variant="outline" onClick={() => { setImportError(null); setImportOpen(true) }}>
<Button size="sm" variant="outline" disabled={!!urlError} onClick={() => { setImportError(null); setImportOpen(true) }}>
<UploadIcon className="size-4" />
Импорт
</Button>
<Button size="sm" onClick={() => { setCreateError(null); setCreateOpen(true) }}>
<Button size="sm" disabled={!!urlError} onClick={() => { setCreateError(null); setCreateOpen(true) }}>
<PlusIcon className="size-4" />
Новый интерфейс
</Button>
@@ -714,6 +713,7 @@ function WireGuardPageContent({ selectedServerId, selectedInterfaceId, allInterf
}
>
<div className="flex flex-col gap-4">
{urlError && <Alert variant="warning" role="alert" aria-label="Фильтры WireGuard"><AlertTitle>Проверьте ссылку</AlertTitle><AlertDescription><p>{urlError}</p><Button type="button" variant="outline" onClick={resetFilters}>Сбросить фильтры</Button></AlertDescription></Alert>}
{isLive && loadError && selectedInterfaceId === null && <Alert variant="warning"><AlertTitle>Не удалось обновить WireGuard</AlertTitle><AlertDescription>Показаны последние полученные данные. Повторите обновление перед изменением объектов.</AlertDescription></Alert>}
{selectedInterfaceId !== null && (
<Alert variant={selectedSourceError || ((!isLive || !loading) && !selectedInterface) ? "warning" : "info"} role="status" aria-label="WireGuard по ссылке">