Refactored pages styling 2/3

This commit is contained in:
Daniel Cojocea
2024-08-28 10:28:02 -04:00
parent b34a17004b
commit 05ffb3d270
20 changed files with 295 additions and 178 deletions

View File

@@ -34,6 +34,7 @@ function App() {
const MonitorsWithAdminProp = withAdminProp(Monitors);
const DetailsWithAdminProp = withAdminProp(Details);
const PageSpeedWithAdminProp = withAdminProp(PageSpeed);
const MaintenanceWithAdminProp = withAdminProp(Maintenance);
return (
<>
<Routes>
@@ -74,7 +75,7 @@ function App() {
/>
<Route
path="maintenance"
element={<ProtectedRoute Component={Maintenance} />}
element={<ProtectedRoute Component={MaintenanceWithAdminProp} />}
/>
<Route
path="/maintenance/create"

View File

@@ -40,7 +40,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin }) => {
marginY={theme.spacing(6)}
color={theme.palette.text.secondary}
>
A {title} monitor is used to:
A {title} is used to:
</Typography>
{checks.map((check, index) => (
<Check
@@ -50,6 +50,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin }) => {
/>
))}
</Stack>
{/* TODO - display a different fallback if user is not an admin*/}
{isAdmin && (
<Button
level="primary"

View File

@@ -150,7 +150,7 @@ const ForgotPassword = () => {
</Box>
<Box
component="form"
width="100%"
width="95%"
textAlign="left"
noValidate
spellCheck={false}
@@ -185,6 +185,7 @@ const ForgotPassword = () => {
<Typography display="inline-block">Go back to </Typography>
<Typography
component="span"
color={theme.palette.common.main}
ml={theme.spacing(2)}
onClick={handleNavigate}
sx={{ userSelect: "none" }}

View File

@@ -275,6 +275,7 @@ const StepTwo = ({ form, errors, onSubmit, onChange, onBack }) => {
</Typography>
<Typography
component="span"
color={theme.palette.common.main}
ml={theme.spacing(2)}
sx={{ userSelect: "none" }}
onClick={handleNavigate}

View File

@@ -21,8 +21,10 @@ import { useSelector } from "react-redux";
import { networkService } from "../../../main";
import { StatusLabel } from "../../../Components/Label";
import { logger } from "../../../Utils/Logger";
import { useTheme } from "@emotion/react";
const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
const theme = useTheme();
const { authToken, user } = useSelector((state) => state.auth);
const [checks, setChecks] = useState([]);
const [checksCount, setChecksCount] = useState(0);
@@ -100,6 +102,19 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
page={paginationController.page + 1} //0-indexed
onChange={handlePageChange}
shape="rounded"
sx={{
backgroundColor: theme.palette.background.main,
border: 1,
borderColor: theme.palette.border.light,
"& button": {
color: theme.palette.text.tertiary,
borderRadius: theme.shape.borderRadius,
},
"& li:first-of-type button, & li:last-of-type button": {
border: 1,
borderColor: theme.palette.border.light,
},
}}
renderItem={(item) => (
<PaginationItem
slots={{
@@ -111,6 +126,13 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
"&:focus": {
outline: "none",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
"&.Mui-selected, &.Mui-selected:hover": {
backgroundColor: theme.palette.background.fill,
},
}}
/>
)}
@@ -118,24 +140,50 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
);
}
let sharedStyles = {
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.main,
p: theme.spacing(30),
};
return (
<>
{checks?.length === 0 && selectedMonitor === "0" ? (
<Box>
<Typography textAlign="center">No incidents recorded yet.</Typography>
<Box sx={{ ...sharedStyles }}>
<Typography textAlign="center" color={theme.palette.text.secondary}>
No incidents recorded yet.
</Typography>
</Box>
) : checks?.length === 0 ? (
<Box>
<Typography textAlign="center">
<Box sx={{ ...sharedStyles }}>
<Typography textAlign="center" color={theme.palette.text.secondary}>
The monitor you have selected has no recorded incidents yet.
</Typography>
</Box>
) : (
<>
<TableContainer component={Paper}>
<TableContainer
component={Paper}
sx={{
border: `solid 1px ${theme.palette.border.light}`,
borderRadius: theme.shape.borderRadius,
}}
>
<Table>
<TableHead>
<TableRow>
<TableHead
sx={{
backgroundColor: theme.palette.background.accent,
}}
>
<TableRow
sx={{
"& > .MuiTableCell-root": {
color: theme.palette.text.secondary,
},
}}
>
<TableCell>Monitor Name</TableCell>
<TableCell>Status</TableCell>
<TableCell>Date & Time</TableCell>

View File

@@ -1,7 +1,3 @@
.incidents h1.MuiTypography-root,
.incidents p.MuiTypography-root {
color: var(--secondary-color);
}
.incidents h1.MuiTypography-root {
font-size: var(--env-var-font-size-large);
font-weight: 600;
@@ -12,19 +8,4 @@
}
.incidents button.MuiButtonBase-root {
height: 34px;
border-color: var(--border-color);
}
.incidents .MuiPagination-root {
background-color: var(--primary-bg);
}
.incidents > .MuiBox-root {
background-color: var(--primary-bg);
border: solid 1px var(--border-color);
border-radius: var(--env-var-radius-1);
padding: 60px;
}
/* remove later */
.incidents .MuiSelect-select {
padding: 0 10px;
}

View File

@@ -78,13 +78,17 @@ const Incidents = () => {
};
return (
<Stack className="incidents" pt={theme.gap.xl} gap={theme.gap.large}>
<Stack className="incidents" pt={theme.spacing(20)} gap={theme.spacing(12)}>
{loading ? (
<SkeletonLayout />
) : (
<>
<Stack direction="row" alignItems="center" gap={theme.gap.medium}>
<Typography display="inline-block" component="h1">
<Stack direction="row" alignItems="center" gap={theme.spacing(6)}>
<Typography
display="inline-block"
component="h1"
color={theme.palette.text.secondary}
>
Incidents for
</Typography>
<Select
@@ -93,15 +97,27 @@ const Incidents = () => {
value={selectedMonitor}
onChange={handleSelect}
items={Object.values(monitors)}
sx={{
backgroundColor: theme.palette.background.main,
}}
/>
<ButtonGroup sx={{ ml: "auto" }}>
<ButtonGroup
sx={{
ml: "auto",
"& .MuiButtonBase-root, & .MuiButtonBase-root:hover": {
borderColor: theme.palette.border.light,
},
}}
>
<Button
level="secondary"
label="All"
onClick={() => setFilter("all")}
sx={{
backgroundColor:
filter === "all" && theme.palette.otherColors.fillGray,
filter === "all"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
<Button
@@ -110,7 +126,9 @@ const Incidents = () => {
onClick={() => setFilter("down")}
sx={{
backgroundColor:
filter === "down" && theme.palette.otherColors.fillGray,
filter === "down"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
<Button
@@ -119,7 +137,9 @@ const Incidents = () => {
onClick={() => setFilter("resolve")}
sx={{
backgroundColor:
filter === "resolve" && theme.palette.otherColors.fillGray,
filter === "resolve"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
</ButtonGroup>

View File

@@ -1,7 +1,3 @@
.integrations h1.MuiTypography-root,
.integrations p.MuiTypography-root {
color: var(--secondary-color);
}
.integrations h1.MuiTypography-root {
font-size: var(--env-var-font-size-large);
font-weight: 600;
@@ -12,9 +8,3 @@
.integrations button {
height: var(--env-var-height-2);
}
.integrations .MuiGrid-item > .MuiStack-root {
border: solid 1px var(--border-color);
border-radius: var(--env-var-radius-1);
background-color: var(--primary-bg);
}

View File

@@ -25,13 +25,17 @@ const IntegrationsComponent = ({ icon, header, info, onClick }) => {
<Stack
direction="row"
justifyContent="space-between"
gap={theme.gap.large}
p={theme.gap.ml}
pl={theme.gap.large}
gap={theme.spacing(12)}
p={theme.spacing(8)}
pl={theme.spacing(12)}
height="100%"
border={1}
borderColor={theme.palette.border.light}
borderRadius={theme.shape.borderRadius}
backgroundColor={theme.palette.background.main}
>
{icon}
<Stack gap={theme.gap.xs} flex={1}>
<Stack gap={theme.spacing(2)} flex={1}>
<Typography component="h1">{header}</Typography>
<Typography
sx={{
@@ -108,12 +112,21 @@ const Integrations = () => {
];
return (
<Stack className="integrations" pt={theme.gap.xl} gap={theme.gap.xs}>
<Stack
className="integrations"
pt={theme.spacing(20)}
gap={theme.spacing(2)}
sx={{
"& h1, & p": {
color: theme.palette.text.secondary,
},
}}
>
<Typography component="h1">Integrations</Typography>
<Typography mb={theme.gap.large}>
<Typography mb={theme.spacing(12)}>
Connect BlueWave Uptime to your favorite service.
</Typography>
<Grid container spacing={theme.gap.large}>
<Grid container spacing={theme.spacing(12)}>
{integrations.map((integration, index) => (
<IntegrationsComponent
key={index}

View File

@@ -13,6 +13,7 @@ import Field from "../../../Components/Inputs/Field";
import { maintenanceWindowValidation } from "../../../Validation/validation";
import { logger } from "../../../Utils/Logger";
import { createToast } from "../../../Utils/toastUtils";
import { useTheme } from "@emotion/react";
const directory = {
title: "Create a maintenance window",
@@ -56,6 +57,8 @@ const durationOptions = [
];
const CreateNewMaintenanceWindow = () => {
const theme = useTheme();
const [values, setValues] = useState({
repeat: 1,
date: dayjs(),
@@ -159,7 +162,11 @@ const CreateNewMaintenanceWindow = () => {
{
title: "Duration",
component: (
<Stack className="duration-config" gap={2} direction="row">
<Stack
className="duration-config"
gap={theme.spacing(5)}
direction="row"
>
<Field
id="duration-value"
placeholder="60"
@@ -195,7 +202,7 @@ const CreateNewMaintenanceWindow = () => {
<Stack
className="add-monitors-fields"
sx={{ width: "60%", maxWidth: "380px" }}
gap={2}
gap={theme.spacing(5)}
>
<Field
id="add-monitors"
@@ -208,7 +215,7 @@ const CreateNewMaintenanceWindow = () => {
sx={{
width: "fit-content",
fontSize: "var(--env-var-font-size-small)",
borderBottom: "1px dashed var(--env-var-color-3)",
borderBottom: `1px dashed ${theme.palette.common.main}`,
paddingBottom: "4px",
}}
>
@@ -221,15 +228,15 @@ const CreateNewMaintenanceWindow = () => {
return (
<div className="create-maintenance-window">
<Stack gap={3}>
<Stack gap={theme.spacing(10)}>
<Button
id="btn-back"
sx={{
width: "100px",
height: "30px",
gap: "10px",
backgroundColor: "var(--env-var-color-32)",
color: "var(--env-var-color-5)",
backgroundColor: theme.palette.background.fill,
color: theme.palette.text.secondary,
}}
label="Back"
level="tertiary"
@@ -239,8 +246,8 @@ const CreateNewMaintenanceWindow = () => {
<Typography
sx={{
fontSize: "var(--env-var-font-size-large)",
fontWeight: "600",
color: "var(--env-var-color-5)",
fontWeight: 600,
color: theme.palette.text.secondary,
}}
>
{directory.title}
@@ -252,14 +259,14 @@ const CreateNewMaintenanceWindow = () => {
</Box>
<Stack
className="maintenance-options"
gap={5}
paddingY={4}
paddingX={8}
paddingBottom={10}
gap={theme.spacing(20)}
paddingY={theme.spacing(15)}
paddingX={theme.spacing(20)}
sx={{
border: "1px solid var(--env-var-color-16)",
borderRadius: "var(--env-var-radius-1)",
backgroundColor: "var(--env-var-color-0)",
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.main,
}}
>
{configOptions.map((item, index) => (

View File

@@ -3,7 +3,7 @@ import { useTheme } from "@emotion/react";
import Fallback from "../../Components/Fallback";
import "./index.css";
const Maintenance = () => {
const Maintenance = ({ isAdmin }) => {
const theme = useTheme();
return (
@@ -29,6 +29,7 @@ const Maintenance = () => {
"Stop sending alerts in maintenance windows",
]}
link="/maintenance/create"
isAdmin={isAdmin}
/>
</Box>
);

View File

@@ -1,4 +1,4 @@
import { Stack, Typography } from "@mui/material";
import { Box, Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
/**
* Host component.
@@ -13,12 +13,39 @@ import PropTypes from "prop-types";
*/
const Host = ({ params }) => {
return (
<Stack direction="row" alignItems="baseline" className="host">
{params.title}
<Typography component="span" sx={{ color: params.percentageColor }}>
<Box className="host">
<Box
display="inline-block"
position="relative"
sx={{
fontWeight: 500,
"&:before": {
position: "absolute",
content: `""`,
width: "4px",
height: "4px",
borderRadius: "50%",
backgroundColor: "gray",
opacity: 0.8,
right: "-10px",
top: "42%",
},
}}
>
{params.title}
</Box>
<Typography
component="span"
sx={{
color: params.percentageColor,
fontWeight: 500,
ml: "15px",
}}
>
{params.percentage}%
</Typography>
</Stack>
<Box sx={{ opacity: 0.6 }}>{params.url}</Box>
</Box>
);
};

View File

@@ -12,6 +12,7 @@ import SkeletonLayout from "./skeleton";
import Fallback from "./fallback";
import StatusBox from "./StatusBox";
import { buildData } from "./monitorData";
import Breadcrumbs from "../../../Components/Breadcrumbs";
const Monitors = ({ isAdmin }) => {
const theme = useTheme();
@@ -33,35 +34,73 @@ const Monitors = ({ isAdmin }) => {
let loading = monitorState.isLoading && monitorState.monitors.length === 0;
const now = new Date();
const hour = now.getHours();
let greeting = "";
let emoji = "";
if (hour < 12) {
greeting = "morning";
emoji = "🌅";
} else if (hour < 18) {
greeting = "afternoon";
emoji = "🌞";
} else {
greeting = "evening";
emoji = "🌙";
}
return (
<Stack className="monitors" gap={theme.gap.large}>
{loading ? (
<SkeletonLayout />
) : (
<>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Typography
component="h1"
sx={{ lineHeight: 1, alignSelf: "flex-end" }}
<Box>
<Breadcrumbs list={[{ name: `monitors`, path: "/monitors" }]} />
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
mt={theme.spacing(5)}
>
Hello, {authState.user.firstName}
</Typography>
{monitorState.monitors?.length !== 0 && (
<Button
level="primary"
label="Create monitor"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ fontWeight: 500 }}
/>
)}
</Stack>
<Box>
<Typography component="h1" lineHeight={1}>
<Typography
component="span"
fontSize="inherit"
color={theme.palette.otherColors.bluishGray}
>
Good {greeting},{" "}
</Typography>
<Typography
component="span"
fontSize="inherit"
fontWeight="inherit"
>
{authState.user.firstName} {emoji}
</Typography>
</Typography>
<Typography
sx={{ opacity: 0.8 }}
lineHeight={1}
fontWeight={300}
>
Heres an overview of your uptime monitors.
</Typography>
</Box>
{monitorState.monitors?.length !== 0 && (
<Button
level="primary"
label="Create monitor"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ fontWeight: 500 }}
/>
)}
</Stack>
</Box>
{monitorState.monitors?.length === 0 && (
<Fallback isAdmin={isAdmin} />
)}

View File

@@ -29,12 +29,11 @@ const data = {
export const buildData = (monitors, isAdmin, navigate) => {
data.rows = monitors.map((monitor, idx) => {
const params = {
url: monitor.url,
title: monitor.name,
percentage: 100,
percentageColor:
monitor.status === true
? "var(--env-var-color-17)"
: "var(--env-var-color-19)",
monitor.status === true ? "var(--success-color)" : "var(--error-color)",
status: monitor.status === true ? "up" : "down",
};
@@ -43,7 +42,6 @@ export const buildData = (monitors, isAdmin, navigate) => {
return {
id: monitor._id,
// disabled for now
handleClick: () => {
navigate(`/monitors/${monitor._id}`);
},

View File

@@ -1,15 +0,0 @@
.not-found-page {
height: 100vh;
}
.not-found-page button,
.not-found-page p {
font-size: var(--env-var-font-size-medium);
}
.not-found-page h1 {
font-size: var(--env-var-font-size-large);
font-weight: 600;
}
.not-found-page h1,
.not-found-page p {
color: var(--secondary-color);
}

View File

@@ -1,10 +1,10 @@
import Button from "../../Components/Button";
import "./index.css";
import React from "react";
import PropTypes from "prop-types";
import NotFoundSvg from "../../../src/assets/Images/sushi_404.svg";
import { Stack, Typography } from "@mui/material";
import { useNavigate } from "react-router";
import NotFoundSvg from "../../../src/assets/Images/sushi_404.svg";
import { useTheme } from "@emotion/react";
/**
* Support for defaultProps will be removed from function components in a future major release
@@ -33,16 +33,24 @@ const DefaultValue = {
*/
const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
const navigate = useNavigate();
const theme = useTheme();
return (
<Stack className="not-found-page" justifyContent="center">
<Stack gap="20px" alignItems="center">
<Stack height="100vh" justifyContent="center">
<Stack
gap={theme.spacing(2)}
alignItems="center"
color={theme.palette.text.secondary}
>
<img src={NotFoundSvg} alt="404" style={{ maxHeight: "25rem" }} />
<Typography component="h1">{title}</Typography>
<Typography>{desc}</Typography>
<Typography component="h1" fontSize={16} fontWeight={600}>
{title}
</Typography>
<Typography fontSize={13}>{desc}</Typography>
<Button
label="Go to the main dashboard"
level="primary"
sx={{ mt: "24px" }}
sx={{ mt: theme.spacing(10) }}
onClick={() => navigate("/")}
/>
</Stack>

View File

@@ -33,6 +33,3 @@
height: 34px;
align-self: flex-end;
}
.page-speed [class*="fallback__"] h1 {
margin-left: var(--env-var-spacing-3);
}

View File

@@ -189,7 +189,7 @@ const PageSpeed = ({ isAdmin }) => {
</Stack>
) : (
<Fallback
title="page speed"
title="pagespeed monitor"
checks={[
"Report on the user experience of a page",
"Help analyze webpage speed",

View File

@@ -5,11 +5,6 @@
.settings p.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
}
.settings h1.MuiTypography-root,
.settings h2.MuiTypography-root,
.settings p.MuiTypography-root {
color: var(--secondary-color);
}
.settings h1.MuiTypography-root {
font-size: var(--env-var-font-size-large);
}
@@ -23,21 +18,4 @@
.settings span.MuiTypography-root {
opacity: 0.6;
margin-right: 4px;
}
.settings .config-box {
padding: var(--env-var-spacing-4) 50px;
padding-bottom: 60px;
border: 1px solid var(--border-color);
border-radius: var(--env-var-radius-1);
background-color: var(--primary-bg);
}
.settings .config-box .MuiBox-root,
.settings .config-box .MuiStack-root {
flex: 1;
}
.settings-form {
display: flex;
flex-direction: column;
gap: var(--env-var-spacing-4);
}
}

View File

@@ -1,5 +1,5 @@
import { useTheme } from "@emotion/react";
import { Box, Stack, Typography } from "@mui/material";
import { Box, Stack, styled, Typography } from "@mui/material";
import Button from "../../Components/Button";
import Field from "../../Components/Inputs/Field";
import Link from "../../Components/Link";
@@ -10,6 +10,33 @@ import "./index.css";
const Settings = () => {
const theme = useTheme();
const ConfigBox = styled("div")({
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: theme.spacing(20),
paddingTop: theme.spacing(12),
paddingInline: theme.spacing(15),
paddingBottom: theme.spacing(25),
backgroundColor: theme.palette.background.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
borderRadius: theme.spacing(2),
"& > div:first-of-type": {
flex: 0.7,
},
"& > div:last-of-type": {
flex: 1,
},
"& h1, & h2": {
color: theme.palette.text.secondary,
},
"& p": {
color: theme.palette.text.tertiary,
},
});
return (
<Box
className="settings"
@@ -17,16 +44,16 @@ const Settings = () => {
paddingBottom: 0,
}}
>
<form className="settings-form" noValidate spellCheck="false">
<Stack
className="config-box"
direction="row"
justifyContent="space-between"
gap={theme.gap.xxl}
>
<Stack
component="form"
gap={theme.spacing(12)}
noValidate
spellCheck="false"
>
<ConfigBox>
<Box>
<Typography component="h1">General Settings</Typography>
<Typography sx={{ mt: theme.gap.small, mb: theme.gap.xs }}>
<Typography sx={{ mt: theme.spacing(2), mb: theme.spacing(2) }}>
<Typography component="span">Display timezone</Typography>- The
timezone of the dashboard you publicly display.
</Typography>
@@ -51,16 +78,11 @@ const Settings = () => {
items={[{ _id: "est", name: "America / Toronto" }]}
/>
</Stack>
</Stack>
<Stack
className="config-box"
direction="row"
justifyContent="space-between"
gap={theme.gap.xxl}
>
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h1">History and monitoring</Typography>
<Typography sx={{ mt: theme.gap.small }}>
<Typography sx={{ mt: theme.spacing(2) }}>
Define here for how long you want to keep the data. You can also
remove all past data.
</Typography>
@@ -81,24 +103,19 @@ const Settings = () => {
<Button
level="error"
label="Clear all stats"
sx={{ mt: theme.gap.small }}
sx={{ mt: theme.spacing(4) }}
/>
</Box>
</Stack>
</Stack>
<Stack
className="config-box"
direction="row"
justifyContent="space-between"
gap={theme.gap.xxl}
>
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h1">About</Typography>
</Box>
<Box>
<Typography component="h2">BlueWave Uptime v1.0.0</Typography>
<Typography
sx={{ mt: theme.gap.xs, mb: theme.gap.medium, opacity: 0.6 }}
sx={{ mt: theme.spacing(2), mb: theme.spacing(6), opacity: 0.6 }}
>
Developed by Bluewave Labs.
</Typography>
@@ -108,11 +125,15 @@ const Settings = () => {
label="https://github.com/bluewave-labs"
/>
</Box>
</Stack>
</ConfigBox>
<Stack direction="row" justifyContent="flex-end">
<Button level="primary" label="Save" sx={{ px: theme.gap.large }} />
<Button
level="primary"
label="Save"
sx={{ px: theme.spacing(12), mt: theme.spacing(20) }}
/>
</Stack>
</form>
</Stack>
</Box>
);
};