diff --git a/Client/src/App.jsx b/Client/src/App.jsx index b5b83e221..69ce98c4c 100644 --- a/Client/src/App.jsx +++ b/Client/src/App.jsx @@ -28,6 +28,9 @@ import CreatePageSpeed from "./Pages/PageSpeed/CreatePageSpeed"; import CreateNewMaintenanceWindow from "./Pages/Maintenance/CreateMaintenanceWindow"; import PageSpeedDetails from "./Pages/PageSpeed/Details"; import PageSpeedConfigure from "./Pages/PageSpeed/Configure"; +import { ThemeProvider } from "@emotion/react"; +import theme, { darkTheme } from "./Utils/Theme"; +import { useSelector } from "react-redux"; function App() { const AdminCheckedRegister = withAdminCheck(Register); @@ -35,8 +38,11 @@ function App() { const DetailsWithAdminProp = withAdminProp(Details); const PageSpeedWithAdminProp = withAdminProp(PageSpeed); const MaintenanceWithAdminProp = withAdminProp(Maintenance); + + const { mode } = useSelector((state) => state.ui); + return ( - <> + }> - + ); } diff --git a/Client/src/Components/BasicTable/index.css b/Client/src/Components/BasicTable/index.css index 4839c7dcb..c345abf7c 100644 --- a/Client/src/Components/BasicTable/index.css +++ b/Client/src/Components/BasicTable/index.css @@ -53,7 +53,6 @@ } .MuiPaper-root + .MuiPagination-root { - margin-top: 24px; border-radius: var(--env-var-radius-1); padding: var(--env-var-spacing-1-plus) var(--env-var-spacing-2); } diff --git a/Client/src/Components/BasicTable/index.jsx b/Client/src/Components/BasicTable/index.jsx index 95abfc05f..9852d7987 100644 --- a/Client/src/Components/BasicTable/index.jsx +++ b/Client/src/Components/BasicTable/index.jsx @@ -203,6 +203,7 @@ const BasicTable = ({ data, paginated, reversed, table }) => { { key={col.id} sx={{ color: theme.palette.text.secondary, + borderBottomColor: theme.palette.border.light, }} > {col.name} @@ -245,6 +247,7 @@ const BasicTable = ({ data, paginated, reversed, table }) => { key={cell.id} sx={{ color: theme.palette.text.secondary, + borderBottomColor: theme.palette.border.light, }} > {cell.data} @@ -299,6 +302,7 @@ const BasicTable = ({ data, paginated, reversed, table }) => { borderColor: theme.palette.border.light, borderRadius: theme.shape.borderRadius, boxShadow: theme.shape.boxShadow, + backgroundColor: theme.palette.background.main, "& li": { p: theme.spacing(2), color: theme.palette.text.tertiary, @@ -329,7 +333,7 @@ const BasicTable = ({ data, paginated, reversed, table }) => { sx={{ mt: theme.spacing(6), color: theme.palette.text.secondary, - "& button, & .MuiSelect-select": { + "& button.MuiButtonBase-root, & .MuiSelect-select": { border: 1, borderColor: theme.palette.border.light, borderRadius: theme.shape.borderRadius, diff --git a/Client/src/Components/Inputs/Checkbox/index.jsx b/Client/src/Components/Inputs/Checkbox/index.jsx index c48c59bf5..e7af04a64 100644 --- a/Client/src/Components/Inputs/Checkbox/index.jsx +++ b/Client/src/Components/Inputs/Checkbox/index.jsx @@ -72,7 +72,7 @@ const Checkbox = ({ mr: theme.spacing(6), }, "&:not(:has(.Mui-disabled)):hover": { - backgroundColor: theme.palette.unresolved.bg, + backgroundColor: theme.palette.background.accent, }, "& span.MuiTypography-root": { fontSize: 13, diff --git a/Client/src/Components/Inputs/Field/index.jsx b/Client/src/Components/Inputs/Field/index.jsx index 3574377d8..293cbcdd3 100644 --- a/Client/src/Components/Inputs/Field/index.jsx +++ b/Client/src/Components/Inputs/Field/index.jsx @@ -141,7 +141,7 @@ const Field = forwardRef( height="100%" sx={{ borderRight: `solid 1px ${theme.palette.border.dark}`, - backgroundColor: "#f9f9fa", + backgroundColor: theme.palette.background.accent, pl: theme.spacing(6), }} > diff --git a/Client/src/Components/Inputs/Radio/index.jsx b/Client/src/Components/Inputs/Radio/index.jsx index c5595be83..1772912ac 100644 --- a/Client/src/Components/Inputs/Radio/index.jsx +++ b/Client/src/Components/Inputs/Radio/index.jsx @@ -41,7 +41,7 @@ const Radio = (props) => { color: "transparent", width: 16, height: 16, - boxShadow: "inset 0 0 0 1px rgb(16 22 26 / 40%)", + boxShadow: "inset 0 0 0 1px #656a74", mt: theme.spacing(0.5), }} /> @@ -50,7 +50,11 @@ const Radio = (props) => { label={ <> {props.title} - + {props.desc} @@ -62,7 +66,7 @@ const Radio = (props) => { m: theme.spacing(-2.5), borderRadius: theme.shape.borderRadius, "&:hover": { - backgroundColor: theme.palette.unresolved.bg, + backgroundColor: theme.palette.background.accent, }, "& .MuiButtonBase-root": { p: 0, diff --git a/Client/src/Components/Inputs/Select/index.jsx b/Client/src/Components/Inputs/Select/index.jsx index 5ae0492fe..9d5f065f4 100644 --- a/Client/src/Components/Inputs/Select/index.jsx +++ b/Client/src/Components/Inputs/Select/index.jsx @@ -85,6 +85,7 @@ const Select = ({ borderColor: theme.palette.border.light, borderRadius: theme.shape.borderRadius, boxShadow: theme.shape.boxShadow, + backgroundColor: theme.palette.background.main, }, }, MenuListProps: { @@ -114,6 +115,9 @@ const Select = ({ "&:not(.Mui-focused):hover fieldset": { borderColor: theme.palette.border.dark, }, + "& svg path": { + fill: theme.palette.other.icon, + }, ...sx, }} > diff --git a/Client/src/Components/Sidebar/index.jsx b/Client/src/Components/Sidebar/index.jsx index 71f7a2987..7dc3618a3 100644 --- a/Client/src/Components/Sidebar/index.jsx +++ b/Client/src/Components/Sidebar/index.jsx @@ -19,7 +19,7 @@ import { useLocation, useNavigate } from "react-router"; import { useTheme } from "@emotion/react"; import { useDispatch, useSelector } from "react-redux"; import { clearAuthState } from "../../Features/Auth/authSlice"; -import { toggleSidebar } from "../../Features/UI/uiSlice"; +import { setMode, toggleSidebar } from "../../Features/UI/uiSlice"; import { clearUptimeMonitorState } from "../../Features/UptimeMonitors/uptimeMonitorsSlice"; import Avatar from "../Avatar"; import LockSvg from "../../assets/icons/lock.svg?react"; @@ -40,6 +40,7 @@ import ArrowDown from "../../assets/icons/down-arrow.svg?react"; import ArrowUp from "../../assets/icons/up-arrow.svg?react"; import ArrowRight from "../../assets/icons/right-arrow.svg?react"; import ArrowLeft from "../../assets/icons/left-arrow.svg?react"; +import DotsVertical from "../../assets/icons/dots-vertical.svg?react"; import "./index.css"; @@ -309,6 +310,8 @@ function Sidebar() { borderColor: theme.palette.border.light, borderRadius: theme.shape.borderRadius, boxShadow: theme.shape.boxShadow, + backgroundColor: theme.palette.background.main, + ml: theme.spacing(1), }, }, }} @@ -424,7 +427,7 @@ function Sidebar() { left: "-7px", height: "100%", borderLeft: 1, - borderLeftColor: "#d6d9dd", + borderLeftColor: theme.palette.other.line, }, "&:last-child::before": { height: "50%", @@ -437,7 +440,7 @@ function Sidebar() { height: "3px", width: "3px", borderRadius: "50%", - backgroundColor: "#d6d9dd", + backgroundColor: theme.palette.other.line, }, "&.selected-path::after": { backgroundColor: theme.palette.text.tertiary, @@ -560,71 +563,6 @@ function Sidebar() { - - - - - {authState.user?.firstName} {authState.user?.lastName} - - - {authState.user?.role} - - - - - - - Log out - - ) : ( <> @@ -637,16 +575,101 @@ function Sidebar() { {authState.user?.role} - + openPopup(event, "logout")} > - + )} + + {collapsed && ( + + + + {authState.user?.firstName} {authState.user?.lastName} + + + {authState.user?.role} + + + + )} + {collapsed && ( + + )} + dispatch(setMode("light"))}>Light + dispatch(setMode("dark"))}>Dark + + + Log out + + ); diff --git a/Client/src/Features/UI/uiSlice.js b/Client/src/Features/UI/uiSlice.js index ebea20bf1..addc4e845 100644 --- a/Client/src/Features/UI/uiSlice.js +++ b/Client/src/Features/UI/uiSlice.js @@ -12,6 +12,7 @@ const initialState = { sidebar: { collapsed: false, }, + mode: "light", }; const uiSlice = createSlice({ @@ -24,8 +25,11 @@ const uiSlice = createSlice({ toggleSidebar: (state) => { state.sidebar.collapsed = !state.sidebar.collapsed; }, + setMode: (state, action) => { + state.mode = action.payload; + }, }, }); export default uiSlice.reducer; -export const { setRowsPerPage, toggleSidebar } = uiSlice.actions; +export const { setRowsPerPage, toggleSidebar, setMode } = uiSlice.actions; diff --git a/Client/src/Layouts/HomeLayout/index.jsx b/Client/src/Layouts/HomeLayout/index.jsx index 81cb2fd9c..92d763f0c 100644 --- a/Client/src/Layouts/HomeLayout/index.jsx +++ b/Client/src/Layouts/HomeLayout/index.jsx @@ -1,14 +1,19 @@ import Sidebar from "../../Components/Sidebar"; import { Outlet } from "react-router"; import { Box } from "@mui/material"; +import { useTheme } from "@emotion/react"; import "./index.css"; const HomeLayout = () => { + const theme = useTheme(); + return ( - - - + + + + + ); }; diff --git a/Client/src/Pages/Incidents/IncidentTable/index.jsx b/Client/src/Pages/Incidents/IncidentTable/index.jsx index 39a835ad4..c6132a26e 100644 --- a/Client/src/Pages/Incidents/IncidentTable/index.jsx +++ b/Client/src/Pages/Incidents/IncidentTable/index.jsx @@ -30,7 +30,7 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => { const [checksCount, setChecksCount] = useState(0); const [paginationController, setPaginationController] = useState({ page: 0, - rowsPerPage: 12, + rowsPerPage: 14, }); useEffect(() => { @@ -169,6 +169,10 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => { sx={{ border: `solid 1px ${theme.palette.border.light}`, borderRadius: theme.shape.borderRadius, + backgroundColor: theme.palette.background.main, + "& .MuiTableCell-root": { + borderBottomColor: theme.palette.border.light, + }, }} > diff --git a/Client/src/Pages/Incidents/index.jsx b/Client/src/Pages/Incidents/index.jsx index 510eeeaaf..75e8fb174 100644 --- a/Client/src/Pages/Incidents/index.jsx +++ b/Client/src/Pages/Incidents/index.jsx @@ -78,7 +78,11 @@ const Incidents = () => { }; return ( - + {loading ? ( ) : ( diff --git a/Client/src/Pages/Monitors/CreateMonitor/index.jsx b/Client/src/Pages/Monitors/CreateMonitor/index.jsx index 3de96ad5c..bc0f55ed3 100644 --- a/Client/src/Pages/Monitors/CreateMonitor/index.jsx +++ b/Client/src/Pages/Monitors/CreateMonitor/index.jsx @@ -237,6 +237,10 @@ const CreateMonitor = () => { onClick={() => setHttps(true)} sx={{ backgroundColor: https && theme.palette.background.fill, + borderColor: theme.palette.border.dark, + "&:hover": { + borderColor: theme.palette.border.dark, + }, }} />
@@ -134,13 +135,28 @@ const PaginationTable = ({ monitorId, dateRange }) => { }} > - + Status - + Date & Time - + Message @@ -151,17 +167,31 @@ const PaginationTable = ({ monitorId, dateRange }) => { return ( - + - + {new Date(check.createdAt).toLocaleString()} - {check.statusCode} + + {check.statusCode} + ); })} diff --git a/Client/src/Pages/Monitors/Home/StatusBox.jsx b/Client/src/Pages/Monitors/Home/StatusBox.jsx index e28d09d6c..a7c56d75a 100644 --- a/Client/src/Pages/Monitors/Home/StatusBox.jsx +++ b/Client/src/Pages/Monitors/Home/StatusBox.jsx @@ -8,7 +8,12 @@ import ClockSnooze from "../../../assets/icons/clock-snooze.svg?react"; const StatusBox = ({ title, value }) => { const theme = useTheme(); - let sharedStyles = { position: "absolute", right: 8, opacity: 0.5 }; + let sharedStyles = { + position: "absolute", + right: 8, + opacity: 0.5, + "& svg path": { stroke: theme.palette.other.icon }, + }; let color; let icon; @@ -48,7 +53,7 @@ const StatusBox = ({ title, value }) => { overflow="hidden" sx={{ "&:hover": { - backgroundColor: "#f9fafb", + backgroundColor: theme.palette.background.accent, }, "&:after": { position: "absolute", diff --git a/Client/src/Pages/Monitors/Home/actionsMenu.jsx b/Client/src/Pages/Monitors/Home/actionsMenu.jsx index 11da8cbdf..d6e9da2ee 100644 --- a/Client/src/Pages/Monitors/Home/actionsMenu.jsx +++ b/Client/src/Pages/Monitors/Home/actionsMenu.jsx @@ -77,6 +77,9 @@ const ActionsMenu = ({ monitor, isAdmin }) => { "&:focus": { outline: "none", }, + "& svg path": { + stroke: theme.palette.other.icon, + }, }} > @@ -94,6 +97,7 @@ const ActionsMenu = ({ monitor, isAdmin }) => { borderColor: theme.palette.border.light, borderRadius: theme.shape.borderRadius, boxShadow: theme.shape.boxShadow, + backgroundColor: theme.palette.background.main, "& ul": { p: theme.spacing(2.5), minWidth: "100px", diff --git a/Client/src/Pages/Monitors/Home/index.jsx b/Client/src/Pages/Monitors/Home/index.jsx index f98ede024..8d7edbcc1 100644 --- a/Client/src/Pages/Monitors/Home/index.jsx +++ b/Client/src/Pages/Monitors/Home/index.jsx @@ -145,7 +145,7 @@ const Monitors = ({ isAdmin }) => { color={theme.palette.text.primary} border={1} borderColor={theme.palette.border.light} - backgroundColor={theme.palette.unresolved.bg} + backgroundColor={theme.palette.background.accent} > {monitorState.monitors.length} diff --git a/Client/src/Pages/Monitors/Home/monitorData.jsx b/Client/src/Pages/Monitors/Home/monitorData.jsx index ae3cc4e30..c82a1fa95 100644 --- a/Client/src/Pages/Monitors/Home/monitorData.jsx +++ b/Client/src/Pages/Monitors/Home/monitorData.jsx @@ -4,6 +4,7 @@ import BarChart from "../../../Components/Charts/BarChart"; import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded"; import { StatusLabel } from "../../../Components/Label"; import { Box } from "@mui/material"; +import { useTheme } from "@emotion/react"; const data = { cols: [ @@ -27,13 +28,17 @@ const data = { }; export const buildData = (monitors, isAdmin, navigate) => { + const theme = useTheme(); + data.rows = monitors.map((monitor, idx) => { const params = { url: monitor.url, title: monitor.name, percentage: 100, percentageColor: - monitor.status === true ? "var(--success-color)" : "var(--error-color)", + monitor.status === true + ? theme.palette.success.main + : theme.palette.error.text, status: monitor.status === true ? "up" : "down", }; diff --git a/Client/src/Utils/Theme.js b/Client/src/Utils/Theme.js index 4f8ede4d0..0122847ce 100644 --- a/Client/src/Utils/Theme.js +++ b/Client/src/Utils/Theme.js @@ -53,7 +53,10 @@ const theme = createTheme({ border: "#fec84b", }, unresolved: { main: "#4e5ba6", light: "#e2eaf7", bg: "#f2f4f7" }, - other: {}, + other: { + icon: "#667085", + line: "#d6d9dd" + }, primary: { main: "#1570EF", }, @@ -73,4 +76,72 @@ const theme = createTheme({ }, }); +export const darkTheme = createTheme({ + typography: { fontFamily: fontFamilyDefault, fontSize: 13 }, + palette: { + common: { main: "#1570ef" }, + text: { + primary: "#fafafa", + secondary: "#e6e6e6", + tertiary: "#a1a1aa", + accent: "#e6e6e6", + }, + background: { + main: "#151518", + alt: "#09090b", + fill: "#2e2e2e", + accent: "#18181a", + }, + border: { light: "#27272a", dark: "#2c2c2c" }, + info: { + text: "#475467", + main: "#475467", + bg: "#ffffff", + light: "#ffffff", + border: "#D0D5DD", + }, + success: { + text: "#079455", + main: "#45bb7a", + light: "#93d5aa", + bg: "#27272a", + }, + error: { + text: "#f04438", + main: "#d32f2f", + light: "#f04438", + bg: "#27272a", + border: "#f04438", + }, + warning: { + text: "#DC6803", + main: "#e88c30", + light: "#fffcf5", + bg: "#ffecbc", + border: "#fec84b", + }, + unresolved: { main: "#4e5ba6", light: "#e2eaf7", bg: "#f2f4f7" }, + other: { + icon: "#e6e6e6", + line: "#27272a" + }, + primary: { + main: "#1570ef", + }, + secondary: { + main: "#e6e6e6", + }, + tertiary: { + main: "#e6e6e6", + }, + }, + spacing: 2, + components: {}, + shape: { + borderRadius: 2, + borderThick: 2, + boxShadow: shadow, + }, +}); + export default theme; diff --git a/Client/src/assets/icons/dots-vertical.svg b/Client/src/assets/icons/dots-vertical.svg new file mode 100644 index 000000000..e720066c4 --- /dev/null +++ b/Client/src/assets/icons/dots-vertical.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Client/src/main.jsx b/Client/src/main.jsx index 00cec7d14..d592f9137 100644 --- a/Client/src/main.jsx +++ b/Client/src/main.jsx @@ -3,8 +3,6 @@ import ReactDOM from "react-dom/client"; import App from "./App.jsx"; import "./index.css"; import { BrowserRouter as Router, HashRouter } from "react-router-dom"; -import theme from "./Utils/Theme.js"; -import { ThemeProvider } from "@mui/material"; import { Provider } from "react-redux"; import { persistor, store } from "./store"; import { PersistGate } from "redux-persist/integration/react"; @@ -13,11 +11,9 @@ export const networkService = new NetworkService(store); ReactDOM.createRoot(document.getElementById("root")).render( - - - - - + + + );