mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-24 11:59:39 -05:00
checks route, checks table
This commit is contained in:
@@ -20,7 +20,7 @@ const getHeaders = (t: Function, uiTimezone: string) => {
|
||||
},
|
||||
{
|
||||
id: "date",
|
||||
content: t("pages.checks.table.headers.dateTime"),
|
||||
content: t("common.table.headers.dateTime"),
|
||||
render: (row) => {
|
||||
return formatDateWithTz(row.createdAt, "ddd, MMMM D, YYYY, HH:mm A", uiTimezone);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import { Table, Pagination, StatusLabel } from "@/Components/design-elements";
|
||||
import Box from "@mui/material/Box";
|
||||
import type { Header } from "@/Components/design-elements";
|
||||
import type { GeoCheck } from "@/Types/GeoCheck";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { formatDateWithTz } from "@/Utils/TimeUtils";
|
||||
import type { RootState } from "@/Types/state";
|
||||
import { useSelector } from "react-redux";
|
||||
import prettyMilliseconds from "pretty-ms";
|
||||
|
||||
const getHeaders = (t: Function, uiTimezone: string) => {
|
||||
const headers: Header<GeoCheck>[] = [
|
||||
{
|
||||
id: "status",
|
||||
content: t("common.table.headers.status"),
|
||||
render: (row) => {
|
||||
const firstResult = row.results[0];
|
||||
const status = firstResult?.status ? "up" : "down";
|
||||
return <StatusLabel status={status} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "date",
|
||||
content: t("common.table.headers.dateTime"),
|
||||
render: (row) => {
|
||||
return formatDateWithTz(row.createdAt, "ddd, MMMM D, YYYY, HH:mm A", uiTimezone);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "statusCode",
|
||||
content: t("pages.checks.table.headers.statusCode"),
|
||||
render: (row) => {
|
||||
const firstResult = row.results[0];
|
||||
return firstResult?.statusCode || "N/A";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "location",
|
||||
content: t("pages.checks.table.headers.location"),
|
||||
render: (row) => {
|
||||
const firstResult = row.results[0];
|
||||
if (!firstResult) return "N/A";
|
||||
const { continent, country, city } = firstResult.location;
|
||||
return `${continent} - ${country}, ${city}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "responseTime",
|
||||
content: t("common.table.headers.responseTime"),
|
||||
render: (row) => {
|
||||
const firstResult = row.results[0];
|
||||
if (!firstResult?.timings?.total) return "N/A";
|
||||
return prettyMilliseconds(firstResult.timings.total, { compact: true });
|
||||
},
|
||||
},
|
||||
];
|
||||
return headers;
|
||||
};
|
||||
|
||||
export const GeoChecksTable = ({
|
||||
geoChecks,
|
||||
count,
|
||||
page,
|
||||
setPage,
|
||||
rowsPerPage,
|
||||
setRowsPerPage,
|
||||
}: {
|
||||
geoChecks: GeoCheck[];
|
||||
count: number;
|
||||
page: number;
|
||||
setPage: (page: number) => void;
|
||||
rowsPerPage: number;
|
||||
setRowsPerPage: (rowsPerPage: number) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const uiTimezone = useSelector((state: RootState) => state.ui.timezone);
|
||||
const headers = getHeaders(t, uiTimezone);
|
||||
|
||||
const handlePageChange = (
|
||||
_e: React.MouseEvent<HTMLButtonElement> | null,
|
||||
newPage: number
|
||||
) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleRowsPerPageChange = (
|
||||
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
|
||||
) => {
|
||||
const value = Number(e.target.value);
|
||||
setPage(0);
|
||||
setRowsPerPage(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Table
|
||||
headers={headers}
|
||||
data={geoChecks}
|
||||
/>
|
||||
<Pagination
|
||||
component="div"
|
||||
count={count}
|
||||
page={page}
|
||||
rowsPerPage={rowsPerPage}
|
||||
onPageChange={handlePageChange}
|
||||
onRowsPerPageChange={handleRowsPerPageChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from "@/Components/monitors";
|
||||
import { TrendingUp, AlertTriangle } from "lucide-react";
|
||||
import { ChecksTable } from "@/Pages/Uptime/Details/Components/ChecksTable";
|
||||
import { GeoChecksTable } from "@/Pages/Uptime/Details/Components/GeoChecksTable";
|
||||
import { MonitorStatBoxes } from "@/Components/monitors";
|
||||
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
@@ -20,7 +21,7 @@ import { useSelector } from "react-redux";
|
||||
import { useGet } from "@/Hooks/UseApi";
|
||||
import type { MonitorDetailsResponse } from "@/Types/Monitor";
|
||||
import type { ChecksResponse } from "@/Types/Check";
|
||||
import type { GeoChecksResult, GeoContinent } from "@/Types/GeoCheck";
|
||||
import type { GeoChecksResult, GeoChecksResponse, GeoContinent } from "@/Types/GeoCheck";
|
||||
import type { RootState } from "@/Types/state";
|
||||
import { formatDateWithTz } from "@/Utils/TimeUtils";
|
||||
import { t } from "i18next";
|
||||
@@ -40,6 +41,8 @@ const UptimeDetailsPage = () => {
|
||||
|
||||
const [page, setPage] = useState<number>(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState<number>(5);
|
||||
const [geoPage, setGeoPage] = useState<number>(0);
|
||||
const [geoRowsPerPage, setGeoRowsPerPage] = useState<number>(5);
|
||||
const [dateRange, setDateRange] = useState<string>("recent");
|
||||
const [selectedLocation, setSelectedLocation] = useState<GeoContinent>("NA");
|
||||
|
||||
@@ -113,7 +116,6 @@ const UptimeDetailsPage = () => {
|
||||
{ keepPreviousData: true, revalidateOnFocus: false }
|
||||
);
|
||||
|
||||
// Geo checks fetch - only for HTTP monitors with geo checks enabled
|
||||
const geoChecksUrl = useMemo(() => {
|
||||
if (!monitorId || monitor?.type !== "http" || !monitor?.geoCheckEnabled) {
|
||||
return null;
|
||||
@@ -124,14 +126,46 @@ const UptimeDetailsPage = () => {
|
||||
return `/monitors/${monitorId}/geo-checks?${params.toString()}`;
|
||||
}, [monitorId, monitor?.type, monitor?.geoCheckEnabled, dateRange, selectedLocation]);
|
||||
|
||||
const { data: _geoChecksData, isLoading: _geoChecksIsLoading } =
|
||||
useGet<GeoChecksResult>(
|
||||
geoChecksUrl,
|
||||
{},
|
||||
{ keepPreviousData: true, revalidateOnFocus: false }
|
||||
);
|
||||
const { data: geoGroupedData } = useGet<GeoChecksResult>(
|
||||
geoChecksUrl,
|
||||
{},
|
||||
{ keepPreviousData: true, revalidateOnFocus: false }
|
||||
);
|
||||
|
||||
const geoChecks = _geoChecksData?.groupedGeoChecks ?? [];
|
||||
const geoGroupedChecks = geoGroupedData?.groupedGeoChecks ?? [];
|
||||
|
||||
// Fetch paginated geo checks for the table
|
||||
const geoChecksTableUrl = useMemo(() => {
|
||||
if (!monitorId || monitor?.type !== "http" || !monitor?.geoCheckEnabled) {
|
||||
return null;
|
||||
}
|
||||
const params = new URLSearchParams();
|
||||
params.append("sortOrder", "desc");
|
||||
params.append("dateRange", dateRange);
|
||||
params.append("page", String(geoPage));
|
||||
params.append("rowsPerPage", String(geoRowsPerPage));
|
||||
if (selectedLocation) {
|
||||
params.append("continent", selectedLocation);
|
||||
}
|
||||
return `/geo-checks/${monitorId}?${params.toString()}`;
|
||||
}, [
|
||||
monitorId,
|
||||
monitor?.type,
|
||||
monitor?.geoCheckEnabled,
|
||||
dateRange,
|
||||
geoPage,
|
||||
geoRowsPerPage,
|
||||
selectedLocation,
|
||||
]);
|
||||
|
||||
const { data: geoChecksTableData } = useGet<GeoChecksResponse>(
|
||||
geoChecksTableUrl,
|
||||
{},
|
||||
{ keepPreviousData: true, revalidateOnFocus: false }
|
||||
);
|
||||
|
||||
const geoChecksForTable = geoChecksTableData?.geoChecks ?? [];
|
||||
const geoChecksCount = geoChecksTableData?.geoChecksCount ?? 0;
|
||||
|
||||
// Extract unique locations from geo checks data
|
||||
const geoLocations = monitor?.geoCheckLocations;
|
||||
@@ -203,9 +237,17 @@ const UptimeDetailsPage = () => {
|
||||
onLocationChange={setSelectedLocation}
|
||||
/>
|
||||
<HistogramDetails
|
||||
checks={geoChecks}
|
||||
checks={geoGroupedChecks}
|
||||
range={dateRange}
|
||||
/>
|
||||
<GeoChecksTable
|
||||
geoChecks={geoChecksForTable}
|
||||
count={geoChecksCount}
|
||||
page={geoPage}
|
||||
setPage={setGeoPage}
|
||||
rowsPerPage={geoRowsPerPage}
|
||||
setRowsPerPage={setGeoRowsPerPage}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</BasePage>
|
||||
|
||||
@@ -55,3 +55,8 @@ export interface GeoChecksResult {
|
||||
monitorType: string;
|
||||
groupedGeoChecks: GroupedGeoCheck[];
|
||||
}
|
||||
|
||||
export interface GeoChecksResponse {
|
||||
geoChecks: GeoCheck[];
|
||||
geoChecksCount: number;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
"type": "Type",
|
||||
"url": "Url",
|
||||
"interval": "Interval",
|
||||
"active": "Active"
|
||||
"active": "Active",
|
||||
"responseTime": "Response time"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -372,8 +373,8 @@
|
||||
"table": {
|
||||
"empty": "No down checks in this time range",
|
||||
"headers": {
|
||||
"dateTime": "Date & time",
|
||||
"statusCode": "Status code"
|
||||
"statusCode": "Status code",
|
||||
"location": "Location"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user