Merge pull request #6713 from homarr-labs/fix/v2-system-resource-widget
fix(v2 system resources widget): overflow and initial chart render
This commit is contained in:
3 files changed
+38
-17
No files matched your search
@@ -53,7 +53,7 @@ export const CommonChart = ({
|
||||
ref={ref}
|
||||
h={"100%"}
|
||||
pos={"relative"}
|
||||
style={{ overflow: "visible", border: `1px solid ${borderColor}` }}
|
||||
style={{ overflow: "hidden", border: `1px solid ${borderColor}` }}
|
||||
p={0}
|
||||
bg={backgroundColor}
|
||||
radius={board.itemRadius}
|
||||
@@ -127,7 +127,12 @@ export const CommonChart = ({
|
||||
},
|
||||
}}
|
||||
tooltipAnimationDuration={200}
|
||||
tooltipProps={tooltipProps}
|
||||
tooltipProps={{
|
||||
// Render via portal so the tooltip isn't clipped by the card's overflow:hidden
|
||||
// (needed to stop the chart line itself bleeding past its rounded corners).
|
||||
portal: typeof document !== "undefined" ? document.body : undefined,
|
||||
...tooltipProps,
|
||||
}}
|
||||
withTooltip={height >= 64}
|
||||
yAxisProps={yAxisProps}
|
||||
fillOpacity={chartType === "area" ? 0.3 : undefined}
|
||||
|
||||
@@ -19,6 +19,15 @@ const COMPACT_HISTORY_SIZE = 15;
|
||||
const ADVANCED_HISTORY_SIZE = 60;
|
||||
const ALL_SYSTEM_CHARTS = ["cpu", "memory", "gpu", "network"] as const;
|
||||
|
||||
const ADVANCED_CHART_COLUMN_BREAKPOINTS = [
|
||||
{ minWidth: 1100, columns: 4 },
|
||||
{ minWidth: 560, columns: 2 },
|
||||
{ minWidth: 0, columns: 1 },
|
||||
] as const;
|
||||
|
||||
const getAdvancedChartColumns = (width: number): number =>
|
||||
ADVANCED_CHART_COLUMN_BREAKPOINTS.find(({ minWidth }) => width >= minWidth)?.columns ?? 1;
|
||||
|
||||
type SystemChart = WidgetComponentProps<"systemResources">["options"]["visibleCharts"][number];
|
||||
|
||||
type ChartItem = {
|
||||
@@ -110,14 +119,13 @@ export default function SystemResources({
|
||||
lastUpdatedAt.current = dataUpdatedAt;
|
||||
setHistoryByIntegration((previous) =>
|
||||
Object.fromEntries(
|
||||
data.map((entry) => [
|
||||
entry.integrationId,
|
||||
appendBoundedHistory(
|
||||
previous[entry.integrationId] ?? [],
|
||||
toChartItem(entry.healthInfo),
|
||||
ADVANCED_HISTORY_SIZE,
|
||||
),
|
||||
]),
|
||||
data.map((entry) => {
|
||||
const currentItem = toChartItem(entry.healthInfo);
|
||||
// Seed with the current item when there's no history yet, so the first real
|
||||
// update lands at 2 points instead of dropping back to the single-value fallback.
|
||||
const seed = previous[entry.integrationId] ?? [currentItem];
|
||||
return [entry.integrationId, appendBoundedHistory(seed, currentItem, ADVANCED_HISTORY_SIZE)];
|
||||
}),
|
||||
),
|
||||
);
|
||||
}, [dataUpdatedAt, data]);
|
||||
@@ -126,7 +134,9 @@ export default function SystemResources({
|
||||
const panelWidth = width / panelColumns;
|
||||
const renderCharts = (entry: (typeof data)[number], availableWidth: number, availableHeight: number) => {
|
||||
const currentItem = toChartItem(entry.healthInfo);
|
||||
const fullHistory = historyByIntegration[entry.integrationId] ?? [currentItem];
|
||||
// Duplicate the first point so the chart has two points to draw a line from
|
||||
// immediately, instead of showing the single-value fallback until the next poll.
|
||||
const fullHistory = historyByIntegration[entry.integrationId] ?? [currentItem, currentItem];
|
||||
const history = isAdvanced ? fullHistory : fullHistory.slice(-COMPACT_HISTORY_SIZE);
|
||||
|
||||
return (
|
||||
@@ -225,20 +235,27 @@ const SystemCharts = ({
|
||||
const showNetwork = visibleCharts.includes("network");
|
||||
const labelDisplayMode = isAdvanced ? "textWithIcon" : options.labelDisplayMode;
|
||||
const chartCount = visibleCharts.length;
|
||||
const chartColumns = isAdvanced && width >= 560 ? 2 : 1;
|
||||
const chartColumns = useMemo(
|
||||
() => (isAdvanced ? getAdvancedChartColumns(width) : 1),
|
||||
[isAdvanced, width],
|
||||
);
|
||||
const compactChartGap = 8;
|
||||
const compactRowHeight = 56;
|
||||
const chartHeight = isAdvanced
|
||||
? 180
|
||||
: `calc((100% - ${Math.max(0, chartCount - 1) * compactChartGap}px) / ${Math.max(1, chartCount)})`;
|
||||
? 110
|
||||
: Math.max(
|
||||
28,
|
||||
Math.min(compactRowHeight, (height - Math.max(0, chartCount - 1) * compactChartGap) / Math.max(1, chartCount)),
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack gap={isAdvanced ? "xs" : compactChartGap} h={isAdvanced ? "auto" : height} miw={0}>
|
||||
<Stack gap={isAdvanced ? "xs" : compactChartGap} h="auto" miw={0}>
|
||||
{showTitle && (
|
||||
<Text size="sm" fw={600} truncate="end">
|
||||
{integrationName}
|
||||
</Text>
|
||||
)}
|
||||
<SimpleGrid cols={chartColumns} spacing={isAdvanced ? "xs" : compactChartGap} style={{ flex: 1, minHeight: 0 }}>
|
||||
<SimpleGrid cols={chartColumns} spacing={isAdvanced ? "xs" : compactChartGap}>
|
||||
{chartCount === 0 && (
|
||||
<Center h="100%">
|
||||
<Text size="sm" c="dimmed">
|
||||
|
||||
@@ -11,7 +11,6 @@ import type { BoardItemAdvancedOptions } from "@homarr/validation/shared";
|
||||
import classes from "./widget-card-shell.module.css";
|
||||
|
||||
const getOverflow = (kind: WidgetKind, hasCustomCssClasses: boolean): CSSProperties => {
|
||||
if (kind === "systemResources") return { overflowX: "visible", overflowY: "visible" };
|
||||
if (kind === "iframe" || kind === "assistant") return { overflowX: "hidden", overflowY: "hidden" };
|
||||
if (hasCustomCssClasses) return {};
|
||||
return { overflowX: "hidden", overflowY: "auto" };
|
||||
|
||||
Reference in new issue
Block a user