Веб-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>
This commit is contained in:
@@ -12,74 +12,6 @@
|
||||
|
||||
{{template "header" ""}}
|
||||
|
||||
<main class="main">
|
||||
<a class="back-link" href="/">← ко всем загрузкам</a>
|
||||
|
||||
{{if .Error}}<div class="result-banner" style="background:var(--st-err-bg);border-color:color-mix(in srgb,var(--st-err) 35%,transparent)"><h2 style="color:var(--st-err)">{{.Error}}</h2></div>{{end}}
|
||||
{{if .StateError}}<div class="result-banner" style="background:var(--st-err-bg);border-color:color-mix(in srgb,var(--st-err) 35%,transparent)"><h2 style="color:var(--st-err)">{{.StateError}}</h2></div>{{end}}
|
||||
|
||||
<!-- Шапка ревью -->
|
||||
<div class="review-head">
|
||||
<div>
|
||||
<div class="review-title">{{.Source}}</div>
|
||||
<div class="reason-line">
|
||||
{{template "status_badge" .State}}
|
||||
{{if .Reasons}}<span>Причины: {{range $i, $r := .Reasons}}{{if $i}} · {{end}}<b>{{$r}}</b>{{end}}</span>{{end}}
|
||||
{{if .Confidence}}<span class="conf">уверенность {{.Confidence}}</span>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if eq .State "recognizing"}}
|
||||
<div class="section">
|
||||
<p style="margin:0">⏳ Идёт распознавание — обновите страницу через несколько секунд.</p>
|
||||
<p style="margin:var(--sp-2) 0 0"><a href="/review/{{.ID}}">Обновить</a></p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<!-- Контекст -->
|
||||
{{if .Context}}
|
||||
<div class="section">
|
||||
<div class="section-head"><h2>Контекст</h2><span class="hint">исходное сообщение при добавлении</span></div>
|
||||
<p style="margin:0;color:var(--text-dim)">«{{.Context}}»</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .HasPlan}}
|
||||
<!-- Единый блок: выбор источника → инфо → предпросмотр раскладки -->
|
||||
{{template "review_source_block" .}}
|
||||
{{end}}
|
||||
|
||||
<!-- Уточнить и перераспознать -->
|
||||
<div class="section">
|
||||
<div class="section-head"><h2>Уточнить и перераспознать</h2></div>
|
||||
{{if .Hints}}
|
||||
<div class="hint-list">
|
||||
{{range $i, $h := .Hints}}
|
||||
<div class="hint-item"><span class="idx">#{{add $i 1}}</span><span class="txt">{{$h}}</span></div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<form method="post" action="/ui/downloads/{{.ID}}/refine">
|
||||
<textarea class="textarea" name="hint" placeholder="Например: «это Fargo, год сериала 2014, не 2015» или «sample.mkv не считать эпизодом»"></textarea>
|
||||
<div class="refine-row">
|
||||
<button class="btn btn-primary btn-sm" type="submit">🔁 Уточнить</button>
|
||||
</div>
|
||||
</form>
|
||||
<form method="post" action="/ui/downloads/{{.ID}}/rerecognize" style="margin-top:var(--sp-2)">
|
||||
<button class="btn btn-sm" type="submit">🔄 Распознать заново</button>
|
||||
<span class="hint">без новой подсказки — по уже накопленному контексту</span>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Панель действий -->
|
||||
<div class="action-bar">
|
||||
<span class="grow">{{if .HasLinks}}Превью готово — можно применять.{{else}}Подтверди источник, чтобы получить превью раскладки.{{end}}</span>
|
||||
<form method="post" action="/ui/downloads/{{.ID}}/defer"><button class="btn btn-lg" type="submit">🕗 Позже</button></form>
|
||||
<form method="post" action="/ui/downloads/{{.ID}}/cancel"><button class="btn btn-lg btn-danger" type="submit">❌ Отклонить</button></form>
|
||||
{{if .HasLinks}}<form method="post" action="/ui/downloads/{{.ID}}/apply"><button class="btn btn-lg btn-primary" type="submit">✅ Применить</button></form>{{end}}
|
||||
</div>
|
||||
|
||||
</main>
|
||||
{{template "review_main" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user