strings and icons
This commit is contained in:
1 parent
79dfa886f1
commit
3208cc9e2c
4 files changed
+70
-27
No files matched your search
@@ -1,17 +1,25 @@
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { BaseChart } from "@/Components/v2/design-elements";
|
||||
import { TrendingUp, AlertTriangle } from "lucide-react";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDateWithTz } from "@/Utils/timeUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ResponsiveContainer, BarChart, XAxis, Bar, Cell, Tooltip } from "recharts";
|
||||
import { getResponseTimeColor } from "@/Utils/MonitorUtils";
|
||||
import type { GroupedCheck } from "@/Types/Check";
|
||||
import type { MonitorData } from "@/Types/Monitor";
|
||||
import type { RootState } from "@/Types/state";
|
||||
|
||||
const XLabel = ({ p1, p2, range }: { p1: any; p2: any; range: string }) => {
|
||||
interface XLabelProps {
|
||||
p1: GroupedCheck;
|
||||
p2: GroupedCheck;
|
||||
range: string;
|
||||
}
|
||||
|
||||
const XLabel = ({ p1, p2, range }: XLabelProps) => {
|
||||
const theme = useTheme();
|
||||
const uiTimezone = useSelector((state: any) => state.ui.timezone);
|
||||
const uiTimezone = useSelector((state: RootState) => state.ui.timezone);
|
||||
const dateFormat = range === "day" ? "MMM D, h:mm A" : "MMM D";
|
||||
return (
|
||||
<>
|
||||
@@ -23,7 +31,7 @@ const XLabel = ({ p1, p2, range }: { p1: any; p2: any; range: string }) => {
|
||||
fontSize={11}
|
||||
fill={theme.palette.text.secondary}
|
||||
>
|
||||
{formatDateWithTz(p1.bucketDate, dateFormat, uiTimezone)}
|
||||
{formatDateWithTz(p1._id, dateFormat, uiTimezone)}
|
||||
</text>
|
||||
<text
|
||||
x="100%"
|
||||
@@ -33,28 +41,45 @@ const XLabel = ({ p1, p2, range }: { p1: any; p2: any; range: string }) => {
|
||||
fontSize={11}
|
||||
fill={theme.palette.text.secondary}
|
||||
>
|
||||
{formatDateWithTz(p2.bucketDate, dateFormat, uiTimezone)}
|
||||
{formatDateWithTz(p2._id, dateFormat, uiTimezone)}
|
||||
</text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const HistogramStatus = ({ monitorData, checks = [], range }) => {
|
||||
console.log(checks);
|
||||
interface HistogramStatusProps {
|
||||
title: string;
|
||||
icon: React.ReactNode;
|
||||
monitorData?: MonitorData;
|
||||
checks?: GroupedCheck[];
|
||||
range: string;
|
||||
}
|
||||
|
||||
export const HistogramStatus = ({
|
||||
title,
|
||||
icon,
|
||||
monitorData,
|
||||
checks = [],
|
||||
range,
|
||||
}: HistogramStatusProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const CustomTooltip = ({ active, payload }: any) => {
|
||||
const uiTimezone = useSelector((state: any) => state.ui.timezone);
|
||||
const CustomTooltip = ({
|
||||
active,
|
||||
payload,
|
||||
}: {
|
||||
active?: boolean;
|
||||
payload?: Array<{ payload: GroupedCheck }>;
|
||||
}) => {
|
||||
const uiTimezone = useSelector((state: RootState) => state.ui.timezone);
|
||||
if (!active || !payload?.length) return null;
|
||||
const d = payload[0]?.payload as any & {
|
||||
avgResponseTime?: number;
|
||||
};
|
||||
const d = payload[0]?.payload;
|
||||
const avg = d?.avgResponseTime ?? 0;
|
||||
const titleText = t("common.charts.uptime.avgResponseTime");
|
||||
const titleText = t("common.charts.labels.averageRepsonseTime");
|
||||
const fmt = range === "30d" ? "MMM D, YYYY" : "ddd, MMM D, YYYY, h:mm A";
|
||||
let dateLabel = "";
|
||||
if (d?.bucketDate) {
|
||||
const base = new Date(d.bucketDate);
|
||||
if (d?._id) {
|
||||
const base = new Date(d._id);
|
||||
const midBucket =
|
||||
range === "30d" ? new Date(base.getTime() + 12 * 60 * 60 * 1000) : base;
|
||||
dateLabel = formatDateWithTz(midBucket.toISOString(), fmt, uiTimezone);
|
||||
@@ -83,10 +108,12 @@ export const HistogramStatus = ({ monitorData, checks = [], range }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const totalChecks = checks.reduce((acc, check) => acc + (check.totalChecks || 0), 0);
|
||||
|
||||
return (
|
||||
<BaseChart
|
||||
icon={<TrendingUp />}
|
||||
title={"Test"}
|
||||
icon={icon}
|
||||
title={title}
|
||||
>
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Stack
|
||||
@@ -95,7 +122,7 @@ export const HistogramStatus = ({ monitorData, checks = [], range }) => {
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Stack>
|
||||
<Typography>Checks: {"totalChecks"}</Typography>
|
||||
<Typography>Total checks: {totalChecks}</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<ResponsiveContainer
|
||||
|
||||
@@ -2,6 +2,7 @@ import { BasePage } from "@/Components/v2/design-elements";
|
||||
import { HeaderMonitorControls, HeaderTimeRange } from "@/Components/v2/common";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import { HistogramStatus } from "@/Components/v2/monitors";
|
||||
import { TrendingUp, AlertTriangle } from "lucide-react";
|
||||
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useIsAdmin } from "@/Hooks/useIsAdmin";
|
||||
@@ -14,6 +15,7 @@ import type { ChecksResponse } from "@/Types/Check";
|
||||
import type { RootState } from "@/Types/state";
|
||||
import { MonitorStatBoxes } from "@/Components/v2/monitors";
|
||||
import { formatDateWithTz } from "@/Utils/timeUtils";
|
||||
import { t } from "i18next";
|
||||
|
||||
const certificateDateFormat = "MMM D, YYYY h A";
|
||||
|
||||
@@ -120,10 +122,19 @@ const UptimeDetailsPage = () => {
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<HistogramStatus
|
||||
title={t("common.charts.labels.uptime")}
|
||||
icon={<TrendingUp />}
|
||||
monitorData={monitorData}
|
||||
checks={monitorData?.groupedUpChecks}
|
||||
range={dateRange}
|
||||
/>
|
||||
<HistogramStatus
|
||||
title={t("common.charts.labels.downtime")}
|
||||
icon={<AlertTriangle />}
|
||||
monitorData={monitorData}
|
||||
checks={monitorData?.groupedDownChecks}
|
||||
range={dateRange}
|
||||
/>
|
||||
</Stack>
|
||||
</BasePage>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Check } from "@/Types/Check";
|
||||
import type { Check, GroupedCheck } from "@/Types/Check";
|
||||
export type MonitorStatus = boolean | undefined;
|
||||
|
||||
export const MonitorTypes = [
|
||||
@@ -48,12 +48,6 @@ export interface MonitorsWithChecksResponse {
|
||||
summary: MonitorsSummary;
|
||||
}
|
||||
|
||||
export interface MonitorGroupedCheck {
|
||||
time: number;
|
||||
responseTime: number;
|
||||
originalResponseTime: number;
|
||||
totalChecks: number;
|
||||
}
|
||||
|
||||
export interface MonitorStats {
|
||||
id: string;
|
||||
@@ -72,10 +66,14 @@ export interface MonitorStats {
|
||||
|
||||
export interface MonitorData {
|
||||
monitor: Monitor;
|
||||
groupedChecks: MonitorGroupedCheck[];
|
||||
groupedChecks: GroupedCheck[];
|
||||
groupedUpChecks: GroupedCheck[];
|
||||
groupedDownChecks: GroupedCheck[];
|
||||
groupedAvgResponseTime: number;
|
||||
groupedUptimePercentage: number;
|
||||
}
|
||||
|
||||
export interface MonitorDetailsResponse {
|
||||
monitorData: MonitorData;
|
||||
monitorStats: MonitorStats;
|
||||
monitorStats: MonitorStats | null;
|
||||
}
|
||||
@@ -24,6 +24,13 @@
|
||||
"type": "Type"
|
||||
},
|
||||
"empty": "Nothing h"
|
||||
},
|
||||
"charts": {
|
||||
"labels": {
|
||||
"uptime": "Uptime",
|
||||
"downtime": "Downtime",
|
||||
"averageRepsonseTime": "Average response time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"submit": "Submit",
|
||||
|
||||
Reference in new issue
Block a user