Merge pull request #692 from bluewave-labs/feat/utils-slice

UI slice
This commit is contained in:
Alexander Holliday
2024-08-20 16:04:22 -07:00
committed by GitHub
10 changed files with 128 additions and 66 deletions

View File

@@ -148,7 +148,7 @@
height: 22px;
}
.MuiTablePagination-root svg path {
stroke: var(--env-var-color-5);
stroke: var(--env-var-color-2);
stroke-width: 1.3;
}
.MuiTablePagination-root .MuiSelect-icon {
@@ -175,7 +175,8 @@
padding: 4px;
min-width: 100px;
}
.pagination-dropdown li {
.pagination-dropdown li,
body:has(.pagination-dropdown) p:has(+ .MuiTablePagination-root) {
font-size: var(--env-var-font-size-medium);
color: var(--env-var-color-2);
padding: 4px;
@@ -185,3 +186,6 @@
.pagination-dropdown li.Mui-selected:hover {
background-color: #f4f4f4;
}
body:has(.pagination-dropdown) p:has(+ .MuiTablePagination-root) {
font-size: var(--env-var-font-size-small-plus);
}

View File

@@ -14,6 +14,9 @@ import {
Typography,
Stack,
} from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { useLocation, useParams } from "react-router-dom";
import { setRowsPerPage } from "../../Features/UI/uiSlice";
import LeftArrowDouble from "../../assets/icons/left-arrow-double.svg?react";
import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react";
import LeftArrow from "../../assets/icons/left-arrow.svg?react";
@@ -140,10 +143,14 @@ const TablePaginationActions = (props) => {
* <BasicTable data={data} rows={rows} paginated={true} />
*/
const BasicTable = ({ data, paginated, reversed, rows = 5 }) => {
const BasicTable = ({ data, paginated, reversed }) => {
const theme = useTheme();
const location = useLocation();
const dispatch = useDispatch();
const uiState = useSelector((state) => state.ui);
let table = location.pathname.split("/").pop();
let rowsPerPage = uiState[table].rowsPerPage;
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(rows);
useEffect(() => {
setPage(0);
@@ -154,7 +161,12 @@ const BasicTable = ({ data, paginated, reversed, rows = 5 }) => {
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
dispatch(
setRowsPerPage({
value: parseInt(event.target.value, 10),
table: table,
})
);
setPage(0);
};
@@ -211,50 +223,59 @@ const BasicTable = ({ data, paginated, reversed, rows = 5 }) => {
</TableBody>
</Table>
</TableContainer>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Typography sx={{ opacity: 0.7 }}>
Showing {getRange()} of {data.rows.length} monitor(s)
</Typography>
<TablePagination
component="div"
count={data.rows.length}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[5, 10, 15, 25]}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
labelRowsPerPage="Rows per page"
labelDisplayedRows={({ page, count }) =>
`Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}`
}
slotProps={{
select: {
MenuProps: {
keepMounted: true,
PaperProps: {
className: "pagination-dropdown",
{paginated && (
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
>
<Typography sx={{ opacity: 0.7 }}>
Showing {getRange()} of {data.rows.length} monitor(s)
</Typography>
<TablePagination
component="div"
count={data.rows.length}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[5, 10, 15, 25]}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
labelRowsPerPage="Rows per page"
labelDisplayedRows={({ page, count }) =>
`Page ${page + 1} of ${Math.max(
0,
Math.ceil(count / rowsPerPage)
)}`
}
slotProps={{
select: {
MenuProps: {
keepMounted: true,
PaperProps: {
className: "pagination-dropdown",
},
transformOrigin: { vertical: "bottom", horizontal: "left" },
anchorOrigin: { vertical: "top", horizontal: "left" },
sx: { mt: "-4px" },
},
transformOrigin: { vertical: "bottom", horizontal: "left" },
anchorOrigin: { vertical: "top", horizontal: "left" },
sx: { mt: "-4px" },
},
inputProps: { id: "pagination-dropdown" },
IconComponent: SelectorVertical,
sx: {
ml: theme.gap.small,
mr: theme.gap.large,
minWidth: theme.gap.xl,
textAlign: "left",
"&.Mui-focused > div": {
backgroundColor: theme.palette.otherColors.white,
inputProps: { id: "pagination-dropdown" },
IconComponent: SelectorVertical,
sx: {
ml: theme.gap.small,
mr: theme.gap.large,
minWidth: theme.gap.xl,
textAlign: "left",
"&.Mui-focused > div": {
backgroundColor: theme.palette.otherColors.white,
},
},
},
},
}}
sx={{ mt: theme.gap.medium }}
/>
</Stack>
}}
sx={{ mt: theme.gap.medium }}
/>
</Stack>
)}
</>
);
};

View File

@@ -58,7 +58,7 @@ aside
height: 100%;
width: 100%;
border-left: solid 1px var(--env-var-color-5);
opacity: 0.3;
opacity: 0.2;
}
aside
.MuiCollapse-wrapperInner
@@ -75,13 +75,13 @@ aside .MuiList-root .MuiListItemText-root + svg {
aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root::after {
content: "";
position: absolute;
left: -7px;
left: -8px;
top: 50%;
height: 1px;
width: 6px;
transform: translateY(-50%);
height: 3px;
width: 3px;
border-radius: 50%;
background-color: var(--env-var-color-5);
opacity: 0.3;
background-color: #d6d9dd;
}
aside {

View File

@@ -19,6 +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 { clearUptimeMonitorState } from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
import Avatar from "../Avatar";
import LockSvg from "../../assets/icons/lock.svg?react";
@@ -86,8 +87,9 @@ function Sidebar() {
const location = useLocation();
const dispatch = useDispatch();
const authState = useSelector((state) => state.auth);
const { sidebar } = useSelector((state) => state.ui);
let collapsed = sidebar.collapsed;
const [open, setOpen] = useState({ Dashboard: false, Account: false });
const [collapsed, setCollapsed] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const [popup, setPopup] = useState();
@@ -157,7 +159,7 @@ function Sidebar() {
borderColor: theme.palette.otherColors.graishWhite,
},
}}
onClick={() => setCollapsed(!collapsed)}
onClick={() => dispatch(toggleSidebar())}
>
{collapsed ? <ArrowRight /> : <ArrowLeft />}
</IconButton>
@@ -200,6 +202,7 @@ function Sidebar() {
],
},
}}
disableInteractive
>
<ListItemButton
className={
@@ -233,6 +236,7 @@ function Sidebar() {
],
},
}}
disableInteractive
>
<ListItemButton
className={
@@ -396,6 +400,7 @@ function Sidebar() {
],
},
}}
disableInteractive
>
<ListItemButton
className={
@@ -450,6 +455,7 @@ function Sidebar() {
],
},
}}
disableInteractive
>
<IconButton
onClick={(event) => openPopup(event, "logout")}

View File

@@ -322,13 +322,13 @@ const ProfilePanel = () => {
<Divider aria-hidden="true" />
<form className="delete-profile-form" noValidate spellCheck="false">
<div className="delete-profile-form__wrapper">
<Stack direction="column" gap="15px">
<Stack direction="column" gap="8px">
<Typography component="h1">Delete account</Typography>
<Typography component="p">
Note that deleting your account will remove all data from our
system. This is permanent and non-recoverable.
</Typography>
<Box sx={{ mt: theme.spacing(1) }}>
<Box sx={{ mt: theme.spacing(2) }}>
<Button
level="error"
label="Delete account"
@@ -399,7 +399,7 @@ const ProfilePanel = () => {
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
width: 450,
bgcolor: "white",
border: "solid 1px #f2f2f2",
borderRadius: `${theme.shape.borderRadius}px`,

View File

@@ -0,0 +1,31 @@
import { createSlice } from "@reduxjs/toolkit";
// Initial state for UI settings.
// Add more settings as needed (e.g., theme preferences, user settings)
const initialState = {
monitors: {
rowsPerPage: 5,
},
team: {
rowsPerPage: 5,
},
sidebar: {
collapsed: false,
},
};
const uiSlice = createSlice({
name: "ui",
initialState,
reducers: {
setRowsPerPage: (state, action) => {
state[action.payload.table].rowsPerPage = action.payload.value;
},
toggleSidebar: (state) => {
state.sidebar.collapsed = !state.sidebar.collapsed;
},
},
});
export default uiSlice.reducer;
export const { setRowsPerPage, toggleSidebar } = uiSlice.actions;

View File

@@ -1,14 +1,13 @@
import PropTypes from "prop-types";
import { useState } from "react";
import { useNavigate } from "react-router";
import { useSelector } from "react-redux";
import { Box, Tab, useTheme } from "@mui/material";
import TabContext from "@mui/lab/TabContext";
import TabList from "@mui/lab/TabList";
import "./index.css";
import ProfilePanel from "../../Components/TabPanels/Account/ProfilePanel";
import PasswordPanel from "../../Components/TabPanels/Account/PasswordPanel";
import TeamPanel from "../../Components/TabPanels/Account/TeamPanel";
import { useNavigate } from "react-router";
import { useSelector } from "react-redux";
import "./index.css";
/**
* Account component renders a settings page with tabs for Profile, Password, and Team settings.

View File

@@ -11,8 +11,6 @@
}
.monitors p.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
}
.monitors p.MuiTypography-root {
color: var(--env-var-color-5);
}
.monitors .MuiStack-root > button:not(.MuiIconButton-root) {

View File

@@ -376,7 +376,7 @@ const Monitors = () => {
let loading = monitorState.isLoading && monitorState.monitors.length === 0;
return (
<Stack className="monitors" pt={theme.gap.xl} gap={theme.gap.large}>
<Stack className="monitors" gap={theme.gap.large}>
{loading ? (
<SkeletonLayout />
) : (
@@ -395,10 +395,11 @@ const Monitors = () => {
{monitorState.monitors?.length !== 0 && (
<Button
level="primary"
label="Create new monitor"
label="Create monitor"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ fontWeight: 500 }}
/>
)}
</Stack>

View File

@@ -3,6 +3,7 @@ import { configureStore, combineReducers } from "@reduxjs/toolkit";
import uptimeMonitorsReducer from "./Features/UptimeMonitors/uptimeMonitorsSlice";
import pageSpeedMonitorReducer from "./Features/PageSpeedMonitor/pageSpeedMonitorSlice";
import authReducer from "./Features/Auth/authSlice";
import uiReducer from "./Features/UI/uiSlice";
import storage from "redux-persist/lib/storage";
import { persistReducer, persistStore, createTransform } from "redux-persist";
@@ -20,7 +21,7 @@ const authTransform = createTransform(
const persistConfig = {
key: "root",
storage,
whitielist: ["auth", "monitors", "pageSpeed"],
whitielist: ["auth", "monitors", "pageSpeed", "ui"],
transforms: [authTransform],
};
@@ -28,6 +29,7 @@ const rootReducer = combineReducers({
uptimeMonitors: uptimeMonitorsReducer,
auth: authReducer,
pageSpeedMonitors: pageSpeedMonitorReducer,
ui: uiReducer,
});
const persistedReducer = persistReducer(persistConfig, rootReducer);