diff --git a/components/widgets/traefik/Widget.tsx b/components/widgets/traefik/Widget.tsx index 4299789..410d57e 100644 --- a/components/widgets/traefik/Widget.tsx +++ b/components/widgets/traefik/Widget.tsx @@ -1,6 +1,5 @@ "use client"; -import { Lock } from "@phosphor-icons/react/ssr"; import type { Widget } from "@/lib/config/schema"; import { useWidgetSubscription } from "@/lib/ws/client"; import { SkeletonLines } from "@/components/widgets/Skeleton"; @@ -12,6 +11,7 @@ export function TraefikWidget({ widget, widgetId }: { widget: TraefikWidget; wid const result = useWidgetSubscription(widgetId); const data = result?.type === "traefik" ? result.data : null; const errorMessage = result?.type === "error" ? result.message : null; + const enabledCount = data?.routers.filter((router) => router.status === "enabled").length ?? 0; return ( @@ -19,34 +19,34 @@ export function TraefikWidget({ widget, widgetId }: { widget: TraefikWidget; wid {widget.name} {data && ( - {data.entrypoints.map((ep) => ep.address).join(" ยท ") || `${data.entrypoints.length} entrypoints`} + {data.entrypoints.length} entrypoints )} {errorMessage && {errorMessage}} {!result && !errorMessage && } {data && ( -
- {data.routers.map((router) => ( -
- - {router.name.replace(/@.*$/, "")} - - - {router.tls && } - - - {router.status} - + <> +
+
+ + {data.routers.length} + Routes
- ))} - + {enabledCount !== data.routers.length && ( +
+ + {enabledCount} + + Enabled +
+ )} +
+ {data.middlewaresCount} middlewares -
+ )} ); diff --git a/lib/collectors/services/coolify.ts b/lib/collectors/services/coolify.ts index ec11e87..9eb23d4 100644 --- a/lib/collectors/services/coolify.ts +++ b/lib/collectors/services/coolify.ts @@ -8,23 +8,33 @@ interface CoolifyProject { name: string; } -export async function collectCoolify( - widget: CoolifyServiceWidget -): Promise<{ stats: ServiceStat[]; detail?: string[] }> { - const base = serviceBaseUrl(widget); - const response = await fetch(`${base}/api/v1/projects`, { - headers: { Authorization: `Bearer ${widget.apiToken}` }, +async function fetchCoolify(base: string, path: string, apiToken: string): Promise { + const response = await fetch(`${base}${path}`, { + headers: { Authorization: `Bearer ${apiToken}` }, signal: AbortSignal.timeout(5_000), }); if (!response.ok) { throw new Error(`Coolify API returned ${response.status}`); } - const projects = (await response.json()) as CoolifyProject[]; + return (await response.json()) as T; +} + +export async function collectCoolify( + widget: CoolifyServiceWidget +): Promise<{ stats: ServiceStat[]; detail?: string[] }> { + const base = serviceBaseUrl(widget); + const [projects, resources] = await Promise.all([ + fetchCoolify(base, "/api/v1/projects", widget.apiToken), + fetchCoolify(base, "/api/v1/resources", widget.apiToken), + ]); const names = projects.slice(0, DETAIL_LIMIT).map((p) => p.name); if (projects.length > DETAIL_LIMIT) names.push(`+${projects.length - DETAIL_LIMIT} more`); return { - stats: [{ label: "Projects", value: String(projects.length) }], + stats: [ + { label: "Projects", value: String(projects.length) }, + { label: "Resources", value: String(resources.length) }, + ], detail: names.length > 0 ? names : undefined, }; }