Merge pull request #770 from bluewave-labs/feat/theme-button-styles

Feat/theme button styles
This commit is contained in:
Alexander Holliday authored and GitHub committed 2024-09-01 10:14:30 -07:00
commit 21fafa1705
38 files changed
+614 -791

No files matched your search

+6 -12
View File
@@ -1,12 +1,11 @@
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import { Box, IconButton, Stack, Typography } from "@mui/material";
import { Box, Button, IconButton, Stack, Typography } from "@mui/material";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import ErrorOutlineOutlinedIcon from "@mui/icons-material/ErrorOutlineOutlined";
import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined";
import CloseIcon from "@mui/icons-material/Close";
import "./index.css";
import Button from "../Button";
/**
* Icons mapping for different alert variants.
@@ -65,8 +64,8 @@ const Alert = ({ variant, title, body, isToast, hasIcon = true, onClick }) => {
)}
{hasIcon && isToast && (
<Button
level="tertiary"
label="Dismiss"
variant="text"
color="info"
onClick={onClick}
sx={{
fontWeight: "600",
@@ -74,15 +73,10 @@ const Alert = ({ variant, title, body, isToast, hasIcon = true, onClick }) => {
mt: theme.spacing(4),
padding: 0,
minWidth: 0,
"&:hover": {
backgroundColor: "transparent",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
></Button>
>
Dismiss
</Button>
)}
</Stack>
{isToast && (
+17 -26
View File
@@ -13,6 +13,7 @@ import {
Box,
Typography,
Stack,
Button,
} from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { setRowsPerPage } from "../../Features/UI/uiSlice";
@@ -21,7 +22,6 @@ import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react";
import LeftArrow from "../../assets/icons/left-arrow.svg?react";
import RightArrow from "../../assets/icons/right-arrow.svg?react";
import SelectorVertical from "../../assets/icons/selector-vertical.svg?react";
import Button from "../Button";
import "./index.css";
/**
* Component for pagination actions (first, previous, next, last).
@@ -54,37 +54,37 @@ const TablePaginationActions = (props) => {
return (
<Box sx={{ flexShrink: 0, ml: "24px" }}>
<Button
level="secondary"
label=""
img={<LeftArrowDouble />}
variant="group"
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
/>
>
<LeftArrowDouble />
</Button>
<Button
level="secondary"
label=""
img={<LeftArrow />}
variant="group"
onClick={handleBackButtonClick}
disabled={page === 0}
aria-label="previous page"
/>
>
<LeftArrow />
</Button>
<Button
level="secondary"
label=""
img={<RightArrow />}
variant="group"
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
/>
>
<RightArrow />
</Button>
<Button
level="secondary"
label=""
img={<RightArrowDouble />}
variant="group"
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
/>
>
<RightArrowDouble />
</Button>
</Box>
);
};
@@ -293,19 +293,10 @@ const BasicTable = ({ data, paginated, reversed, table }) => {
sx={{
mt: theme.spacing(6),
color: theme.palette.text.secondary,
"& button.MuiButtonBase-root, & .MuiSelect-select": {
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
},
"& svg path": {
stroke: theme.palette.text.tertiary,
strokeWidth: 1.3,
},
"& button:not(.Mui-disabled):hover": {
backgroundColor: theme.palette.background.fill,
borderColor: theme.palette.background.fill,
},
}}
/>
</Stack>
-33
View File
@@ -1,33 +0,0 @@
.MuiButtonBase-root.button-rotate90 svg {
transition: transform 500ms ease;
}
.MuiButtonBase-root.button-rotate90:hover svg {
transform: rotate(90deg);
transform-origin: center;
}
.MuiButtonBase-root.button-rotate180 svg {
transition: transform 700ms ease;
}
.MuiButtonBase-root.button-rotate180:hover svg {
transform: rotate(180deg);
transform-origin: center;
}
.MuiButtonBase-root.button-slideLeft {
padding-left: 45px;
}
.MuiButtonBase-root.button-slideLeft svg {
position: absolute;
left: 15px;
transition: left 250ms cubic-bezier(0.65, 0, 0.076, 1);
}
.MuiButtonBase-root.button-slideLeft:hover svg {
left: 11px;
}
.MuiButtonBase-root.button-slideLeft:hover,
.MuiButtonBase-root.button-rotate180:hover,
.MuiButtonBase-root.button-rotate90:hover {
background-color: rgba(71, 84, 103, 0.08);
}
-108
View File
@@ -1,108 +0,0 @@
import { Button as MuiButton } from "@mui/material";
import PropTypes from "prop-types";
import "./index.css";
const levelConfig = {
primary: {
variant: "contained",
color: "primary",
},
secondary: {
variant: "outlined",
color: "secondary",
},
tertiary: {
variant: "text",
color: "tertiary",
},
error: {
variant: "contained",
color: "error",
},
imagePrimary: {
color: "primary",
variant: "text",
},
imageSecondary: {
color: "secondary",
variant: "text",
},
imageTertiary: {
color: "tertiary",
variant: "text",
},
};
/**
* @component
* @param {Object} props
* @param {'primary' | 'secondary' | 'tertiary' | 'error' | 'imagePrimary' | 'imageSecondary' | 'imageTertiary'} props.level - The level of the button
* @param {string} props.type - The type of the button
* @param {string} props.label - The label of the button
* @param {React.ReactNode} props.img - Image for button
* @param {boolean} [props.disabled] - Whether the button is disabled
* @param {function} props.onClick - Function to run when the button is clicked
* @param {Object} props.sx - Styles for the button
* @returns {JSX.Element}
* @example
* // Render an error button
* <Button type="submit" level="error" label="Error" disabled sx={{marginTop: "1rem"}}/>
*/
const Button = ({
id,
animate,
type,
level,
label,
disabled,
img,
onClick,
props,
sx,
}) => {
const { variant, color } = levelConfig[level];
return (
<MuiButton
id={id}
className={`button-${animate}`}
type={type}
variant={variant}
color={color}
disabled={disabled}
onClick={onClick}
disableRipple
sx={{
lineHeight: 1.5,
fontWeight: 400,
boxShadow: "none",
textTransform: "none",
borderRadius: "4px",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
},
...sx,
}}
{...props}
>
{img && img}
<span>{label}</span>
</MuiButton>
);
};
Button.propTypes = {
id: PropTypes.string,
type: PropTypes.string,
level: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
img: PropTypes.node,
onClick: PropTypes.func,
sx: PropTypes.object,
disabled: PropTypes.bool,
};
export default Button;
@@ -1,105 +0,0 @@
import LoadingButton from "@mui/lab/LoadingButton";
import PropTypes from "prop-types";
const levelConfig = {
primary: {
variant: "contained",
color: "primary",
},
secondary: {
variant: "outlined",
color: "secondary",
},
tertiary: {
variant: "text",
color: "tertiary",
},
error: {
variant: "contained",
color: "error",
},
};
/**
* @component
* @param {Object} props
* @param {'primary' | 'secondary' | 'tertiary' | 'error'} props.level - The style level of the button.
* @param {string} props.label - The label text displayed on the button.
* @param {React.ReactNode} [props.img] - Icon or image element to display within the button.
* @param {boolean} [props.disabled=false] - Determines if the button is disabled.
* @param {string} [props.loadingText] - Text displayed when the button is in a loading state.
* @param {'start' | 'end'} [props.position] - Specifies where the icon or loading loadingText should be positioned relative to the label.
* @param {function} props.onClick - Callback function invoked when the button is clicked.
* @param {boolean} props.isLoading - Indicates if the button is in a loading state.
* @param {Object} [props.sx] - Additional styles to apply to the button.
* @returns {JSX.Element}
* @example
* // Render a primary button with an icon at the end
* <ButtonSpinner
* level="primary"
* label="Save"
* img={<SaveIcon />}
* position="end"
* onClick={handleSaveClick}
* isLoading={loading}
* />
*/
const ButtonSpinner = ({
level,
label,
disabled,
loadingText,
position,
img,
onClick,
isLoading,
sx,
}) => {
const { variant, color } = levelConfig[level];
//if both a loadingPosition and loadingIndicator are provided, the spinner overlaps with the text and it breaks
if (position && loadingText) loadingText = null;
return (
<LoadingButton
variant={variant}
color={color}
disabled={disabled}
loadingIndicator={loadingText}
loadingPosition={position}
startIcon={position === "start" && img}
endIcon={position === "end" && img}
onClick={onClick}
loading={isLoading}
disableRipple
sx={{
boxShadow: "none",
textTransform: "none",
borderRadius: "4px",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
transition: "none",
},
...sx,
}}
>
<span>{label}</span>
</LoadingButton>
);
};
ButtonSpinner.propTypes = {
level: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
loadingText: PropTypes.string,
position: PropTypes.oneOf(["start", "end"]),
img: PropTypes.node,
onClick: PropTypes.func.isRequired,
isLoading: PropTypes.bool.isRequired,
sx: PropTypes.object,
disabled: PropTypes.bool,
};
export default ButtonSpinner;
@@ -22,7 +22,7 @@ const CustomToolTip = ({ active, payload, label }) => {
>
<Typography
sx={{
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontSize: 13,
}}
>
+6 -5
View File
@@ -1,10 +1,9 @@
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import Skeleton from "../../assets/Images/create-placeholder.svg?react";
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
import Background from "../../assets/Images/background-grid.svg?react";
import Button from "../Button";
import Check from "../Check/Check";
import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
@@ -66,11 +65,13 @@ const Fallback = ({ title, checks, link = "/", isAdmin }) => {
{/* TODO - display a different fallback if user is not an admin*/}
{isAdmin && (
<Button
level="primary"
label={`Let's create your ${title}`}
variant="contained"
color="primary"
sx={{ alignSelf: "center" }}
onClick={() => navigate(link)}
/>
>
Let's create your {title}
</Button>
)}
</Stack>
);
+3 -3
View File
@@ -38,12 +38,12 @@ const ImageField = ({ id, src, loading, onChange }) => {
border: "dashed",
borderRadius: theme.shape.borderRadius,
borderColor: isDragging
? theme.palette.common.main
? theme.palette.primary.main
: theme.palette.border.light,
borderWidth: "2px",
transition: "0.2s",
"&:hover": {
borderColor: theme.palette.common.main,
borderColor: theme.palette.primary.main,
backgroundColor: "hsl(215, 87%, 51%, 0.05)",
},
}}
@@ -96,7 +96,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
<Typography
component="span"
fontSize="inherit"
color={theme.palette.common.main}
color={theme.palette.primary.main}
fontWeight={500}
>
Click to upload
+2 -2
View File
@@ -28,11 +28,11 @@ const Link = ({ level, label, url }) => {
sx: {
textDecoration: "underline",
textDecorationStyle: "dashed",
textDecorationColor: theme.palette.common.main,
textDecorationColor: theme.palette.primary.main,
textUnderlineOffset: "1px",
":hover": {
color: theme.palette.text.tertiary,
textDecorationColor: theme.palette.common.main,
textDecorationColor: theme.palette.primary.main,
backgroundColor: theme.palette.background.fill,
},
},
+1 -1
View File
@@ -75,7 +75,7 @@ aside.collapsed .MuiAvatar-root + .MuiBox-root + .MuiIconButton-root {
}
aside .MuiListSubheader-root {
transition: all 200ms ease;
transition: padding 200ms ease;
}
@keyframes fadeIn {
+1 -1
View File
@@ -154,7 +154,7 @@ function Sidebar() {
color="white"
sx={{
position: "relative",
backgroundColor: theme.palette.common.main,
backgroundColor: theme.palette.primary.main,
borderRadius: theme.shape.borderRadius,
userSelect: "none",
}}
@@ -2,7 +2,7 @@ import TabPanel from "@mui/lab/TabPanel";
import React, { useState } from "react";
import { useTheme } from "@emotion/react";
import { Box, Stack, Typography } from "@mui/material";
import ButtonSpinner from "../../ButtonSpinner";
import LoadingButton from "@mui/lab/LoadingButton";
import Field from "../../Inputs/Field";
import { credentials } from "../../../Validation/validation";
import Alert from "../../Alert";
@@ -164,19 +164,20 @@ const PasswordPanel = () => {
</Box>
</Stack>
<Stack direction="row" justifyContent="flex-end">
<ButtonSpinner
level="primary"
label="Save"
<LoadingButton
variant="contained"
color="primary"
onClick={handleSubmit}
isLoading={isLoading}
loadingText="Saving..."
loading={isLoading}
loadingIndicator="Saving..."
disabled={Object.keys(errors).length !== 0 && true}
sx={{
paddingX: theme.spacing(12),
width: "fit-content",
px: theme.spacing(12),
mt: theme.spacing(20),
}}
/>
>
Save
</LoadingButton>
</Stack>
</Stack>
</TabPanel>
@@ -1,9 +1,7 @@
import { useTheme } from "@emotion/react";
import { useRef, useState } from "react";
import TabPanel from "@mui/lab/TabPanel";
import { Box, Divider, Modal, Stack, Typography } from "@mui/material";
import ButtonSpinner from "../../ButtonSpinner";
import Button from "../../Button";
import { Box, Button, Divider, Modal, Stack, Typography } from "@mui/material";
import Avatar from "../../Avatar";
import Field from "../../Inputs/Field";
import ImageField from "../../Inputs/Image";
@@ -20,6 +18,7 @@ import { formatBytes } from "../../../Utils/fileUtils";
import { clearUptimeMonitorState } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import LoadingButton from "@mui/lab/LoadingButton";
/**
* ProfilePanel component displays a form for editing user profile information
@@ -292,19 +291,12 @@ const ProfilePanel = () => {
}
sx={{ mr: "8px" }}
/>
<Button
level="tertiary"
label="Delete"
onClick={handleDeletePicture}
/>
<Button
level="tertiary"
label="Update"
onClick={openPictureModal}
sx={{
color: theme.palette.common.main,
}}
/>
<Button variant="text" color="info" onClick={handleDeletePicture}>
Delete
</Button>
<Button variant="text" color="primary" onClick={openPictureModal}>
Update
</Button>
</Stack>
</Stack>
<Divider
@@ -316,19 +308,19 @@ const ProfilePanel = () => {
/>
<Stack direction="row" justifyContent="flex-end">
<Box width="fit-content">
<ButtonSpinner
level="primary"
label="Save"
<LoadingButton
variant="contained"
color="primary"
onClick={handleSaveProfile}
isLoading={isLoading}
loadingText="Saving..."
loading={isLoading}
loadingIndicator="Saving..."
disabled={
Object.keys(errors).length !== 0 && !errors?.picture && true
}
sx={{
paddingX: theme.spacing(12),
}}
/>
sx={{ px: theme.spacing(12) }}
>
Save
</LoadingButton>
</Box>
</Stack>
</Stack>
@@ -339,13 +331,8 @@ const ProfilePanel = () => {
borderColor: theme.palette.border.light,
}}
/>
<Stack
component="form"
noValidate
spellCheck="false"
gap={theme.spacing(4)}
>
<Box>
<Box component="form" noValidate spellCheck="false">
<Box mb={theme.spacing(6)}>
<Typography component="h1">Delete account</Typography>
<Typography component="p" sx={{ opacity: 0.6 }}>
Note that deleting your account will remove all data from our
@@ -353,12 +340,13 @@ const ProfilePanel = () => {
</Typography>
</Box>
<Button
level="error"
label="Delete account"
variant="contained"
color="error"
onClick={() => setIsOpen("delete")}
sx={{ width: "fit-content", mt: theme.spacing(4) }}
/>
</Stack>
>
Delete account
</Button>
</Box>
{/* TODO - Update ModalPopup Component with @mui for reusability */}
<Modal
aria-labelledby="modal-delete-account"
@@ -400,17 +388,17 @@ const ProfilePanel = () => {
mt={theme.spacing(5)}
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
onClick={() => setIsOpen("")}
/>
<ButtonSpinner
level="error"
label="Delete account"
<Button variant="text" color="info" onClick={() => setIsOpen("")}>
Cancel
</Button>
<LoadingButton
variant="contained"
color="error"
onClick={handleDeleteAccount}
isLoading={isLoading}
/>
loading={isLoading}
>
Delete account
</LoadingButton>
</Stack>
</Stack>
</Modal>
@@ -480,15 +468,19 @@ const ProfilePanel = () => {
justifyContent="flex-end"
>
<Button
level="secondary"
label="Edit"
variant="outlined"
color="secondary"
disabled
sx={{ mr: "auto" }}
/>
<Button level="tertiary" label="Remove" onClick={removePicture} />
>
Edit
</Button>
<Button variant="text" color="info" onClick={removePicture}>
Remove
</Button>
<Button
level="primary"
label="Update"
variant="contained"
color="primary"
onClick={handleUpdatePicture}
disabled={
(Object.keys(errors).length !== 0 && errors?.picture) ||
@@ -496,7 +488,9 @@ const ProfilePanel = () => {
? true
: false
}
/>
>
Update
</Button>
</Stack>
</Stack>
</Modal>
@@ -2,6 +2,7 @@ import { useTheme } from "@emotion/react";
import TabPanel from "@mui/lab/TabPanel";
import {
Box,
Button,
ButtonGroup,
Divider,
IconButton,
@@ -10,8 +11,6 @@ import {
TextField,
Typography,
} from "@mui/material";
import ButtonSpinner from "../../ButtonSpinner";
import Button from "../../Button";
import { useEffect, useState } from "react";
import EditSvg from "../../../assets/icons/edit.svg?react";
import Field from "../../Inputs/Field";
@@ -22,6 +21,7 @@ import { useSelector } from "react-redux";
import BasicTable from "../../BasicTable";
import Remove from "../../../assets/icons/trash-bin.svg?react";
import Select from "../../Inputs/Select";
import LoadingButton from "@mui/lab/LoadingButton";
/**
* TeamPanel component manages the organization and team members,
@@ -283,48 +283,37 @@ const TeamPanel = () => {
gap={theme.spacing(6)}
sx={{ fontSize: 14 }}
>
<ButtonGroup
sx={{
"& button, & button:hover": {
borderColor: theme.palette.border.light,
},
}}
>
<ButtonGroup>
<Button
level="secondary"
label="All"
variant="group"
filled={(filter === "all").toString()}
onClick={() => setFilter("all")}
sx={{
backgroundColor:
filter === "all" && theme.palette.background.fill,
}}
/>
>
All
</Button>
<Button
level="secondary"
label="Administrator"
variant="group"
filled={(filter === "admin").toString()}
onClick={() => setFilter("admin")}
sx={{
backgroundColor:
filter === "admin" && theme.palette.background.fill,
}}
/>
>
Administrator
</Button>
<Button
level="secondary"
label="Member"
variant="group"
filled={(filter === "user").toString()}
onClick={() => setFilter("user")}
sx={{
backgroundColor:
filter === "user" && theme.palette.background.fill,
}}
/>
>
Member
</Button>
</ButtonGroup>
</Stack>
<Button
level="primary"
label="Invite a team member"
sx={{ paddingX: theme.spacing(15) }}
variant="contained"
color="primary"
onClick={() => setIsOpen(true)}
/>
>
Invite a team member
</Button>
</Stack>
<BasicTable
data={tableData}
@@ -400,18 +389,18 @@ const TeamPanel = () => {
mt={theme.spacing(8)}
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
onClick={closeInviteModal}
/>
<ButtonSpinner
level="primary"
label="Send invite"
<Button variant="text" color="info" onClick={closeInviteModal}>
Cancel
</Button>
<LoadingButton
variant="contained"
color="primary"
onClick={handleInviteMember}
isLoading={false}
loading={false}
disabled={Object.keys(errors).length !== 0}
/>
>
Send invite
</LoadingButton>
</Stack>
</Stack>
</Modal>
+10 -9
View File
@@ -1,11 +1,10 @@
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router";
import { createToast } from "../../Utils/toastUtils";
import { forgotPassword } from "../../Features/Auth/authSlice";
import Button from "../../Components/Button";
import background from "../../assets/Images/background_pattern_decorative.png";
import EmailIcon from "../../assets/icons/email.svg?react";
import Logo from "../../assets/icons/bwu-icon.svg?react";
@@ -90,9 +89,9 @@ const CheckEmail = () => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 26,
fontSize: 22,
},
"& p": {
fontSize: 14,
@@ -150,21 +149,23 @@ const CheckEmail = () => {
</Typography>
</Box>
<Button
level="primary"
label="Open email app"
variant="contained"
color="primary"
onClick={openMail}
sx={{
width: "100%",
maxWidth: 400,
}}
/>
>
Open email app
</Button>
<Typography sx={{ alignSelf: "center", mb: theme.spacing(6) }}>
Didn&apos;t receive the email?{" "}
<Typography
component="span"
onClick={resendToken}
sx={{
color: theme.palette.common.main,
color: theme.palette.primary.main,
userSelect: "none",
pointerEvents: disabled ? "none" : "auto",
cursor: disabled ? "default" : "pointer",
@@ -181,7 +182,7 @@ const CheckEmail = () => {
<Typography
component="span"
ml={theme.spacing(2)}
color={theme.palette.common.main}
color={theme.palette.primary.main}
onClick={handleNavigate}
sx={{ userSelect: "none" }}
>
+10 -9
View File
@@ -7,10 +7,10 @@ import { useEffect, useState } from "react";
import { credentials } from "../../Validation/validation";
import { useNavigate } from "react-router-dom";
import Field from "../../Components/Inputs/Field";
import ButtonSpinner from "../../Components/ButtonSpinner";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Key from "../../assets/icons/key.svg?react";
import background from "../../assets/Images/background_pattern_decorative.png";
import LoadingButton from "@mui/lab/LoadingButton";
import "./index.css";
const ForgotPassword = () => {
@@ -92,7 +92,7 @@ const ForgotPassword = () => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 24,
},
@@ -166,18 +166,19 @@ const ForgotPassword = () => {
onChange={handleChange}
error={errors.email}
/>
<ButtonSpinner
<LoadingButton
variant="contained"
color="primary"
loading={isLoading}
disabled={errors.email !== undefined}
onClick={handleSubmit}
isLoading={isLoading}
level="primary"
label="Send instructions"
sx={{
width: "100%",
fontWeight: 400,
mt: theme.spacing(15),
}}
/>
>
Send instructions
</LoadingButton>
</Box>
</Stack>
</Stack>
@@ -185,7 +186,7 @@ const ForgotPassword = () => {
<Typography display="inline-block">Go back to —</Typography>
<Typography
component="span"
color={theme.palette.common.main}
color={theme.palette.primary.main}
ml={theme.spacing(2)}
onClick={handleNavigate}
sx={{ userSelect: "none" }}
+50 -33
View File
@@ -1,12 +1,11 @@
import { useState, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { credentials } from "../../Validation/validation";
import { login } from "../../Features/Auth/authSlice";
import { useDispatch, useSelector } from "react-redux";
import { createToast } from "../../Utils/toastUtils";
import Button from "../../Components/Button";
import { networkService } from "../../main";
import Field from "../../Components/Inputs/Field";
import background from "../../assets/Images/background_pattern_decorative.png";
@@ -40,17 +39,22 @@ const LandingPage = ({ onContinue }) => {
</Box>
<Box width="100%">
<Button
level="secondary"
label="Continue with Email"
img={<Mail />}
variant="outlined"
color="info"
onClick={onContinue}
sx={{
width: "100%",
"& svg": {
mr: theme.spacing(4),
"& path": {
stroke: theme.palette.other.icon,
},
},
}}
/>
>
<Mail />
Continue with Email
</Button>
</Box>
<Box maxWidth={400}>
<Typography className="tos-p">
@@ -151,27 +155,29 @@ const StepOne = ({ form, errors, onSubmit, onChange, onBack }) => {
</Box>
<Stack direction="row" justifyContent="space-between">
<Button
level="secondary"
label="Back"
animate="slideLeft"
img={<ArrowBackRoundedIcon />}
variant="outlined"
color="info"
onClick={onBack}
sx={{
mb: theme.spacing(6),
px: theme.spacing(8),
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(2),
mr: theme.spacing(3),
},
}}
props={{ tabIndex: -1 }}
/>
>
<ArrowBackRoundedIcon />
Back
</Button>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={onSubmit}
disabled={errors.email && true}
sx={{ width: "30%" }}
/>
>
Continue
</Button>
</Stack>
</Stack>
</>
@@ -219,6 +225,7 @@ const StepTwo = ({ form, errors, onSubmit, onChange, onBack }) => {
<>
<Stack
gap={{ xs: theme.spacing(8), sm: theme.spacing(12) }}
position="relative"
textAlign="center"
>
<Box>
@@ -243,39 +250,49 @@ const StepTwo = ({ form, errors, onSubmit, onChange, onBack }) => {
</Box>
<Stack direction="row" justifyContent="space-between">
<Button
level="secondary"
label="Back"
animate="slideLeft"
img={<ArrowBackRoundedIcon />}
variant="outlined"
color="info"
onClick={onBack}
sx={{
mb: theme.spacing(6),
px: theme.spacing(8),
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(2),
mr: theme.spacing(3),
},
}}
props={{ tabIndex: -1 }}
/>
>
<ArrowBackRoundedIcon />
Back
</Button>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={onSubmit}
disabled={errors.password && true}
sx={{ width: "30%" }}
/>
>
Continue
</Button>
</Stack>
<Box textAlign="center">
<Box
textAlign="center"
sx={{
position: "absolute",
top: "103%",
left: "50%",
transform: "translateX(-50%)"
}}
>
<Typography
className="forgot-p"
display="inline-block"
color={theme.palette.common.main}
color={theme.palette.primary.main}
>
Forgot password?
</Typography>
<Typography
component="span"
color={theme.palette.common.main}
color={theme.palette.primary.main}
ml={theme.spacing(2)}
sx={{ userSelect: "none" }}
onClick={handleNavigate}
@@ -419,7 +436,7 @@ const Login = () => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 30,
},
@@ -491,7 +508,7 @@ const Login = () => {
</Typography>
<Typography
component="span"
color={theme.palette.common.main}
color={theme.palette.primary.main}
ml={theme.spacing(2)}
onClick={() => {
navigate("/register");
@@ -1,10 +1,9 @@
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router";
import { useDispatch } from "react-redux";
import { clearAuthState } from "../../Features/Auth/authSlice";
import { clearUptimeMonitorState } from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
import Button from "../../Components/Button";
import background from "../../assets/Images/background_pattern_decorative.png";
import ConfirmIcon from "../../assets/icons/confirm-icon.svg?react";
import Logo from "../../assets/icons/bwu-icon.svg?react";
@@ -27,7 +26,7 @@ const NewPasswordConfirmed = () => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 22,
},
@@ -85,21 +84,23 @@ const NewPasswordConfirmed = () => {
</Typography>
</Box>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={() => navigate("/monitors")}
sx={{
width: "100%",
maxWidth: 400,
}}
/>
>
Continue
</Button>
</Stack>
</Stack>
<Box textAlign="center" p={theme.spacing(12)}>
<Typography display="inline-block">Go back to —</Typography>
<Typography
component="span"
color={theme.palette.common.main}
color={theme.palette.primary.main}
ml={theme.spacing(2)}
onClick={handleNavigate}
sx={{ userSelect: "none" }}
+51 -39
View File
@@ -2,7 +2,7 @@ import PropTypes from "prop-types";
import { useState, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { useTheme } from "@emotion/react";
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useDispatch } from "react-redux";
import { credentials } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
@@ -13,11 +13,9 @@ import Logo from "../../../assets/icons/bwu-icon.svg?react";
import Mail from "../../../assets/icons/mail.svg?react";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import Check from "../../../Components/Check/Check";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
import { networkService } from "../../../main";
import "../index.css";
import { logger } from "../../../Utils/Logger";
/**
* Displays the initial landing page.
@@ -46,17 +44,22 @@ const LandingPage = ({ isSuperAdmin, onSignup }) => {
</Box>
<Box width="100%">
<Button
level="secondary"
label="Sign up with Email"
img={<Mail />}
variant="outlined"
color="info"
onClick={onSignup}
sx={{
width: "100%",
"& svg": {
mr: theme.spacing(4),
"& path": {
stroke: theme.palette.other.icon,
},
},
}}
/>
>
<Mail />
Sign up with Email
</Button>
</Box>
<Box maxWidth={400}>
<Typography className="tos-p">
@@ -180,26 +183,29 @@ const StepOne = ({ form, errors, onSubmit, onChange, onBack }) => {
</Box>
<Stack direction="row" justifyContent="space-between">
<Button
level="secondary"
label="Back"
animate="slideLeft"
img={<ArrowBackRoundedIcon />}
variant="outlined"
color="info"
onClick={onBack}
sx={{
px: theme.spacing(8),
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(2),
mr: theme.spacing(3),
},
}}
props={{ tabIndex: -1 }}
/>
>
<ArrowBackRoundedIcon />
Back
</Button>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={onSubmit}
disabled={(errors.firstName || errors.lastName) && true}
sx={{ width: "30%" }}
/>
>
Continue
</Button>
</Stack>
</Stack>
</>
@@ -270,26 +276,29 @@ const StepTwo = ({ form, errors, onSubmit, onChange, onBack }) => {
</Box>
<Stack direction="row" justifyContent="space-between">
<Button
level="secondary"
label="Back"
animate="slideLeft"
img={<ArrowBackRoundedIcon />}
variant="outlined"
color="info"
onClick={onBack}
sx={{
px: theme.spacing(8),
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(2),
mr: theme.spacing(3),
},
}}
props={{ tabIndex: -1 }}
/>
>
<ArrowBackRoundedIcon />
Back
</Button>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={onSubmit}
disabled={errors.email && true}
sx={{ width: "30%" }}
/>
>
Continue
</Button>
</Stack>
</Stack>
</>
@@ -443,26 +452,29 @@ const StepThree = ({ form, errors, onSubmit, onChange, onBack }) => {
</Box>
<Stack direction="row" justifyContent="space-between">
<Button
level="secondary"
label="Back"
animate="slideLeft"
img={<ArrowBackRoundedIcon />}
variant="outlined"
color="info"
onClick={onBack}
sx={{
px: theme.spacing(8),
px: theme.spacing(5),
"& svg.MuiSvgIcon-root": {
mr: theme.spacing(2),
mr: theme.spacing(3),
},
}}
props={{ tabIndex: -1 }}
/>
>
<ArrowBackRoundedIcon />
Back
</Button>
<Button
level="primary"
label="Continue"
variant="contained"
color="primary"
onClick={onSubmit}
disabled={errors.email && true}
sx={{ width: "30%" }}
/>
>
Continue
</Button>
</Stack>
</Stack>
</>
@@ -644,7 +656,7 @@ const Register = ({ isSuperAdmin }) => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 30,
},
@@ -731,7 +743,7 @@ const Register = ({ isSuperAdmin }) => {
onClick={() => {
navigate("/login");
}}
sx={{ userSelect: "none", color: theme.palette.common.main }}
sx={{ userSelect: "none", color: theme.palette.primary.main }}
>
Log In
</Typography>
+11 -9
View File
@@ -8,11 +8,11 @@ import { useState } from "react";
import { credentials } from "../../Validation/validation";
import { useNavigate } from "react-router-dom";
import Check from "../../Components/Check/Check";
import ButtonSpinner from "../../Components/ButtonSpinner";
import Field from "../../Components/Inputs/Field";
import LockIcon from "../../assets/icons/lock-button-icon.svg?react";
import background from "../../assets/Images/background_pattern_decorative.png";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import LoadingButton from "@mui/lab/LoadingButton";
import "./index.css";
const SetNewPassword = () => {
@@ -109,7 +109,7 @@ const SetNewPassword = () => {
overflow="hidden"
sx={{
"& h1": {
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 600,
fontSize: 24,
},
@@ -266,21 +266,23 @@ const SetNewPassword = () => {
/>
</Stack>
</Box>
<ButtonSpinner
disabled={Object.keys(errors).length !== 0}
isLoading={isLoading}
<LoadingButton
variant="contained"
color="primary"
loading={isLoading}
onClick={handleSubmit}
level="primary"
label="Reset password"
disabled={Object.keys(errors).length !== 0}
sx={{ width: "100%", maxWidth: 400 }}
/>
>
Reset password
</LoadingButton>
</Stack>
</Stack>
<Box textAlign="center" p={theme.spacing(12)}>
<Typography display="inline-block">Go back to —</Typography>
<Typography
component="span"
color={theme.palette.common.main}
color={theme.palette.primary.main}
ml={theme.spacing(2)}
onClick={() => navigate("/login")}
sx={{ userSelect: "none" }}
+23 -34
View File
@@ -1,7 +1,12 @@
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { ButtonGroup, Stack, Skeleton, Typography } from "@mui/material";
import Button from "../../Components/Button";
import {
ButtonGroup,
Stack,
Skeleton,
Typography,
Button,
} from "@mui/material";
import { networkService } from "../../main";
import { useTheme } from "@emotion/react";
import Select from "../../Components/Inputs/Select";
@@ -78,11 +83,7 @@ const Incidents = () => {
};
return (
<Stack
className="incidents"
pt={theme.spacing(21)}
gap={theme.spacing(12)}
>
<Stack className="incidents" pt={theme.spacing(21)} gap={theme.spacing(12)}>
{loading ? (
<SkeletonLayout />
) : (
@@ -114,38 +115,26 @@ const Incidents = () => {
}}
>
<Button
level="secondary"
label="All"
variant="group"
filled={(filter === "all").toString()}
onClick={() => setFilter("all")}
sx={{
backgroundColor:
filter === "all"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
>
All
</Button>
<Button
level="secondary"
label="Down"
variant="group"
filled={(filter === "down").toString()}
onClick={() => setFilter("down")}
sx={{
backgroundColor:
filter === "down"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
>
Down
</Button>
<Button
level="secondary"
label="Cannot Resolve"
variant="group"
filled={(filter === "resolve").toString()}
onClick={() => setFilter("resolve")}
sx={{
backgroundColor:
filter === "resolve"
? theme.palette.background.fill
: theme.palette.background.main,
}}
/>
>
Cannot Resolve
</Button>
</ButtonGroup>
</Stack>
<IncidentTable
+6 -5
View File
@@ -1,6 +1,5 @@
import PropTypes from "prop-types";
import { Stack, Typography, Grid } from "@mui/material";
import Button from "../../Components/Button";
import { Stack, Typography, Grid, Button } from "@mui/material";
import { useTheme } from "@emotion/react";
import Discord from "../../assets/icons/discord-icon.svg?react";
import Slack from "../../assets/icons/slack-icon.svg?react";
@@ -47,12 +46,14 @@ const IntegrationsComponent = ({ icon, header, info, onClick }) => {
</Typography>
</Stack>
<Button
label="Add"
level="primary"
variant="contained"
color="primary"
onClick={onClick}
sx={{ alignSelf: "center" }}
disabled={true}
/>
>
Add
</Button>
</Stack>
</Grid>
);
@@ -1,7 +1,6 @@
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import "./index.css";
import { useState } from "react";
import Button from "../../../Components/Button";
import Back from "../../../assets/icons/left-arrow-long.svg?react";
import Select from "../../../Components/Inputs/Select";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
@@ -215,7 +214,7 @@ const CreateNewMaintenanceWindow = () => {
sx={{
width: "fit-content",
fontSize: "var(--env-var-font-size-small)",
borderBottom: `1px dashed ${theme.palette.common.main}`,
borderBottom: `1px dashed ${theme.palette.primary.main}`,
paddingBottom: "4px",
}}
>
@@ -230,18 +229,17 @@ const CreateNewMaintenanceWindow = () => {
<div className="create-maintenance-window">
<Stack gap={theme.spacing(10)}>
<Button
id="btn-back"
variant="contained"
color="secondary"
sx={{
width: "100px",
height: "30px",
gap: "10px",
backgroundColor: theme.palette.background.fill,
color: theme.palette.text.secondary,
}}
label="Back"
level="tertiary"
img={<Back />}
/>
>
<Back />
Back
</Button>
<Box>
<Typography
sx={{
@@ -278,26 +276,19 @@ const CreateNewMaintenanceWindow = () => {
</Stack>
<Stack justifyContent="end" direction="row" marginTop={3}>
<Button
variant="text"
color="info"
sx={{
"&:hover": {
backgroundColor: "transparent",
boxShadow: "none",
},
}}
level="tertiary"
label="Cancel"
/>
<Button
sx={{
"&:hover": {
backgroundColor: "#1570EF",
boxShadow: "none",
},
}}
level="primary"
label="Create"
onClick={handleSubmit}
/>
>
Cancel
</Button>
<Button variant="contained" color="primary" onClick={handleSubmit}>
Create
</Button>
</Stack>
</Stack>
</div>
+53 -28
View File
@@ -2,7 +2,7 @@ import { useNavigate, useParams } from "react-router";
import { useTheme } from "@emotion/react";
import { useDispatch, useSelector } from "react-redux";
import { useEffect, useState } from "react";
import { Box, Modal, Stack, Typography } from "@mui/material";
import { Box, Button, Modal, Stack, Typography } from "@mui/material";
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
@@ -14,16 +14,17 @@ import {
getUptimeMonitorsByTeamId,
deleteUptimeMonitor,
} from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
import Select from "../../../Components/Inputs/Select";
import Checkbox from "../../../Components/Inputs/Checkbox";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import PulseDot from "../../../Components/Animated/PulseDot";
import "./index.css";
import SkeletonLayout from "./skeleton";
import ButtonSpinner from "../../../Components/ButtonSpinner";
import LoadingButton from "@mui/lab/LoadingButton";
import "./index.css";
/**
* Parses a URL string and returns a URL object.
*
@@ -248,27 +249,40 @@ const Configure = () => {
ml: "auto",
}}
>
<ButtonSpinner
isLoading={isLoading}
level="tertiary"
label={monitor?.isActive ? "Pause" : "Resume"}
img={<PauseCircleOutlineIcon />}
<LoadingButton
variant="contained"
color="secondary"
loading={isLoading}
sx={{
backgroundColor: theme.palette.background.main,
px: theme.spacing(6),
px: theme.spacing(5),
mr: theme.spacing(6),
"& svg": {
mr: theme.spacing(2),
},
}}
onClick={handlePause}
/>
<ButtonSpinner
isLoading={isLoading}
level="error"
label="Remove"
sx={{
px: theme.spacing(8),
}}
>
{monitor?.isActive ? (
<>
<PauseCircleOutlineIcon />
Pause
</>
) : (
<>
<PlayCircleOutlineRoundedIcon />
Resume
</>
)}
</LoadingButton>
<Button
variant="contained"
color="error"
sx={{ px: theme.spacing(8) }}
onClick={() => setIsOpen(true)}
/>
>
Remove
</Button>
</Box>
</Stack>
<ConfigBox>
@@ -375,13 +389,15 @@ const Configure = () => {
</Stack>
</ConfigBox>
<Stack direction="row" justifyContent="flex-end" mt="auto">
<ButtonSpinner
isLoading={isLoading}
level="primary"
label="Save"
<LoadingButton
variant="contained"
color="primary"
loading={isLoading}
sx={{ px: theme.spacing(12) }}
onClick={handleSubmit}
/>
>
Save
</LoadingButton>
</Stack>
</Stack>
</>
@@ -434,11 +450,20 @@ const Configure = () => {
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
variant="text"
color="info"
onClick={() => setIsOpen(false)}
/>
<Button level="error" label="Delete" onClick={handleRemove} />
>
Cancel
</Button>
<LoadingButton
variant="contained"
color="error"
loading={isLoading}
onClick={handleRemove}
>
Delete
</LoadingButton>
</Stack>
</Stack>
</Modal>
@@ -1,5 +1,5 @@
import { useState } from "react";
import { Box, ButtonGroup, Stack, Typography } from "@mui/material";
import { Box, Button, ButtonGroup, Stack, Typography } from "@mui/material";
import { useSelector, useDispatch } from "react-redux";
import { monitorValidation } from "../../../Validation/validation";
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
@@ -9,7 +9,6 @@ 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";
@@ -232,29 +231,19 @@ const CreateMonitor = () => {
{monitor.type === "http" ? (
<ButtonGroup sx={{ ml: "32px" }}>
<Button
level="secondary"
label="HTTPS"
variant="group"
filled={https.toString()}
onClick={() => setHttps(true)}
sx={{
backgroundColor: https && theme.palette.background.fill,
borderColor: theme.palette.border.dark,
"&:hover": {
borderColor: theme.palette.border.dark,
},
}}
/>
>
HTTPS
</Button>
<Button
level="secondary"
label="HTTP"
variant="group"
filled={(!https).toString()}
onClick={() => setHttps(false)}
sx={{
backgroundColor: !https && theme.palette.background.fill,
borderColor: theme.palette.border.dark,
"&:hover": {
borderColor: theme.palette.border.dark,
},
}}
/>
>
HTTP
</Button>
</ButtonGroup>
) : (
""
@@ -354,12 +343,13 @@ const CreateMonitor = () => {
</ConfigBox>
<Stack direction="row" justifyContent="flex-end">
<Button
id="create-monitor-btn"
level="primary"
label="Create monitor"
variant="contained"
color="primary"
onClick={handleCreateMonitor}
disabled={Object.keys(errors).length !== 0 && true}
/>
>
Create monitor
</Button>
</Stack>
</Stack>
</Box>
+34 -45
View File
@@ -1,6 +1,13 @@
import PropTypes from "prop-types";
import { useEffect, useState, useCallback } from "react";
import { Box, Skeleton, Stack, Typography, useTheme } from "@mui/material";
import {
Box,
Button,
Skeleton,
Stack,
Typography,
useTheme,
} from "@mui/material";
import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { networkService } from "../../../main";
@@ -11,7 +18,6 @@ import {
} from "../../../Utils/timeUtils";
import MonitorDetailsAreaChart from "../../../Components/Charts/MonitorDetailsAreaChart";
import ButtonGroup from "@mui/material/ButtonGroup";
import Button from "../../../Components/Button";
import SettingsIcon from "../../../assets/icons/settings-bold.svg?react";
import PaginationTable from "./PaginationTable";
import Breadcrumbs from "../../../Components/Breadcrumbs";
@@ -37,7 +43,7 @@ const StatBox = ({ title, value }) => {
mb={theme.spacing(2)}
fontSize={14}
fontWeight={500}
color={theme.palette.common.main}
color={theme.palette.primary.main}
sx={{
"& span": {
color: theme.palette.text.accent,
@@ -237,28 +243,23 @@ const DetailsPage = ({ isAdmin }) => {
</Box>
{isAdmin && (
<Button
level="tertiary"
label="Configure"
animate="rotate90"
img={
<SettingsIcon
style={{
minWidth: theme.spacing(10),
minHeight: theme.spacing(10),
}}
/>
}
variant="contained"
color="secondary"
onClick={() => navigate(`/monitors/configure/${monitorId}`)}
sx={{
ml: "auto",
alignSelf: "flex-end",
backgroundColor: theme.palette.background.fill,
px: theme.spacing(6),
px: theme.spacing(5),
"& svg": {
mr: theme.spacing(3),
"& path": {
stroke: theme.palette.other.icon,
},
},
}}
/>
>
<SettingsIcon /> Configure
</Button>
)}
</Stack>
<Stack
@@ -326,40 +327,28 @@ const DetailsPage = ({ isAdmin }) => {
>
Response Times
</Typography>
<ButtonGroup
sx={{
"& .MuiButtonBase-root": {
borderColor: theme.palette.border.light,
},
}}
>
<ButtonGroup>
<Button
level="secondary"
label="Day"
variant="group"
filled={(dateRange === "day").toString()}
onClick={() => setDateRange("day")}
sx={{
backgroundColor:
dateRange === "day" && theme.palette.background.fill,
}}
/>
>
Day
</Button>
<Button
level="secondary"
label="Week"
variant="group"
filled={(dateRange === "week").toString()}
onClick={() => setDateRange("week")}
sx={{
backgroundColor:
dateRange === "week" && theme.palette.background.fill,
}}
/>
>
Week
</Button>
<Button
level="secondary"
label="Month"
variant="group"
filled={(dateRange === "month").toString()}
onClick={() => setDateRange("month")}
sx={{
backgroundColor:
dateRange === "month" && theme.palette.background.fill,
}}
/>
>
Month
</Button>
</ButtonGroup>
</Stack>
<Box
+11 -7
View File
@@ -4,6 +4,7 @@ import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import { createToast } from "../../../Utils/toastUtils";
import {
Button,
IconButton,
Menu,
MenuItem,
@@ -16,7 +17,6 @@ import {
getUptimeMonitorsByTeamId,
} from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import Settings from "../../../assets/icons/settings-bold.svg?react";
import Button from "../../../Components/Button";
import PropTypes from "prop-types";
const ActionsMenu = ({ monitor, isAdmin }) => {
@@ -189,21 +189,25 @@ const ActionsMenu = ({ monitor, isAdmin }) => {
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
variant="text"
color="info"
onClick={(e) => {
e.stopPropagation();
setIsOpen(false);
}}
/>
>
Cancel
</Button>
<Button
level="error"
label="Delete"
variant="contained"
color="error"
onClick={(e) => {
e.stopPropagation(e);
handleRemove(e);
}}
/>
>
Delete
</Button>
</Stack>
</Stack>
</Modal>
+6 -5
View File
@@ -1,6 +1,5 @@
import { Stack, Typography } from "@mui/material";
import { Button, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import Button from "../../../Components/Button";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
@@ -25,13 +24,15 @@ const Fallback = ({ isAdmin }) => {
</Typography>
{isAdmin && (
<Button
level="primary"
label="Create your first monitor"
variant="contained"
color="primary"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ mt: theme.spacing(12) }}
/>
>
Create your first monitor
</Button>
)}
</Stack>
);
+6 -5
View File
@@ -3,10 +3,9 @@ import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { getUptimeMonitorsByTeamId } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { useNavigate } from "react-router-dom";
import Button from "../../../Components/Button";
import { useTheme } from "@emotion/react";
import BasicTable from "../../../Components/BasicTable";
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
import SkeletonLayout from "./skeleton";
import Fallback from "./fallback";
@@ -77,13 +76,15 @@ const Monitors = ({ isAdmin }) => {
<Greeting type="uptime" />
{monitorState.monitors?.length !== 0 && (
<Button
level="primary"
label="Create monitor"
variant="contained"
color="primary"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ fontWeight: 500 }}
/>
>
Create monitor
</Button>
)}
</Stack>
</Box>
+6 -5
View File
@@ -1,8 +1,7 @@
import Button from "../../Components/Button";
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 { Button, Stack, Typography } from "@mui/material";
import { useNavigate } from "react-router";
import { useTheme } from "@emotion/react";
@@ -48,11 +47,13 @@ const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
</Typography>
<Typography fontSize={13}>{desc}</Typography>
<Button
label="Go to the main dashboard"
level="primary"
variant="contained"
color="primary"
sx={{ mt: theme.spacing(10) }}
onClick={() => navigate("/")}
/>
>
Go to the main dashboard
</Button>
</Stack>
</Stack>
);
+31 -22
View File
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
import { Box, Modal, Skeleton, Stack, Typography } from "@mui/material";
import { Box, Button, Modal, Skeleton, Stack, Typography } from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router";
import {
@@ -11,7 +11,6 @@ import {
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
import Select from "../../../Components/Inputs/Select";
import Checkbox from "../../../Components/Inputs/Checkbox";
@@ -197,29 +196,33 @@ const PageSpeedConfigure = () => {
</Box>
<Box alignSelf="flex-end" ml="auto">
<Button
level="tertiary"
label="Pause"
animate="rotate180"
img={<PauseCircleOutlineIcon />}
variant="contained"
color="secondary"
sx={{
backgroundColor: theme.palette.background.fill,
pl: theme.spacing(4),
pr: theme.spacing(6),
"& svg": {
mr: theme.spacing(2),
"& path": {
stroke: theme.palette.other.icon,
strokeWidth: 0.1,
},
},
}}
/>
>
<PauseCircleOutlineIcon />
Pause
</Button>
<Button
level="error"
label="Remove"
variant="contained"
color="error"
onClick={() => setIsOpen(true)}
sx={{
boxShadow: "none",
px: theme.spacing(8),
ml: theme.spacing(6),
}}
onClick={() => setIsOpen(true)}
/>
>
Remove
</Button>
</Box>
</Stack>
<Stack
@@ -321,11 +324,13 @@ const PageSpeedConfigure = () => {
<Stack direction="row" justifyContent="flex-end" mt="auto">
<Button
type="submit"
level="primary"
label="Save"
variant="contained"
color="primary"
onClick={handleSave}
sx={{ px: theme.spacing(12), mt: theme.spacing(12) }}
/>
sx={{ px: theme.spacing(12) }}
>
Save
</Button>
</Stack>
</Stack>
</>
@@ -376,11 +381,15 @@ const PageSpeedConfigure = () => {
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
variant="text"
color="info"
onClick={() => setIsOpen(false)}
/>
<Button level="error" label="Delete" onClick={handleRemove} />
>
Cancel
</Button>
<Button variant="contained" color="error" onClick={handleRemove}>
Delete
</Button>
</Stack>
</Stack>
</Modal>
@@ -22,6 +22,7 @@
.create-page-speed .section-disabled {
opacity: 0.4;
padding: 10px;
margin-right: -5px;
border-radius: 8px;
user-select: none;
pointer-events: none;
@@ -1,11 +1,10 @@
import { Box, Stack, Typography } from "@mui/material";
import { Box, Button, Stack, Typography } from "@mui/material";
import { useState } from "react";
import { useTheme } from "@emotion/react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router";
import Field from "../../../Components/Inputs/Field";
import Select from "../../../Components/Inputs/Select";
import Button from "../../../Components/Button";
import Checkbox from "../../../Components/Inputs/Checkbox";
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
@@ -229,11 +228,13 @@ const CreatePageSpeed = () => {
<Stack direction="row" justifyContent="flex-end" mt="auto">
<Button
type="submit"
level="primary"
label="Create"
variant="contained"
color="primary"
onClick={handleCreate}
sx={{ px: theme.spacing(12), mt: theme.spacing(12) }}
/>
>
Create
</Button>
</Stack>
</Stack>
</Stack>
+15 -20
View File
@@ -1,5 +1,5 @@
import PropTypes from "prop-types";
import { Box, Skeleton, Stack, Typography } from "@mui/material";
import { Box, Button, Skeleton, Stack, Typography } from "@mui/material";
import { PieChart } from "@mui/x-charts/PieChart";
import { useDrawingArea } from "@mui/x-charts";
import { useEffect, useState } from "react";
@@ -12,7 +12,6 @@ import {
} from "../../../Utils/timeUtils";
import { logger } from "../../../Utils/Logger";
import { networkService } from "../../../main";
import Button from "../../../Components/Button";
import SettingsIcon from "../../../assets/icons/settings-bold.svg?react";
import LastCheckedIcon from "../../../assets/icons/calendar-check.svg?react";
import ClockIcon from "../../../assets/icons/maintenance.svg?react";
@@ -43,7 +42,7 @@ const StatBox = ({ icon, title, value }) => {
<Box>
<Typography
variant="h6"
color={theme.palette.common.main}
color={theme.palette.primary.main}
mb={theme.spacing(6)}
>
{title}
@@ -398,28 +397,24 @@ const PageSpeedDetails = () => {
</Typography>
</Box>
<Button
level="tertiary"
label="Configure"
animate="rotate90"
img={
<SettingsIcon
style={{
width: theme.spacing(10),
height: theme.spacing(10),
}}
/>
}
variant="contained"
color="secondary"
onClick={() => navigate(`/pagespeed/configure/${monitorId}`)}
sx={{
ml: "auto",
alignSelf: "flex-end",
backgroundColor: theme.palette.background.fill,
px: theme.spacing(6),
px: theme.spacing(5),
"& svg": {
mr: "6px",
mr: theme.spacing(3),
"& path": {
stroke: theme.palette.other.icon,
},
},
}}
/>
>
<SettingsIcon />
Configure
</Button>
</Stack>
<Stack
direction="row"
@@ -592,7 +587,7 @@ const PageSpeedDetails = () => {
<Typography
component="span"
sx={{
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 500,
textDecoration: "underline",
cursor: "pointer",
@@ -627,7 +622,7 @@ const PageSpeedDetails = () => {
<Typography
component="span"
sx={{
color: theme.palette.common.main,
color: theme.palette.primary.main,
fontWeight: 500,
textDecoration: "underline",
cursor: "pointer",
+7 -6
View File
@@ -1,4 +1,4 @@
import { Box, Grid, Skeleton, Stack, Typography } from "@mui/material";
import { Box, Button, Grid, Skeleton, Stack, Typography } from "@mui/material";
import { useEffect } from "react";
import { useTheme } from "@emotion/react";
import { formatDate, formatDurationRounded } from "../../Utils/timeUtils";
@@ -8,7 +8,6 @@ import { getPageSpeedByTeamId } from "../../Features/PageSpeedMonitor/pageSpeedM
import PageSpeedIcon from "../../assets/icons/page-speed.svg?react";
import Fallback from "../../Components/Fallback";
import "./index.css";
import Button from "../../Components/Button";
import { useNavigate } from "react-router";
import { getLastChecked } from "../../Utils/monitorUtils";
import PropTypes from "prop-types";
@@ -52,7 +51,7 @@ const Card = ({ data }) => {
<Typography
component="h2"
mb={theme.spacing(2)}
color={theme.palette.common.main}
color={theme.palette.primary.main}
>
{data.name}
</Typography>
@@ -196,10 +195,12 @@ const PageSpeed = ({ isAdmin }) => {
>
<Greeting type="pagespeed" />
<Button
level="primary"
label="Create new"
variant="contained"
color="primary"
onClick={() => navigate("/pagespeed/create")}
/>
>
Create new
</Button>
</Stack>
</Box>
<Grid container spacing={theme.spacing(12)}>
+14 -11
View File
@@ -1,7 +1,5 @@
import { useTheme } from "@emotion/react";
import { Box, Stack, styled, Typography } from "@mui/material";
import Button from "../../Components/Button";
import ButtonSpinner from "../../Components/ButtonSpinner";
import { Box, Button, Stack, styled, Typography } from "@mui/material";
import Field from "../../Components/Inputs/Field";
import Link from "../../Components/Link";
import Select from "../../Components/Inputs/Select";
@@ -11,6 +9,7 @@ import { useDispatch, useSelector } from "react-redux";
import { createToast } from "../../Utils/toastUtils";
import { deleteMonitorChecksByTeamId } from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
import PropTypes from "prop-types";
import LoadingButton from "@mui/lab/LoadingButton";
const Settings = ({ isAdmin }) => {
const theme = useTheme();
const { user, authToken } = useSelector((state) => state.auth);
@@ -125,13 +124,15 @@ const Settings = ({ isAdmin }) => {
/>
<Box>
<Typography>Clear all stats. This is irreversible.</Typography>
<ButtonSpinner
isLoading={isLoading}
level="error"
label="Clear all stats"
<LoadingButton
variant="contained"
color="error"
loading={isLoading}
onClick={handleClearStats}
sx={{ mt: theme.spacing(4) }}
/>
>
Clear all stats
</LoadingButton>
</Box>
</Stack>
</ConfigBox>
@@ -156,10 +157,12 @@ const Settings = ({ isAdmin }) => {
</ConfigBox>
<Stack direction="row" justifyContent="flex-end">
<Button
level="primary"
label="Save"
variant="contained"
color="primary"
sx={{ px: theme.spacing(12), mt: theme.spacing(20) }}
/>
>
Save
</Button>
</Stack>
</Stack>
</Box>
+46 -14
View File
@@ -24,13 +24,14 @@ const darkTheme = createTheme({
typography: { fontFamily: fontFamilyDefault, fontSize: 13 },
palette: {
mode: "dark",
common: { main: "#1570ef" },
primary: { main: "#1570ef" },
secondary: { main: "#2e2e2e" },
text: text,
background: background,
border: border,
info: {
text: text.primary,
main: text.primary,
main: text.secondary,
bg: background.main,
light: background.main,
border: border.light,
@@ -46,6 +47,7 @@ const darkTheme = createTheme({
main: "#d32f2f",
light: "#1e1e1e",
bg: "#27272a",
dark: "#932020",
border: "#f04438",
},
warning: {
@@ -63,29 +65,52 @@ const darkTheme = createTheme({
fill: "#18181a",
grid: "#454546",
},
// TO BE REMOVED //
primary: {
main: "#1570ef",
},
secondary: {
main: "#e6e6e6",
},
tertiary: {
main: "#e6e6e6",
},
// ----------------- //
},
spacing: 2,
components: {
MuiButtonBase: {
MuiButton: {
defaultProps: {
disableRipple: true,
},
styleOverrides: {
root: ({ theme }) => ({
variants: [
{
props: (props) => props.variant === "group",
style: {
color: theme.palette.secondary.contrastText,
backgroundColor: theme.palette.background.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
},
},
{
props: (props) =>
props.variant === "group" && props.filled === "true",
style: {
backgroundColor: theme.palette.secondary.main,
},
},
],
fontWeight: 400,
borderRadius: 4,
boxShadow: "none",
textTransform: "none",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
},
}),
},
},
MuiIconButton: {
styleOverrides: {
root: {
padding: 4,
transition: "none",
"&:hover": {
backgroundColor: background.fill,
},
@@ -114,6 +139,13 @@ const darkTheme = createTheme({
},
},
},
MuiListItemButton: {
styleOverrides: {
root: {
transition: "none",
},
},
},
MuiMenuItem: {
styleOverrides: {
root: {
+49 -18
View File
@@ -22,16 +22,17 @@ const shadow =
const lightTheme = createTheme({
typography: { fontFamily: fontFamilyDefault, fontSize: 13 },
palette: {
common: { main: "#1570ef" },
primary: { main: "#1570EF" },
secondary: { main: "#F4F4F4", dark: "#e3e3e3", contrastText: "#475467" },
text: text,
background: background,
border: border,
info: {
text: "#475467",
main: "#475467",
bg: "#ffffff",
light: "#ffffff",
border: "#D0D5DD",
text: text.primary,
main: text.tertiary,
bg: background.main,
light: background.main,
border: border.dark,
},
success: {
text: "#079455",
@@ -61,29 +62,52 @@ const lightTheme = createTheme({
fill: "#e3e3e3",
grid: "#a2a3a3",
},
// TO BE REMOVED //
primary: {
main: "#1570EF",
},
secondary: {
main: "#475467",
},
tertiary: {
main: "#475467",
},
// ----------------- //
},
spacing: 2,
components: {
MuiButtonBase: {
MuiButton: {
defaultProps: {
disableRipple: true,
},
styleOverrides: {
root: ({ theme }) => ({
variants: [
{
props: (props) => props.variant === "group",
style: {
color: theme.palette.secondary.contrastText,
backgroundColor: theme.palette.background.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
},
},
{
props: (props) =>
props.variant === "group" && props.filled === "true",
style: {
backgroundColor: theme.palette.secondary.main,
},
},
],
fontWeight: 400,
borderRadius: 4,
boxShadow: "none",
textTransform: "none",
"&:focus": {
outline: "none",
},
"&:hover": {
boxShadow: "none",
},
}),
},
},
MuiIconButton: {
styleOverrides: {
root: {
padding: 4,
transition: "none",
"&:hover": {
backgroundColor: background.fill,
},
@@ -110,6 +134,13 @@ const lightTheme = createTheme({
},
},
},
MuiListItemButton: {
styleOverrides: {
root: {
transition: "none",
},
},
},
MuiMenuItem: {
styleOverrides: {
root: {