fix(ui): завершить основу таблиц и фильтров серверов

This commit is contained in:
Denozordec committed 2026-09-13 14:46:17 +07:00
1 parent f9a4a07996
commit 3d3c45e4d2
24 files changed
+385 -263

No files matched your search

+7 -52
View File
@@ -1,54 +1,9 @@
# ReUI: оставшиеся замечания реестра
# ReUI: итог lint этапа 2
2026-09-13. `npx eslint components/reui/data-grid components/reui/filters components/reui/cascader --format json`. Осталось 21 ошибка и 27 предупреждений (было 23 и 27). Две ошибки сложных выражений в зависимостях useMemo исправлены без изменения семантики сравнения. Правила не отключены.
2026-09-13. Проверены изменённые файлы серверов/Filters и вся новая группа Data Grid, Filters, Cascader. **0 ошибок, 1 предупреждение** (исходно 23 ошибки и 27 предупреждений). Правила не отключены.
| Файл | Позиция | Уровень | Правило | Замечание |
| --- | --- | --- | --- | --- |
| `components/reui/cascader/cascader-async.tsx` | 786:7 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader-virtual.tsx` | 132:5 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader.tsx` | 934:15 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/cascader/cascader.tsx` | 934:15 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/cascader/cascader.tsx` | 1089:22 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader.tsx` | 1142:5 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader.tsx` | 1672:5 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader.tsx` | 1688:27 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/cascader/cascader.tsx` | 2111:45 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/cascader/cascader.tsx` | 2112:36 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/data-grid/data-grid-scroll-area.tsx` | 234:7 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/data-grid/data-grid-table-dnd-rows.tsx` | 62:3 | warning | `@typescript-eslint/no-unused-vars` | 'verticalListSortingStrategy' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table-dnd-rows.tsx` | 67:39 | warning | `@typescript-eslint/no-unused-vars` | 'Table' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table-dnd-rows.tsx` | 454:5 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/data-grid/data-grid-table-dnd.tsx` | 61:3 | warning | `@typescript-eslint/no-unused-vars` | 'Table' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 32:28 | warning | `@typescript-eslint/no-unused-vars` | 'Table' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 762:23 | warning | `react-hooks/incompatible-library` | Compilation Skipped: Use of incompatible library |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 807:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 811:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 813:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 815:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 817:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 835:9 | warning | `react-hooks/exhaustive-deps` | The 'virtualItems' conditional could make the dependencies of useEffect Hook (at line 1037) change on every render. To fix this, wrap the initialization of 'virtualItems' in its own useMemo() Hook. |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 1052:3 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 31:42 | warning | `@typescript-eslint/no-unused-vars` | 'Table' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table.tsx` | 744:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 746:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 748:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 750:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 756:5 | warning | `directive` | Unused eslint-disable directive (no problems were reported from 'react-hooks/exhaustive-deps'). |
| `components/reui/data-grid/data-grid-table.tsx` | 959:3 | warning | `@typescript-eslint/no-unused-vars` | 'rowId' is defined but never used. Allowed unused args must match /^_/u. |
| `components/reui/data-grid/data-grid-table.tsx` | 1463:11 | warning | `@typescript-eslint/no-unused-vars` | 'table' is assigned a value but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table.tsx` | 2342:30 | warning | `@typescript-eslint/no-unused-vars` | 'TData' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid-table.tsx` | 2411:24 | warning | `@typescript-eslint/no-unused-vars` | 'TData' is defined but never used. Allowed unused vars must match /^_/u. |
| `components/reui/data-grid/data-grid.tsx` | 889:3 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/data-grid/data-grid.tsx` | 892:3 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/data-grid/data-grid.tsx` | 899:3 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/data-grid/data-grid.tsx` | 949:44 | error | `react-hooks/refs` | Error: Cannot access refs during render |
| `components/reui/data-grid/data-grid.tsx` | 950:5 | warning | `react-hooks/exhaustive-deps` | React Hook useMemo has an unnecessary dependency: 'table.store'. Either exclude it or remove the dependency array. |
| `components/reui/filters/filters-advanced.tsx` | 757:18 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/filters/filters-advanced.tsx` | 765:5 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/filters/filters-advanced.tsx` | 1529:9 | warning | `@typescript-eslint/no-unused-vars` | 'issueMap' is assigned a value but never used. Allowed unused vars must match /^_/u. |
| `components/reui/filters/filters-advanced.tsx` | 1544:6 | warning | `react-hooks/exhaustive-deps` | React Hook React.useMemo has an unnecessary dependency: 'rowStateVersion'. Either exclude it or remove the dependency array. |
| `components/reui/filters/filters-advanced.tsx` | 1566:9 | warning | `@typescript-eslint/no-unused-vars` | 'focusFirstIssue' is assigned a value but never used. Allowed unused vars must match /^_/u. |
| `components/reui/filters/filters-chip.tsx` | 377:15 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/filters/filters-chip.tsx` | 466:18 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
| `components/reui/filters/filters-chip.tsx` | 550:9 | warning | `@typescript-eslint/no-unused-vars` | 'operator' is assigned a value but never used. Allowed unused vars must match /^_/u. |
| `components/reui/filters/filters-chip.tsx` | 569:18 | error | `react-hooks/set-state-in-effect` | Error: Calling setState synchronously within an effect can trigger cascading renders |
Оставшийся виртуализатор исключается React Compiler из автоматической мемоизации. Его браузерную регрессию и производительность проверять при переносе использующих его экранов. Исходные общепроектные ошибки вне этого этапа перечислены в основном журнале.
| Файл | Позиция | Правило | Замечание |
| --- | --- | --- | --- |
| `components/reui/data-grid/data-grid-table-virtual.tsx` | 764:23 | `react-hooks/incompatible-library` | Compilation Skipped: Use of incompatible library |
+36 -2
View File
@@ -16,8 +16,8 @@
| --- | --- | --- |
| 0 | Исходная база, карта миграции, проверки и обзор экранов | Завершён 2026-09-13 |
| 1 | Достоверность сохранения, удаления, включения и опроса серверов | Завершён 2026-09-13 |
| 2 | Общая оболочка Data Grid/TanStack v9, Filters и эталон серверов | В работе: основа и серверы перенесены, приёмка не завершена |
| 3 | Основные таблицы и справочники | Не начат |
| 2 | Общая оболочка Data Grid/TanStack v9, Filters и эталон серверов | Завершён 2026-09-13, с перечисленными ограничениями приёмки |
| 3 | Основные таблицы и справочники | Следующий, отдельное окно |
| 4 | Остальные таблицы, удаление старых API, общая регрессия | Не начат |
| 5 | Состояния данных, свежесть, частичные сбои, гонки polling | Не начат |
| 6 | Навигация и дашборд | Не начат |
@@ -147,6 +147,40 @@ flowchart LR
Проверки: TypeScript всего проекта прошёл; браузерный тест v9 (12 строк, сортировка, раскрытие) прошёл. Повторный lint группы: **21 ошибка, 27 предупреждений**, актуальный компактный отчёт — `docs/reui-migration-lint.md`. Production build не повторялся после этой локальной правки; предыдущая сборка этапа прошла. Этап 2 остаётся в работе; следующий объём прежний.
## Этап 2 — завершение
Продолжение от `f9a4a07` в `codex/reui-v9-migration`. Записи о промежуточных остановках выше — история; текущий следующий шаг — **этап 3**.
### Результат
- Серверы используют ReUI Data Grid/TanStack 9.2.4 и новый `FilterQuery`; таблица сохраняет все строки, сортировку, детали и подтверждённые операции этапа 1. Для раскрытия есть отдельная кнопка с `aria-expanded`, работающая с клавиатуры. При пустом результате фильтрации показывается «Нет совпадений», а не предложение добавить первый сервер.
- `ServerFilters` повторяет контракт официального `c-filters-1`. Поля `country/status/type` имеют `type: select`, потому что данные скалярные. Варианты множественного выбора задаются операторами. Добавлены русские подписи Filters, вычислитель дерева `applyFilterQuery` и временный `migrateFilterQuery` для AND-массива старых условий. Неизвестное условие не расширяет выборку, незавершённые условия не превращают OR в истинное выражение.
- `DataPageToolbar.filterControl` позволяет переносить потребителей по одному; старые props сохранены только на период этапов 3–4. Новые импорты Filters обязательно указывают `/filters/filters`, пока существует старый одноимённый файл.
- Выполнены локальные исправления совместимости исходников ReUI с React Compiler. Контекст Data Grid передаёт актуальный снимок данных; императивный координатор ширины получает только закоммиченные React значения. Кэш подписей Cascader обновляется без мутации ref во время рендера; измерения запускаются через ResizeObserver/кадр браузера, отложенная навигация отменяется при смене контекста. Draft и автооткрытие Filters синхронизируются до рендера дочерних редакторов. Убраны неиспользуемые импорты и лишние вычисления. Правила lint не отключались, публичные API и композиция сохранены. При будущем обновлении реестра эти исправления сравнить с upstream, не перезаписывать автоматически.
### Приёмка
| Проверка | Результат |
| --- | --- |
| `npm run test:servers` | 17 браузерных тестов прошли, включая операции, сортировку 12 строк, фильтрацию AND, изменение/сброс, Escape и клавиатурное раскрытие |
| `npx tsx --test lib/data-filters/apply-filter-query.test.ts` | 6 тестов прошли: AND/OR, отрицание, черновики, пустые/неизвестные условия, эквивалентность поддерживаемых старых операторов |
| TypeScript и `npm run build` | Успешно, 34 статические страницы |
| Lint изменённых участков и новой группы ReUI | 0 ошибок, 1 предупреждение `react-hooks/incompatible-library` для виртуализатора. React Compiler пропускает его оптимизацию; [отчёт](reui-migration-lint.md) |
| Визуальная проверка | Просмотрены экраны 1440×1000 и 390×844. Page overflow отсутствует; широкая таблица сохраняет горизонтальный скролл внутри своего контейнера |
| ReUI audit | Checklist получен; проверены композиция Frame/base-nova, API, типизированные HTTP-данные, подписи, состояния и фокус эталона. Правки internals ограничены описанной совместимостью, без смены дизайна |
Границы приёмки: моки HTTP не подтверждают реальные права или применение RouterOS. Общая мобильная шапка обрезает часть действий, KPI занимают много высоты — исходные задачи этапов 6–7. Некоторые служебные объявления вложенного Cascader ещё английские — завершить локализацию на этапе 7. Все режимы DnD/виртуализации/автоподбора ширины не были проверены браузером на этом этапе; их проверять при переносе использующих их экранов. Изменённый способ публикации контекста Data Grid требует профилирования больших таблиц на этапе 12. Это не полная приёмка доступности/производительности всего приложения.
### Образец следующего переноса
1. В выбранном доменном grid заменить `react-table-v8` на `react-table`, legacy-оболочку на `DataGridShell` и заголовки на новый `DataGridSortHeader`.
2. Тип колонок — `ColumnDef<DataGridFeatures, T>`, таблицы — `Table<DataGridFeatures, T>`. Использовать `useTable({ features: dataGridFeatures, ... })`; удалить старые `get*RowModel`. Сверить переименованные sorting/pinning/resize props с установленным API. Сохранить стабильный `getRowId`.
3. Явно определить пагинацию: для полного списка без панели — `manualPagination: true`; для серверной — передавать реальный `rowCount`; для клиентской — подключить панель и контролируемую страницу.
4. Для Filters перенести поля `key → id`, выбрать тип по данным, сохранить AND через `migrateFilterQuery`. Вычислитель сейчас поддерживает только операторы скалярных фильтров серверов и прежние текстовые contains; перед переносом дат, чисел или массивов расширить вычисление и тесты. Нельзя просто сплющить OR-дерево.
5. Проверить фильтрацию, сортировку, сброс/страницу, раскрытие и действия. Старую основу удалять только после последнего потребителя в этапе 4.
Следующий шаг: проверить квоту и состояние файлов; выполнить только этап 3 (обзор, мониторинг, трафик, статистика и справочники) в этой ветке, перечислить оставшихся legacy-потребителей и сделать локальный коммит без push. Перед миграцией виртуализированных таблиц добавить профильные проверки указанного выше риска контекста. Этапы 2–4 не выпускать до общей регрессии этапа 4.
## Карта миграции
Текущая связка: @tanstack/react-table ^8.21.3, @tanstack/react-virtual ^3.14.4, base-nova. Актуальный ReUI MCP ранее подтвердил useTable/dataGridFeatures для Data Grid и дерево FilterQuery вместо filters/onChange для Filters. Перед установкой перепроверить совместимые версии, сохранить семантику существующих фильтров (простые условия → AND) и закрепить lockfile.