Andrey Epifancev ef9abfa8bd docs: план доработок экранов доски (#112)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:08:15 +04:00

129 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
После выкатки #108 (25.10.2026) владелец посмотрел «Бэклог», «Спринт» и «Kanban» на живой доске AWPCA (4216, три
спринта) и записал 10 замечаний в sdlc-hub#112. Владелец попросил не проводить brainstorming-вопросы и писать дизайн
по тексту issue, поэтому всё, что в issue не сказано прямо, — решения агента (раздел «Decisions made without
discussion»).
Текущее состояние (`web/src/modules/jira/agile/`): `BacklogPage` рисует секции `Panel` без свёртки, эпики идут строками
наравне с задачами; `SprintPage` показывает один активный спринт, переключатель `Segmented` — только между активными;
`BoardColumns` — flex-ряд с `align-items:flex-start` и `overflow-x:auto`; `TypeIcon` знает три вида (эпик —
`IconBoard`, ошибка — `IconCritical` (молния), прочее — `IconCheck`). Фильтров нет. Все нужные данные уже приходят в
`GET /agile` (`AgileIssue`: `issue_type`, `assignee`, `epic_key`, `done`, `rank`, `status`) — сервер не меняется.
## Goals / Non-Goals
Цели — 10 пунктов #112 и попутно веб-маркеры из hub#111 (M-6, T10.3, T9.4, T12.2–T12.4). Не цели — правки Jira из
веба, изменения API/схемы/агента/MCP, настройки доски AWPCA в Jira, серверные пункты hub#111.
## Decisions
1. **Фильтры — на клиенте, чистой моделью.** Новый модуль `agile/filters.ts`: тип состояния страницы
(`q`, `assignee`, `epic`, `hideDone`, `collapsed`, `hiddenColumns`, `epicsPanel`), функция «видна ли задача»
(поиск по `key` и `summary` без учёта регистра; `assignee`: `""` — все, `"-"` — без исполнителя; `epic`: `""` — все,
`"-"` — без эпика, иначе `epic_key === epic`; `hideDone`), списки вариантов исполнителей и эпиков. Страницы и
компоненты только рисуют. Модель покрыта unit-тестами, страницы — тестами поведения.
2. **Запоминание — один ключ `sdlc-hub-agile`.** JSON `{ "<метка>": { "backlog": {...}, "sprint": {...},
"kanban": {...} } }`; хранится всё, кроме `q` и выбора спринтов. Чтение и запись — в `try/catch` (закрытое
хранилище, мусор, чужая форма — значения по умолчанию), как `sidebarPref`/`legendPref`. Миграция `jira-hub-` не нужна
— ключ новый. Свёрнутые секции — по id спринта и `"backlog"`; id закрытых/удалённых спринтов при чтении не мешают
(просто не совпадают). Скрытые колонки — по имени колонки (`"Без колонки"` — тоже имя).
3. **Панель фильтров** — общий компонент `AgileToolbar` для трёх страниц, набор элементов — пропсами. Используются
готовые `SearchInput`, `Select`, `Checkbox`/`Button aria-pressed`, `Dropdown`/`Menu` из `web/src/ui`; новые элементы
UI-кита не вводятся, кроме значков (п. 7). Устаревшее значение исполнителя/эпика остаётся в списке (как
`withCurrent` у списка задач), чтобы пустой результат объяснялся видимым фильтром.
4. **Свёртка секций «Бэклога».** Заголовок секции — `<button aria-expanded aria-controls>` с шевроном
(`IconChevronDown`/`Up`) и прежним содержимым заголовка; свёрнутая секция показывает только заголовок с итогами.
«Прошлые спринты» остаются `<details>` (не запоминаются — как сейчас).
5. **Эпики на «Бэклоге».** Эпик — задача, у которой `TypeIcon` определяет вид «эпик» (одна функция `typeKind` для
значка и фильтра). Строки эпиков убираются из всех секций «Бэклога» (и из счёта «N задач» секции «Бэклог», который
считается на клиенте). Панель — колонка слева шириной ~240 px в сетке страницы; при контейнере `page` уже 900 px —
`Select «Эпик»` в панели фильтров. Число у эпика — задачи с этим `epic_key` в активных, будущих спринтах и «Бэклоге»
без учёта остальных фильтров. На «Спринте» и «Kanban» эпики не трогаются (в issue речь только о бэклоге).
6. **Итоги секций — факты спринта.** Заголовок спринта показывает серверные `count`/`points`/`unestimated`; фильтры их
не меняют, добавляется «показано K», когда видно меньше задач секции. Так ретро-цифры спринта не «плавают» от фильтра.
Числа в заголовках колонок доски — по видимым карточкам.
7. **Значки типов по образцу Jira.** `typeKind(issue_type)` → `epic | story | task | bug | subtask | other`; значок —
скруглённый квадрат 16 px цвета вида с белым символом (эпик — молния, история — закладка, задача — галочка, ошибка
— круг, подзадача — два квадрата, прочее — нейтральный серый квадрат с точкой). Новые символы — в
`web/src/ui/icons.tsx` тем же `make(...)`; цвета — токенами дизайн-системы (эпик — `--k-ui`, история —
`--color-status-success`, задача — `--color-action-primary`, ошибка — `--color-status-error`, подзадача и прочее —
нейтральные), контраст белого символа проверить в обеих темах. При завершении — перенести значки в kit скилла
`aura-design`.
8. **Выбор спринтов на «Спринте».** `Dropdown` с отметками (активные, затем будущие по `start_date`, без даты — в
конце), адрес `?sprint=<id>[,<id>…]` с `replace` (без записи истории). Задачи доски — объединение задач выбранных
спринтов без повторов по ключу, порядок — по `rank` (строка LexoRank сравнивается как строка; `null` — в конце, затем
по ключу). Заголовков столько, сколько выбрано спринтов, компактной строкой каждый; «осталось N дн.» — только у
активного. Прежний одиночный `?sprint=<id>` остаётся рабочим адресом.
9. **Колонки одной высоты и прокрутка (пп. 8 и 10).** Гипотеза по багу (подтвердить воспроизведением в начале
задачи, superpowers:systematic-debugging): горизонтальная полоса `.agile-columns` есть, но лежит под самой длинной
колонкой, далеко ниже окна (и скрыта macOS до прокрутки), поэтому правые колонки на 2560 px выглядят обрезанными.
Исправление: страницы доски растягиваются на высоту основной области оболочки (`flex:1; min-height:0` по цепочке,
доска `min-height:360px`), `.agile-columns` — `align-items:stretch` и своя высота, у колонки прокручивается список
(`overflow-y:auto`). Тогда полоса горизонтальной прокрутки всегда у нижнего края окна, колонки одной высоты. Если
воспроизведение покажет другую причину — чинится причина, требование спеки то же.
10. **Скрытие колонок** — меню «Колонки» с отметками на «Спринте» и «Kanban»; последнюю видимую снять нельзя; число
скрытых — `Badge` на кнопке. Скрытие — только вид, `columnsOf` не меняется, фильтруется результат.
11. **Попутные маркеры hub#111.** M-6 — `fmtSp` округляет до двух знаков и убирает хвостовые нули (веб-сторона;
MCP `:g` не трогаем, расхождение для дробных до сотых исчезает). T10.3 — `h3` в заголовках колонок. T9.4 — тесты
загрузки и ошибки `AgileGate` и пункта «Kanban» kanban-проекта в меню. T12.2–T12.4 — e2e доски: фиксированный
`jira_updated` в сиде, строгие локаторы по роли и тексту, без зависимости от порядка DOM.
12. **Тестовые данные.** Сид e2e (`web/scripts/test-hub.sh` и фикстуры агента) дополняется так, чтобы были: эпик с
задачами в спринте и бэклоге, задачи без эпика и без исполнителя, будущий спринт с задачами, доска с числом колонок
и карточек, достаточным для широкой доски из сценария «Широкая доска».
## Risks / Trade-offs
- **Высота доски от оболочки.** Растяжение по высоте зависит от цепочки flex в `shell.css`/`Layout.tsx`; нельзя
сломать прокрутку других страниц — e2e «страница без горизонтальной прокрутки» и сценарии оболочки остаются зелёными.
- **Объединение спринтов.** Задача может числиться и в активном, и в будущем спринте (перенос) — без дедупликации
карточка задвоится; дедупликация по ключу — в п. 8.
- **Распознавание эпика по имени типа.** Тип зависит от локали Jira; список имён — один на значок и фильтр, расширяется
в одном месте.
## Decisions made without discussion
Все — 25.10.2026, владелец попросил писать дизайн по issue без вопросов. Нумерация рулингов R-n — с R-1 в пределах
этой фичи.
- R-1 (design #2): фильтры и свёртка запоминаются отдельно по странице (`backlog`/`sprint`/`kanban`) и проекту, поиск
и выбор спринтов — не запоминаются. Обоснование: как в Jira — поиск разовый, выбор спринтов живёт в адресе.
Цена ошибки — сделать исполнителя общим для страниц или запоминать поиск: правка одного модуля `filters.ts`.
- R-2 (design #5): эпики убираются строками только на «Бэклоге»; на «Спринте» и «Kanban» остаются карточками.
Обоснование: в issue речь о бэклоге. Цена ошибки — тот же фильтр на доске, одна строка.
- R-3 (design #5): фильтр по эпику действует и на прошлые спринты; число у эпика — без учёта других фильтров и без
прошлых спринтов. Цена ошибки — правка подсчёта в модели.
- R-4 (design #6): итоги секций спринта не зависят от фильтров, добавляется «показано K»; числа колонок доски — по
видимым. Цена ошибки — пересчитывать итоги на клиенте.
- R-5 (spec): «Скрыть выполненные» не действует на прошлые спринты и на «Kanban» (у kanban последняя колонка — уже
«за 14 дней»). Цена ошибки — включить флагом.
- R-6 (design #8): выбор спринтов — несколько сразу (по умолчанию все активные), в адресе. Формулировка issue
(«выбор отображаемых спринтов: и активные, и будущие») допускает и одиночный выбор; множественный — надмножество.
Цена ошибки — заменить список отметок одиночным выбором.
- R-7 (spec): поиск и исполнитель — на всех трёх страницах, включая «Kanban», хотя в issue названы «Бэклог» и доска
спринта: общий компонент, единообразие. Цена ошибки — скрыть два поля на «Kanban».
- R-8 (design #7): набор видов значков и их цвета (Jira: эпик фиолетовый с молнией, история зелёная с закладкой,
задача синяя с галочкой, ошибка красная с кругом, подзадача). Цена ошибки — перерисовать значки.
- R-9 (design #9): причина бага прокрутки — гипотеза, подлежит проверке воспроизведением; починка — через растяжение
доски на высоту окна, совмещённую с п. 8. Цена ошибки — другая починка того же требования.
- R-10 (proposal): из hub#111 взяты только веб-маркеры M-6 (веб-сторона), T10.3, T9.4, T12.2–T12.4; hub#111 после
merge остаётся открытой с комментарием о закрытых маркерах. Цена ошибки — взять/отложить другие пункты.
- R-11 (spec): узкий экран — панель эпиков превращается в выбор при контейнере уже 900 px. Цена ошибки — подобрать
порог.
- R-12 (plan, Task 7): на страницах доски («Спринт», «Kanban») страница не ограничена `max-width: 1440px` у `.page` —
на 2560 px колонки используют ширину окна (комментарий в `agile.css` уже называл «Спринт» страницей во всю ширину, а
ограничение оставалось). Обоснование: замечание владельца о 2560 px. Цена ошибки — вернуть ограничение одной строкой.
- R-13 (plan, Task 1): значок задачи без типа подписан «Тип не указан» (сейчас — «Задача»), вид — нейтральный.
Цена ошибки — вернуть прежнюю подпись.