diff --git a/Common/Server/Infrastructure/Queue.ts b/Common/Server/Infrastructure/Queue.ts
index 3c38f78354..4a68d36d78 100644
--- a/Common/Server/Infrastructure/Queue.ts
+++ b/Common/Server/Infrastructure/Queue.ts
@@ -65,11 +65,11 @@ export default class Queue {
}
public static getQueueInspectorRouter(): ExpressRouter {
- const serverAdapter = new ExpressAdapter();
+ const serverAdapter: ExpressAdapter = new ExpressAdapter();
createBullBoard({
queues: [
- ...Object.values(QueueName).map((queueName) => {
+ ...Object.values(QueueName).map((queueName: QueueName) => {
return new BullMQAdapter(this.getQueue(queueName));
}),
],
diff --git a/Common/Types/Date.ts b/Common/Types/Date.ts
index ee6c32289c..9fc807b730 100644
--- a/Common/Types/Date.ts
+++ b/Common/Types/Date.ts
@@ -1138,8 +1138,6 @@ export default class OneUptimeDate {
);
}
-
-
public static getDateWithCustomTime(data: {
hours: number;
minutes: number;
diff --git a/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx b/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
index 9f552f3e54..86f9032bb9 100644
--- a/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
+++ b/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
@@ -1,10 +1,10 @@
// Tremor Raw LineChart [v0.3.1]
/* eslint-disable @typescript-eslint/no-explicit-any */
-"use client"
+"use client";
-import React from "react"
-import { RiArrowLeftSLine, RiArrowRightSLine } from "@remixicon/react"
+import React from "react";
+import { RiArrowLeftSLine, RiArrowRightSLine } from "@remixicon/react";
import {
CartesianGrid,
Dot,
@@ -16,36 +16,41 @@ import {
Tooltip,
XAxis,
YAxis,
-} from "recharts"
-import { AxisDomain } from "recharts/types/util/types"
+} from "recharts";
+import { AxisDomain } from "recharts/types/util/types";
-import { useOnWindowResize } from "../Utils/UseWindowOnResize"
+import { useOnWindowResize } from "../Utils/UseWindowOnResize";
import {
AvailableChartColors,
AvailableChartColorsKeys,
constructCategoryColors,
getColorClassName,
-} from "../Utils/ChartColors"
-import { cx } from "../Utils/Cx"
-import { getYAxisDomain } from "../Utils/GetYAxisDomain"
-import { hasOnlyOneValueForKey } from "../Utils/HasOnlyOneValueForKey"
+} from "../Utils/ChartColors";
+import { cx } from "../Utils/Cx";
+import { getYAxisDomain } from "../Utils/GetYAxisDomain";
+import { hasOnlyOneValueForKey } from "../Utils/HasOnlyOneValueForKey";
//#region Legend
interface LegendItemProps {
- name: string
- color: AvailableChartColorsKeys
- onClick?: (name: string, color: AvailableChartColorsKeys) => void
- activeLegend?: string
+ name: string;
+ color: AvailableChartColorsKeys;
+ onClick?: (name: string, color: AvailableChartColorsKeys) => void;
+ activeLegend?: string;
}
-const LegendItem = ({
+const LegendItem: ({
+ name,
+ color,
+ onClick,
+ activeLegend,
+}: LegendItemProps) => React.JSX.Element = ({
name,
color,
onClick,
activeLegend,
}: LegendItemProps) => {
- const hasOnValueChange = !!onClick
+ const hasOnValueChange: boolean = Boolean(onClick);
return (
{
- e.stopPropagation()
- onClick?.(name, color)
+ onClick={(e: React.MouseEvent) => {
+ e.stopPropagation();
+ onClick?.(name, color);
}}
>
- )
-}
+ );
+};
interface ScrollButtonProps {
- icon: React.ElementType
- onClick?: () => void
- disabled?: boolean
+ icon: React.ElementType;
+ onClick?: () => void;
+ disabled?: boolean;
}
-const ScrollButton = ({ icon, onClick, disabled }: ScrollButtonProps) => {
- const Icon = icon
- const [isPressed, setIsPressed] = React.useState(false)
- const intervalRef = React.useRef(null)
+const ScrollButton: ({
+ icon,
+ onClick,
+ disabled,
+}: ScrollButtonProps) => React.JSX.Element = ({
+ icon,
+ onClick,
+ disabled,
+}: ScrollButtonProps) => {
+ const Icon: React.ElementType = icon;
+ const [isPressed, setIsPressed] = React.useState(false);
+ const intervalRef: React.MutableRefObject =
+ React.useRef(null);
React.useEffect(() => {
if (isPressed) {
intervalRef.current = setInterval(() => {
- onClick?.()
- }, 300)
+ onClick?.();
+ }, 300);
} else {
- clearInterval(intervalRef.current as NodeJS.Timeout)
+ clearInterval(intervalRef.current as NodeJS.Timeout);
}
- return () => clearInterval(intervalRef.current as NodeJS.Timeout)
- }, [isPressed, onClick])
+ return () => {
+ return clearInterval(intervalRef.current as NodeJS.Timeout);
+ };
+ }, [isPressed, onClick]);
React.useEffect(() => {
if (disabled) {
- clearInterval(intervalRef.current as NodeJS.Timeout)
- setIsPressed(false)
+ clearInterval(intervalRef.current as NodeJS.Timeout);
+ setIsPressed(false);
}
- }, [disabled])
+ }, [disabled]);
return (
- )
-}
+ );
+};
interface LegendProps extends React.OlHTMLAttributes {
- categories: string[]
- colors?: AvailableChartColorsKeys[]
- onClickLegendItem?: (category: string, color: string) => void
- activeLegend?: string
- enableLegendSlider?: boolean
+ categories: string[];
+ colors?: AvailableChartColorsKeys[];
+ onClickLegendItem?: (category: string, color: string) => void;
+ activeLegend?: string;
+ enableLegendSlider?: boolean;
}
type HasScrollProps = {
- left: boolean
- right: boolean
-}
+ left: boolean;
+ right: boolean;
+};
-const Legend = React.forwardRef((props, ref) => {
- const {
- categories,
- colors = AvailableChartColors,
- className,
- onClickLegendItem,
- activeLegend,
- enableLegendSlider = false,
- ...other
- } = props
- const scrollableRef = React.useRef(null)
- const scrollButtonsRef = React.useRef(null)
- const [hasScroll, setHasScroll] = React.useState(null)
- const [isKeyDowned, setIsKeyDowned] = React.useState(null)
- const intervalRef = React.useRef(null)
+const Legend: React.ForwardRefExoticComponent<
+ LegendProps & React.RefAttributes
+> = React.forwardRef(
+ (props: LegendProps, ref: React.ForwardedRef) => {
+ const {
+ categories,
+ colors = AvailableChartColors,
+ className,
+ onClickLegendItem,
+ activeLegend,
+ enableLegendSlider = false,
+ ...other
+ } = props;
- const checkScroll = React.useCallback(() => {
- const scrollable = scrollableRef?.current
- if (!scrollable) return
+ const scrollableRef: React.RefObject =
+ React.useRef(null);
+ const scrollButtonsRef: React.RefObject =
+ React.useRef(null);
+ const [hasScroll, setHasScroll] = React.useState(
+ null,
+ );
+ const [isKeyDowned, setIsKeyDowned] = React.useState(null);
+ const intervalRef = React.useRef(null);
- const hasLeftScroll = scrollable.scrollLeft > 0
- const hasRightScroll =
- scrollable.scrollWidth - scrollable.clientWidth > scrollable.scrollLeft
-
- setHasScroll({ left: hasLeftScroll, right: hasRightScroll })
- }, [setHasScroll])
-
- const scrollToTest = React.useCallback(
- (direction: "left" | "right") => {
- const element = scrollableRef?.current
- const scrollButtons = scrollButtonsRef?.current
- const scrollButtonsWith = scrollButtons?.clientWidth ?? 0
- const width = element?.clientWidth ?? 0
-
- if (element && enableLegendSlider) {
- element.scrollTo({
- left:
- direction === "left"
- ? element.scrollLeft - width + scrollButtonsWith
- : element.scrollLeft + width - scrollButtonsWith,
- behavior: "smooth",
- })
- setTimeout(() => {
- checkScroll()
- }, 400)
+ const checkScroll = React.useCallback(() => {
+ const scrollable = scrollableRef?.current;
+ if (!scrollable) {
+ return;
}
- },
- [enableLegendSlider, checkScroll],
- )
- React.useEffect(() => {
- const keyDownHandler = (key: string) => {
- if (key === "ArrowLeft") {
- scrollToTest("left")
- } else if (key === "ArrowRight") {
- scrollToTest("right")
+ const hasLeftScroll = scrollable.scrollLeft > 0;
+ const hasRightScroll =
+ scrollable.scrollWidth - scrollable.clientWidth > scrollable.scrollLeft;
+
+ setHasScroll({ left: hasLeftScroll, right: hasRightScroll });
+ }, [setHasScroll]);
+
+ const scrollToTest = React.useCallback(
+ (direction: "left" | "right") => {
+ const element = scrollableRef?.current;
+ const scrollButtons = scrollButtonsRef?.current;
+ const scrollButtonsWith = scrollButtons?.clientWidth ?? 0;
+ const width = element?.clientWidth ?? 0;
+
+ if (element && enableLegendSlider) {
+ element.scrollTo({
+ left:
+ direction === "left"
+ ? element.scrollLeft - width + scrollButtonsWith
+ : element.scrollLeft + width - scrollButtonsWith,
+ behavior: "smooth",
+ });
+ setTimeout(() => {
+ checkScroll();
+ }, 400);
+ }
+ },
+ [enableLegendSlider, checkScroll],
+ );
+
+ React.useEffect(() => {
+ const keyDownHandler = (key: string) => {
+ if (key === "ArrowLeft") {
+ scrollToTest("left");
+ } else if (key === "ArrowRight") {
+ scrollToTest("right");
+ }
+ };
+ if (isKeyDowned) {
+ keyDownHandler(isKeyDowned);
+ intervalRef.current = setInterval(() => {
+ keyDownHandler(isKeyDowned);
+ }, 300);
+ } else {
+ clearInterval(intervalRef.current!);
}
- }
- if (isKeyDowned) {
- keyDownHandler(isKeyDowned)
- intervalRef.current = setInterval(() => {
- keyDownHandler(isKeyDowned)
- }, 300)
- } else {
- clearInterval(intervalRef.current as NodeJS.Timeout)
- }
- return () => clearInterval(intervalRef.current as NodeJS.Timeout)
- }, [isKeyDowned, scrollToTest])
+ return () => {
+ return clearInterval(intervalRef.current as NodeJS.Timeout);
+ };
+ }, [isKeyDowned, scrollToTest]);
- const keyDown = (e: KeyboardEvent) => {
- e.stopPropagation()
- if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
- e.preventDefault()
- setIsKeyDowned(e.key)
- }
- }
- const keyUp = (e: KeyboardEvent) => {
- e.stopPropagation()
- setIsKeyDowned(null)
- }
+ const keyDown = (e: KeyboardEvent) => {
+ e.stopPropagation();
+ if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
+ e.preventDefault();
+ setIsKeyDowned(e.key);
+ }
+ };
+ const keyUp = (e: KeyboardEvent) => {
+ e.stopPropagation();
+ setIsKeyDowned(null);
+ };
- React.useEffect(() => {
- const scrollable = scrollableRef?.current
- if (enableLegendSlider) {
- checkScroll()
- scrollable?.addEventListener("keydown", keyDown)
- scrollable?.addEventListener("keyup", keyUp)
- }
+ React.useEffect(() => {
+ const scrollable = scrollableRef?.current;
+ if (enableLegendSlider) {
+ checkScroll();
+ scrollable?.addEventListener("keydown", keyDown);
+ scrollable?.addEventListener("keyup", keyUp);
+ }
- return () => {
- scrollable?.removeEventListener("keydown", keyDown)
- scrollable?.removeEventListener("keyup", keyUp)
- }
- }, [checkScroll, enableLegendSlider])
+ return () => {
+ scrollable?.removeEventListener("keydown", keyDown);
+ scrollable?.removeEventListener("keyup", keyUp);
+ };
+ }, [checkScroll, enableLegendSlider]);
- return (
-
-
- {categories.map((category, index) => (
-
- ))}
-
- {enableLegendSlider && (hasScroll?.right || hasScroll?.left) ? (
- <>
-
- {
- setIsKeyDowned(null)
- scrollToTest("left")
- }}
- disabled={!hasScroll?.left}
- />
- {
- setIsKeyDowned(null)
- scrollToTest("right")
- }}
- disabled={!hasScroll?.right}
- />
-
- >
- ) : null}
-
- )
-})
+
+ {categories.map((category, index) => {
+ return (
+
+ );
+ })}
+
+ {enableLegendSlider && (hasScroll?.right || hasScroll?.left) ? (
+ <>
+
+ {
+ setIsKeyDowned(null);
+ scrollToTest("left");
+ }}
+ disabled={!hasScroll?.left}
+ />
+ {
+ setIsKeyDowned(null);
+ scrollToTest("right");
+ }}
+ disabled={!hasScroll?.right}
+ />
+
+ >
+ ) : null}
+
+ );
+ },
+);
-Legend.displayName = "Legend"
+Legend.displayName = "Legend";
const ChartLegend = (
{ payload }: any,
@@ -324,18 +356,21 @@ const ChartLegend = (
legendPosition?: "left" | "center" | "right",
yAxisWidth?: number,
) => {
- const legendRef = React.useRef(null)
+ const legendRef = React.useRef(null);
useOnWindowResize(() => {
- const calculateHeight = (height: number | undefined) =>
- height ? Number(height) + 15 : 60
- setLegendHeight(calculateHeight(legendRef.current?.clientHeight))
- })
+ const calculateHeight = (height: number | undefined) => {
+ return height ? Number(height) + 15 : 60;
+ };
+ setLegendHeight(calculateHeight(legendRef.current?.clientHeight));
+ });
- const legendPayload = payload.filter((item: any) => item.type !== "none")
+ const legendPayload = payload.filter((item: any) => {
+ return item.type !== "none";
+ });
const paddingLeft =
- legendPosition === "left" && yAxisWidth ? yAxisWidth - 8 : 0
+ legendPosition === "left" && yAxisWidth ? yAxisWidth - 8 : 0;
return (
- )
-}
+ );
+};
//#region Tooltip
-type TooltipProps = Pick
+type TooltipProps = Pick;
type PayloadItem = {
- category: string
- value: number
- index: string
- color: AvailableChartColorsKeys
- type?: string
- payload: any
-}
+ category: string;
+ value: number;
+ index: string;
+ color: AvailableChartColorsKeys;
+ type?: string;
+ payload: any;
+};
interface ChartTooltipProps {
- active: boolean | undefined
- payload: PayloadItem[]
- label: string
- valueFormatter: (value: number) => string
+ active: boolean | undefined;
+ payload: PayloadItem[];
+ label: string;
+ valueFormatter: (value: number) => string;
}
const ChartTooltip = ({
@@ -388,7 +425,9 @@ const ChartTooltip = ({
valueFormatter,
}: ChartTooltipProps) => {
if (active && payload && payload.length) {
- const legendPayload = payload.filter((item: any) => item.type !== "none")
+ const legendPayload = payload.filter((item: any) => {
+ return item.type !== "none";
+ });
return (
- {legendPayload.map(({ value, category, color }, index) => (
-
-
-
+ {legendPayload.map(({ value, category, color }, index) => {
+ return (
+
+
- {category}
+ {valueFormatter(value)}
-
- {valueFormatter(value)}
-
-
- ))}
+ );
+ })}
- )
+ );
}
- return null
-}
+ return null;
+};
//#region LineChart
interface ActiveDot {
- index?: number
- dataKey?: string
+ index?: number;
+ dataKey?: string;
}
type BaseEventProps = {
- eventType: "dot" | "category"
- categoryClicked: string
- [key: string]: number | string
-}
+ eventType: "dot" | "category";
+ categoryClicked: string;
+ [key: string]: number | string;
+};
-type LineChartEventProps = BaseEventProps | null | undefined
+type LineChartEventProps = BaseEventProps | null | undefined;
interface LineChartProps extends React.HTMLAttributes {
- data: Record[]
- index: string
- categories: string[]
- colors?: AvailableChartColorsKeys[]
- valueFormatter?: (value: number) => string
- startEndOnly?: boolean
- showXAxis?: boolean
- showYAxis?: boolean
- showGridLines?: boolean
- yAxisWidth?: number
- intervalType?: "preserveStartEnd" | "equidistantPreserveStart"
- curve?: "linear" | "monotone"
- showTooltip?: boolean
- showLegend?: boolean
- autoMinValue?: boolean
- minValue?: number
- maxValue?: number
- allowDecimals?: boolean
- onValueChange?: (value: LineChartEventProps) => void
- enableLegendSlider?: boolean
- tickGap?: number
- connectNulls?: boolean
- xAxisLabel?: string
- yAxisLabel?: string
- legendPosition?: "left" | "center" | "right"
- tooltipCallback?: (tooltipCallbackContent: TooltipProps) => void
- customTooltip?: React.ComponentType
+ data: Record[];
+ index: string;
+ categories: string[];
+ colors?: AvailableChartColorsKeys[];
+ valueFormatter?: (value: number) => string;
+ startEndOnly?: boolean;
+ showXAxis?: boolean;
+ showYAxis?: boolean;
+ showGridLines?: boolean;
+ yAxisWidth?: number;
+ intervalType?: "preserveStartEnd" | "equidistantPreserveStart";
+ showTooltip?: boolean;
+ showLegend?: boolean;
+ autoMinValue?: boolean;
+ minValue?: number;
+ maxValue?: number;
+ allowDecimals?: boolean;
+ onValueChange?: (value: LineChartEventProps) => void;
+ enableLegendSlider?: boolean;
+ tickGap?: number;
+ connectNulls?: boolean;
+ xAxisLabel?: string;
+ yAxisLabel?: string;
+ legendPosition?: "left" | "center" | "right";
+ tooltipCallback?: (tooltipCallbackContent: TooltipProps) => void;
+ customTooltip?: React.ComponentType;
}
const LineChart = React.forwardRef(
@@ -508,7 +548,9 @@ const LineChart = React.forwardRef(
categories = [],
index,
colors = AvailableChartColors,
- valueFormatter = (value: number) => value.toString(),
+ valueFormatter = (value: number) => {
+ return value.toString();
+ },
startEndOnly = false,
showXAxis = true,
showYAxis = true,
@@ -532,28 +574,30 @@ const LineChart = React.forwardRef(
tooltipCallback,
customTooltip,
...other
- } = props
- const CustomTooltip = customTooltip
+ } = props;
+ const CustomTooltip = customTooltip;
const paddingValue =
- (!showXAxis && !showYAxis) || (startEndOnly && !showYAxis) ? 0 : 20
- const [legendHeight, setLegendHeight] = React.useState(60)
+ (!showXAxis && !showYAxis) || (startEndOnly && !showYAxis) ? 0 : 20;
+ const [legendHeight, setLegendHeight] = React.useState(60);
const [activeDot, setActiveDot] = React.useState(
undefined,
- )
+ );
const [activeLegend, setActiveLegend] = React.useState(
undefined,
- )
- const categoryColors = constructCategoryColors(categories, colors)
+ );
+ const categoryColors = constructCategoryColors(categories, colors);
- const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue)
- const hasOnValueChange = !!onValueChange
- const prevActiveRef = React.useRef(undefined)
- const prevLabelRef = React.useRef(undefined)
+ const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue);
+ const hasOnValueChange = Boolean(onValueChange);
+ const prevActiveRef = React.useRef(undefined);
+ const prevLabelRef = React.useRef(undefined);
function onDotClick(itemData: any, event: React.MouseEvent) {
- event.stopPropagation()
+ event.stopPropagation();
- if (!hasOnValueChange) return
+ if (!hasOnValueChange) {
+ return;
+ }
if (
(itemData.index === activeDot?.index &&
itemData.dataKey === activeDot?.dataKey) ||
@@ -561,41 +605,43 @@ const LineChart = React.forwardRef(
activeLegend &&
activeLegend === itemData.dataKey)
) {
- setActiveLegend(undefined)
- setActiveDot(undefined)
- onValueChange?.(null)
+ setActiveLegend(undefined);
+ setActiveDot(undefined);
+ onValueChange?.(null);
} else {
- setActiveLegend(itemData.dataKey)
+ setActiveLegend(itemData.dataKey);
setActiveDot({
index: itemData.index,
dataKey: itemData.dataKey,
- })
+ });
onValueChange?.({
eventType: "dot",
categoryClicked: itemData.dataKey,
...itemData.payload,
- })
+ });
}
}
function onCategoryClick(dataKey: string) {
- if (!hasOnValueChange) return
+ if (!hasOnValueChange) {
+ return;
+ }
if (
(dataKey === activeLegend && !activeDot) ||
(hasOnlyOneValueForKey(data, dataKey) &&
activeDot &&
activeDot.dataKey === dataKey)
) {
- setActiveLegend(undefined)
- onValueChange?.(null)
+ setActiveLegend(undefined);
+ onValueChange?.(null);
} else {
- setActiveLegend(dataKey)
+ setActiveLegend(dataKey);
onValueChange?.({
eventType: "category",
categoryClicked: dataKey,
- })
+ });
}
- setActiveDot(undefined)
+ setActiveDot(undefined);
}
return (
@@ -606,9 +652,9 @@ const LineChart = React.forwardRef(
onClick={
hasOnValueChange && (activeLegend || activeDot)
? () => {
- setActiveDot(undefined)
- setActiveLegend(undefined)
- onValueChange?.(null)
+ setActiveDot(undefined);
+ setActiveLegend(undefined);
+ onValueChange?.(null);
}
: undefined
}
@@ -634,7 +680,10 @@ const LineChart = React.forwardRef(
tick={{ transform: "translate(0, 6)" }}
ticks={
startEndOnly
- ? ([(data[0] as any)[index], (data[data.length - 1] as any)[index]] as any)
+ ? ([
+ (data[0] as any)[index],
+ (data[data.length - 1] as any)[index],
+ ] as any)
: undefined
}
fill=""
@@ -699,26 +748,28 @@ const LineChart = React.forwardRef(
position={{ y: 0 }}
content={({ active, payload, label }: any) => {
const cleanPayload: TooltipProps["payload"] = payload
- ? payload.map((item: any) => ({
- category: item.dataKey,
- value: item.value,
- index: item.payload[index],
- color: categoryColors.get(
- item.dataKey,
- ) as AvailableChartColorsKeys,
- type: item.type,
- payload: item.payload,
- }))
- : []
+ ? payload.map((item: any) => {
+ return {
+ category: item.dataKey,
+ value: item.value,
+ index: item.payload[index],
+ color: categoryColors.get(
+ item.dataKey,
+ ) as AvailableChartColorsKeys,
+ type: item.type,
+ payload: item.payload,
+ };
+ })
+ : [];
if (
tooltipCallback &&
(active !== prevActiveRef.current ||
label !== prevLabelRef.current)
) {
- tooltipCallback({ active, payload: cleanPayload, label })
- prevActiveRef.current = active
- prevLabelRef.current = label
+ tooltipCallback({ active, payload: cleanPayload, label });
+ prevActiveRef.current = active;
+ prevLabelRef.current = label;
}
return showTooltip && active ? (
@@ -736,7 +787,7 @@ const LineChart = React.forwardRef(
valueFormatter={valueFormatter}
/>
)
- ) : null
+ ) : null;
}}
/>
@@ -744,102 +795,50 @@ const LineChart = React.forwardRef(
- ChartLegend(
+ content={({ payload }: any) => {
+ return ChartLegend(
{ payload },
categoryColors,
setLegendHeight,
activeLegend,
hasOnValueChange
- ? (clickedLegendItem: string) =>
- onCategoryClick(clickedLegendItem)
+ ? (clickedLegendItem: string) => {
+ return onCategoryClick(clickedLegendItem);
+ }
: undefined,
enableLegendSlider,
legendPosition,
yAxisWidth,
- )
- }
+ );
+ }}
/>
) : null}
- {categories.map((category) => (
- {
- const {
- cx: cxCoord,
- cy: cyCoord,
- stroke,
- strokeLinecap,
- strokeLinejoin,
- strokeWidth,
- dataKey,
- } = props
- return (
- onDotClick(props, event)}
- />
- )
- }}
- dot={(props: any) => {
- const {
- stroke,
- strokeLinecap,
- strokeLinejoin,
- strokeWidth,
- cx: cxCoord,
- cy: cyCoord,
- dataKey,
- index,
- } = props
-
- if (
- (hasOnlyOneValueForKey(data, category) &&
- !(
- activeDot ||
- (activeLegend && activeLegend !== category)
- )) ||
- (activeDot?.index === index &&
- activeDot?.dataKey === category)
- ) {
+ {categories.map((category) => {
+ return (
+ {
+ const {
+ cx: cxCoord,
+ cy: cyCoord,
+ stroke,
+ strokeLinecap,
+ strokeLinejoin,
+ strokeWidth,
+ dataKey,
+ } = props;
return (
(
"fill",
),
)}
+ cx={cxCoord}
+ cy={cyCoord}
+ r={5}
+ fill=""
+ stroke={stroke}
+ strokeLinecap={strokeLinecap}
+ strokeLinejoin={strokeLinejoin}
+ strokeWidth={strokeWidth}
+ onClick={(_: any, event: any) => {
+ return onDotClick(props, event);
+ }}
/>
- )
- }
- return
- }}
- key={category}
- name={category}
- type="linear"
- dataKey={category}
- stroke=""
- strokeWidth={2}
- strokeLinejoin="round"
- strokeLinecap="round"
- isAnimationActive={false}
- connectNulls={connectNulls}
- />
- ))}
+ );
+ }}
+ dot={(props: any) => {
+ const {
+ stroke,
+ strokeLinecap,
+ strokeLinejoin,
+ strokeWidth,
+ cx: cxCoord,
+ cy: cyCoord,
+ dataKey,
+ index,
+ } = props;
+
+ if (
+ (hasOnlyOneValueForKey(data, category) &&
+ !(
+ activeDot ||
+ (activeLegend && activeLegend !== category)
+ )) ||
+ (activeDot?.index === index &&
+ activeDot?.dataKey === category)
+ ) {
+ return (
+
+ );
+ }
+ return ;
+ }}
+ key={category}
+ name={category}
+ type="linear"
+ dataKey={category}
+ stroke=""
+ strokeWidth={2}
+ strokeLinejoin="round"
+ strokeLinecap="round"
+ isAnimationActive={false}
+ connectNulls={connectNulls}
+ />
+ );
+ })}
{/* hidden lines to increase clickable target area */}
{onValueChange
- ? categories.map((category) => (
- {
- event.stopPropagation()
- const { name } = props
- onCategoryClick(name)
- }}
- />
- ))
+ ? categories.map((category) => {
+ return (
+ {
+ event.stopPropagation();
+ const { name } = props;
+ onCategoryClick(name);
+ }}
+ />
+ );
+ })
: null}
- )
+ );
},
-)
+);
-LineChart.displayName = "LineChart"
+LineChart.displayName = "LineChart";
-export { LineChart, type LineChartEventProps, type TooltipProps }
\ No newline at end of file
+export { LineChart, type LineChartEventProps, type TooltipProps };
diff --git a/Common/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts b/Common/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts
index 737feb8fe4..7fbff12928 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts
@@ -1,3 +1,3 @@
-export default interface ChartDataPoint {
- [x: string]: number | string;
-}
\ No newline at end of file
+export default interface ChartDataPoint {
+ [x: string]: number | string;
+}
diff --git a/Common/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts b/Common/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts
index 1b849b4138..dce18dce69 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Utils/ChartColors.ts
@@ -1,8 +1,12 @@
// Tremor Raw chartColors [v0.1.0]
-export type ColorUtility = "bg" | "stroke" | "fill" | "text"
+export type ColorUtility = "bg" | "stroke" | "fill" | "text";
-export const chartColors = {
+export const chartColors: {
+ [color: string]: {
+ [key in ColorUtility]: string;
+ };
+} = {
blue: {
bg: "bg-blue-500",
stroke: "stroke-blue-500",
@@ -69,28 +73,24 @@ export const chartColors = {
fill: "fill-rose-500",
text: "text-rose-500",
},
-} as const satisfies {
- [color: string]: {
- [key in ColorUtility]: string
- }
-}
+};
-export type AvailableChartColorsKeys = keyof typeof chartColors
+export type AvailableChartColorsKeys = keyof typeof chartColors;
export const AvailableChartColors: AvailableChartColorsKeys[] = Object.keys(
chartColors,
-) as Array
+) as Array;
export const constructCategoryColors = (
categories: string[],
colors: AvailableChartColorsKeys[],
): Map => {
- const categoryColors = new Map()
+ const categoryColors = new Map();
categories.forEach((category, index) => {
- categoryColors.set(category, colors[index % colors.length]!)
- })
- return categoryColors
-}
+ categoryColors.set(category, colors[index % colors.length]!);
+ });
+ return categoryColors;
+};
export const getColorClassName = (
color: AvailableChartColorsKeys,
@@ -101,6 +101,6 @@ export const getColorClassName = (
stroke: "stroke-gray-500",
fill: "fill-gray-500",
text: "text-gray-500",
- }
- return chartColors[color]?.[type] ?? fallbackColor[type]
-}
\ No newline at end of file
+ };
+ return chartColors[color]?.[type] ?? fallbackColor[type];
+};
diff --git a/Common/UI/Components/Charts/ChartLibrary/Utils/Cx.ts b/Common/UI/Components/Charts/ChartLibrary/Utils/Cx.ts
index 4003f49828..d1bea6ed1c 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Utils/Cx.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Utils/Cx.ts
@@ -1,8 +1,8 @@
// Tremor Raw cx [v0.0.0]
-import clsx, { type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import clsx, { type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
-export function cx(...args: ClassValue[]) {
- return twMerge(clsx(...args))
-}
\ No newline at end of file
+export function cx(...args: ClassValue[]): string {
+ return twMerge(clsx(...args));
+}
diff --git a/Common/UI/Components/Charts/ChartLibrary/Utils/GetYAxisDomain.ts b/Common/UI/Components/Charts/ChartLibrary/Utils/GetYAxisDomain.ts
index 29fa274a10..36bd188b37 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Utils/GetYAxisDomain.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Utils/GetYAxisDomain.ts
@@ -1,11 +1,11 @@
// Tremor Raw getYAxisDomain [v0.0.0]
-export const getYAxisDomain = (
- autoMinValue: boolean,
- minValue: number | undefined,
- maxValue: number | undefined,
- ) => {
- const minDomain = autoMinValue ? "auto" : (minValue ?? 0)
- const maxDomain = maxValue ?? "auto"
- return [minDomain, maxDomain]
- }
\ No newline at end of file
+export const getYAxisDomain: (autoMinValue: boolean, minValue: number | undefined, maxValue: number | undefined) => (number | "auto")[] = (
+ autoMinValue: boolean,
+ minValue: number | undefined,
+ maxValue: number | undefined,
+): (number | "auto")[] => {
+ const minDomain: number | "auto" = autoMinValue ? "auto" : minValue ?? 0;
+ const maxDomain: number | "auto" = maxValue ?? "auto";
+ return [minDomain, maxDomain];
+};
diff --git a/Common/UI/Components/Charts/ChartLibrary/Utils/HasOnlyOneValueForKey.ts b/Common/UI/Components/Charts/ChartLibrary/Utils/HasOnlyOneValueForKey.ts
index 0397554f21..017a386899 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Utils/HasOnlyOneValueForKey.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Utils/HasOnlyOneValueForKey.ts
@@ -1,19 +1,19 @@
// Tremor Raw hasOnlyOneValueForKey [v0.1.0]
export function hasOnlyOneValueForKey(
- array: any[],
- keyToCheck: string,
- ): boolean {
- const val: any[] = []
-
- for (const obj of array) {
- if (Object.prototype.hasOwnProperty.call(obj, keyToCheck)) {
- val.push(obj[keyToCheck])
- if (val.length > 1) {
- return false
- }
+ array: any[],
+ keyToCheck: string,
+): boolean {
+ const val: any[] = [];
+
+ for (const obj of array) {
+ if (Object.prototype.hasOwnProperty.call(obj, keyToCheck)) {
+ val.push(obj[keyToCheck]);
+ if (val.length > 1) {
+ return false;
}
}
-
- return true
- }
\ No newline at end of file
+ }
+
+ return true;
+}
diff --git a/Common/UI/Components/Charts/ChartLibrary/Utils/UseWindowOnResize.ts b/Common/UI/Components/Charts/ChartLibrary/Utils/UseWindowOnResize.ts
index 2d6fb5e9fd..90e4edbc33 100644
--- a/Common/UI/Components/Charts/ChartLibrary/Utils/UseWindowOnResize.ts
+++ b/Common/UI/Components/Charts/ChartLibrary/Utils/UseWindowOnResize.ts
@@ -1,15 +1,15 @@
-// Tremor Raw useOnWindowResize [v0.0.0]
+import * as React from "react";
-import * as React from "react"
-
-export const useOnWindowResize = (handler: { (): void }) => {
+export const useOnWindowResize: (handler: () => void) => void = (handler: () => void): void => {
React.useEffect(() => {
- const handleResize = () => {
- handler()
- }
- handleResize()
- window.addEventListener("resize", handleResize)
+ const handleResize: () => void = () => {
+ handler();
+ };
+ handleResize();
+ window.addEventListener("resize", handleResize);
- return () => window.removeEventListener("resize", handleResize)
- }, [handler])
-}
\ No newline at end of file
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
+ }, [handler]);
+};
diff --git a/Common/UI/Components/Charts/Line/LineChart.tsx b/Common/UI/Components/Charts/Line/LineChart.tsx
index 5065dee20b..e84fd1e5d9 100644
--- a/Common/UI/Components/Charts/Line/LineChart.tsx
+++ b/Common/UI/Components/Charts/Line/LineChart.tsx
@@ -7,7 +7,6 @@ import ChartCurve from "../Types/ChartCurve";
import ChartDataPoint from "../ChartLibrary/Types/ChartDataPoint";
import DataPointUtil from "../Utils/DataPoint";
-
export interface ComponentProps {
data: Array;
xAxis: XAxis;
@@ -19,6 +18,9 @@ export interface ComponentProps {
const LineChartElement: FunctionComponent = (
props: ComponentProps,
): ReactElement => {
+ if (!props.sync) {
+ return <>>;
+ }
const [records, setRecords] = React.useState>([]);
@@ -27,7 +29,6 @@ const LineChartElement: FunctionComponent = (
});
useEffect(() => {
-
if (!props.data || props.data.length === 0) {
setRecords([]);
}
@@ -35,14 +36,12 @@ const LineChartElement: FunctionComponent = (
const records: Array = DataPointUtil.getChartDataPoints({
seriesPoints: props.data,
xAxis: props.xAxis,
+ yAxis: props.yAxis,
});
setRecords(records);
-
}, [props.data]);
-
-
return (
= (
tickGap={1}
index={"Time"}
categories={categories}
- colors={["indigo", "rose", "emerald", "amber", "cyan", "gray", "pink", "lime", "fuchsia"]}
+ colors={[
+ "indigo",
+ "rose",
+ "emerald",
+ "amber",
+ "cyan",
+ "gray",
+ "pink",
+ "lime",
+ "fuchsia",
+ ]}
valueFormatter={props.yAxis.options.formatter || undefined}
showTooltip={true}
connectNulls={true}
yAxisWidth={60}
- onValueChange={(v) => {
- return console.log(v);
- }}
/>
);
};
diff --git a/Common/UI/Components/Charts/Types/XAxis/XAxis.ts b/Common/UI/Components/Charts/Types/XAxis/XAxis.ts
index a4be3397e9..8fb3cd9150 100644
--- a/Common/UI/Components/Charts/Types/XAxis/XAxis.ts
+++ b/Common/UI/Components/Charts/Types/XAxis/XAxis.ts
@@ -2,7 +2,7 @@ import XAxisMaxMin from "./XAxisMaxMin";
import XAxisType from "./XAxisType";
export enum XAxisAggregateType {
- Average = "Average",
+ Average = "Average",
Sum = "Sum",
Max = "Max",
Min = "Min",
diff --git a/Common/UI/Components/Charts/Types/YAxis/YAxis.ts b/Common/UI/Components/Charts/Types/YAxis/YAxis.ts
index ec8a8db873..594fe8fb76 100644
--- a/Common/UI/Components/Charts/Types/YAxis/YAxis.ts
+++ b/Common/UI/Components/Charts/Types/YAxis/YAxis.ts
@@ -13,7 +13,7 @@ export interface YAxisOptions {
min: YAxisMaxMin;
max: YAxisMaxMin;
formatter: (value: number) => string;
- precision:
+ precision: YAxisPrecision;
}
export default interface YAxis {
diff --git a/Common/UI/Components/Charts/Utils/DataPoint.ts b/Common/UI/Components/Charts/Utils/DataPoint.ts
index 02d9f20cf6..c5d161d989 100644
--- a/Common/UI/Components/Charts/Utils/DataPoint.ts
+++ b/Common/UI/Components/Charts/Utils/DataPoint.ts
@@ -1,6 +1,4 @@
-
-
-/// ChartDataPoint is in the format of:
+/// ChartDataPoint is in the format of:
// {
// date: "Feb 22",
// SolarPanels: 2756,
@@ -15,109 +13,176 @@ import XAxisMaxMin from "../Types/XAxis/XAxisMaxMin";
import YAxis, { YAxisPrecision } from "../Types/YAxis/YAxis";
import XAxisUtil from "./XAxis";
-
+interface SeriesData {
+ sum: number;
+ count: number;
+ max: number;
+ min: number;
+}
export default class DataPointUtil {
- public static getChartDataPoints(data: {
- seriesPoints: Array;
- xAxis: XAxis;
- yAxis: YAxis;
- }): Array {
+ public static getChartDataPoints(data: {
+ seriesPoints: Array;
+ xAxis: XAxis;
+ yAxis: YAxis;
+ }): Array {
+ const { xAxisLegend, intervals, formatter } = this.initializeXAxisData(
+ data.xAxis,
+ );
+ const arrayOfData: ChartDataPoint[] = this.initializeArrayOfData(
+ intervals,
+ xAxisLegend,
+ formatter,
+ );
+ const seriesDataMap: {
+ [key: string]: SeriesData;
+ } = this.processSeriesData(
+ data.seriesPoints,
+ arrayOfData,
+ xAxisLegend,
+ formatter,
+ data.xAxis.options.aggregateType,
+ );
+ this.formatSeriesData(
+ arrayOfData,
+ seriesDataMap,
+ data.yAxis.options.precision,
+ );
+ return arrayOfData;
+ }
- const xAxisMax: XAxisMaxMin = data.xAxis.options.max;
- const xAxisMin: XAxisMaxMin = data.xAxis.options.min;
-
- const xAxisLegend: string = data.xAxis.legend;
-
- const intervals: Array = XAxisUtil.getPrecisionIntervals({
- xAxisMax: xAxisMax,
- xAxisMin: xAxisMin
- });
-
- const formatter: (value: Date) => string = XAxisUtil.getFormatter({
- xAxisMax: xAxisMax,
- xAxisMin: xAxisMin
- });
-
- const arrayOfData: Array = [];
-
- // format all the intervals.
- for (const interval of intervals) {
- const dataPoint: ChartDataPoint = {};
- dataPoint[xAxisLegend] = formatter(interval);
- arrayOfData.push(dataPoint);
- }
-
- interface SeriesData {
- sum: number;
- count: number;
- max: number;
- min: number;
- }
-
- // Initialize a new data structure to store sum, count, max, and min for each series
- const seriesDataMap: { [key: string]: SeriesData } = {};
-
- // now we need to add the data points.
- for (const series of data.seriesPoints) {
- for (const dataPoint of series.data) {
- const date: Date = dataPoint.x;
- const value: number = dataPoint.y;
- const formattedDate: string = formatter(date);
-
- for (const chartDataPoint of arrayOfData) {
- if (chartDataPoint[xAxisLegend] === formattedDate) {
- // Initialize series data if it doesn't exist
- if (!seriesDataMap[series.seriesName]) {
- seriesDataMap[series.seriesName] = { sum: 0, count: 0, max: Number.NEGATIVE_INFINITY, min: Number.POSITIVE_INFINITY };
- }
-
- // Update sum, count, max, and min
- seriesDataMap[series.seriesName]!.sum += value;
- seriesDataMap[series.seriesName]!.count += 1;
- seriesDataMap[series.seriesName]!.max = Math.max(seriesDataMap[series.seriesName]!.max, value);
- seriesDataMap[series.seriesName]!.min = Math.min(seriesDataMap[series.seriesName]!.min, value);
-
- // Calculate the average, sum, max, or min based on the aggregate type
- if (data.xAxis.options.aggregateType === XAxisAggregateType.Average) {
- chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.sum / seriesDataMap[series.seriesName]!.count;
- } else if (data.xAxis.options.aggregateType === XAxisAggregateType.Sum) {
- chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.sum;
- } else if (data.xAxis.options.aggregateType === XAxisAggregateType.Max) {
- chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.max;
- } else if (data.xAxis.options.aggregateType === XAxisAggregateType.Min) {
- chartDataPoint[series.seriesName] = seriesDataMap[series.seriesName]!.min;
- } else {
- throw new BadDataException("Aggregate type not supported.");
- }
-
- if (chartDataPoint[series.seriesName] && typeof chartDataPoint[series.seriesName] === "number") {
-
- // Format the series data based on yAxis precision
- const yAxisPrecision = data.yAxis.options.precision;
- switch (yAxisPrecision) {
- case YAxisPrecision.NoDecimals:
- chartDataPoint[series.seriesName] = parseFloat((chartDataPoint[series.seriesName]! as number).toFixed(0));
- break;
- case YAxisPrecision.OneDecimal:
- chartDataPoint[series.seriesName] = parseFloat(((chartDataPoint[series.seriesName]! as number).toFixed(1)));
- break;
- case YAxisPrecision.TwoDecimals:
- chartDataPoint[series.seriesName] = parseFloat(((chartDataPoint[series.seriesName]! as number).toFixed(2)));
- break;
- case YAxisPrecision.ThreeDecimals:
- chartDataPoint[series.seriesName] = parseFloat(((chartDataPoint[series.seriesName]! as number).toFixed(3)))
- break;
- default:
- throw new BadDataException("YAxis precision not supported.");
- }
- }
- }
- }
- }
- }
-
- return arrayOfData;
+ private static initializeXAxisData(xAxis: XAxis): {
+ xAxisMax: XAxisMaxMin;
+ xAxisMin: XAxisMaxMin;
+ xAxisLegend: string;
+ intervals: Array;
+ formatter: (value: Date) => string;
+ } {
+ const xAxisMax: XAxisMaxMin = xAxis.options.max;
+ const xAxisMin: XAxisMaxMin = xAxis.options.min;
+ const xAxisLegend: string = xAxis.legend;
+ const intervals: Array = XAxisUtil.getPrecisionIntervals({
+ xAxisMax,
+ xAxisMin,
+ });
+ const formatter: (value: Date) => string = XAxisUtil.getFormatter({
+ xAxisMax,
+ xAxisMin,
+ });
+ return { xAxisMax, xAxisMin, xAxisLegend, intervals, formatter };
+ }
+ private static initializeArrayOfData(
+ intervals: Array,
+ xAxisLegend: string,
+ formatter: (value: Date) => string,
+ ): Array {
+ const arrayOfData: Array = [];
+ for (const interval of intervals) {
+ const dataPoint: ChartDataPoint = {};
+ dataPoint[xAxisLegend] = formatter(interval);
+ arrayOfData.push(dataPoint);
}
-}
\ No newline at end of file
+ return arrayOfData;
+ }
+
+ private static processSeriesData(
+ seriesPoints: Array,
+ arrayOfData: Array,
+ xAxisLegend: string,
+ formatter: (value: Date) => string,
+ aggregateType: XAxisAggregateType,
+ ): { [key: string]: SeriesData } {
+ const seriesDataMap: { [key: string]: SeriesData } = {};
+ for (const series of seriesPoints) {
+ for (const dataPoint of series.data) {
+ const date: Date = dataPoint.x;
+ const value: number = dataPoint.y;
+ const formattedDate: string = formatter(date);
+ for (const chartDataPoint of arrayOfData) {
+ if (chartDataPoint[xAxisLegend] === formattedDate) {
+ if (!seriesDataMap[series.seriesName]) {
+ seriesDataMap[series.seriesName] = {
+ sum: 0,
+ count: 0,
+ max: Number.NEGATIVE_INFINITY,
+ min: Number.POSITIVE_INFINITY,
+ };
+ }
+ seriesDataMap[series.seriesName]!.sum += value;
+ seriesDataMap[series.seriesName]!.count += 1;
+ seriesDataMap[series.seriesName]!.max = Math.max(
+ seriesDataMap[series.seriesName]!.max,
+ value,
+ );
+ seriesDataMap[series.seriesName]!.min = Math.min(
+ seriesDataMap[series.seriesName]!.min,
+ value,
+ );
+ chartDataPoint[series.seriesName] = this.calculateAggregate(
+ seriesDataMap[series.seriesName]!,
+ aggregateType,
+ );
+ }
+ }
+ }
+ }
+ return seriesDataMap;
+ }
+
+ private static calculateAggregate(
+ seriesData: SeriesData,
+ aggregateType: XAxisAggregateType,
+ ): number {
+ switch (aggregateType) {
+ case XAxisAggregateType.Average:
+ return seriesData.sum / seriesData.count;
+ case XAxisAggregateType.Sum:
+ return seriesData.sum;
+ case XAxisAggregateType.Max:
+ return seriesData.max;
+ case XAxisAggregateType.Min:
+ return seriesData.min;
+ default:
+ throw new BadDataException("Aggregate type not supported.");
+ }
+ }
+
+ private static formatSeriesData(
+ arrayOfData: Array,
+ seriesDataMap: { [key: string]: SeriesData },
+ yAxisPrecision: YAxisPrecision,
+ ): void {
+ for (const chartDataPoint of arrayOfData) {
+ for (const seriesName in seriesDataMap) {
+ if (
+ chartDataPoint[seriesName] &&
+ typeof chartDataPoint[seriesName] === "number"
+ ) {
+ chartDataPoint[seriesName] = this.formatValue(
+ chartDataPoint[seriesName] as number,
+ yAxisPrecision,
+ );
+ }
+ }
+ }
+ }
+
+ private static formatValue(
+ value: number,
+ yAxisPrecision: YAxisPrecision,
+ ): number {
+ switch (yAxisPrecision) {
+ case YAxisPrecision.NoDecimals:
+ return parseFloat(value.toFixed(0));
+ case YAxisPrecision.OneDecimal:
+ return parseFloat(value.toFixed(1));
+ case YAxisPrecision.TwoDecimals:
+ return parseFloat(value.toFixed(2));
+ case YAxisPrecision.ThreeDecimals:
+ return parseFloat(value.toFixed(3));
+ default:
+ throw new BadDataException("YAxis precision not supported.");
+ }
+ }
+}
diff --git a/Common/UI/Components/Charts/Utils/XAxis.ts b/Common/UI/Components/Charts/Utils/XAxis.ts
index 4cbb661230..98194c6135 100644
--- a/Common/UI/Components/Charts/Utils/XAxis.ts
+++ b/Common/UI/Components/Charts/Utils/XAxis.ts
@@ -3,207 +3,265 @@ import XAxisMaxMin from "../Types/XAxis/XAxisMaxMin";
import XAxisPrecision from "../Types/XAxis/XAxisPrecision";
export default class XAxisUtil {
- public static getPrecision(data: {
- xAxisMin: XAxisMaxMin,
- xAxisMax: XAxisMaxMin,
- }): XAxisPrecision {
-
- if (typeof data.xAxisMax === "number" || typeof data.xAxisMin === "number") {
- // number not yet supported.
- throw new NotImplementedException();
- }
-
- const startDate: Date = data.xAxisMin;
- const endDate: Date = data.xAxisMax;
-
- const totalMilliseconds = endDate.getTime() - startDate.getTime();
- const totalSeconds = totalMilliseconds / 1000;
- const totalMinutes = totalSeconds / 60;
- const totalHours = totalMinutes / 60;
- const totalDays = totalHours / 24;
- const totalWeeks = totalDays / 7;
- const totalMonths = totalDays / 30;
-
-
- if (totalSeconds <= 50) return XAxisPrecision.EVERY_SECOND;
- if (totalSeconds <= 250) return XAxisPrecision.EVERY_FIVE_SECONDS;
- if (totalSeconds <= 500) return XAxisPrecision.EVERY_TEN_SECONDS;
- if (totalSeconds <= 1500) return XAxisPrecision.EVERY_THIRTY_SECONDS;
- if (totalMinutes <= 50) return XAxisPrecision.EVERY_MINUTE;
- if (totalMinutes <= 250) return XAxisPrecision.EVERY_FIVE_MINUTES;
- if (totalMinutes <= 500) return XAxisPrecision.EVERY_TEN_MINUTES;
- if (totalMinutes <= 1500) return XAxisPrecision.EVERY_THIRTY_MINUTES;
- if (totalHours <= 50) return XAxisPrecision.EVERY_HOUR;
- if (totalHours <= 100) return XAxisPrecision.EVERY_TWO_HOURS;
- if (totalHours <= 150) return XAxisPrecision.EVERY_THREE_HOURS;
- if (totalHours <= 300) return XAxisPrecision.EVERY_SIX_HOURS;
- if (totalHours <= 600) return XAxisPrecision.EVERY_TWELVE_HOURS;
- if (totalDays <= 50) return XAxisPrecision.EVERY_DAY;
- if (totalDays <= 100) return XAxisPrecision.EVERY_TWO_DAYS;
- if (totalWeeks <= 50) return XAxisPrecision.EVERY_WEEK;
- if (totalWeeks <= 100) return XAxisPrecision.EVERY_TWO_WEEKS;
- if (totalMonths <= 50) return XAxisPrecision.EVERY_MONTH;
- if (totalMonths <= 100) return XAxisPrecision.EVERY_TWO_MONTHS;
- if (totalMonths <= 150) return XAxisPrecision.EVERY_THREE_MONTHS;
- if (totalMonths <= 300) return XAxisPrecision.EVERY_SIX_MONTHS;
- return XAxisPrecision.EVERY_YEAR;
-
+ public static getPrecision(data: {
+ xAxisMin: XAxisMaxMin;
+ xAxisMax: XAxisMaxMin;
+ }): XAxisPrecision {
+ if (
+ typeof data.xAxisMax === "number" ||
+ typeof data.xAxisMin === "number"
+ ) {
+ // number not yet supported.
+ throw new NotImplementedException();
}
- public static getPrecisionIntervals(data: {
- xAxisMin: XAxisMaxMin,
- xAxisMax: XAxisMaxMin,
- }): Array {
- const precision: XAxisPrecision = XAxisUtil.getPrecision(data);
+ const startDate: Date = data.xAxisMin as Date;
+ const endDate: Date = data.xAxisMax as Date;
- if (typeof data.xAxisMax === "number" || typeof data.xAxisMin === "number") {
- // number not yet supported.
- throw new NotImplementedException();
- }
+ const totalMilliseconds: number = endDate.getTime() - startDate.getTime();
+ const totalSeconds: number = totalMilliseconds / 1000;
+ const totalMinutes: number = totalSeconds / 60;
+ const totalHours: number = totalMinutes / 60;
+ const totalDays: number = totalHours / 24;
+ const totalWeeks: number = totalDays / 7;
+ const totalMonths: number = totalDays / 30;
- const startDate: Date = new Date(data.xAxisMin);
- const endDate: Date = new Date(data.xAxisMax);
- const intervals: Array = [];
+ if (totalSeconds <= 100) {
+ return XAxisPrecision.EVERY_SECOND;
+ }
+ if (totalSeconds <= 500) {
+ return XAxisPrecision.EVERY_FIVE_SECONDS;
+ }
+ if (totalSeconds <= 1000) {
+ return XAxisPrecision.EVERY_TEN_SECONDS;
+ }
+ if (totalSeconds <= 3000) {
+ return XAxisPrecision.EVERY_THIRTY_SECONDS;
+ }
+ if (totalMinutes <= 100) {
+ return XAxisPrecision.EVERY_MINUTE;
+ }
+ if (totalMinutes <= 500) {
+ return XAxisPrecision.EVERY_FIVE_MINUTES;
+ }
+ if (totalMinutes <= 1000) {
+ return XAxisPrecision.EVERY_TEN_MINUTES;
+ }
+ if (totalMinutes <= 3000) {
+ return XAxisPrecision.EVERY_THIRTY_MINUTES;
+ }
+ if (totalHours <= 100) {
+ return XAxisPrecision.EVERY_HOUR;
+ }
+ if (totalHours <= 200) {
+ return XAxisPrecision.EVERY_TWO_HOURS;
+ }
+ if (totalHours <= 300) {
+ return XAxisPrecision.EVERY_THREE_HOURS;
+ }
+ if (totalHours <= 600) {
+ return XAxisPrecision.EVERY_SIX_HOURS;
+ }
+ if (totalHours <= 1200) {
+ return XAxisPrecision.EVERY_TWELVE_HOURS;
+ }
+ if (totalDays <= 100) {
+ return XAxisPrecision.EVERY_DAY;
+ }
+ if (totalDays <= 200) {
+ return XAxisPrecision.EVERY_TWO_DAYS;
+ }
+ if (totalWeeks <= 100) {
+ return XAxisPrecision.EVERY_WEEK;
+ }
+ if (totalWeeks <= 200) {
+ return XAxisPrecision.EVERY_TWO_WEEKS;
+ }
+ if (totalMonths <= 100) {
+ return XAxisPrecision.EVERY_MONTH;
+ }
+ if (totalMonths <= 200) {
+ return XAxisPrecision.EVERY_TWO_MONTHS;
+ }
+ if (totalMonths <= 300) {
+ return XAxisPrecision.EVERY_THREE_MONTHS;
+ }
+ if (totalMonths <= 600) {
+ return XAxisPrecision.EVERY_SIX_MONTHS;
+ }
+ return XAxisPrecision.EVERY_YEAR;
+ }
- let currentDate = startDate;
+ public static getPrecisionIntervals(data: {
+ xAxisMin: XAxisMaxMin;
+ xAxisMax: XAxisMaxMin;
+ }): Array {
+ const precision: XAxisPrecision = XAxisUtil.getPrecision(data);
- while (currentDate <= endDate) {
- intervals.push(new Date(currentDate));
-
- switch (precision) {
- case XAxisPrecision.EVERY_SECOND:
- currentDate.setSeconds(currentDate.getSeconds() + 1);
- break;
- case XAxisPrecision.EVERY_FIVE_SECONDS:
- currentDate.setSeconds(currentDate.getSeconds() + 5);
- break;
- case XAxisPrecision.EVERY_TEN_SECONDS:
- currentDate.setSeconds(currentDate.getSeconds() + 10);
- break;
- case XAxisPrecision.EVERY_THIRTY_SECONDS:
- currentDate.setSeconds(currentDate.getSeconds() + 30);
- break;
- case XAxisPrecision.EVERY_MINUTE:
- currentDate.setMinutes(currentDate.getMinutes() + 1);
- break;
- case XAxisPrecision.EVERY_FIVE_MINUTES:
- currentDate.setMinutes(currentDate.getMinutes() + 5);
- break;
- case XAxisPrecision.EVERY_TEN_MINUTES:
- currentDate.setMinutes(currentDate.getMinutes() + 10);
- break;
- case XAxisPrecision.EVERY_THIRTY_MINUTES:
- currentDate.setMinutes(currentDate.getMinutes() + 30);
- break;
- case XAxisPrecision.EVERY_HOUR:
- currentDate.setHours(currentDate.getHours() + 1);
- break;
- case XAxisPrecision.EVERY_TWO_HOURS:
- currentDate.setHours(currentDate.getHours() + 2);
- break;
- case XAxisPrecision.EVERY_THREE_HOURS:
- currentDate.setHours(currentDate.getHours() + 3);
- break;
- case XAxisPrecision.EVERY_SIX_HOURS:
- currentDate.setHours(currentDate.getHours() + 6);
- break;
- case XAxisPrecision.EVERY_TWELVE_HOURS:
- currentDate.setHours(currentDate.getHours() + 12);
- break;
- case XAxisPrecision.EVERY_DAY:
- currentDate.setDate(currentDate.getDate() + 1);
- break;
- case XAxisPrecision.EVERY_TWO_DAYS:
- currentDate.setDate(currentDate.getDate() + 2);
- break;
- case XAxisPrecision.EVERY_WEEK:
- currentDate.setDate(currentDate.getDate() + 7);
- break;
- case XAxisPrecision.EVERY_TWO_WEEKS:
- currentDate.setDate(currentDate.getDate() + 14);
- break;
- case XAxisPrecision.EVERY_MONTH:
- currentDate.setMonth(currentDate.getMonth() + 1);
- break;
- case XAxisPrecision.EVERY_TWO_MONTHS:
- currentDate.setMonth(currentDate.getMonth() + 2);
- break;
- case XAxisPrecision.EVERY_THREE_MONTHS:
- currentDate.setMonth(currentDate.getMonth() + 3);
- break;
- case XAxisPrecision.EVERY_SIX_MONTHS:
- currentDate.setMonth(currentDate.getMonth() + 6);
- break;
- case XAxisPrecision.EVERY_YEAR:
- currentDate.setFullYear(currentDate.getFullYear() + 1);
- break;
- }
- }
-
- return intervals;
+ if (
+ typeof data.xAxisMax === "number" ||
+ typeof data.xAxisMin === "number"
+ ) {
+ // number not yet supported.
+ throw new NotImplementedException();
}
- public static getFormatter(data: {
- xAxisMin: XAxisMaxMin,
- xAxisMax: XAxisMaxMin,
- }): (value: Date) => string {
+ const startDate: Date = new Date(data.xAxisMin as Date);
+ const endDate: Date = new Date(data.xAxisMax as Date);
+ const intervals: Array = [];
- const precision: XAxisPrecision = XAxisUtil.getPrecision(data);
+ const currentDate: Date = new Date(startDate);
- switch (precision) {
- case XAxisPrecision.EVERY_SECOND:
- case XAxisPrecision.EVERY_FIVE_SECONDS:
- case XAxisPrecision.EVERY_TEN_SECONDS:
- case XAxisPrecision.EVERY_THIRTY_SECONDS:
- return (value: Date) => value.toISOString().substring(11, 19); // HH:mm:ss
- case XAxisPrecision.EVERY_MINUTE:
- case XAxisPrecision.EVERY_FIVE_MINUTES:
- case XAxisPrecision.EVERY_TEN_MINUTES:
- case XAxisPrecision.EVERY_THIRTY_MINUTES:
- return (value: Date) => value.toISOString().substring(11, 16); // HH:mm
- case XAxisPrecision.EVERY_HOUR:
- case XAxisPrecision.EVERY_TWO_HOURS:
- case XAxisPrecision.EVERY_THREE_HOURS:
- case XAxisPrecision.EVERY_SIX_HOURS:
- case XAxisPrecision.EVERY_TWELVE_HOURS:
- return (value: Date) => {
- const dateString = value.toISOString();
- const day = dateString.substring(8, 10);
- const month = value.toLocaleString('default', { month: 'short' });
- const hour = dateString.substring(11, 13);
- return `${day} ${month}, ${hour}:00`;
- }; // DD MMM, HH:00
- case XAxisPrecision.EVERY_DAY:
- case XAxisPrecision.EVERY_TWO_DAYS:
- return (value: Date) => {
- const dateString = value.toISOString();
- const day = dateString.substring(8, 10);
- const month = value.toLocaleString('default', { month: 'short' });
- return `${day} ${month}`;
- }; // DD MMM
- case XAxisPrecision.EVERY_WEEK:
- case XAxisPrecision.EVERY_TWO_WEEKS:
- return (value: Date) => {
- const dateString = value.toISOString();
- const day = dateString.substring(8, 10);
- const month = value.toLocaleString('default', { month: 'short' });
- return `${day} ${month}`;
- }; // DD MMM
- case XAxisPrecision.EVERY_MONTH:
- case XAxisPrecision.EVERY_TWO_MONTHS:
- case XAxisPrecision.EVERY_THREE_MONTHS:
- case XAxisPrecision.EVERY_SIX_MONTHS:
- return (value: Date) => {
- const dateString = value.toISOString();
- const day = dateString.substring(8, 10);
- const year = dateString.substring(0, 4);
- const month = value.toLocaleString('default', { month: 'short' });
- return `${day} ${month} ${year}`;
- }; // DD MMM
- case XAxisPrecision.EVERY_YEAR:
- return (value: Date) => value.toISOString().substring(0, 4); // YYYY
- default:
- throw new Error("Unsupported precision");
- }
+ while (currentDate <= endDate) {
+ intervals.push(new Date(currentDate));
+
+ switch (precision) {
+ case XAxisPrecision.EVERY_SECOND:
+ currentDate.setSeconds(currentDate.getSeconds() + 1);
+ break;
+ case XAxisPrecision.EVERY_FIVE_SECONDS:
+ currentDate.setSeconds(currentDate.getSeconds() + 5);
+ break;
+ case XAxisPrecision.EVERY_TEN_SECONDS:
+ currentDate.setSeconds(currentDate.getSeconds() + 10);
+ break;
+ case XAxisPrecision.EVERY_THIRTY_SECONDS:
+ currentDate.setSeconds(currentDate.getSeconds() + 30);
+ break;
+ case XAxisPrecision.EVERY_MINUTE:
+ currentDate.setMinutes(currentDate.getMinutes() + 1);
+ break;
+ case XAxisPrecision.EVERY_FIVE_MINUTES:
+ currentDate.setMinutes(currentDate.getMinutes() + 5);
+ break;
+ case XAxisPrecision.EVERY_TEN_MINUTES:
+ currentDate.setMinutes(currentDate.getMinutes() + 10);
+ break;
+ case XAxisPrecision.EVERY_THIRTY_MINUTES:
+ currentDate.setMinutes(currentDate.getMinutes() + 30);
+ break;
+ case XAxisPrecision.EVERY_HOUR:
+ currentDate.setHours(currentDate.getHours() + 1);
+ break;
+ case XAxisPrecision.EVERY_TWO_HOURS:
+ currentDate.setHours(currentDate.getHours() + 2);
+ break;
+ case XAxisPrecision.EVERY_THREE_HOURS:
+ currentDate.setHours(currentDate.getHours() + 3);
+ break;
+ case XAxisPrecision.EVERY_SIX_HOURS:
+ currentDate.setHours(currentDate.getHours() + 6);
+ break;
+ case XAxisPrecision.EVERY_TWELVE_HOURS:
+ currentDate.setHours(currentDate.getHours() + 12);
+ break;
+ case XAxisPrecision.EVERY_DAY:
+ currentDate.setDate(currentDate.getDate() + 1);
+ break;
+ case XAxisPrecision.EVERY_TWO_DAYS:
+ currentDate.setDate(currentDate.getDate() + 2);
+ break;
+ case XAxisPrecision.EVERY_WEEK:
+ currentDate.setDate(currentDate.getDate() + 7);
+ break;
+ case XAxisPrecision.EVERY_TWO_WEEKS:
+ currentDate.setDate(currentDate.getDate() + 14);
+ break;
+ case XAxisPrecision.EVERY_MONTH:
+ currentDate.setMonth(currentDate.getMonth() + 1);
+ break;
+ case XAxisPrecision.EVERY_TWO_MONTHS:
+ currentDate.setMonth(currentDate.getMonth() + 2);
+ break;
+ case XAxisPrecision.EVERY_THREE_MONTHS:
+ currentDate.setMonth(currentDate.getMonth() + 3);
+ break;
+ case XAxisPrecision.EVERY_SIX_MONTHS:
+ currentDate.setMonth(currentDate.getMonth() + 6);
+ break;
+ case XAxisPrecision.EVERY_YEAR:
+ currentDate.setFullYear(currentDate.getFullYear() + 1);
+ break;
+ }
}
-}
\ No newline at end of file
+
+ return intervals;
+ }
+
+ public static getFormatter(data: {
+ xAxisMin: XAxisMaxMin;
+ xAxisMax: XAxisMaxMin;
+ }): (value: Date) => string {
+ const precision: XAxisPrecision = XAxisUtil.getPrecision(data);
+
+ switch (precision) {
+ case XAxisPrecision.EVERY_SECOND:
+ case XAxisPrecision.EVERY_FIVE_SECONDS:
+ case XAxisPrecision.EVERY_TEN_SECONDS:
+ case XAxisPrecision.EVERY_THIRTY_SECONDS:
+ return (value: Date) => {
+ return value.toISOString().substring(11, 19);
+ }; // HH:mm:ss
+ case XAxisPrecision.EVERY_MINUTE:
+ case XAxisPrecision.EVERY_FIVE_MINUTES:
+ case XAxisPrecision.EVERY_TEN_MINUTES:
+ case XAxisPrecision.EVERY_THIRTY_MINUTES:
+ return (value: Date) => {
+ return value.toISOString().substring(11, 16);
+ }; // HH:mm
+ case XAxisPrecision.EVERY_HOUR:
+ case XAxisPrecision.EVERY_TWO_HOURS:
+ case XAxisPrecision.EVERY_THREE_HOURS:
+ case XAxisPrecision.EVERY_SIX_HOURS:
+ case XAxisPrecision.EVERY_TWELVE_HOURS:
+ return (value: Date) => {
+ const dateString: string = value.toISOString();
+ const day: string = dateString.substring(8, 10);
+ const month: string = value.toLocaleString("default", {
+ month: "short",
+ });
+ const hour: string = dateString.substring(11, 13);
+ return `${day} ${month}, ${hour}:00`;
+ }; // DD MMM, HH:00
+ case XAxisPrecision.EVERY_DAY:
+ case XAxisPrecision.EVERY_TWO_DAYS:
+ return (value: Date) => {
+ const dateString: string = value.toISOString();
+ const day: string = dateString.substring(8, 10);
+ const month: string = value.toLocaleString("default", {
+ month: "short",
+ });
+ return `${day} ${month}`;
+ }; // DD MMM
+ case XAxisPrecision.EVERY_WEEK:
+ case XAxisPrecision.EVERY_TWO_WEEKS:
+ return (value: Date) => {
+ const dateString: string = value.toISOString();
+ const day: string = dateString.substring(8, 10);
+ const month: string = value.toLocaleString("default", {
+ month: "short",
+ });
+ return `${day} ${month}`;
+ }; // DD MMM
+ case XAxisPrecision.EVERY_MONTH:
+ case XAxisPrecision.EVERY_TWO_MONTHS:
+ case XAxisPrecision.EVERY_THREE_MONTHS:
+ case XAxisPrecision.EVERY_SIX_MONTHS:
+ return (value: Date) => {
+ const dateString: string = value.toISOString();
+ const day: string = dateString.substring(8, 10);
+ const year: string = dateString.substring(0, 4);
+ const month: string = value.toLocaleString("default", {
+ month: "short",
+ });
+ return `${day} ${month} ${year}`;
+ }; // DD MMM
+ case XAxisPrecision.EVERY_YEAR:
+ return (value: Date) => {
+ return value.toISOString().substring(0, 4);
+ }; // YYYY
+ default:
+ throw new Error("Unsupported precision");
+ }
+ }
+}
diff --git a/Dashboard/src/Components/Metrics/MetricView.tsx b/Dashboard/src/Components/Metrics/MetricView.tsx
index 1d72241e7a..4022f82aec 100644
--- a/Dashboard/src/Components/Metrics/MetricView.tsx
+++ b/Dashboard/src/Components/Metrics/MetricView.tsx
@@ -29,7 +29,7 @@ import ModelAPI from "Common/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI";
import Metric from "Common/Models/AnalyticsModels/Metric";
import OneUptimeDate from "Common/Types/Date";
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
-import ComponentLoader from "Common/UI/Components/Compon\entLoader/ComponentLoader";
+import ComponentLoader from "Common/UI/Components/ComponentLoader/ComponentLoader";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import ChartGroup, {
Chart,
@@ -66,7 +66,6 @@ export interface ComponentProps {
const MetricView: FunctionComponent = (
props: ComponentProps,
): ReactElement => {
-
const [xAxisType, setXAxisType] = useState(XAxisType.Time);
const [chartStartDate, setChartStartDate] = useState(
@@ -135,7 +134,6 @@ const MetricView: FunctionComponent = (
return XAxisType.Date;
};
-
useEffect(() => {
fetchAggregatedResults().catch((err: Error) => {
setMetricResultsError(API.getFriendlyErrorMessage(err as Error));
@@ -158,29 +156,43 @@ const MetricView: FunctionComponent = (
continue;
}
- let xAxisAggregationType = XAxisAggregateType.Average;
+ let xAxisAggregationType: XAxisAggregateType = XAxisAggregateType.Average;
- if(queryConfig.metricQueryData.filterData.aggegationType === MetricsAggregationType.Sum) {
+ if (
+ queryConfig.metricQueryData.filterData.aggegationType ===
+ MetricsAggregationType.Sum
+ ) {
xAxisAggregationType = XAxisAggregateType.Sum;
}
- if(queryConfig.metricQueryData.filterData.aggegationType === MetricsAggregationType.Count) {
+ if (
+ queryConfig.metricQueryData.filterData.aggegationType ===
+ MetricsAggregationType.Count
+ ) {
xAxisAggregationType = XAxisAggregateType.Sum;
}
- if(queryConfig.metricQueryData.filterData.aggegationType === MetricsAggregationType.Max) {
+ if (
+ queryConfig.metricQueryData.filterData.aggegationType ===
+ MetricsAggregationType.Max
+ ) {
xAxisAggregationType = XAxisAggregateType.Max;
}
- if(queryConfig.metricQueryData.filterData.aggegationType === MetricsAggregationType.Min) {
+ if (
+ queryConfig.metricQueryData.filterData.aggegationType ===
+ MetricsAggregationType.Min
+ ) {
xAxisAggregationType = XAxisAggregateType.Min;
}
- if(queryConfig.metricQueryData.filterData.aggegationType === MetricsAggregationType.Avg) {
+ if (
+ queryConfig.metricQueryData.filterData.aggegationType ===
+ MetricsAggregationType.Avg
+ ) {
xAxisAggregationType = XAxisAggregateType.Average;
}
-
const chart: Chart = {
id: index.toString(),
type: ChartType.LINE,
diff --git a/Dashboard/src/Components/Monitor/MonitorCharts/MonitorChart.tsx b/Dashboard/src/Components/Monitor/MonitorCharts/MonitorChart.tsx
index c4b1478b05..12ba5866b7 100644
--- a/Dashboard/src/Components/Monitor/MonitorCharts/MonitorChart.tsx
+++ b/Dashboard/src/Components/Monitor/MonitorCharts/MonitorChart.tsx
@@ -14,9 +14,14 @@ import Probe from "Common/Models/DatabaseModels/Probe";
import DataPoint from "Common/UI/Components/Charts/Types/DataPoint";
import SeriesPoints from "Common/UI/Components/Charts/Types/SeriesPoints";
import YAxisType from "Common/UI/Components/Charts/Types/YAxis/YAxisType";
-import YAxis, { YAxisPrecision } from "Common/UI/Components/Charts/Types/YAxis/YAxis";
+import YAxis, {
+ YAxisPrecision,
+} from "Common/UI/Components/Charts/Types/YAxis/YAxis";
import XAxisType from "Common/UI/Components/Charts/Types/XAxis/XAxisType";
-import { XAxis, XAxisAggregateType } from "Common/UI/Components/Charts/Types/XAxis/XAxis";
+import {
+ XAxis,
+ XAxisAggregateType,
+} from "Common/UI/Components/Charts/Types/XAxis/XAxis";
import ChartCurve from "Common/UI/Components/Charts/Types/ChartCurve";
export class MonitorCharts {
@@ -259,31 +264,31 @@ export class MonitorCharts {
monitorMetricsByMinute: Array;
checkOn: CheckOn;
}): XAxis {
- const startTime: Date =
- data.monitorMetricsByMinute[0]?.createdAt! || undefined;
+ const startTime: Date =
+ data.monitorMetricsByMinute[0]!.createdAt! || undefined;
const endTime: Date =
- data.monitorMetricsByMinute[data.monitorMetricsByMinute.length - 1]
- ?.createdAt! || undefined;
+ data.monitorMetricsByMinute[data.monitorMetricsByMinute.length - 1]!
+ .createdAt! || undefined;
let xAxisAggregationType: XAxisAggregateType = XAxisAggregateType.Average;
- if(data.checkOn === CheckOn.ResponseStatusCode) {
+ if (data.checkOn === CheckOn.ResponseStatusCode) {
xAxisAggregationType = XAxisAggregateType.Max;
}
- if(data.checkOn === CheckOn.IsOnline) {
+ if (data.checkOn === CheckOn.IsOnline) {
xAxisAggregationType = XAxisAggregateType.Min;
}
- if(data.checkOn === CheckOn.ResponseTime) {
+ if (data.checkOn === CheckOn.ResponseTime) {
xAxisAggregationType = XAxisAggregateType.Average;
}
- if(
+ if (
data.checkOn === CheckOn.DiskUsagePercent ||
data.checkOn === CheckOn.MemoryUsagePercent ||
data.checkOn === CheckOn.CPUUsagePercent
- ){
+ ) {
xAxisAggregationType = XAxisAggregateType.Average;
}
@@ -309,7 +314,7 @@ export class MonitorCharts {
precision: YAxisPrecision.NoDecimals,
formatter: (value: number) => {
return `${value} ms`;
- }
+ },
},
};
} else if (data.checkOn === CheckOn.ResponseStatusCode) {
@@ -322,7 +327,7 @@ export class MonitorCharts {
precision: YAxisPrecision.NoDecimals,
formatter: (value: number) => {
return `${value}`;
- }
+ },
},
};
} else if (
@@ -339,7 +344,7 @@ export class MonitorCharts {
precision: YAxisPrecision.TwoDecimals,
formatter: (value: number) => {
return `${value}%`;
- }
+ },
},
};
}
@@ -353,7 +358,7 @@ export class MonitorCharts {
precision: YAxisPrecision.NoDecimals,
formatter: (value: number) => {
return `${value}`;
- }
+ },
},
};
}
diff --git a/eslint.config.js b/eslint.config.js
index b4ae69a974..5c5d22e190 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -204,6 +204,7 @@ export default tseslint.config(
module: true,
__dirname: true,
exports: true,
+ "NodeJS": true
},
parserOptions: {
project: ["./tsconfig.json"], // Specify it only for TypeScript files