feat(widgets): add frontend widget runtime (types, API, hooks, registry, components)

PR 3 of 4 for configurable dashboard widgets.

- Add TypeScript widget interfaces (WidgetInstance, WidgetInstanceInput,
  WidgetTypeInfo, WidgetDataResponse).
- Create widget API client for CRUD, registry metadata, and per-widget data.
- Create TanStack Query hooks for instances, data, sources, types, and mutations.
- Create closed frontend widget registry with metadata, source type, refresh
  intervals, and config fields.
- Add six shadcn/ui-based widget components: Jellyfin, Backups, Grafana link,
  Prometheus metric, SSH task output, and static text.
- Add Vitest unit tests for registry metadata.

Verification:
- backend ruff clean; pytest 200 passed
- frontend npm run lint: 0 errors
- frontend npm run build: success
- frontend npm run test -- src/widgets/registry.test.ts: 3 passed
This commit is contained in:
Developer
2026-06-21 16:24:44 +00:00
parent e6d333ef7b
commit e1356b20f1
13 changed files with 700 additions and 1 deletions
@@ -93,9 +93,56 @@ Focused widget test output: `27 passed`.
- Adapters currently call `get_settings_store()` internally for `backups`/`ssh_task` sources. The router-level endpoint uses FastAPI DI, but adapter unit tests patch `get_settings_store` to inject a test store. A future refactor can pass `store` and `settings` explicitly into `adapter.fetch()` for cleaner testability.
## Completed tasks (Slice 3)
All Slice 3 tasks are marked `- [x]` in `tasks.md`:
- [x] 3.1 Add TypeScript widget interfaces (`WidgetInstance`, `WidgetInstanceInput`, `WidgetTypeInfo`, `WidgetDataResponse`)
- [x] 3.2 Create widget API client (`frontend/src/api/widgets.ts`)
- [x] 3.3 Create widget TanStack Query hooks (`frontend/src/hooks/useWidgets.ts`)
- [x] 3.4 Create frontend widget registry (`frontend/src/widgets/registry.ts`)
- [x] 3.5 Implement six widget presentational components (`frontend/src/widgets/*.tsx`)
- [x] 3.6 Add frontend registry unit test (`frontend/src/widgets/registry.test.ts`)
## Files changed (Slice 3)
### New files
- `frontend/src/api/widgets.ts` — API functions for widget CRUD, registry metadata, and per-widget data.
- `frontend/src/hooks/useWidgets.ts` — TanStack Query hooks for instances, data, sources, types, and mutations.
- `frontend/src/widgets/registry.ts` — Closed frontend registry with metadata, refresh intervals, and config fields.
- `frontend/src/widgets/JellyfinWidget.tsx` — Renders Jellyfin session activity.
- `frontend/src/widgets/BackupsWidget.tsx` — Renders backup dashboard summary.
- `frontend/src/widgets/GrafanaLinkWidget.tsx` — Renders a deep-link to Grafana (no iframe).
- `frontend/src/widgets/PrometheusMetricWidget.tsx` — Renders PromQL instant query result.
- `frontend/src/widgets/SshTaskWidget.tsx` — Renders saved SSH task output.
- `frontend/src/widgets/StaticWidget.tsx` — Renders static text.
- `frontend/src/widgets/index.ts` — Barrel exports.
- `frontend/src/widgets/registry.test.ts` — Vitest unit tests for registry metadata.
### Modified files
- `frontend/src/types/index.ts` — Added widget TypeScript interfaces.
## Verification (Slice 3)
```bash
cd backend
.venv/bin/python -m ruff check . # All checks passed
PYTHONPATH=src .venv/bin/python -m pytest # 200 passed, 2 warnings
cd ../frontend
npm run lint # 2 pre-existing warnings, 0 errors
npm run build # Built successfully
npm run test -- src/widgets/registry.test.ts # 3 passed
```
## Deviations from design (Slice 3)
- Registry unit test is colocated at `frontend/src/widgets/registry.test.ts` and runs with Vitest, matching the project's existing `npm run test` setup, instead of `frontend/tests/widgets.test.mjs`.
- `JellyfinWidget` uses `SessionActivityPanel` directly because `NowPlaying` does not expose an `emptyMessage` prop.
## Remaining work
- Slice 3: Frontend types/API/hooks/registry/components
- Slice 4: Dashboard loop + configuration UI + addon pages
## PR boundary