fix(ui): восстанавливать поиск и фильтры BGP из URL
This commit is contained in:
1 parent
5c307a5b6c
commit
aa678b9d5d
8 files changed
+220
-16
No files matched your search
+14
-15
@@ -5,9 +5,8 @@ import { useRouter, useSearchParams } from "next/navigation"
|
||||
import { PageHeader } from "@/components/page-header"
|
||||
import { DataPageToolbar } from "@/components/data-page-toolbar"
|
||||
import { BgpSessionsDataGrid } from "@/components/data-grids/bgp-sessions-data-grid"
|
||||
import { createFilterQuery } from "@/components/reui/filters/filters-query"
|
||||
import { useBgpUrlState } from "@/hooks/use-bgp-url-state"
|
||||
import { QueryFilters } from "@/components/data-grids/query-filters"
|
||||
import type { FilterQuery } from "@/components/reui/filters/filters-types"
|
||||
import { applyFilterQuery } from "@/lib/data-filters/apply-filter-query"
|
||||
import { BGP_FILTER_FIELDS } from "@/lib/data-filters/bgp-filter-fields"
|
||||
import type { BgpSessionRow, BgpState, BgpType } from "@/lib/bgp/types"
|
||||
@@ -37,8 +36,6 @@ import { ALL_SERVERS_ID, type ServerTileItem } from "@/components/server-tile-ra
|
||||
|
||||
type BgpSession = BgpSessionRow
|
||||
type BgpTab = "sessions" | "routers" | "analytics"
|
||||
type StateFilter = "all" | BgpState
|
||||
type TypeFilter = "all" | BgpType
|
||||
|
||||
const AS_NAMES = BGP_AS_NAMES
|
||||
// ─── mock data ────────────────────────────────────────────────────────────────
|
||||
@@ -261,13 +258,11 @@ const BGP_FILTER_ACCESSORS = {
|
||||
}
|
||||
|
||||
function SessionsTab({ sessions, emptyTitle, selectedSessionId, onSelectSession }: { sessions: BgpSession[]; emptyTitle?: string; selectedSessionId: string | null; onSelectSession: (id: string | null) => void }) {
|
||||
const [search, setSearch] = useState("")
|
||||
const [stateFilter, setStateFilter] = useState<StateFilter>("all")
|
||||
const [typeFilter, setTypeFilter] = useState<TypeFilter>("all")
|
||||
const [advancedFilters, setAdvancedFilters] = useState<FilterQuery>(() => createFilterQuery())
|
||||
|
||||
const { search, setSearch, stateFilter, setStateFilter, typeFilter, setTypeFilter, filters: advancedFilters, setFilters: setAdvancedFilters, error: urlError, hasFilters, reset } = useBgpUrlState()
|
||||
const fields = useMemo(() => BGP_FILTER_FIELDS.map(field => field.id === "afi" ? { ...field, options: Array.from(new Set(sessions.map(s => s.afi))).sort().map(value => ({ value, label: value })) } : field), [sessions])
|
||||
const q = search.toLowerCase()
|
||||
const filtered = useMemo(() => {
|
||||
if (urlError) return []
|
||||
const base = sessions.filter((s) => {
|
||||
if (stateFilter !== "all" && s.state !== stateFilter) return false
|
||||
if (typeFilter !== "all" && s.type !== typeFilter) return false
|
||||
@@ -275,7 +270,7 @@ function SessionsTab({ sessions, emptyTitle, selectedSessionId, onSelectSession
|
||||
q &&
|
||||
!s.peerIp.includes(q) &&
|
||||
!s.description.toLowerCase().includes(q) &&
|
||||
!s.serverLabel.includes(q) &&
|
||||
!s.serverLabel.toLowerCase().includes(q) &&
|
||||
!String(s.remoteAs).includes(q) &&
|
||||
!(s.remoteAs === null ? "" : AS_NAMES[s.remoteAs] ?? "").toLowerCase().includes(q)
|
||||
) {
|
||||
@@ -284,10 +279,11 @@ function SessionsTab({ sessions, emptyTitle, selectedSessionId, onSelectSession
|
||||
return true
|
||||
})
|
||||
return applyFilterQuery(base, advancedFilters, BGP_FILTER_ACCESSORS)
|
||||
}, [sessions, q, stateFilter, typeFilter, advancedFilters])
|
||||
}, [sessions, q, stateFilter, typeFilter, advancedFilters, urlError])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{urlError && <Alert variant="warning"><AlertCircleIcon /><AlertDescription>{urlError}<Button variant="outline" size="sm" onClick={reset}>Сбросить фильтры BGP</Button></AlertDescription></Alert>}
|
||||
<DataPageCard>
|
||||
<DataPageToolbar
|
||||
segmented={{
|
||||
@@ -295,24 +291,26 @@ function SessionsTab({ sessions, emptyTitle, selectedSessionId, onSelectSession
|
||||
onChange: setStateFilter,
|
||||
options: [
|
||||
{ value: "all", label: "Все", count: sessions.length },
|
||||
{ value: "Unknown", label: "Неизвестно", count: sessions.filter(s => s.state === "Unknown").length },
|
||||
{ value: "Established", label: "Established", count: sessions.filter((s) => s.state === "Established").length },
|
||||
{ value: "Active", label: "Active", count: sessions.filter((s) => s.state === "Active").length },
|
||||
{ value: "Idle", label: "Idle", count: sessions.filter((s) => s.state === "Idle").length },
|
||||
{ value: "OpenSent", label: "OpenSent", count: sessions.filter((s) => s.state === "OpenSent").length },
|
||||
],
|
||||
}}
|
||||
filterControl={<QueryFilters fields={BGP_FILTER_FIELDS} query={advancedFilters} onQueryChange={setAdvancedFilters} />}
|
||||
filterControl={<QueryFilters fields={fields} query={advancedFilters} onQueryChange={setAdvancedFilters} />}
|
||||
search={search}
|
||||
onSearchChange={setSearch}
|
||||
searchPlaceholder="IP, AS, описание…"
|
||||
countLabel={`${filtered.length} из ${sessions.length}`}
|
||||
actions={
|
||||
<div className="flex items-center gap-0.5 p-0.5 rounded-md border border-border bg-muted/40">
|
||||
{(["all", "eBGP", "iBGP"] as const).map((t) => (
|
||||
{(["all", "eBGP", "iBGP", "Unknown"] as const).map((t) => (
|
||||
<button
|
||||
key={t}
|
||||
type="button"
|
||||
onClick={() => setTypeFilter(t)}
|
||||
aria-pressed={typeFilter === t}
|
||||
className={cn(
|
||||
"px-2.5 py-1 text-[11px] rounded transition-colors",
|
||||
typeFilter === t
|
||||
@@ -320,13 +318,14 @@ function SessionsTab({ sessions, emptyTitle, selectedSessionId, onSelectSession
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{t === "all" ? "Все типы" : t}
|
||||
{t === "all" ? "Все типы" : t === "Unknown" ? "Неизвестно" : t}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<BgpSessionsDataGrid sessions={filtered} emptyTitle={emptyTitle} selectedSessionId={selectedSessionId} onSelectSession={onSelectSession} />
|
||||
{hasFilters && !urlError && <Button variant="ghost" size="sm" onClick={reset}>Сбросить фильтры BGP</Button>}
|
||||
<BgpSessionsDataGrid sessions={filtered} emptyTitle={urlError ? "Некорректные фильтры BGP" : emptyTitle} selectedSessionId={selectedSessionId} onSelectSession={onSelectSession} />
|
||||
</DataPageCard>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user