feat: enhance backups page with live data loading and backup job management

Implemented live data fetching for servers and backups on the backups page, replacing static initial data. Added functionality for manual backup creation and job status tracking, including error handling and UI updates. Updated the network map layout to improve node prioritization and visual representation of server roles.

Also, registered new backups API routes in the backend for improved data handling.
This commit is contained in:
Denozordec
2026-05-07 14:24:58 +07:00
parent 6d8379501c
commit 84ecd4f061
24 changed files with 146391 additions and 54 deletions
+20 -5
View File
@@ -246,9 +246,12 @@ const STATUS_STYLE = {
}
const TYPE_STYLE: Record<ServerType, { label: string; fill: string; r: number }> = {
"jump-host": { label: "JH", fill: "#7c3aed", r: 36 },
"exit-node": { label: "EN", fill: "#0369a1", r: 36 },
"home-router": { label: "HR", fill: "#16a34a", r: 30 },
// HR — визуальный корень топологии: крупнее и с более сильным акцентом.
"home-router": { label: "HR", fill: "#16a34a", r: 40 },
// JH — агрегирующий слой по центру.
"jump-host": { label: "JH", fill: "#7c3aed", r: 34 },
// EN — крайние edge-узлы, менее акцентные.
"exit-node": { label: "EN", fill: "#0369a1", r: 30 },
}
const WAN_COLORS = ["#0ea5e9", "#f97316", "#a855f7", "#ec4899", "#14b8a6"]
@@ -886,7 +889,10 @@ export default function NetworkMapPage() {
})
}, [useLiveData, loadLive])
const autoLayout = useMemo(() => computeNetworkMapLayout(mapServers), [mapServers])
const autoLayout = useMemo(
() => computeNetworkMapLayout(mapServers, mapGreTunnels, greResolvedMap),
[mapServers, mapGreTunnels, greResolvedMap],
)
const wanJhEdges = useMemo(() => buildWanJhEdges(mapServers), [mapServers])
const srvResMap = useMemo(() => buildServerResourceMap(mapServers), [mapServers])
const homeRouters = useMemo(
@@ -1099,7 +1105,16 @@ export default function NetworkMapPage() {
return out
}, [greEdges])
const nodes = mapServers.map((s) => ({ ...s, ...nodePosById[s.id]! }))
const nodes = mapServers
.map((s) => ({ ...s, ...nodePosById[s.id]! }))
// Визуальный приоритет: HR поверх JH, JH поверх EN.
.sort((a, b) => {
const weight = (t: ServerType) =>
t === "home-router" ? 3 :
t === "jump-host" ? 2 :
1
return weight(a.type) - weight(b.type)
})
const nodeById = Object.fromEntries(nodes.map((n) => [n.id, n]))
// ── Refs ─────────────────────────────────────────────────────────────────────