diff --git a/docs/widgets/services/dockhand.md b/docs/widgets/services/dockhand.md index 152c9ccef..710c2ec0f 100644 --- a/docs/widgets/services/dockhand.md +++ b/docs/widgets/services/dockhand.md @@ -7,6 +7,8 @@ Learn more about [Dockhand](https://dockhand.pro/). The widget reads `/api/dashboard/stats` from your Dockhand instance. It currently supports Dockhand's **local** authentication only. +Available fields (max 4): `running`, `stopped`, `cpu`, `memory`, `images`, `volumes`, `events_today`, `pending_updates`, `stacks`, `paused`. + ```yaml widget: type: dockhand diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 8d6feaf5d..f75e7adc2 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -1141,6 +1141,12 @@ "running": "Running", "stopped": "Stopped", "cpu": "CPU", - "memory": "Memory" + "memory": "Memory", + "images": "Images", + "volumes": "Volumes", + "events_today": "Events Today", + "pending_updates": "Pending Updates", + "stacks": "Stacks", + "paused": "Paused" } } diff --git a/src/widgets/dockhand/component.jsx b/src/widgets/dockhand/component.jsx index 443343b9b..c9b9b12d6 100644 --- a/src/widgets/dockhand/component.jsx +++ b/src/widgets/dockhand/component.jsx @@ -4,10 +4,18 @@ import { useTranslation } from "next-i18next"; import useWidgetAPI from "utils/proxy/use-widget-api"; +const MAX_FIELDS = 4; + export default function Component({ service }) { const { t } = useTranslation(); const { widget } = service; + if (!widget.fields) { + widget.fields = ["running", "stopped", "cpu", "memory"]; + } else if (widget.fields.length > MAX_FIELDS) { + widget.fields = widget.fields.slice(0, MAX_FIELDS); + } + const { data: stats, error: statsError } = useWidgetAPI(widget, "dashboard/stats"); if (statsError) { @@ -19,45 +27,89 @@ export default function Component({ service }) { + + + + + + ); } let running; let stopped; + let paused; + let pendingUpdates; let cpuPercent; let memoryPercent; + let imagesTotal; + let volumesTotal; + let stacksRunning; + let stacksTotal; + let eventsToday; if (widget?.environment) { const environment = stats.find( - (env) => env?.name === widget.environment || env?.id?.toString() === widget.environment.toString(), + (env) => + env?.name?.toString().toLowerCase() === widget?.environment.toString().toLowerCase() || + env?.id?.toString() === widget?.environment.toString(), ); if (environment) { running = environment?.containers?.running; stopped = environment?.containers?.stopped ?? (environment?.containers?.total ?? 0) - (running ?? 0); + paused = environment?.containers?.paused; + pendingUpdates = environment?.containers?.pendingUpdates; cpuPercent = environment?.metrics?.cpuPercent; memoryPercent = environment?.metrics?.memoryPercent; + imagesTotal = environment?.images?.total; + volumesTotal = environment?.volumes?.total; + stacksRunning = environment?.stacks?.running; + stacksTotal = environment?.stacks?.total; + eventsToday = environment?.events?.today; } - } else { + } + + if (running === undefined) { // Aggregate across all environments running = stats.reduce((sum, env) => sum + (env?.containers?.running ?? 0), 0); const total = stats.reduce((sum, env) => sum + (env?.containers?.total ?? 0), 0); stopped = total - running; + paused = stats.reduce((sum, env) => sum + (env?.containers?.paused ?? 0), 0); + pendingUpdates = stats.reduce((sum, env) => sum + (env?.containers?.pendingUpdates ?? 0), 0); const totalCpu = stats.reduce((sum, env) => sum + (env?.metrics?.cpuPercent ?? 0), 0); const totalMemory = stats.reduce((sum, env) => sum + (env?.metrics?.memoryPercent ?? 0), 0); const envCount = stats.length; cpuPercent = envCount > 0 ? totalCpu / envCount : 0; memoryPercent = envCount > 0 ? totalMemory / envCount : 0; + imagesTotal = stats.reduce((sum, env) => sum + (env?.images?.total ?? 0), 0); + volumesTotal = stats.reduce((sum, env) => sum + (env?.volumes?.total ?? 0), 0); + stacksRunning = stats.reduce((sum, env) => sum + (env?.stacks?.running ?? 0), 0); + stacksTotal = stats.reduce((sum, env) => sum + (env?.stacks?.total ?? 0), 0); + eventsToday = stats.reduce((sum, env) => sum + (env?.events?.today ?? 0), 0); } return ( + + + + + + ); }