Refactored pages styling 3/3
This commit is contained in:
1 parent
bd1d1d8082
commit
a4c5dd3ee7
23 files changed
+611
-577
No files matched your search
@@ -1,52 +1,17 @@
|
||||
.configure-monitor h1.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
.configure-monitor h2.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large);
|
||||
font-weight: 600;
|
||||
}
|
||||
.configure-monitor h2.MuiTypography-root,
|
||||
.configure-monitor .config-box p.MuiTypography-root,
|
||||
.configure-monitor .MuiSelect-select {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.configure-monitor .MuiModal-root h2.MuiTypography-root {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.configure-monitor p.MuiTypography-root,
|
||||
.configure-monitor .MuiSelect-select {
|
||||
.configure-monitor p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.configure-monitor h6.MuiTypography-root {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.configure-monitor h6.MuiTypography-root,
|
||||
.configure-monitor h1.MuiTypography-root + span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
}
|
||||
.configure-monitor button.MuiButtonBase-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.configure-monitor button.MuiButtonBase-root {
|
||||
height: var(--env-var-height-2);
|
||||
}
|
||||
.configure-monitor .config-box {
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
background-color: var(--primary-bg);
|
||||
}
|
||||
.configure-monitor .config-box > .MuiBox-root,
|
||||
.configure-monitor .config-box > .MuiStack-root {
|
||||
flex: 1;
|
||||
padding: 24px 30px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.configure-monitor .config-box > *:first-child {
|
||||
flex: 0.7;
|
||||
border-right: solid 1px var(--border-color);
|
||||
}
|
||||
|
||||
.configure-monitor .MuiStack-root:has(span.MuiTypography-root.input-error) {
|
||||
position: relative;
|
||||
}
|
||||
@@ -54,25 +19,3 @@
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
}
|
||||
.configure-monitor .MuiInputBase-root:has(> .Mui-disabled) {
|
||||
background-color: var(--primary-bg-accent);
|
||||
}
|
||||
|
||||
.MuiInputBase-root:has(#monitor-interval) {
|
||||
height: 34px;
|
||||
width: 100%;
|
||||
}
|
||||
#monitor-interval {
|
||||
padding: 0 10px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.MuiInputBase-root:not(.Mui-focused):has(#monitor-interval):hover fieldset {
|
||||
border-color: var(--border-color-dark);
|
||||
}
|
||||
|
||||
body:has(.configure-monitor) .select-dropdown .MuiMenuItem-root,
|
||||
.configure-monitor .select-wrapper .select-component > .MuiSelect-select {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { Box, Modal, Skeleton, Stack, Typography } from "@mui/material";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
import { ConfigBox } from "../styled";
|
||||
import {
|
||||
updateUptimeMonitor,
|
||||
getUptimeMonitorsByTeamId,
|
||||
@@ -45,8 +46,8 @@ const SkeletonLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<Skeleton variant="rounded" width="15%" height={34} />
|
||||
<Stack gap={theme.gap.xl} mt={theme.gap.medium}>
|
||||
<Stack direction="row" gap={theme.gap.small} mt={theme.gap.small}>
|
||||
<Stack gap={theme.spacing(20)} mt={theme.spacing(6)}>
|
||||
<Stack direction="row" gap={theme.spacing(4)} mt={theme.spacing(4)}>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
style={{ minWidth: 24, minHeight: 24 }}
|
||||
@@ -56,13 +57,13 @@ const SkeletonLayout = () => {
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={24}
|
||||
sx={{ mb: theme.gap.small }}
|
||||
sx={{ mb: theme.spacing(4) }}
|
||||
/>
|
||||
<Skeleton variant="rounded" width="50%" height={18} />
|
||||
</Box>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.gap.medium}
|
||||
gap={theme.spacing(6)}
|
||||
sx={{
|
||||
ml: "auto",
|
||||
alignSelf: "flex-end",
|
||||
@@ -209,7 +210,7 @@ const Configure = () => {
|
||||
let loading = Object.keys(monitor).length === 0;
|
||||
|
||||
return (
|
||||
<Stack className="configure-monitor" gap={theme.gap.large}>
|
||||
<Stack className="configure-monitor" gap={theme.spacing(12)}>
|
||||
{loading ? (
|
||||
<SkeletonLayout />
|
||||
) : (
|
||||
@@ -225,20 +226,25 @@ const Configure = () => {
|
||||
component="form"
|
||||
noValidate
|
||||
spellCheck="false"
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
flex={1}
|
||||
>
|
||||
<Stack direction="row" gap={theme.gap.xs}>
|
||||
<Stack direction="row" gap={theme.spacing(2)}>
|
||||
<PulseDot
|
||||
color={
|
||||
monitor?.status
|
||||
? theme.label.up.dotColor
|
||||
: theme.label.down.dotColor
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.main
|
||||
}
|
||||
/>
|
||||
<Box>
|
||||
{parsedUrl?.host ? (
|
||||
<Typography component="h1" mb={theme.gap.xs} lineHeight={1}>
|
||||
<Typography
|
||||
component="h1"
|
||||
mb={theme.spacing(2)}
|
||||
lineHeight={1}
|
||||
color={theme.palette.text.primary}
|
||||
>
|
||||
{parsedUrl.host || "..."}
|
||||
</Typography>
|
||||
) : (
|
||||
@@ -246,11 +252,11 @@ const Configure = () => {
|
||||
)}
|
||||
<Typography
|
||||
component="span"
|
||||
lineHeight={theme.gap.large}
|
||||
lineHeight={theme.spacing(12)}
|
||||
sx={{
|
||||
color: monitor?.status
|
||||
? "var(--success-color)"
|
||||
: "var(--error-color)",
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.text,
|
||||
}}
|
||||
>
|
||||
Your site is {monitor?.status ? "up" : "down"}.
|
||||
@@ -268,12 +274,12 @@ const Configure = () => {
|
||||
animate="rotate180"
|
||||
img={<PauseCircleOutlineIcon />}
|
||||
sx={{
|
||||
backgroundColor: theme.palette.otherColors.fillGray,
|
||||
pl: theme.gap.small,
|
||||
pr: theme.gap.medium,
|
||||
mr: theme.gap.medium,
|
||||
backgroundColor: theme.palette.background.main,
|
||||
pl: theme.spacing(4),
|
||||
pr: theme.spacing(6),
|
||||
mr: theme.spacing(6),
|
||||
"& svg": {
|
||||
mr: theme.gap.xs,
|
||||
mr: theme.spacing(2),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -282,25 +288,21 @@ const Configure = () => {
|
||||
label="Remove"
|
||||
sx={{
|
||||
boxShadow: "none",
|
||||
px: theme.gap.ml,
|
||||
px: theme.spacing(8),
|
||||
}}
|
||||
onClick={() => setIsOpen(true)}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Stack
|
||||
className="config-box"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">General settings</Typography>
|
||||
<Typography component="p" sx={{ mt: theme.gap.xs }}>
|
||||
<Typography component="p">
|
||||
Here you can select the URL of the host, together with the
|
||||
type of monitor.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.xl}>
|
||||
<Stack gap={theme.spacing(20)}>
|
||||
<Field
|
||||
type={monitor?.type === "http" ? "url" : "text"}
|
||||
https={protocol === "https"}
|
||||
@@ -322,20 +324,16 @@ const Configure = () => {
|
||||
error={errors["name"]}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
className="config-box"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Incident notifications</Typography>
|
||||
<Typography component="p" mt={theme.gap.xs}>
|
||||
<Typography component="p">
|
||||
When there is an incident, notify users.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.medium}>
|
||||
<Typography component="p" mt={theme.gap.small}>
|
||||
<Stack gap={theme.spacing(6)}>
|
||||
<Typography component="p">
|
||||
When there is a new incident,
|
||||
</Typography>
|
||||
<Checkbox
|
||||
@@ -368,7 +366,7 @@ const Configure = () => {
|
||||
{monitor?.notifications?.some(
|
||||
(notification) => notification.type === "emails"
|
||||
) ? (
|
||||
<Box mx={`calc(${theme.gap.ml} * 2)`}>
|
||||
<Box mx={theme.spacing(16)}>
|
||||
<Field
|
||||
id="notify-email-list"
|
||||
type="text"
|
||||
@@ -376,7 +374,7 @@ const Configure = () => {
|
||||
value=""
|
||||
onChange={() => logger.warn("disabled")}
|
||||
/>
|
||||
<Typography mt={theme.gap.small}>
|
||||
<Typography mt={theme.spacing(4)}>
|
||||
You can separate multiple emails with a comma
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -384,16 +382,12 @@ const Configure = () => {
|
||||
""
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
className="config-box"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Advanced settings</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.xl}>
|
||||
<Stack gap={theme.spacing(20)}>
|
||||
<Select
|
||||
id="monitor-interval-configure"
|
||||
label="Check frequency"
|
||||
@@ -402,12 +396,12 @@ const Configure = () => {
|
||||
items={frequencies}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
<Stack direction="row" justifyContent="flex-end" mt="auto">
|
||||
<Button
|
||||
level="primary"
|
||||
label="Save"
|
||||
sx={{ px: theme.gap.large }}
|
||||
sx={{ px: theme.spacing(12) }}
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
</Stack>
|
||||
@@ -422,33 +416,43 @@ const Configure = () => {
|
||||
disablePortal
|
||||
>
|
||||
<Stack
|
||||
gap={theme.gap.xs}
|
||||
gap={theme.spacing(2)}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "white",
|
||||
border: "solid 1px #f2f2f2",
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
bgcolor: theme.palette.background.main,
|
||||
border: 1,
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: 24,
|
||||
p: "30px",
|
||||
p: theme.spacing(15),
|
||||
"&:focus": {
|
||||
outline: "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography id="modal-delete-monitor" component="h2">
|
||||
<Typography
|
||||
id="modal-delete-monitor"
|
||||
component="h2"
|
||||
fontSize={16}
|
||||
color={theme.palette.text.primary}
|
||||
fontWeight={600}
|
||||
>
|
||||
Do you really want to delete this monitor?
|
||||
</Typography>
|
||||
<Typography id="delete-monitor-confirmation">
|
||||
<Typography
|
||||
id="delete-monitor-confirmation"
|
||||
color={theme.palette.text.tertiary}
|
||||
>
|
||||
Once deleted, this monitor cannot be retrieved.
|
||||
</Typography>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.gap.small}
|
||||
mt={theme.gap.large}
|
||||
gap={theme.spacing(4)}
|
||||
mt={theme.spacing(12)}
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
.create-monitor h1.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
.create-monitor h2.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large);
|
||||
font-weight: 600;
|
||||
}
|
||||
.create-monitor p.MuiTypography-root,
|
||||
.create-monitor button.MuiButtonBase-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.create-monitor h2.MuiTypography-root {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.create-monitor h6.MuiTypography-root,
|
||||
.create-monitor p.MuiTypography-root {
|
||||
color: var(--secondary-color-light);
|
||||
}
|
||||
.create-monitor h6.MuiTypography-root,
|
||||
.create-monitor .MuiBox-root .field + p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
@@ -26,11 +14,11 @@
|
||||
.create-monitor button.MuiButtonBase-root {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.create-monitor .error-container {
|
||||
position: relative;
|
||||
}
|
||||
.create-monitor .error-container p.MuiTypography-root.input-error {
|
||||
color: var(--error-color);
|
||||
opacity: 0.8;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -42,30 +30,9 @@
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
}
|
||||
.create-monitor .config-box {
|
||||
flex-direction: row;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
background-color: var(--primary-bg);
|
||||
}
|
||||
.create-monitor .config-box > .MuiBox-root,
|
||||
.create-monitor .config-box > .MuiStack-root {
|
||||
flex: 1;
|
||||
padding: 24px 30px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.create-monitor .config-box > *:first-child {
|
||||
flex: 0.7;
|
||||
border-right: solid 1px var(--border-color);
|
||||
}
|
||||
|
||||
.create-monitor .MuiStack-root .MuiButtonGroup-root button {
|
||||
font-size: var(--env-var-font-size-small);
|
||||
height: 28px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
body:has(.create-monitor) .select-dropdown .MuiMenuItem-root,
|
||||
.create-monitor .select-wrapper .select-component > .MuiSelect-select {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
import "./index.css";
|
||||
import { useState } from "react";
|
||||
import Radio from "../../../Components/Inputs/Radio";
|
||||
import Button from "../../../Components/Button";
|
||||
import { Box, ButtonGroup, Stack, Typography } from "@mui/material";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
import { ConfigBox } from "../styled";
|
||||
import Radio from "../../../Components/Inputs/Radio";
|
||||
import Button from "../../../Components/Button";
|
||||
import Field from "../../../Components/Inputs/Field";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
import "./index.css";
|
||||
|
||||
const CreateMonitor = () => {
|
||||
const MS_PER_MINUTE = 60000;
|
||||
@@ -33,7 +34,7 @@ const CreateMonitor = () => {
|
||||
const [monitor, setMonitor] = useState({
|
||||
url: "",
|
||||
name: "",
|
||||
type: "",
|
||||
type: "http",
|
||||
notifications: [],
|
||||
interval: 1,
|
||||
});
|
||||
@@ -144,7 +145,14 @@ const CreateMonitor = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<Box className="create-monitor">
|
||||
<Box
|
||||
className="create-monitor"
|
||||
sx={{
|
||||
"& h1": {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Breadcrumbs
|
||||
list={[
|
||||
{ name: "monitors", path: "/monitors" },
|
||||
@@ -157,14 +165,14 @@ const CreateMonitor = () => {
|
||||
onSubmit={handleCreateMonitor}
|
||||
noValidate
|
||||
spellCheck="false"
|
||||
gap={theme.gap.large}
|
||||
mt={theme.gap.medium}
|
||||
gap={theme.spacing(12)}
|
||||
mt={theme.spacing(6)}
|
||||
>
|
||||
<Typography component="h1">
|
||||
<Typography
|
||||
component="span"
|
||||
fontSize="inherit"
|
||||
color={theme.palette.otherColors.bluishGray}
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Create your{" "}
|
||||
</Typography>
|
||||
@@ -172,15 +180,15 @@ const CreateMonitor = () => {
|
||||
monitor
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Stack className="config-box">
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">General settings</Typography>
|
||||
<Typography component="p" mt={theme.gap.xs}>
|
||||
<Typography component="p">
|
||||
Here you can select the URL of the host, together with the type of
|
||||
monitor.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.xl}>
|
||||
<Stack gap={theme.spacing(15)}>
|
||||
<Field
|
||||
type={monitor.type === "http" ? "url" : "text"}
|
||||
id="monitor-url"
|
||||
@@ -202,16 +210,16 @@ const CreateMonitor = () => {
|
||||
error={errors["name"]}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack className="config-box">
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Checks to perform</Typography>
|
||||
<Typography component="p" mt={theme.gap.xs}>
|
||||
<Typography component="p">
|
||||
You can always add or remove checks after adding your site.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.large}>
|
||||
<Stack gap={theme.gap.medium}>
|
||||
<Stack gap={theme.spacing(12)}>
|
||||
<Stack gap={theme.spacing(6)}>
|
||||
<Radio
|
||||
id="monitor-checks-http"
|
||||
title="Website monitoring"
|
||||
@@ -228,8 +236,7 @@ const CreateMonitor = () => {
|
||||
label="HTTPS"
|
||||
onClick={() => setHttps(true)}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
https && theme.palette.otherColors.fillGray,
|
||||
backgroundColor: https && theme.palette.background.fill,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
@@ -237,8 +244,7 @@ const CreateMonitor = () => {
|
||||
label="HTTP"
|
||||
onClick={() => setHttps(false)}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
!https && theme.palette.otherColors.fillGray,
|
||||
backgroundColor: !https && theme.palette.background.fill,
|
||||
}}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
@@ -257,7 +263,11 @@ const CreateMonitor = () => {
|
||||
/>
|
||||
{errors["type"] ? (
|
||||
<Box className="error-container">
|
||||
<Typography component="p" className="input-error">
|
||||
<Typography
|
||||
component="p"
|
||||
className="input-error"
|
||||
color={theme.palette.error.text}
|
||||
>
|
||||
{errors["type"]}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -265,15 +275,15 @@ const CreateMonitor = () => {
|
||||
""
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack className="config-box">
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Incident notifications</Typography>
|
||||
<Typography component="p" mt={theme.gap.xs}>
|
||||
<Typography component="p">
|
||||
When there is an incident, notify users.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.medium}>
|
||||
<Stack gap={theme.spacing(6)}>
|
||||
<Typography component="p">When there is a new incident,</Typography>
|
||||
<Checkbox
|
||||
id="notify-sms"
|
||||
@@ -303,7 +313,7 @@ const CreateMonitor = () => {
|
||||
{monitor.notifications.some(
|
||||
(notification) => notification.type === "emails"
|
||||
) ? (
|
||||
<Box mx={`calc(${theme.gap.ml} * 2)`}>
|
||||
<Box mx={theme.spacing(16)}>
|
||||
<Field
|
||||
id="notify-email-list"
|
||||
type="text"
|
||||
@@ -311,7 +321,7 @@ const CreateMonitor = () => {
|
||||
value=""
|
||||
onChange={() => logger.warn("disabled")}
|
||||
/>
|
||||
<Typography mt={theme.gap.small}>
|
||||
<Typography mt={theme.spacing(4)}>
|
||||
You can separate multiple emails with a comma
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -319,12 +329,12 @@ const CreateMonitor = () => {
|
||||
""
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack className="config-box">
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Advanced settings</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.large}>
|
||||
<Stack gap={theme.spacing(12)}>
|
||||
<Select
|
||||
id="monitor-interval"
|
||||
label="Check frequency"
|
||||
@@ -332,73 +342,8 @@ const CreateMonitor = () => {
|
||||
onChange={(event) => handleChange(event, "interval")}
|
||||
items={frequencies}
|
||||
/>
|
||||
{/* TODO */}
|
||||
{/* <FlexibileTextField
|
||||
id="monitor-settings-retries"
|
||||
title="Maximum retries before the service is marked as down"
|
||||
type="number"
|
||||
value={advancedSettings.retries}
|
||||
onChange={(event) =>
|
||||
handleChange(event, "retries", setAdvancedSettings)
|
||||
}
|
||||
/>
|
||||
<FlexibileTextField
|
||||
id="monitor-settings-codes"
|
||||
title="Accepted status codes"
|
||||
type="number"
|
||||
value={advancedSettings.codes}
|
||||
onChange={(event) =>
|
||||
handleChange(event, "codes", setAdvancedSettings)
|
||||
}
|
||||
/>
|
||||
<FlexibileTextField
|
||||
id="monitor-settings-redirects"
|
||||
title="Maximum redirects"
|
||||
type="number"
|
||||
value={advancedSettings.redirects}
|
||||
onChange={(event) =>
|
||||
handleChange(event, "redirects", setAdvancedSettings)
|
||||
}
|
||||
/> */}
|
||||
</Stack>
|
||||
</Stack>
|
||||
{/* TODO */}
|
||||
{/*
|
||||
<ConfigBox
|
||||
leftLayout={
|
||||
<div className="config-box-desc">
|
||||
<div className="config-box-desc-title">Proxy settings</div>
|
||||
</div>
|
||||
}
|
||||
rightLayout={
|
||||
<div className="proxy-setting-config">
|
||||
<CustomizableCheckBox
|
||||
id="monitor-proxy-enable"
|
||||
title="Enable proxy"
|
||||
isChecked={proxy.enabled}
|
||||
handleChange={() => handleCheck("enabled", setProxy)}
|
||||
/>
|
||||
<FlexibileTextField
|
||||
id="monitor-proxy-protocol"
|
||||
title="Proxy protocol"
|
||||
value={proxy.protocol}
|
||||
onChange={(event) => handleChange(event, "protocol", setProxy)}
|
||||
/>
|
||||
<FlexibileTextField
|
||||
id="monitor-proxy-address"
|
||||
title="Proxy address"
|
||||
value={proxy.address}
|
||||
onChange={(event) => handleChange(event, "address", setProxy)}
|
||||
/>
|
||||
<FlexibileTextField
|
||||
id="monitor-proxy-port"
|
||||
title="Proxy port"
|
||||
value={proxy.proxy_port}
|
||||
onChange={(event) => handleChange(event, "proxy_port", setProxy)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/> */}
|
||||
</ConfigBox>
|
||||
<Stack direction="row" justifyContent="flex-end">
|
||||
<Button
|
||||
id="create-monitor-btn"
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
.monitor-details h1.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
color: var(--primary-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
.monitor-details h2.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large);
|
||||
}
|
||||
.monitor-details h2.MuiTypography-root{
|
||||
.monitor-details h2.MuiTypography-root {
|
||||
font-weight: 600;
|
||||
}
|
||||
.monitor-details h2.MuiTypography-root,
|
||||
.monitor-details h4.MuiTypography-root {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.monitor-details h6.MuiTypography-root {
|
||||
color: var(--theme-main);
|
||||
}
|
||||
.monitor-details button.MuiButtonBase-root,
|
||||
.monitor-details h4.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
}
|
||||
.monitor-details button.MuiButtonBase-root {
|
||||
height: var(--env-var-height-2);
|
||||
line-height: 1;
|
||||
@@ -28,28 +16,3 @@
|
||||
.monitor-details p.MuiTypography-root span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
}
|
||||
.monitor-details p.MuiTypography-root {
|
||||
color: var(--secondary-color-light);
|
||||
}
|
||||
|
||||
.monitor-details .stat-box {
|
||||
flex: 1 20%;
|
||||
min-width: 100px;
|
||||
border: solid 1px;
|
||||
border-radius: var(--env-var-radius-1);
|
||||
padding: var(--env-var-spacing-1) 16px;
|
||||
background-color: var(--primary-bg);
|
||||
}
|
||||
.monitor-details h6.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium-plus);
|
||||
}
|
||||
.monitor-details h6.MuiTypography-root span.MuiTypography-root {
|
||||
font-style: italic;
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
color: var(--secondary-color);
|
||||
opacity: 0.7;
|
||||
}
|
||||
.monitor-details button.MuiButtonBase-root,
|
||||
.monitor-details .stat-box {
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { Box, Skeleton, Stack, Typography, useTheme } from "@mui/material";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
@@ -19,12 +19,41 @@ import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import "./index.css";
|
||||
|
||||
const StatBox = ({ title, value }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Box className="stat-box">
|
||||
<Typography variant="h6" mb={1} fontWeight={500}>
|
||||
<Box
|
||||
className="stat-box"
|
||||
flex="20%"
|
||||
minWidth="100px"
|
||||
px={theme.spacing(8)}
|
||||
py={theme.spacing(4)}
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
>
|
||||
<Typography
|
||||
variant="h6"
|
||||
mb={theme.spacing(2)}
|
||||
fontSize={14}
|
||||
fontWeight={500}
|
||||
color={theme.palette.common.main}
|
||||
sx={{
|
||||
"& span": {
|
||||
color: theme.palette.text.accent,
|
||||
fontSize: 13,
|
||||
fontStyle: "italic",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h4" fontWeight={500}>
|
||||
<Typography
|
||||
variant="h4"
|
||||
fontWeight={500}
|
||||
fontSize={13}
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -47,8 +76,8 @@ const SkeletonLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<Skeleton variant="rounded" width="20%" height={34} />
|
||||
<Stack gap={theme.gap.xl} mt={theme.gap.medium}>
|
||||
<Stack direction="row" gap={theme.gap.small} mt={theme.gap.small}>
|
||||
<Stack gap={theme.spacing(20)} mt={theme.spacing(6)}>
|
||||
<Stack direction="row" gap={theme.spacing(4)} mt={theme.spacing(4)}>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
style={{ minWidth: 24, minHeight: 24 }}
|
||||
@@ -59,7 +88,7 @@ const SkeletonLayout = () => {
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={18}
|
||||
sx={{ mt: theme.gap.small }}
|
||||
sx={{ mt: theme.spacing(4) }}
|
||||
/>
|
||||
</Box>
|
||||
<Skeleton
|
||||
@@ -72,7 +101,7 @@ const SkeletonLayout = () => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
>
|
||||
<Skeleton variant="rounded" width="100%" height={80} />
|
||||
<Skeleton variant="rounded" width="100%" height={80} />
|
||||
@@ -82,7 +111,7 @@ const SkeletonLayout = () => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.gap.ml}
|
||||
mb={theme.spacing(8)}
|
||||
>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
@@ -96,7 +125,7 @@ const SkeletonLayout = () => {
|
||||
<Skeleton variant="rounded" width="100%" height="100%" />
|
||||
</Box>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.ml}>
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Skeleton variant="rounded" width="20%" height={24} />
|
||||
<Skeleton variant="rounded" width="100%" height={200} />
|
||||
<Skeleton variant="rounded" width="100%" height={50} />
|
||||
@@ -169,26 +198,33 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
{ name: "details", path: `/monitors/${monitorId}` },
|
||||
]}
|
||||
/>
|
||||
<Stack gap={theme.gap.large} mt={theme.gap.large}>
|
||||
<Stack direction="row" gap={theme.gap.xs}>
|
||||
<Stack gap={theme.spacing(12)} mt={theme.spacing(12)}>
|
||||
<Stack direction="row" gap={theme.spacing(2)}>
|
||||
<PulseDot
|
||||
color={
|
||||
monitor?.status
|
||||
? theme.label.up.dotColor
|
||||
: theme.label.down.dotColor
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.main
|
||||
}
|
||||
/>
|
||||
<Box>
|
||||
<Typography component="h1" sx={{ lineHeight: 1 }}>
|
||||
<Typography
|
||||
component="h1"
|
||||
color={theme.palette.text.primary}
|
||||
lineHeight={1}
|
||||
>
|
||||
{monitor.url?.replace(/^https?:\/\//, "") || "..."}
|
||||
</Typography>
|
||||
<Typography mt={theme.gap.small}>
|
||||
<Typography
|
||||
mt={theme.spacing(4)}
|
||||
color={theme.palette.text.tertiary}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
color: monitor?.status
|
||||
? "var(--env-var-color-17)"
|
||||
: "var(--env-var-color-24)",
|
||||
? theme.palette.success.main
|
||||
: theme.palette.success.text,
|
||||
}}
|
||||
>
|
||||
Your site is {monitor?.status ? "up" : "down"}.
|
||||
@@ -204,8 +240,8 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
img={
|
||||
<SettingsIcon
|
||||
style={{
|
||||
minWidth: theme.gap.mlplus,
|
||||
minHeight: theme.gap.mlplus,
|
||||
minWidth: theme.spacing(10),
|
||||
minHeight: theme.spacing(10),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@@ -213,10 +249,10 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
sx={{
|
||||
ml: "auto",
|
||||
alignSelf: "flex-end",
|
||||
backgroundColor: "#f4f4f4",
|
||||
px: theme.gap.medium,
|
||||
backgroundColor: theme.palette.background.fill,
|
||||
px: theme.spacing(6),
|
||||
"& svg": {
|
||||
mr: "6px",
|
||||
mr: theme.spacing(3),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -225,7 +261,7 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
<StatBox
|
||||
@@ -278,20 +314,29 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.gap.ml}
|
||||
mb={theme.spacing(8)}
|
||||
>
|
||||
<Typography component="h2" alignSelf="flex-end">
|
||||
<Typography
|
||||
component="h2"
|
||||
alignSelf="flex-end"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Response Times
|
||||
</Typography>
|
||||
<ButtonGroup>
|
||||
<ButtonGroup
|
||||
sx={{
|
||||
"& .MuiButtonBase-root": {
|
||||
borderColor: theme.palette.border.light,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
level="secondary"
|
||||
label="Day"
|
||||
onClick={() => setDateRange("day")}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
dateRange === "day" &&
|
||||
theme.palette.otherColors.fillGray,
|
||||
dateRange === "day" && theme.palette.background.fill,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
@@ -300,8 +345,7 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
onClick={() => setDateRange("week")}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
dateRange === "week" &&
|
||||
theme.palette.otherColors.fillGray,
|
||||
dateRange === "week" && theme.palette.background.fill,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
@@ -310,19 +354,18 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
onClick={() => setDateRange("month")}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
dateRange === "month" &&
|
||||
theme.palette.otherColors.fillGray,
|
||||
dateRange === "month" && theme.palette.background.fill,
|
||||
}}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</Stack>
|
||||
<Box
|
||||
p={theme.gap.mlplus}
|
||||
pb={theme.gap.xs}
|
||||
backgroundColor={theme.palette.otherColors.white}
|
||||
p={theme.spacing(10)}
|
||||
pb={theme.spacing(2)}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
border={1}
|
||||
borderColor={theme.palette.otherColors.graishWhite}
|
||||
borderRadius={`${theme.shape.borderRadius}px`}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
sx={{ height: "250px" }}
|
||||
>
|
||||
<MonitorDetailsAreaChart
|
||||
@@ -330,8 +373,10 @@ const DetailsPage = ({ isAdmin }) => {
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Stack gap={theme.gap.ml}>
|
||||
<Typography component="h2">History</Typography>
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Typography component="h2" color={theme.palette.text.secondary}>
|
||||
History
|
||||
</Typography>
|
||||
<PaginationTable monitorId={monitorId} dateRange={dateRange} />
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -13,21 +13,21 @@ const StatusBox = ({ title, value }) => {
|
||||
let color;
|
||||
let icon;
|
||||
if (title === "up") {
|
||||
color = theme.pie.green.stroke;
|
||||
color = theme.palette.success.main;
|
||||
icon = (
|
||||
<Box sx={{ ...sharedStyles, top: 8 }}>
|
||||
<Arrow />
|
||||
</Box>
|
||||
);
|
||||
} else if (title === "down") {
|
||||
color = theme.pie.red.stroke;
|
||||
color = theme.palette.error.text;
|
||||
icon = (
|
||||
<Box sx={{ ...sharedStyles, transform: "rotate(180deg)", top: 5 }}>
|
||||
<Arrow />
|
||||
</Box>
|
||||
);
|
||||
} else if (title === "paused") {
|
||||
color = theme.pie.yellow.stroke;
|
||||
color = theme.palette.warning.main;
|
||||
icon = (
|
||||
<Box sx={{ ...sharedStyles, top: 12, right: 12 }}>
|
||||
<ClockSnooze />
|
||||
@@ -40,11 +40,11 @@ const StatusBox = ({ title, value }) => {
|
||||
position="relative"
|
||||
flex={1}
|
||||
border={1}
|
||||
borderColor={theme.palette.otherColors.graishWhite}
|
||||
borderRadius={`${theme.shape.borderRadius}px`}
|
||||
backgroundColor={theme.palette.otherColors.white}
|
||||
px={theme.gap.large}
|
||||
py={theme.gap.ml}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
px={theme.spacing(12)}
|
||||
py={theme.spacing(8)}
|
||||
overflow="hidden"
|
||||
sx={{
|
||||
"&:hover": {
|
||||
@@ -67,8 +67,8 @@ const StatusBox = ({ title, value }) => {
|
||||
textTransform="uppercase"
|
||||
fontSize={15}
|
||||
letterSpacing={0.5}
|
||||
color={theme.palette.otherColors.bluishGray}
|
||||
mb={theme.gap.ml}
|
||||
color={theme.palette.text.secondary}
|
||||
mb={theme.spacing(8)}
|
||||
sx={{ opacity: 0.6 }}
|
||||
>
|
||||
{title}
|
||||
@@ -87,7 +87,7 @@ const StatusBox = ({ title, value }) => {
|
||||
component="span"
|
||||
fontSize={20}
|
||||
fontWeight={300}
|
||||
color={theme.palette.otherColors.bluishGray}
|
||||
color={theme.palette.text.secondary}
|
||||
sx={{ opacity: 0.3 }}
|
||||
>
|
||||
#
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import {
|
||||
IconButton,
|
||||
@@ -14,10 +16,8 @@ import {
|
||||
getUptimeMonitorsByTeamId,
|
||||
} from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import Settings from "../../../assets/icons/settings-bold.svg?react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import Button from "../../../Components/Button";
|
||||
import PropTypes from "prop-types";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const ActionsMenu = ({ monitor, isAdmin }) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
@@ -87,6 +87,30 @@ const ActionsMenu = ({ monitor, isAdmin }) => {
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={(e) => closeMenu(e)}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
border: 1,
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: theme.shape.boxShadow,
|
||||
"& ul": {
|
||||
p: theme.spacing(2.5),
|
||||
minWidth: "100px",
|
||||
},
|
||||
"& li": {
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 13,
|
||||
px: theme.spacing(4),
|
||||
py: theme.spacing(2.5),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
},
|
||||
"& li:last-of-type": {
|
||||
color: theme.palette.error.text,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{actions.url !== null ? (
|
||||
<MenuItem
|
||||
@@ -137,31 +161,35 @@ const ActionsMenu = ({ monitor, isAdmin }) => {
|
||||
aria-labelledby="modal-delete-monitor"
|
||||
aria-describedby="delete-monitor-confirmation"
|
||||
open={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
disablePortal
|
||||
onClose={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(false);
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
gap={theme.gap.xs}
|
||||
gap={theme.spacing(2)}
|
||||
color={theme.palette.text.secondary}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "white",
|
||||
border: "solid 1px #f2f2f2",
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
bgcolor: theme.palette.background.main,
|
||||
border: 1,
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: 24,
|
||||
p: "30px",
|
||||
p: theme.spacing(15),
|
||||
"&:focus": {
|
||||
outline: "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography id="modal-delete-monitor" component="h2">
|
||||
<Typography id="modal-delete-monitor" component="h2" fontWeight={600}>
|
||||
Do you really want to delete this monitor?
|
||||
</Typography>
|
||||
<Typography id="delete-monitor-confirmation">
|
||||
<Typography id="delete-monitor-confirmation" fontSize={13}>
|
||||
Once deleted, this monitor cannot be retrieved.
|
||||
</Typography>
|
||||
<Stack
|
||||
@@ -173,12 +201,18 @@ const ActionsMenu = ({ monitor, isAdmin }) => {
|
||||
<Button
|
||||
level="tertiary"
|
||||
label="Cancel"
|
||||
onClick={() => setIsOpen(false)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(false);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
level="error"
|
||||
label="Delete"
|
||||
onClick={(e) => handleRemove(e)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(e);
|
||||
handleRemove(e);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -11,12 +11,13 @@ const Fallback = ({ isAdmin }) => {
|
||||
return (
|
||||
<Stack
|
||||
alignItems="center"
|
||||
backgroundColor={theme.palette.otherColors.white}
|
||||
p={theme.gap.xxl}
|
||||
gap={theme.gap.xs}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
p={theme.spacing(30)}
|
||||
gap={theme.spacing(2)}
|
||||
border={1}
|
||||
borderRadius={`${theme.shape.borderRadius}px`}
|
||||
borderColor={theme.palette.otherColors.graishWhite}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
borderColor={theme.palette.border.light}
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
<Typography component="h2">No monitors found</Typography>
|
||||
<Typography>
|
||||
@@ -29,7 +30,7 @@ const Fallback = ({ isAdmin }) => {
|
||||
onClick={() => {
|
||||
navigate("/monitors/create");
|
||||
}}
|
||||
sx={{ mt: theme.gap.large }}
|
||||
sx={{ mt: theme.spacing(12) }}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import PropTypes from "prop-types";
|
||||
/**
|
||||
* Host component.
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
.monitors h1.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
.monitors h2.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large);
|
||||
color: var(--secondary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
.monitors p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.monitors h1.MuiTypography-root + p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium-plus);
|
||||
@@ -28,36 +25,9 @@
|
||||
padding: 5px;
|
||||
min-width: 25px;
|
||||
min-height: 25px;
|
||||
background-color: var(--unresolved-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 50%;
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
margin-left: 10px;
|
||||
line-height: 0.8;
|
||||
}
|
||||
|
||||
body:has(.monitors) .actions-menu .MuiPaper-root {
|
||||
box-shadow: var(--env-var-shadow-1);
|
||||
border: solid 1px var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
gap: 1px;
|
||||
}
|
||||
body:has(.monitors) .actions-menu .MuiList-root {
|
||||
padding: 6px 8px;
|
||||
min-width: 100px;
|
||||
}
|
||||
body:has(.monitors) .actions-menu li.MuiButtonBase-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
color: var(--secondary-color);
|
||||
padding: 5px 8px;
|
||||
border-radius: var(--env-var-radius-1);
|
||||
}
|
||||
body:has(.monitors) .actions-menu li.MuiButtonBase-root:last-of-type {
|
||||
color: var(--error-color);
|
||||
}
|
||||
body:has(.monitors) .actions-menu .MuiModal-root p.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-medium);
|
||||
color: var(--secondary-color-light);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const Monitors = ({ isAdmin }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack className="monitors" gap={theme.gap.large}>
|
||||
<Stack className="monitors" gap={theme.spacing(12)}>
|
||||
{loading ? (
|
||||
<SkeletonLayout />
|
||||
) : (
|
||||
@@ -65,11 +65,15 @@ const Monitors = ({ isAdmin }) => {
|
||||
mt={theme.spacing(5)}
|
||||
>
|
||||
<Box>
|
||||
<Typography component="h1" lineHeight={1}>
|
||||
<Typography
|
||||
component="h1"
|
||||
lineHeight={1}
|
||||
color={theme.palette.text.primary}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
fontSize="inherit"
|
||||
color={theme.palette.otherColors.bluishGray}
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Good {greeting},{" "}
|
||||
</Typography>
|
||||
@@ -85,6 +89,7 @@ const Monitors = ({ isAdmin }) => {
|
||||
sx={{ opacity: 0.8 }}
|
||||
lineHeight={1}
|
||||
fontWeight={300}
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Here’s an overview of your uptime monitors.
|
||||
</Typography>
|
||||
@@ -108,7 +113,7 @@ const Monitors = ({ isAdmin }) => {
|
||||
{monitorState.monitors?.length !== 0 && (
|
||||
<>
|
||||
<Stack
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
@@ -118,17 +123,30 @@ const Monitors = ({ isAdmin }) => {
|
||||
</Stack>
|
||||
<Box
|
||||
flex={1}
|
||||
p={theme.gap.lgplus}
|
||||
p={theme.spacing(16)}
|
||||
border={1}
|
||||
borderColor={theme.palette.otherColors.graishWhite}
|
||||
backgroundColor={theme.palette.otherColors.white}
|
||||
sx={{
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
}}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" mb={theme.gap.large}>
|
||||
<Typography component="h2">Current monitors</Typography>
|
||||
<Box className="current-monitors-counter">
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
mb={theme.spacing(12)}
|
||||
>
|
||||
<Typography
|
||||
component="h2"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Current monitors
|
||||
</Typography>
|
||||
<Box
|
||||
className="current-monitors-counter"
|
||||
color={theme.palette.text.primary}
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
backgroundColor={theme.palette.unresolved.bg}
|
||||
>
|
||||
{monitorState.monitors.length}
|
||||
</Box>
|
||||
{/* TODO - add search bar */}
|
||||
|
||||
@@ -16,7 +16,7 @@ const SkeletonLayout = () => {
|
||||
<Skeleton variant="rounded" width="15%" height={36} />
|
||||
</Stack>
|
||||
<Stack
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
@@ -24,7 +24,11 @@ const SkeletonLayout = () => {
|
||||
<Skeleton variant="rounded" width="100%" height={100} />
|
||||
<Skeleton variant="rounded" width="100%" height={100} />
|
||||
</Stack>
|
||||
<Stack gap={theme.gap.large} p={theme.gap.xl} backgroundColor="#f9fafb">
|
||||
<Stack
|
||||
gap={theme.spacing(12)}
|
||||
p={theme.spacing(20)}
|
||||
backgroundColor="#f9fafb"
|
||||
>
|
||||
<Skeleton variant="rounded" width="50%" height={25} />
|
||||
<Skeleton variant="rounded" width="100%" height={300} />
|
||||
<Skeleton variant="rounded" width="100%" height={100} />
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Stack, styled } from "@mui/material";
|
||||
|
||||
export const ConfigBox = styled(Stack)(({ theme }) => ({
|
||||
flexDirection: "row",
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.spacing(2),
|
||||
backgroundColor: theme.palette.background.main,
|
||||
"& > *": {
|
||||
paddingTop: theme.spacing(12),
|
||||
paddingBottom: theme.spacing(18),
|
||||
},
|
||||
"& > div:first-of-type": {
|
||||
flex: 0.7,
|
||||
borderRight: 1,
|
||||
borderRightStyle: "solid",
|
||||
borderRightColor: theme.palette.border.light,
|
||||
paddingRight: theme.spacing(15),
|
||||
paddingLeft: theme.spacing(15),
|
||||
},
|
||||
"& > div:last-of-type": {
|
||||
flex: 1,
|
||||
paddingRight: theme.spacing(20),
|
||||
paddingLeft: theme.spacing(18),
|
||||
},
|
||||
"& h2": {
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 15,
|
||||
fontWeight: 600,
|
||||
},
|
||||
"& h3, & p": {
|
||||
color: theme.palette.text.tertiary,
|
||||
},
|
||||
}));
|
||||
@@ -1,23 +1,9 @@
|
||||
.configure-pagespeed form > .MuiStack-root:nth-child(2) {
|
||||
background-color: var(--primary-bg);
|
||||
border: solid 1px var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
padding: var(--env-var-font-size-large-plus) var(--env-var-font-size-xlarge);
|
||||
}
|
||||
.configure-pagespeed h1.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
}
|
||||
.configure-pagespeed h1.MuiTypography-root,
|
||||
.configure-pagespeed h2.MuiTypography-root {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.configure-pagespeed span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
}
|
||||
.configure-pagespeed p.MuiTypography-root,
|
||||
.configure-pagespeed h3.MuiTypography-root {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.configure-pagespeed h1.MuiTypography-root,
|
||||
.configure-pagespeed h3.MuiTypography-root,
|
||||
.configure-pagespeed h2.MuiTypography-root {
|
||||
@@ -38,13 +24,10 @@
|
||||
.configure-pagespeed .checkbox-wrapper {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
.configure-pagespeed .MuiInputBase-root:has(> .Mui-disabled) {
|
||||
background-color: var(--primary-bg-accent);
|
||||
}
|
||||
|
||||
/* to be removed */
|
||||
.configure-pagespeed .section-disabled {
|
||||
opacity: 0.4;
|
||||
background-color: #f1f1f2;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
user-select: none;
|
||||
@@ -55,11 +38,6 @@
|
||||
height: var(--env-var-height-2);
|
||||
}
|
||||
|
||||
body:has(.configure-pagespeed) .select-dropdown .MuiMenuItem-root,
|
||||
.configure-pagespeed .select-wrapper .select-component > .MuiSelect-select {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.configure-pagespeed h3.MuiTypography-root {
|
||||
flex: 0.7;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ const SkeletonLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<Skeleton variant="rounded" width="15%" height={34} />
|
||||
<Stack gap={theme.gap.xl} mt={theme.gap.medium} maxWidth="1000px">
|
||||
<Stack direction="row" gap={theme.gap.small} mt={theme.gap.small}>
|
||||
<Stack gap={theme.spacing(20)} mt={theme.spacing(6)} maxWidth="1000px">
|
||||
<Stack direction="row" gap={theme.spacing(4)} mt={theme.spacing(4)}>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
style={{ minWidth: 24, minHeight: 24 }}
|
||||
@@ -43,13 +43,13 @@ const SkeletonLayout = () => {
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={24}
|
||||
sx={{ mb: theme.gap.small }}
|
||||
sx={{ mb: theme.spacing(4) }}
|
||||
/>
|
||||
<Skeleton variant="rounded" width="50%" height={18} />
|
||||
</Box>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.gap.medium}
|
||||
gap={theme.spacing(6)}
|
||||
sx={{
|
||||
ml: "auto",
|
||||
alignSelf: "flex-end",
|
||||
@@ -147,7 +147,7 @@ const PageSpeedConfigure = () => {
|
||||
let loading = Object.keys(monitor).length === 0;
|
||||
|
||||
return (
|
||||
<Stack className="configure-pagespeed" gap={theme.gap.large}>
|
||||
<Stack className="configure-pagespeed" gap={theme.spacing(12)}>
|
||||
{loading ? (
|
||||
<SkeletonLayout />
|
||||
) : (
|
||||
@@ -165,21 +165,22 @@ const PageSpeedConfigure = () => {
|
||||
spellCheck="false"
|
||||
onSubmit={handleSave}
|
||||
flex={1}
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
>
|
||||
<Stack direction="row" gap={theme.gap.xs}>
|
||||
<Stack direction="row" gap={theme.spacing(2)}>
|
||||
<PulseDot
|
||||
color={
|
||||
monitor?.status
|
||||
? theme.label.up.dotColor
|
||||
: theme.label.down.dotColor
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.main
|
||||
}
|
||||
/>
|
||||
<Box>
|
||||
<Typography
|
||||
component="h1"
|
||||
mb={theme.gap.xs}
|
||||
mb={theme.spacing(2)}
|
||||
sx={{ lineHeight: 1 }}
|
||||
color={theme.palette.text.primary}
|
||||
>
|
||||
{monitor?.url}
|
||||
</Typography>
|
||||
@@ -187,8 +188,8 @@ const PageSpeedConfigure = () => {
|
||||
component="span"
|
||||
sx={{
|
||||
color: monitor?.status
|
||||
? "var(--success-color)"
|
||||
: "var(--error-color)",
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.text,
|
||||
}}
|
||||
>
|
||||
Your pagespeed monitor is {monitor?.status ? "live" : "down"}.
|
||||
@@ -201,11 +202,11 @@ const PageSpeedConfigure = () => {
|
||||
animate="rotate180"
|
||||
img={<PauseCircleOutlineIcon />}
|
||||
sx={{
|
||||
backgroundColor: theme.palette.otherColors.fillGray,
|
||||
pl: theme.gap.small,
|
||||
pr: theme.gap.medium,
|
||||
backgroundColor: theme.palette.background.fill,
|
||||
pl: theme.spacing(4),
|
||||
pr: theme.spacing(6),
|
||||
"& svg": {
|
||||
mr: theme.gap.xs,
|
||||
mr: theme.spacing(2),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@@ -214,14 +215,27 @@ const PageSpeedConfigure = () => {
|
||||
label="Remove"
|
||||
sx={{
|
||||
boxShadow: "none",
|
||||
px: theme.gap.ml,
|
||||
ml: theme.gap.medium,
|
||||
px: theme.spacing(8),
|
||||
ml: theme.spacing(6),
|
||||
}}
|
||||
onClick={() => setIsOpen(true)}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Stack gap={theme.gap.xl}>
|
||||
<Stack
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
p={theme.spacing(20)}
|
||||
pl={theme.spacing(15)}
|
||||
gap={theme.spacing(20)}
|
||||
sx={{
|
||||
"& h3, & p": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Stack direction="row">
|
||||
<Typography component="h3">Monitor display name</Typography>
|
||||
<Field
|
||||
@@ -233,7 +247,14 @@ const PageSpeedConfigure = () => {
|
||||
error={errors.name}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack direction="row">
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
".MuiInputBase-root:has(> .Mui-disabled)": {
|
||||
backgroundColor: theme.palette.background.accent,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography component="h3">URL</Typography>
|
||||
<Field
|
||||
type="url"
|
||||
@@ -259,8 +280,11 @@ const PageSpeedConfigure = () => {
|
||||
Incidents notifications{" "}
|
||||
<Typography component="span">(coming soon)</Typography>
|
||||
</Typography>
|
||||
<Stack className="section-disabled">
|
||||
<Typography mb={theme.gap.small}>
|
||||
<Stack
|
||||
className="section-disabled"
|
||||
backgroundColor={theme.palette.background.fill}
|
||||
>
|
||||
<Typography mb={theme.spacing(4)}>
|
||||
When there is a new incident,
|
||||
</Typography>
|
||||
<Checkbox
|
||||
@@ -279,7 +303,7 @@ const PageSpeedConfigure = () => {
|
||||
label="Notify via email to following emails"
|
||||
isChecked={false}
|
||||
/>
|
||||
<Box mx={`calc(${theme.gap.ml} * 2)`}>
|
||||
<Box mx={theme.spacing(16)}>
|
||||
<Field
|
||||
id="notify-emails-list"
|
||||
placeholder="notifications@gmail.com"
|
||||
@@ -287,7 +311,7 @@ const PageSpeedConfigure = () => {
|
||||
onChange={() => logger.warn("disabled")}
|
||||
error=""
|
||||
/>
|
||||
<Typography mt={theme.gap.small}>
|
||||
<Typography mt={theme.spacing(4)}>
|
||||
You can separate multiple emails with a comma
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -300,7 +324,7 @@ const PageSpeedConfigure = () => {
|
||||
level="primary"
|
||||
label="Save"
|
||||
onClick={handleSave}
|
||||
sx={{ px: theme.gap.large, mt: theme.gap.large }}
|
||||
sx={{ px: theme.spacing(12), mt: theme.spacing(12) }}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
@@ -314,33 +338,41 @@ const PageSpeedConfigure = () => {
|
||||
disablePortal
|
||||
>
|
||||
<Stack
|
||||
gap={theme.gap.xs}
|
||||
gap={theme.spacing(2)}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "white",
|
||||
border: "solid 1px #f2f2f2",
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
bgcolor: theme.palette.background.main,
|
||||
border: 1,
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxShadow: 24,
|
||||
p: "30px",
|
||||
p: theme.spacing(15),
|
||||
"&:focus": {
|
||||
outline: "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography id="modal-delete-pagespeed-monitor" component="h2">
|
||||
<Typography
|
||||
id="modal-delete-pagespeed-monitor"
|
||||
component="h2"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Do you really want to delete this monitor?
|
||||
</Typography>
|
||||
<Typography id="delete-pagespeed-monitor-confirmation">
|
||||
<Typography
|
||||
id="delete-pagespeed-monitor-confirmation"
|
||||
color={theme.palette.text.tertiary}
|
||||
>
|
||||
Once deleted, this monitor cannot be retrieved.
|
||||
</Typography>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.gap.small}
|
||||
mt={theme.gap.large}
|
||||
gap={theme.spacing(4)}
|
||||
mt={theme.spacing(12)}
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
.create-page-speed form > .MuiStack-root:not(:last-of-type) {
|
||||
background-color: var(--primary-bg);
|
||||
border: solid 1px var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
padding: var(--env-var-font-size-large-plus) var(--env-var-font-size-xlarge);
|
||||
}
|
||||
.create-page-speed h1.MuiTypography-root {
|
||||
font-size: 22px;
|
||||
color: var(--primary-bg);
|
||||
}
|
||||
.create-page-speed p.MuiTypography-root,
|
||||
.create-page-speed h3.MuiTypography-root {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.create-page-speed h1.MuiTypography-root,
|
||||
.create-page-speed h3.MuiTypography-root {
|
||||
font-weight: 600;
|
||||
@@ -31,10 +17,10 @@
|
||||
.create-page-speed .checkbox-wrapper {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
/* to be removed */
|
||||
.create-page-speed .section-disabled {
|
||||
opacity: 0.4;
|
||||
background-color: #f1f1f2;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
user-select: none;
|
||||
@@ -45,11 +31,6 @@
|
||||
height: var(--env-var-height-2);
|
||||
}
|
||||
|
||||
body:has(.create-page-speed) .select-dropdown .MuiMenuItem-root,
|
||||
.create-page-speed .select-wrapper .select-component > .MuiSelect-select {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.create-page-speed h3.MuiTypography-root {
|
||||
flex: 0.7;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ const CreatePageSpeed = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack className="create-page-speed" gap={theme.gap.mlplus}>
|
||||
<Stack className="create-page-speed" gap={theme.spacing(6)}>
|
||||
<Breadcrumbs
|
||||
list={[
|
||||
{ name: "pagespeed", path: "/pagespeed" },
|
||||
@@ -111,11 +111,47 @@ const CreatePageSpeed = () => {
|
||||
noValidate
|
||||
spellCheck="false"
|
||||
onSubmit={handleCreate}
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
flex={1}
|
||||
>
|
||||
<Typography component="h1">Create pagespeed monitor</Typography>
|
||||
<Stack gap={theme.gap.xl}>
|
||||
<Typography
|
||||
component="h1"
|
||||
lineHeight={1}
|
||||
fontSize={21}
|
||||
color={theme.palette.text.primary}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
fontSize="inherit"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
Create your{" "}
|
||||
</Typography>
|
||||
<Typography component="span" fontSize="inherit" fontWeight="inherit">
|
||||
pagespeed{" "}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="span"
|
||||
fontSize="inherit"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
monitor
|
||||
</Typography>
|
||||
</Typography>
|
||||
<Stack
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
p={theme.spacing(20)}
|
||||
pl={theme.spacing(15)}
|
||||
gap={theme.spacing(20)}
|
||||
sx={{
|
||||
"& h3, & p": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Stack direction="row">
|
||||
<Typography component="h3">Monitor display name</Typography>
|
||||
<Field
|
||||
@@ -152,8 +188,11 @@ const CreatePageSpeed = () => {
|
||||
Incidents notifications{" "}
|
||||
<Typography component="span">(coming soon)</Typography>
|
||||
</Typography>
|
||||
<Stack className="section-disabled">
|
||||
<Typography mb={theme.gap.small}>
|
||||
<Stack
|
||||
className="section-disabled"
|
||||
backgroundColor={theme.palette.background.fill}
|
||||
>
|
||||
<Typography mb={theme.spacing(4)}>
|
||||
When there is a new incident,
|
||||
</Typography>
|
||||
<Checkbox
|
||||
@@ -180,7 +219,7 @@ const CreatePageSpeed = () => {
|
||||
onChange={() => logger.warn("disabled")}
|
||||
error=""
|
||||
/>
|
||||
<Typography mt={theme.gap.small}>
|
||||
<Typography mt={theme.spacing(4)}>
|
||||
You can separate multiple emails with a comma
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -193,7 +232,7 @@ const CreatePageSpeed = () => {
|
||||
level="primary"
|
||||
label="Create"
|
||||
onClick={handleCreate}
|
||||
sx={{ px: theme.gap.large, mt: theme.gap.large }}
|
||||
sx={{ px: theme.spacing(12), mt: theme.spacing(12) }}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.page-speed-details h1 {
|
||||
font-size: var(--env-var-font-size-large-plus);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.page-speed-details h2,
|
||||
.page-speed-details h6 {
|
||||
@@ -15,13 +14,7 @@
|
||||
.page-speed-details h4 > span {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
}
|
||||
.page-speed-details h2,
|
||||
.page-speed-details h4,
|
||||
.page-speed-details p {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.page-speed-details h6 {
|
||||
color: var(--theme-main);
|
||||
line-height: 22px;
|
||||
}
|
||||
.page-speed-details h1,
|
||||
@@ -33,14 +26,6 @@
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.page-speed-details .stat-box,
|
||||
.page-speed-details > .MuiStack-root:last-child,
|
||||
.page-speed-details > .MuiBox-root:nth-last-child(3) {
|
||||
border: solid 1px var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
background-color: var(--primary-bg);
|
||||
min-width: 200px;
|
||||
}
|
||||
.page-speed-details .stat-box {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -29,17 +29,28 @@ const StatBox = ({ icon, title, value }) => {
|
||||
<Stack
|
||||
className="stat-box"
|
||||
direction="row"
|
||||
gap={theme.gap.small}
|
||||
pt={theme.gap.ml}
|
||||
px={theme.gap.ml}
|
||||
pb={theme.gap.mlplus}
|
||||
gap={theme.spacing(4)}
|
||||
pt={theme.spacing(8)}
|
||||
px={theme.spacing(8)}
|
||||
pb={theme.spacing(10)}
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
minWidth="200px"
|
||||
>
|
||||
{icon}
|
||||
<Box>
|
||||
<Typography variant="h6" mb={theme.gap.medium}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color={theme.palette.common.main}
|
||||
mb={theme.spacing(6)}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h4">{value}</Typography>
|
||||
<Typography variant="h4" color={theme.palette.text.secondary}>
|
||||
{value}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
@@ -151,7 +162,7 @@ const SkeletonLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<Skeleton variant="rounded" width="15%" height={34} />
|
||||
<Stack direction="row" gap={theme.gap.small}>
|
||||
<Stack direction="row" gap={theme.spacing(4)}>
|
||||
<Skeleton variant="circular" style={{ minWidth: 24, minHeight: 24 }} />
|
||||
<Box width="85%">
|
||||
<Skeleton variant="rounded" width="50%" height={24} />
|
||||
@@ -159,7 +170,7 @@ const SkeletonLayout = () => {
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={18}
|
||||
sx={{ mt: theme.gap.small }}
|
||||
sx={{ mt: theme.spacing(4) }}
|
||||
/>
|
||||
</Box>
|
||||
<Skeleton
|
||||
@@ -172,7 +183,7 @@ const SkeletonLayout = () => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
gap={theme.gap.xl}
|
||||
gap={theme.spacing(20)}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
<Skeleton variant="rounded" width="30%" height={90} sx={{ flex: 1 }} />
|
||||
@@ -237,10 +248,37 @@ const PageSpeedDetails = () => {
|
||||
* @returns {{stroke: string, text: string, bg: string}} The color properties for the given performance value.
|
||||
*/
|
||||
const getColors = (value) => {
|
||||
if (value >= 90 && value <= 100) return theme.pie.green;
|
||||
else if (value >= 50 && value < 90) return theme.pie.yellow;
|
||||
else if (value >= 0 && value < 50) return theme.pie.red;
|
||||
return theme.pie.default;
|
||||
if (value >= 90 && value <= 100)
|
||||
return {
|
||||
stroke: theme.palette.success.main,
|
||||
strokeBg: theme.palette.success.light,
|
||||
text: theme.palette.success.text,
|
||||
bg: theme.palette.success.bg,
|
||||
shape: "circle",
|
||||
};
|
||||
else if (value >= 50 && value < 90)
|
||||
return {
|
||||
stroke: theme.palette.warning.main,
|
||||
strokeBg: theme.palette.warning.bg,
|
||||
text: theme.palette.warning.text,
|
||||
bg: theme.palette.warning.light,
|
||||
shape: "square",
|
||||
};
|
||||
else if (value >= 0 && value < 50)
|
||||
return {
|
||||
stroke: theme.palette.error.text,
|
||||
strokeBg: theme.palette.error.light,
|
||||
text: theme.palette.error.text,
|
||||
bg: theme.palette.error.bg,
|
||||
shape: "circle",
|
||||
};
|
||||
return {
|
||||
stroke: theme.palette.unresolved.main,
|
||||
strokeBg: theme.palette.unresolved.light,
|
||||
text: theme.palette.unresolved.main,
|
||||
bg: theme.palette.unresolved.bg,
|
||||
shape: "",
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -312,8 +350,15 @@ const PageSpeedDetails = () => {
|
||||
|
||||
let loading = Object.keys(monitor).length === 0;
|
||||
const data = monitor?.checks ? [...monitor.checks].reverse() : [];
|
||||
|
||||
let sharedStyles = {
|
||||
border: 1,
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
backgroundColor: theme.palette.background.main,
|
||||
};
|
||||
return (
|
||||
<Stack className="page-speed-details" gap={theme.gap.large}>
|
||||
<Stack className="page-speed-details" gap={theme.spacing(12)}>
|
||||
{loading ? (
|
||||
<SkeletonLayout />
|
||||
) : (
|
||||
@@ -324,25 +369,30 @@ const PageSpeedDetails = () => {
|
||||
{ name: "details", path: `/pagespeed/${monitorId}` },
|
||||
]}
|
||||
/>
|
||||
<Stack direction="row" gap={theme.gap.xs}>
|
||||
<Stack direction="row" gap={theme.spacing(2)}>
|
||||
<PulseDot
|
||||
color={
|
||||
monitor?.status
|
||||
? theme.label.up.dotColor
|
||||
: theme.label.down.dotColor
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.main
|
||||
}
|
||||
/>
|
||||
<Box>
|
||||
<Typography
|
||||
component="h1"
|
||||
mb={theme.gap.xs}
|
||||
mb={theme.spacing(2)}
|
||||
color={theme.palette.text.primary}
|
||||
sx={{ lineHeight: 1 }}
|
||||
>
|
||||
{monitor?.url}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ color: "var(--success-color)" }}
|
||||
color={
|
||||
monitor?.status
|
||||
? theme.palette.success.main
|
||||
: theme.palette.error.text
|
||||
}
|
||||
>
|
||||
Your pagespeed monitor is live.
|
||||
</Typography>
|
||||
@@ -353,15 +403,18 @@ const PageSpeedDetails = () => {
|
||||
animate="rotate90"
|
||||
img={
|
||||
<SettingsIcon
|
||||
style={{ width: theme.gap.mlplus, height: theme.gap.mlplus }}
|
||||
style={{
|
||||
width: theme.spacing(10),
|
||||
height: theme.spacing(10),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
onClick={() => navigate(`/pagespeed/configure/${monitorId}`)}
|
||||
sx={{
|
||||
ml: "auto",
|
||||
alignSelf: "flex-end",
|
||||
backgroundColor: theme.palette.otherColors.fillGray,
|
||||
px: theme.gap.medium,
|
||||
backgroundColor: theme.palette.background.fill,
|
||||
px: theme.spacing(6),
|
||||
"& svg": {
|
||||
mr: "6px",
|
||||
},
|
||||
@@ -371,7 +424,7 @@ const PageSpeedDetails = () => {
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
gap={theme.gap.large}
|
||||
gap={theme.spacing(12)}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
<StatBox
|
||||
@@ -412,19 +465,39 @@ const PageSpeedDetails = () => {
|
||||
value={formatDurationRounded(monitor?.interval)}
|
||||
></StatBox>
|
||||
</Stack>
|
||||
<Typography component="h2">Score history</Typography>
|
||||
<Box height="300px">
|
||||
<Typography component="h2" color={theme.palette.text.secondary}>
|
||||
Score history
|
||||
</Typography>
|
||||
<Box
|
||||
height="300px"
|
||||
sx={{
|
||||
...sharedStyles,
|
||||
}}
|
||||
>
|
||||
<PageSpeedLineChart pageSpeedChecks={data} />
|
||||
</Box>
|
||||
<Typography component="h2">Performance report</Typography>
|
||||
<Stack direction="row" alignItems="center" overflow="hidden" flex={1}>
|
||||
<Typography component="h2" color={theme.palette.text.secondary}>
|
||||
Performance report
|
||||
</Typography>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
overflow="hidden"
|
||||
flex={1}
|
||||
sx={{
|
||||
"& p": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
...sharedStyles,
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
alignItems="center"
|
||||
textAlign="center"
|
||||
minWidth="300px"
|
||||
flex={1}
|
||||
px={theme.gap.xl}
|
||||
py={theme.gap.ml}
|
||||
px={theme.spacing(20)}
|
||||
py={theme.spacing(8)}
|
||||
>
|
||||
<Box onMouseLeave={() => setExpand(false)}>
|
||||
{expand ? (
|
||||
@@ -514,12 +587,12 @@ const PageSpeedDetails = () => {
|
||||
</PieChart>
|
||||
)}
|
||||
</Box>
|
||||
<Typography mt={theme.gap.medium}>
|
||||
<Typography mt={theme.spacing(6)}>
|
||||
Values are estimated and may vary.{" "}
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
color: theme.palette.primary.main,
|
||||
color: theme.palette.common.main,
|
||||
fontWeight: 500,
|
||||
textDecoration: "underline",
|
||||
cursor: "pointer",
|
||||
@@ -530,21 +603,23 @@ const PageSpeedDetails = () => {
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Box
|
||||
px={theme.gap.xl}
|
||||
py={theme.gap.ml}
|
||||
px={theme.spacing(20)}
|
||||
py={theme.spacing(8)}
|
||||
height="100%"
|
||||
flex={1}
|
||||
sx={{
|
||||
borderLeft: `solid 1px ${theme.palette.otherColors.graishWhite}`,
|
||||
borderLeft: 1,
|
||||
borderLeftColor: theme.palette.border.light,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
mb={theme.gap.medium}
|
||||
pb={theme.gap.ml}
|
||||
color={theme.palette.secondary.main}
|
||||
mb={theme.spacing(6)}
|
||||
pb={theme.spacing(8)}
|
||||
color={theme.palette.text.secondary}
|
||||
textAlign="center"
|
||||
sx={{
|
||||
borderBottom: `solid 1px ${theme.palette.otherColors.graishWhite}`,
|
||||
borderBottom: 1,
|
||||
borderBottomColor: theme.palette.border.light,
|
||||
borderBottomStyle: "dashed",
|
||||
}}
|
||||
>
|
||||
@@ -552,7 +627,7 @@ const PageSpeedDetails = () => {
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
color: theme.palette.primary.main,
|
||||
color: theme.palette.common.main,
|
||||
fontWeight: 500,
|
||||
textDecoration: "underline",
|
||||
cursor: "pointer",
|
||||
@@ -569,8 +644,8 @@ const PageSpeedDetails = () => {
|
||||
<Stack
|
||||
direction="row"
|
||||
flexWrap="wrap"
|
||||
pt={theme.gap.ml}
|
||||
gap={theme.gap.ml}
|
||||
pt={theme.spacing(8)}
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
{Object.keys(audits).map((key) => {
|
||||
if (key === "_id") return;
|
||||
@@ -581,8 +656,8 @@ const PageSpeedDetails = () => {
|
||||
let shape = (
|
||||
<Box
|
||||
sx={{
|
||||
width: theme.gap.medium,
|
||||
height: theme.gap.medium,
|
||||
width: theme.spacing(6),
|
||||
height: theme.spacing(6),
|
||||
borderRadius: "50%",
|
||||
backgroundColor: metricParams.stroke,
|
||||
}}
|
||||
@@ -592,8 +667,8 @@ const PageSpeedDetails = () => {
|
||||
shape = (
|
||||
<Box
|
||||
sx={{
|
||||
width: theme.gap.medium,
|
||||
height: theme.gap.medium,
|
||||
width: theme.spacing(6),
|
||||
height: theme.spacing(6),
|
||||
backgroundColor: metricParams.stroke,
|
||||
}}
|
||||
></Box>
|
||||
@@ -604,10 +679,14 @@ const PageSpeedDetails = () => {
|
||||
sx={{
|
||||
width: 0,
|
||||
height: 0,
|
||||
ml: `calc((${theme.gap.medium} - ${theme.gap.small}) / -2)`,
|
||||
borderLeft: `${theme.gap.small} solid transparent`,
|
||||
borderRight: `${theme.gap.small} solid transparent`,
|
||||
borderBottom: `${theme.gap.medium} solid ${metricParams.stroke}`,
|
||||
ml: `calc((${theme.spacing(6)} - ${theme.spacing(
|
||||
4
|
||||
)}) / -2)`,
|
||||
borderLeft: `${theme.spacing(4)} solid transparent`,
|
||||
borderRight: `${theme.spacing(4)} solid transparent`,
|
||||
borderBottom: `${theme.spacing(6)} solid ${
|
||||
metricParams.stroke
|
||||
}`,
|
||||
}}
|
||||
></Box>
|
||||
);
|
||||
@@ -630,7 +709,7 @@ const PageSpeedDetails = () => {
|
||||
className="metric"
|
||||
key={`${key}-box`}
|
||||
direction="row"
|
||||
gap={theme.gap.small}
|
||||
gap={theme.spacing(4)}
|
||||
>
|
||||
{shape}
|
||||
<Box>
|
||||
@@ -650,8 +729,8 @@ const PageSpeedDetails = () => {
|
||||
component="span"
|
||||
ml="2px"
|
||||
sx={{
|
||||
color: theme.palette.secondary.main,
|
||||
fontSize: "13px",
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: 13,
|
||||
}}
|
||||
>
|
||||
{unit}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
.page-speed h1.MuiTypography-root,
|
||||
.page-speed span.MuiTypography-root,
|
||||
.page-speed p.MuiTypography-root {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
.page-speed h2.MuiTypography-root {
|
||||
color: var(--theme-main);
|
||||
line-height: 1.1;
|
||||
}
|
||||
.page-speed h1.MuiTypography-root,
|
||||
@@ -19,11 +13,6 @@
|
||||
.page-speed p.MuiTypography-root > span.MuiTypography-root {
|
||||
font-size: var(--env-var-font-size-small-plus);
|
||||
}
|
||||
.page-speed .MuiGrid-item > .MuiStack-root {
|
||||
border: solid 1px var(--border-color);
|
||||
border-radius: var(--env-var-radius-1);
|
||||
background-color: var(--primary-bg);
|
||||
}
|
||||
.page-speed .label {
|
||||
padding: 7px;
|
||||
height: 22px;
|
||||
|
||||
@@ -30,15 +30,25 @@ const Card = ({ data }) => {
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.gap.medium}
|
||||
p={theme.gap.ml}
|
||||
gap={theme.spacing(6)}
|
||||
p={theme.spacing(8)}
|
||||
onClick={() => navigate(`/pagespeed/${data._id}`)}
|
||||
border={1}
|
||||
borderColor={theme.palette.border.light}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
sx={{ cursor: "pointer" }}
|
||||
>
|
||||
<PageSpeedIcon style={{ width: theme.gap.ml, height: theme.gap.ml }} />
|
||||
<PageSpeedIcon
|
||||
style={{ width: theme.spacing(8), height: theme.spacing(8) }}
|
||||
/>
|
||||
<Box flex={1}>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Typography component="h2" mb={theme.gap.xs}>
|
||||
<Typography
|
||||
component="h2"
|
||||
mb={theme.spacing(2)}
|
||||
color={theme.palette.common.main}
|
||||
>
|
||||
{data.name}
|
||||
</Typography>
|
||||
<StatusLabel
|
||||
@@ -47,7 +57,7 @@ const Card = ({ data }) => {
|
||||
/>
|
||||
</Stack>
|
||||
<Typography>{data.url.replace(/^https?:\/\//, "")}</Typography>
|
||||
<Typography mt={theme.gap.large}>
|
||||
<Typography mt={theme.spacing(12)}>
|
||||
<Typography component="span" fontWeight={600}>
|
||||
Last checked:{" "}
|
||||
</Typography>
|
||||
@@ -75,11 +85,11 @@ const SkeletonLayout = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack gap={theme.gap.xs}>
|
||||
<Stack gap={theme.spacing(2)}>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.gap.large}
|
||||
mb={theme.spacing(12)}
|
||||
>
|
||||
<Box width="80%">
|
||||
<Skeleton variant="rounded" width="25%" height={24} />
|
||||
@@ -87,7 +97,7 @@ const SkeletonLayout = () => {
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={19.5}
|
||||
sx={{ mt: theme.gap.xs }}
|
||||
sx={{ mt: theme.spacing(2) }}
|
||||
/>
|
||||
</Box>
|
||||
<Skeleton
|
||||
@@ -97,7 +107,7 @@ const SkeletonLayout = () => {
|
||||
sx={{ alignSelf: "flex-end" }}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack direction="row" flexWrap="wrap" gap={theme.gap.large}>
|
||||
<Stack direction="row" flexWrap="wrap" gap={theme.spacing(12)}>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
@@ -163,15 +173,22 @@ const PageSpeed = ({ isAdmin }) => {
|
||||
{isActuallyLoading ? (
|
||||
<SkeletonLayout />
|
||||
) : monitors?.length !== 0 ? (
|
||||
<Stack gap={theme.gap.xs}>
|
||||
<Stack
|
||||
gap={theme.spacing(2)}
|
||||
sx={{
|
||||
"& h1, & span.MuiTypography-root, & p": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.gap.large}
|
||||
mb={theme.spacing(12)}
|
||||
>
|
||||
<Box>
|
||||
<Typography component="h1">All page speed monitors</Typography>
|
||||
<Typography mt={theme.gap.xs}>
|
||||
<Typography mt={theme.spacing(2)}>
|
||||
Click on one of the monitors to get more site speed information.
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -181,7 +198,7 @@ const PageSpeed = ({ isAdmin }) => {
|
||||
onClick={() => navigate("/pagespeed/create")}
|
||||
/>
|
||||
</Stack>
|
||||
<Grid container spacing={theme.gap.large}>
|
||||
<Grid container spacing={theme.spacing(12)}>
|
||||
{monitors?.map((monitor) => (
|
||||
<Card data={monitor} key={`monitor-${monitor._id}`} />
|
||||
))}
|
||||
|
||||
@@ -53,7 +53,12 @@ const theme = createTheme({
|
||||
light: "#ffffff",
|
||||
border: "#D0D5DD",
|
||||
},
|
||||
success: { main: "#17b26a", light: "#d4f4e1", bg: "#ecfdf3" },
|
||||
success: {
|
||||
text: "#079455",
|
||||
main: "#17b26a",
|
||||
light: "#d4f4e1",
|
||||
bg: "#ecfdf3",
|
||||
},
|
||||
error: {
|
||||
text: "#f04438",
|
||||
main: "#d32f2f",
|
||||
|
||||
Reference in new issue
Block a user