import { useEffect, useState } from "react"; import { Activity, Terminal, FolderOpen, Container, Wifi, Monitor, } from "lucide-react"; import { useTranslation } from "react-i18next"; import { registerWidget } from "./WidgetRegistry"; import type { RecentActivityConfig, ActivityType, 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"; import { runVisibleInterval } from "../use-visible-interval"; 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 ActivityIcon({ type }: { type: string }) { const cls = "shrink-0 text-accent-brand"; switch (type) { case "terminal": return ; case "file_manager": return ; case "docker": return ; case "tunnel": return ; case "rdp": case "vnc": case "telnet": return ; default: return ; } } function RecentActivityWidget({ widget, config, }: WidgetComponentProps) { const { t } = useTranslation(); const { maxItems, filterTypes, showTimestamp } = config; const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const fetchData = async () => { try { const data = await getRecentActivity(maxItems * 3); const filtered = filterTypes.length > 0 ? data.filter((i) => filterTypes.includes(i.type as ActivityType)) : data; setItems(filtered.slice(0, maxItems)); } catch { /* ignore */ } finally { setLoading(false); } }; useEffect(() => { fetchData(); return runVisibleInterval(() => { void fetchData(); }, 60_000); }, [maxItems, filterTypes.join(",")]); if (loading) { return ( {t("homepage.loading")} ); } if (items.length === 0) { return ( {t("homepage.noActivity")} ); } return ( } /> {items.map((item) => ( {item.hostName} {item.type.replace("_", " ")} {showTimestamp && ( {relativeTime(item.timestamp)} )} ))} ); } registerWidget({ id: "recent_activity", name: "Recent Activity", description: "Shows recent terminal, Docker, file, and tunnel activity", category: "system", icon: , defaultConfig: { maxItems: 10, filterTypes: [], showTimestamp: true }, defaultSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 9 }, minSize: { w: GRID_SIZE * 4, h: GRID_SIZE * 3 }, component: RecentActivityWidget, }); export { RecentActivityWidget };