extract header

This commit is contained in:
Alex Holliday
2026-02-11 20:11:22 +00:00
parent cbd8b5db47
commit 4b1c588f5a
13 changed files with 105 additions and 114 deletions
@@ -105,6 +105,29 @@ export const PausedStatusBox = ({ n }: { n: number }) => {
/>
);
};
export const MaintenanceStatusBox = ({ n }: { n: number }) => {
const theme = useTheme();
const { t } = useTranslation();
return (
<StatusBox
label={t("pages.common.monitors.status.maintenance")}
n={n}
color={theme.palette.warning.light}
/>
);
};
export const InitializingStatusBox = ({ n }: { n: number }) => {
const theme = useTheme();
const { t } = useTranslation();
return (
<StatusBox
label={t("pages.common.monitors.status.initializing")}
n={n}
color={theme.palette.warning.light}
/>
);
};
export const TotalChecksBox = ({ n }: { n: number }) => {
const theme = useTheme();
const { t } = useTranslation();
@@ -138,15 +161,3 @@ export const UpChecksBox = ({ n }: { n: number }) => {
/>
);
};
export const InitializingStatusBox = ({ n }: { n: number }) => {
const theme = useTheme();
const { t } = useTranslation();
return (
<StatusBox
label={t("pages.common.monitors.status.initializing")}
n={n}
color={theme.palette.warning.light}
/>
);
};
@@ -11,33 +11,24 @@ import { useTranslation } from "react-i18next";
export const ValueTypes = ["positive", "negative", "neutral"] as const;
export type ValueType = (typeof ValueTypes)[number];
export const StatusLabel = ({
status,
isActive,
sx,
}: {
status: MonitorStatus;
isActive?: boolean;
sx?: SxProps;
}) => {
export const StatusLabel = ({ status, sx }: { status: MonitorStatus; sx?: SxProps }) => {
const { t } = useTranslation();
const theme = useTheme();
const palette = getStatusPalette(status);
const determineStatus = (
isActive: boolean | undefined,
status: MonitorStatus
): string => {
if (isActive === false) {
const determineStatus = (status: MonitorStatus): string => {
if (status === "up") {
return t("pages.common.monitors.status.up");
} else if (status === "down") {
return t("pages.common.monitors.status.down");
} else if (status === "maintenance") {
return t("pages.common.monitors.status.maintenance");
} else if (status === "paused") {
return t("pages.common.monitors.status.paused");
} else if (status === "initializing") {
return t("pages.common.monitors.status.initializing");
}
if (status === true) {
return t("pages.common.monitors.status.up");
}
if (status === false) {
return t("pages.common.monitors.status.down");
}
return t("pages.common.monitors.status.initializing");
};
@@ -64,9 +55,7 @@ export const StatusLabel = ({
borderRadius="50%"
marginRight="5px"
/>
<Typography textTransform={"capitalize"}>
{determineStatus(isActive, status)}
</Typography>
<Typography textTransform={"capitalize"}>{determineStatus(status)}</Typography>
</BaseBox>
);
};
@@ -0,0 +1,29 @@
import {
UpStatusBox,
DownStatusBox,
PausedStatusBox,
InitializingStatusBox,
} from "@/Components/v2/design-elements";
import Stack from "@mui/material/Stack";
import type { MonitorsSummary } from "@/Types/Monitor";
import { useTheme } from "@mui/material";
interface MonitorsSummaryProps {
summary: MonitorsSummary | null;
}
export const HeaderMonitorsSummary = ({ summary }: MonitorsSummaryProps) => {
const theme = useTheme();
return (
<Stack
direction={{ xs: "column", md: "row" }}
gap={theme.spacing(8)}
>
<UpStatusBox n={summary?.upMonitors || 0} />
<DownStatusBox n={summary?.downMonitors || 0} />
<PausedStatusBox n={summary?.pausedMonitors || 0} />
<InitializingStatusBox n={summary?.initializingMonitors || 0} />
</Stack>
);
};
@@ -11,3 +11,4 @@ export * from "./charts/PiePageSpeedLegend";
export * from "./charts/HistogramPageSpeedDetails";
export * from "./charts/HistogramPageSpeedDetailsTooltip";
export * from "./charts/HistogramInfrastructure";
export * from "./HeaderMonitorsSummary";
@@ -1,13 +1,8 @@
import Stack from "@mui/material/Stack";
import useMediaQuery from "@mui/material/useMediaQuery";
import {
MonitorBasePageWithStates,
UpStatusBox,
DownStatusBox,
PausedStatusBox,
} from "@/Components/v2/design-elements";
import { MonitorBasePageWithStates } from "@/Components/v2/design-elements";
import { HeaderCreate } from "@/Components/v2/common";
import { ControlsFilter } from "@/Components/v2/monitors";
import { ControlsFilter, HeaderMonitorsSummary } from "@/Components/v2/monitors";
import { TextField, Dialog } from "@/Components/v2/inputs";
import { useGet, useDelete } from "@/Hooks/UseApi";
@@ -99,7 +94,7 @@ const InfrastructureMonitors = () => {
{ refreshInterval: 5000, keepPreviousData: true }
);
const { summary, count } = monitorsWithChecksData ?? {};
const { summary, count } = monitorsWithChecksData ?? { summary: null, count: 0 };
const isLoading = monitorsWithChecksLoading;
// Check if any filters are active
@@ -138,14 +133,7 @@ const InfrastructureMonitors = () => {
isLoading={isLoading}
isAdmin={isAdmin}
/>
<Stack
direction={isSmall ? "column" : "row"}
gap={theme.spacing(8)}
>
<UpStatusBox n={summary?.upMonitors || 0} />
<DownStatusBox n={summary?.downMonitors || 0} />
<PausedStatusBox n={summary?.pausedMonitors || 0} />
</Stack>
<HeaderMonitorsSummary summary={summary} />
<Stack
direction={isSmall ? "column" : "row"}
justifyContent={isSmall ? "flex-start" : "space-between"}
+4 -16
View File
@@ -1,27 +1,22 @@
import {
MonitorBasePageWithStates,
UpStatusBox,
DownStatusBox,
PausedStatusBox,
PageSpeedKeyPriorityFallback,
} from "@/Components/v2/design-elements";
import { Dialog } from "@/Components/v2/inputs";
import { HeaderCreate } from "@/Components/v2/common";
import Stack from "@mui/material/Stack";
import { PageSpeedMonitorsTable } from "@/Pages/PageSpeed/Monitors/Components/PageSpeedMonitorsTable";
import type { Monitor } from "@/Types/Monitor";
import { useTheme } from "@mui/material";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import { useIsAdmin } from "@/Hooks/useIsAdmin";
import { useGet, useDelete } from "@/Hooks/UseApi";
import type { MonitorsWithChecksResponse } from "@/Types/Monitor";
import type { AppSettingsResponse } from "@/Types/Settings";
import { HeaderMonitorsSummary } from "@/Components/v2/monitors";
const PageSpeedMonitorsPage = () => {
const { t } = useTranslation();
const theme = useTheme();
const isAdmin = useIsAdmin();
const { deleteFn, loading: isDeleting } = useDelete();
@@ -48,8 +43,8 @@ const PageSpeedMonitorsPage = () => {
const [rowsPerPage, setRowsPerPage] = useState(10);
const monitors = monitorsData?.monitors;
const monitorsCount = monitorsData?.count;
const summary = monitorsData?.summary;
const monitorsCount = monitorsData?.count ?? 0;
const summary = monitorsData?.summary ?? null;
const isLoading = monitorsIsLoading || settingsIsLoading;
@@ -80,14 +75,7 @@ const PageSpeedMonitorsPage = () => {
isLoading={isLoading}
isAdmin={isAdmin}
/>
<Stack
direction={{ xs: "column", md: "row" }}
gap={theme.spacing(8)}
>
<UpStatusBox n={summary?.upMonitors || 0} />
<DownStatusBox n={summary?.downMonitors || 0} />
<PausedStatusBox n={summary?.pausedMonitors || 0} />
</Stack>
<HeaderMonitorsSummary summary={summary} />
<PageSpeedMonitorsTable
monitors={monitors || []}
refetch={refetch}
@@ -7,7 +7,6 @@ import { StatusLabel, BaseBox } from "@/Components/v2/design-elements";
import { SwitchComponent } from "@/Components/v2/inputs";
import { useTheme } from "@mui/material/styles";
import { determineState } from "@/Utils/MonitorUtils";
import { useSelector } from "react-redux";
import { useState } from "react";
import type { Monitor } from "@/Types/Monitor";
@@ -54,7 +53,6 @@ export const MonitorsList = ({ statusPage, monitors }: MonitorsListProps) => {
)}
{monitors?.map((monitor) => {
const status = determineState(monitor);
return (
<BaseBox
key={monitor.id}
@@ -87,10 +85,7 @@ export const MonitorsList = ({ statusPage, monitors }: MonitorsListProps) => {
</Typography>
)}
</Box>
<StatusLabel
status={status === "up"}
isActive={monitor.isActive}
/>
<StatusLabel status={monitor.status} />
</Stack>
{statusPage.showCharts !== false && (
<Box sx={{ overflow: "hidden", minWidth: 0, flex: 1 }}>
@@ -12,16 +12,16 @@ const getMonitorStatus = (monitors: Monitor[], theme: Theme, t: Function) => {
icon: <AlertTriangle size={24} />,
};
if (monitors.every((monitor) => monitor.status === true)) {
if (monitors.every((monitor) => monitor.status === "up")) {
monitorsStatus.msg = t("pages.statusPages.statusBar.allUp");
monitorsStatus.color = theme.palette.success.main;
monitorsStatus.icon = <CircleCheck size={24} />;
return monitorsStatus;
} else if (monitors.every((monitor) => monitor.status === false)) {
} else if (monitors.every((monitor) => monitor.status === "down")) {
monitorsStatus.msg = t("pages.statusPages.statusBar.allDown");
monitorsStatus.color = theme.palette.error.main;
return monitorsStatus;
} else if (monitors.some((monitor) => monitor.status === false)) {
} else if (monitors.some((monitor) => monitor.status === "down")) {
monitorsStatus.msg = t("pages.statusPages.statusBar.degraded");
monitorsStatus.color = theme.palette.warning.main;
return monitorsStatus;
@@ -186,12 +186,7 @@ export const MonitorTable = ({
</Stack>
),
render: (row) => {
return (
<StatusLabel
status={row.status}
isActive={row.isActive}
/>
);
return <StatusLabel status={row.status} />;
},
},
{
+9 -16
View File
@@ -1,10 +1,5 @@
import { ControlsFilter } from "@/Components/v2/monitors";
import {
MonitorBasePageWithStates,
UpStatusBox,
DownStatusBox,
PausedStatusBox,
} from "@/Components/v2/design-elements";
import { ControlsFilter, HeaderMonitorsSummary } from "@/Components/v2/monitors";
import { MonitorBasePageWithStates } from "@/Components/v2/design-elements";
import { TextField, Dialog } from "@/Components/v2/inputs";
import Stack from "@mui/material/Stack";
import { MonitorTable } from "@/Pages/Uptime/Monitors/Components/UptimeMonitorsTable";
@@ -99,7 +94,11 @@ const UptimeMonitorsPage = () => {
{ refreshInterval: 5000, keepPreviousData: true }
);
const { monitors: monitorsWithChecks, summary, count } = monitorsWithChecksData ?? {};
const {
monitors: monitorsWithChecks,
summary,
count,
} = monitorsWithChecksData ?? { monitors: null, summary: null, count: 0 };
// Delete hook
const { deleteFn, loading: isDeleting } = useDelete();
@@ -150,14 +149,8 @@ const UptimeMonitorsPage = () => {
isLoading={isLoading}
isAdmin={isAdmin}
/>
<Stack
direction={isSmall ? "column" : "row"}
gap={theme.spacing(8)}
>
<UpStatusBox n={summary?.upMonitors || 0} />
<DownStatusBox n={summary?.downMonitors || 0} />
<PausedStatusBox n={summary?.pausedMonitors || 0} />
</Stack>
<HeaderMonitorsSummary summary={summary} />
<Stack
direction={isSmall ? "column" : "row"}
+10 -2
View File
@@ -1,5 +1,4 @@
import type { GroupedCheck, CheckSnapshot } from "@/Types/Check";
export type MonitorStatus = boolean | undefined;
export const MonitorTypes = [
"http",
@@ -13,6 +12,15 @@ export const MonitorTypes = [
] as const;
export type MonitorType = (typeof MonitorTypes)[number];
export const MonitorStatuses = [
"up",
"down",
"paused",
"initializing",
"maintenance",
] as const;
export type MonitorStatus = (typeof MonitorStatuses)[number];
export interface MonitorThresholds {
usage_cpu?: number;
usage_memory?: number;
@@ -28,7 +36,7 @@ export interface Monitor {
teamId: string;
name: string;
description?: string;
status?: boolean;
status: MonitorStatus;
statusWindow: boolean[];
statusWindowSize: number;
statusWindowThreshold: number;
+7 -14
View File
@@ -2,13 +2,6 @@ import type { Monitor, MonitorStatus, MonitorType } from "@/Types/Monitor";
import type { PaletteKey } from "@/Utils/Theme/v2Theme";
import type { ValueType } from "@/Components/v2/design-elements/StatusLabel";
export const determineState = (monitor: Monitor) => {
if (typeof monitor === "undefined") return "pending";
if (monitor?.isActive === false) return "paused";
if (monitor?.status === undefined) return "pending";
return monitor?.status == true ? "up" : "down";
};
export const getMonitorPath = (type: MonitorType): string => {
const pathMap: Record<MonitorType, string> = {
http: "uptime",
@@ -24,10 +17,10 @@ export const getMonitorPath = (type: MonitorType): string => {
};
export const getStatusPalette = (status: MonitorStatus): PaletteKey => {
if (status === true) {
if (status === "up") {
return "success";
}
if (status === false) {
if (status === "down") {
return "error";
}
return "warning";
@@ -43,11 +36,11 @@ export const getValuePalette = (value: ValueType): PaletteKey => {
};
export const getStatusColor = (status: MonitorStatus, theme: any): string => {
if (status === true) {
if (status === "up") {
return theme.palette.success.light;
}
if (status === false) {
if (status === "down") {
return theme.palette.error.light;
}
@@ -101,9 +94,9 @@ export const getStatusPageHeaderConfig = (
return { paletteKey: "error", message: "No monitors available" };
}
const allUp = monitors.every((monitor) => monitor.status === true);
const anyDown = monitors.some((monitor) => monitor.status === false);
const allDown = monitors.every((monitor) => monitor.status === false);
const allUp = monitors.every((monitor) => monitor.status === "up");
const anyDown = monitors.some((monitor) => monitor.status === "down");
const allDown = monitors.every((monitor) => monitor.status === "down");
if (allUp)
return {
+1
View File
@@ -775,6 +775,7 @@
"status": {
"down": "down",
"initializing": "initializing",
"maintenance": "maintenance",
"paused": "paused",
"total": "total",
"up": "up"