mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-20 16:39:07 -05:00
status bar
This commit is contained in:
@@ -95,7 +95,7 @@ export const HeaderMonitorControls = ({
|
||||
await refetch();
|
||||
}}
|
||||
>
|
||||
{monitor?.isActive ? t("pause") : t("resume")}
|
||||
{monitor?.isActive ? t("common.buttons.pause") : t("common.buttons.resume")}
|
||||
</Button>
|
||||
)}
|
||||
{isAdmin && (
|
||||
@@ -105,7 +105,7 @@ export const HeaderMonitorControls = ({
|
||||
startIcon={<Icon icon={Settings} />}
|
||||
onClick={() => navigate(`/${path}/configure/${monitor.id}`)}
|
||||
>
|
||||
Configure
|
||||
{t("common.buttons.configure")}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
@@ -155,7 +155,7 @@ export const HeaderDeleteControls = ({
|
||||
await refetch();
|
||||
}}
|
||||
>
|
||||
{monitor?.isActive ? t("pause") : t("resume")}
|
||||
{monitor?.isActive ? t("common.buttons.pause") : t("common.buttons.resume")}
|
||||
</Button>
|
||||
)}
|
||||
{isAdmin && (
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { Icon } from "@/Components/v2/design-elements";
|
||||
import { Button } from "@/Components/v2/inputs";
|
||||
import { Settings, ExternalLink } from "lucide-react";
|
||||
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import type { StatusPage } from "@/Types/StatusPage";
|
||||
|
||||
interface HeaderStatusPageControlsProps {
|
||||
isAdmin: boolean;
|
||||
statusPage: StatusPage;
|
||||
isPublic?: boolean;
|
||||
}
|
||||
export const HeaderStatusPageControls = ({
|
||||
isAdmin,
|
||||
statusPage,
|
||||
isPublic = false,
|
||||
}: HeaderStatusPageControlsProps) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Stack
|
||||
direction={"row"}
|
||||
alignItems={"center"}
|
||||
justifyContent={"space-between"}
|
||||
mb={4}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(4)}
|
||||
alignItems="baseline"
|
||||
>
|
||||
<Typography
|
||||
variant="h1"
|
||||
overflow="hidden"
|
||||
textOverflow="ellipsis"
|
||||
sx={{
|
||||
maxWidth: { xs: "200px", sm: "100%" },
|
||||
}}
|
||||
>
|
||||
{statusPage?.companyName}
|
||||
</Typography>
|
||||
{statusPage?.isPublished && !isPublic && (
|
||||
<>
|
||||
<Typography
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`/status/uptime/public/${statusPage.url}`,
|
||||
"_blank",
|
||||
"noopener,noreferrer"
|
||||
);
|
||||
}}
|
||||
sx={{
|
||||
borderBottom: 1,
|
||||
borderColor: "transparent",
|
||||
":hover": {
|
||||
cursor: "pointer",
|
||||
borderBottom: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{t("publicLink")}
|
||||
</Typography>
|
||||
<Box>
|
||||
<ExternalLink size={14} />
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
startIcon={<Icon icon={Settings} />}
|
||||
onClick={() => navigate(`status/uptime/configure/${statusPage.url}`)}
|
||||
>
|
||||
{t("common.buttons.configure")}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
import { AlertTriangle, CircleCheck } from "lucide-react";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { Theme } from "@mui/material";
|
||||
import { useTheme } from "@mui/material";
|
||||
import type { Monitor } from "@/Types/Monitor";
|
||||
|
||||
const getMonitorStatus = (monitors: Monitor[], theme: Theme, t: Function) => {
|
||||
const monitorsStatus: Record<string, any> = {
|
||||
icon: <AlertTriangle size={24} />,
|
||||
};
|
||||
|
||||
if (monitors.every((monitor) => monitor.status === true)) {
|
||||
monitorsStatus.msg = t("pages.statusPages.statusBar.allUp");
|
||||
monitorsStatus.color = theme.palette.success.main;
|
||||
monitorsStatus.icon = <CircleCheck size={24} />;
|
||||
}
|
||||
|
||||
if (monitors.every((monitor) => monitor.status === false)) {
|
||||
monitorsStatus.msg = t("pages.statusPages.statusBar.allDown");
|
||||
monitorsStatus.color = theme.palette.error.main;
|
||||
}
|
||||
|
||||
if (monitors.some((monitor) => monitor.status === false)) {
|
||||
monitorsStatus.msg = t("pages.statusPages.statusBar.degraded");
|
||||
monitorsStatus.color = theme.palette.warning.main;
|
||||
}
|
||||
|
||||
// Paused or unknown
|
||||
if (monitors.some((monitor) => typeof monitor.status === "undefined")) {
|
||||
monitorsStatus.msg = t("pages.statusPages.statusBar.unknown");
|
||||
monitorsStatus.color = theme.palette.warning.main;
|
||||
}
|
||||
return monitorsStatus;
|
||||
};
|
||||
|
||||
interface StatusBarProps {
|
||||
monitors: Monitor[];
|
||||
}
|
||||
|
||||
export const StatusBar = ({ monitors }: StatusBarProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const monitorsStatus = getMonitorStatus(monitors, theme, t);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={theme.spacing(2)}
|
||||
height={theme.spacing(30)}
|
||||
bgcolor={monitorsStatus.color}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
>
|
||||
{monitorsStatus.icon}
|
||||
<Typography>{monitorsStatus.msg}</Typography>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { BasePage } from "@/Components/v2/design-elements";
|
||||
import { StatusBar } from "@/Pages/StatusPage/Status/Components/StatusBar";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useIsAdmin } from "@/Hooks/useIsAdmin";
|
||||
import { useLocation, useParams } from "react-router-dom";
|
||||
import { useGet } from "@/Hooks/UseApi";
|
||||
import type { StatusPageResponse } from "@/Types/StatusPage";
|
||||
import { HeaderStatusPageControls } from "./Components/HeaderStatusPageControls";
|
||||
|
||||
const StatusPageView = () => {
|
||||
const { t } = useTranslation();
|
||||
const { url } = useParams();
|
||||
const isAdmin = useIsAdmin();
|
||||
const location = useLocation();
|
||||
const isPublic = location.pathname.startsWith("/status/uptime/public");
|
||||
|
||||
const apiUrl = url ? `/status-page/${url}?type=uptime` : null;
|
||||
|
||||
const { data, isLoading, error } = useGet<StatusPageResponse>(apiUrl);
|
||||
|
||||
const statusPage = data?.statusPage;
|
||||
const monitors = data?.monitors ?? [];
|
||||
|
||||
if (!statusPage || !monitors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (monitors.length === 0) {
|
||||
return "poo";
|
||||
}
|
||||
|
||||
return (
|
||||
<BasePage
|
||||
loading={isLoading}
|
||||
error={error}
|
||||
>
|
||||
<HeaderStatusPageControls
|
||||
isAdmin={isAdmin}
|
||||
statusPage={statusPage}
|
||||
isPublic={isPublic}
|
||||
/>
|
||||
<Typography variant="h2">{t("statusPageStatusServiceStatus")}</Typography>
|
||||
<StatusBar monitors={monitors} />
|
||||
<pre> {JSON.stringify(data, null, 2)}</pre>
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatusPageView;
|
||||
@@ -38,7 +38,7 @@ import Incidents from "../Pages/Incidents/";
|
||||
// Status pages
|
||||
import CreateStatus from "../Pages/StatusPage/Create/index.jsx";
|
||||
import StatusPages from "../Pages/StatusPage/StatusPages";
|
||||
import Status from "../Pages/StatusPage/Status/index.jsx";
|
||||
import Status from "../Pages/StatusPage/Status";
|
||||
|
||||
import Notifications from "../Pages/Notifications";
|
||||
import CreateNotifications from "../Pages/Notifications/create";
|
||||
@@ -238,7 +238,13 @@ const Routes = () => {
|
||||
|
||||
<Route
|
||||
path="status/uptime/:url"
|
||||
element={<Status />}
|
||||
element={
|
||||
<>
|
||||
<ThemeProvider theme={v2theme}>
|
||||
<Status />
|
||||
</ThemeProvider>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
@@ -360,7 +366,13 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="/status/uptime/public/:url"
|
||||
element={<Status />}
|
||||
element={
|
||||
<>
|
||||
<ThemeProvider theme={v2theme}>
|
||||
<Status />
|
||||
</ThemeProvider>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { Monitor } from "@/Types/Monitor";
|
||||
|
||||
export interface StatusPage {
|
||||
id: string;
|
||||
userId: string;
|
||||
@@ -22,3 +24,8 @@ export interface StatusPage {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface StatusPageResponse {
|
||||
statusPage: StatusPage;
|
||||
monitors: Monitor[];
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"save": "Save",
|
||||
"test": "Test"
|
||||
"test": "Test",
|
||||
"configure": "Configure"
|
||||
},
|
||||
|
||||
"alerts": {
|
||||
@@ -201,10 +202,6 @@
|
||||
},
|
||||
"uptime": {
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"headers": {
|
||||
"responseTime": "Response time"
|
||||
}
|
||||
@@ -217,10 +214,6 @@
|
||||
},
|
||||
"checks": {
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"headers": {
|
||||
"dateTime": "Date & time",
|
||||
"statusCode": "Status code"
|
||||
@@ -249,10 +242,6 @@
|
||||
"actionButton": "Let's create your first PageSpeed monitor!"
|
||||
},
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"headers": {
|
||||
"pageSpeedScore": "PageSpeed score"
|
||||
}
|
||||
@@ -285,10 +274,6 @@
|
||||
"actionButton": "Let's create your first infrastructure monitor!"
|
||||
},
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"headers": {
|
||||
"cpu": "CPU",
|
||||
"disk": "Disk",
|
||||
@@ -349,10 +334,6 @@
|
||||
"title": "Notification channles are used to:"
|
||||
},
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"headers": {
|
||||
"destination": "Destination"
|
||||
}
|
||||
@@ -417,10 +398,6 @@
|
||||
},
|
||||
|
||||
"table": {
|
||||
"headers": {
|
||||
"name": "Status page name",
|
||||
"url": "Public URL"
|
||||
},
|
||||
"activeIncidents": "Active Incidents",
|
||||
"resolvedIncidents": "Resolved Incidents",
|
||||
"headers": {
|
||||
@@ -495,6 +472,13 @@
|
||||
"Keep users informed about outages and performance"
|
||||
],
|
||||
"title": "A status page is used to:"
|
||||
},
|
||||
"serviceStauts": "Service stauts",
|
||||
"statusBar": {
|
||||
"allUp": "All systems operational",
|
||||
"allDown": "All systems down",
|
||||
"degraded": "Degraded performance",
|
||||
"unknown": "Unknown status"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user