Мутирующие действия больше не уводят со страницы: undo/relink/retry/cancel
в списке свопят карточку (#card-{id}), на /download/{id} — #download-main;
петля ревью (refine/rerecognize) свопит #review-main и допалливает
recognizing до готового плана (fragment /fragments/downloads/{id}/review,
every 2s). Выходы ревью (apply/defer/cancel) остаются навигацией. Без htmx —
прежний PRG-редирект (деградация). Ошибка действия на htmx-пути — HTTP 200
с сообщением в фрагменте (ActionError), иначе htmx не свопит DOM.
Разметка вынесена в партиалы card/download_main/review_main (корень = элемент
с целевым id), различение поверхности — скрытым полем surface=list|download.
Извлечены buildCardView/buildDownloadView. handleSetProvider переведён на
reviewBlockAction (консистентность source-действий).
Реализация change htmx-action-swap (OpenSpec).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
5.3 KiB
Markdown
58 lines
5.3 KiB
Markdown
## ADDED Requirements
|
||
|
||
### Requirement: Петлевые действия ревью обновляют экран на месте
|
||
|
||
Петлевые действия распознавания на экране ревью — **Распознать заново** (`rerecognize`) и **Уточнить** (`refine`) — SHALL выполняться htmx-запросом и обновлять тело экрана ревью на месте (partial swap), без полной перезагрузки страницы и без сброса позиции прокрутки. Поскольку эти действия асинхронны (переводят загрузку в `recognizing`, распознавание доделывает воркер), своп SHALL отражать актуальное состояние — состояние `recognizing` с индикацией «идёт распознавание», а не мгновенно готовый план. Накопленные подсказки и ручные override MUST переживать перераспознавание. Это согласуется с уже действующим частичным свопом при смене выбранного источника (см. «Единый список источников совпадения на ревью»).
|
||
|
||
Пока загрузка в `recognizing`, экран ревью SHALL сам обновляться поллингом
|
||
htmx-фрагмента (`GET /fragments/downloads/{id}/review`) и по завершении
|
||
распознавания SHALL автоматически смениться на готовый план (список источников,
|
||
инфо и предпросмотр активного источника), без ручного обновления страницы. Как
|
||
только состояние вышло из `recognizing`, фрагмент SHALL возвращаться без
|
||
поллера, и опрос прекращается. Без htmx экран SHALL деградировать до ручной
|
||
ссылки «Обновить».
|
||
|
||
Выходы из ревью, после которых загрузка покидает `review` — **Применить**
|
||
(`apply` → раскладка/`done`), **Позже** (`defer` → `deferred`) и **Отклонить**
|
||
(`cancel` → `cancelled`), — НЕ обязаны свопить экран на месте и MAY уводить с
|
||
экрана ревью навигацией (редирект/`HX-Redirect`), поскольку загрузка перестаёт
|
||
быть предметом этого экрана.
|
||
|
||
Поведение петлевых действий MUST деградировать без htmx: без заголовка
|
||
`HX-Request` обработчик SHALL исполнять то же доменное действие и отвечать
|
||
редиректом на `/review/{id}`, как раньше.
|
||
|
||
#### Scenario: Перераспознавание свопит экран в состояние recognizing
|
||
|
||
- **GIVEN** загрузка в `review`, экран ревью открыт
|
||
- **WHEN** пользователь нажимает «Распознать заново» или «Уточнить» с подсказкой
|
||
(htmx активен)
|
||
- **THEN** тело экрана ревью обновляется на месте в состояние `recognizing` с
|
||
индикацией «идёт распознавание», без полной перезагрузки и без прыжка
|
||
прокрутки наверх
|
||
- **AND** накопленные подсказки и ручные override сохраняются
|
||
|
||
#### Scenario: Экран сам обновляется до готового плана
|
||
|
||
- **GIVEN** экран ревью показывает состояние `recognizing` после петлевого
|
||
действия
|
||
- **WHEN** воркер завершает распознавание и загрузка снова в `review`
|
||
- **THEN** экран автоматически (поллингом фрагмента) сменяется на готовый план
|
||
(источники, инфо, предпросмотр), без ручного обновления
|
||
- **AND** после выхода из `recognizing` фрагмент возвращается без поллера и опрос
|
||
прекращается
|
||
|
||
#### Scenario: Выход из ревью уводит с экрана
|
||
|
||
- **GIVEN** загрузка в `review` с готовым превью
|
||
- **WHEN** пользователь нажимает «Применить», «Позже» или «Отклонить»
|
||
- **THEN** загрузка покидает `review` (соответственно `done`/`deferred`/
|
||
`cancelled`), а интерфейс уводит пользователя с экрана ревью навигацией
|
||
|
||
#### Scenario: Деградация петлевого действия без htmx
|
||
|
||
- **WHEN** «Распознать заново» или «Уточнить» приходит POST-запросом без
|
||
заголовка `HX-Request`
|
||
- **THEN** обработчик исполняет то же доменное действие и отвечает редиректом на
|
||
`/review/{id}`, поведение без JavaScript не ломается
|