docker details tweaks

This commit is contained in:
Alex Holliday committed 2025-12-30 22:21:51 +00:00
1 parent 5c9d6b5523
commit 86cfc89545
5 files changed
+85 -43

No files matched your search

@@ -12,9 +12,11 @@ import {
} from "recharts";
import { XTick } from "@/components/monitors/ChartResponseTime";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { BaseBox } from "@/components/design-elements";
import { useAppSelector } from "@/hooks/AppHooks";
import { formatDateWithTz, tooltipDateFormatLookup } from "@/utils/TimeUtils";
import { useTranslation } from "react-i18next";
type Datum = Record<string, unknown> & { _id: string | number };
@@ -33,11 +35,12 @@ export const BarDockerCount = ({
}) => {
const theme = useTheme();
const hasData = Array.isArray(data) && data.length > 0;
const isSmall = useMediaQuery(theme.breakpoints.down("sm"));
const uiTimezone = useAppSelector((state: any) => state.ui.timezone);
const { t } = useTranslation();
const CountTooltip = ({ active, payload, label }: any) => {
if (!active || !payload || !label) return null;
console.log(JSON.stringify(payload, null, 2));
const fmt = tooltipDateFormatLookup(range);
const value = payload?.[0]?.payload?.[dataKey] ?? 0;
return (
@@ -45,20 +48,29 @@ export const BarDockerCount = ({
<Typography>
{formatDateWithTz(String(label), fmt, uiTimezone)}
</Typography>
<Typography>Containers: {value}</Typography>
<Typography>
{t("monitors.docker.details.tooltips.containers", { value })}
</Typography>
</BaseBox>
);
};
return (
<BaseChart title={title} icon={null}>
<BaseChart
title={title}
icon={null}
padding={{ xs: theme.spacing(4), md: theme.spacing(8) }}
>
{!hasData ? (
<Stack height={"100%"} alignItems={"center"} justifyContent={"center"}>
<Typography variant="h2">{emptyText || "No data"}</Typography>
</Stack>
) : (
<ResponsiveContainer width="100%" height={200}>
<BarChart data={data}>
<BarChart
data={data}
margin={{ top: 8, right: 8, left: isSmall ? 4 : 12, bottom: 8 }}
>
<defs>
<linearGradient id={"gradient"} x1="0" y1="0" x2="0" y2="1">
<stop
@@ -82,7 +94,12 @@ export const BarDockerCount = ({
dataKey={"_id"}
tick={(props) => <XTick {...props} range={range} />}
/>
<YAxis allowDecimals={false} />
<YAxis
allowDecimals={false}
width={isSmall ? 24 : 36}
tick={{ fontSize: isSmall ? 10 : 11 }}
tickMargin={4}
/>
<Tooltip content={<CountTooltip />} cursor={false} />
<Bar dataKey={dataKey} fill={`url(#gradient)`} />
</BarChart>
+4 -2
View File
@@ -2,6 +2,7 @@ import { BaseBox } from "../design-elements";
import Stack from "@mui/material/Stack";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import type { ResponsiveStyleValue } from "@mui/system";
import { useTheme } from "@mui/material/styles";
@@ -10,6 +11,7 @@ type BaseChartProps = React.PropsWithChildren<{
title: string;
width?: number | string;
maxWidth?: number | string;
padding?: number | string | ResponsiveStyleValue<number | string>;
}>;
export const BaseChart = ({
@@ -18,13 +20,13 @@ export const BaseChart = ({
title,
width = "100%",
maxWidth = "100%",
padding,
}: BaseChartProps) => {
const theme = useTheme();
return (
<BaseBox
sx={{
padding: theme.spacing(8),
padding: padding ?? theme.spacing(8),
display: "flex",
flex: 1,
width: width,
@@ -11,6 +11,7 @@ import {
} from "recharts";
import { XTick } from "@/components/monitors/ChartResponseTime";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
export const HistogramDockerPercentage = ({
data,
@@ -26,17 +27,25 @@ export const HistogramDockerPercentage = ({
emptyText?: string;
}) => {
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down("sm"));
const hasData = Array.isArray(data) && data.length > 0;
return (
<BaseChart title={title} icon={null}>
<BaseChart
title={title}
icon={null}
padding={{ xs: theme.spacing(4), md: theme.spacing(8) }}
>
{!hasData ? (
<Stack height={"100%"} alignItems={"center"} justifyContent={"center"}>
<Typography variant="h2">{emptyText || "No data"}</Typography>
</Stack>
) : (
<ResponsiveContainer width="100%" height={155}>
<AreaChart data={data}>
<ResponsiveContainer width="100%" height={200}>
<AreaChart
data={data}
margin={{ top: 8, right: 8, left: isSmall ? 0 : 8, bottom: 8 }}
>
<CartesianGrid
stroke={theme.palette.divider}
strokeWidth={1}
@@ -60,9 +69,15 @@ export const HistogramDockerPercentage = ({
</defs>
<XAxis
dataKey={"_id"}
axisLine={false}
tickLine={false}
tick={(props) => <XTick {...props} range={range} />}
/>
<YAxis />
<YAxis
width={isSmall ? 24 : 36}
tick={{ fontSize: isSmall ? 10 : 11 }}
tickMargin={4}
/>
<Area
dataKey={dataKey}
stroke={theme.palette.primary.main}
+7 -4
View File
@@ -547,6 +547,9 @@
"runningCountChart": {
"empty": "No data",
"title": "# of running containers"
},
"tooltips": {
"containers": "Containers: {{value}}"
}
},
"fallback": {
@@ -585,7 +588,7 @@
"optionCpuUsage": "CPU usage (%)",
"optionDiskUsage": "Disk usage (%)",
"optionMemoryUsage": "Memory usage (%)",
"optionTemperature": "Temperature (°C)",
"optionTemperature": "Temperature (\u00b0C)",
"title": "Thresholds for alerts"
}
},
@@ -715,7 +718,7 @@
},
"form": {
"discord": {
"description": "Configure your Discord webhook URL. Create one in Discord: Settings & administration → Manage apps → Custom Integrations → Incoming Webhooks",
"description": "Configure your Discord webhook URL. Create one in Discord: Settings & administration \u2192 Manage apps \u2192 Custom Integrations \u2192 Incoming Webhooks",
"option": "Webhook URL",
"placeholder": "https://discord.com/api/webhooks/YOUR/WEBHOOK/URL",
"title": "Discord configuration"
@@ -733,7 +736,7 @@
"title": "Channel name"
},
"slack": {
"description": "Configure your Slack webhook URL. Create one in Slack: Settings & administration → Manage apps → Custom Integrations → Incoming Webhooks",
"description": "Configure your Slack webhook URL. Create one in Slack: Settings & administration \u2192 Manage apps \u2192 Custom Integrations \u2192 Incoming Webhooks",
"option": "Webhook URL",
"placeholder": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
"title": "Slack configuration"
@@ -891,4 +894,4 @@
}
}
}
}
}
+33 -28
View File
@@ -86,34 +86,39 @@ const DockerDetailsPage = () => {
<CardDockerContainer key={c.container_id} container={c} />
))}
</Stack>
<BarDockerCount
data={checks}
dataKey="healthyContainers"
range={range}
title={t("monitors.docker.details.healthyCountChart.title")}
emptyText={t("monitors.docker.details.healthyCountChart.empty")}
/>
<BarDockerCount
data={checks}
dataKey="runningContainers"
range={range}
title={t("monitors.docker.details.runningCountChart.title")}
emptyText={t("monitors.docker.details.runningCountChart.empty")}
/>
<HistogramDockerPercentage
data={checks}
dataKey="healthyPercent"
range={range}
title={t("monitors.docker.details.healthyChart.title")}
emptyText={t("monitors.docker.details.healthyChart.empty")}
/>
<HistogramDockerPercentage
data={checks}
dataKey="runningPercent"
range={range}
title={t("monitors.docker.details.healthyChart.title")}
emptyText={t("monitors.docker.details.healthyChart.empty")}
/>
<Stack gap={theme.spacing(6)} direction={{ xs: "column", lg: "row" }}>
<HistogramDockerPercentage
data={checks}
dataKey="healthyPercent"
range={range}
title={t("monitors.docker.details.healthyChart.title")}
emptyText={t("monitors.docker.details.healthyChart.empty")}
/>
<BarDockerCount
data={checks}
dataKey="healthyContainers"
range={range}
title={t("monitors.docker.details.healthyCountChart.title")}
emptyText={t("monitors.docker.details.healthyCountChart.empty")}
/>
</Stack>
<Stack gap={theme.spacing(6)} direction={{ xs: "column", lg: "row" }}>
<HistogramDockerPercentage
data={checks}
dataKey="runningPercent"
range={range}
title={t("monitors.docker.details.runningChart.title")}
emptyText={t("monitors.docker.details.runningChart.empty")}
/>
<BarDockerCount
data={checks}
dataKey="runningContainers"
range={range}
title={t("monitors.docker.details.runningCountChart.title")}
emptyText={t("monitors.docker.details.runningCountChart.empty")}
/>
</Stack>
</BasePage>
);
};