docs: план issue-card-modal (#37); уточнения design 5, 10–13, 25
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
590e15e0e0
commit
9484d10d0b
1949
docs/superpowers/plans/2026-10-15-issue-card-modal.md
Normal file
1949
docs/superpowers/plans/2026-10-15-issue-card-modal.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -44,8 +44,8 @@
|
|||||||
|
|
||||||
### Хаб
|
### Хаб
|
||||||
|
|
||||||
5. **Таблица `issue_comment`** `(key, comment_id, author, created, updated, body, PRIMARY KEY (key, comment_id))`, индекс
|
5. **Таблица `issue_comment`** `(key, comment_id, author, created, updated, body, PRIMARY KEY (key, comment_id))`; выборка
|
||||||
по `key`. Схема v3; миграция v2 → v3 создаёт таблицу (копия базы `schema-v2` — существующим механизмом).
|
по `key` идёт по первичному ключу, отдельный индекс не нужен. Схема v3; миграция v2 → v3 создаёт таблицу (копия базы `schema-v2` — существующим механизмом).
|
||||||
6. **Запись.** `apply_state`: для задачи с полем `comments` (список) комментарии этой задачи удаляются и вставляются
|
6. **Запись.** `apply_state`: для задачи с полем `comments` (список) комментарии этой задачи удаляются и вставляются
|
||||||
присланные — в одной транзакции с задачей; задача без поля `comments` своих комментариев не теряет (агент до v10).
|
присланные — в одной транзакции с задачей; задача без поля `comments` своих комментариев не теряет (агент до v10).
|
||||||
7. **Проверка формы** в `h_agent_state` до записи: `comments` — список объектов; `id` — непустая строка; `body` — строка;
|
7. **Проверка формы** в `h_agent_state` до записи: `comments` — список объектов; `id` — непустая строка; `body` — строка;
|
||||||
@ -60,16 +60,27 @@
|
|||||||
### Веб-приложение: окно
|
### Веб-приложение: окно
|
||||||
|
|
||||||
10. **Фоновая страница.** Ссылки на карточку (ключ в списке, «ⓘ» на доске, связи в карточке) передают в
|
10. **Фоновая страница.** Ссылки на карточку (ключ в списке, «ⓘ» на доске, связи в карточке) передают в
|
||||||
`location.state` `{background, depth}`: `background` — адрес страницы под окном (`pathname + search`), `depth` —
|
`location.state` `{background, depth, direct}`: `background` — адрес страницы под окном (`pathname + search`),
|
||||||
сколько карточек открыто поверх неё (1 при открытии со страницы, +1 при переходе по связи). `Layout` отрисовывает
|
`depth` — сколько записей истории занято карточками поверх неё (1 при открытии со страницы, +1 при переходе по
|
||||||
маршрут `background` (если он есть), а при адресе `/issues/:key` — окно поверх него. Страница под окном не
|
связи), `direct` — окно открыто прямым адресом (переносится в переходы по связям). Маршрут верхнего уровня —
|
||||||
пересоздаётся: её состояние (фильтры, загруженные порции, прокрутка, раскладка доски, опрос пакета) сохраняется.
|
`{path: "*", element: <Layout/>}`; `Layout` всегда рисует страницы через `useRoutes(PAGE_ROUTES, pageLocation)` с
|
||||||
11. **Прямой адрес** `/app/issues/{key}` без `state` (новая вкладка, закладка, перезагрузка): под окном — список задач без
|
явным адресом: `background` при открытом окне, иначе текущий адрес. Явный адрес нужен всегда: так дерево
|
||||||
фильтров, `depth = 0`.
|
компонентов страницы не меняется при открытии окна (страница не пересоздаётся), а `useSearchParams`/`useLocation`
|
||||||
12. **Закрытие** (✕, Esc, щелчок по фону): при `depth ≥ 1` — `navigate(-depth)`, браузер возвращается к фоновой
|
внутри фоновой страницы видят её собственный адрес, и фильтры списка не сбрасываются. Состояние страницы (фильтры,
|
||||||
странице, и «назад» после закрытия ведёт на шаг раньше неё; при `depth = 0` — `navigate("/issues", {replace: true})`.
|
загруженные порции, прокрутка, раскладка доски, опрос пакета) сохраняется. `ErrorBoundary` страницы получает ключ по
|
||||||
|
адресу страницы, у окна — свой.
|
||||||
|
11. **Прямой адрес** `/app/issues/{key}` без `state` (новая вкладка, закладка): `Layout` заменяет запись истории тем же
|
||||||
|
адресом со `state = {background: /issues, depth: 0, direct: true}`; под окном — список задач без фильтров.
|
||||||
|
Перезагрузка страницы с открытым окном сохраняет `state` (браузер хранит его в записи истории).
|
||||||
|
12. **Закрытие** (✕, Esc, щелчок по фону): `depth = 0` — `navigate("/issues", {replace: true})`; `depth ≥ 1` —
|
||||||
|
`navigate(-depth)`, браузер возвращается к записи страницы под окном, и «назад» после закрытия ведёт на шаг раньше
|
||||||
|
неё; если окно было открыто прямым адресом (`direct`), запись прямого адреса, на которую вернулись, заменяется на
|
||||||
|
`/issues` (`replace`). Закрытие проходит через блокировщик заметок (п. 14). Вкладки «Доска»/«Задачи» в шапке
|
||||||
|
подсвечиваются по адресу страницы под окном.
|
||||||
13. **Элемент `<dialog>`** с `showModal()`: фокус удерживается в окне, фон недоступен, Esc вызывает `cancel` (обрабатываем
|
13. **Элемент `<dialog>`** с `showModal()`: фокус удерживается в окне, фон недоступен, Esc вызывает `cancel` (обрабатываем
|
||||||
сами — закрытие по п. 12 с проверкой заметок). Щелчок по фону — щелчок по самому `<dialog>` вне области содержимого.
|
сами — закрытие по п. 12 с проверкой заметок; если `cancel` не отменяемый — браузер закрыл окно сам без активации
|
||||||
|
пользователя, — по событию `close` окно открывается снова и закрытие идёт тем же путём). Щелчок по фону — щелчок по
|
||||||
|
самому `<dialog>` вне области содержимого.
|
||||||
Прокрутка страницы под окном на время открытия блокируется (`overflow: hidden` у `body`), содержимое окна
|
Прокрутка страницы под окном на время открытия блокируется (`overflow: hidden` у `body`), содержимое окна
|
||||||
прокручивается внутри, шапка окна закреплена. Ширина до 1000 px, высота до 90vh; на экранах уже 700 px — на всю
|
прокручивается внутри, шапка окна закреплена. Ширина до 1000 px, высота до 90vh; на экранах уже 700 px — на всю
|
||||||
ширину.
|
ширину.
|
||||||
@ -112,10 +123,11 @@
|
|||||||
|
|
||||||
### Проверки
|
### Проверки
|
||||||
|
|
||||||
25. **Тестовый хаб**: фикстура `hub-basic` дополняется у одной задачи описанием длиннее 8 строк, тремя комментариями и
|
25. **Тестовый хаб**: `web/scripts/seed-extras.json` — дополнения к фикстуре доски только для тестового хаба: у AURORA-9001
|
||||||
двумя командами; у второй — входящими и исходящими связями всех групп, включая тип вне `link_types` и связь на
|
описание длиннее 8 строк, три комментария и две команды (пакет автора `seed`, команды завершены). `seed-hub.py`
|
||||||
задачу вне зеркала. Эталоны доски от этого не меняются (комментарии и описание в модель доски не входят) — проверяется
|
применяет их после фикстуры. Связи не добавляются (они меняют доску и её e2e); группа «Прочие» и связь на задачу вне
|
||||||
golden-тестом.
|
зеркала проверяются в vitest, а связь на задачу вне зеркала (`lower-1`) уже есть в фикстуре. Фикстура доски и её
|
||||||
|
golden-эталоны не меняются.
|
||||||
26. **e2e** (Playwright на :8791): открытие из списка (фильтр и прокрутка списка после закрытия на месте), по «ⓘ» с доски
|
26. **e2e** (Playwright на :8791): открытие из списка (фильтр и прокрутка списка после закрытия на месте), по «ⓘ» с доски
|
||||||
(прокрутка и раскладка доски на месте), переход по связи и «назад», Esc / ✕ / фон, «назад» после закрытия не
|
(прокрутка и раскладка доски на месте), переход по связи и «назад», Esc / ✕ / фон, «назад» после закрытия не
|
||||||
открывает карточку, прямой адрес и перезагрузка с открытым окном, подтверждение при несохранённой заметке, ширина
|
открывает карточку, прямой адрес и перезагрузка с открытым окном, подтверждение при несохранённой заметке, ширина
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user