import { useEffect, useState } from "react"; import { Container } from "lucide-react"; import { useTranslation } from "react-i18next"; import { registerWidget } from "./WidgetRegistry"; import type { DockerActivityConfig, WidgetComponentProps, } from "@/types/homepage-types"; import { GRID_SIZE } from "@/types/homepage-types"; import { getRecentActivity } from "@/api/dashboard-api"; import type { RecentActivityItem } from "@/api/dashboard-api"; import { WidgetTitle } from "./WidgetTitle"; function relativeTime(ts: string): string { const diff = Date.now() - new Date(ts).getTime(); const m = Math.floor(diff / 60_000); if (m < 1) return "just now"; if (m < 60) return `${m}m ago`; const h = Math.floor(m / 60); if (h < 24) return `${h}h ago`; return `${Math.floor(h / 24)}d ago`; } function DockerActivityWidget({ widget, config, }: WidgetComponentProps) { const { t } = useTranslation(); const { maxItems, showHostName } = config; const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const fetchData = async () => { try { const data = await getRecentActivity(maxItems * 5); setItems(data.filter((i) => i.type === "docker").slice(0, maxItems)); } catch { /* ignore */ } finally { setLoading(false); } }; useEffect(() => { fetchData(); const iv = setInterval(fetchData, 30_000); return () => clearInterval(iv); }, [maxItems]); if (loading) { return (
{t("homepage.loading")}
); } if (items.length === 0) { return (
{t("homepage.noDockerActivity")}
); } return (
} />
{items.map((item) => (
{showHostName && ( {item.hostName} )} {relativeTime(item.timestamp)}
))}
); } registerWidget({ id: "docker_activity", name: "Docker Activity", description: "Recent Docker connection activity across your hosts", category: "system", icon: , defaultConfig: { maxItems: 10, showHostName: true }, defaultSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 8 }, minSize: { w: GRID_SIZE * 4, h: GRID_SIZE * 4 }, component: DockerActivityWidget, }); export { DockerActivityWidget };