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
+24
View File
@@ -0,0 +1,24 @@
import { SectionCard } from "../components/SectionCard";
import { useWidgetData } from "../hooks/useWidgets";
import type { WidgetInstance } from "../types";
import { getWidgetDefinition } from "./registry";
interface Props {
widget: WidgetInstance;
}
export function StaticWidget({ widget }: Props) {
const def = getWidgetDefinition(widget.widget_type);
const { data } = useWidgetData(widget.id, def?.refreshInterval ?? 0);
const text = data?.data?.text as string | undefined;
return (
<SectionCard title={widget.title} description={def?.description}>
{text ? (
<p className="whitespace-pre-wrap text-sm">{text}</p>
) : (
<p className="text-sm text-muted-foreground">No content configured.</p>
)}
</SectionCard>
);
}