Skip to content

Commit ba2a480

Browse files
committed
refactor: Update XAxisOptions interface to include a formatter function
1 parent 3b141d7 commit ba2a480

File tree

6 files changed

+137
-56
lines changed

6 files changed

+137
-56
lines changed

Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ interface LineChartProps extends React.HTMLAttributes<HTMLDivElement> {
483483
showGridLines?: boolean
484484
yAxisWidth?: number
485485
intervalType?: "preserveStartEnd" | "equidistantPreserveStart"
486+
curve?: "linear" | "monotone"
486487
showTooltip?: boolean
487488
showLegend?: boolean
488489
autoMinValue?: boolean
@@ -696,7 +697,7 @@ const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(
696697
cursor={{ stroke: "#d1d5db", strokeWidth: 1 }}
697698
offset={20}
698699
position={{ y: 0 }}
699-
content={({ active, payload, label }) => {
700+
content={({ active, payload, label }: any) => {
700701
const cleanPayload: TooltipProps["payload"] = payload
701702
? payload.map((item: any) => ({
702703
category: item.dataKey,
@@ -743,7 +744,7 @@ const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(
743744
<RechartsLegend
744745
verticalAlign="top"
745746
height={legendHeight}
746-
content={({ payload }) =>
747+
content={({ payload }: any) =>
747748
ChartLegend(
748749
{ payload },
749750
categoryColors,
@@ -803,7 +804,7 @@ const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(
803804
strokeLinecap={strokeLinecap}
804805
strokeLinejoin={strokeLinejoin}
805806
strokeWidth={strokeWidth}
806-
onClick={(_, event) => onDotClick(props, event)}
807+
onClick={(_: any, event: any) => onDotClick(props, event)}
807808
/>
808809
)
809810
}}
@@ -882,7 +883,7 @@ const LineChart = React.forwardRef<HTMLDivElement, LineChartProps>(
882883
tooltipType="none"
883884
strokeWidth={12}
884885
connectNulls={connectNulls}
885-
onClick={(props: any, event) => {
886+
onClick={(props: any, event: any) => {
886887
event.stopPropagation()
887888
const { name } = props
888889
onCategoryClick(name)

Common/UI/Components/Charts/Line/LineChart.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ChartCurve from "../Types/ChartCurve";
77
import ChartDataPoint from "../ChartLibrary/Types/ChartDataPoint";
88
import DataPointUtil from "../Utils/DataPoint";
99

10+
1011
export interface ComponentProps {
1112
data: Array<SeriesPoint>;
1213
xAxis: XAxis;
@@ -47,11 +48,12 @@ const LineChartElement: FunctionComponent<ComponentProps> = (
4748
className="h-80"
4849
data={records}
4950
tickGap={1}
50-
index={props.xAxis.legend}
51+
index={"Time"}
5152
categories={categories}
52-
colors={["indigo", "rose", "amber"]}
53+
colors={["indigo", "rose", "emerald", "amber", "cyan", "gray", "pink", "lime", "fuchsia"]}
5354
valueFormatter={props.yAxis.options.formatter || undefined}
5455
showTooltip={true}
56+
connectNulls={true}
5557
yAxisWidth={60}
5658
onValueChange={(v) => {
5759
return console.log(v);

Common/UI/Components/Charts/Types/XAxis/XAxis.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import XAxisMaxMin from "./XAxisMaxMin";
22
import XAxisType from "./XAxisType";
33

4+
export enum XAxisAggregateType {
5+
Average = "Average",
6+
Sum = "Sum",
7+
Max = "Max",
8+
Min = "Min",
9+
}
10+
411
export interface XAxisOptions {
512
type: XAxisType;
613
min: XAxisMaxMin;
714
max: XAxisMaxMin;
15+
aggregateType: XAxisAggregateType;
816
}
917

1018
export interface XAxis {

Common/UI/Components/Charts/Utils/DataPoint.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@
77
// Inverters: 2103,
88
// }
99

10+
import BadDataException from "../../../../Types/Exception/BadDataException";
1011
import ChartDataPoint from "../ChartLibrary/Types/ChartDataPoint";
1112
import SeriesPoints from "../Types/SeriesPoints";
12-
import { XAxis } from "../Types/XAxis/XAxis";
13+
import { XAxis, XAxisAggregateType } from "../Types/XAxis/XAxis";
1314
import XAxisMaxMin from "../Types/XAxis/XAxisMaxMin";
1415
import XAxisUtil from "./XAxis";
1516

1617

1718

18-
export default class DataPointUtil {
19+
export default class DataPointUtil {
1920
public static getChartDataPoints(data: {
2021
seriesPoints: Array<SeriesPoints>;
2122
xAxis: XAxis
2223
}): Array<ChartDataPoint> {
2324

24-
const xAxisMax:XAxisMaxMin = data.xAxis.options.max;
25+
const xAxisMax: XAxisMaxMin = data.xAxis.options.max;
2526
const xAxisMin: XAxisMaxMin = data.xAxis.options.min;
2627

2728
const xAxisLegend: string = data.xAxis.legend;
@@ -45,27 +46,53 @@ export default class DataPointUtil {
4546
arrayOfData.push(dataPoint);
4647
}
4748

49+
interface SeriesData {
50+
sum: number;
51+
count: number;
52+
max: number;
53+
min: number;
54+
}
55+
56+
// Initialize a new data structure to store sum, count, max, and min for each series
57+
const seriesDataMap: { [key: string]: SeriesData } = {};
58+
4859
// now we need to add the data points.
49-
for(const series of data.seriesPoints) {
50-
for(const dataPoint of series.data) {
60+
for (const series of data.seriesPoints) {
61+
for (const dataPoint of series.data) {
5162
const date: Date = dataPoint.x;
5263
const value: number = dataPoint.y;
5364
const formattedDate: string = formatter(date);
54-
55-
for(const chartDataPoint of arrayOfData) {
56-
if(chartDataPoint[xAxisLegend] === formattedDate) {
57-
// if the series exists, sum the value.
58-
59-
if(chartDataPoint[series.seriesName]) {
60-
(chartDataPoint[series.seriesName] as number) += value;
65+
66+
for (const chartDataPoint of arrayOfData) {
67+
if (chartDataPoint[xAxisLegend] === formattedDate) {
68+
// Initialize series data if it doesn't exist
69+
if (!seriesDataMap[series.seriesName]) {
70+
seriesDataMap[series.seriesName] = { sum: 0, count: 0, max: Number.NEGATIVE_INFINITY, min: Number.POSITIVE_INFINITY };
71+
}
72+
73+
// Update sum, count, max, and min
74+
seriesDataMap[series.seriesName]!.sum += value;
75+
seriesDataMap[series.seriesName]!.count += 1;
76+
seriesDataMap[series.seriesName]!.max = Math.max(seriesDataMap[series.seriesName]!.max, value);
77+
seriesDataMap[series.seriesName]!.min = Math.min(seriesDataMap[series.seriesName]!.min, value);
78+
79+
// Calculate the average, sum, max, or min based on the aggregate type
80+
if (data.xAxis.options.aggregateType === XAxisAggregateType.Average) {
81+
chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.sum / seriesDataMap[series.seriesName]!.count;
82+
} else if (data.xAxis.options.aggregateType === XAxisAggregateType.Sum) {
83+
chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.sum;
84+
} else if (data.xAxis.options.aggregateType === XAxisAggregateType.Max) {
85+
chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.max;
86+
} else if (data.xAxis.options.aggregateType === XAxisAggregateType.Min) {
87+
chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.min;
88+
} else {
89+
throw new BadDataException("Aggregate type not supported.");
6190
}
62-
63-
chartDataPoint[series.seriesName] = value;
6491
}
6592
}
6693
}
6794
}
68-
95+
6996
return arrayOfData;
7097

7198
}

Common/UI/Components/Charts/Utils/XAxis.ts

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,27 @@ export default class XAxisUtil {
2525
const totalMonths = totalDays / 30;
2626

2727

28-
if (totalSeconds <= 200) return XAxisPrecision.EVERY_SECOND;
29-
if (totalSeconds <= 1000) return XAxisPrecision.EVERY_FIVE_SECONDS;
30-
if (totalSeconds <= 2000) return XAxisPrecision.EVERY_TEN_SECONDS;
31-
if (totalSeconds <= 6000) return XAxisPrecision.EVERY_THIRTY_SECONDS;
32-
if (totalMinutes <= 200) return XAxisPrecision.EVERY_MINUTE;
33-
if (totalMinutes <= 1000) return XAxisPrecision.EVERY_FIVE_MINUTES;
34-
if (totalMinutes <= 2000) return XAxisPrecision.EVERY_TEN_MINUTES;
35-
if (totalMinutes <= 6000) return XAxisPrecision.EVERY_THIRTY_MINUTES;
36-
if (totalHours <= 200) return XAxisPrecision.EVERY_HOUR;
37-
if (totalHours <= 400) return XAxisPrecision.EVERY_TWO_HOURS;
38-
if (totalHours <= 600) return XAxisPrecision.EVERY_THREE_HOURS;
39-
if (totalHours <= 1200) return XAxisPrecision.EVERY_SIX_HOURS;
40-
if (totalHours <= 2400) return XAxisPrecision.EVERY_TWELVE_HOURS;
41-
if (totalDays <= 200) return XAxisPrecision.EVERY_DAY;
42-
if (totalDays <= 400) return XAxisPrecision.EVERY_TWO_DAYS;
43-
if (totalWeeks <= 200) return XAxisPrecision.EVERY_WEEK;
44-
if (totalWeeks <= 400) return XAxisPrecision.EVERY_TWO_WEEKS;
45-
if (totalMonths <= 200) return XAxisPrecision.EVERY_MONTH;
46-
if (totalMonths <= 400) return XAxisPrecision.EVERY_TWO_MONTHS;
47-
if (totalMonths <= 600) return XAxisPrecision.EVERY_THREE_MONTHS;
48-
if (totalMonths <= 1200) return XAxisPrecision.EVERY_SIX_MONTHS;
28+
if (totalSeconds <= 50) return XAxisPrecision.EVERY_SECOND;
29+
if (totalSeconds <= 250) return XAxisPrecision.EVERY_FIVE_SECONDS;
30+
if (totalSeconds <= 500) return XAxisPrecision.EVERY_TEN_SECONDS;
31+
if (totalSeconds <= 1500) return XAxisPrecision.EVERY_THIRTY_SECONDS;
32+
if (totalMinutes <= 50) return XAxisPrecision.EVERY_MINUTE;
33+
if (totalMinutes <= 250) return XAxisPrecision.EVERY_FIVE_MINUTES;
34+
if (totalMinutes <= 500) return XAxisPrecision.EVERY_TEN_MINUTES;
35+
if (totalMinutes <= 1500) return XAxisPrecision.EVERY_THIRTY_MINUTES;
36+
if (totalHours <= 50) return XAxisPrecision.EVERY_HOUR;
37+
if (totalHours <= 100) return XAxisPrecision.EVERY_TWO_HOURS;
38+
if (totalHours <= 150) return XAxisPrecision.EVERY_THREE_HOURS;
39+
if (totalHours <= 300) return XAxisPrecision.EVERY_SIX_HOURS;
40+
if (totalHours <= 600) return XAxisPrecision.EVERY_TWELVE_HOURS;
41+
if (totalDays <= 50) return XAxisPrecision.EVERY_DAY;
42+
if (totalDays <= 100) return XAxisPrecision.EVERY_TWO_DAYS;
43+
if (totalWeeks <= 50) return XAxisPrecision.EVERY_WEEK;
44+
if (totalWeeks <= 100) return XAxisPrecision.EVERY_TWO_WEEKS;
45+
if (totalMonths <= 50) return XAxisPrecision.EVERY_MONTH;
46+
if (totalMonths <= 100) return XAxisPrecision.EVERY_TWO_MONTHS;
47+
if (totalMonths <= 150) return XAxisPrecision.EVERY_THREE_MONTHS;
48+
if (totalMonths <= 300) return XAxisPrecision.EVERY_SIX_MONTHS;
4949
return XAxisPrecision.EVERY_YEAR;
5050

5151
}
@@ -55,21 +55,21 @@ export default class XAxisUtil {
5555
xAxisMax: XAxisMaxMin,
5656
}): Array<Date> {
5757
const precision: XAxisPrecision = XAxisUtil.getPrecision(data);
58-
58+
5959
if (typeof data.xAxisMax === "number" || typeof data.xAxisMin === "number") {
6060
// number not yet supported.
6161
throw new NotImplementedException();
6262
}
63-
63+
6464
const startDate: Date = new Date(data.xAxisMin);
6565
const endDate: Date = new Date(data.xAxisMax);
6666
const intervals: Array<Date> = [];
67-
67+
6868
let currentDate = startDate;
69-
69+
7070
while (currentDate <= endDate) {
7171
intervals.push(new Date(currentDate));
72-
72+
7373
switch (precision) {
7474
case XAxisPrecision.EVERY_SECOND:
7575
currentDate.setSeconds(currentDate.getSeconds() + 1);
@@ -139,7 +139,7 @@ export default class XAxisUtil {
139139
break;
140140
}
141141
}
142-
142+
143143
return intervals;
144144
}
145145

@@ -166,22 +166,40 @@ export default class XAxisUtil {
166166
case XAxisPrecision.EVERY_THREE_HOURS:
167167
case XAxisPrecision.EVERY_SIX_HOURS:
168168
case XAxisPrecision.EVERY_TWELVE_HOURS:
169-
return (value: Date) => value.toISOString().substring(11, 13) + ":00"; // HH:00
169+
return (value: Date) => {
170+
const dateString = value.toISOString();
171+
const day = dateString.substring(8, 10);
172+
const month = value.toLocaleString('default', { month: 'short' });
173+
const hour = dateString.substring(11, 13);
174+
return `${day} ${month}, ${hour}:00`;
175+
}; // DD MMM, HH:00
170176
case XAxisPrecision.EVERY_DAY:
171177
case XAxisPrecision.EVERY_TWO_DAYS:
172-
return (value: Date) => value.toISOString().substring(0, 10); // YYYY-MM-DD
178+
return (value: Date) => {
179+
const dateString = value.toISOString();
180+
const day = dateString.substring(8, 10);
181+
const month = value.toLocaleString('default', { month: 'short' });
182+
return `${day} ${month}`;
183+
}; // DD MMM
173184
case XAxisPrecision.EVERY_WEEK:
174185
case XAxisPrecision.EVERY_TWO_WEEKS:
175186
return (value: Date) => {
176-
const startOfWeek = new Date(value);
177-
startOfWeek.setDate(value.getDate() - value.getDay());
178-
return startOfWeek.toISOString().substring(0, 10); // YYYY-MM-DD
179-
};
187+
const dateString = value.toISOString();
188+
const day = dateString.substring(8, 10);
189+
const month = value.toLocaleString('default', { month: 'short' });
190+
return `${day} ${month}`;
191+
}; // DD MMM
180192
case XAxisPrecision.EVERY_MONTH:
181193
case XAxisPrecision.EVERY_TWO_MONTHS:
182194
case XAxisPrecision.EVERY_THREE_MONTHS:
183195
case XAxisPrecision.EVERY_SIX_MONTHS:
184-
return (value: Date) => value.toISOString().substring(0, 7); // YYYY-MM
196+
return (value: Date) => {
197+
const dateString = value.toISOString();
198+
const day = dateString.substring(8, 10);
199+
const year = dateString.substring(0, 4);
200+
const month = value.toLocaleString('default', { month: 'short' });
201+
return `${day} ${month} ${year}`;
202+
}; // DD MMM
185203
case XAxisPrecision.EVERY_YEAR:
186204
return (value: Date) => value.toISOString().substring(0, 4); // YYYY
187205
default:

Dashboard/src/Components/Monitor/MonitorCharts/MonitorChart.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import SeriesPoints from "Common/UI/Components/Charts/Types/SeriesPoints";
1616
import YAxisType from "Common/UI/Components/Charts/Types/YAxis/YAxisType";
1717
import YAxis from "Common/UI/Components/Charts/Types/YAxis/YAxis";
1818
import XAxisType from "Common/UI/Components/Charts/Types/XAxis/XAxisType";
19-
import { XAxis } from "Common/UI/Components/Charts/Types/XAxis/XAxis";
19+
import { XAxis, XAxisAggregateType } from "Common/UI/Components/Charts/Types/XAxis/XAxis";
2020
import ChartCurve from "Common/UI/Components/Charts/Types/ChartCurve";
2121

2222
export class MonitorCharts {
@@ -168,6 +168,7 @@ export class MonitorCharts {
168168
data: chartData,
169169
xAxis: MonitorCharts.getXAxisFor({
170170
monitorMetricsByMinute,
171+
checkOn: checkOn,
171172
}),
172173
yAxis: MonitorCharts.getYAxisFor({
173174
checkOn: checkOn,
@@ -256,17 +257,41 @@ export class MonitorCharts {
256257

257258
public static getXAxisFor(data: {
258259
monitorMetricsByMinute: Array<MonitorMetricsByMinute>;
260+
checkOn: CheckOn;
259261
}): XAxis {
260262
const startTime: Date =
261263
data.monitorMetricsByMinute[0]?.createdAt! || undefined;
262264
const endTime: Date =
263265
data.monitorMetricsByMinute[data.monitorMetricsByMinute.length - 1]
264266
?.createdAt! || undefined;
265267

268+
let xAxisAggregationType: XAxisAggregateType = XAxisAggregateType.Average;
269+
270+
if(data.checkOn === CheckOn.ResponseStatusCode) {
271+
xAxisAggregationType = XAxisAggregateType.Max;
272+
}
273+
274+
if(data.checkOn === CheckOn.IsOnline) {
275+
xAxisAggregationType = XAxisAggregateType.Min;
276+
}
277+
278+
if(data.checkOn === CheckOn.ResponseTime) {
279+
xAxisAggregationType = XAxisAggregateType.Average;
280+
}
281+
282+
if(
283+
data.checkOn === CheckOn.DiskUsagePercent ||
284+
data.checkOn === CheckOn.MemoryUsagePercent ||
285+
data.checkOn === CheckOn.CPUUsagePercent
286+
){
287+
xAxisAggregationType = XAxisAggregateType.Average;
288+
}
289+
266290
return {
267291
legend: "Time",
268292
options: {
269293
type: XAxisType.Time,
294+
aggregateType: xAxisAggregationType,
270295
min: startTime,
271296
max: endTime,
272297
},

0 commit comments

Comments
 (0)