Ревью: oob-обновление панели действий при свопе источника

Кнопка «Применить» (завязана на HasLinks) лежит вне #source-block и не
обновлялась при htmx-свопе выбора источника — в краевом случае (пустой
предпросмотр из-за коллизии) рассинхронивалась с превью до полной
перезагрузки. Выделил панель в партиал review_action_bar с id=action-bar;
reviewBlockAction теперь рендерит review_source_swap — свежий #source-block
плюс oob-копию панели (hx-swap-oob), так кнопка синхронно отражает HasLinks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-07-11 09:28:45 +03:00
co-authored by Claude Opus 4.8
parent e8ce828296
commit 847d471852
4 changed files with 96 additions and 10 deletions
+10 -4
View File
@@ -59,6 +59,7 @@ type reviewView struct {
NoBase bool // выбрано «без базы»
Sources []sourceView // единый список источников совпадения
BlockError string // ошибка выбора внутри блока (htmx); не путать с Error (?err=)
ActionBarOOB bool // рендерить панель действий как oob-фрагмент (своп источника)
}
// sourceView — строка единого списка источников на экране ревью: нейронка или
@@ -455,9 +456,10 @@ func isHTMX(r *http.Request) bool {
// reviewBlockAction — помощник для действий выбора источника: выполнить
// операцию и вернуть свежий блок источника. На htmx-запрос перечитывает
// состояние и рендерит партиал `review_source_block` (ошибку кладёт в
// BlockError, активный источник не меняется); без htmx деградирует до
// PRG-редиректа, как reviewAction.
// состояние и рендерит `review_source_swap` — партиал `review_source_block`
// плюс oob-обновление панели действий `review_action_bar` (кнопка «Применить»
// зависит от HasLinks, а лежит вне блока), ошибку кладёт в BlockError, активный
// источник не меняется; без htmx деградирует до PRG-редиректа, как reviewAction.
func (s *server) reviewBlockAction(w http.ResponseWriter, r *http.Request, fn func(context.Context, string) error) {
id, err := pathID(r)
if err != nil {
@@ -487,7 +489,11 @@ func (s *server) reviewBlockAction(w http.ResponseWriter, r *http.Request, fn fu
if actionErr != nil {
view.BlockError = userErr(r, actionErr, id)
}
s.render(w, "review_source_block", view)
// Панель действий («Применить» завязана на HasLinks) лежит вне #source-block,
// поэтому обновляем её тем же ответом через hx-swap-oob — иначе кнопка
// рассинхронилась бы с превью до полной перезагрузки.
view.ActionBarOOB = true
s.render(w, "review_source_swap", view)
}
// matchURL выбирает ссылку на подтверждённую запись метабазы. Приоритет — URL