Files
ss-tools/specs/034-task-status-center/contracts/ux/screen-models.md
busya 33ee976c48 feat(reports): Task Status Center — unified /reports dashboard
Страница /reports трансформирована в Центр статусов задач:

Backend:
- GET /api/reports/summary — агрегированные счётчики тип×статус (5 корзин)
- GET/PUT /api/settings/reports — глобальные настройки отчётов
- _filter_tasks_by_rbac() — row-level фильтрация по роли
- normalize_task_report: LLM-валидация с ошибками → FAILED/PARTIAL
- get_summary(): 5 корзин pending/running/awaiting_input/success/failed

Frontend:
- TaskCenterModel.svelte.ts (400 строк) — Screen Model
- SummaryPanel — сводная панель с цветовым кодированием и active filter
- ReportCard — humanized labels, duration, task_id, failed border
- FilterBar — search + sort + time range с label'ами
- Pagination — showingText, уникальные id для select
- Quick views: «Упавшие», «В работе», «Успешные»
- TaskDrawer: scroll-to-error, footer скрыт для terminal, «Н/Д» fix

Тесты: 48 backend + 38 frontend (2521 всего)
Build:   Console errors: 0
2026-07-02 18:53:58 +03:00

3.7 KiB
Raw Blame History

#region UxScreenModels [C:3] [TYPE ADR] [SEMANTICS ux,screen-models,task-status-center] @defgroup Ux Screen Model inventory for Task Status Center.

Model: TaskCenterModel

  • File: frontend/src/lib/models/TaskCenterModel.svelte.ts
  • Type: [TYPE Model] C4
  • Bound to: /reports page (TaskCenterReportsPage)
  • Complexity: C4 — stateful, WebSocket lifecycle, side effects

Atoms ($state)

Atom Type Default Purpose
tasks TaskReport[] [] Full task list from backend
summary TaskSummary | null null Aggregated counts by type×status
filters TaskCenterFilter defaults Current filter state
screenState ScreenState 'loading' FSM state: loading/ready/empty/disconnected/reconnecting/error
wsConnected boolean false WebSocket connection status
selectedTaskId string | null null Currently selected task for drawer
page number 1 Current page
pageSize number 20 Items per page
disabledTypes TaskType[] [] Admin-disabled types (from backend)
visibleTypes TaskType[] all Operator preference (from localStorage)
lastUpdated Date | null null Timestamp of last data update (for stale indicator)

Derived ($derived)

Derived Type Computation
filteredTasks TaskReport[] tasks → filter by types/statuses/search/time_range → sort (active first, then sort_by)
visibleSummary TaskSummary | null summary filtered by disabledTypes AND visibleTypes
isEmpty boolean tasks.length === 0 && screenState === 'ready'
isFilteredEmpty boolean filteredTasks.length === 0 && filters active
hasActiveFilters boolean any filter non-default

Actions

Action Signature Side Effects
loadInitialData (initialFilters?: Partial<TaskCenterFilter>) => Promise<void> REST: summary + list + settings; WS: connect
applyFilter (partial: Partial<TaskCenterFilter>) => void URL: replaceState (debounced 300ms)
clearFilters () => void URL: replaceState
selectTask (taskId: string) => void Store: openDrawerForTask
refreshSummary () => Promise<void> REST: summary + list
connectWebSocket () => void WS: connect /ws/task-events
disconnectWebSocket () => void WS: close
destroy () => void WS: disconnect, timers: clear
toggleTypeVisibility (type: TaskType) => void localStorage: update visibleTypes

Invariants

  1. Active tasks (PENDING, RUNNING, AWAITING_INPUT) always sorted before completed in filteredTasks
  2. visibleSummary excludes types in disabledTypes (admin priority) and not in visibleTypes (operator preference)
  3. WebSocket lifecycle: connect on loadInitialData, disconnect on destroy
  4. DECOMPOSITION GATE: 400 lines, 40 methods (ADR-0010)

Private

  • _ws: WebSocket | null
  • _eventBuffer: TaskStatusEvent[]
  • _flushTimeout: ReturnType<typeof setTimeout> | null
  • _reconnectAttempt: number
  • _reconnectTimer: ReturnType<typeof setTimeout> | null
  • _urlSyncTimeout: ReturnType<typeof setTimeout> | null

FSM

loading ──(data loaded)──► ready
loading ──(data empty)───► empty
loading ──(fetch fail)────► error
ready ──(ws close)────────► reconnecting ──(2s)──► disconnected
reconnecting ──(ws open)──► ready
disconnected ──(ws open)──► ready
ready ──(filter applied, no results)──► filtered_empty (list only, summary stays)

#endregion UxScreenModels