diff --git a/components/data-grids/ospf-routes-data-grid.tsx b/components/data-grids/ospf-routes-data-grid.tsx index 154334ea..7a7fd7b2 100644 --- a/components/data-grids/ospf-routes-data-grid.tsx +++ b/components/data-grids/ospf-routes-data-grid.tsx @@ -49,12 +49,12 @@ function OspfRoutesDataGrid({ routes, emptyTitle }: OspfRoutesDataGridProps) { () => [ { id: "destination", - size: 150, + size: 180, accessorKey: "destination", header: ({ column }) => ( ), - cell: ({ row }) => {row.original.destination}, + cell: ({ row }) => {row.original.destination}, meta: { headerTitle: "Назначение", headerClassName: DATA_GRID_CELL_PAD_FIRST, diff --git a/docs/ux-ui-external-acceptance.md b/docs/ux-ui-external-acceptance.md index 94ea858a..2d5420ff 100644 --- a/docs/ux-ui-external-acceptance.md +++ b/docs/ux-ui-external-acceptance.md @@ -835,3 +835,15 @@ Production image не содержит dev-only jose: первый fixture impor **Очистка.** Exact ID/name/comment/address/interface/interfaces/addresses/public key preflight; удалены только свои templates/area/instance/BFD/IP/bridge/GRE/WG peers/interfaces. Исходные IDs10 коллекций×2 совпали, public/default routes и195.195.195.195/32 сохранены. WG secret fields не включены в report. Оба CHR доступны, passwords неизменны; временных контейнеров не осталось. Backend diagnostics89/PG healthy, frontend optimizer87 сохранён. Один локальный commit без push. Схема: primary → BFD/adjacency loss → alternate GRE over WG → проверка data plane → восстановленный primary. Транспорт подтверждён [GRE](https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE) и [WireGuard](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard); таблицы сохраняют референсы общего плана. Продолжение91 — обрезка CIDR, затем BGP propagation/остальные внешние границы. BFD-only устойчивый запрет/physical WAN/IPv6/scale/maximum throughput/Portal SSO остаются открыты. Квота66% использовано; этап12.5 открыт. + +## 12.5.91 — OSPF Data Grid: целый IPv4 CIDR (2026-10-09) + +Уточнена визуальная проблема90: это не потеря API-данных, а перенос последней цифры /32 на вторую строку; первый ряд выглядел как /3. Столбец назначения расширен150→180px, span использует whitespace-nowrap и title полного значения. Установленные Data Grid/Table/ScrollArea, pinned column, theme и структура сохранены. ReUI inline API и audit checklist прочитаны; [API](https://reui.io/docs/components/base/data-grid?ref=mcp), [превью](https://reui.io/components/data-grid?ref=mcp). + +**Проверки.** Новый browser test ждёт document.fonts.ready и проверяет Range rectangles: ровно одна строка, текст внутри ячейки. До исправления1280px failed: /3 и2 дали два rect. Первоначальная проверка только границ проходила и была уточнена, чтобы не пропустить разрыв CIDR. После изменения4 размера320/390/1280/1440 и IPv4 CIDR15/18 символов проходят; сортировка/количество строк/document fit/no writes сохранены. С OSPF unknown cost/disabled/inactive —7/7. Scoped TypeScript, ESLint/diff passed. Это meaningful visual regression, не проверка буквального size в исходнике. + +**Live.** Backend diagnostics89 и обновлённый frontend ospf91, без mocks: два CHR×1280/320 =4/4. Свои GRE/OSPF private link198.18.93.0/30/loopbacks198.18.193.1/32↔2/32; Full/active learned route/Ping3/3. Целый /32 виден в одной строке после загрузки шрифтов; title, границы ячейки, URL/reload, document fit/pageerror0 подтверждены. [Browser отчёт](ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json), [native/cleanup](ux-ui/acceptance/ospf-cidr-native-2026-10-09.json), [ПК после](ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png), [320px после](ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png). PC снимок просмотрен:198.18.193.2/32 полностью читается. Проверка не обещает одновременную видимость всех колонок на телефоне: сохраняется внутренняя горизонтальная прокрутка. + +**Контроль/runtime.** Свои objects удалены по exact IDs/атрибутам, baseline7 коллекций×2 совпал, оба CHR доступны, default/public/195.195.195.195/32 и credentials сохранены. Нормализованные SHA source/deployed DataGrid renderer и OSPF consumer совпадали до изменения, поэтому проблема не была вызвана отставшим компонентом стенда. Один frontend Docker build, production TypeScript/build, entry/node --check/compose --wait passed. mmapp-test/frontend:ux-ospf91/version1.0.0-test.ospf91, image sha256:b4bade515234115b3cad257ceb87ef7beb347e754ca92d6a97a25adc2199fd33. Context optimizer87 frontend +один consumer file, override SHA27a27569335c377bf8662fb5b39d200ce98d52925cafdf51dee165464c1532078, label не Git SHA. .env backup приватный, backend/migrations не менялись, полная регрессия/failover не повторялись. Один локальный commit без push. + +Следующий92 — BGP propagation собственных private prefixes, withdrawal/re-advertisement и UI counters; только собственные GRE/instances/filter chains. Квота84% использовано после блока, этап12.5 и внешние границы остаются открытыми. diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 57990c0c..6516b6fb 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -1,6 +1,6 @@ # План реализации UX/UI по пятичасовым окнам -Актуальное продолжение 2026-10-09: 12.5.90 принял контролируемый OSPF/BFD failover primary GRE→alternate GRE over WireGuard→primary; steady Ping3/3×2 во всех фазах,4 UI cases. BFD/not-Full≈798ms, first alternate route≈4250ms — HTTP observations, не SLA. Отдельный переходный Ping18/40/55% loss сохранён, бесшовность не заявлена. Baseline10 коллекций×2 восстановлен. Runtime diagnostics89/optimizer87. Следующий12.5.91 — устранить обрезку IPv4 CIDR в OSPF Data Grid, выявленную live desktop снимком; затем BGP route propagation и оставшиеся внешние границы. Квота66% использовано; этап12.5 открыт. +Актуальное продолжение 2026-10-09: 12.5.91 устранил неоднозначное отображение IPv4 CIDR в OSPF: /32 больше не разбивается на /3 и2. Column180px/nowrap/title, red-before/green-after geometry test,7 E2E и4 live UI cases. Baseline7 коллекций×2 восстановлен. Backend ux-diagnostics89/frontend ux-ospf91. Следующий12.5.92 — обмен только собственным BGP prefix через GRE, отзыв и повторное объявление, API/UI контекст. Квота84% использовано; этап12.5 открыт. Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-09. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат. diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index 7e93ab50..04586ec1 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -1,6 +1,6 @@ # UX/UI: журнал реализации -Актуальное продолжение 2026-10-09: 12.5.90 принял контролируемый OSPF/BFD failover primary GRE→alternate GRE over WireGuard→primary; steady Ping3/3×2 во всех фазах,4 UI cases. BFD/not-Full≈798ms, first alternate route≈4250ms — HTTP observations, не SLA. Отдельный переходный Ping18/40/55% loss сохранён, бесшовность не заявлена. Baseline10 коллекций×2 восстановлен. Runtime diagnostics89/optimizer87. Следующий12.5.91 — устранить обрезку IPv4 CIDR в OSPF Data Grid, выявленную live desktop снимком; затем BGP route propagation и оставшиеся внешние границы. Квота66% использовано; этап12.5 открыт. +Актуальное продолжение 2026-10-09: 12.5.91 устранил неоднозначное отображение IPv4 CIDR в OSPF: /32 больше не разбивается на /3 и2. Column180px/nowrap/title, red-before/green-after geometry test,7 E2E и4 live UI cases. Baseline7 коллекций×2 восстановлен. Backend ux-diagnostics89/frontend ux-ospf91. Следующий12.5.92 — обмен только собственным BGP prefix через GRE, отзыв и повторное объявление, API/UI контекст. Квота84% использовано; этап12.5 открыт. Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md). @@ -36,7 +36,19 @@ | 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 | | 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 | | 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 | -| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–90 и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-optimizer87. | +| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Локальная приёмка завершена в границах12.3.83; внешняя12.5 в работе, выполненные блоки1–91 и ограничения ниже. Runtime backend ux-diagnostics89/frontend ux-ospf91. | + +## 12.5.91 — OSPF Data Grid: целый IPv4 CIDR (2026-10-09) + +Уточнена визуальная проблема90: это не потеря API-данных, а перенос последней цифры /32 на вторую строку; первый ряд выглядел как /3. Столбец назначения расширен150→180px, span использует whitespace-nowrap и title полного значения. Установленные Data Grid/Table/ScrollArea, pinned column, theme и структура сохранены. ReUI inline API и audit checklist прочитаны; [API](https://reui.io/docs/components/base/data-grid?ref=mcp), [превью](https://reui.io/components/data-grid?ref=mcp). + +**Проверки.** Новый browser test ждёт document.fonts.ready и проверяет Range rectangles: ровно одна строка, текст внутри ячейки. До исправления1280px failed: /3 и2 дали два rect. Первоначальная проверка только границ проходила и была уточнена, чтобы не пропустить разрыв CIDR. После изменения4 размера320/390/1280/1440 и IPv4 CIDR15/18 символов проходят; сортировка/количество строк/document fit/no writes сохранены. С OSPF unknown cost/disabled/inactive —7/7. Scoped TypeScript, ESLint/diff passed. Это meaningful visual regression, не проверка буквального size в исходнике. + +**Live.** Backend diagnostics89 и обновлённый frontend ospf91, без mocks: два CHR×1280/320 =4/4. Свои GRE/OSPF private link198.18.93.0/30/loopbacks198.18.193.1/32↔2/32; Full/active learned route/Ping3/3. Целый /32 виден в одной строке после загрузки шрифтов; title, границы ячейки, URL/reload, document fit/pageerror0 подтверждены. [Browser отчёт](ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json), [native/cleanup](ux-ui/acceptance/ospf-cidr-native-2026-10-09.json), [ПК после](ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png), [320px после](ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png). PC снимок просмотрен:198.18.193.2/32 полностью читается. Проверка не обещает одновременную видимость всех колонок на телефоне: сохраняется внутренняя горизонтальная прокрутка. + +**Контроль/runtime.** Свои objects удалены по exact IDs/атрибутам, baseline7 коллекций×2 совпал, оба CHR доступны, default/public/195.195.195.195/32 и credentials сохранены. Нормализованные SHA source/deployed DataGrid renderer и OSPF consumer совпадали до изменения, поэтому проблема не была вызвана отставшим компонентом стенда. Один frontend Docker build, production TypeScript/build, entry/node --check/compose --wait passed. mmapp-test/frontend:ux-ospf91/version1.0.0-test.ospf91, image sha256:b4bade515234115b3cad257ceb87ef7beb347e754ca92d6a97a25adc2199fd33. Context optimizer87 frontend +один consumer file, override SHA27a27569335c377bf8662fb5b39d200ce98d52925cafdf51dee165464c1532078, label не Git SHA. .env backup приватный, backend/migrations не менялись, полная регрессия/failover не повторялись. Один локальный commit без push. + +Следующий92 — BGP propagation собственных private prefixes, withdrawal/re-advertisement и UI counters; только собственные GRE/instances/filter chains. Квота84% использовано после блока, этап12.5 и внешние границы остаются открытыми. ## 12.5.90 — OSPF/BFD: переход на резервный GRE и возврат (2026-10-09) diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index e0b9edcd..886521f0 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -2144,3 +2144,15 @@ Production image не содержит dev-only jose: первый fixture impor **Очистка.** Exact ID/name/comment/address/interface/interfaces/addresses/public key preflight; удалены только свои templates/area/instance/BFD/IP/bridge/GRE/WG peers/interfaces. Исходные IDs10 коллекций×2 совпали, public/default routes и195.195.195.195/32 сохранены. WG secret fields не включены в report. Оба CHR доступны, passwords неизменны; временных контейнеров не осталось. Backend diagnostics89/PG healthy, frontend optimizer87 сохранён. Один локальный commit без push. Схема: primary → BFD/adjacency loss → alternate GRE over WG → проверка data plane → восстановленный primary. Транспорт подтверждён [GRE](https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE) и [WireGuard](https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard); таблицы сохраняют референсы общего плана. Продолжение91 — обрезка CIDR, затем BGP propagation/остальные внешние границы. BFD-only устойчивый запрет/physical WAN/IPv6/scale/maximum throughput/Portal SSO остаются открыты. Квота66% использовано; этап12.5 открыт. + +## 12.5.91 — OSPF Data Grid: целый IPv4 CIDR (2026-10-09) + +Уточнена визуальная проблема90: это не потеря API-данных, а перенос последней цифры /32 на вторую строку; первый ряд выглядел как /3. Столбец назначения расширен150→180px, span использует whitespace-nowrap и title полного значения. Установленные Data Grid/Table/ScrollArea, pinned column, theme и структура сохранены. ReUI inline API и audit checklist прочитаны; [API](https://reui.io/docs/components/base/data-grid?ref=mcp), [превью](https://reui.io/components/data-grid?ref=mcp). + +**Проверки.** Новый browser test ждёт document.fonts.ready и проверяет Range rectangles: ровно одна строка, текст внутри ячейки. До исправления1280px failed: /3 и2 дали два rect. Первоначальная проверка только границ проходила и была уточнена, чтобы не пропустить разрыв CIDR. После изменения4 размера320/390/1280/1440 и IPv4 CIDR15/18 символов проходят; сортировка/количество строк/document fit/no writes сохранены. С OSPF unknown cost/disabled/inactive —7/7. Scoped TypeScript, ESLint/diff passed. Это meaningful visual regression, не проверка буквального size в исходнике. + +**Live.** Backend diagnostics89 и обновлённый frontend ospf91, без mocks: два CHR×1280/320 =4/4. Свои GRE/OSPF private link198.18.93.0/30/loopbacks198.18.193.1/32↔2/32; Full/active learned route/Ping3/3. Целый /32 виден в одной строке после загрузки шрифтов; title, границы ячейки, URL/reload, document fit/pageerror0 подтверждены. [Browser отчёт](ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json), [native/cleanup](ux-ui/acceptance/ospf-cidr-native-2026-10-09.json), [ПК после](ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png), [320px после](ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png). PC снимок просмотрен:198.18.193.2/32 полностью читается. Проверка не обещает одновременную видимость всех колонок на телефоне: сохраняется внутренняя горизонтальная прокрутка. + +**Контроль/runtime.** Свои objects удалены по exact IDs/атрибутам, baseline7 коллекций×2 совпал, оба CHR доступны, default/public/195.195.195.195/32 и credentials сохранены. Нормализованные SHA source/deployed DataGrid renderer и OSPF consumer совпадали до изменения, поэтому проблема не была вызвана отставшим компонентом стенда. Один frontend Docker build, production TypeScript/build, entry/node --check/compose --wait passed. mmapp-test/frontend:ux-ospf91/version1.0.0-test.ospf91, image sha256:b4bade515234115b3cad257ceb87ef7beb347e754ca92d6a97a25adc2199fd33. Context optimizer87 frontend +один consumer file, override SHA27a27569335c377bf8662fb5b39d200ce98d52925cafdf51dee165464c1532078, label не Git SHA. .env backup приватный, backend/migrations не менялись, полная регрессия/failover не повторялись. Один локальный commit без push. + +Следующий92 — BGP propagation собственных private prefixes, withdrawal/re-advertisement и UI counters; только собственные GRE/instances/filter chains. Квота84% использовано после блока, этап12.5 и внешние границы остаются открытыми. diff --git a/docs/ux-ui-test-server.md b/docs/ux-ui-test-server.md index b5956892..d1991df4 100644 --- a/docs/ux-ui-test-server.md +++ b/docs/ux-ui-test-server.md @@ -1,6 +1,6 @@ # Тестовый сервер UX/UI — 2026-10-09 -Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-diagnostics89/version1.0.0-test.diagnostics89, frontend ux-optimizer87/version1.0.0-test.optimizer87; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. +Сервер161.104.46.222 предоставлен для временного тестирования. Backend ux-diagnostics89/version1.0.0-test.diagnostics89, frontend ux-ospf91/version1.0.0-test.ospf91; backend/PG healthy, frontend HTTP/browser passed. Основной блок IPsec77 принят в границах журнала, own fixtures/fake DB rows удалены; каталог flash CHR2 сохранён из-за неподтверждённого ownership. SSH/оба CHR доступны, пароли прежние. | Параметр | Проверенное состояние | | --- | --- | @@ -717,3 +717,5 @@ flowchart LR 12.5.88 (2026-10-09): recursion/GRE/Ping, apply/restore и4 browser checks passed; native baseline4 коллекций×2, cache/history сохранены. Backend recursive88, frontend optimizer87. 12.5.89 (2026-10-09): терминал/диагностика/RBAC и8 live UI checks passed, baseline7 коллекций×2 сохранён. Production auth не менялся. + +12.5.91 (2026-10-09): frontend ospf91; целый CIDR подтверждён4 live cases, baseline7 коллекций×2 сохранён. Backend diagnostics89 неизменён. diff --git a/docs/ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json b/docs/ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json new file mode 100644 index 00000000..173fdae6 --- /dev/null +++ b/docs/ux-ui/acceptance/browser-ospf-cidr-2026-10-09.json @@ -0,0 +1,43 @@ +{ + "date": "2026-10-09", + "phase": "2 320", + "cases": [ + { + "serverId": 1, + "width": 1280, + "destination": "198.18.193.2/32", + "oneLine": true, + "noCellClipping": true, + "documentFits": true, + "urlRestore": true + }, + { + "serverId": 1, + "width": 320, + "destination": "198.18.193.2/32", + "oneLine": true, + "noCellClipping": true, + "documentFits": true, + "urlRestore": true + }, + { + "serverId": 2, + "width": 1280, + "destination": "198.18.193.1/32", + "oneLine": true, + "noCellClipping": true, + "documentFits": true, + "urlRestore": true + }, + { + "serverId": 2, + "width": 320, + "destination": "198.18.193.1/32", + "oneLine": true, + "noCellClipping": true, + "documentFits": true, + "urlRestore": true + } + ], + "errors": [] +} \ No newline at end of file diff --git a/docs/ux-ui/acceptance/ospf-cidr-native-2026-10-09.json b/docs/ux-ui/acceptance/ospf-cidr-native-2026-10-09.json new file mode 100644 index 00000000..cb18d77d --- /dev/null +++ b/docs/ux-ui/acceptance/ospf-cidr-native-2026-10-09.json @@ -0,0 +1,161 @@ +{ + "date": "2026-10-09", + "name": "mm-ospf91-1791559266208", + "observations": [ + { + "serverId": 1, + "nativeNeighbor": { + ".id": "*F3FDDC00", + "router-id": "198.18.193.2", + "address": "198.18.93.2", + "interface": "mm-ospf91-1791559266208", + "state": "Full", + "state-changes": "6" + }, + "nativeRoute": { + ".id": "*2014C000", + "dst-address": "198.18.193.2/32", + "gateway": "198.18.93.2%mm-ospf91-1791559266208", + "ospf": "true", + "active": "true", + "distance": "110" + }, + "catalogNeighbors": [ + { + "id": "*F3FDDC00", + "serverId": 1, + "serverName": "CHR", + "serverSite": "", + "serverCountry": "", + "address": "198.18.93.2", + "routerId": "198.18.193.2", + "instance": "mm-ospf91-1791559266208", + "area": "mm-ospf91-1791559266208", + "areaId": "0.0.0.0", + "interface": "mm-ospf91-1791559266208", + "state": "Full", + "uptime": "3s", + "stateChanges": 6, + "priority": null + } + ], + "catalogRoutes": [ + { + "id": "*2014C000", + "serverId": 1, + "serverName": "CHR", + "serverSite": "", + "destination": "198.18.193.2/32", + "type": "Unknown", + "cost": null, + "nextHop": "198.18.93.2", + "via": "mm-ospf91-1791559266208", + "area": "" + } + ], + "pingReceived": 3 + }, + { + "serverId": 2, + "nativeNeighbor": { + ".id": "*F3FDDC00", + "router-id": "198.18.193.1", + "address": "198.18.93.1", + "interface": "mm-ospf91-1791559266208", + "state": "Full", + "state-changes": "5" + }, + "nativeRoute": { + ".id": "*2014C000", + "dst-address": "198.18.193.1/32", + "gateway": "198.18.93.1%mm-ospf91-1791559266208", + "ospf": "true", + "active": "true", + "distance": "110" + }, + "catalogNeighbors": [ + { + "id": "*F3FDDC00", + "serverId": 2, + "serverName": "CHR", + "serverSite": "", + "serverCountry": "", + "address": "198.18.93.1", + "routerId": "198.18.193.1", + "instance": "mm-ospf91-1791559266208", + "area": "mm-ospf91-1791559266208", + "areaId": "0.0.0.0", + "interface": "mm-ospf91-1791559266208", + "state": "Full", + "uptime": "3s", + "stateChanges": 5, + "priority": null + } + ], + "catalogRoutes": [ + { + "id": "*2014C000", + "serverId": 2, + "serverName": "CHR", + "serverSite": "", + "destination": "198.18.193.1/32", + "type": "Unknown", + "cost": null, + "nextHop": "198.18.93.1", + "via": "mm-ospf91-1791559266208", + "area": "" + } + ], + "pingReceived": 3 + } + ], + "cleanup": [ + { + "serverId": 1, + "/routing/ospf/interface-template": true, + "/routing/ospf/area": true, + "/routing/ospf/instance": true, + "/interface/gre": true, + "/interface/bridge": true, + "/ip/address": true, + "/ip/route": true + }, + { + "serverId": 2, + "/routing/ospf/interface-template": true, + "/routing/ospf/area": true, + "/routing/ospf/instance": true, + "/interface/gre": true, + "/interface/bridge": true, + "/ip/address": true, + "/ip/route": true + } + ], + "currentRoutes": [ + { + ".id": "*20145050", + "dst-address": "198.18.93.0/30", + "gateway": "mm-ospf91-1791559266208", + "active": "true", + "distance": "0", + "routing-table": "main" + }, + { + ".id": "*2014C000", + "dst-address": "198.18.193.1/32", + "gateway": "198.18.93.1%mm-ospf91-1791559266208", + "active": "true", + "ospf": "true", + "distance": "110", + "routing-table": "main" + }, + { + ".id": "*20145060", + "dst-address": "198.18.193.2/32", + "gateway": "mm-ospf91-1791559266208-loop", + "active": "true", + "distance": "0", + "routing-table": "main" + } + ] +} \ No newline at end of file diff --git a/docs/ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png b/docs/ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png new file mode 100644 index 00000000..ca59e073 Binary files /dev/null and b/docs/ux-ui/screens/ospf-real-cidr-server1-1280-2026-10-09.png differ diff --git a/docs/ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png b/docs/ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png new file mode 100644 index 00000000..12988316 Binary files /dev/null and b/docs/ux-ui/screens/ospf-real-cidr-server1-320-2026-10-09.png differ diff --git a/docs/ux-ui/screens/ospf-real-cidr-server2-1280-2026-10-09.png b/docs/ux-ui/screens/ospf-real-cidr-server2-1280-2026-10-09.png new file mode 100644 index 00000000..35e2aabd Binary files /dev/null and b/docs/ux-ui/screens/ospf-real-cidr-server2-1280-2026-10-09.png differ diff --git a/docs/ux-ui/screens/ospf-real-cidr-server2-320-2026-10-09.png b/docs/ux-ui/screens/ospf-real-cidr-server2-320-2026-10-09.png new file mode 100644 index 00000000..2eb8445a Binary files /dev/null and b/docs/ux-ui/screens/ospf-real-cidr-server2-320-2026-10-09.png differ diff --git a/tests/e2e/ospf-route-cidr.spec.ts b/tests/e2e/ospf-route-cidr.spec.ts new file mode 100644 index 00000000..04113459 --- /dev/null +++ b/tests/e2e/ospf-route-cidr.spec.ts @@ -0,0 +1,42 @@ +import { test, expect } from "@playwright/test" + +for (const width of [320, 390, 1280, 1440]) test("OSPF: CIDR целиком помещается в закреплённой ячейке " + width, async ({ page }) => { + await page.setViewportSize({ width, height: 1000 }) + const destinations = ["198.18.190.2/32", "255.255.255.255/32"] + const host = { serverId: 1, serverName: "CHR", serverSite: "", serverCountry: "RU" } + let writes = 0 + await page.route("**/health", r => r.fulfill({ json: { ok: true } })) + await page.route("**/api/**", r => { + const path = new URL(r.request().url()).pathname + if (r.request().method() !== "GET") writes++ + return r.fulfill({ json: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [{ id: 1, name: "CHR", host: "192.0.2.1", enabled: true, country: "RU", status: null }] : path === "/api/ospf/catalog" ? { + neighbors: [], interfaces: [], instances: [], bfdSessions: [], failures: [], + routes: destinations.map((destination, i) => ({ ...host, id: "route-" + i, destination, type: "Unknown", cost: null, nextHop: "198.18.91.2", via: "GRE-reserve", area: "" })), + } : {} }) + }) + await page.goto("/ospf?server=1&tab=routes") + await expect(page.locator("tr[data-row-id]")).toHaveCount(2) + await page.evaluate(() => document.fonts.ready) + for (const destination of destinations) { + const text = page.getByText(destination, { exact: true }) + await text.scrollIntoViewIfNeeded() + const bounds = await text.evaluate(element => { + const cell = element.closest("td")!, cellRect = cell.getBoundingClientRect(), style = getComputedStyle(cell) + const range = document.createRange(); range.selectNodeContents(element) + const rects = Array.from(range.getClientRects()) + return { cell: { left: cellRect.left + parseFloat(style.paddingLeft), right: cellRect.right - parseFloat(style.paddingRight), top: cellRect.top, bottom: cellRect.bottom }, text: rects.map(r => ({ left: r.left, right: r.right, top: r.top, bottom: r.bottom })) } + }) + // Splitting /32 into /3 + 2 makes the prefix visually ambiguous. + expect(bounds.text).toHaveLength(1) + for (const rect of bounds.text) { + expect(rect.left).toBeGreaterThanOrEqual(bounds.cell.left - 1) + expect(rect.right).toBeLessThanOrEqual(bounds.cell.right + 1) + expect(rect.top).toBeGreaterThanOrEqual(bounds.cell.top) + expect(rect.bottom).toBeLessThanOrEqual(bounds.cell.bottom) + } + } + expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true) + await page.getByRole("button", { name: "Назначение", exact: true }).click() + await expect(page.locator("tr[data-row-id]")).toHaveCount(2) + expect(writes).toBe(0) +})