diff --git a/packages/widgets/src/beszel-system-stats/component.tsx b/packages/widgets/src/beszel-system-stats/component.tsx
index 67adf9302..7e457182e 100644
--- a/packages/widgets/src/beszel-system-stats/component.tsx
+++ b/packages/widgets/src/beszel-system-stats/component.tsx
@@ -44,7 +44,7 @@ export default function BeszelSystemStatsWidget({
setOptions,
}: WidgetComponentProps<"beszelSystemStats">) {
const t = useScopedI18n("widget.beszelSystemStats");
- const { data: systemsResult = [] } = clientApi.widget.beszel.getSystems.useQuery(
+ const { data: systemsResult = [], isPending: systemsPending } = clientApi.widget.beszel.getSystems.useQuery(
{ integrationIds },
{ staleTime: 30 * 1000 },
);
@@ -56,7 +56,8 @@ export default function BeszelSystemStatsWidget({
const selectedSystem = options.systemId || systems[0]?.value || "";
const selectedLabel = systems.find((s) => s.value === selectedSystem)?.label;
- const systemExists = systems.length === 0 || systems.some((s) => s.value === selectedSystem);
+ const systemExists = systems.some((s) => s.value === selectedSystem);
+ const systemReady = !systemsPending && (selectedSystem === "" || systemExists);
const handleSelectSystem = useCallback(
(value: string) => setOptions({ newOptions: { systemId: value } }),
@@ -70,13 +71,13 @@ export default function BeszelSystemStatsWidget({
{
integrationIds,
systemId: selectedSystem,
- timePeriod: options.timePeriod as "1h" | "12h" | "24h" | "1w" | "30d",
+ timePeriod: options.timePeriod,
includeDocker: showDocker,
},
- { staleTime: 30 * 1000, enabled: !isLive && systemExists && selectedSystem !== "" },
+ { staleTime: 30 * 1000, enabled: !isLive && systemReady && selectedSystem !== "" },
);
- const liveData = useLiveStats(integrationIds, selectedSystem, showDocker, isLive && systemExists);
+ const liveData = useLiveStats(integrationIds, selectedSystem, isLive && systemReady);
const activeStats = isLive ? liveData : statsResult;
@@ -122,7 +123,7 @@ export default function BeszelSystemStatsWidget({
const cols = width > 600 ? 2 : 1;
- if (!systemExists && systems.length > 0) {
+ if (!systemsPending && !systemExists && systems.length > 0) {
return (
diff --git a/packages/widgets/src/beszel/_shared/chart.tsx b/packages/widgets/src/beszel/_shared/chart.tsx
index 08112d2f8..67b8957da 100644
--- a/packages/widgets/src/beszel/_shared/chart.tsx
+++ b/packages/widgets/src/beszel/_shared/chart.tsx
@@ -11,6 +11,13 @@ import type { BeszelContainerStatsRecord, BeszelSystemStatsRecord } from "@homar
const formatTime = (timestamp: string) => dayjs(timestamp).format("HH:mm");
const formatTimeLive = (timestamp: string) => dayjs(timestamp).format("HH:mm:ss");
+function prepareRecords(records: T[], live: boolean) {
+ return {
+ fmt: live ? formatTimeLive : formatTime,
+ ordered: live ? records : [...records].toReversed(),
+ };
+}
+
const yAxisBase = { tickMargin: 0, tick: { fontSize: 10 } } as const;
interface ChartPanelProps {
@@ -82,8 +89,7 @@ export const useSystemChartData = (
) =>
useMemo(() => {
if (!systemStats) return [];
- const fmt = live ? formatTimeLive : formatTime;
- const ordered = live ? systemStats : [...systemStats].toReversed();
+ const { fmt, ordered } = prepareRecords(systemStats, live);
return ordered.map((r) => ({
time: fmt(r.created),
...mapFn(r.stats),
@@ -123,8 +129,7 @@ export const useDockerChartData = (
if (!containerStats?.length) return [];
const extract = defaultContainerExtractors[metric];
if (!extract) return [];
- const fmt = live ? formatTimeLive : formatTime;
- const ordered = live ? containerStats : [...containerStats].toReversed();
+ const { fmt, ordered } = prepareRecords(containerStats, live);
return ordered.map((record) => {
const point: Record = { time: fmt(record.created) };
for (const name of containerNames) {
diff --git a/packages/widgets/src/beszel/_shared/use-live-stats.ts b/packages/widgets/src/beszel/_shared/use-live-stats.ts
index f664a9484..8338e4c49 100644
--- a/packages/widgets/src/beszel/_shared/use-live-stats.ts
+++ b/packages/widgets/src/beszel/_shared/use-live-stats.ts
@@ -1,6 +1,6 @@
"use client";
-import { useCallback, useEffect, useRef, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { clientApi } from "@homarr/api/client";
import type { BeszelContainerStatsRecord, BeszelSystemStatsRecord } from "@homarr/integrations/types";
@@ -12,29 +12,29 @@ interface LiveStatsData {
containerStats: BeszelContainerStatsRecord[];
}
-export const useLiveStats = (integrationIds: string[], systemId: string, includeDocker: boolean, enabled: boolean) => {
- const bufferRef = useRef({ systemStats: [], containerStats: [] });
+export const useLiveStats = (integrationIds: string[], systemId: string, enabled: boolean) => {
const [data, setData] = useState(null);
+ const integrationKey = integrationIds.join(",");
useEffect(() => {
- bufferRef.current = { systemStats: [], containerStats: [] };
setData(null);
- }, [systemId, enabled, ...integrationIds]);
+ }, [systemId, enabled, integrationKey]);
const onData = useCallback(
(incoming: { stats: BeszelSystemStatsRecord; containerStats: BeszelContainerStatsRecord | null }) => {
- const buf = bufferRef.current;
- buf.systemStats = [...buf.systemStats, incoming.stats].slice(-MAX_BUFFER);
- if (incoming.containerStats) {
- buf.containerStats = [...buf.containerStats, incoming.containerStats].slice(-MAX_BUFFER);
- }
- setData({ ...buf });
+ setData((prev) => {
+ const systemStats = [...(prev?.systemStats ?? []), incoming.stats].slice(-MAX_BUFFER);
+ const containerStats = incoming.containerStats
+ ? [...(prev?.containerStats ?? []), incoming.containerStats].slice(-MAX_BUFFER)
+ : prev?.containerStats ?? [];
+ return { systemStats, containerStats };
+ });
},
[],
);
clientApi.widget.beszel.subscribeSystemStats.useSubscription(
- { integrationIds, systemId, includeDocker },
+ { integrationIds, systemId },
{ enabled: enabled && systemId !== "", onData },
);