diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f0b762f9..ee6a76da0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ All notable, unreleased changes to this project will be documented in this file. - Add lazyload to locales - #692 by @eaglesemanation - Fix not closed address update modal with two confirmations - #699 by @orzechdev - Update schema with PositiveDecimal type - #695 by @AlicjaSzu +- Restyle side menu - #697 by @dominik-zeglen ## 2.10.1 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/assets/images/menu-apps-icon.svg b/assets/images/menu-apps-icon.svg index 3033691d1..85d36954a 100644 --- a/assets/images/menu-apps-icon.svg +++ b/assets/images/menu-apps-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-catalog-icon.svg b/assets/images/menu-catalog-icon.svg index 6b67b5aac..159804b6d 100644 --- a/assets/images/menu-catalog-icon.svg +++ b/assets/images/menu-catalog-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-configure-icon.svg b/assets/images/menu-configure-icon.svg index c1defe727..7a435af97 100644 --- a/assets/images/menu-configure-icon.svg +++ b/assets/images/menu-configure-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-customers-icon.svg b/assets/images/menu-customers-icon.svg index b46a2fc1e..989bc7b0d 100644 --- a/assets/images/menu-customers-icon.svg +++ b/assets/images/menu-customers-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-discounts-icon.svg b/assets/images/menu-discounts-icon.svg index 6f15dce79..30ca87a8e 100644 --- a/assets/images/menu-discounts-icon.svg +++ b/assets/images/menu-discounts-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-home-icon.svg b/assets/images/menu-home-icon.svg index f91bd00a1..2c90eedf3 100644 --- a/assets/images/menu-home-icon.svg +++ b/assets/images/menu-home-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-orders-icon.svg b/assets/images/menu-orders-icon.svg index 1e97d098d..74603fe7a 100644 --- a/assets/images/menu-orders-icon.svg +++ b/assets/images/menu-orders-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/images/menu-translation-icon.svg b/assets/images/menu-translation-icon.svg index 7d034dd68..e869dedd1 100644 --- a/assets/images/menu-translation-icon.svg +++ b/assets/images/menu-translation-icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/cypress/elements/account/left-menu/left-menu-selectors.js b/cypress/elements/account/left-menu/left-menu-selectors.js index 453e686ca..fb525ee06 100644 --- a/cypress/elements/account/left-menu/left-menu-selectors.js +++ b/cypress/elements/account/left-menu/left-menu-selectors.js @@ -1,4 +1,4 @@ /* eslint-disable sort-keys */ export const LEFT_MENU_SELECTORS = { - catalog: "[data-testid='catalogue']" + catalog: "[data-test-id='catalogue']" }; diff --git a/cypress/elements/catalog/product-selectors.js b/cypress/elements/catalog/product-selectors.js index aae2d0b9f..6e9c992aa 100644 --- a/cypress/elements/catalog/product-selectors.js +++ b/cypress/elements/catalog/product-selectors.js @@ -1,6 +1,6 @@ /* eslint-disable sort-keys */ export const PRODUCTS_SELECTORS = { - products: "[href='/dashboard/products?']", + products: "[data-test='submenu-item-label'][data-test-id='products']", createProductBtn: "[data-test='add-product']", productNameInput: "[name='name']", productTypeInput: "[data-test='product-type']", diff --git a/cypress/integration/warehouse.js b/cypress/integration/warehouse.js index 7ed06c295..208321164 100644 --- a/cypress/integration/warehouse.js +++ b/cypress/integration/warehouse.js @@ -7,7 +7,7 @@ describe("Warehouse settings", () => { xit("Warehouse section visible in the configuration", () => { cy.visit("/configuration/") .loginUser() - .get("[data-testid=warehouses][data-test=settingsSubsection]") + .get("[data-test-id=warehouses][data-test=settingsSubsection]") .click(); cy.location("pathname").should("eq", "/warehouses/"); }); diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index 7ec4f91d5..88ea9ae01 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -2719,7 +2719,7 @@ }, "src_dot_home": { "context": "home section name", - "string": "Home" + "string": "Dashboard" }, "src_dot_home_dot_components_dot_HomeActivityCard_dot_draft": { "string": "Order #{orderId} was placed from draft by {userEmail}" diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx index bbfbf4475..2f6041ee2 100644 --- a/src/components/AppLayout/AppLayout.tsx +++ b/src/components/AppLayout/AppLayout.tsx @@ -1,11 +1,7 @@ -import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg"; -import saleorDarkLogo from "@assets/images/logo-dark.svg"; -import menuArrowIcon from "@assets/images/menu-arrow-icon.svg"; import Avatar from "@material-ui/core/Avatar"; import Chip from "@material-ui/core/Chip"; import ClickAwayListener from "@material-ui/core/ClickAwayListener"; import Grow from "@material-ui/core/Grow"; -import Hidden from "@material-ui/core/Hidden"; import LinearProgress from "@material-ui/core/LinearProgress"; import MenuItem from "@material-ui/core/MenuItem"; import Menu from "@material-ui/core/MenuList"; @@ -14,7 +10,6 @@ import Popper from "@material-ui/core/Popper"; import { makeStyles } from "@material-ui/core/styles"; import { createConfigurationMenu } from "@saleor/configuration"; import useAppState from "@saleor/hooks/useAppState"; -import useLocalStorage from "@saleor/hooks/useLocalStorage"; import useNavigator from "@saleor/hooks/useNavigator"; import useTheme from "@saleor/hooks/useTheme"; import useUser from "@saleor/hooks/useUser"; @@ -22,7 +17,6 @@ import ArrowDropdown from "@saleor/icons/ArrowDropdown"; import { staffMemberDetailsUrl } from "@saleor/staff/urls"; import classNames from "classnames"; import React from "react"; -import SVG from "react-inlinesvg"; import { FormattedMessage, useIntl } from "react-intl"; import useRouter from "use-react-router"; @@ -30,12 +24,11 @@ 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"; -import MenuList from "./MenuList"; +import { appLoaderHeight } from "./consts"; import createMenuStructure from "./menuStructure"; -import ResponsiveDrawer from "./ResponsiveDrawer"; import ThemeSwitch from "./ThemeSwitch"; const useStyles = makeStyles( @@ -52,12 +45,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 +63,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,136 +80,11 @@ 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", padding: "25px 20px" }, - menuIcon: { - "& span": { - "&:nth-child(1)": { - top: 15 - }, - "&:nth-child(2), &:nth-child(3)": { - top: 20 - }, - "&:nth-child(4)": { - top: 25 - }, - background: theme.palette.secondary.light, - display: "block", - height: 1, - left: "20%", - opacity: 1, - position: "absolute", - transform: "rotate(0deg)", - transition: ".25s ease-in-out", - width: "60%" - }, - [theme.breakpoints.up("md")]: { - display: "none" - }, - [theme.breakpoints.down("sm")]: { - left: 0 - }, - background: theme.palette.background.paper, - borderRadius: "50%", - cursor: "pointer", - height: 42, - left: theme.spacing(), - marginRight: theme.spacing(2), - position: "relative", - transform: "rotate(0deg)", - transition: `${theme.transitions.duration.shorter}ms ease-in-out`, - width: 42 - }, - menuIconDark: { - "& span": { - background: theme.palette.common.white - } - }, - menuIconOpen: { - "& span": { - "&:nth-child(1), &:nth-child(4)": { - left: "50%", - top: 20, - width: 0 - }, - "&:nth-child(2)": { - transform: "rotate(45deg)" - }, - "&:nth-child(3)": { - transform: "rotate(-45deg)" - } - }, - left: 280, - position: "absolute", - zIndex: 1999 - }, menuSmall: { background: theme.palette.background.paper, height: "100vh", @@ -238,18 +95,12 @@ const useStyles = makeStyles( zIndex: 1 }, root: { + display: "flex", width: `100%` }, rotate: { transform: "rotate(180deg)" }, - sideBar: { - [theme.breakpoints.down("sm")]: { - padding: 0 - }, - background: theme.palette.background.paper, - padding: `0 ${theme.spacing(4)}px` - }, spacer: { flex: 1 }, @@ -276,7 +127,6 @@ const useStyles = makeStyles( textAlign: "right" }, view: { - backgroundColor: theme.palette.background.default, flex: 1, flexGrow: 1, marginLeft: 0, @@ -286,7 +136,7 @@ const useStyles = makeStyles( } }, viewContainer: { - minHeight: `calc(100vh - ${theme.spacing(2) + appLoaderHeight + 70}px)` + minHeight: `calc(100vh - ${theme.spacing(4) + appLoaderHeight + 120}px)` } }), { @@ -301,8 +151,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(); const appHeaderAnchor = React.useRef(); @@ -337,17 +185,6 @@ const AppLayout: React.FC = ({ children }) => { navigate(staffMemberDetailsUrl(user.id)); }; - const handleMenuItemClick = (url: string, event: React.MouseEvent) => { - event.stopPropagation(); - event.preventDefault(); - setDrawerState(false); - navigate(url); - }; - - const handleIsMenuSmall = () => { - setMenuSmall(!isMenuSmall); - }; - const handleErrorBack = () => { navigate("/"); dispatchAppState({ @@ -367,49 +204,14 @@ const AppLayout: React.FC = ({ children }) => {
-
- setDrawerState(false)} - open={isDrawerOpened} - small={!isMenuSmall} - > -
- -
- -
- -
-
- -
-
-
+ +
{appState.loading ? ( ) : ( @@ -419,18 +221,6 @@ const AppLayout: React.FC = ({ children }) => {
-
setDrawerState(!isDrawerOpened)} - > - - - - -
diff --git a/src/components/AppLayout/MenuList.tsx b/src/components/AppLayout/MenuList.tsx deleted file mode 100644 index 05f6fa971..000000000 --- a/src/components/AppLayout/MenuList.tsx +++ /dev/null @@ -1,369 +0,0 @@ -import configureIcon from "@assets/images/menu-configure-icon.svg"; -import { makeStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography"; -import { User } from "@saleor/fragments/types/User"; -import useTheme from "@saleor/hooks/useTheme"; -import { sectionNames } from "@saleor/intl"; -import classNames from "classnames"; -import React from "react"; -import SVG from "react-inlinesvg"; -import { FormattedMessage, useIntl } from "react-intl"; -import { matchPath } from "react-router"; - -import { - configurationMenuUrl, - createConfigurationMenu -} from "../../configuration"; -import { createHref } from "../../misc"; -import { orderDraftListUrl, orderListUrl } from "../../orders/urls"; -import MenuNested from "./MenuNested"; -import { IMenuItem } from "./menuStructure"; - -const useStyles = makeStyles( - theme => ({ - menuIcon: { - "& svg": { - height: 32, - width: 32 - }, - display: "inline-block", - position: "relative", - top: 8 - }, - menuIconDark: { - "& path": { - fill: theme.palette.common.white - } - }, - menuIconSmall: { - left: -5 - }, - menuIsActive: { - boxShadow: "0px 0px 12px 1px rgba(0,0,0,0.2)" - }, - menuItemHover: { - "& p": { - fontSize: 14, - transition: "color 0.5s ease, opacity 0.3s ease-out" - }, - "& path": { - transition: "fill 0.5s ease" - }, - "&:hover": { - "& p": { - color: theme.palette.primary.main - }, - "& path": { - fill: theme.palette.primary.main - }, - "&:before": { - borderLeft: `solid 2px ${theme.palette.primary.main}`, - content: "''", - height: 33, - left: -20, - position: "absolute", - top: 8 - }, - color: theme.palette.primary.main - }, - cursor: "pointer", - position: "relative" - }, - menuList: { - display: "flex", - flexDirection: "column", - height: "100%", - marginLeft: theme.spacing(4), - marginTop: theme.spacing(2), - paddingBottom: theme.spacing(3) - }, - menuListItem: { - alignItems: "center", - display: "block", - marginBottom: theme.spacing(5), - paddingLeft: 0, - textDecoration: "none", - transition: theme.transitions.duration.standard + "ms" - }, - menuListItemActive: { - "& $menuListItemText": { - color: theme.palette.primary.main - }, - "& path": { - color: theme.palette.primary.main, - fill: theme.palette.primary.main - } - }, - menuListItemOpen: { - "&:after": { - borderBottom: `10px solid transparent`, - borderLeft: `10px solid ${theme.palette.background.paper}`, - borderTop: `10px solid transparent`, - content: "''", - height: 0, - position: "absolute", - right: -30, - top: 15, - width: 0 - }, - "&:before": { - borderLeft: `solid 2px ${theme.palette.primary.main}`, - content: "''", - height: 33, - left: -20, - position: "absolute", - top: 8 - }, - position: "relative" - }, - menuListItemText: { - "&:hover": { - color: theme.palette.primary.main - }, - bottom: 0, - cursor: "pointer", - fontSize: "1rem", - fontWeight: 500, - left: 30, - opacity: 1, - paddingLeft: 16, - position: "absolute", - textTransform: "uppercase", - transition: "opacity 0.5s ease" - }, - menuListItemTextHide: { - bottom: 0, - left: 30, - opacity: 0, - position: "absolute" - }, - subMenu: { - padding: "0 15px" - }, - subMenuDrawer: { - background: "#000", - cursor: "pointer", - height: "100vh", - left: 0, - opacity: 0.2, - position: "absolute", - top: 0, - width: 0, - zIndex: -2 - }, - subMenuDrawerOpen: { - width: `100vw` - } - }), - { name: "MenuList" } -); - -interface MenuListProps { - className?: string; - menuItems: IMenuItem[]; - isMenuSmall: boolean; - location: string; - user: User; - renderConfigure: boolean; - onMenuItemClick: (url: string, event: React.MouseEvent) => void; -} - -export interface IActiveSubMenu { - isActive: boolean; - label: string | null; -} - -const MenuList: React.FC = props => { - const { - className, - menuItems, - isMenuSmall, - location, - user, - renderConfigure, - onMenuItemClick - } = props; - - const classes = useStyles(props); - - const { isDark } = useTheme(); - const [activeSubMenu, setActiveSubMenu] = React.useState({ - isActive: false, - label: null - }); - const intl = useIntl(); - - const configurationMenu = createConfigurationMenu(intl).map(menu => { - menu.menuItems.map(item => - user.userPermissions.map(perm => perm.code).includes(item.permission) - ); - }); - - const handleSubMenu = itemLabel => { - setActiveSubMenu({ - isActive: - itemLabel === activeSubMenu.label ? !activeSubMenu.isActive : true, - label: itemLabel - }); - }; - - const closeSubMenu = (menuItemUrl, event) => { - setActiveSubMenu({ - isActive: false, - label: null - }); - if (menuItemUrl && event) { - onMenuItemClick(menuItemUrl, event); - event.stopPropagation(); - event.preventDefault(); - } - }; - - return ( -
- {/* FIXME: this .split("?")[0] looks gross */} - {menuItems.map(menuItem => { - const isActive = (menuItem: IMenuItem) => - 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] - }); - - if ( - menuItem.permission && - !user.userPermissions - .map(perm => perm.code) - .includes(menuItem.permission) - ) { - return null; - } - - if (!menuItem.url) { - const isAnyChildActive = menuItem.children.reduce( - (acc, child) => acc || isActive(child), - false - ); - - return ( -
-
handleSubMenu(menuItem.ariaLabel)} - > - - - {menuItem.label} - -
- -
closeSubMenu(null, event)} - className={classNames(classes.subMenuDrawer, { - [classes.subMenuDrawerOpen]: activeSubMenu.isActive - })} - /> -
- ); - } - - return ( - closeSubMenu(menuItem.url, event)} - key={menuItem.label} - data-testid={menuItem.testingContextId} - data-test="menuItemEntry" - > -
- - - {menuItem.label} - -
-
- ); - })} - {renderConfigure && configurationMenu.length > 0 && ( - closeSubMenu(configurationMenuUrl, event)} - > -
- - - - -
-
- )} -
- ); -}; - -MenuList.displayName = "MenuList"; -export default MenuList; diff --git a/src/components/AppLayout/MenuNested.tsx b/src/components/AppLayout/MenuNested.tsx deleted file mode 100644 index 0a64b1892..000000000 --- a/src/components/AppLayout/MenuNested.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import menuArrowIcon from "@assets/images/menu-arrow-icon.svg"; -import Hidden from "@material-ui/core/Hidden"; -import { makeStyles } from "@material-ui/core/styles"; -import Typography from "@material-ui/core/Typography"; -import useTheme from "@saleor/hooks/useTheme"; -import { createHref } from "@saleor/misc"; -import classNames from "classnames"; -import React from "react"; -import SVG from "react-inlinesvg"; - -import { drawerNestedMenuWidth, drawerWidthExpandedMobile } from "./consts"; -import { IActiveSubMenu } from "./MenuList"; -import { IMenuItem } from "./menuStructure"; - -const useStyles = makeStyles( - theme => ({ - menuListNested: { - background: theme.palette.background.paper, - height: "100vh", - position: "absolute", - right: 0, - top: 0, - transition: `right ${theme.transitions.duration.shorter}ms ease`, - width: drawerNestedMenuWidth, - zIndex: -1 - }, - menuListNestedClose: { - "& svg": { - fill: theme.palette.primary.main, - left: 11, - position: "relative", - top: 1 - }, - border: `solid 1px #EAEAEA`, - borderRadius: "100%", - cursor: "pointer", - height: 32, - position: "absolute", - right: 32, - top: 35, - transform: "rotate(180deg)", - width: 32 - }, - menuListNestedCloseDark: { - border: `solid 1px #252728` - }, - menuListNestedHide: { - opacity: 0 - }, - menuListNestedIcon: { - "& path": { - fill: "initial" - }, - "& svg": { height: 32, position: "relative", top: 7, width: 32 } - }, - menuListNestedIconDark: { - "& path": { - fill: theme.palette.common.white - } - }, - menuListNestedItem: { - "&:hover": { - "& p": { - color: theme.palette.primary.main - } - }, - display: "block", - marginBottom: theme.spacing(2), - padding: "0px 30px", - textDecoration: "none" - }, - menuListNestedOpen: { - [theme.breakpoints.down("sm")]: { - right: 0, - width: drawerWidthExpandedMobile, - zIndex: 2 - }, - right: -drawerNestedMenuWidth, - width: drawerNestedMenuWidth, - zIndex: -1 - }, - subHeader: { - borderBottom: "solid 1px #EAEAEA", - margin: "30px", - marginBottom: 39, - paddingBottom: 22 - }, - subHeaderDark: { - borderBottom: "solid 1px #252728" - }, - subHeaderTitle: { - [theme.breakpoints.up("md")]: { - paddingLeft: 0 - }, - display: "inline", - paddingLeft: 10 - } - }), - { name: "MenuNested" } -); - -export interface MenuNestedProps { - activeItem: IActiveSubMenu; - ariaLabel: string; - closeSubMenu: ({ isActive, label }: IActiveSubMenu) => void; - icon: string; - menuItem: IMenuItem; - title: string; - handleSubMenu: (itemLabel: string) => void; - onMenuItemClick: (url: string, event: React.MouseEvent) => void; -} - -const MenuNested: React.FC = props => { - const { - activeItem, - ariaLabel, - - closeSubMenu, - icon, - menuItem, - onMenuItemClick, - title - } = props; - const classes = useStyles(props); - - const menuItems = menuItem.children; - const { isDark } = useTheme(); - const closeMenu = (menuItemUrl, event) => { - onMenuItemClick(menuItemUrl, event); - closeSubMenu({ - isActive: false, - label: null - }); - event.stopPropagation(); - event.preventDefault(); - }; - return ( - <> -
- - - - -
{title}
- -
- closeSubMenu({ - isActive: false, - label: null - }) - } - > - -
-
-
- {menuItems.map(item => ( - closeMenu(item.url, event)} - key={item.label} - > - {item.label} - - ))} -
- - ); -}; - -MenuNested.displayName = "MenuNested"; -export default MenuNested; diff --git a/src/components/AppLayout/ResponsiveDrawer.tsx b/src/components/AppLayout/ResponsiveDrawer.tsx deleted file mode 100644 index 49baa1e7f..000000000 --- a/src/components/AppLayout/ResponsiveDrawer.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import Drawer from "@material-ui/core/Drawer"; -import Hidden from "@material-ui/core/Hidden"; -import { makeStyles } from "@material-ui/core/styles"; -import React from "react"; - -import { - drawerWidth, - drawerWidthExpanded, - drawerWidthExpandedMobile -} from "./consts"; - -const useStyles = makeStyles( - theme => ({ - drawerDesktop: { - backgroundColor: theme.palette.background.paper, - border: "none", - height: "100vh", - overflow: "visible", - padding: 0, - position: "fixed" as "fixed", - transition: "width 0.3s ease", - width: drawerWidthExpanded - }, - drawerDesktopSmall: { - overflow: "visible", - transition: "width 0.2s ease", - width: drawerWidth - }, - drawerMobile: { - width: drawerWidthExpandedMobile - } - }), - { name: "ResponsiveDrawer" } -); - -interface ResponsiveDrawerProps { - children?: React.ReactNode; - open: boolean; - small: boolean; - onClose?(); -} - -const ResponsiveDrawer: React.FC = props => { - const { children, onClose, open, small } = props; - - const classes = useStyles(props); - - return ( - <> - - - {children} - - - - - {children} - - - - ); -}; -export default ResponsiveDrawer; diff --git a/src/components/SaveButtonBar/SaveButtonBar.tsx b/src/components/SaveButtonBar/SaveButtonBar.tsx index adf2bdcdb..b7a5b6cf0 100644 --- a/src/components/SaveButtonBar/SaveButtonBar.tsx +++ b/src/components/SaveButtonBar/SaveButtonBar.tsx @@ -5,6 +5,7 @@ import Portal from "@material-ui/core/Portal"; import { makeStyles } from "@material-ui/core/styles"; import useWindowScroll from "@saleor/hooks/useWindowScroll"; import { buttonMessages } from "@saleor/intl"; +import classNames from "classnames"; import React from "react"; import { useIntl } from "react-intl"; @@ -17,12 +18,21 @@ import Container from "../Container"; const useStyles = makeStyles( theme => ({ + applyShadow: { + "&$card": { + boxShadow: "0px 6px 30px rgba(0, 0, 0, 0.16)" + } + }, button: { marginRight: theme.spacing(1) }, cancelButton: { marginRight: theme.spacing(2) }, + card: { + boxShadow: "0px 0px 0px rgba(0, 0, 0, 0.16)", + transition: theme.transitions.duration.shortest + "ms" + }, content: { "&:last-child": { paddingBottom: theme.spacing(2) @@ -79,7 +89,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 ( @@ -88,7 +98,11 @@ export const SaveButtonBar: React.FC = props => {
- + {!!onDelete && ( + {menuItem.children && ( + + setOpen(false)}> + + {menuItem.children.map(subMenuItem => ( + handleClick(event, subMenuItem)} + data-test="submenu-item-label" + data-test-id={subMenuItem.testingContextId} + variant="body2" + > + {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..04570317e --- /dev/null +++ b/src/components/SideBar/SideBar.tsx @@ -0,0 +1,131 @@ +import logoLight from "@assets/images/logo-sidebar-light.svg"; +import configurationIcon from "@assets/images/menu-configure-icon.svg"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { configurationMenuUrl } from "@saleor/configuration"; +import { User } from "@saleor/fragments/types/User"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +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 ExpandButton from "./ExpandButton"; +import MenuItem, { menuWidth, shrunkMenuWidth } from "./MenuItem"; +import { isMenuActive } from "./utils"; + +const useStyles = makeStyles( + theme => ({ + expandButton: { + marginLeft: theme.spacing(2) + }, + float: { + position: "fixed" + }, + logo: { + margin: `36px 0 ${theme.spacing(3)}px ${theme.spacing(3)}px` + }, + root: { + transition: "width 0.5s ease", + width: menuWidth, + zIndex: 100 + }, + rootShrink: { + width: shrunkMenuWidth + } + }), + { + name: "SideBar" + } +); + +export interface SideBarProps { + className?: string; + menuItems: IMenuItem[]; + location: string; + user: User; + renderConfigure: boolean; + onMenuItemClick: UseNavigatorResult; +} + +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 && ( + acc || isMenuActive(location, menuItem), + false + ) + } + isMenuShrunk={isShrunk} + menuItem={{ + ariaLabel: "configure", + icon: configurationIcon, + label: intl.formatMessage(sectionNames.configuration), + testingContextId: "configure", + url: configurationMenuUrl + }} + onClick={onMenuItemClick} + /> + )} + setShrink(!isShrunk)} + /> +
+
+ ); +}; + +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..06827a7ac --- /dev/null +++ b/src/components/SideBar/utils.ts @@ -0,0 +1,24 @@ +import { orderDraftListUrl, orderListUrl } from "@saleor/orders/urls"; +import { matchPath } from "react-router"; + +import { IMenuItem } from "../AppLayout/menuStructure"; + +export function isMenuActive(location: string, menuItem: IMenuItem) { + if (menuItem.children) { + return menuItem.children.reduce( + (acc, subMenuItem) => acc || isMenuActive(location, subMenuItem), + false + ); + } + + const activeUrl = location.split("?")[0]; + const menuItemUrl = menuItem.url.split("?")[0]; + + return activeUrl === orderDraftListUrl().split("?")[0] && + menuItemUrl === orderListUrl().split("?")[0] + ? false + : !!matchPath(activeUrl, { + exact: menuItemUrl === "/", + path: menuItemUrl + }); +} diff --git a/src/configuration/ConfigurationPage.tsx b/src/configuration/ConfigurationPage.tsx index 502b9568c..271a08eca 100644 --- a/src/configuration/ConfigurationPage.tsx +++ b/src/configuration/ConfigurationPage.tsx @@ -127,7 +127,7 @@ export const ConfigurationPage: React.FC = props => { onClick={() => onSectionClick(item.url)} key={itemIndex} data-test="settingsSubsection" - data-testid={item.title.toLowerCase()} + data-test-id={item.title.toLowerCase()} >
{item.icon}
diff --git a/src/intl.ts b/src/intl.ts index 1b8042ec8..fa27aa818 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -196,7 +196,7 @@ export const sectionNames = defineMessages({ description: "draft orders section name" }, home: { - defaultMessage: "Home", + defaultMessage: "Dashboard", description: "home section name" }, navigation: { diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 1929499ea..126c0eb58 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -52831,7 +52831,7 @@ exports[`Storyshots Views / Configuration default 1`] = `
= props => { onClick={warehouse ? onRowClick(warehouse.id) : undefined} key={warehouse ? warehouse.id : "skeleton"} data-test="warehouseEntry" - data-testid={warehouse?.name.toLowerCase().replace(" ", "")} + data-test-id={warehouse?.name.toLowerCase().replace(" ", "")} > {maybe(() => warehouse.name, )}