Add chart to detail page

This commit is contained in:
Alex Holliday committed 2024-07-17 12:33:24 -07:00
1 parent 8cc83a4422
commit 9f95d3d4bf
4 files changed
+118 -1

No files matched your search

@@ -0,0 +1,45 @@
const RANGE_MAX = 100;
const RANGE_MIN = 1;
const calculatePercentile = (arr, percentile) => {
const sorted = arr.slice().sort((a, b) => a.responseTime - b.responseTime);
const index = (percentile / 100) * (sorted.length - 1);
const lower = Math.floor(index);
const upper = lower + 1;
const weight = index % 1;
if (upper >= sorted.length) return sorted[lower].responseTime;
return (
sorted[lower].responseTime * (1 - weight) +
sorted[upper].responseTime * weight
);
};
export const NormalizeData = (checks) => {
if (checks.length > 1) {
// Get the 5th and 95th percentile
const min = calculatePercentile(checks, 5);
const max = calculatePercentile(checks, 95);
const normalizedChecks = checks.map((check) => {
// Normalize the response time between 1 and 100
let normalizedResponseTime =
RANGE_MIN +
((check.responseTime - min) * (RANGE_MAX - RANGE_MIN)) / (max - min);
// Put a floor on the response times so we don't have extreme outliers
// Better visuals
normalizedResponseTime = Math.max(
RANGE_MIN,
Math.min(RANGE_MAX, normalizedResponseTime)
);
return {
...check,
responseTime: normalizedResponseTime,
};
});
return normalizedChecks;
} else {
return checks;
}
};
Whitespace-only changes.
@@ -0,0 +1,69 @@
import PropTypes from "prop-types";
import {
AreaChart,
Area,
XAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
import { NormalizeData } from "../ChartUtils";
const MonitorDetailsAreaChart = ({ checks }) => {
// SQUASH ERROR, NOT PERMANENT SOLUTION
const error = console.error;
console.error = (...args) => {
if (/defaultProps/.test(args[0])) return;
error(...args);
};
// END SQUASH ERROR, NOT PERMANENT SOLUTION
const formatDate = (timestamp) => {
const date = new Date(timestamp);
return date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
hour12: true,
});
};
let normalizedChecks = [];
if (checks && checks.length > 0) {
normalizedChecks = NormalizeData(checks);
}
return (
<ResponsiveContainer width="100%" height="100%">
<AreaChart
width={500}
height={400}
data={normalizedChecks}
margin={{
top: 10,
right: 30,
left: 0,
bottom: 0,
}}
>
<XAxis
dataKey="createdAt"
tickFormatter={formatDate}
tick={{ fontSize: "13px" }}
/>
<Tooltip />
<Area
type="monotone"
dataKey="responseTime"
stroke="#29afee"
fill="#eaf2fd"
/>
</AreaChart>
</ResponsiveContainer>
);
};
MonitorDetailsAreaChart.propTypes = {
checks: PropTypes.array,
};
export default MonitorDetailsAreaChart;
+4 -1
View File
@@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import axiosInstance from "../../Utils/axiosConfig";
import BasicTable from "../../Components/BasicTable";
import MonitorDetailsAreaChart from "../../Components/Charts/MonitorDetailsAreaChart";
/**
* Details page component displaying monitor details and related information.
* @component
@@ -107,6 +107,9 @@ const DetailsPage = () => {
return (
<div>
<div style={{ height: "10rem" }}>
<MonitorDetailsAreaChart checks={monitor.checks} />
</div>
<BasicTable data={data} paginated={true} />
</div>
);