Files
jellybit/openspec/changes/htmx-action-swap/specs/review/spec.md
T
avandClaude Opus 4.8 2f8e6e3576 Веб-UI: htmx-своп действий на месте вместо PRG-редиректа
Мутирующие действия больше не уводят со страницы: 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>
2026-07-04 14:37:51 +03:00

5.3 KiB
Raw Blame History

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), Позже (deferdeferred) и Отклонить (cancelcancelled), — НЕ обязаны свопить экран на месте и 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 не ломается