add heatmap chart

This commit is contained in:
Alex Holliday committed 2025-11-25 19:56:26 +00:00
1 parent c2a1d6d97e
commit a8d83b33b4
4 files changed
+75 -29

No files matched your search

@@ -2,13 +2,19 @@ import Box from "@mui/material/Box";
import { useTheme } from "@mui/material/styles";
import type { ICheck } from "@/types/check";
import { getResponseColor } from "@/utils/DataUtils";
import { HistogramResponseTimeTooltip } from "@/components/monitors/HistogramResponseTimeTooltip";
import { HeatmapResponseTimeTooltip } from "./HeatmapResponseTimeTooltip";
import type { SxProps } from "@mui/material/styles";
interface HeatmapResponseTimeProps {
checks: ICheck[];
availabilityCellSx?: SxProps;
responseCellSx?: SxProps;
}
export const HeatmapResponseTime = ({ checks }: HeatmapResponseTimeProps) => {
export const HeatmapResponseTime = ({
checks,
availabilityCellSx,
responseCellSx,
}: HeatmapResponseTimeProps) => {
const theme = useTheme();
if (!checks || checks.length === 0) return null;
@@ -53,35 +59,41 @@ export const HeatmapResponseTime = ({ checks }: HeatmapResponseTimeProps) => {
});
return (
<HistogramResponseTimeTooltip
key={`${check}-${index}`}
check={check}
>
<HeatmapResponseTimeTooltip key={`${check}-${index}`} check={check}>
<Box
sx={{
display: "grid",
gridTemplateRows: "auto auto",
gap: theme.spacing(0.5),
}}
>
<Box
sx={{
width: "100%",
height: theme.spacing(0.75),
borderRadius: theme.spacing(0.5),
bgcolor: statusBg,
display: "flex",
flexDirection: "column",
gap: theme.spacing(2),
}}
/>
<Box
sx={{
width: "100%",
aspectRatio: "1 / 1",
borderRadius: theme.spacing(0.5),
bgcolor: respBg,
}}
/>
>
<Box
sx={{
width: "100%",
aspectRatio: "10",
bgcolor: statusBg,
borderRadius: theme.spacing(0.5),
...availabilityCellSx,
}}
/>
<Box
sx={{
width: "100%",
aspectRatio: "1 / 1",
bgcolor: respBg,
borderRadius: theme.spacing(0.5),
...responseCellSx,
}}
/>
</Box>
</Box>
</HistogramResponseTimeTooltip>
</HeatmapResponseTimeTooltip>
);
})}
</Box>
@@ -6,13 +6,18 @@ import { useAppSelector } from "@/hooks/AppHooks";
import type { LatestCheck } from "@/types/check";
import { useTheme } from "@mui/material/styles";
export const HistogramResponseTimeTooltip: React.FC<{
export const HeatmapResponseTimeTooltip: React.FC<{
children: React.ReactElement;
check: LatestCheck;
}> = ({ children, check }) => {
const uiTimezone = useAppSelector((state: any) => state.ui.timezone);
const theme = useTheme();
const getColor = (status: string) => {
if (status === "up") return theme.palette.success.lowContrast;
if (status === "down") return theme.palette.error.lowContrast;
};
if (check.status === "placeholder") {
return children;
}
@@ -47,8 +52,12 @@ export const HistogramResponseTimeTooltip: React.FC<{
{check?.responseTime && (
<Typography>Response Time: {check.responseTime} ms</Typography>
)}
<Typography color="error" textTransform={"capitalize"}>
Status: {check?.status}
<Typography textTransform={"capitalize"}>
Status:{" "}
<span style={{ color: getColor(check?.status) }}>
{check?.status}
</span>
</Typography>
</Stack>
}
@@ -1,6 +1,7 @@
import Box from "@mui/material/Box";
import { BaseBox } from "@/components/design-elements";
import type { MonitorStatus } from "@/types/monitor";
import type { SxProps } from "@mui/material/styles";
import { getStatusPalette, getValuePalette } from "@/utils/MonitorUtils";
import { useTheme } from "@mui/material/styles";
@@ -8,7 +9,13 @@ import { useTheme } from "@mui/material/styles";
export const ValueTypes = ["positive", "negative", "neutral"] as const;
export type ValueType = (typeof ValueTypes)[number];
export const StatusLabel = ({ status }: { status: MonitorStatus }) => {
export const StatusLabel = ({
status,
sx,
}: {
status: MonitorStatus;
sx?: SxProps;
}) => {
const theme = useTheme();
const palette = getStatusPalette(status);
const transformedText =
@@ -27,6 +34,7 @@ export const StatusLabel = ({ status }: { status: MonitorStatus }) => {
theme.palette.mode === "dark"
? "rgba(255, 255, 255, 0.08)"
: "rgba(0, 0, 0, 0.08)",
...sx,
}}
>
<Box
@@ -2,10 +2,13 @@ import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { HeatmapResponseTime } from "../common/HeatmapResponseTime";
import { StatusLabel } from "@/components/design-elements";
import { useTheme } from "@mui/material/styles";
import type { IMonitor } from "@/types/monitor";
export const StatusPageRow = ({ monitor }: { monitor: IMonitor }) => {
const theme = useTheme();
return (
<Grid container>
<Grid size={6} display={"flex"} alignItems={"center"}>
@@ -17,10 +20,24 @@ export const StatusPageRow = ({ monitor }: { monitor: IMonitor }) => {
alignItems={"center"}
justifyContent={"flex-end"}
>
<StatusLabel status={monitor?.status} />
<StatusLabel status={monitor?.status} sx={{ py: 1 }} />
</Grid>
<Grid size={12}>
<HeatmapResponseTime checks={monitor?.latestChecks} />
<Grid size={12} marginTop={theme.spacing(2)}>
<HeatmapResponseTime
checks={monitor?.latestChecks}
availabilityCellSx={{
borderRadius: {
xs: theme.spacing(0.5),
md: theme.shape.borderRadius,
},
}}
responseCellSx={{
borderRadius: {
xs: theme.spacing(0.5),
md: theme.shape.borderRadius,
},
}}
/>
</Grid>
</Grid>
);