Refactor pagespeed details

This commit is contained in:
Alex Holliday committed 2025-01-28 15:42:46 -08:00
1 parent 36b6173528
commit ac2cf49082
19 files changed
+643 -582

No files matched your search

@@ -0,0 +1,90 @@
import { Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import IconBox from "../../IconBox";
import PropTypes from "prop-types";
const ChartBox = ({
children,
icon,
header,
height = "300px",
justifyContent = "space-between",
Legend,
borderRadiusRight = 4,
}) => {
const theme = useTheme();
return (
<Stack
flex={1}
direction="row"
sx={{
backgroundColor: theme.palette.primary.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.primary.lowContrast,
borderRadius: 2,
borderTopRightRadius: borderRadiusRight,
borderBottomRightRadius: borderRadiusRight,
}}
>
<Stack
flex={1}
alignItems="center"
sx={{
padding: theme.spacing(8),
justifyContent,
gap: theme.spacing(8),
height,
minWidth: 250,
"& h2": {
color: theme.palette.primary.contrastTextSecondary,
fontSize: 15,
fontWeight: 500,
},
"& .MuiBox-root:not(.area-tooltip) p": {
color: theme.palette.primary.contrastTextTertiary,
fontSize: 13,
},
"& .MuiBox-root > span": {
color: theme.palette.primary.contrastText,
fontSize: 20,
"& span": {
opacity: 0.8,
marginLeft: 2,
fontSize: 15,
},
},
"& tspan, & text": {
fill: theme.palette.primary.contrastTextTertiary,
},
"& path": {
transition: "fill 300ms ease, stroke-width 400ms ease",
},
}}
>
<Stack
alignSelf="flex-start"
direction="row"
alignItems="center"
gap={theme.spacing(6)}
>
<IconBox>{icon}</IconBox>
<Typography component="h2">{header}</Typography>
</Stack>
{children}
</Stack>
{Legend && Legend}
</Stack>
);
};
export default ChartBox;
ChartBox.propTypes = {
children: PropTypes.node,
icon: PropTypes.node.isRequired,
header: PropTypes.string.isRequired,
height: PropTypes.string,
};
@@ -0,0 +1,42 @@
import { Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import IconBox from "../../IconBox";
import PropTypes from "prop-types";
const LegendBox = ({ children, icon, header, sx }) => {
const theme = useTheme();
return (
<Stack
direction="column"
gap={theme.spacing(4)}
borderRadius={theme.spacing(8)}
sx={{
...sx,
"& label": { pl: theme.spacing(6) },
borderLeftStyle: "solid",
borderLeftWidth: 1,
borderLeftColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: theme.spacing(8),
background: `linear-gradient(325deg, ${theme.palette.tertiary.main} 20%, ${theme.palette.primary.main} 45%)`,
}}
>
<Stack
direction="row"
gap={theme.spacing(6)}
>
<IconBox>{icon}</IconBox>
<Typography component="h2">{header}</Typography>
</Stack>
{children}
</Stack>
);
};
LegendBox.propTypes = {
children: PropTypes.node,
icon: PropTypes.node,
header: PropTypes.string,
};
export default LegendBox;
@@ -0,0 +1,40 @@
import { Button, Box } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import SettingsIcon from "../../../assets/icons/settings-bold.svg?react";
import PropTypes from "prop-types";
const ConfigButton = ({ shouldRender, monitorId }) => {
const theme = useTheme();
const navigate = useNavigate();
if (!shouldRender) return null;
return (
<Box alignSelf="flex-end">
<Button
variant="contained"
color="secondary"
onClick={() => navigate(`/uptime/configure/${monitorId}`)}
sx={{
px: theme.spacing(5),
"& svg": {
mr: theme.spacing(3),
"& path": {
/* Should always be contrastText for the button color */
stroke: theme.palette.secondary.contrastText,
},
},
}}
>
<SettingsIcon /> Configure
</Button>
</Box>
);
};
ConfigButton.propTypes = {
shouldRender: PropTypes.bool,
monitorId: PropTypes.string,
};
export default ConfigButton;
@@ -0,0 +1,54 @@
import { Stack, Typography } from "@mui/material";
import PulseDot from "../Animated/PulseDot";
import Dot from "../Dot";
import { useTheme } from "@emotion/react";
import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
import { formatDurationRounded } from "../../Utils/timeUtils";
import ConfigButton from "./ConfigButton";
import SkeletonLayout from "./skeleton";
import PropTypes from "prop-types";
const MonitorHeader = ({ shouldRender = true, isAdmin, monitor }) => {
const theme = useTheme();
const { statusColor, statusMsg, determineState } = useUtils();
if (!shouldRender) {
return <SkeletonLayout />;
}
return (
<Stack
direction="row"
justifyContent="space-between"
>
<Stack>
<Typography variant="h1">{monitor.name}</Typography>
<Stack
direction="row"
alignItems={"center"}
gap={theme.spacing(2)}
>
<PulseDot color={statusColor[determineState(monitor)]} />
<Typography variant="h2">
{monitor?.url?.replace(/^https?:\/\//, "") || "..."}
</Typography>
<Dot />
<Typography>
Checking every {formatDurationRounded(monitor?.interval)}.
</Typography>
</Stack>
</Stack>
<ConfigButton
shouldRender={isAdmin}
monitorId={monitor._id}
/>
</Stack>
);
};
MonitorHeader.propTypes = {
shouldRender: PropTypes.bool,
isAdmin: PropTypes.bool,
monitor: PropTypes.object,
};
export default MonitorHeader;
@@ -0,0 +1,23 @@
import { Stack, Skeleton } from "@mui/material";
const SkeletonLayout = () => {
return (
<Stack
direction="row"
justifyContent="space-between"
>
<Skeleton
height={40}
variant="rounded"
width="15%"
/>
<Skeleton
height={40}
variant="rounded"
width="15%"
/>
</Stack>
);
};
export default SkeletonLayout;