diff --git a/app/(main)/dashboard/page.tsx b/app/(main)/dashboard/page.tsx index 9fc314f5..f5750db5 100644 --- a/app/(main)/dashboard/page.tsx +++ b/app/(main)/dashboard/page.tsx @@ -1,5 +1,7 @@ "use client" +import { useState } from "react" +import { Button } from "@/components/ui/button" import Link from "next/link" import { ActivityIcon, @@ -36,6 +38,8 @@ function fmtIntRu(n: number): string { } function AttentionRows({ rows }: { rows: AttentionRow[] }) { + const [expanded,setExpanded]=useState(false) + const [visible,setVisible]=useState(55) function renderRow(row: AttentionRow) { return ( {rows.slice(0, 5).map(renderRow)} {rows.length > 5 && ( -
+
{setExpanded(event.currentTarget.open);if(!event.currentTarget.open)setVisible(55)}}> Ещё {rows.length - 5} - {rows.slice(5).map(renderRow)} + {expanded && rows.slice(5,visible).map(renderRow)} + {expanded && rows.length>visible && }
)} diff --git a/docs/ux-ui-plan.md b/docs/ux-ui-plan.md index 61252fe6..f549a897 100644 --- a/docs/ux-ui-plan.md +++ b/docs/ux-ui-plan.md @@ -4,7 +4,7 @@ ## Актуальная точка продолжения — 2026-10-03 -Этап 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 очереди проблем; затем специализированные grids и12.4 сводная регрессия/production build. См. 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 каталог/сохранение страницы при обновлении; затем остальные специализированные grids и12.4 регрессия/build. См. 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 b80efc0b..ca273f49 100644 --- a/docs/ux-ui-progress.md +++ b/docs/ux-ui-progress.md @@ -36,6 +36,14 @@ +## 12.3.3 — DOM очереди проблем дашборда (2026-10-04) + +AttentionRows больше не создаёт весь скрытый список: первые5 всегда видны, native details монтирует следующие50 по запросу, кнопка добавляет по50. Закрытие удаляет скрытые строки и сбрасывает порцию; полный счётчик/ссылки сохраняются. Нет скрытых1000 anchors до действия пользователя. Раскрытие выполняется обычным summary и клавиатурой, используется существующий Button; Frame/AttentionQueue primitives unchanged. + +Проверки:62 dashboard/permissions browser (включая1000 проблем: DOM5→55→105→5→55, переход к серверу,320px),20 dashboard unit, typecheck/ESLint прошли. На fixture1000 offline servers начальный dashboard:831 DOM nodes,1081ms ready в одном dev прогоне. Порционное раскрытие может по запросу пользователя постепенно создать весь список; полноценная виртуализация очереди не заявляется. + +Далее12.3.4: большой каталог BGP, учитывая сохранение страницы при фоновом обновлении. Другие27 специализированных manualPagination grids и wide pivot остаются отдельными ограничениями.12.4 сводные проверки/production build ещё не приняты; внешняя приёмка не заменяется локальными данными. + ## 12.3.2 — ограничение DOM общего CompactDataGrid (2026-10-04) Общая компактная таблица теперь использует штатную client pagination50 строк; сохранены исходные data/columns/row callbacks и загрузка/empty/detail. Навигация сохраняется при выбранном меньшем размере. На1000 строк статистики (88894 JSON bytes массива users) DOM уменьшился12585→1210 nodes, rendered rows1000→50. Доready5195ms, после2928/1195ms в отдельных dev прогонах; прогретость отличается, production SLA не заявляется. Полный ответ и pivot columns по-прежнему находятся в памяти. diff --git a/docs/ux-ui-stage-12.md b/docs/ux-ui-stage-12.md index 520b6ab8..ca875e1d 100644 --- a/docs/ux-ui-stage-12.md +++ b/docs/ux-ui-stage-12.md @@ -118,3 +118,11 @@ Active WAN выбирается только по наблюдаемому defau Проверки:25 statistics/migrated/catalog/snapshot browser прошли; large-case сначала ошибочно ожидал прямую кнопку последней страницы из нового upstream API, установленная версия использует группы. Тест исправлен под фактические штатные ellipsis controls, повтор1 large-case прошёл (последняя страница, назад, сортировка всего1000 набора,320px). Typecheck/ESLint прошли; ReUI API/checklist изучены, установленный primitive не переписан. Не считать12.3 завершённым:28 специализированных grids используют manualPagination:true и требуют раздельного разбора (часть получает server page/limit). Скрытые строки AttentionRows тоже всё ещё создаются в DOM. Далее12.3.3: управляемое раскрытие большой очереди проблем, затем профильный разбор специализированных grids/ограничений и12.4 регрессия/build. + +## 12.3.3 — DOM очереди проблем дашборда (2026-10-04) + +AttentionRows больше не создаёт весь скрытый список: первые5 всегда видны, native details монтирует следующие50 по запросу, кнопка добавляет по50. Закрытие удаляет скрытые строки и сбрасывает порцию; полный счётчик/ссылки сохраняются. Нет скрытых1000 anchors до действия пользователя. Раскрытие выполняется обычным summary и клавиатурой, используется существующий Button; Frame/AttentionQueue primitives unchanged. + +Проверки:62 dashboard/permissions browser (включая1000 проблем: DOM5→55→105→5→55, переход к серверу,320px),20 dashboard unit, typecheck/ESLint прошли. На fixture1000 offline servers начальный dashboard:831 DOM nodes,1081ms ready в одном dev прогоне. Порционное раскрытие может по запросу пользователя постепенно создать весь список; полноценная виртуализация очереди не заявляется. + +Далее12.3.4: большой каталог BGP, учитывая сохранение страницы при фоновом обновлении. Другие27 специализированных manualPagination grids и wide pivot остаются отдельными ограничениями.12.4 сводные проверки/production build ещё не приняты; внешняя приёмка не заменяется локальными данными. diff --git a/tests/e2e/dashboard-data.spec.ts b/tests/e2e/dashboard-data.spec.ts index a15f9fd1..a08e361a 100644 --- a/tests/e2e/dashboard-data.spec.ts +++ b/tests/e2e/dashboard-data.spec.ts @@ -265,3 +265,7 @@ for(const state of ["unmeasured","measured","failed","unknown"])test("Dashboard if(state==="unknown"){await expect(strip.getByText("Неизвестно",{exact:true})).toBeVisible();await expect(strip.getByText("Оффлайн",{exact:true})).toHaveCount(0)} await page.setViewportSize({width:320,height:900});await expect(strip).toBeVisible();expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true) }) + +test("Dashboard large attention queue mounts rows on demand",async({page},info)=>{ + test.setTimeout(90000);const start=Date.now();await setup(page,false,1000);await expect(refresh(page)).toBeEnabled();const queue=page.getByRole("region",{name:"Требует внимания",exact:true});const links=queue.locator('a[href^="/servers?server="]');await expect(links).toHaveCount(5);const sample={fixtureRows:1000,readyMs:Date.now()-start,renderedAttentionRows:await links.count(),domNodes:await page.locator("*").count()};console.log(JSON.stringify(sample));await info.attach("large-attention-metrics",{body:JSON.stringify(sample),contentType:"application/json"});const summary=queue.locator("summary").filter({hasText:"Ещё 995"});await summary.focus();await summary.press("Enter");await expect(links).toHaveCount(55);await queue.getByRole("button",{name:"Показать ещё 50",exact:true}).click();await expect(links).toHaveCount(105);await summary.focus();await summary.press("Enter");await expect(links).toHaveCount(5);await summary.press("Enter");await expect(links).toHaveCount(55);await page.setViewportSize({width:320,height:900});expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true);await links.first().click();await expect(page).toHaveURL(/servers\?server=1$/);await expect(page.getByRole("status",{name:"Сервер по ссылке"})).toContainText("Узел 1") +})