diff --git a/Client/src/Components/Charts/AreaChart/index.jsx b/Client/src/Components/Charts/AreaChart/index.jsx index 4aa507940..d05dbb14a 100644 --- a/Client/src/Components/Charts/AreaChart/index.jsx +++ b/Client/src/Components/Charts/AreaChart/index.jsx @@ -10,7 +10,7 @@ import { import { createGradient } from "../Utils/gradientUtils"; import PropTypes from "prop-types"; import { useTheme } from "@mui/material"; - +import { useId } from "react"; /** * CustomAreaChart component for rendering an area chart with optional gradient and custom ticks. * @@ -83,13 +83,16 @@ const CustomAreaChart = ({ gradientStartColor, gradientEndColor, customTooltip, + height = "100%", }) => { const theme = useTheme(); - const gradientId = `gradient-${Math.random().toString(36).slice(2, 9)}`; + const uniqueId = useId(); + const gradientId = `gradient-${uniqueId}`; return ( - {customTooltip ? ( { * Renders a base box with consistent styling * @param {Object} props - Component properties * @param {React.ReactNode} props.children - Child components to render inside the box + * @param {Object} props.sx - Additional styling for the box * @returns {React.ReactElement} Styled box component */ -const BaseBox = ({ children }) => { +const BaseBox = ({ children, sx = {} }) => { const theme = useTheme(); return ( {children} @@ -60,6 +65,7 @@ const BaseBox = ({ children }) => { BaseBox.propTypes = { children: PropTypes.node.isRequired, + sx: PropTypes.object, }; /** @@ -159,6 +165,18 @@ const InfrastructureDetails = () => { ]; const [monitor, setMonitor] = useState(null); + // These calculations are needed because ResponsiveContainer + // doesn't take padding of parent/siblings into account + // when calculating height. + const chartContainerHeight = 300; + const totalChartContainerPadding = + parseInt(theme.spacing(BASE_BOX_PADDING_VERTICAL), 10) * 2; + const totalTypographyPadding = parseInt(theme.spacing(TYPOGRAPHY_PADDING), 10) * 2; + const areaChartHeight = + (chartContainerHeight - totalChartContainerPadding - totalTypographyPadding) * 0.95; + // end height calculations + + // Fetch data useEffect(() => { const fetchData = async () => { try { @@ -176,6 +194,86 @@ const InfrastructureDetails = () => { fetchData(); }, []); + const statBoxConfigs = [ + { + id: 0, + heading: "CPU", + subHeading: `${monitor?.checks[0]?.cpu?.physical_core} cores`, + }, + { + id: 1, + heading: "Memory", + subHeading: formatBytes(monitor?.checks[0]?.memory?.total_bytes), + }, + { + id: 2, + heading: "Disk", + subHeading: formatBytes(monitor?.checks[0]?.disk[0]?.total_bytes), + }, + { id: 3, heading: "Uptime", subHeading: "100%" }, + { + id: 4, + heading: "Status", + subHeading: monitor?.status === true ? "Active" : "Inactive", + }, + ]; + + const gaugeBoxConfigs = [ + { + type: "memory", + value: monitor?.checks[0]?.memory?.usage_percent * 100, + heading: "Memory Usage", + metricOne: "Used", + valueOne: formatBytes(monitor?.checks[0]?.memory?.used_bytes), + metricTwo: "Total", + valueTwo: formatBytes(monitor?.checks[0]?.memory?.total_bytes), + }, + { + type: "cpu", + value: monitor?.checks[0]?.cpu?.usage_percent * 100, + heading: "CPU Usage", + metricOne: "Cores", + valueOne: monitor?.checks[0]?.cpu?.physical_core, + metricTwo: "Frequency", + valueTwo: `${(monitor?.checks[0]?.cpu?.frequency / 1000).toFixed(2)} Ghz`, + }, + ...(monitor?.checks[0]?.disk ?? []).map((disk, idx) => ({ + type: "disk", + diskIndex: idx, + value: disk.usage_percent * 100, + heading: `Disk${idx} usage`, + metricOne: "Used", + valueOne: formatBytes(disk.total_bytes - disk.free_bytes), + metricTwo: "Total", + valueTwo: formatBytes(disk.total_bytes), + })), + ]; + + const areaChartConfigs = [ + { + type: "memory", + dataKey: "memory.usage_percent", + heading: "Memory usage", + strokeColor: theme.palette.primary.main, + yLabel: "Memory Usage", + }, + { + type: "cpu", + dataKey: "cpu.usage_percent", + heading: "CPU usage", + strokeColor: theme.palette.success.main, + yLabel: "CPU Usage", + }, + ...(monitor?.checks?.[0]?.disk?.map((disk, idx) => ({ + type: "disk", + diskIndex: idx, + dataKey: `disk[${idx}].usage_percent`, + heading: `Disk${idx} usage`, + strokeColor: theme.palette.warning.main, + yLabel: "Disk Usage", + })) || []), + ]; + return ( monitor && ( @@ -189,64 +287,32 @@ const InfrastructureDetails = () => { direction="row" gap={theme.spacing(8)} > - - - - - + {statBoxConfigs.map((statBox) => ( + + ))} - - - {monitor.checks[0].disk.map((disk, idx) => { - return ( - - ); - })} + {gaugeBoxConfigs.map((config) => ( + + ))} { }, }} > - - - Memory usage - - ( - - )} - xTick={} - yTick={} - strokeColor={theme.palette.primary.main} - gradient={true} - gradientStartColor={theme.palette.primary.main} //FE team HELP! Not sure what colors to use - gradientEndColor="#ffffff" // FE team HELP! - /> - - - - CPU usage - - ( - - )} - xTick={} - yTick={} - strokeColor={theme.palette.success.main} // FE team HELP! - gradient={true} - fill={theme.palette.success.main} // FE team HELP! - gradientStartColor={theme.palette.success.main} - gradientEndColor="#ffffff" - /> - - {monitor?.checks?.[0]?.disk?.map((disk, idx) => { - // disk is an array of disks, so we need to map over it - return ( - - - {`Disk${idx} usage`} - - ( - - )} - xTick={} - yTick={} - strokeColor={theme.palette.warning.main} - gradient={true} - gradientStartColor={theme.palette.warning.main} - gradientEndColor="#ffffff" - /> - - ); - })} + {areaChartConfigs.map((config) => ( + + + {config.heading} + + ( + + )} + xTick={} + yTick={} + strokeColor={config.strokeColor} + gradient={true} + gradientStartColor={config.strokeColor} + gradientEndColor="#ffffff" + /> + + ))}