import { useEffect, useState } from "react"; import { Server } from "lucide-react"; import { useTranslation } from "@termix/plugin-sdk/frontend"; import { registerWidget } from "./WidgetRegistry"; import type { SystemOverviewConfig, WidgetComponentProps } from "../types.js"; import { GRID_SIZE } from "../types.js"; import { WidgetTitle, getDatabaseHealth, getUptime, getVersionInfo, runVisibleInterval, } from "@termix/plugin-sdk/ui"; interface InfoRowProps { label: string; value: string | null | undefined; valueColor?: string; } function InfoRow({ label, value, valueColor }: InfoRowProps) { if (!value) return null; return (
{label} {value}
); } function SystemOverviewWidget({ widget, config, }: WidgetComponentProps) { const { t } = useTranslation(); const { showVersion, showDbHealth, showUptime } = config; const [version, setVersion] = useState(null); const [updateAvailable, setUpdateAvailable] = useState(false); const [dbStatus, setDbStatus] = useState(null); const [uptimeFormatted, setUptimeFormatted] = useState(null); const fetchData = async () => { try { if (showVersion) { // `checkRemote=false` makes /version return early with just // {localVersion, status: "update_check_disabled"}, and the response has // no `updateAvailable` field in either mode -- so the previous read was // false twice over. `status` is what the endpoint actually answers with, // and what the dashboard and profile badges already read. const info = await getVersionInfo(); setVersion((info?.localVersion as string) ?? null); setUpdateAvailable(info?.status === "requires_update"); } if (showDbHealth) { const health = await getDatabaseHealth(); setDbStatus((health?.status as string) ?? "unknown"); } if (showUptime) { const up = await getUptime(); setUptimeFormatted(up.formatted); } } catch { /* ignore */ } }; useEffect(() => { fetchData(); return runVisibleInterval(() => { void fetchData(); }, 300_000); }, [showVersion, showDbHealth, showUptime]); const accent = getComputedStyle(document.documentElement) .getPropertyValue("--accent-brand") .trim() || "#f59145"; return (
} fallback="Termix" />
{showVersion && ( )} {showVersion && updateAvailable && ( )} {showDbHealth && ( )} {showUptime && ( )}
); } registerWidget({ id: "system_overview", name: "System Overview", description: "Termix version, database health, and uptime at a glance", category: "system", icon: , defaultConfig: { showVersion: true, showDbHealth: true, showUptime: true }, defaultSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 6 }, minSize: { w: GRID_SIZE * 4, h: GRID_SIZE * 3 }, component: SystemOverviewWidget, }); export { SystemOverviewWidget };