Files
vesti/openspec/changes/archive/2026-09-17-keep-bulk-checkboxes/design.md
T
kpa39l c8fe5f7c85 fix(web): keep bulk checkbox selection across post navigation (openspec change keep-bulk-checkboxes)
- Save/restore checked candidate ids in sessionStorage (vesti_bulk_candidates / vesti_bulk_selected)
- Restore checks after page reload when opening a post via ?selected=N
- Fix selector: checkboxes live outside <form> (form=bulk-form attribute), query input[name=ids] globally
- Openspec: new capability candidates-bulk-selection, change archived
2026-09-17 00:52:51 +00:00

34 lines
4.1 KiB
Markdown

## Context
Страницы /candidates и /selected (FastAPI + Jinja2 + Bootstrap, шаблоны web/templates/candidates.html и selected.html) имеют общий паттерн: слева список постов с чекбоксами массового выбора (form bulk-form, input name=ids), справа детали открытого поста. Открытие поста — обычная GET-навигация (?selected=N), которая перезагружает страницу: сервер отдаёт checked только для текущего поста, остальные отметки теряются. Серверный код (web/app.py) менять не требуется — фикс чистого frontend.
## Goals / Non-Goals
**Goals:**
- Сохранять отметки чекбоксов между перезагрузками страницы (навигация по постам) на /candidates и /selected.
- Восстанавливать отметки при загрузке; считать sel-count по восстановленному состоянию.
- Сбрасывать состояние после успешной отправки bulk-формы.
**Non-Goals:**
- Не менять серверный рендеринг, API, БД.
- Не делать мульти-выбор «как в трекере» со сложным состоянием на сервере — только сохранение существующих чекбоксов.
## Decisions
1. **Хранилище — sessionStorage браузера (не localStorage, не сервер).**
- Отметки нужны только в рамках текущей вкладки/сессии просмотра, серверное состояние не требуется (список кандидатов меняется от краула, ids в sessionStorage «протухнут» — это ок, чекбокс просто не найдётся).
- localStorage переживал бы вкладки и захламлялся бы; серверное состояние = лишний API + потеря при «назад».
- Ключ: `vesti_bulk_<page>` где page ∈ {candidates, selected}. Изоляция страниц (требование спеки) — автоматически через разные ключи.
2. **JS-инициализация в конце body (block scripts), как существующий скрипт подсчёта.**
- После загрузки DOM: прочитать sessionStorage, проставить checked всем чекбоксам ids из сохранённого Set, затем вызвать upd() для счётчика.
- Перехват change на чекбоксах: перезапись Set в sessionStorage (add/delete по value).
- Перехват submit bulk-form: очистить sessionStorage (отметки отправлены — состояние больше не нужно).
3. **Чекбокс открытого поста** продолжает получать `checked` от сервера (существующая логика `{% if selected and selected.id == p.id %}checked{% endif %}`) — сохраняется текущее поведение; поверх него восстанавливаются остальные.
## Risks / Trade-offs
- [Отметки «протухают» при повторном использовании страницы позже] → ок: sessionStorage живёт до закрытия вкладки; ids не найденных постов игнорируются.
- [Дублирование кода в двух шаблонах] → приёмлемо: шаблоны уже дублируют bulk-логику; выносить общий JS в static-файл можно позже отдельным change-ом.
- [Отключённый JS] → до фикса поведение было «отметки сбрасываются при навигации»; после фикса без JS — то же самое, регрессии нет.