cleanup
This commit is contained in:
1 parent
85190992c7
commit
1fefb038f0
9 files changed
+13
-513
No files matched your search
@@ -17,7 +17,6 @@ import { useNavigate } from "react-router-dom";
|
||||
import { useStatusPageFetch } from "../Status/Hooks/useStatusPageFetch.jsx";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useStatusPageDelete } from "../Status/Hooks/useStatusPageDelete.jsx";
|
||||
//Constants
|
||||
const ERROR_TAB_MAPPING = [
|
||||
["companyName", "url", "timezone", "color", "isPublished", "logo"],
|
||||
@@ -60,7 +59,7 @@ const CreateStatusPage = () => {
|
||||
const [createStatusPage] = useCreateStatusPage(isCreate);
|
||||
const [statusPage, statusPageMonitors, statusPageIsLoading, , fetchStatusPage] =
|
||||
useStatusPageFetch(isCreate, url);
|
||||
const [deleteStatusPage, isDeleting] = useStatusPageDelete(fetchStatusPage, url);
|
||||
// const [deleteStatusPage, isDeleting] = useStatusPageDelete(fetchStatusPage, url);
|
||||
|
||||
// Handlers
|
||||
const handleFormChange = (e) => {
|
||||
@@ -133,7 +132,7 @@ const CreateStatusPage = () => {
|
||||
const handleDelete = async () => {
|
||||
setIsDeleteOpen(false);
|
||||
// Start deletion process but don't wait for it
|
||||
deleteStatusPage();
|
||||
// deleteStatusPage();
|
||||
// Immediately navigate away to prevent additional fetches for the deleted page
|
||||
navigate("/status");
|
||||
};
|
||||
@@ -252,7 +251,7 @@ const CreateStatusPage = () => {
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
loading={isDeleting}
|
||||
// loading={isDeleting}
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={() => setIsDeleteOpen(true)}
|
||||
@@ -266,7 +265,7 @@ const CreateStatusPage = () => {
|
||||
open={isDeleteOpen}
|
||||
confirmationButtonLabel={t("deleteStatusPageConfirm")}
|
||||
description={t("deleteStatusPageDescription")}
|
||||
isLoading={isDeleting || statusPageIsLoading}
|
||||
// isLoading={isDeleting || statusPageIsLoading}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
@@ -290,7 +289,7 @@ const CreateStatusPage = () => {
|
||||
handleDelete={handleDelete}
|
||||
isDeleteOpen={isDeleteOpen}
|
||||
setIsDeleteOpen={setIsDeleteOpen}
|
||||
isDeleting={isDeleting}
|
||||
// isDeleting={isDeleting}
|
||||
isLoading={statusPageIsLoading}
|
||||
/>
|
||||
<Stack
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
// Components
|
||||
import { Box, Typography } from "@mui/material";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const AdminLink = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Typography
|
||||
className="forgot-p"
|
||||
display="inline-block"
|
||||
color={theme.palette.primary.contrastText}
|
||||
>
|
||||
{t("administrator")}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="span"
|
||||
color={theme.palette.accent.main}
|
||||
ml={theme.spacing(2)}
|
||||
sx={{ cursor: "pointer" }}
|
||||
onClick={() => navigate("/login")}
|
||||
>
|
||||
{t("loginHere")}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminLink;
|
||||
@@ -1,141 +0,0 @@
|
||||
// Components
|
||||
import { Box, Stack, Typography, Button } from "@mui/material";
|
||||
import Image from "@/Components/v1/Image/index.jsx";
|
||||
import Icon from "@/Components/v1/Icon";
|
||||
import ThemeSwitch from "@/Components/v1/ThemeSwitch/index.jsx";
|
||||
//Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const Controls = ({ url, type }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const currentPath = location.pathname;
|
||||
const navigate = useNavigate();
|
||||
|
||||
if (currentPath.startsWith("/status/uptime/public")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(2)}
|
||||
>
|
||||
<Box>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
if (type === "uptime") {
|
||||
navigate(`/status/uptime/configure/${url}`);
|
||||
}
|
||||
}}
|
||||
sx={{
|
||||
px: theme.spacing(5),
|
||||
"& svg": {
|
||||
mr: theme.spacing(3),
|
||||
"& path": {
|
||||
stroke: theme.palette.secondary.contrastText,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
name="Settings"
|
||||
size={18}
|
||||
style={{ marginRight: "8px" }}
|
||||
/>{" "}
|
||||
{t("configure")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
Controls.propTypes = {
|
||||
type: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
};
|
||||
|
||||
const ControlsHeader = ({ statusPage, isPublic, url, type = "uptime" }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const publicUrl = `/status/uptime/public/${url}`;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
alignSelf="flex-start"
|
||||
direction="row"
|
||||
width="100%"
|
||||
gap={theme.spacing(2)}
|
||||
justifyContent="space-between"
|
||||
alignItems="flex-end"
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
alignItems="flex-end"
|
||||
>
|
||||
<Image
|
||||
shouldRender={statusPage?.logo?.data ? true : false}
|
||||
alt={"Company logo"}
|
||||
maxWidth={"300px"}
|
||||
maxHeight={"50px"}
|
||||
base64={statusPage?.logo?.data}
|
||||
/>
|
||||
<Typography
|
||||
variant="h1"
|
||||
overflow="hidden"
|
||||
textOverflow="ellipsis"
|
||||
sx={{
|
||||
maxWidth: { xs: "200px", sm: "100%" },
|
||||
}}
|
||||
>
|
||||
{statusPage?.companyName}
|
||||
</Typography>
|
||||
{statusPage?.isPublished && !isPublic && (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
onClick={() => {
|
||||
window.open(publicUrl, "_blank", "noopener,noreferrer");
|
||||
}}
|
||||
sx={{
|
||||
display: "inline-flex",
|
||||
":hover": {
|
||||
cursor: "pointer",
|
||||
borderBottom: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography>{t("publicLink")}</Typography>
|
||||
<Icon
|
||||
name="ExternalLink"
|
||||
size={18}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
<Controls
|
||||
url={url}
|
||||
type={type}
|
||||
/>
|
||||
{isPublic && <ThemeSwitch />}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
ControlsHeader.propTypes = {
|
||||
url: PropTypes.string,
|
||||
statusPage: PropTypes.object,
|
||||
isPublic: PropTypes.bool,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
export default ControlsHeader;
|
||||
@@ -1,69 +0,0 @@
|
||||
// Components
|
||||
import { Stack, Box } from "@mui/material";
|
||||
import Host from "@/Components/v1/Host/index.jsx";
|
||||
import StatusPageBarChart from "@/Components/v1/Charts/StatusPageBarChart/index.jsx";
|
||||
import { StatusLabel } from "@/Components/v1/Label/index.jsx";
|
||||
|
||||
//Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const MonitorsList = ({
|
||||
isLoading = false,
|
||||
shouldRender = true,
|
||||
monitors = [],
|
||||
statusPage = {},
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { determineState } = useMonitorUtils();
|
||||
|
||||
const { showURL } = useSelector((state) => state.ui);
|
||||
|
||||
return (
|
||||
<>
|
||||
{monitors?.map((monitor) => {
|
||||
const status = determineState(monitor);
|
||||
return (
|
||||
<Stack
|
||||
key={monitor.id}
|
||||
width="100%"
|
||||
gap={theme.spacing(10)}
|
||||
margin="0 auto"
|
||||
maxWidth="95%"
|
||||
>
|
||||
<Host
|
||||
key={monitor.id}
|
||||
url={monitor.url}
|
||||
title={monitor.name}
|
||||
percentageColor={monitor.percentageColor}
|
||||
percentage={monitor.percentage}
|
||||
showURL={showURL}
|
||||
status={status}
|
||||
/>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(1)}
|
||||
>
|
||||
{statusPage.showCharts !== false && (
|
||||
<Box flex={9}>
|
||||
<StatusPageBarChart checks={monitor?.checks?.slice().reverse()} />
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
MonitorsList.propTypes = {
|
||||
monitors: PropTypes.array.isRequired,
|
||||
statusPage: PropTypes.object,
|
||||
};
|
||||
|
||||
export default MonitorsList;
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Stack, Skeleton } from "@mui/material";
|
||||
|
||||
const SkeletonLayout = () => {
|
||||
return (
|
||||
<Stack>
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
height={"90vh"}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
@@ -1,77 +0,0 @@
|
||||
// Components
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import Icon from "@/Components/v1/Icon";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const getMonitorStatus = (monitors, theme) => {
|
||||
const monitorsStatus = {
|
||||
icon: (
|
||||
<Icon
|
||||
name="AlertTriangle"
|
||||
size={24}
|
||||
color="primary.contrastTextSecondaryDarkBg"
|
||||
/>
|
||||
),
|
||||
};
|
||||
if (monitors.every((monitor) => monitor.status === true)) {
|
||||
monitorsStatus.msg = "All systems operational";
|
||||
monitorsStatus.color = theme.palette.success.lowContrast;
|
||||
monitorsStatus.icon = (
|
||||
<Icon
|
||||
name="CheckCircle2"
|
||||
size={24}
|
||||
color="primary.contrastTextSecondaryDarkBg"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (monitors.every((monitor) => monitor.status === false)) {
|
||||
monitorsStatus.msg = "All systems down";
|
||||
monitorsStatus.color = theme.palette.error.lowContrast;
|
||||
}
|
||||
|
||||
if (monitors.some((monitor) => monitor.status === false)) {
|
||||
monitorsStatus.msg = "Degraded performance";
|
||||
monitorsStatus.color = theme.palette.warning.lowContrast;
|
||||
}
|
||||
|
||||
// Paused or unknown
|
||||
if (monitors.some((monitor) => typeof monitor.status === "undefined")) {
|
||||
monitorsStatus.msg = "Unknown status";
|
||||
monitorsStatus.color = theme.palette.warning.lowContrast;
|
||||
}
|
||||
return monitorsStatus;
|
||||
};
|
||||
|
||||
const StatusBar = ({ monitors }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
if (typeof monitors === "undefined") return;
|
||||
|
||||
const monitorsStatus = getMonitorStatus(monitors, theme);
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
gap={theme.spacing(2)}
|
||||
height={theme.spacing(30)}
|
||||
width={"100%"}
|
||||
backgroundColor={monitorsStatus.color}
|
||||
borderRadius={theme.spacing(2)}
|
||||
>
|
||||
{monitorsStatus.icon}
|
||||
{/* CAIO_REVIEW */}
|
||||
<Typography variant="h2DarkBg">{monitorsStatus.msg}</Typography>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatusBar;
|
||||
|
||||
StatusBar.propTypes = {
|
||||
status: PropTypes.object,
|
||||
};
|
||||
@@ -1,166 +0,0 @@
|
||||
// Components
|
||||
import { Typography, Stack } from "@mui/material";
|
||||
import GenericFallback from "@/Components/v1/GenericFallback/index.jsx";
|
||||
import AdminLink from "./Components/AdminLink/index.jsx";
|
||||
import ControlsHeader from "./Components/ControlsHeader/index.jsx";
|
||||
import SkeletonLayout from "./Components/Skeleton/index.jsx";
|
||||
import StatusBar from "./Components/StatusBar/index.jsx";
|
||||
import MonitorsList from "./Components/MonitorsList/index.jsx";
|
||||
import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx";
|
||||
import TextLink from "@/Components/v1/TextLink/index.jsx";
|
||||
|
||||
// Utils
|
||||
import { useStatusPageFetch } from "./Hooks/useStatusPageFetch.jsx";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useIsAdmin } from "@/Hooks/useIsAdmin.js";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PublicStatus = () => {
|
||||
const { url } = useParams();
|
||||
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
const [statusPage, monitors, isLoading, networkError] = useStatusPageFetch(false, url);
|
||||
|
||||
// Breadcrumbs
|
||||
const crumbs = [
|
||||
{ name: t("statusBreadCrumbsStatusPages"), path: "/status" },
|
||||
{ name: t("statusBreadCrumbsDetails"), path: `/status/uptime/${statusPage?.url}` },
|
||||
];
|
||||
|
||||
// Setup
|
||||
let sx = { paddingLeft: theme.spacing(20), paddingRight: theme.spacing(20) };
|
||||
let link = undefined;
|
||||
const isPublic = location.pathname.startsWith("/status/uptime/public");
|
||||
// Public status page
|
||||
if (isPublic && statusPage && statusPage.showAdminLoginLink === true) {
|
||||
sx = {
|
||||
paddingTop: theme.spacing(20),
|
||||
paddingLeft: "20vw",
|
||||
paddingRight: "20vw",
|
||||
};
|
||||
link = <AdminLink />;
|
||||
}
|
||||
|
||||
// Loading
|
||||
if (isLoading) {
|
||||
return <SkeletonLayout />;
|
||||
}
|
||||
|
||||
if (monitors?.length === 0) {
|
||||
return (
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{"Theres nothing here yet"}
|
||||
</Typography>
|
||||
{isAdmin && (
|
||||
<TextLink
|
||||
linkText={"Add a monitor to get started"}
|
||||
href={`/status/uptime/configure/${url}`}
|
||||
/>
|
||||
)}
|
||||
</GenericFallback>
|
||||
);
|
||||
}
|
||||
|
||||
// Error fetching data
|
||||
if (networkError === true) {
|
||||
return (
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{t("common.toasts.networkError")}
|
||||
</Typography>
|
||||
<Typography>{t("common.toasts.checkConnection")}</Typography>
|
||||
</GenericFallback>
|
||||
);
|
||||
}
|
||||
|
||||
// Public status page fallback
|
||||
if (!isLoading && typeof statusPage === "undefined" && isPublic) {
|
||||
return (
|
||||
<Stack sx={sx}>
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{t("statusPageStatus")}
|
||||
</Typography>
|
||||
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
|
||||
</GenericFallback>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
// Finished loading, but status page is not public
|
||||
if (!isLoading && isPublic && statusPage.isPublished === false) {
|
||||
return (
|
||||
<Stack sx={sx}>
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{t("statusPageStatusNotPublic")}
|
||||
</Typography>
|
||||
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
|
||||
</GenericFallback>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
// Status page doesn't exist
|
||||
if (!isLoading && typeof statusPage === "undefined") {
|
||||
return (
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{t("statusPageStatusNoPage")}
|
||||
</Typography>
|
||||
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
|
||||
</GenericFallback>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack
|
||||
gap={theme.spacing(10)}
|
||||
sx={{ ...sx, position: "relative" }}
|
||||
>
|
||||
{!isPublic && <Breadcrumbs list={crumbs} />}
|
||||
<ControlsHeader
|
||||
statusPage={statusPage}
|
||||
url={url}
|
||||
isPublic={isPublic}
|
||||
/>
|
||||
<Typography variant="h2">{t("statusPageStatusServiceStatus")}</Typography>
|
||||
<StatusBar monitors={monitors} />
|
||||
<MonitorsList
|
||||
monitors={monitors}
|
||||
statusPage={statusPage}
|
||||
/>
|
||||
{link}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicStatus;
|
||||
@@ -3,6 +3,8 @@ import { StatusPagesTable } from "./Components/StatusPagesTable";
|
||||
import { useGet } from "@/Hooks/UseApi";
|
||||
import type { StatusPage } from "@/Types/StatusPage";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HeaderCreate } from "@/Components/v2/common";
|
||||
import { useIsAdmin } from "@/Hooks/useIsAdmin";
|
||||
|
||||
const StatusPages = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -13,6 +15,8 @@ const StatusPages = () => {
|
||||
error,
|
||||
} = useGet<StatusPage[]>("/status-page/team");
|
||||
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
return (
|
||||
<BasePageWithStates
|
||||
page={t("pages.statusPages.title")}
|
||||
@@ -25,6 +29,10 @@ const StatusPages = () => {
|
||||
actionButtonText={t("pages.statusPages.fallback.actionButton")}
|
||||
actionLink="/status/uptime/create"
|
||||
>
|
||||
<HeaderCreate
|
||||
path="/status/uptime/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
<StatusPagesTable data={statusPages ?? []} />
|
||||
</BasePageWithStates>
|
||||
);
|
||||
|
||||
@@ -546,10 +546,6 @@
|
||||
"showCharts": "Show charts",
|
||||
"showUptimePercentage": "Show uptime percentage",
|
||||
"removeLogo": "Remove Logo",
|
||||
"statusPageStatus": "A public status page is not set up.",
|
||||
"statusPageStatusContactAdmin": "Please contact to your administrator",
|
||||
"statusPageStatusNotPublic": "This status page is not public.",
|
||||
"statusPageStatusNoPage": "There's no status page here.",
|
||||
"statusPageStatusServiceStatus": "Service status",
|
||||
"deleteStatusPage": "Do you want to delete this status page?",
|
||||
"deleteStatusPageConfirm": "Yes, delete status page",
|
||||
|
||||
Reference in new issue
Block a user