fix(ui): не подставлять выдуманный cost соседа OSPF
This commit is contained in:
1 parent
3dc25628af
commit
748a3c00ad
5 files changed
+18
-8
No files matched your search
@@ -64,7 +64,7 @@ interface OspfNeighbor {
|
|||||||
remoteRouterId: string
|
remoteRouterId: string
|
||||||
area: string
|
area: string
|
||||||
state: OspfNeighborState
|
state: OspfNeighborState
|
||||||
cost: number
|
cost: number | null
|
||||||
uptime: string
|
uptime: string
|
||||||
priority: number
|
priority: number
|
||||||
dataUnknown?: boolean
|
dataUnknown?: boolean
|
||||||
@@ -152,7 +152,7 @@ function backendToNeighbor(b: BackendNeighbor, ifaceMap: Map<string, number>): O
|
|||||||
remoteRouterId: b.routerId,
|
remoteRouterId: b.routerId,
|
||||||
area: b.areaId !== b.area ? `${b.area} (${b.areaId})` : b.area,
|
area: b.areaId !== b.area ? `${b.area} (${b.areaId})` : b.area,
|
||||||
state,
|
state,
|
||||||
cost: ifaceMap.get(costKey) ?? 10,
|
cost: ifaceMap.get(costKey) ?? null,
|
||||||
uptime: b.uptime ?? "—",
|
uptime: b.uptime ?? "—",
|
||||||
priority: b.priority,
|
priority: b.priority,
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ const EDGE_COLOR: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface GraphNode { id: string; label: string; short: string; site: string; x: number; y: number }
|
interface GraphNode { id: string; label: string; short: string; site: string; x: number; y: number }
|
||||||
interface GraphEdge { from: string; to: string; state: OspfNeighbor["state"]; cost: number }
|
interface GraphEdge { from: string; to: string; state: OspfNeighbor["state"]; cost: number | null }
|
||||||
|
|
||||||
// Mock topology (static layout for mock mode)
|
// Mock topology (static layout for mock mode)
|
||||||
const MOCK_GRAPH_NODES: GraphNode[] = [
|
const MOCK_GRAPH_NODES: GraphNode[] = [
|
||||||
@@ -459,7 +459,7 @@ function TopologyGraph({ graphNodes, graphEdges, highlightId, selectedId, showDo
|
|||||||
<rect x="-15" y="-10" width="30" height="18" rx="4"
|
<rect x="-15" y="-10" width="30" height="18" rx="4"
|
||||||
fill="#060d1a" stroke={color} strokeWidth="0.8" opacity="0.95" />
|
fill="#060d1a" stroke={color} strokeWidth="0.8" opacity="0.95" />
|
||||||
<text textAnchor="middle" y="4" fontSize="8.5" fontWeight="700"
|
<text textAnchor="middle" y="4" fontSize="8.5" fontWeight="700"
|
||||||
fill={color} fontFamily="ui-monospace,monospace">{e.cost}</text>
|
fill={color} fontFamily="ui-monospace,monospace">{e.cost ?? "—"}</text>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
)
|
)
|
||||||
@@ -613,7 +613,7 @@ function NodeDetailPanel({
|
|||||||
<span className="size-1.5 rounded-full shrink-0 mt-1.5" style={{ background: ec }} />
|
<span className="size-1.5 rounded-full shrink-0 mt-1.5" style={{ background: ec }} />
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-xs font-mono font-medium text-[#f1f5f9] truncate leading-tight">{adj.peerLabel}</p>
|
<p className="text-xs font-mono font-medium text-[#f1f5f9] truncate leading-tight">{adj.peerLabel}</p>
|
||||||
<p className="text-[10px] font-mono text-[#64748b] mt-0.5">{adj.iface} · cost {adj.cost}</p>
|
<p className="text-[10px] font-mono text-[#64748b] mt-0.5">{adj.iface} · cost {adj.cost ?? "—"}</p>
|
||||||
<p className="text-[10px] text-[#475569] mt-0.5 tabular-nums">{adj.uptime}</p>
|
<p className="text-[10px] text-[#475569] mt-0.5 tabular-nums">{adj.uptime}</p>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[10px] font-mono font-semibold shrink-0 mt-0.5" style={{ color: ec }}>{adj.state}</span>
|
<span className="text-[10px] font-mono font-semibold shrink-0 mt-0.5" style={{ color: ec }}>{adj.state}</span>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export interface OspfNeighborRow {
|
|||||||
remoteRouterId: string
|
remoteRouterId: string
|
||||||
area: string
|
area: string
|
||||||
state: OspfNeighborState
|
state: OspfNeighborState
|
||||||
cost: number
|
cost: number | null
|
||||||
uptime: string
|
uptime: string
|
||||||
priority: number
|
priority: number
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ function OspfNeighborsDataGrid({
|
|||||||
accessorKey: "cost",
|
accessorKey: "cost",
|
||||||
header: ({ column }) => <DataGridSortHeader column={column} title="Cost" />,
|
header: ({ column }) => <DataGridSortHeader column={column} title="Cost" />,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="font-mono tabular-nums text-center block">{row.original.cost}</span>
|
<span className="font-mono tabular-nums text-center block">{row.original.cost ?? "—"}</span>
|
||||||
),
|
),
|
||||||
meta: {
|
meta: {
|
||||||
headerTitle: "Cost",
|
headerTitle: "Cost",
|
||||||
|
|||||||
@@ -26,11 +26,16 @@
|
|||||||
| 7 | Серверы и мониторинг: детали, формы, URL-контекст, права | Завершён в границах локальной приёмки 2026-09-23; внешние ограничения ниже |
|
| 7 | Серверы и мониторинг: детали, формы, URL-контекст, права | Завершён в границах локальной приёмки 2026-09-23; внешние ограничения ниже |
|
||||||
| 8 | Трафик и статистика | Завершён 2026-09-28 в границах локальной приёмки; ограничения в блоке 8.13 |
|
| 8 | Трафик и статистика | Завершён 2026-09-28 в границах локальной приёмки; ограничения в блоке 8.13 |
|
||||||
| 9 | VPN, Firewall и Filters | Завершён в границах локальной приёмки 2026-09-30; блоки 9.1–9.64, ограничения в 9.64 |
|
| 9 | VPN, Firewall и Filters | Завершён в границах локальной приёмки 2026-09-30; блоки 9.1–9.64, ограничения в 9.64 |
|
||||||
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.13, состояния OSPF/BFD; далее неизвестные показатели/URL/layout |
|
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.14, состояния и cost соседей OSPF; далее показатели/URL/layout |
|
||||||
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Не начат |
|
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Не начат |
|
||||||
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат |
|
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат |
|
||||||
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат |
|
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат |
|
||||||
|
|
||||||
|
## Блок 10.14 — неизвестный cost соседа OSPF (2026-09-30)
|
||||||
|
|
||||||
|
- При отсутствии интерфейса в каталоге cost соседа остаётся null: таблица, линия топологии и панель узла показывают «—». Значение 10 больше не выдумывается; известные costs и сортировка сохранены.
|
||||||
|
- 11 E2E states/routing-tables и TypeScript прошли. Production-сборки проверены в 10.13; повторная полная регрессия не требовалась. Далее nullable показатели строгого backend-каталога, URL и layout; backend defaults ещё требуют проверки. 96% окна использовано; локальный коммит без push.
|
||||||
|
|
||||||
## Блок 10.13 — подтверждённые состояния OSPF/BFD (2026-09-30)
|
## Блок 10.13 — подтверждённые состояния OSPF/BFD (2026-09-30)
|
||||||
|
|
||||||
- Восемь состояний соседства RouterOS распознаются независимо от регистра. Attempt, Init, ExStart, Exchange и Loading сохраняются как переходные состояния; неизвестные значения показываются нейтрально, без подмены Down. Топология различает Pending/Unknown и подтверждённый отказ. При неизвестном состоянии сводка не выдаёт полный подсчёт состояний.
|
- Восемь состояний соседства RouterOS распознаются независимо от регистра. Attempt, Init, ExStart, Exchange и Loading сохраняются как переходные состояния; неизвестные значения показываются нейтрально, без подмены Down. Топология различает Pending/Unknown и подтверждённый отказ. При неизвестном состоянии сводка не выдаёт полный подсчёт состояний.
|
||||||
|
|||||||
@@ -92,3 +92,7 @@ Lock/readiness, существующее mm:servers:write, валидация п
|
|||||||
## 10.13. Состояния соседства и BFD
|
## 10.13. Состояния соседства и BFD
|
||||||
|
|
||||||
Все восемь состояний из [RouterOS OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/331612216/routing%2Bospf) сохранены. Переходные состояния — amber/Pending, неизвестные — neutral/Unknown, подтверждённый Down — red. Строгий каталог не подставляет Down при отсутствующем BFD state; старые endpoints совместимы. 14 E2E, два unit-теста, TS и обе production-сборки прошли. Далее неизвестные показатели, URL и визуальная приёмка.
|
Все восемь состояний из [RouterOS OSPF](https://help.mikrotik.com/docs/spaces/ROS/pages/331612216/routing%2Bospf) сохранены. Переходные состояния — amber/Pending, неизвестные — neutral/Unknown, подтверждённый Down — red. Строгий каталог не подставляет Down при отсутствующем BFD state; старые endpoints совместимы. 14 E2E, два unit-теста, TS и обе production-сборки прошли. Далее неизвестные показатели, URL и визуальная приёмка.
|
||||||
|
|
||||||
|
## 10.14. Неизвестный cost соседа
|
||||||
|
|
||||||
|
Отсутствующий интерфейс не означает cost=10: таблица/линия/панель показывают «—». 11 E2E и TS прошли. Backend defaults/nullable показатели остаются следующим блоком.
|
||||||
@@ -9,6 +9,7 @@ test("OSPF и BFD: переходные и неизвестные состоян
|
|||||||
await page.getByRole("button", { name: "Соседи", exact: true }).click()
|
await page.getByRole("button", { name: "Соседи", exact: true }).click()
|
||||||
const rows = page.locator("tr[data-row-id]")
|
const rows = page.locator("tr[data-row-id]")
|
||||||
await expect(rows).toHaveCount(9)
|
await expect(rows).toHaveCount(9)
|
||||||
|
for (const row of await rows.all()) await expect(row.locator("td").nth(5)).toHaveText("—")
|
||||||
for(const state of ["Full", "2-Way", "ExStart", "Exchange", "Loading", "Attempt", "Init", "Down", "Неизвестно"]) await expect(rows.getByText(state, { exact: true })).toHaveCount(1)
|
for(const state of ["Full", "2-Way", "ExStart", "Exchange", "Loading", "Attempt", "Init", "Down", "Неизвестно"]) await expect(rows.getByText(state, { exact: true })).toHaveCount(1)
|
||||||
await page.getByRole("button", { name: "BFD", exact: true }).click()
|
await page.getByRole("button", { name: "BFD", exact: true }).click()
|
||||||
await expect(rows).toHaveCount(5)
|
await expect(rows).toHaveCount(5)
|
||||||
|
|||||||
Reference in new issue
Block a user