fix(ui): восстанавливать контекст OSPF из URL

This commit is contained in:
Denozordec committed 2026-09-30 19:58:43 +07:00
1 parent af05ad5cda
commit 1d522527b4
7 files changed
+130 -44

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
import assert from "node:assert/strict"
import { test } from "node:test"
import { readOspfUrl, patchOspfUrl } from "./ospf-url-state"
test("OSPF device/tab URL preserves unrelated context", () => {
const url=patchOspfUrl(new URLSearchParams("keep=x"),{server:"2",tab:"bfd"})
assert.deepEqual(readOspfUrl(new URL(url,"http://test").searchParams),{server:"2",tab:"bfd",error:null})
assert.equal(patchOspfUrl(new URL(url,"http://test").searchParams,{server:null,tab:null}),"/ospf?keep=x")
})
test("invalid or repeated context is explicit instead of widening to all",()=>{
for(const raw of ["server=a&server=b","tab=bfd&tab=neighbors","tab=broken","server=", "server="+"x".repeat(65),"server=%2F"]) assert.ok(readOspfUrl(new URLSearchParams(raw)).error)
assert.equal(readOspfUrl(new URLSearchParams("server=srv1&tab=neighbors")).error,null)
})
+16
View File
@@ -0,0 +1,16 @@
export const ospfTabs = ["interfaces", "neighbors", "routes", "bfd"] as const
export type OspfTab = typeof ospfTabs[number]
export function readOspfUrl(params: URLSearchParams) {
const server = params.get("server") ?? "all"
const rawTab = params.get("tab") ?? "interfaces"
let error: string | null = null
if (["server", "tab"].some(key => params.getAll(key).length > 1)) error = "В ссылке повторяется контекст OSPF."
else if (!/^[a-zA-Z0-9_.:-]{1,64}$/.test(server)) error = "В ссылке указан некорректный сервер OSPF."
else if (!(ospfTabs as readonly string[]).includes(rawTab)) error = "В ссылке указана неизвестная вкладка OSPF."
return { server, tab: (ospfTabs as readonly string[]).includes(rawTab) ? rawTab as OspfTab : "interfaces" as OspfTab, error }
}
export function patchOspfUrl(params: URLSearchParams, changes: Record<string, string | null>) {
const next = new URLSearchParams(params)
for (const [key,value] of Object.entries(changes)) { if (value === null || value === "") next.delete(key); else next.set(key,value) }
return "/ospf" + (next.size ? "?" + next.toString() : "")
}