fix(ui): изолировать операции Firewall по источнику

This commit is contained in:
Denozordec committed 2026-09-30 10:56:49 +07:00
1 parent 5e6057842f
commit c2159508d5
7 files changed
+143 -6

No files matched your search

+23 -3
View File
@@ -1918,6 +1918,11 @@ function payloadToMockRule(
function FirewallPageInner() {
const { mode, backendUrl } = useDataSource()
const isLive = mode === "live"
const mounted = useRef(true)
useEffect(() => {
mounted.current = true
return () => { mounted.current = false }
}, [])
const apiFetch = useMemo(() => makeApiFetch(backendUrl), [backendUrl])
const searchParams = useSearchParams()
const serverFromQuery = searchParams.get("server")
@@ -1967,7 +1972,7 @@ function FirewallPageInner() {
const [historyRestoring, setHistoryRestoring] = useState(false)
const loadLive = useCallback(async () => {
if (!isLive) return
if (!isLive || !mounted.current) return
const epoch = ++loadEpoch.current
setDataLoading(true)
setDataError(null)
@@ -1999,7 +2004,7 @@ function FirewallPageInner() {
useEffect(() => () => { historyEpoch.current += 1 }, [historyServerId, backendUrl, isLive])
const loadRevisions = useCallback(async () => {
if (!isLive || !historyServerId) return
if (!isLive || !historyServerId || !mounted.current) return
const epoch = ++historyEpoch.current
setHistoryLoading(true)
setHistoryError(null)
@@ -2030,6 +2035,7 @@ function FirewallPageInner() {
`/api/firewall/revisions/${encodeURIComponent(id)}/restore`,
{ method: "POST", body: JSON.stringify({ serverId: historyServerId }) },
)
if (!mounted.current) return
if (res?.ok !== true) throw new Error("Сервер не подтвердил восстановление")
toast.success("Версия применена на роутер")
await loadLive()
@@ -2173,6 +2179,7 @@ function FirewallPageInner() {
method: "PATCH",
body: JSON.stringify({ ...key, disabled: r.enabled }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил изменение правила")
await loadLive()
} catch (e) {
@@ -2208,6 +2215,7 @@ function FirewallPageInner() {
const result = await apiFetch<{ ok: boolean }>(target.kind === "rule" ? "/api/firewall/rules" : "/api/firewall/address-lists", {
method: "DELETE", body: JSON.stringify(key),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил удаление")
await loadLive()
} else if (target.kind === "rule") {
@@ -2215,6 +2223,7 @@ function FirewallPageInner() {
} else {
setMockAddrLists(rows => rows.filter(x => x.id !== target.item.id))
}
if (!mounted.current) return
setPendingDelete(null)
toast.success(target.kind === "rule" ? "Правило удалено" : "Запись удалена")
} catch (e) {
@@ -2267,6 +2276,7 @@ function FirewallPageInner() {
...(dest.dest ? { destinationRosId: dest.dest } : {}),
}),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил перемещение правила")
await loadLive()
} catch (e) {
@@ -2321,6 +2331,7 @@ function FirewallPageInner() {
method: "PUT",
body: JSON.stringify({ serverId, family, table, rosId: editingRule.rosId, ...payload }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил сохранение")
toast.success("Правило сохранено")
} else {
@@ -2328,6 +2339,7 @@ function FirewallPageInner() {
method: "POST",
body: JSON.stringify({ serverId, family, table, ...payload }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил сохранение")
toast.success("Правило создано")
}
@@ -2398,6 +2410,7 @@ function FirewallPageInner() {
method: "PATCH",
body: JSON.stringify({ ...key, disabled: !e.disabled }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил изменение адреса")
await loadLive()
} catch (err) {
@@ -2440,6 +2453,7 @@ function FirewallPageInner() {
method: "PUT",
body: JSON.stringify({ serverId, family, rosId: editingAddr.rosId, ...payload }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил сохранение")
toast.success("Запись сохранена")
} else {
@@ -2447,6 +2461,7 @@ function FirewallPageInner() {
method: "POST",
body: JSON.stringify({ serverId, family, ...payload }),
})
if (!mounted.current) return
if (result?.ok !== true) throw new Error("Сервер не подтвердил сохранение")
toast.success("Запись создана")
}
@@ -2791,10 +2806,15 @@ function FirewallPageInner() {
)
}
function FirewallSource() {
const { mode, backendUrl } = useDataSource()
return <FirewallPageInner key={JSON.stringify([mode, backendUrl])} />
}
export default function FirewallPage() {
return (
<Suspense fallback={null}>
<FirewallPageInner />
<FirewallSource />
</Suspense>
)
}