diff --git a/assets/images/logo-sidebar-light.svg b/assets/images/logo-sidebar-light.svg new file mode 100644 index 000000000..6d186cce1 --- /dev/null +++ b/assets/images/logo-sidebar-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/logo-white.svg b/assets/images/logo-white.svg deleted file mode 100644 index d01d84844..000000000 --- a/assets/images/logo-white.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx index bbfbf4475..5dccbac04 100644 --- a/src/components/AppLayout/AppLayout.tsx +++ b/src/components/AppLayout/AppLayout.tsx @@ -30,6 +30,7 @@ import Container from "../Container"; import ErrorPage from "../ErrorPage"; import Navigator from "../Navigator"; import NavigatorButton from "../NavigatorButton/NavigatorButton"; +import SideBar from "../SideBar"; import AppActionContext from "./AppActionContext"; import AppHeaderContext from "./AppHeaderContext"; import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts"; @@ -52,12 +53,12 @@ const useStyles = makeStyles( }, appLoader: { height: appLoaderHeight, - marginBottom: theme.spacing(2), + marginBottom: theme.spacing(4), zIndex: 1201 }, appLoaderPlaceholder: { height: appLoaderHeight, - marginBottom: theme.spacing(2) + marginBottom: theme.spacing(4) }, arrow: { marginLeft: theme.spacing(2), @@ -70,18 +71,7 @@ const useStyles = makeStyles( } }, content: { - [theme.breakpoints.down("sm")]: { - paddingLeft: 0 - }, - paddingLeft: drawerWidthExpanded, - transition: "padding-left 0.5s ease", - width: "100%" - }, - contentToggle: { - [theme.breakpoints.down("sm")]: { - paddingLeft: 0 - }, - paddingLeft: drawerWidth + flex: 1 }, darkThemeSwitch: { [theme.breakpoints.down("sm")]: { @@ -98,70 +88,6 @@ const useStyles = makeStyles( height: 40, marginBottom: theme.spacing(3) }, - isMenuSmall: { - "& path": { - fill: theme.palette.primary.main - }, - "& span": { - margin: "0 8px" - }, - "& svg": { - marginTop: 8, - transform: "rotate(180deg)" - }, - "&:hover": { - background: "#E6F3F3" - }, - background: theme.palette.background.paper, - border: `solid 1px #EAEAEA`, - borderRadius: "50%", - cursor: "pointer", - height: 32, - position: "absolute", - right: -16, - top: 65, - transition: `background ${theme.transitions.duration.shorter}ms`, - width: 32, - zIndex: 99 - }, - isMenuSmallDark: { - "&:hover": { - background: `linear-gradient(0deg, rgba(25, 195, 190, 0.1), rgba(25, 195, 190, 0.1)), ${theme.palette.background.paper}` - }, - border: `solid 1px #252728`, - transition: `background ${theme.transitions.duration.shorter}ms` - }, - isMenuSmallHide: { - "& svg": { - marginLeft: "3px", - transform: "rotate(0deg)" - } - }, - logo: { - "& svg": { - left: "50%", - position: "absolute", - top: "50%", - transform: "translate(-50%,-50%)" - }, - background: theme.palette.secondary.main, - display: "block", - height: 80, - position: "relative" - }, - logoDark: { - "& path": { - fill: theme.palette.common.white - }, - background: theme.palette.primary.main - }, - logoSmall: { - "& svg": { - margin: 0, - padding: 0, - width: "80px" - } - }, menu: { background: theme.palette.background.paper, height: "100vh", @@ -238,6 +164,7 @@ const useStyles = makeStyles( zIndex: 1 }, root: { + display: "flex", width: `100%` }, rotate: { @@ -286,7 +213,7 @@ const useStyles = makeStyles( } }, viewContainer: { - minHeight: `calc(100vh - ${theme.spacing(2) + appLoaderHeight + 70}px)` + minHeight: `calc(100vh - ${theme.spacing(4) + appLoaderHeight + 120}px)` } }), { @@ -301,7 +228,6 @@ interface AppLayoutProps { const AppLayout: React.FC = ({ children }) => { const classes = useStyles({}); const { isDark, toggleTheme } = useTheme(); - const [isMenuSmall, setMenuSmall] = useLocalStorage("isMenuSmall", false); const [isDrawerOpened, setDrawerState] = React.useState(false); const [isMenuOpened, setMenuState] = React.useState(false); const appActionAnchor = React.useRef(); @@ -344,10 +270,6 @@ const AppLayout: React.FC = ({ children }) => { navigate(url); }; - const handleIsMenuSmall = () => { - setMenuSmall(!isMenuSmall); - }; - const handleErrorBack = () => { navigate("/"); dispatchAppState({ @@ -367,7 +289,7 @@ const AppLayout: React.FC = ({ children }) => {
-
+ {/*
setDrawerState(false)} open={isDrawerOpened} @@ -404,12 +326,15 @@ const AppLayout: React.FC = ({ children }) => { onMenuItemClick={handleMenuItemClick} /> -
-
+
*/} + +
{appState.loading ? ( ) : ( diff --git a/src/components/SaveButtonBar/SaveButtonBar.tsx b/src/components/SaveButtonBar/SaveButtonBar.tsx index adf2bdcdb..681c75e73 100644 --- a/src/components/SaveButtonBar/SaveButtonBar.tsx +++ b/src/components/SaveButtonBar/SaveButtonBar.tsx @@ -79,7 +79,7 @@ export const SaveButtonBar: React.FC = props => { const intl = useIntl(); const scrollPosition = useWindowScroll(); const scrolledToBottom = - scrollPosition.y + window.innerHeight >= document.body.scrollHeight; + scrollPosition.y + window.innerHeight - document.body.scrollHeight >= -5; return ( diff --git a/src/components/SideBar/ExpandButton.tsx b/src/components/SideBar/ExpandButton.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/SideBar/MenuItem.tsx b/src/components/SideBar/MenuItem.tsx new file mode 100644 index 000000000..4d1b7454b --- /dev/null +++ b/src/components/SideBar/MenuItem.tsx @@ -0,0 +1,80 @@ +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import React from "react"; + +import { IMenuItem } from "../AppLayout/menuStructure"; + +export interface MenuItemProps { + menuItem: IMenuItem; + onClick: (url: string, event: React.MouseEvent) => void; +} + +const useStyles = makeStyles( + theme => ({ + paper: { + borderRadius: 16, + padding: theme.spacing(3) + }, + popper: { + marginLeft: theme.spacing(3), + zIndex: 2 + } + }), + { + name: "MenuItem" + } +); + +const MenuItem: React.FC = ({ menuItem, onClick }) => { + const classes = useStyles({}); + const [open, setOpen] = React.useState(false); + const anchor = React.useRef(null); + + const handleClick = (event: React.MouseEvent, menuItem: IMenuItem) => { + if (menuItem.children) { + setOpen(true); + } else { + onClick(menuItem.url, event); + setOpen(false); + } + }; + + return ( +
handleClick(event, menuItem)}> + {menuItem.label} + {menuItem.children && ( + + setOpen(false)} + mouseEvent="onClick" + > + + {menuItem.children.map(subMenuItem => ( +
handleClick(event, subMenuItem)} + data-test="select-option" + > + {subMenuItem.label} +
+ ))} +
+
+
+ )} +
+ ); +}; + +MenuItem.displayName = "MenuItem"; +export default MenuItem; diff --git a/src/components/SideBar/SideBar.tsx b/src/components/SideBar/SideBar.tsx new file mode 100644 index 000000000..32019b202 --- /dev/null +++ b/src/components/SideBar/SideBar.tsx @@ -0,0 +1,105 @@ +import logoLight from "@assets/images/logo-sidebar-light.svg"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { + configurationMenuUrl, + createConfigurationMenu +} from "@saleor/configuration"; +import { User } from "@saleor/fragments/types/User"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import { sectionNames } from "@saleor/intl"; +import classNames from "classnames"; +import React from "react"; +import SVG from "react-inlinesvg"; +import { useIntl } from "react-intl"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import MenuItem from "./MenuItem"; +import { isMenuActive } from "./utils"; + +const useStyles = makeStyles( + theme => ({ + logo: { + margin: "36px 0 0 19px" + }, + root: { + transition: "width 0.5s ease", + width: 210 + }, + shrunk: { + "&$root": { + width: 72 + } + } + }), + { + name: "SideBar" + } +); + +export interface SideBarProps { + className?: string; + menuItems: IMenuItem[]; + location: string; + user: User; + renderConfigure: boolean; + onMenuItemClick: (url: string, event: React.MouseEvent) => void; +} + +export interface IActiveSubMenu { + isActive: boolean; + label: string | null; +} + +const SideBar: React.FC = ({ + location, + menuItems, + renderConfigure, + user, + onMenuItemClick +}) => { + const classes = useStyles({}); + const [isShrunk, setShrink] = useLocalStorage("isMenuSmall", false); + const intl = useIntl(); + + return ( +
+
+ +
+ {menuItems.map(menuItem => { + // const isActive = isMenuActive(location, menuItem); + + if ( + menuItem.permission && + !user.userPermissions + .map(perm => perm.code) + .includes(menuItem.permission) + ) { + return null; + } + + return ; + })} + {renderConfigure && ( + + )} + +
+ ); +}; + +SideBar.displayName = "SideBar"; +export default SideBar; diff --git a/src/components/SideBar/SubMenu.tsx b/src/components/SideBar/SubMenu.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/SideBar/index.ts b/src/components/SideBar/index.ts new file mode 100644 index 000000000..df08bddc7 --- /dev/null +++ b/src/components/SideBar/index.ts @@ -0,0 +1,2 @@ +export * from "./SideBar"; +export { default } from "./SideBar"; diff --git a/src/components/SideBar/utils.ts b/src/components/SideBar/utils.ts new file mode 100644 index 000000000..bd894f877 --- /dev/null +++ b/src/components/SideBar/utils.ts @@ -0,0 +1,14 @@ +import { orderDraftListUrl, orderListUrl } from "@saleor/orders/urls"; +import { matchPath } from "react-router"; + +import { IMenuItem } from "../AppLayout/menuStructure"; + +export function isMenuActive(location: string, menuItem: IMenuItem) { + return location.split("?")[0] === orderDraftListUrl().split("?")[0] && + menuItem.url.split("?")[0] === orderListUrl().split("?")[0] + ? false + : !!matchPath(location.split("?")[0], { + exact: menuItem.url.split("?")[0] === "/", + path: menuItem.url.split("?")[0] + }); +}