import type { ComponentType } from "react"; import type { WidgetInstance } from "../types"; import { BackupsWidget } from "./BackupsWidget"; import { GrafanaLinkWidget } from "./GrafanaLinkWidget"; import { JellyfinWidget } from "./JellyfinWidget"; import { PrometheusMetricWidget } from "./PrometheusMetricWidget"; import { SshTaskWidget } from "./SshTaskWidget"; import { StaticWidget } from "./StaticWidget"; export interface WidgetConfigField { key: string; label: string; type: "string" | "select" | "boolean" | "number"; options?: { label: string; value: string }[]; helper?: string; } export interface WidgetDefinition { widgetType: string; addonId: string; name: string; description: string; sourceType: string; refreshInterval: number; defaultConfig: Record; configFields: WidgetConfigField[]; component: ComponentType<{ widget: WidgetInstance }>; } export const WIDGET_REGISTRY: Record = { jellyfin: { widgetType: "jellyfin", addonId: "core", name: "Jellyfin activity", description: "Live sessions and idle users from a Jellyfin server.", sourceType: "jellyfin", refreshInterval: 30_000, defaultConfig: { machine_id: "" }, configFields: [ { key: "machine_id", label: "Machine ID", type: "string", helper: "Jellyfin machine id (empty = default)", }, ], component: JellyfinWidget, }, backups: { widgetType: "backups", addonId: "backups", name: "Backups", description: "Backup job summary and active alerts.", sourceType: "backups", refreshInterval: 60_000, defaultConfig: {}, configFields: [], component: BackupsWidget, }, "grafana-link": { widgetType: "grafana-link", addonId: "grafana", name: "Grafana link", description: "Deep-link to a Grafana dashboard or panel.", sourceType: "grafana", refreshInterval: 0, defaultConfig: { dashboard_uid: "" }, configFields: [ { key: "dashboard_uid", label: "Dashboard UID", type: "string" }, { key: "panel_id", label: "Panel ID", type: "number", helper: "Optional", }, ], component: GrafanaLinkWidget, }, "prometheus-metric": { widgetType: "prometheus-metric", addonId: "prometheus", name: "Prometheus metric", description: "Instant query result rendered as a metric.", sourceType: "prometheus", refreshInterval: 30_000, defaultConfig: { promql: "" }, configFields: [{ key: "promql", label: "PromQL query", type: "string" }], component: PrometheusMetricWidget, }, "ssh-task": { widgetType: "ssh-task", addonId: "ssh-tasks", name: "SSH task output", description: "Output of a saved task run on a machine.", sourceType: "ssh_task", refreshInterval: 0, defaultConfig: { task_id: "" }, configFields: [{ key: "task_id", label: "Saved task ID", type: "string" }], component: SshTaskWidget, }, static: { widgetType: "static", addonId: "core", name: "Static text", description: "Plain text or markdown note.", sourceType: "static", refreshInterval: 0, defaultConfig: { text: "" }, configFields: [{ key: "text", label: "Text", type: "string" }], component: StaticWidget, }, }; export function getWidgetDefinition( widgetType: string, ): WidgetDefinition | undefined { return WIDGET_REGISTRY[widgetType]; } export function listWidgetTypes(): WidgetDefinition[] { return Object.values(WIDGET_REGISTRY); }