Add navigator button
This commit is contained in:
parent
1eb3ec7b2d
commit
3816ebb0a5
3 changed files with 175 additions and 160 deletions
|
@ -28,6 +28,7 @@ import useRouter from "use-react-router";
|
|||
|
||||
import Container from "../Container";
|
||||
import ErrorPage from "../ErrorPage";
|
||||
import Navigator from "../Navigator";
|
||||
import AppActionContext from "./AppActionContext";
|
||||
import AppHeaderContext from "./AppHeaderContext";
|
||||
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
|
||||
|
@ -310,6 +311,7 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
|||
const intl = useIntl();
|
||||
const [appState, dispatchAppState] = useAppState();
|
||||
const { location } = useRouter();
|
||||
const [isNavigatorVisible, setNavigatorVisibility] = React.useState(false);
|
||||
|
||||
const menuStructure = createMenuStructure(intl);
|
||||
const configurationMenu = createConfigurationMenu(intl);
|
||||
|
@ -356,170 +358,181 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<AppHeaderContext.Provider value={appHeaderAnchor}>
|
||||
<AppActionContext.Provider value={appActionAnchor}>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.sideBar}>
|
||||
<ResponsiveDrawer
|
||||
onClose={() => setDrawerState(false)}
|
||||
open={isDrawerOpened}
|
||||
small={!isMenuSmall}
|
||||
>
|
||||
<div
|
||||
className={classNames(classes.logo, {
|
||||
[classes.logoSmall]: isMenuSmall,
|
||||
[classes.logoDark]: isDark
|
||||
})}
|
||||
<>
|
||||
<Navigator
|
||||
visible={isNavigatorVisible}
|
||||
setVisibility={setNavigatorVisibility}
|
||||
/>
|
||||
<AppHeaderContext.Provider value={appHeaderAnchor}>
|
||||
<AppActionContext.Provider value={appActionAnchor}>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.sideBar}>
|
||||
<ResponsiveDrawer
|
||||
onClose={() => setDrawerState(false)}
|
||||
open={isDrawerOpened}
|
||||
small={!isMenuSmall}
|
||||
>
|
||||
<SVG src={isMenuSmall ? saleorDarkLogoSmall : saleorDarkLogo} />
|
||||
</div>
|
||||
<Hidden smDown>
|
||||
<div
|
||||
className={classNames(classes.isMenuSmall, {
|
||||
[classes.isMenuSmallHide]: isMenuSmall,
|
||||
[classes.isMenuSmallDark]: isDark
|
||||
className={classNames(classes.logo, {
|
||||
[classes.logoSmall]: isMenuSmall,
|
||||
[classes.logoDark]: isDark
|
||||
})}
|
||||
onClick={handleIsMenuSmall}
|
||||
>
|
||||
<SVG src={menuArrowIcon} />
|
||||
<SVG
|
||||
src={isMenuSmall ? saleorDarkLogoSmall : saleorDarkLogo}
|
||||
/>
|
||||
</div>
|
||||
</Hidden>
|
||||
<MenuList
|
||||
className={isMenuSmall ? classes.menuSmall : classes.menu}
|
||||
menuItems={menuStructure}
|
||||
isMenuSmall={!isMenuSmall}
|
||||
location={location.pathname}
|
||||
user={user}
|
||||
renderConfigure={renderConfigure}
|
||||
onMenuItemClick={handleMenuItemClick}
|
||||
/>
|
||||
</ResponsiveDrawer>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(classes.content, {
|
||||
[classes.contentToggle]: isMenuSmall
|
||||
})}
|
||||
>
|
||||
{appState.loading ? (
|
||||
<LinearProgress className={classes.appLoader} color="primary" />
|
||||
) : (
|
||||
<div className={classes.appLoaderPlaceholder} />
|
||||
)}
|
||||
<div className={classes.viewContainer}>
|
||||
<div>
|
||||
<Container>
|
||||
<div className={classes.header}>
|
||||
<div
|
||||
className={classNames(classes.menuIcon, {
|
||||
[classes.menuIconOpen]: isDrawerOpened,
|
||||
[classes.menuIconDark]: isDark
|
||||
})}
|
||||
onClick={() => setDrawerState(!isDrawerOpened)}
|
||||
>
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
</div>
|
||||
<div ref={appHeaderAnchor} />
|
||||
<div className={classes.spacer} />
|
||||
<div className={classes.userBar}>
|
||||
<ThemeSwitch
|
||||
className={classes.darkThemeSwitch}
|
||||
checked={isDark}
|
||||
onClick={toggleTheme}
|
||||
/>
|
||||
<div className={classes.userMenuContainer} ref={anchor}>
|
||||
<Chip
|
||||
avatar={
|
||||
user.avatar && (
|
||||
<Avatar alt="user" src={user.avatar.url} />
|
||||
)
|
||||
}
|
||||
classes={{
|
||||
avatar: classes.avatar
|
||||
}}
|
||||
className={classes.userChip}
|
||||
label={
|
||||
<>
|
||||
{user.email}
|
||||
<ArrowDropdown
|
||||
className={classNames(classes.arrow, {
|
||||
[classes.rotate]: isMenuOpened
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
onClick={() => setMenuState(!isMenuOpened)}
|
||||
data-test="userMenu"
|
||||
<Hidden smDown>
|
||||
<div
|
||||
className={classNames(classes.isMenuSmall, {
|
||||
[classes.isMenuSmallHide]: isMenuSmall,
|
||||
[classes.isMenuSmallDark]: isDark
|
||||
})}
|
||||
onClick={handleIsMenuSmall}
|
||||
>
|
||||
<SVG src={menuArrowIcon} />
|
||||
</div>
|
||||
</Hidden>
|
||||
<MenuList
|
||||
className={isMenuSmall ? classes.menuSmall : classes.menu}
|
||||
menuItems={menuStructure}
|
||||
isMenuSmall={!isMenuSmall}
|
||||
location={location.pathname}
|
||||
user={user}
|
||||
renderConfigure={renderConfigure}
|
||||
onMenuItemClick={handleMenuItemClick}
|
||||
/>
|
||||
</ResponsiveDrawer>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(classes.content, {
|
||||
[classes.contentToggle]: isMenuSmall
|
||||
})}
|
||||
>
|
||||
{appState.loading ? (
|
||||
<LinearProgress className={classes.appLoader} color="primary" />
|
||||
) : (
|
||||
<div className={classes.appLoaderPlaceholder} />
|
||||
)}
|
||||
<div className={classes.viewContainer}>
|
||||
<div>
|
||||
<Container>
|
||||
<div className={classes.header}>
|
||||
<div
|
||||
className={classNames(classes.menuIcon, {
|
||||
[classes.menuIconOpen]: isDrawerOpened,
|
||||
[classes.menuIconDark]: isDark
|
||||
})}
|
||||
onClick={() => setDrawerState(!isDrawerOpened)}
|
||||
>
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
</div>
|
||||
<div ref={appHeaderAnchor} />
|
||||
<div className={classes.spacer} />
|
||||
<div className={classes.userBar}>
|
||||
<ThemeSwitch
|
||||
className={classes.darkThemeSwitch}
|
||||
checked={isDark}
|
||||
onClick={toggleTheme}
|
||||
/>
|
||||
<Popper
|
||||
className={classes.popover}
|
||||
open={isMenuOpened}
|
||||
anchorEl={anchor.current}
|
||||
transition
|
||||
placement="bottom-end"
|
||||
>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
style={{
|
||||
transformOrigin:
|
||||
placement === "bottom"
|
||||
? "right top"
|
||||
: "right bottom"
|
||||
}}
|
||||
>
|
||||
<Paper>
|
||||
<ClickAwayListener
|
||||
onClickAway={() => setMenuState(false)}
|
||||
mouseEvent="onClick"
|
||||
>
|
||||
<Menu>
|
||||
<MenuItem
|
||||
className={classes.userMenuItem}
|
||||
onClick={handleViewerProfile}
|
||||
data-test="accountSettingsButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Account Settings"
|
||||
description="button"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className={classes.userMenuItem}
|
||||
onClick={handleLogout}
|
||||
data-test="logOutButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Log out"
|
||||
description="button"
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
<button onClick={() => setNavigatorVisibility(true)}>
|
||||
naviigator
|
||||
</button>
|
||||
<div className={classes.userMenuContainer} ref={anchor}>
|
||||
<Chip
|
||||
avatar={
|
||||
user.avatar && (
|
||||
<Avatar alt="user" src={user.avatar.url} />
|
||||
)
|
||||
}
|
||||
classes={{
|
||||
avatar: classes.avatar
|
||||
}}
|
||||
className={classes.userChip}
|
||||
label={
|
||||
<>
|
||||
{user.email}
|
||||
<ArrowDropdown
|
||||
className={classNames(classes.arrow, {
|
||||
[classes.rotate]: isMenuOpened
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
onClick={() => setMenuState(!isMenuOpened)}
|
||||
data-test="userMenu"
|
||||
/>
|
||||
<Popper
|
||||
className={classes.popover}
|
||||
open={isMenuOpened}
|
||||
anchorEl={anchor.current}
|
||||
transition
|
||||
placement="bottom-end"
|
||||
>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
style={{
|
||||
transformOrigin:
|
||||
placement === "bottom"
|
||||
? "right top"
|
||||
: "right bottom"
|
||||
}}
|
||||
>
|
||||
<Paper>
|
||||
<ClickAwayListener
|
||||
onClickAway={() => setMenuState(false)}
|
||||
mouseEvent="onClick"
|
||||
>
|
||||
<Menu>
|
||||
<MenuItem
|
||||
className={classes.userMenuItem}
|
||||
onClick={handleViewerProfile}
|
||||
data-test="accountSettingsButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Account Settings"
|
||||
description="button"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className={classes.userMenuItem}
|
||||
onClick={handleLogout}
|
||||
data-test="logOutButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Log out"
|
||||
description="button"
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</Container>
|
||||
</div>
|
||||
<main className={classes.view}>
|
||||
{appState.error
|
||||
? appState.error === "unhandled" && (
|
||||
<ErrorPage onBack={handleErrorBack} />
|
||||
)
|
||||
: children}
|
||||
</main>
|
||||
</div>
|
||||
<main className={classes.view}>
|
||||
{appState.error
|
||||
? appState.error === "unhandled" && (
|
||||
<ErrorPage onBack={handleErrorBack} />
|
||||
)
|
||||
: children}
|
||||
</main>
|
||||
<div className={classes.appAction} ref={appActionAnchor} />
|
||||
</div>
|
||||
<div className={classes.appAction} ref={appActionAnchor} />
|
||||
</div>
|
||||
</div>
|
||||
</AppActionContext.Provider>
|
||||
</AppHeaderContext.Provider>
|
||||
</AppActionContext.Provider>
|
||||
</AppHeaderContext.Provider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -60,8 +60,12 @@ const useStyles = makeStyles(
|
|||
}
|
||||
);
|
||||
|
||||
const Navigator: React.FC = () => {
|
||||
const [visible, setVisible] = React.useState(false);
|
||||
export interface NavigatorProps {
|
||||
visible: boolean;
|
||||
setVisibility: (state: boolean) => void;
|
||||
}
|
||||
|
||||
const Navigator: React.FC<NavigatorProps> = ({ visible, setVisibility }) => {
|
||||
const input = React.useRef(null);
|
||||
const [query, mode, change, actions] = useQuickSearch(visible, input);
|
||||
const intl = useIntl();
|
||||
|
@ -76,7 +80,7 @@ const Navigator: React.FC = () => {
|
|||
React.useEffect(() => {
|
||||
hotkeys(navigatorHotkey, event => {
|
||||
event.preventDefault();
|
||||
setVisible(!visible);
|
||||
setVisibility(!visible);
|
||||
});
|
||||
|
||||
if (cmp(APP_VERSION, "2.1.0") !== 1 && !notifiedAboutNavigator) {
|
||||
|
@ -110,7 +114,7 @@ const Navigator: React.FC = () => {
|
|||
<Modal
|
||||
className={classes.modal}
|
||||
open={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
onClose={() => setVisibility(false)}
|
||||
>
|
||||
<Fade appear in={visible} timeout={theme.transitions.duration.short}>
|
||||
<div className={classes.root}>
|
||||
|
@ -122,7 +126,7 @@ const Navigator: React.FC = () => {
|
|||
onSelect={(item: QuickSearchAction) => {
|
||||
const shouldRemainVisible = item.onClick();
|
||||
if (!shouldRemainVisible) {
|
||||
setVisible(false);
|
||||
setVisibility(false);
|
||||
}
|
||||
}}
|
||||
onInputValueChange={value =>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import Navigator from "@saleor/components/Navigator";
|
||||
import useAppState from "@saleor/hooks/useAppState";
|
||||
import { defaultDataIdFromObject, InMemoryCache } from "apollo-cache-inmemory";
|
||||
import { ApolloClient } from "apollo-client";
|
||||
|
@ -139,7 +138,6 @@ const Routes: React.FC = () => {
|
|||
<WindowTitle title={intl.formatMessage(commonMessages.dashboard)} />
|
||||
{isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? (
|
||||
<AppLayout>
|
||||
<Navigator />
|
||||
<ErrorBoundary
|
||||
onError={() =>
|
||||
dispatchAppState({
|
||||
|
|
Loading…
Reference in a new issue