AURORA-1841: справочник ВСП - виртуализация строк и вынос состояния модалок #219

Merged
aep merged 4 commits from feat/214-aurora-1841-dict-vsp-virtual into test 2026-11-01 09:35:18 +03:00
Owner

Closes #214

Jira: AURORA-1841

Что сделано

  • Состояние модалок (open, editingItem, exportOpen, saveLoading, handleSave) вынесено из TableDictVsp в новый DictVspModals (forwardRef + useImperativeHandle: openAdd, openEdit(item), openExport). Открытие модалки больше не перерисовывает MRT-таблицу.
  • TableDictVsp обёрнут в memo; колбэки onAddClick/onEditClick/onExportClick в DictVspPage стабильные (useCallback + ref на модалки); handleAdd/handleEdit/handleDelete обёрнуты в useCallback.
  • Виртуализация строк (enableRowVirtualization, overscan: 5, estimateSize 54). Высота строк измеряется MRT по умолчанию, потому что «Примечания» многострочные (pre-wrap); осознанное отличие от 1836.
  • size/minSize/maxSize колонок выверены под grid-раскладку (было size > maxSize у «Код РФ»; ширины подняты под длину заголовков и адресов, чтобы ничего не обрезалось).
  • Фильтрация по ССП вынесена в utils/filterVspBySsp.js.

Тесты

  • web/src/pages/DictVspPage/utils/filterVspBySsp.test.js - 3 теста, node --test: 3 pass, 0 fail.
  • npm run build проходит. biome: новых нарушений нет (остались прежние console, ==).
  • Бэк не менялся, pytest не запускался.

Проверить руками

Роли admin и executor_dfip:

  • добавить ВСП, отредактировать, удалить
  • фильтр по ССП
  • экспорт
  • прокрутка до конца (720 строк): № идёт подряд, строки с многострочными примечаниями не наезжают друг на друга
  • закреплённые колонки слева (№, Код РФ, Регистрационный номер) и «Действия» справа на месте
  • заголовки и адреса не обрезаны, горизонтальный скролл работает, вертикальный скролл внутри контейнера
    Роль executor_rf: фильтров нет, таблица и экспорт работают.

Замер до/после

Будет добавлен после ночного прогона на стенде perf/. Сценарий: модалки dict_vsp_* на масштабе 1 (PERF_MODALS='dict_vsp_*' PERF_REPEATS=5 npx playwright test scenarios/modals.spec.ts; метрики click_to_visible_ms, main_thread_ms; база 167/193/159 мс) + разовый замер на 720 ВСП доращиванием через create_vsp после остальных замеров.

Rulings I made

  • R-1: ширины колонок подобраны по оценке длины заголовка (bold 0.88rem), без скриншота «до». Цена ошибки: возможна обрезка заголовка или лишняя ширина, правится числами в columns.
  • R-2: estimateSize = 54 px (padding 2*0.75rem + строка 18 px). Цена ошибки: небольшие прыжки скроллбара.

🤖 Generated with Claude Code

Closes #214 Jira: AURORA-1841 ## Что сделано - Состояние модалок (`open`, `editingItem`, `exportOpen`, `saveLoading`, `handleSave`) вынесено из `TableDictVsp` в новый `DictVspModals` (`forwardRef` + `useImperativeHandle`: `openAdd`, `openEdit(item)`, `openExport`). Открытие модалки больше не перерисовывает MRT-таблицу. - `TableDictVsp` обёрнут в `memo`; колбэки `onAddClick`/`onEditClick`/`onExportClick` в `DictVspPage` стабильные (`useCallback` + ref на модалки); `handleAdd`/`handleEdit`/`handleDelete` обёрнуты в `useCallback`. - Виртуализация строк (`enableRowVirtualization`, `overscan: 5`, `estimateSize` 54). Высота строк измеряется MRT по умолчанию, потому что «Примечания» многострочные (`pre-wrap`); осознанное отличие от 1836. - `size/minSize/maxSize` колонок выверены под grid-раскладку (было `size > maxSize` у «Код РФ»; ширины подняты под длину заголовков и адресов, чтобы ничего не обрезалось). - Фильтрация по ССП вынесена в `utils/filterVspBySsp.js`. ## Тесты - `web/src/pages/DictVspPage/utils/filterVspBySsp.test.js` - 3 теста, `node --test`: 3 pass, 0 fail. - `npm run build` проходит. biome: новых нарушений нет (остались прежние `console`, `==`). - Бэк не менялся, pytest не запускался. ## Проверить руками Роли admin и executor_dfip: - [ ] добавить ВСП, отредактировать, удалить - [ ] фильтр по ССП - [ ] экспорт - [ ] прокрутка до конца (720 строк): № идёт подряд, строки с многострочными примечаниями не наезжают друг на друга - [ ] закреплённые колонки слева (№, Код РФ, Регистрационный номер) и «Действия» справа на месте - [ ] заголовки и адреса не обрезаны, горизонтальный скролл работает, вертикальный скролл внутри контейнера Роль executor_rf: фильтров нет, таблица и экспорт работают. ## Замер до/после Будет добавлен после ночного прогона на стенде perf/. Сценарий: модалки `dict_vsp_*` на масштабе 1 (`PERF_MODALS='dict_vsp_*' PERF_REPEATS=5 npx playwright test scenarios/modals.spec.ts`; метрики `click_to_visible_ms`, `main_thread_ms`; база 167/193/159 мс) + разовый замер на 720 ВСП доращиванием через `create_vsp` после остальных замеров. ## Rulings I made - R-1: ширины колонок подобраны по оценке длины заголовка (bold 0.88rem), без скриншота «до». Цена ошибки: возможна обрезка заголовка или лишняя ширина, правится числами в `columns`. - R-2: `estimateSize` = 54 px (padding 2*0.75rem + строка 18 px). Цена ошибки: небольшие прыжки скроллбара. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 2 commits 2026-10-28 17:10:21 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Модалки в DictVspModals (forwardRef), таблица в memo со стабильными колбэками,
enableRowVirtualization, size/minSize/maxSize колонок выверены под grid-раскладку.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Ночной замер на стенде perf/ (29.10, масштаб 1 = 180 ВСП, D0 без grow, CPU 1x, arm-ka-* остановлены; Apple M4)

Сборки: «до» — test 2a28748; «после» — этот PR b0de763. Данные и API одни.
Команда: PERF_MODALS='dict_vsp_*' PERF_PRIORITY=2 PERF_REPEATS=5 npx playwright test scenarios/modals.spec.ts; рендеры — профилирующая сборка :8081 PERF_PROFILING=1 PERF_REPEATS=1.

модалка (admin), медиана 5 click_to_visible до → после, мс main_thread до → после, мс коммитов / рендеров за открытие до → после
dict_vsp_add 184.2 → 74.6 187.4 → 81.3 10 / 26 971 → 9 / 1 622
dict_vsp_edit 192.1 → 52.0 202.2 → 71.7 12 / 27 287 → 11 / 1 938
dict_vsp_export 167.1 → 54.1 171.0 → 57.0 9 / 25 722 → 8 / 373

Таблица выпала из коммита открытия: в «до» в топе Styled(td) 2 896 рендеров и MRT_TableBodyCell 2 880, в «после» — только поля формы (DateField, DesktopDatePicker).

Вердикт: критерий Jira «≤ 60 мс при 720 ВСП» на 180 ВСП: edit 52.0 и export 54.1 — в пределах, add 74.6 — выше 60 (14 мс self React — DateField/DesktopDatePicker модалки). Замер на 720 ВСП (доращивание create_vsp) — в плане после всех замеров; если не успею — отмечу в итоговом комментарии.

Скриншоты справочника (1600×900, верх и конец списка): до — night/base/shots/base-dictvsp-1600-{top,end}.png, после — night/1841/shots/p1841-dictvsp-1600-{top,end}.png; каталог /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/. Попиксельная сверка — в итоговом комментарии.

🤖 Generated with Claude Code

## Ночной замер на стенде perf/ (29.10, масштаб 1 = 180 ВСП, D0 без grow, CPU 1x, arm-ka-* остановлены; Apple M4) **Сборки:** «до» — `test` 2a28748; «после» — этот PR b0de763. Данные и API одни. **Команда:** `PERF_MODALS='dict_vsp_*' PERF_PRIORITY=2 PERF_REPEATS=5 npx playwright test scenarios/modals.spec.ts`; рендеры — профилирующая сборка :8081 `PERF_PROFILING=1 PERF_REPEATS=1`. | модалка (admin), медиана 5 | click_to_visible до → после, мс | main_thread до → после, мс | коммитов / рендеров за открытие до → после | |---|---|---|---| | dict_vsp_add | 184.2 → **74.6** | 187.4 → 81.3 | 10 / 26 971 → 9 / 1 622 | | dict_vsp_edit | 192.1 → **52.0** | 202.2 → 71.7 | 12 / 27 287 → 11 / 1 938 | | dict_vsp_export | 167.1 → **54.1** | 171.0 → 57.0 | 9 / 25 722 → 8 / 373 | Таблица выпала из коммита открытия: в «до» в топе `Styled(td)` 2 896 рендеров и `MRT_TableBodyCell` 2 880, в «после» — только поля формы (`DateField`, `DesktopDatePicker`). **Вердикт:** критерий Jira «≤ 60 мс при 720 ВСП» на 180 ВСП: edit 52.0 и export 54.1 — в пределах, **add 74.6 — выше 60** (14 мс self React — DateField/DesktopDatePicker модалки). Замер на 720 ВСП (доращивание `create_vsp`) — в плане после всех замеров; если не успею — отмечу в итоговом комментарии. Скриншоты справочника (1600×900, верх и конец списка): до — `night/base/shots/base-dictvsp-1600-{top,end}.png`, после — `night/1841/shots/p1841-dictvsp-1600-{top,end}.png`; каталог `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/`. Попиксельная сверка — в итоговом комментарии. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

Ночной замер — часть 2 (итог)

Сборки как в части 1 (до — test, после — b0de763). Добавлено: 720 ВСП, сверка скриншотов, combo.

720 ВСП (D1 + доращивание до 720 записей create_vsp одинаково для обеих сборок; PERF_MODALS='dict_vsp_*' PERF_PRIORITY=2 PERF_REPEATS=5), click_to_visible_ms, медиана [min–max]:

модалка (admin) test, 720 1841, 720 1841, 180 (часть 1) порог ≤ 60
dict_vsp_add 503.7 [488.3–519.7] 69.4 [66.2–74.1] 74.6 не выполнен
dict_vsp_edit 575.8 [572.9–589.8] 52.0 [47.8–54.4] 52.0 выполнен
dict_vsp_export 472.6 [471.2–473.5] 55.0 [48.6–57.8] 54.1 выполнен
Рендеры за открытие add (профилирующая сборка, 720 ВСП): 102 031 (self 275.8 мс) → 1 622 (20.8 мс); Styled(td) 11 536 → нет в топе. Остаток add — DateField/DesktopDatePicker.

combo (180 ВСП): add 68.3, edit 48.7, export 56.8 (одиночная 1841: 74.6 / 52.0 / 54.1; export на 5 % выше внутри разброса 51.7–60.0).

Сверка скриншотов 1600×900, верх и конец списка (base против p1841): 6,3 % пикселей, и в combo ровно столько же. На картинках не косметика:

  • в base таблица справочника имеет 11 колонок, в 1841 — 8: нет «Дата закрытия ВСП» и «Форма расположения ВСП», остальные колонки шире;
  • в окно влезает 12 строк вместо 11; данные и порядок строк (№ 1…12, RF01-0001…) те же.
    То же на 720 ВСП (vsp720/shots). Причина не установлена (возможно, виртуализация колонок по ширине окна); проверить руками до мержа.
    Сравнить: /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/base/shots/base-dictvsp-1600-top.png и /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1841/shots/p1841-dictvsp-1600-top.png, разница — /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/imgdiff/diff-p1841-dictvsp-1600-top.png.

Вердикт по цели Jira (≤ 60 мс при 720 ВСП): edit и export — выполнен; add — не выполнен (69.4). Критерий «ячейки не рендерятся при открытии» — выполнен.
Файлы: /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/vsp720/, прогоны perf/report-data/n-{base,p1841}-vsp720.

## Ночной замер — часть 2 (итог) Сборки как в части 1 (до — `test`, после — b0de763). Добавлено: 720 ВСП, сверка скриншотов, combo. **720 ВСП** (D1 + доращивание до 720 записей `create_vsp` одинаково для обеих сборок; `PERF_MODALS='dict_vsp_*' PERF_PRIORITY=2 PERF_REPEATS=5`), click_to_visible_ms, медиана [min–max]: | модалка (admin) | test, 720 | **1841, 720** | 1841, 180 (часть 1) | порог ≤ 60 | |---|---|---|---|---| | dict_vsp_add | 503.7 [488.3–519.7] | **69.4** [66.2–74.1] | 74.6 | **не выполнен** | | dict_vsp_edit | 575.8 [572.9–589.8] | **52.0** [47.8–54.4] | 52.0 | выполнен | | dict_vsp_export | 472.6 [471.2–473.5] | **55.0** [48.6–57.8] | 54.1 | выполнен | Рендеры за открытие add (профилирующая сборка, 720 ВСП): 102 031 (self 275.8 мс) → 1 622 (20.8 мс); `Styled(td)` 11 536 → нет в топе. Остаток add — `DateField`/`DesktopDatePicker`. **combo (180 ВСП):** add 68.3, edit 48.7, export 56.8 (одиночная 1841: 74.6 / 52.0 / 54.1; export на 5 % выше внутри разброса 51.7–60.0). **Сверка скриншотов 1600×900, верх и конец списка (base против p1841): 6,3 % пикселей, и в combo ровно столько же.** На картинках не косметика: - в base таблица справочника имеет 11 колонок, в 1841 — 8: **нет «Дата закрытия ВСП» и «Форма расположения ВСП»**, остальные колонки шире; - в окно влезает 12 строк вместо 11; данные и порядок строк (№ 1…12, RF01-0001…) те же. То же на 720 ВСП (`vsp720/shots`). Причина не установлена (возможно, виртуализация колонок по ширине окна); **проверить руками до мержа.** Сравнить: `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/base/shots/base-dictvsp-1600-top.png` и `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1841/shots/p1841-dictvsp-1600-top.png`, разница — `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/imgdiff/diff-p1841-dictvsp-1600-top.png`. **Вердикт по цели Jira (≤ 60 мс при 720 ВСП):** edit и export — выполнен; **add — не выполнен (69.4)**. Критерий «ячейки не рендерятся при открытии» — выполнен. Файлы: `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/vsp720/`, прогоны `perf/report-data/n-{base,p1841}-vsp720`.
aep added 1 commit 2026-10-29 11:11:00 +03:00
aep added 1 commit 2026-10-29 11:23:14 +03:00
Author
Owner

Разбор ночной находки: «пропавшие» колонки справочника — исправлено

Колонки не пропадали: виртуализация строк включила grid-раскладку (ширина = size), а ширины колонок были подняты (R-1 исполнителя) — таблица стала шире на 600 px, «Дата закрытия ВСП» и «Форма расположения ВСП» ушли под закреплённую справа «Действия».

  • bf64fa0 — ширины как в test (измерены в браузере, 1600×900); у «Региональный филиал/ССП» maxSize поднят до 200, чтобы вместить фактические 186 px.
  • 7b67740 — заголовок «Действия» был на 10 px ниже (в grid th — flex-колонка, align center центрировал по вертикали): justifyContent: 'flex-start'.
    Проверка в браузере: ширины всех 16 колонок и scrollWidth (2330 против 2331) совпадают с test.
## Разбор ночной находки: «пропавшие» колонки справочника — исправлено Колонки не пропадали: виртуализация строк включила grid-раскладку (ширина = size), а ширины колонок были подняты (R-1 исполнителя) — таблица стала шире на 600 px, «Дата закрытия ВСП» и «Форма расположения ВСП» ушли под закреплённую справа «Действия». - bf64fa0 — ширины как в test (измерены в браузере, 1600×900); у «Региональный филиал/ССП» maxSize поднят до 200, чтобы вместить фактические 186 px. - 7b67740 — заголовок «Действия» был на 10 px ниже (в grid th — flex-колонка, align center центрировал по вертикали): `justifyContent: 'flex-start'`. Проверка в браузере: ширины всех 16 колонок и scrollWidth (2330 против 2331) совпадают с test.
PotapovaA approved these changes 2026-10-29 15:59:24 +03:00
aep merged commit 61c8ab7fff into test 2026-11-01 09:35:18 +03:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/DFiP_Budget_planing#219
No description provided.