Files
Checkmate/client/src/Pages/Infrastructure/Details/Components/ChartsNetwork.tsx
T
gorkem-bwl 77b817778b address review feedback: rename notice to match new trigger
The notice now triggers on interface names (loopback / container-bridge
only), not on zero traffic. Update the variable, i18n key, and English
copy to match:

- showNoTrafficNotice -> showLoopbackOnlyNotice
- pages.infrastructure.charts.labels.netNoTraffic ->
  pages.infrastructure.charts.labels.loopbackOnlyNotice
- English string rewritten to describe the loopback-only condition
  rather than "zero traffic on every interface"

Other locales still hold the old string under the old key and will fall
back to English until the translation pipeline picks up the new key.
Tracked separately.
2026-07-11 04:29:22 +03:00

136 lines
3.8 KiB
TypeScript

import Grid from "@mui/material/Grid";
import Stack from "@mui/material/Stack";
import { NoticeBanner } from "@/Components/design-elements";
import { HistogramInfrastructure } from "@/Components/monitors";
import { useTranslation } from "react-i18next";
import type { HardwareCheckStats } from "@/Types/Monitor";
import { useMemo } from "react";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { LAYOUT } from "@/Utils/Theme/constants";
const formatBytesToMB = (value: number) => `${(value / (1024 * 1024)).toFixed(2)} MB`;
interface ChartConfig {
title: string;
type: string;
dataKeys: string[];
strokeColor: string;
gradientStartColor: string;
idx: number | null;
interfaceName?: string;
}
const getChartConfigs = (
theme: any,
checks: HardwareCheckStats[],
t: any
): ChartConfig[] => {
const configs: ChartConfig[] = [];
// Find the first check that has network data to get interface names
const checkWithNet = checks.find((c) => c.net && c.net.length > 0);
const netInterfaces = checkWithNet?.net || [];
netInterfaces.forEach((iface, idx) => {
configs.push(
{
title: t("pages.infrastructure.charts.labels.netBytesSent", {
name: iface.name,
}),
type: "netBytesSent",
dataKeys: [`net[${idx}].bytesSentPerSecond`],
strokeColor: theme.palette.primary.main,
gradientStartColor: theme.palette.primary.main,
idx,
interfaceName: iface.name,
},
{
title: t("pages.infrastructure.charts.labels.netBytesRecv", {
name: iface.name,
}),
type: "netBytesRecv",
dataKeys: [`net[${idx}].deltaBytesRecv`],
strokeColor: theme.palette.success.main,
gradientStartColor: theme.palette.success.main,
idx,
interfaceName: iface.name,
}
);
});
return configs;
};
// Loopback / bridge names Capture sees when it can only observe the container's
// own network namespace. When ALL reported interfaces match this set we assume
// the "no real interfaces visible" case and surface the notice.
const CONTAINER_ONLY_IFACE_NAMES = new Set(["lo", "lo0", "docker0"]);
const onlyContainerVisibleInterfaces = (checks: HardwareCheckStats[]): boolean => {
const named = new Set<string>();
checks.forEach((c) => c.net?.forEach((iface) => named.add(iface.name)));
if (named.size === 0) return false;
for (const name of named) {
if (!CONTAINER_ONLY_IFACE_NAMES.has(name)) return false;
}
return true;
};
export const InfraNetworkCharts = ({
checks,
dateRange,
}: {
checks: HardwareCheckStats[];
dateRange: string;
}) => {
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
const { t } = useTranslation();
const chartConfigs = useMemo(
() => getChartConfigs(theme, checks, t),
[theme, checks, t]
);
const showLoopbackOnlyNotice =
chartConfigs.length > 0 && onlyContainerVisibleInterfaces(checks);
return (
<Stack gap={theme.spacing(LAYOUT.XS)}>
{showLoopbackOnlyNotice && (
<NoticeBanner severity="warning">
{t("pages.infrastructure.charts.labels.loopbackOnlyNotice")}
</NoticeBanner>
)}
<Grid
container
spacing={theme.spacing(LAYOUT.MD)}
>
{chartConfigs.map((config) => {
return (
<Grid
size={isSmall ? 12 : 6}
key={`${config.type}-${config.interfaceName ?? config.idx ?? ""}`}
>
<HistogramInfrastructure
dateRange={dateRange}
title={config.title}
type={config.type}
idx={config.idx}
checks={checks}
xKey="bucketDate"
dataKeys={config.dataKeys}
gradient={true}
gradientStartColor={config.gradientStartColor}
gradientEndColor="#ffffff"
strokeColor={config.strokeColor}
yAxisFormatter={formatBytesToMB}
/>
</Grid>
);
})}
</Grid>
</Stack>
);
};