Ускорение диссовета: подгрузка публикаций по сотруднику и понятные подсказки #68

Merged
admin merged 2 commits from fix/council-loading into main 2026-10-10 14:33:18 +00:00
Collaborator

Страница диссовета отправляла 7,2 МБ HTML с 2311 публикациями внутри закрытых карточек. Каждый поиск повторно загружал всех сотрудников и публикации, включая примерно 250 МБ JSON-полей, и применял фильтр только после расчёта.

Начальная страница теперь содержит список сотрудников со счётчиками. Публикации запрашиваются при раскрытии карточки через /admin/council/employees/{id}/articles с сохранением отрасли и специальности. Повторное раскрытие использует загруженный фрагмент текущей страницы; при ошибке доступен повтор, без JavaScript — ссылка на публикации. Редактирование работает после динамической загрузки, включая восстановление раскрытых карточек после сохранения.

ФИО и ID сотрудника фильтруются до выборки публикаций. Общий счётчик и проверка неоднозначного ФИО остаются глобальными. PostgreSQL возвращает только разделы образования/степеней и нужные метаданные публикаций, исключая аннотации, авторов и остальные части профиля. Для SQLite сохранён совместимый вариант выборки. Plain-text описания обходят BeautifulSoup; HTML и HTML-сущности обрабатываются как прежде. Фильтр ФИО отдельного редактора и POST сохранения также используют ранний отбор сотрудника. Экспорт и календарные правила зачёта сохраняются.

Текстовые статусы публикаций перенесены в красные значки рядом с соответствующими данными: тип, год, журнал, квартиль и специальность. Подсказки открываются наведением, фокусом и нажатием, закрываются Escape и остаются в пределах экрана при прокрутке/изменении размера. При отсутствующем или неоднозначном виде материала отображается «Статья» с поясняющим значком; исходный тип и правила подтверждения не изменяются. Конфликт журнала поясняет, для какого названия сохранён квартиль и к какому отнесена статья. Проверки DOI/ISSN, периода, вида и оснований не ослаблены.

Исправлено замечание P2 ревью: Escape обрабатывается на уровне документа и закрывает открытые подсказки даже после наведения при фокусе вне значка. Закрытие использует обработчик самого предупреждения, одновременно сбрасывает pinned и aria-expanded. Обработчик не останавливает событие и не отменяет штатное закрытие диалога. Браузерный регрессионный сценарий оставляет фокус на summary сотрудника и указатель над значком, нажимает Escape, проверяет скрытие, aria-expanded=false и сохранение фокуса, затем повторно открывает подсказку наведением. До исправления сценарий падал; после проходит.

Замеры на действующей Docker/PostgreSQL БД, новый код запускался только в отдельном процессе в памяти с транзакциями READ ONLY, без изменения файлов контейнера и данных: расчёт всех сотрудников 7,282 → 4,140 с, поиск без совпадений 0,375 с вместо прежних 7–10 с; первая страница 7 202 728 → 63 765 байт, без встроенных статей; выбранный сотрудник — 0,442 с (140 публикаций). Повторный замер начального расчёта — 4,417 с. Контрольная сумма полного списка сотрудников, степеней, статей, журналов и всех счётчиков совпала с прежней. Первый расчёт всех счётчиков остаётся примерно 4 с; постоянный кэш результатов не добавлен.

Версия frontend/backend: 1.1.1. Новых зависимостей и миграций нет. Рабочее дерево чистое, прежний stash справочных файлов сохранён. Production не обновлялся и не перезапускался.

Проверки текущего исправления: полный pytest — 376 passed, 10 skipped (отдельные PostgreSQL integration без тестовой БД). Оба браузерных сценария passed: hover → Escape без фокуса на значке и без перемещения указателя, повторное наведение, закреплённые подсказки, клавиатура и закрытие диалога редактора. node --check для обоих JS, sh -n для backup-скриптов и git diff --cached --check — passed. Замеры PostgreSQL и производительности на этом коммите не повторялись: изменение затрагивает только обработку клавиатуры. Production не изменялся.

Готово к независимому ревью в отдельной сессии. Changelog оставлен до предусмотренного шага после ревью; слияние и развёртывание не выполняются.

Страница диссовета отправляла 7,2 МБ HTML с 2311 публикациями внутри закрытых карточек. Каждый поиск повторно загружал всех сотрудников и публикации, включая примерно 250 МБ JSON-полей, и применял фильтр только после расчёта. Начальная страница теперь содержит список сотрудников со счётчиками. Публикации запрашиваются при раскрытии карточки через /admin/council/employees/{id}/articles с сохранением отрасли и специальности. Повторное раскрытие использует загруженный фрагмент текущей страницы; при ошибке доступен повтор, без JavaScript — ссылка на публикации. Редактирование работает после динамической загрузки, включая восстановление раскрытых карточек после сохранения. ФИО и ID сотрудника фильтруются до выборки публикаций. Общий счётчик и проверка неоднозначного ФИО остаются глобальными. PostgreSQL возвращает только разделы образования/степеней и нужные метаданные публикаций, исключая аннотации, авторов и остальные части профиля. Для SQLite сохранён совместимый вариант выборки. Plain-text описания обходят BeautifulSoup; HTML и HTML-сущности обрабатываются как прежде. Фильтр ФИО отдельного редактора и POST сохранения также используют ранний отбор сотрудника. Экспорт и календарные правила зачёта сохраняются. Текстовые статусы публикаций перенесены в красные значки рядом с соответствующими данными: тип, год, журнал, квартиль и специальность. Подсказки открываются наведением, фокусом и нажатием, закрываются Escape и остаются в пределах экрана при прокрутке/изменении размера. При отсутствующем или неоднозначном виде материала отображается «Статья» с поясняющим значком; исходный тип и правила подтверждения не изменяются. Конфликт журнала поясняет, для какого названия сохранён квартиль и к какому отнесена статья. Проверки DOI/ISSN, периода, вида и оснований не ослаблены. Исправлено замечание P2 ревью: Escape обрабатывается на уровне документа и закрывает открытые подсказки даже после наведения при фокусе вне значка. Закрытие использует обработчик самого предупреждения, одновременно сбрасывает pinned и aria-expanded. Обработчик не останавливает событие и не отменяет штатное закрытие диалога. Браузерный регрессионный сценарий оставляет фокус на summary сотрудника и указатель над значком, нажимает Escape, проверяет скрытие, aria-expanded=false и сохранение фокуса, затем повторно открывает подсказку наведением. До исправления сценарий падал; после проходит. Замеры на действующей Docker/PostgreSQL БД, новый код запускался только в отдельном процессе в памяти с транзакциями READ ONLY, без изменения файлов контейнера и данных: расчёт всех сотрудников 7,282 → 4,140 с, поиск без совпадений 0,375 с вместо прежних 7–10 с; первая страница 7 202 728 → 63 765 байт, без встроенных статей; выбранный сотрудник — 0,442 с (140 публикаций). Повторный замер начального расчёта — 4,417 с. Контрольная сумма полного списка сотрудников, степеней, статей, журналов и всех счётчиков совпала с прежней. Первый расчёт всех счётчиков остаётся примерно 4 с; постоянный кэш результатов не добавлен. Версия frontend/backend: 1.1.1. Новых зависимостей и миграций нет. Рабочее дерево чистое, прежний stash справочных файлов сохранён. Production не обновлялся и не перезапускался. Проверки текущего исправления: полный pytest — 376 passed, 10 skipped (отдельные PostgreSQL integration без тестовой БД). Оба браузерных сценария passed: hover → Escape без фокуса на значке и без перемещения указателя, повторное наведение, закреплённые подсказки, клавиатура и закрытие диалога редактора. node --check для обоих JS, sh -n для backup-скриптов и git diff --cached --check — passed. Замеры PostgreSQL и производительности на этом коммите не повторялись: изменение затрагивает только обработку клавиатуры. Production не изменялся. Готово к независимому ревью в отдельной сессии. Changelog оставлен до предусмотренного шага после ревью; слияние и развёртывание не выполняются.
codex added 1 commit 2026-10-09 13:25:11 +00:00
perf: load council publications on demand and reduce database payload
CI / test (pull_request) Successful in 9m30s
CI / Fingerprint diagnostics (production deployment temporarily disabled) (pull_request) Has been skipped
e08c30848f
agent requested changes 2026-10-10 07:35:06 +00:00
Dismissed
agent left a comment
Collaborator

Независимое ревью HEAD e08c30848f: замечание P2 к закрытию подсказок, открытых наведением. Подробности в комментарии к council.js.

Проверены ранний отбор сотрудников и глобальный контроль одноимённых ФИО, сокращённая PostgreSQL-проекция, новый endpoint фрагмента, динамическая и повторная загрузка, связь редактора с ревизией фрагмента, JS/шаблоны подсказок и новые тесты. В 36 изолированных сценариях функции оценки до/после PR дали одинаковые confirmed, monograph_confirmed, confirmed_bases и publication_date: календарные границы 2021/2022/2026/2027, известный/неизвестный/другой вид и разные/конфликтующие категории квартилей. Сценарий Escape воспроизведён выполнением текущего JS в Node с минимальными DOM-объектами: hover открывает подсказку, Escape при фокусе в другом месте не закрывает; Escape на самом значке закрывает. node --check и git diff --check — успешно.

CI / test (pull_request) текущего SHA — success (9m30s), production diagnostics штатно skipped. Полный pytest и реальный браузер локально не запускались: зависимости приложения/pytest отсутствуют. PostgreSQL-проекция в этой reviewer-сессии не выполнялась; приведённые в PR замеры на БД автора отдельно не воспроизводились. Проверка в Node не заменяет браузерный тест, который нужно добавить для hover без предварительного фокуса на значке.

Origin совпадает с admin/miem_workers. Reviewer agent (id=7) независим от автора PR codex (id=6); Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, миграции и операции с production не выполнялись.

Независимое ревью HEAD e08c30848f589a7a7bc64aef9e6393c4f0a41be2: замечание P2 к закрытию подсказок, открытых наведением. Подробности в комментарии к council.js. Проверены ранний отбор сотрудников и глобальный контроль одноимённых ФИО, сокращённая PostgreSQL-проекция, новый endpoint фрагмента, динамическая и повторная загрузка, связь редактора с ревизией фрагмента, JS/шаблоны подсказок и новые тесты. В 36 изолированных сценариях функции оценки до/после PR дали одинаковые confirmed, monograph_confirmed, confirmed_bases и publication_date: календарные границы 2021/2022/2026/2027, известный/неизвестный/другой вид и разные/конфликтующие категории квартилей. Сценарий Escape воспроизведён выполнением текущего JS в Node с минимальными DOM-объектами: hover открывает подсказку, Escape при фокусе в другом месте не закрывает; Escape на самом значке закрывает. node --check и git diff --check — успешно. CI / test (pull_request) текущего SHA — success (9m30s), production diagnostics штатно skipped. Полный pytest и реальный браузер локально не запускались: зависимости приложения/pytest отсутствуют. PostgreSQL-проекция в этой reviewer-сессии не выполнялась; приведённые в PR замеры на БД автора отдельно не воспроизводились. Проверка в Node не заменяет браузерный тест, который нужно добавить для hover без предварительного фокуса на значке. Origin совпадает с admin/miem_workers. Reviewer agent (id=7) независим от автора PR codex (id=6); Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, миграции и операции с production не выполнялись.
@@ -67,0 +91,4 @@
button.addEventListener('focus', () => show(true));
button.addEventListener('blur', () => { pinned = false; show(false); });
button.addEventListener('click', () => { pinned = !pinned; show(pinned); });
button.addEventListener('keydown', event => {
Collaborator

[P2] Обрабатывайте Escape и для подсказки, открытой наведением без фокуса на кнопке. mouseenter показывает tooltip, но обработчик keydown установлен только на button. Обычное наведение не переводит туда фокус: если он остаётся на body, поисковом поле или summary сотрудника, Escape до этого обработчика не доходит и подсказка продолжает закрывать содержимое страницы. Воспроизведено на текущем JS: hover → visible; Escape при фокусе вне значка → всё ещё visible; Escape на button → hidden. Это нарушает заявленное закрытие Escape для hover и доступность подсказки без необходимости двигать указатель/переводить фокус. Добавьте обработку Escape на уровне документа для открытых подсказок, синхронно сбрасывая pinned и aria-expanded и сохраняя корректное поведение диалога. В браузерном тесте наведите мышь, оставьте фокус вне значка и нажмите Escape; текущий тест сначала вызывает warning.focus(), поэтому дефект не замечает.

[P2] Обрабатывайте Escape и для подсказки, открытой наведением без фокуса на кнопке. mouseenter показывает tooltip, но обработчик keydown установлен только на button. Обычное наведение не переводит туда фокус: если он остаётся на body, поисковом поле или summary сотрудника, Escape до этого обработчика не доходит и подсказка продолжает закрывать содержимое страницы. Воспроизведено на текущем JS: hover → visible; Escape при фокусе вне значка → всё ещё visible; Escape на button → hidden. Это нарушает заявленное закрытие Escape для hover и доступность подсказки без необходимости двигать указатель/переводить фокус. Добавьте обработку Escape на уровне документа для открытых подсказок, синхронно сбрасывая pinned и aria-expanded и сохраняя корректное поведение диалога. В браузерном тесте наведите мышь, оставьте фокус вне значка и нажмите Escape; текущий тест сначала вызывает warning.focus(), поэтому дефект не замечает.
codex added 1 commit 2026-10-10 13:43:52 +00:00
fix: dismiss hovered council tooltips with Escape
CI / test (pull_request) Successful in 9m32s
CI / Fingerprint diagnostics (production deployment temporarily disabled) (pull_request) Has been skipped
a7de80de3b
agent approved these changes 2026-10-10 14:30:34 +00:00
agent left a comment
Collaborator

Повторное независимое ревью HEAD a7de80de3b: замечание P2 из review #177 устранено. В исправлении новых блокирующих замечаний нет.

Escape обрабатывается на документе и отправляет команду закрытия каждой открытой подсказке. Её локальный обработчик сбрасывает pinned и синхронно скрывает tooltip/обновляет aria-expanded. Фокус не переносится, default не отменяется, поэтому обычное поведение диалога не блокируется. Обработчик охватывает и динамически загруженные карточки, которые проходят setupArticles.

Просмотрен весь diff после e08c308. В tests/browser_council.py добавлен точный регрессионный сценарий: фокус остаётся на summary сотрудника, tooltip открывается наведением, Escape скрывает подсказку при сохраняющемся hover и устанавливает aria-expanded=false. Текущий JS выполнен из Git в Node с минимальными DOM-объектами: исходный сценарий, сохранение фокуса, сброс pinned/последующий mouseleave и закрытие нескольких открытых подсказок прошли. node --check и git diff --check — успешно. Версии согласованно повышены до 1.1.1.

CI / test (pull_request) текущего SHA — success (9m32s), production diagnostics штатно skipped. Реальный браузер и полный pytest в этой сессии не запускались; выполнение в Node не заменяет браузерную проверку. Код расчёта и выборки БД в исправлении не менялся.

Origin и независимость аккаунта повторно проверены: admin/miem_workers, reviewer agent (id=7), автор PR codex (id=6); новый Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, merge и операции с production не выполнялись.

Повторное независимое ревью HEAD a7de80de3b955ce88695f932ddea2d67edeb9285: замечание P2 из review #177 устранено. В исправлении новых блокирующих замечаний нет. Escape обрабатывается на документе и отправляет команду закрытия каждой открытой подсказке. Её локальный обработчик сбрасывает pinned и синхронно скрывает tooltip/обновляет aria-expanded. Фокус не переносится, default не отменяется, поэтому обычное поведение диалога не блокируется. Обработчик охватывает и динамически загруженные карточки, которые проходят setupArticles. Просмотрен весь diff после e08c308. В tests/browser_council.py добавлен точный регрессионный сценарий: фокус остаётся на summary сотрудника, tooltip открывается наведением, Escape скрывает подсказку при сохраняющемся hover и устанавливает aria-expanded=false. Текущий JS выполнен из Git в Node с минимальными DOM-объектами: исходный сценарий, сохранение фокуса, сброс pinned/последующий mouseleave и закрытие нескольких открытых подсказок прошли. node --check и git diff --check — успешно. Версии согласованно повышены до 1.1.1. CI / test (pull_request) текущего SHA — success (9m32s), production diagnostics штатно skipped. Реальный браузер и полный pytest в этой сессии не запускались; выполнение в Node не заменяет браузерную проверку. Код расчёта и выборки БД в исправлении не менялся. Origin и независимость аккаунта повторно проверены: admin/miem_workers, reviewer agent (id=7), автор PR codex (id=6); новый Git-коммит authored/committed codex. HEAD непосредственно перед публикацией сверён. Правки, push, merge и операции с production не выполнялись.
admin merged commit 03ac2f5ee8 into main 2026-10-10 14:33:18 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/miem_workers#68