feat(page-history): редизайн окна истории — плотный список + мини-календарь heatmap (#568) #578

Merged
vvzvlad merged 3 commits from feat/568-page-history-redesign into develop 2026-07-13 04:32:43 +03:00

3 Commits

Author SHA1 Message Date
agent_coder 8124d5c2ba fix(page-history): gate nav-panel empty state on !isLoading to kill load-flash (#568)
HistoryNavPanel only received isError, not isLoading, so during the initial
history query (data undefined -> empty groups, isError false) it flashed the
false 'No page history saved yet.' text until rows arrived. Thread isLoading
in and gate the empty branch on !isLoading, mirroring the right pane. Add a
loading-state test asserting the empty text is not shown while isLoading.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 04:26:22 +03:00
agent_coder 7743278a92 fix(page-history): устранить замечания ревью #578 (empty/error, i18n ru, a11y, тесты)
F1 (регрессия) — вместо пустой панели показываем явные состояния: ошибка загрузки
истории и «нет истории». Список и правая панель несут свои error/empty-состояния;
heatmap по-прежнему fail-open (пустая сетка) независимо.

F2 (i18n) — добавлены 8 недостающих ключей в ru-RU (Selected version, via, of,
Previous/Next change, Previous/Next month, No revisions found for that day) плюс
новый aria-ключ. ru-RU правится текстовым append'ом — существующие (в т.ч.
дублирующиеся) ключи не тронуты.

F3 (a11y) — новые интерактивы доступны с клавиатуры: строки ревизий и ячейки
календаря — role=button + tabIndex + активация Enter/Space. Heatmap больше не
только-цвет: каждая ячейка несёт aria-label/title «дата: N versions»
(не-цветовой сигнал числа ревизий).

F4 — тесты history-nav-panel.tsx: рендер плотных строк, переключатель «Only
versions» реально фильтрует автосейвы (mutation-check), pick-day скроллит к дню,
error/empty-состояния.

F5 — тесты mini-calendar: границы тиров heat, клавиатурная активация, aria-cue.

F6 (hover-prefetch) — отложено (опционально, не тривиально в новой раскладке).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 04:26:22 +03:00
agent_coder fd5d97e51d feat(page-history): редизайн десктопного окна истории — плотный список + мини-календарь heatmap (#568)
Натягиваю прототип NewDesign/PageHistoryModal на существующую подсистему истории,
переиспользуя всю механику (запросы, дифф, restore, права, пагинация) и добавляя
единственный дешёвый агрегат бэка — «число version-ревизий по дням» под heatmap.

Клиент:
- Новый десктоп-body history-modal-desktop.tsx: одно-строчная шапка (заголовок,
  лейбл выбранной версии, Highlight changes + N/M дифф-навигация, Restore, закрытие)
  над телом «левая навигация 280px | правый рендер версии».
- history-nav-panel.tsx: фильтр «Only versions» + мини-календарь + ПЛОТНЫЙ список
  (одна ревизия = одна строка), группировка по дням (data-day якоря), jump-to-day с
  корректной догрузкой страниц по границе dayISO старейшей строки (не «N страниц»),
  недостижимый день → тост, без зацикливания.
- revision-row.tsx + чистый адаптер utils/revision-row.ts: глиф по идентичности
  (agent → квадратный глиф роли + «via <launcher>», иначе круглый аватар), бейдж
  SAVED только для kind==='manual'; автосейвы приглушены. Два ортогональных сигнала
  сохранены (identity vs intentionality).
- mini-calendar.tsx: heatmap-интенсивность = version-ревизии за день, навигация
  месяцев клиентская, pick-day по dayISO; fail-open на пустую сетку.
- usePageHistoryDayCounts + day-counts-service; historyKindMeta вынесен в чистый
  utils/history-kind-meta.ts (тот же предикат для фильтра и бейджа).
- resolvePrevSnapshotId по-прежнему считается на ПОЛНОМ плоском списке; restore и
  дифф-навигация переиспользуют useHistoryRestore/useDiffNavigation без изменений.
- Мобильная модалка (history-modal-mobile.tsx) не тронута; орфанный
  history-modal-body.tsx удалён.

Сервер:
- POST /pages/history/day-counts {pageId, tz} → [{dayISO, count}] за всю историю,
  view-gated (validateCanView), неверный tz → 400 (как /history/time).
- computeDayCounts + чистый countRevisionsByDay (считает только version-строки),
  переиспользует tz-ядро zonedDayStart/isoDay из work-time/bucket-by-day.ts.

Тесты: клиент vitest (адаптер kind→бейдж/глиф, dense-row рендер, heatmap/календарь);
сервер jest (баркетер + эндпоинт: view-gate, tz→400, группировка по дням).

Удалён прототип NewDesign/PageHistoryModal.tsx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 04:26:22 +03:00