Merge pull request #770 from bluewave-labs/feat/theme-button-styles
Feat/theme button styles
This commit is contained in:
38 files changed
+614
-791
No files matched your search
@@ -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 && (
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'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" }}
|
||||
>
|
||||
|
||||
@@ -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" }}
|
||||
|
||||
@@ -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" }}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)}>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in new issue
Block a user