виджет на сайте

Виджет на сайте — хаб и три редактора-группы

Консоль рисует один экран из семи стопкой сложенных панелей и 16 полей. На телефоне это ровно та «слишком длинная простыня», которую отвергло решение о разбиении: единый пункт «Ещё → Виджет на сайте» открывает хаб, а хаб — три коротких редактора-группы, каждый отвечает на один вопрос, который тенант держит в голове.

3редактора-группы за одним пунктом: Внешний вид · Поведение и приветствие · Согласие и запись
16полей DTO, и каждое сохранение шлёт их все — иначе сервер молча сбросит отсутствующие булевы
1общая ViewModel держит закоммиченный полный конфиг; редактор мержит только свой срез
11

Хаб: один пункт открывает три группы

Не семь экранов (четыре консольные панели — это по одному переключателю; вкладка на чекбокс читается как поломка), не один экран (та самая простыня), не вкладки (бриф говорит «каждый экран, который сохраняет» — значит независимые сохранения). Три — это число по-настоящему разных вопросов: как выглядит, что делает, что можно и что обязательно.

хаб
9:41
Виджет на сайте
Для скорости отдачи виджет кэширует настройки в браузере посетителя на сутки. Изменения из конфигуратора доходят до вернувшегося посетителя в течение суток (до нового — сразу); тот, у кого виджет уже открыт на странице, увидит их после перезагрузки. Чтобы проверить изменения немедленно, очистите данные сайта: в Chrome — вкладка «Приложение» (Application) → «Хранилище» (Storage) → отметить все флажки → «Очистить данные сайта» (Clear site data).
Настройки виджета
Внешний вид
Цвет #2F6FED · справа внизу · Русский · «Чем помочь?»
Поведение и приветствие
Автооткрытие через 30 с · привлекать внимание вкл
Согласие и запись
Согласие обязательно · приём файлов выкл
/channels/widget-config — открывается из «Ещё → Каналы», между «Установка виджета» и «MAX»

Подписи строк — это сводка текущего конфига, чтобы тенант видел состояние группы, не заходя в неё. Заметка adr/0029 («следующая загрузка страницы») и загрузка/ошибка/повтор живут один раз здесь, на хабе, а не повторяются в каждом редакторе.

Вложенность хаб → редактор — собственная навигация фичи, а не второй уровень списка «Ещё» (у треда из «Диалогов» точно так же есть своя внутренняя навигация). Гейт — site:configure, одно и то же разрешение на строку, GET и PUT: rail-vs-server разрыва здесь нет.

состояние: не загрузилось
9:41
Виджет на сайте

Не удалось загрузить настройки

Проверьте соединение и попробуйте ещё раз. Настройки доступны только с правом site:configure, поэтому «попробовать снова» здесь честно.

Повторить
WidgetConfigHubScreen · Failed(reason) → RefusalBody(onRetry=refresh)

Единственное место для «не загрузилось / повторить» — хаб. Три редактора не дублируют это состояние: они получают уже загруженный committed-конфиг из общей ViewModel.

Принцип (teaching mode): разбиение консоли на 7 панелей — это information architecture для десктопа; разбиение приложения на 3 экрана — другая IA для другого вьюпорта, по правилу «один связный вопрос на экран», а не по порядку полей на бэкенде. Альтернатива — один экран с TabRow из трёх вкладок и одним «Сохранить» — отклонена: бриф говорит «каждый экран, который сохраняет, шлёт полный объект», а это про несколько независимо сохраняющих экранов, вкладки же схлопнули бы их обратно в единую форму.

Ловушка полного DTO — центральная корректность

Три экрана сохраняют независимо, и каждый PUT обязан нести все 16 полей, иначе сервер сбросит отсутствующие (requireContactConsent помечен [JsonRequired] именно поэтому; любой другой bool при отсутствии биндится в false). Наивное «каждый экран PUT-ит только свои поля» молча выключило бы согласие/приём файлов/привлечение внимания при сохранении любого другого экрана.

Защита структурная: одна общая WidgetConfigViewModel держит committed — полный конфиг (загружен один раз GET-ом, пересеивается из эха каждого PUT). Сохранение редактора строит committed.copy(<свой срез из черновика>) и PUT-ит целиком. Ни один булев никогда не отсутствует в PUT, и несохранённый черновик соседнего экрана не утекает в чужое сохранение.