From 837298a171351ef22bef57bdd767154eb493afad Mon Sep 17 00:00:00 2001 From: Denozordec Date: Sun, 4 Oct 2026 12:16:34 +0700 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=D0=BE=D0=B3=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=87=D0=B8=D1=82=D1=8C=20=D1=80=D0=B0=D1=81=D0=BA=D1=80=D1=8B?= =?UTF-8?q?=D1=82=D0=B8=D0=B5=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=20WireGuard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/data-grids/wireguard-data-grid.tsx | 1 + .../data-grids/wireguard-peers-detail.tsx | 48 ++++++++++-------- docs/ux-ui-plan.md | 2 +- docs/ux-ui-progress.md | 8 +++ docs/ux-ui-stage-12.md | 9 ++++ .../screens/large-wireguard-detail-320.png | Bin 0 -> 48649 bytes tests/e2e/large-wireguard-peers.spec.ts | 27 ++++++++++ 7 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 docs/ux-ui/screens/large-wireguard-detail-320.png diff --git a/components/data-grids/wireguard-data-grid.tsx b/components/data-grids/wireguard-data-grid.tsx index 6937f890..a2e23f45 100644 --- a/components/data-grids/wireguard-data-grid.tsx +++ b/components/data-grids/wireguard-data-grid.tsx @@ -122,6 +122,7 @@ function WireguardDataGrid({ expandedContent: (row: WgIfaceWithServer) => ( onDeletePeer(row, peerId) : undefined} onExportPeer={onExportPeer ? (peerId) => onExportPeer(row, peerId) : undefined} /> diff --git a/components/data-grids/wireguard-peers-detail.tsx b/components/data-grids/wireguard-peers-detail.tsx index b55dc691..29c446a2 100644 --- a/components/data-grids/wireguard-peers-detail.tsx +++ b/components/data-grids/wireguard-peers-detail.tsx @@ -1,5 +1,6 @@ "use client" +import { useState } from "react" import type { WireGuardPeer } from "@/lib/data" import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" @@ -30,13 +31,20 @@ function peerKey(peer: WireGuardPeer, index: number): string { function WireGuardPeersDetail({ peers, + interfaceName, onDeletePeer, onExportPeer, }: { peers: WireGuardPeer[] + interfaceName: string onDeletePeer?: (peerId: string) => void onExportPeer?: (peerId: string) => void }) { + const [page, setPage] = useState(0) + const lastPage = Math.max(0, Math.ceil(peers.length / 50) - 1) + const currentPage = Math.min(page, lastPage) + const offset = currentPage * 50 + if (page > lastPage) setPage(lastPage) if (peers.length === 0) { return (
@@ -46,30 +54,30 @@ function WireGuardPeersDetail({ } return ( -
-
- Public Key - Allowed IPs - Последнее рукопожатие - RX / TX - Endpoint - Действия +
+
+

Пиры {offset + 1}–{Math.min(offset + 50, peers.length)} из {peers.length}

+ {peers.length > 50 &&
+ + +
}
- {peers.map((peer, index) => { - const id = peerKey(peer, index) + {peers.slice(offset, offset + 50).map((peer, index) => { + const id = peerKey(peer, offset + index) return (
- - {truncKey(peer.publicKey)} + + {peer.name || truncKey(peer.publicKey)}
-
- {peer.allowedIps.join(", ")} +
+ Allowed IPs: {peer.allowedIps.join(", ")}
- {peer.latestHandshake ?? "нет рукопожатия"} + Последнее рукопожатие: {peer.latestHandshake ?? "нет рукопожатия"}
@@ -89,14 +97,14 @@ function WireGuardPeersDetail({ {fmtBytes(peer.transferTx)}
- {peer.endpoint ?? "—"} + Endpoint: {peer.endpoint ?? "—"}
{onExportPeer && (
) })} -
+
) } diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 4ca0fb12..1219ed8d 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -4,7 +4,7 @@ ## Актуальная точка продолжения — 2026-10-04 -Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. 12.4.1 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. 12.4.2 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принят локально:BFD1000/50 DOM/cache/320px/12 browser/build. 12.4.4 принят локально:context213/25 файлов и unit36 прошли на5b2a291. 12.4.5 принят локально:main1110/171 прошли на21859be. 12.3.26 принят локально:strict atomic Ping write/подтверждение каталога и сохранения/история удаления/62 browser/context11/DI6/builds. 12.3.27 принят локально:WireGuard zero/missing counters/UI/backend mapper/29 browser/unit/builds. 12.3.28 принят локально:WireGuard interfaces1000/50 DOM/pinning/actions/cache/29+1 browser/build. 12.3.29 принят локально:WG peers1000/50 DOM/pinning/точный delete target/29+3 browser/build. Следующий блок12.3.30: большое раскрытие пиров; далее network grids и полная main/context регрессия.12.5 отдельно. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются. +Этап 11Б завершён в границах локальной приёмки (11Б.7); внешний выпуск не проверен. 12.1 принят локально: доступность оболочки/клавиатура/health в описанных сценариях. 12.2.1 принят локально: strict BGP catalog/partial/nullable counters. 12.2.2 принят локально: strict traffic DTO и агрегация без выдуманных точек. 12.2.3 принят локально: observations для server traffic от backend до dashboard. 12.2.4 принят локально: strict servers/probes и unknown server status. 12.2.5 принят локально: реальные ping samples/unknown/ось RTT/Recharts. 12.2.6 принят локально: strict GRE/WireGuard/VXLAN и device failures. 12.2.7 принят локально: strict Internet path snapshot/fallback. 12.2.8 принят локально: подтверждение полного backend сбора. 12.2.9 принят локально: метрики участков и наблюдаемый WAN без эвристической подмены. 12.3.1 принят локально:1000 серверов/штатная пагинация. 12.3.2 принят локально: пагинация CompactDataGrid/1000 строк статистики. 12.3.3 принят локально: порционный DOM очереди проблем. 12.3.4 принят локально: большой BGP каталог/страница при обновлении. Production build и123 профильных browser приняты локально на3978976. 12.2.10 принят локально: обязательные RouterOS поля. 12.3.5 принят локально: страница CompactDataGrid сохраняется при опросе,89 browser и повторный production build прошли. 12.3.6 сохранён: baseline1000 speed probes (ограничение DOM пока не выполнено). 12.3.7 принят локально:50 строк speed-проб/сохранение страницы/глобальная сортировка/1000→1; каталог1001 устройства остаётся в DOM. 12.3.8 принят локально:50 строк ресурсов, URL/поиск/сохранение страницы/1000→1; исправлена pagination оболочки с children, production build и8 больших browser прошли. 12.3.9 принят локально:порционное раскрытие1000 предупреждений ресурсов/клавиатура/axe; исходная ошибка ESLint speedDraft подтверждена. 12.3.10 принят локально:недоступные интерфейсы очищаются в обработчиках,54 browser/полный ESLint/production build прошли. 12.3.11 принят локально:ServerTileRail50 устройств/URL/поиск/клавиатура/две площадки/mobile Sheet/axe обе темы;47 browser и production build прошли. 12.3.12 принят локально:BGP ручная страница при выбранной URL сессии/refresh/reload,16 browser/build прошли. 12.4.1 записан:main1091 сценарий/1088 passed/3 устаревших fixtures; оба исправленных файла6 passed. 12.4.2 принят локально:context205/24 файла и unit28 прошли. 12.3.13 принят локально:wide pivot51×16/ScrollArea/axe/24+2 browser/builds. 12.3.14 принят локально:history200/50 DOM/54+1 browser/build. 12.3.15 принят локально:live расписание1000/page20 error cache/15 browser. 12.3.16 принят локально:certificates1000/50 DOM/refresh деталей/19+3 browser/build. 12.3.17 принят локально:pinning идентификатора/видимость значений/29 browser/build. 12.3.18 принят локально:users1000/поиск всего списка/детали и ошибка refresh/32 browser/build. 12.3.19 принят локально:backups1000/все мобильные действия/возврат focus/39+4 browser/build. 12.3.20 принят локально:независимые speed GET/cache/freshness/58+4 browser/build. 12.3.21 принят локально:strict history DTO/null rates от DB до UI/60+5 browser/unit4/builds. 12.4.3 принят локально:users/backups delta context36 на a558412. 12.3.22 принят локально:shared speed-probes DTO/context8/60+6+47 browser/unit5/builds. 12.3.23 принят локально:strict write DTO/atomic replacement/confirmed scheduler warning/65 browser/HTTP DI JWT/builds. 12.3.24 принят локально:OSPF routes1000/50 DOM/page20/cache/320px/22+1 browser/build. 12.3.25 принят локально:BFD1000/50 DOM/cache/320px/12 browser/build. 12.4.4 принят локально:context213/25 файлов и unit36 прошли на5b2a291. 12.4.5 принят локально:main1110/171 прошли на21859be. 12.3.26 принят локально:strict atomic Ping write/подтверждение каталога и сохранения/история удаления/62 browser/context11/DI6/builds. 12.3.27 принят локально:WireGuard zero/missing counters/UI/backend mapper/29 browser/unit/builds. 12.3.28 принят локально:WireGuard interfaces1000/50 DOM/pinning/actions/cache/29+1 browser/build. 12.3.29 принят локально:WG peers1000/50 DOM/pinning/точный delete target/29+3 browser/build. 12.3.30 принят локально:WG detail1000/50 DOM/320px/клавиатура/31+1 browser/build. Следующий блок12.3.31: достоверность подписи рукопожатия; далее network grids и полная main/context регрессия.12.5 отдельно. См. docs/ux-ui-stage-12.md. Внешние ограничения 11Б сохраняются. Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md). diff --git a/docs/ux-ui-progress.md b/docs/ux-ui-progress.md index faa04af9..8751950c 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -36,6 +36,14 @@ +## 12.3.30 — порционное раскрытие пиров WireGuard (2026-10-04) + +Раскрытие интерфейса ограничено50 пирами на страницу, сохраняет страницу при refresh и ограничивает её при сокращении списка до отображения. Имена и точные IDs действий сохранены. На320px карточки имеют две колонки внутри sticky области шириной экрана; кнопки44px, пагинация доступна с клавиатуры и показывает диапазон/общий счётчик. На ПК сохраняется компактная строка полей. + +Профиль1000 пиров:50 карточек/2388 DOM nodes. Проверены Enter/страница20/refresh,320px при крайнем horizontal scroll/доступ к действиям/axe detail, правильный последний пир в delete dialog и1000→1.31 browser прошли; после устранения setState-in-effect повтор большого detail1/1. TypeScript без incremental, ESLint и production frontend build прошли. [Снимок320px](ux-ui/screens/large-wireguard-detail-320.png) просмотрен. Измерения используют локальные HTTP-моки, RouterOS latency не измерена. + +Следующий блок12.3.31: убрать вывод «онлайн» из наличия старого handshake, показать отсутствие данных отдельно. Официальный RouterOS last-handshake — время после последнего успешного рукопожатия: https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard. Затем WireGuard URL filters/context и оставшиеся network grids.17 manualPagination:true grids/общая регрессия после delta/внешняя12.5 остаются. Коммит локальный без push. + ## 12.3.29 — большой каталог пиров WireGuard (2026-10-04) Peer grid теперь использует client pagination50, clamp и сохранение страницы при refresh. Полный поиск/сортировка выполняются до страницы, composite server/interface/peer ID сохранён. Штатные ReUI ScrollArea/start pinning удерживают идентификатор на320px, действия имеют44px цель. Подтверждение удаления теперь показывает имя и точный ID пира, а не только интерфейс. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index fde99649..ff6c29c2 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -416,3 +416,12 @@ Peer grid теперь использует client pagination50, clamp и сох Осталось17 manualPagination:true specialized grids, включая bounded/demo источники. Следующий блок12.3.30: ограничить DOM раскрытия большого списка пиров одного интерфейса. Восстановление WireGuard search/tab/status из URL, аудит подписи «онлайн» по факту handshake и внешняя12.5 остаются; presence старого handshake не доказывает текущую доступность. Общая main/context после delta целиком ещё не повторена. Коммит локальный без push. + +## 12.3.30 — порционное раскрытие пиров WireGuard (2026-10-04) + +Раскрытие интерфейса ограничено50 пирами на страницу, сохраняет страницу при refresh и ограничивает её при сокращении списка до отображения. Имена и точные IDs действий сохранены. На320px карточки имеют две колонки внутри sticky области шириной экрана; кнопки44px, пагинация доступна с клавиатуры и показывает диапазон/общий счётчик. На ПК сохраняется компактная строка полей. + +Профиль1000 пиров:50 карточек/2388 DOM nodes. Проверены Enter/страница20/refresh,320px при крайнем horizontal scroll/доступ к действиям/axe detail, правильный последний пир в delete dialog и1000→1.31 browser прошли; после устранения setState-in-effect повтор большого detail1/1. TypeScript без incremental, ESLint и production frontend build прошли. [Снимок320px](ux-ui/screens/large-wireguard-detail-320.png) просмотрен. Измерения используют локальные HTTP-моки, RouterOS latency не измерена. + +Следующий блок12.3.31: убрать вывод «онлайн» из наличия старого handshake, показать отсутствие данных отдельно. Официальный RouterOS last-handshake — время после последнего успешного рукопожатия: https://help.mikrotik.com/docs/spaces/ROS/pages/69664792/WireGuard. Затем WireGuard URL filters/context и оставшиеся network grids.17 manualPagination:true grids/общая регрессия после delta/внешняя12.5 остаются. Коммит локальный без push. + diff --git a/docs/ux-ui/screens/large-wireguard-detail-320.png b/docs/ux-ui/screens/large-wireguard-detail-320.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed800293e1b33124b000cb5e60fe129700d7632 GIT binary patch literal 48649 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/large-wireguard-peers.spec.ts b/tests/e2e/large-wireguard-peers.spec.ts index f6e24a93..fb6426ab 100644 --- a/tests/e2e/large-wireguard-peers.spec.ts +++ b/tests/e2e/large-wireguard-peers.spec.ts @@ -52,3 +52,30 @@ test("WireGuard1000 peers: full search/sort/page/cache/target/320px", async ({ p await expect(page.getByRole("alertdialog")).toContainText("Пир 1000");await page.getByRole("alertdialog").getByRole("button",{name:"Отмена",exact:true}).click() expect(writes).toEqual([]) }) + +test("WireGuard1000 peer details: bounded DOM/page/refresh/clamp/keyboard/320px", async ({ page }, info) => { + test.setTimeout(90000) + let peers = Array.from({length:1000},(_,i)=>({id:"p"+(i+1),rosId:"*P"+(i+1),publicKey:"key-"+(i+1),name:"Пир "+(i+1),allowedIps:["10."+Math.floor(i/256)+"."+(i%256)+".1/32"],transferRx:0})) + let calls=0 + await page.route("**/health",r=>r.fulfill({json:{ok:true}})) + await page.route("**/api/**",r=>{const p=new URL(r.request().url()).pathname;if(p==="/api/wireguard"){calls++;return r.fulfill({json:wgListResponseSchema.parse({interfaces:[{id:"*1",rosId:"*1",name:"wg-main",serverId:"1",serverName:"Роутер",listenPort:13231,mtu:1420,comment:"",enabled:true,status:"up",peers}]})})}return r.fulfill({json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[]:{}})}) + await page.goto("/wireguard") + await page.getByRole("button",{name:"Пиры: wg-main",exact:true}).click() + const region=page.getByRole("region",{name:"Пиры: wg-main",exact:true}),items=region.locator("[data-wireguard-peer]") + await expect(items).toHaveCount(50) + const profile={peers:peers.length,rendered:await items.count(),nodes:await page.locator("*").count()};console.log("WG detail profile",JSON.stringify(profile));await info.attach("profile",{body:JSON.stringify(profile),contentType:"application/json"}) + const next=region.getByRole("button",{name:"Следующая страница пиров",exact:true}) + await next.focus();await page.keyboard.press("Enter");await expect(items.first()).toHaveAttribute("data-wireguard-peer","p51") + for(let i=1;i<19;i++)await next.click() + await expect(next).toBeDisabled();await expect(items.first()).toHaveAttribute("data-wireguard-peer","p951") + const before=calls;await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect.poll(()=>calls).toBeGreaterThan(before);await expect(items.first()).toHaveAttribute("data-wireguard-peer","p951") + await page.setViewportSize({width:320,height:1000});await region.scrollIntoViewIfNeeded() + const scroll=page.locator('[data-slot="data-grid"] [data-slot="scroll-area-viewport"]');await scroll.evaluate(el=>{el.scrollLeft=el.scrollWidth}) + expect(await region.evaluate(el=>{const r=el.getBoundingClientRect();return r.left>=0&&r.right<=innerWidth})).toBe(true) + await expect(items.first().getByRole("button",{name:"Удалить пира",exact:true})).toBeInViewport() + expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true) + await page.addScriptTag({content:axe.source});expect((await page.evaluate(async()=>(window as unknown as {axe:typeof axe}).axe.run(document.querySelector('section[aria-label="Пиры: wg-main"]')!,{runOnly:{type:"tag",values:["wcag2a","wcag2aa","wcag21a","wcag21aa"]}}))).violations).toEqual([]) + await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:info.outputPath("wireguard-detail-320.png"),animations:"disabled"}) + await items.last().getByRole("button",{name:"Удалить пира",exact:true}).click();await expect(page.getByRole("alertdialog")).toContainText("Пир 1000");await page.getByRole("alertdialog").getByRole("button",{name:"Отмена",exact:true}).click() + peers=[peers[999]];await page.getByRole("button",{name:"Обновить",exact:true}).click();await expect(items).toHaveCount(1);await expect(items.first()).toHaveAttribute("data-wireguard-peer","p1000") +})