@mui/material#Drawer TypeScript Examples

The following examples show how to use @mui/material#Drawer. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Header.tsx    From fluttertemplates.dev with MIT License 6 votes vote down vote up
displayMobile = (isOpen: boolean, onToggle: any) => {
  return (
    <div>
      <IconButton onClick={onToggle}>
        <MenuRounded />
      </IconButton>
      <Drawer open={isOpen} anchor="bottom" onClose={onToggle}>
        {commonNav.map((item) => (
          <ListItem
            key={item.props.href}
            style={{
              padding: 16,
              justifyContent: "center",
            }}
          >
            {item}
          </ListItem>
        ))}
      </Drawer>
    </div>
  );
}
Example #2
Source File: Layout.tsx    From your_spotify with GNU General Public License v3.0 6 votes vote down vote up
export default function Layout({ children }: LayoutProps) {
  const [open, setOpen] = useState(false);
  const showSider = !useMediaQuery('(max-width: 900px)');
  const publicToken = useSelector(selectPublicToken);

  const drawer = useCallback(() => {
    setOpen((old) => !old);
  }, []);

  return (
    <div className={s.root}>
      {!showSider && (
        <Drawer open={open} anchor="left" onClose={() => setOpen(false)}>
          <Sider />
        </Drawer>
      )}
      <section className={s.sider}>{showSider && <Sider />}</section>
      <section
        className={clsx({
          [s.content]: true,
          [s.contentdrawer]: showSider,
        })}>
        {publicToken && (
          <div className={s.publictoken}>
            <Text>You are viewing as guest</Text>
          </div>
        )}
        {!showSider && (
          <IconButton onClick={drawer} className={s.drawerbutton}>
            <Menu />
          </IconButton>
        )}
        {children}
      </section>
    </div>
  );
}
Example #3
Source File: LibraryOptions.tsx    From Tachidesk-WebUI with Mozilla Public License 2.0 6 votes vote down vote up
export default function LibraryOptions() {
    const [filtersOpen, setFiltersOpen] = React.useState(false);
    const { active } = useLibraryOptionsContext();
    return (
        <>
            <IconButton
                onClick={() => setFiltersOpen(!filtersOpen)}
                color={active ? 'warning' : 'default'}
            >
                <FilterListIcon />
            </IconButton>

            <Drawer
                anchor="bottom"
                open={filtersOpen}
                onClose={() => setFiltersOpen(false)}
                PaperProps={{
                    style: {
                        maxWidth: 600, padding: '1em', marginLeft: 'auto', marginRight: 'auto',
                    },
                }}
            >
                <Options />
            </Drawer>
        </>
    );
}
Example #4
Source File: ItemViewer.tsx    From NekoMaid with MIT License 5 votes vote down vote up
GlobalItems: React.FC<{ open: boolean, onClose: () => void }> = ({ open, onClose }) => {
  const matches = useMediaQuery((theme: any) => theme.breakpoints.down('md'))
  const [flag, update] = useState(0)
  const [copyItemLeft, setCopyItemLeft] = useState<Item | undefined>()
  const [copyItemRight, setCopyItemRight] = useState<Item | undefined>()
  const items: Array<Item | undefined> = JSON.parse(localStorage.getItem('NekoMaid:items') || '[]')
  const save = () => {
    localStorage.setItem('NekoMaid:items', JSON.stringify(items))
    process.nextTick(update, flag + 1)
  }
  return <Drawer anchor='bottom' variant='persistent' elevation={16} open={open} PaperProps={{ elevation: 16 }}>
    <Box sx={{ padding: 2, display: 'flex', justifyContent: 'center', paddingBottom: 0, alignItems: 'center' }}>
      <ItemViewer
        item={copyItemLeft}
        data={{ type: InvType.GLOBAL_ITEMS }}
        onDrag={() => process.nextTick(setCopyItemLeft)}
        onDrop={it => {
          setCopyItemLeft(it)
          setCopyItemRight(it)
        }}
      />&nbsp;{`< ${lang.itemEditor.clone} >`}&nbsp;<ItemViewer
        item={copyItemRight}
        data={{ type: InvType.GLOBAL_ITEMS }}
        onDrag={() => process.nextTick(setCopyItemRight)}
        onDrop={it => {
          setCopyItemLeft(it)
          setCopyItemRight(it)
        }}
      />
    </Box>
    <Box sx={{ padding: 2, display: 'flex', justifyContent: 'center', flexWrap: 'wrap' }}>
      {Array.from({ length: 14 }, (_, i) => <ItemViewer
        key={i}
        item={items[i]}
        data={{ type: InvType.GLOBAL_ITEMS }}
        onDrag={() => {
          items[i] = undefined
          save()
          if (matches) process.nextTick(onClose)
        }}
        onDrop={it => {
          items[i] = it
          save()
        }}
        onEdit={item => {
          if (item === false) return
          items[i] = item || undefined
          save()
        }}
      />)}
    </Box>
    <ItemEditor />
  </Drawer>
}
Example #5
Source File: Menu.tsx    From console with GNU Affero General Public License v3.0 5 votes vote down vote up
Menu = ({ classes }: IMenuProps) => {
  const dispatch = useDispatch();

  const features = useSelector(selFeatures);

  const sidebarOpen = useSelector(
    (state: AppState) => state.system.sidebarOpen
  );
  const operatorMode = useSelector(selOpMode);

  const logout = () => {
    const deleteSession = () => {
      clearSession();
      dispatch(userLogged(false));
      localStorage.setItem("userLoggedIn", "");
      localStorage.setItem("redirect-path", "");
      dispatch(resetSession());
      history.push(`${baseUrl}login`);
    };
    api
      .invoke("POST", `/api/v1/logout`)
      .then(() => {
        deleteSession();
      })
      .catch((err: ErrorResponseHandler) => {
        console.log(err);
        deleteSession();
      });
  };
  const allowedMenuItems = validRoutes(features, operatorMode);

  return (
    <Drawer
      id="app-menu"
      variant="permanent"
      className={clsx(classes.drawer, {
        [classes.drawerOpen]: sidebarOpen,
        [classes.drawerClose]: !sidebarOpen,
      })}
      classes={{
        paper: clsx({
          [classes.drawerOpen]: sidebarOpen,
          [classes.drawerClose]: !sidebarOpen,
        }),
      }}
    >
      <MenuToggle
        onToggle={(nextState) => {
          dispatch(menuOpen(nextState));
        }}
        isOpen={sidebarOpen}
      />

      <ConsoleMenuList
        menuItems={allowedMenuItems}
        isOpen={sidebarOpen}
        onLogoutClick={logout}
      />
    </Drawer>
  );
}
Example #6
Source File: Header.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
function MobileHeader({ anchor, currentTab }) {
  const [mobileOpen, setMobileOpen] = useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };


  const { t } = useTranslation("ui")
  return <>
    <AppBar position="fixed" sx={{ bgcolor: "#343a40" }} elevation={0}  >
      <Drawer
        anchor="right"
        variant="temporary"
        open={mobileOpen}
        onClose={handleDrawerToggle}
        ModalProps={{
          keepMounted: true, // Better open performance on mobile.
        }}
      >
        <List>
          <ListItemButton key="home" component={RouterLink} to={'/'} selected={currentTab === ""} disabled={currentTab === ""} onClick={handleDrawerToggle} >
            <ListItemText>{t("pageTitle")}</ListItemText>
          </ListItemButton >
          {content.map(({ i18Key, value, to, svg }) =>
            <ListItemButton key={value} component={RouterLink} to={to} selected={currentTab === value} disabled={currentTab === value} onClick={handleDrawerToggle} >
              <ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
              <ListItemText>{t(i18Key)}</ListItemText>
            </ListItemButton >)}
        </List>
        <Divider />
        <List>
          {links.map(({ i18Key, href, svg, label }) =>
            <ListItemButton key={label} component="a" href={href} target="_blank" onClick={e => ReactGA.outboundLink({ label }, () => { })} >
              <ListItemIcon><FontAwesomeIcon icon={svg} /></ListItemIcon>
              <ListItemText>{t(i18Key)}</ListItemText>
            </ListItemButton >)}
        </List>
      </Drawer>
      <Toolbar>
        <Button variant="text" sx={{ color: "white" }} component={RouterLink} to="/">
          <Typography variant="h6" noWrap component="div">
            <Trans t={t} i18nKey="pageTitle">Genshin Optimizer</Trans>
          </Typography>
        </Button>
        <Box flexGrow={1} />
        <IconButton
          color="inherit"
          aria-label="open drawer"
          edge="end"
          onClick={handleDrawerToggle}
        >
          <MenuIcon />
        </IconButton>
      </Toolbar>
    </AppBar>
    {/* add a blank toolbar to keep space and provide a scroll anchor */}
    <Toolbar id={anchor} />
  </>
}
Example #7
Source File: SourceOptions.tsx    From Tachidesk-WebUI with Mozilla Public License 2.0 5 votes vote down vote up
export default function SourceOptions({
    sourceFilter,
    updateFilterValue,
    resetFilterValue,
    setTriggerUpdate,
    setSearch,
    update,
}: IFilters1) {
    const [FilterOptions, setFilterOptions] = React.useState(false);

    function handleReset() {
        resetFilterValue(0);
        setFilterOptions(false);
    }

    function handleSubmit() {
        setTriggerUpdate(0);
        setSearch(true);
        setFilterOptions(false);
    }

    return (
        <>
            <Fab
                sx={{ position: 'fixed', bottom: '2em', right: '3em' }}
                onClick={() => setFilterOptions(!FilterOptions)}
                variant="extended"
                color="primary"
            >
                <FilterListIcon />
                Filter
            </Fab>

            <Drawer
                anchor="bottom"
                open={FilterOptions}
                onClose={() => setFilterOptions(false)}
                PaperProps={{
                    style: {
                        maxWidth: 600, padding: '1em', marginLeft: 'auto', marginRight: 'auto',
                    },
                }}
            >
                <Box sx={{ display: 'flex' }}>
                    <Button
                        onClick={handleReset}
                    >
                        Reset
                    </Button>
                    <Button
                        sx={{ marginLeft: 'auto' }}
                        variant="contained"
                        onClick={handleSubmit}
                    >
                        Submit
                    </Button>
                </Box>
                <Options
                    sourceFilter={sourceFilter}
                    updateFilterValue={updateFilterValue}
                    group={undefined}
                    update={update}
                />
            </Drawer>
        </>
    );
}
Example #8
Source File: PageBuilderSidebar.tsx    From Cromwell with MIT License 5 votes vote down vote up
render() {
        const props = this.props;
        props.getInst(this);
        const block = this.selectedBlock;
        const data = block?.getData();
        if (data?.isConstant) return <></>;

        const bType = data?.type;
        const blockProps = props.createBlockProps(block);


        let content;

        if (bType === 'text') {
            content = <TextBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'plugin') {
            content = <PluginBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'container') {
            content = <ContainerBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'HTML') {
            content = <HTMLBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'image') {
            content = <ImageBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'gallery') {
            content = <GalleryBlockSidebar
                {...blockProps}
            />
        }
        if (bType === 'editor') {
            content = <EditorBlockSidebar
                {...blockProps}
            />
        }

        return (
            <Drawer
                classes={{ root: styles.sidebar, paper: styles.sidebarPaper }}
                variant="persistent"
                anchor={'left'}
                open={!!this.selectedBlock}
                onClick={(e) => e.stopPropagation()}
            >
                <Tooltip title="Close settings">
                    <IconButton
                        className={styles.sidebarCloseBtn}
                        onClick={this.handleClose}
                    >
                        <CloseIcon />
                    </IconButton>
                </Tooltip>
                <div className={styles.settings}>
                    {!!this.selectedBlock && content}
                </div>
            </Drawer>
        );
    }
Example #9
Source File: ChapterOptions.tsx    From Tachidesk-WebUI with Mozilla Public License 2.0 4 votes vote down vote up
export default function ChapterOptions(props: IProps) {
    const { options, optionsDispatch } = props;
    const [filtersOpen, setFiltersOpen] = useState(false);
    const [tabNum, setTabNum] = useState(0);

    const filterOptions = useCallback(
        (value: NullAndUndefined<boolean>, name: string) => {
            optionsDispatch({ type: 'filter', filterType: name.toLowerCase(), filterValue: value });
        }, [],
    );

    return (
        <>
            <IconButton
                onClick={() => setFiltersOpen(!filtersOpen)}
                color={options.active ? 'warning' : 'default'}
            >
                <FilterListIcon />
            </IconButton>

            <Drawer
                anchor="bottom"
                open={filtersOpen}
                onClose={() => setFiltersOpen(false)}
                PaperProps={{
                    style: {
                        maxWidth: 600,
                        padding: '1em',
                        marginLeft: 'auto',
                        marginRight: 'auto',
                        minHeight: '150px',
                    },
                }}
            >
                <Box>
                    <Tabs
                        key={tabNum}
                        value={tabNum}
                        variant="fullWidth"
                        onChange={(e, newTab) => setTabNum(newTab)}
                        indicatorColor="primary"
                        textColor="primary"
                    >
                        <Tab value={0} label="Filter" />
                        <Tab value={1} label="Sort" />
                        <Tab value={2} label="Display" />
                    </Tabs>
                    <TabPanel index={0} currentIndex={tabNum}>
                        <Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '150px' }}>
                            <FormControlLabel control={<ThreeStateCheckbox name="Unread" checked={options.unread} onChange={filterOptions} />} label="Unread" />
                            <FormControlLabel control={<ThreeStateCheckbox name="Downloaded" checked={options.downloaded} onChange={filterOptions} />} label="Downloaded" />
                            <FormControlLabel control={<ThreeStateCheckbox name="Bookmarked" checked={options.bookmarked} onChange={filterOptions} />} label="Bookmarked" />
                        </Box>
                    </TabPanel>
                    <TabPanel index={1} currentIndex={tabNum}>
                        <Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '150px' }}>
                            {
                                SortTab.map((item) => (
                                    <Stack
                                        direction="row"
                                        alignItems="center"
                                        spacing="2"
                                        sx={{ py: 1, height: 42 }}
                                        onClick={() => (item[0] !== options.sortBy
                                            ? optionsDispatch({ type: 'sortBy', sortBy: item[0] })
                                            : optionsDispatch({ type: 'sortReverse' }))}
                                    >
                                        <Box sx={{ height: 24, width: 24 }}>
                                            {
                                                options.sortBy === item[0]
                                                && (options.reverse
                                                    ? (<ArrowUpward color="primary" />) : (<ArrowDownward color="primary" />))
                                            }
                                        </Box>
                                        <Typography>{item[1]}</Typography>
                                    </Stack>

                                ))
                            }
                        </Box>
                    </TabPanel>
                    <TabPanel index={2} currentIndex={tabNum}>
                        <Stack flexDirection="column" sx={{ minHeight: '150px' }}>
                            <RadioGroup name="chapter-title-display" onChange={() => optionsDispatch({ type: 'showChapterNumber' })} value={options.showChapterNumber}>
                                <FormControlLabel label="By Source Title" value="title" control={<Radio checked={!options.showChapterNumber} />} />
                                <FormControlLabel label="By Chapter Number" value="chapterNumber" control={<Radio checked={options.showChapterNumber} />} />
                            </RadioGroup>
                        </Stack>
                    </TabPanel>
                </Box>
            </Drawer>

        </>
    );
}
Example #10
Source File: Layout.tsx    From abrechnung with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function Layout({ group = null, children, ...props }) {
    const authenticated = useRecoilValue(isAuthenticated);
    const [anchorEl, setAnchorEl] = useState(null);
    const theme: Theme = useTheme();
    const dotsMenuOpen = Boolean(anchorEl);
    const cfg = useRecoilValue(config);
    const location = useLocation();

    const [mobileOpen, setMobileOpen] = useState(true);

    const { window } = props;

    const handleProfileMenuOpen = (event) => {
        setAnchorEl(event.currentTarget);
    };

    const handleDotsMenuClose = (event) => {
        setAnchorEl(null);
    };

    const handleDrawerToggle = () => {
        setMobileOpen(!mobileOpen);
    };

    const drawer = (
        <div style={{ height: "100%" }}>
            <Toolbar />
            <Divider />
            {group != null && (
                <List sx={{ pb: 0 }}>
                    <ListItemLink
                        to={`/groups/${group.id}/`}
                        selected={
                            location.pathname === `/groups/${group.id}/` || location.pathname === `/groups/${group.id}`
                        }
                    >
                        <ListItemIcon>
                            <Paid />
                        </ListItemIcon>
                        <ListItemText primary="Transactions" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/balances`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/balances`)}
                    >
                        <ListItemIcon>
                            <BarChart />
                        </ListItemIcon>
                        <ListItemText primary="Balances" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/accounts`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/accounts`)}
                    >
                        <ListItemIcon>
                            <AccountBalance />
                        </ListItemIcon>
                        <ListItemText primary="Accounts" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/detail`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/detail`)}
                    >
                        <ListItemIcon>
                            <AdminPanelSettings />
                        </ListItemIcon>
                        <ListItemText primary="Group Settings" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/members`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/members`)}
                    >
                        <ListItemIcon>
                            <People />
                        </ListItemIcon>
                        <ListItemText primary="Group Members" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/invites`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/invites`)}
                    >
                        <ListItemIcon>
                            <Mail />
                        </ListItemIcon>
                        <ListItemText primary="Group Invites" />
                    </ListItemLink>
                    <ListItemLink
                        to={`/groups/${group.id}/log`}
                        selected={location.pathname.startsWith(`/groups/${group.id}/log`)}
                    >
                        <ListItemIcon>
                            <Message />
                        </ListItemIcon>
                        <ListItemText primary="Group Log" />
                    </ListItemLink>
                    <Divider />
                </List>
            )}
            <SidebarGroupList group={group} />

            <Box
                sx={{
                    display: "flex",
                    position: "absolute",
                    width: "100%",
                    justifyContent: "center",
                    bottom: 0,
                    padding: 1,
                    borderTop: 1,
                    borderColor: theme.palette.divider,
                }}
            >
                {cfg.imprintURL && (
                    <Link href={cfg.imprintURL} target="_blank" sx={{ mr: 2 }}>
                        imprint
                    </Link>
                )}
                <Tooltip title="Source Code">
                    <Link sx={{ ml: 1 }} target="_blank" href={cfg.sourceCodeURL}>
                        <GitHub />
                    </Link>
                </Tooltip>
                {cfg.issueTrackerURL && (
                    <Tooltip title="Bug reports">
                        <Link sx={{ ml: 1 }} target="_blank" href={cfg.issueTrackerURL}>
                            <BugReport />
                        </Link>
                    </Tooltip>
                )}
            </Box>
        </div>
    );

    const container = window !== undefined ? () => window().document.body : undefined;

    return (
        <Box sx={{ display: "flex" }}>
            <CssBaseline />
            <AppBar
                position="fixed"
                sx={{
                    // width: {sm: `calc(100% - ${drawerWidth}px)`},
                    // ml: {sm: `${drawerWidth}px`},
                    zIndex: (theme) => theme.zIndex.drawer + 1,
                }}
            >
                <Toolbar>
                    <IconButton
                        color="inherit"
                        aria-label="open drawer"
                        onClick={handleDrawerToggle}
                        edge="start"
                        sx={{ mr: 2, display: { sm: "none" } }}
                    >
                        <MenuIcon />
                    </IconButton>
                    <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
                        Abrechnung
                    </Typography>
                    {authenticated ? (
                        <div>
                            <IconButton
                                aria-label="account of current user"
                                aria-controls="menu-appbar"
                                aria-haspopup="true"
                                onClick={handleProfileMenuOpen}
                                color="inherit"
                            >
                                <AccountCircleIcon />
                            </IconButton>
                            <Menu
                                id="menu-appbar"
                                open={dotsMenuOpen}
                                anchorOrigin={{
                                    vertical: "top",
                                    horizontal: "right",
                                }}
                                keepMounted
                                anchorEl={anchorEl}
                                transformOrigin={{
                                    vertical: "top",
                                    horizontal: "right",
                                }}
                                onClose={handleDotsMenuClose}
                            >
                                <MenuItem component={RouterLink} to="/profile">
                                    Profile
                                </MenuItem>
                                <MenuItem component={RouterLink} to="/profile/settings">
                                    Settings
                                </MenuItem>
                                <MenuItem component={RouterLink} to="/profile/sessions">
                                    Sessions
                                </MenuItem>
                                <MenuItem component={RouterLink} to="/profile/change-email">
                                    Change E-Mail
                                </MenuItem>
                                <MenuItem component={RouterLink} to="/profile/change-password">
                                    Change Password
                                </MenuItem>
                                <Divider />
                                <MenuItem component={RouterLink} to="/logout">
                                    <ListItemIcon>
                                        <Logout fontSize="small" />
                                    </ListItemIcon>
                                    <ListItemText>Sign out</ListItemText>
                                </MenuItem>
                            </Menu>
                        </div>
                    ) : (
                        <Button component={RouterLink} color="inherit" to="/login">
                            Login
                        </Button>
                    )}
                </Toolbar>
            </AppBar>

            {authenticated ? (
                <Box component="nav" sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}>
                    <Drawer
                        container={container}
                        variant="temporary"
                        open={mobileOpen}
                        onClose={handleDrawerToggle}
                        ModalProps={{
                            keepMounted: true, // Better open performance on mobile.
                        }}
                        sx={{
                            display: { xs: "block", sm: "none" },
                            "& .MuiDrawer-paper": {
                                boxSizing: "border-box",
                                width: drawerWidth,
                            },
                        }}
                    >
                        {drawer}
                    </Drawer>
                    <Drawer
                        variant="permanent"
                        sx={{
                            flexShrink: 0,
                            display: { xs: "none", sm: "block" },
                            "& .MuiDrawer-paper": {
                                boxSizing: "border-box",
                                width: drawerWidth,
                            },
                        }}
                        open
                    >
                        {drawer}
                    </Drawer>
                </Box>
            ) : null}
            <Box
                component="main"
                sx={{
                    flexGrow: 1,
                    width: { sm: `calc(100% - ${drawerWidth}px)` },
                }}
            >
                <Toolbar />
                <Banner />
                <Container maxWidth="lg" sx={{ padding: { xs: 0, md: 1, lg: 3 } }}>
                    {children}
                </Container>
            </Box>
        </Box>
    );
}
Example #11
Source File: index.tsx    From ExpressLRS-Configurator with GNU General Public License v3.0 4 votes vote down vote up
Sidebar: FunctionComponent = () => {
  const location = useLocation();
  const configuratorActive =
    matchPath(location.pathname, '/configurator') !== null;
  const backpackActive = matchPath(location.pathname, '/backpack') !== null;
  // const settingsActive = matchPath(location.pathname, '/settings') !== null;
  const logsActive = matchPath(location.pathname, '/logs') !== null;
  const serialMonitorActive =
    matchPath(location.pathname, '/serial-monitor') !== null;
  const supportActive = matchPath(location.pathname, '/support') !== null;
  const { appStatus } = useAppState();

  const navigationEnabled = appStatus !== AppStatus.Busy;

  return (
    <Drawer sx={styles.drawer} variant="permanent">
      <Toolbar />
      <Divider />
      <Box sx={styles.drawerContainer}>
        <List>
          <ListItem
            component={Link}
            to="/configurator"
            selected={configuratorActive}
            sx={styles.menuItem}
            button
            disabled={!navigationEnabled}
          >
            <ListItemIcon>
              <BuildIcon />
            </ListItemIcon>
            <ListItemText primary="Configurator" />
          </ListItem>
          <ListItem
            component={Link}
            to="/backpack"
            selected={backpackActive}
            sx={styles.menuItem}
            button
            disabled={!navigationEnabled}
          >
            <ListItemIcon>
              <BackpackIcon />
            </ListItemIcon>
            <ListItemText primary="Backpack" />
          </ListItem>

          {/* <ListItem */}
          {/*  component={Link} */}
          {/*  to="/settings" */}
          {/*  selected={settingsActive} */}
          {/*  sx={styles.menuItem} */}
          {/*  button */}
          {/* > */}
          {/*  <ListItemIcon> */}
          {/*    <SettingsIcon /> */}
          {/*  </ListItemIcon> */}
          {/*  <ListItemText primary="Settings" /> */}
          {/* </ListItem> */}

          <ListItem
            component={Link}
            to="/logs"
            selected={logsActive}
            sx={styles.menuItem}
            button
            disabled={!navigationEnabled}
          >
            <ListItemIcon>
              <ListIcon />
            </ListItemIcon>
            <ListItemText primary="Logs" />
          </ListItem>

          <ListItem
            component={Link}
            to="/serial-monitor"
            selected={serialMonitorActive}
            sx={styles.menuItem}
            button
            disabled={!navigationEnabled}
          >
            <ListItemIcon>
              <DvrIcon />
            </ListItemIcon>
            <ListItemText primary="Serial Monitor" />
          </ListItem>

          <ListItem
            component={Link}
            to="/support"
            selected={supportActive}
            sx={styles.menuItem}
            button
            disabled={!navigationEnabled}
          >
            <ListItemIcon>
              <HelpIcon />
            </ListItemIcon>
            <ListItemText primary="Support" />
          </ListItem>
        </List>
      </Box>
    </Drawer>
  );
}
Example #12
Source File: SettingsDrawer.tsx    From GTAV-NativeDB with MIT License 4 votes vote down vote up
export default function SettingsDrawer({ open, onClose }: SettingsDrawerProps) {
  const smallDisplay = useIsSmallDisplay()
  const settings = useSettings()
  const dispatch = useDispatch()

  const handleThemeChanged = useCallback((e: ReactMouseEvent<HTMLElement, MouseEvent>, value: any) => {
    if (value !== null) {
      dispatch(setTheme(value))
    }
  }, [dispatch])

  const handleSourcesChanged = useCallback((e: ReactMouseEvent<HTMLElement, MouseEvent>, value: any) => {
    dispatch(setSources(value))
  }, [dispatch])

  return (
    <Drawer
      anchor={smallDisplay ? 'bottom' : 'right' }
      open={open}
      onClose={onClose}
    >
      <Box 
        sx={{ 
          display: 'flex', 
          alignItems: 'center', 
          justifyContent: 'space-between',
          width: smallDisplay ? undefined : 400,
          p: 2
        }}
      >
        <Typography
          variant="h5"
        >
          Settings
        </Typography>
        <IconButton aria-label="close settings" onClick={onClose}>
          <CloseIcon fontSize="medium" />
        </IconButton>
      </Box>
      <Divider variant="fullWidth" />
      <Box sx={{ p: 2 }}>
        <Stack spacing={2}>
          <div>
            <Typography variant="body1" gutterBottom>
              Theme
            </Typography>
            <ToggleButtonGroup
              color="primary"
              value={settings.theme}
              onChange={handleThemeChanged}
              exclusive
              fullWidth
            >
              <ToggleButton value="light">
                <LightIcon sx={{ mr: 1 }} /> 
                Light
              </ToggleButton>
              <ToggleButton value="system">
                <SystemIcon sx={{ mr: 1 }} /> 
                System
              </ToggleButton>
              <ToggleButton value="dark">
                <DarkIcon sx={{ mr: 1 }} />
                Dark
              </ToggleButton>
            </ToggleButtonGroup>
          </div>
          <div>
            <Typography variant="body1" gutterBottom>
              Sources
            </Typography>
            <ToggleButtonGroup
              color="primary"
              value={settings.sources}
              onChange={handleSourcesChanged}
              fullWidth
            >
              <ToggleButton value="alloc8or" disabled>
                Alloc8or
              </ToggleButton>
              <ToggleButton value="dottiedot">
                DottieDot
              </ToggleButton>
              <ToggleButton value="fivem">
                FiveM
              </ToggleButton>
            </ToggleButtonGroup>
          </div>
        </Stack>
      </Box>
    </Drawer>
  )
}
Example #13
Source File: CommentItemModule.tsx    From bouncecode-cms with GNU General Public License v3.0 4 votes vote down vote up
function CommentItemModule({post, comment}: ICommentItemModule) {
  const [moreVert, setMoreVert] = React.useState(null);
  const openMoreVert = Boolean(moreVert);
  const toggleMoreVert = open => {
    return event => {
      if (open) {
        setMoreVert(event.currentTarget);
      } else {
        setMoreVert(null);
      }
    };
  };

  const [commentDrawer, setCommentDrawer] = React.useState(null);
  const toggleCommentDrawer = open => {
    return event => {
      if (
        event.type === 'keydown' &&
        (event.key === 'Tab' || event.key === 'Shift')
      ) {
        return;
      }

      setCommentDrawer(open);
    };
  };

  const [
    emotionMutation,
    {loading: emotionLoading},
  ] = useCommentEmotionMutation();
  const [
    undoEmotionMutation,
    {loading: undoEmotionLoading},
  ] = useCommentEmotionUndoMutation();
  const updateEmotion = emotion => {
    return () => {
      console.log(myEmotion);
      console.log(emotion);
      if (myEmotion === emotion.toLowerCase()) {
        undoEmotionMutation({
          variables: {
            where: {
              id: comment.id,
            },
          },
          refetchQueries: [
            {
              query: CommentMyEmotionDocument,
              variables: {where: {id: comment.id}},
            },
          ],
        });
      } else {
        emotionMutation({
          variables: {
            where: {
              id: comment.id,
            },
            data: {emotion},
          },
          refetchQueries: [
            {
              query: CommentMyEmotionDocument,
              variables: {where: {id: comment.id}},
            },
          ],
        });
      }
    };
  };

  const {
    data: myEmotionData,
    loading: myEmotionLoading,
  } = useCommentMyEmotionQuery({
    variables: {where: {id: comment.id}},
  });
  const myEmotion = myEmotionData?.commentMyEmotion?.emotion;

  return (
    <Grid container direction="column" spacing={1}>
      <Grid item>
        <Grid container spacing={2}>
          <Grid item>
            <Avatar></Avatar>
          </Grid>
          <Grid item xs>
            <Grid container direction="column" spacing={1}>
              <Grid item>
                <Grid container spacing={2} alignItems="center">
                  <Grid item>
                    <Typography variant="body2">
                      {comment.user.email}
                    </Typography>
                  </Grid>
                  <Grid item>
                    <Typography variant="caption">
                      {formatDistance(
                        new Date(comment.createdDate),
                        new Date(),
                        {addSuffix: true},
                      )}
                    </Typography>
                  </Grid>
                </Grid>
              </Grid>
              <Grid item>
                <Typography variant="body1">{comment.text}</Typography>
              </Grid>
              <Grid
                container
                justifyContent="space-between"
                alignItems="center">
                <Grid item>
                  <Grid container alignItems="center">
                    <Grid item>
                      <Button
                        variant="text"
                        size="small"
                        startIcon={<ThumbUpOutlined />}
                        onClick={updateEmotion('LIKE')}
                        disabled={
                          myEmotionLoading ||
                          emotionLoading ||
                          undoEmotionLoading
                        }>
                        {comment.like || ''}
                      </Button>
                    </Grid>
                    <Grid item>
                      <Button
                        variant="text"
                        size="small"
                        startIcon={<ThumbDownOutlined />}
                        onClick={updateEmotion('UNLIKE')}
                        disabled={
                          myEmotionLoading ||
                          emotionLoading ||
                          undoEmotionLoading
                        }>
                        {comment.unlike || ''}
                      </Button>
                    </Grid>
                    {post ? (
                      <Grid item>
                        <Button
                          variant="text"
                          size="small"
                          onClick={toggleCommentDrawer(true)}
                          disabled>
                          답글
                        </Button>
                        <Drawer
                          anchor="bottom"
                          open={commentDrawer}
                          onClose={toggleCommentDrawer(false)}>
                          <Container maxWidth="md">
                            <Box pt={2} pb={2}>
                              <CommentCreateFormModule />
                            </Box>
                          </Container>
                        </Drawer>
                      </Grid>
                    ) : (
                      undefined
                    )}
                  </Grid>
                </Grid>
                <Grid item>
                  <IconButton onClick={toggleMoreVert(true)} disabled>
                    <MoreVert fontSize="small" />
                  </IconButton>
                  <Menu
                    anchorEl={moreVert}
                    open={openMoreVert}
                    onClose={toggleMoreVert(false)}>
                    <MenuItem
                      // selected={option === 'Pyxis'}
                      onClick={toggleMoreVert(false)}>
                      <ListItemIcon>
                        <AssistantPhotoOutlined />
                      </ListItemIcon>
                      <Typography variant="inherit">신고</Typography>
                    </MenuItem>
                  </Menu>
                </Grid>
              </Grid>
              {/* {post ? (
                <Grid item>
                  <Grid container direction="column" spacing={2}>
                    <Grid item>
                      <Button
                        variant="text"
                        size="small"
                        startIcon={<KeyboardArrowDown />}>
                        답글 1개 보기
                      </Button>
                    </Grid>
                    <Grid item>
                      <CommentItemModule comment />
                    </Grid>
                  </Grid>
                </Grid>
              ) : (
                undefined
              )} */}
            </Grid>
          </Grid>
        </Grid>
      </Grid>
    </Grid>
  );
}
Example #14
Source File: Navbar.tsx    From website with Apache License 2.0 4 votes vote down vote up
Navbar = ({
  rootPageHasAnimation,
}: {
  rootPageHasAnimation?: boolean;
}) => {
  const [drawerState, setDrawerState] = useState(false);
  const [toggleMoreIcon, setToggleMoreIcon] = useState(false);
  const [initialPageWidth, setInitialPageWidth] = useState(0);
  const theme = useTheme();
  const ref = useRef<HTMLButtonElement | null>(null);

  /* In the future we should come up with a different solution that doesn't
   rerender this component, its not much of a problem right now but later it
   *may* become a problem 

   - Cody
   */
  const scrollPos = useScrollPosition(15);
  const toggleDrawer = useCallback(
    (open: boolean = false) => setDrawerState(open ?? !drawerState),
    [drawerState],
  );

  useEffect(() => {
    // This is used for checking if its mobile or not
    setInitialPageWidth(window.innerWidth);
  }, []);

  return (
    <Wrapper>
      <SkipNavLink
        contentId="skipNav"
        style={{
          background: theme.background.backgroundColor,
          color:
            theme.type === "dark"
              ? theme.text.textColorExtremelyLight
              : theme.text.textColorDark,
          zIndex: 9999999,
        }}
      />
      <Drawer
        anchor="left"
        open={drawerState}
        onClose={() => toggleDrawer(false)}
      >
        <DrawerLogoContainer>
          <DrawerLogo
            alt="dahliaOS logo"
            src={
              theme.type === "dark"
                ? "/images/logos/logo-white.png"
                : "/images/logos/logo-color.png"
            }
          />
        </DrawerLogoContainer>
        <Container>
          <Link href="/#features">Features</Link>
          <Link href="/#download">Download</Link>
          <Link href="mailto:[email protected]">Contact</Link>
          <Link href="https://github.com/orgs/dahliaos/people" target="_blank">
            Developers
          </Link>
          <Link href="https://docs.dahliaOS.io">Documentation</Link>
          <Divider />
          <Category>Find us on</Category>
          <Link href="/discord" target="_blank">
            Discord
          </Link>
          <Link href="/github" target="_blank">
            GitHub
          </Link>
          <Link href="/reddit" target="_blank">
            Reddit
          </Link>
          <Link href="/telegram" target="_blank">
            Telegram
          </Link>
          <Link href="/facebook" target="_blank">
            Facebook
          </Link>
          <Link href="/instagram" target="_blank">
            Instagram
          </Link>
          <Link href="/twitter" target="_blank">
            Twitter
          </Link>
          <Divider />
          <Category>For developers</Category>
          <Link href="/github">Source Code</Link>
          <Link href="/discord">Join Our Team</Link>
        </Container>
      </Drawer>
      <StyledAppBar
        rootPageHasAnimation={
          initialPageWidth < 1075 ? false : rootPageHasAnimation
        }
        position="fixed"
        scrollPos={scrollPos}
      >
        <StyledToolbar scrollPos={scrollPos}>
          <IconButton
            edge="start"
            color="inherit"
            aria-label="menu"
            onClick={() => toggleDrawer(true)}
          >
            <MenuIcon
              style={
                theme.type === "dark"
                  ? undefined
                  : { color: theme.text.textColorDark }
              }
            />
          </IconButton>
          <AppBarLogoLinkContainer href="/">
            <AppBarLogo
              alt="dahliaOS logo"
              src={
                theme.type === "dark"
                  ? "/images/logos/logo-white.png"
                  : "/images/logos/logo-color.png"
              }
              draggable={false}
            />
          </AppBarLogoLinkContainer>
          <DesktopNav>
            <AppBarLink href="/#features">Features</AppBarLink>
            <AppBarLink href="/#download">Download</AppBarLink>
            <AppBarLink href="https://web.dahliaOS.io" target="_blank">
              Demo
            </AppBarLink>
            <AppBarLink
              href="https://github.com/orgs/dahliaos/people"
              target="_blank"
            >
              Developers
            </AppBarLink>
            <AppBarLink href="https://docs.dahliaOS.io">
              Documentation
            </AppBarLink>
            <IconButton
              ref={ref}
              aria-label="nav-more"
              aria-haspopup="true"
              onClick={() => setToggleMoreIcon(true)}
            >
              <MoreVert style={{ color: theme.text.textColorLight }} />
            </IconButton>
            <Menu
              open={toggleMoreIcon}
              onClose={() => setToggleMoreIcon(false)}
              anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
              anchorEl={ref.current}
              keepMounted
            >
              <MenuItem>
                <MenuLink href="/github" target="_blank">
                  Source Code
                </MenuLink>
              </MenuItem>
              <MenuItem disabled>Screenshots</MenuItem>
            </Menu>
          </DesktopNav>
        </StyledToolbar>
      </StyledAppBar>
      <SkipNavContent id="skipNav" />
    </Wrapper>
  );
}
Example #15
Source File: ThemeEditActions.tsx    From Cromwell with MIT License 4 votes vote down vote up
render() {
        const { isSidebarOpen, themeConfig } = this.state;
        const editingPageConfig = this.getThemeEditor().getEditingPageConfig();
        const pageInfos = this.state.pageInfos?.map(p => {
            if (p.id === editingPageConfig?.id) {
                return Object.assign({}, p, editingPageConfig);
            }
            return p;
        });
        const defaultPages = pageInfos?.filter(p => !p.isVirtual);
        const customPages = pageInfos?.filter(p => p.isVirtual);

        if (!themeConfig) return null;

        return (<>
            <div className={styles.ThemeEditActions} ref={this.wrapperRef}>
                <div>
                    <Tooltip title="Pages">
                        <IconButton
                            onClick={this.handlePagesToggle}
                        >
                            <PagesIcon />
                        </IconButton>
                    </Tooltip>
                    <Tooltip title="Page meta info">
                        <IconButton
                            onClick={this.handleMetaToggle}
                        >
                            <InfoOutlinedIcon />
                        </IconButton>
                    </Tooltip>
                    <Popover open={this.state.pageMetaOpen}
                        anchorEl={this.wrapperRef.current}
                        style={{ zIndex: 9999 }}
                        onClose={this.handleMetaToggle}
                        anchorOrigin={{
                            vertical: 'bottom',
                            horizontal: 'left',
                        }}
                        transformOrigin={{
                            vertical: 'top',
                            horizontal: 'left',
                        }}
                    >
                        <PageSettings
                            themeConfig={themeConfig}
                            pageConfig={editingPageConfig}
                            handlePageInfoChange={this.handlePageInfoChange}
                        />
                    </Popover>
                    <Tooltip title="Undo">
                        <IconButton
                            ref={this.undoBtnRef}
                            onClick={this.undoModification}
                        >
                            <UndoIcon />
                        </IconButton>
                    </Tooltip>
                    <Tooltip title="Redo">
                        <IconButton
                            ref={this.redoBtnRef}
                            onClick={this.redoModification}
                        >
                            <RedoIcon />
                        </IconButton>
                    </Tooltip>
                </div>
                <div className={styles.bottomBlock} >
                    <Tooltip title="Options">
                        <IconButton
                            onClick={this.handleOptionsToggle}
                            className={styles.actionBtn}
                            aria-label="Options"
                            ref={this.optionsAnchorEl}
                        >
                            <MoreVertOutlinedIcon />
                        </IconButton>
                    </Tooltip>
                    <Popover open={this.state.pageOptionsOpen}
                        anchorEl={this.optionsAnchorEl.current}
                        style={{ zIndex: 9999 }}
                        onClose={this.handleOptionsToggle}
                        anchorOrigin={{
                            vertical: 'bottom',
                            horizontal: 'left',
                        }}
                        transformOrigin={{
                            vertical: 'top',
                            horizontal: 'left',
                        }}
                    >
                        <div>
                            <MenuItem
                                onClick={this.handleResetCurrentPage} className={styles.optionsItem}>
                                <SettingsBackupRestoreIcon />
                                <p>Reset to default</p>
                            </MenuItem>
                            <MenuItem
                                disabled={!editingPageConfig?.isVirtual}
                                onClick={this.handleDeleteCurrentPage} className={styles.optionsItem}>
                                <DeleteForeverIcon />
                                <p>Delete page</p>
                            </MenuItem>
                        </div>
                    </Popover>
                    <Button variant="contained" color="primary"
                        className={styles.saveBtn}
                        size="small"
                        onClick={this.handleSaveEditingPage}
                    >Save</Button>
                </div>
            </div>
            <LoadingStatus isActive={this.state.loadingStatus} />
            <Drawer
                classes={{ paper: styles.sidebarPaper }}
                variant="persistent"
                anchor={'left'}
                open={isSidebarOpen}
                onClick={(e) => e.stopPropagation()}
            >
                <div className={styles.sidebar}>
                    <div className={styles.pageList} key="_2_">
                        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                            <p className={styles.pageListHeader}>Theme pages</p>
                            <div style={{ display: 'flex', alignItems: 'center' }}>
                                <Tooltip title="Theme settings">
                                    <IconButton
                                        className={styles.sidebarCloseBtn}
                                        onClick={this.handleThemeSettingsToggle}>
                                        <SettingsIcon />
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title="Close">
                                    <IconButton
                                        className={styles.sidebarCloseBtn}
                                        onClick={this.handlePagesToggle}>
                                        <CloseIcon />
                                    </IconButton>
                                </Tooltip>
                            </div>
                        </div>
                        {defaultPages?.map(p => (
                            <PageListItem
                                activePage={editingPageConfig}
                                key={p.id + p.route}
                                page={p}
                                handleOpenPage={this.handleOpenPage}
                                handleDeletePage={this.handleDeletePage}
                                onPreviewChange={this.handlePreviewChange(p)}
                            />
                        ))}
                    </div>
                    {customPages && (
                        <div className={styles.pageList} key="_3_">
                            <p className={styles.pageListHeader}>Custom pages</p>
                            {customPages.map(p => (
                                <PageListItem
                                    activePage={editingPageConfig}
                                    key={p.id + p.route}
                                    page={p}
                                    handleOpenPage={this.handleOpenPage}
                                    handleDeletePage={this.handleDeletePage}
                                    onPreviewChange={this.handlePreviewChange(p)}
                                />

                            ))}
                            <Tooltip title="Add a new page">
                                <MenuItem
                                    className={clsx(styles.addPageItem, styles.navBarItem)}
                                >
                                    <IconButton
                                        aria-label="add page"
                                        onClick={this.handleAddCustomPage}
                                    >
                                        <AddCircleIcon />
                                    </IconButton>
                                </MenuItem>
                            </Tooltip>
                        </div>
                    )}
                </div>
                <Modal
                    open={this.state?.themeSettingsOpen}
                    blurSelector="#root"
                    className={commonStyles.center}
                    onClose={this.handleThemeSettingsToggle}
                >
                    <div className={styles.themeSettings}>
                        <div className={styles.themeSettingsItem}
                            style={{ justifyContent: 'space-between' }}
                        >
                            <h3 className={styles.themeSettingsTitle}>Theme settings</h3>
                            <IconButton
                                onClick={this.handleThemeSettingsToggle}>
                                <CloseIcon />
                            </IconButton>
                        </div>
                        <div className={styles.themeSettingsItem}>
                            <ModeSwitch
                                value={this.state?.themePalette?.mode ?? 'light'}
                                onToggle={() => {
                                    this.changedPalette = true;
                                    this.setState(prev => {
                                        const isLight = prev.themePalette?.mode !== 'dark';
                                        return {
                                            themePalette: Object.assign({}, prev.themePalette, {
                                                mode: isLight ? 'dark' : 'light'
                                            })
                                        }
                                    });
                                }}
                            />
                        </div>
                        <div className={styles.themeSettingsItem}>
                            <ColorPicker
                                label="Primary color"
                                value={this.state.themePalette?.primaryColor}
                                onChange={(color) => {
                                    this.changedPalette = true;
                                    this.setState(prev => {
                                        return {
                                            themePalette: Object.assign({}, prev.themePalette, {
                                                primaryColor: color,
                                            })
                                        }
                                    })
                                }}
                            />
                        </div>
                        <div className={styles.themeSettingsItem}>
                            <ColorPicker
                                label="Secondary color"
                                value={this.state.themePalette?.secondaryColor}
                                onChange={(color) => {
                                    this.changedPalette = true;
                                    this.setState(prev => {
                                        return {
                                            themePalette: Object.assign({}, prev.themePalette, {
                                                secondaryColor: color,
                                            })
                                        }
                                    })
                                }}
                            />
                        </div>
                    </div>
                </Modal>
            </Drawer>
        </>)
    }
Example #16
Source File: Header.tsx    From metaplex with Apache License 2.0 4 votes vote down vote up
Header = ({ narrow }: { narrow: boolean }) => {
  const navs = [
    {
      href: `/entanglement/`,
      innerNarrow: 'About',
      inner: <HomeIcon />,
    },

    {
      href: `/entanglement/create`,
      inner: 'Create',
    },
    {
      href: `/entanglement/show`,
      inner: 'Show',
    },

    {
      href: `/entanglement/swap`,
      inner: 'Swap',
    },
    {
      href: `/entanglement/search`,
      inner: 'Search',
    },
    {
      href: `/entanglement/wizard`,
      inner: 'Wizard',
    },
  ];

  const [drawerOpen, setDrawerOpen] = React.useState(false);

  const toggleDrawer = open => event => {
    if (
      event.type === 'keydown' &&
      (event.key === 'Tab' || event.key === 'Shift')
    ) {
      return;
    }

    setDrawerOpen(open);
  };

  return (
    <Box
      sx={{
        height: '52px',
        display: 'flex',
        bgcolor: 'action.disabledBackground',
        overflow: 'auto',
      }}
    >
      {narrow ? (
        <React.Fragment>
          <Button onClick={toggleDrawer(true)}>
            <MenuIcon />
          </Button>
          <Drawer open={drawerOpen} onClose={toggleDrawer(false)}>
            <Box
              sx={{ width: 250 }}
              role="presentation"
              onClick={toggleDrawer(false)}
              onKeyDown={toggleDrawer(false)}
            >
              <List>
                <ListItem>
                  <ListItemText
                    primary="Token Entangler"
                    primaryTypographyProps={{
                      fontSize: '1.2rem',
                      fontWeight: 'medium',
                      letterSpacing: 0,
                    }}
                  />
                </ListItem>
                <Divider />
                {navs.map((nav, idx) => {
                  return (
                    <Link to={nav.href} key={idx} style={{ color: 'inherit' }}>
                      <ListItemButton>
                        {nav.innerNarrow || nav.inner}
                      </ListItemButton>
                    </Link>
                  );
                })}
              </List>
            </Box>
          </Drawer>
        </React.Fragment>
      ) : (
        <Stack
          direction="row"
          spacing={2}
          sx={{
            display: 'flex',
            justifyContent: 'flex-start',
            alignItems: 'center',
            marginLeft: '36px',
          }}
        >
          {navs.map((nav, idx) => {
            return (
              <Link to={nav.href} key={idx}>
                <Button variant="outlined" style={{ minWidth: 0 }}>
                  {nav.inner}
                </Button>
              </Link>
            );
          })}
        </Stack>
      )}
      <Box sx={{ flexGrow: 1, minWidth: '36px' }}></Box>
      <Settings narrow={narrow} />
    </Box>
  );
}
Example #17
Source File: index.tsx    From metaplex with Apache License 2.0 4 votes vote down vote up
Settings = ({ narrow }: { narrow: boolean }) => {
  const { disconnect, publicKey } = useWallet();
  const { setEndpoint, env, endpoint } = useConnectionConfig();
  const { setVisible } = useWalletModal();
  const open = React.useCallback(() => setVisible(true), [setVisible]);
  const { setModal } = useModal();
  const theme = useTheme();
  const colorModeCtx = useColorMode();

  const handleConnect = React.useCallback(() => {
    setModal(ModalEnum.WALLET);
    setVisible(true);
  }, [setModal, setVisible]);

  const connectedActions = [
    {
      click: async () => {
        if (publicKey) {
          await navigator.clipboard.writeText(publicKey.toBase58());
          notify({
            message: 'Wallet update',
            description: 'Address copied to clipboard',
          });
        }
      },
      innerNarrow: () =>
        `Copy Address (${publicKey && shortenAddress(publicKey.toBase58())})`,
      inner: function ConnectedWalletCopyC() {
        return (
          <React.Fragment>
            <CopyOutlined />
            {publicKey && shortenAddress(publicKey.toBase58())}
          </React.Fragment>
        );
      },
    },
    {
      click: open,
      inner: () => 'Change\u00A0Wallet',
    },
    {
      click: () => disconnect().catch(),
      inner: () => `Disconnect\u00A0(${env})`,
      expandedExtra: {
        // these are interepreted as props. TODO: specific types
        color: 'error' as any,
        variant: 'contained' as any,
      },
    },
  ];

  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const [envCollapseOpen, setEnvCollapseOpen] = React.useState(false);

  const hackySkipSet = 'hackySkipSet';
  const toggleDrawer = open => event => {
    if (
      event.type === 'keydown' &&
      (event.key === 'Tab' || event.key === 'Shift')
    ) {
      return;
    }

    if (event.target.classList.contains(hackySkipSet)) {
      return;
    }

    setDrawerOpen(open);
  };

  const drawerC = inner => {
    return (
      <React.Fragment>
        <Button onClick={toggleDrawer(true)}>
          <AccountBalanceWalletIcon />
        </Button>
        <Drawer anchor="right" open={drawerOpen} onClose={toggleDrawer(false)}>
          <Box
            sx={{ width: 250 }}
            role="presentation"
            onClick={toggleDrawer(false)}
            onKeyDown={toggleDrawer(false)}
          >
            {inner}
          </Box>
        </Drawer>
      </React.Fragment>
    );
  };

  const themeSwitch = (
    <Button
      sx={{ ml: 1 }}
      onClick={colorModeCtx.toggleColorMode}
      color="inherit"
    >
      {theme.palette.mode === 'dark' ? (
        <Brightness7Icon />
      ) : (
        <Brightness4Icon />
      )}
    </Button>
  );

  if (narrow) {
    const listHead = (
      <ListItem>
        <ListItemText
          primary="Wallet"
          primaryTypographyProps={{
            fontSize: '1.2rem',
            fontWeight: 'medium',
            letterSpacing: 0,
          }}
        />
      </ListItem>
    );
    return (
      <React.Fragment>
        {!publicKey &&
          drawerC(
            <List>
              {listHead}
              <Divider />
              <ListItemButton
                onClick={() => setEnvCollapseOpen(!envCollapseOpen)}
                className={hackySkipSet}
              >
                Change Network
                {envCollapseOpen ? <ExpandLess /> : <ExpandMore />}
              </ListItemButton>
              <Collapse in={envCollapseOpen} timeout="auto" unmountOnExit>
                <List component="div" disablePadding>
                  {ENDPOINTS.map(p => (
                    <ListItemButton
                      selected={endpoint === p.endpoint}
                      onClick={() => setEndpoint(p.endpoint)}
                      key={p.name}
                      sx={{ pl: 4 }}
                      className={hackySkipSet}
                    >
                      {p.name}
                    </ListItemButton>
                  ))}
                </List>
              </Collapse>
              <ListItemButton onClick={handleConnect}>Connect</ListItemButton>
            </List>,
          )}
        {publicKey &&
          drawerC(
            <List>
              {listHead}
              <Divider />
              {connectedActions.map((a, idx) => {
                return (
                  <ListItemButton onClick={a.click} key={idx}>
                    {(a.innerNarrow && a.innerNarrow()) || a.inner()}
                  </ListItemButton>
                );
              })}
            </List>,
          )}
        {themeSwitch}
      </React.Fragment>
    );
  } else {
    return (
      <Stack
        direction="row"
        spacing={2}
        sx={{
          display: 'flex',
          justifyContent: 'flex-end',
          alignItems: 'center',
          marginRight: '36px',
        }}
      >
        {!publicKey && (
          <React.Fragment>
            <FormControl variant="standard" style={{ minWidth: '10ch' }}>
              <Select
                id="connected-env-select"
                onChange={e => {
                  setEndpoint(e.target.value);
                }}
                value={endpoint}
              >
                {ENDPOINTS.map(({ name, endpoint }) => (
                  <MenuItem key={name} value={endpoint}>
                    {name}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <Link underline="none">
              <Button variant="contained" onClick={handleConnect}>
                Connect
              </Button>
            </Link>
          </React.Fragment>
        )}
        {publicKey &&
          connectedActions.map((a, idx) => {
            return (
              <Button
                key={idx}
                variant="outlined"
                onClick={a.click}
                {...a.expandedExtra}
              >
                {a.inner()}
              </Button>
            );
          })}
        {themeSwitch}
      </Stack>
    );
  }
}
Example #18
Source File: App.tsx    From NekoMaid with MIT License 4 votes vote down vote up
App: React.FC<{ darkMode: boolean, setDarkMode: (a: boolean) => void }> = React.memo(({ darkMode, setDarkMode }) => {
  const loc = useLocation()
  const his = useHistory()
  const pluginRef = useRef<Plugin | null>(null)
  const [mobileOpen, setMobileOpen] = useState(false)
  const [globalItemsOpen, setGlobalItemsOpen] = useState(false)
  const [globalData, setGlobalData] = useState<GlobalInfo>({ } as any)
  const [drawerWidth, setDrawerWidth] = useState(240)
  const updateF = useState(0)[1]
  const create = useMemo(() => {
    const io = socketIO(origin!, { path: pathname!, auth: { token } })
    const map: Record<string, Plugin> = { }
    const fn = (window as any).__NekoMaidAPICreate = (name: string) => map[name] || (map[name] = new Plugin(io, name))
    const nekoMaid = pluginRef.current = fn('NekoMaid')
    io.on('globalData', (data: GlobalInfo) => {
      const his: ServerRecord[] = JSON.parse(localStorage.getItem('NekoMaid:servers') || '[]')
      const curAddress = address!.replace('http://', '') + '?' + token
      let cur = his.find(it => it.address === curAddress)
      if (!cur) his.push((cur = { address: curAddress, time: 0 }))
      cur.time = Date.now()
      cur.icon = data.icon
      const arr = loc.pathname.split('/')
      if (!sent && arr.length > 2) io.emit('switchPage', arr[1], arr[2])
      sent = true
      localStorage.setItem('NekoMaid:servers', JSON.stringify(his))
      new Set(Object.values(data.plugins).flat()).forEach(loadPlugin)
      setGlobalData(data)
      pages = { }
      initPages(nekoMaid)
      onGlobalDataReceived(nekoMaid, data)
      update(Math.random())
      if (process.env.NODE_ENV !== 'development' && data.pluginVersion !== version) toast(lang.pluginUpdate, 'warning')
    }).on('!', () => {
      io.close()
      dialog({ content: lang.wrongToken, cancelButton: false })
        // eslint-disable-next-line no-return-assign
        .then(() => (location.search = location.pathname = location.hash = ''))
    }).on('reconnect', () => {
      toast(lang.reconnect)
      setTimeout(() => location.reload(), 5000)
    }).on('disconnect', () => failed(lang.disconnected)).on('connect_error', () => failed(lang.failedToConnect))
    return fn
  }, [])
  useEffect(() => { if (!loc.pathname || loc.pathname === '/') his.replace('/NekoMaid/dashboard') }, [loc.pathname])
  useEffect(() => {
    update = updateF
    return () => { update = undefined as any }
  }, [])

  const handleDrawerToggle = () => {
    setDrawerWidth(240)
    setMobileOpen(!mobileOpen)
  }

  const isExpand = drawerWidth === 240

  const routes: JSX.Element[] = []
  const mapToItem = (name: string, it: Page) => {
    const path = Array.isArray(it.path) ? it.path[0] : it.path
    const key = '/' + name + '/' + path
    routes.push(<pluginCtx.Provider key={key} value={create(name)}>
      <Route
        path={Array.isArray(it.path) ? it.path.map(it => '/' + name + '/' + it) : key}
        component={it.component}
        strict={it.strict}
        exact={it.exact}
        sensitive={it.sensitive}
      />
    </pluginCtx.Provider>)
    const icon = <ListItemIcon><pluginCtx.Provider value={create(name)}>
      {(typeof it.icon === 'function' ? <it.icon /> : it.icon) || <Build />}
    </pluginCtx.Provider></ListItemIcon>
    return it.title
      ? <NavLink key={key} to={'/' + name + '/' + (it.url || path)} activeClassName='actived'>
        <ListItem button>
          {isExpand ? icon : <Tooltip title={it.title} placement='right'>{icon}</Tooltip>}
          {isExpand && <ListItemText primary={it.title} />}
        </ListItem>
      </NavLink>
      : undefined
  }

  const singlePages: JSX.Element[] = []
  const multiPagesPages: Array<JSX.Element | JSX.Element[]> = []
  let index = 0
  for (const name in pages) {
    if (pages[name].length === 1) {
      const elm = mapToItem(name, pages[name][0])
      if (elm) singlePages.push(elm)
    } else {
      if (multiPagesPages.length) multiPagesPages.push(<Divider key={index++} />)
      multiPagesPages.push(pages[name].map(it => mapToItem(name, it)!).filter(Boolean))
    }
  }
  if (singlePages.length) multiPagesPages.push(<Divider key={index++} />, singlePages)

  const drawer = <Box sx={{ overflowX: 'hidden' }}>
    <Toolbar />
    <Divider sx={{ display: { sm: 'none', xs: 'block' } }} />
    <List sx={{
      '& a': {
        color: 'inherit',
        textDecoration: 'inherit'
      },
      '& .actived > div': {
        fontWeight: 'bold',
        color: theme => theme.palette.primary.main,
        backgroundColor: theme => alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity) + '!important',
        '& svg': { color: theme => theme.palette.primary.main + '!important' }
      }
    }}>{multiPagesPages.flat()}</List>
  </Box>

  return <Box sx={{ display: 'flex' }}>
    <CssBaseline />
    <AppBar position='fixed' sx={{ zIndex: theme => theme.zIndex.drawer + 1 }}>
      <Toolbar>
        <IconButton
          color='inherit'
          edge='start'
          onClick={() => setDrawerWidth(isExpand ? 57 : 240)}
          sx={{ mr: 1, display: { sm: 'inline-flex', xs: 'none' } }}
        ><ChevronLeft sx={{ transition: '.3s', transform: isExpand ? undefined : 'rotate(-180deg)' }} /></IconButton>
        <IconButton color='inherit' edge='start' onClick={handleDrawerToggle} sx={{ mr: 2, display: { sm: 'none' } }}><Menu /></IconButton>
        <Typography variant='h3' noWrap component='div' sx={{ flexGrow: 1 }}>NekoMaid</Typography>
        {globalData.hasNBTAPI && <IconButton
          color='inherit'
          onClick={() => setGlobalItemsOpen(!globalItemsOpen)}
          onDragOver={() => setGlobalItemsOpen(true)}
        ><Backpack /></IconButton>}
        <LanguageSwitch />
        <IconButton color='inherit' edge='end' onClick={() => setDarkMode(!darkMode)}>
          {darkMode ? <Brightness7 /> : <Brightness4 />}
        </IconButton>
      </Toolbar>
    </AppBar>
    <globalCtx.Provider value={globalData}>
      <Box component='nav' sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}>
        <Drawer
          variant='temporary'
          open={mobileOpen}
          onClose={handleDrawerToggle}
          ModalProps={{ keepMounted: true }}
          sx={{
            display: { xs: 'block', sm: 'none' },
            '& .MuiDrawer-paper': {
              boxSizing: 'border-box',
              width: drawerWidth,
              backgroundImage: theme => theme.palette.mode === 'dark'
                ? 'linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05))'
                : undefined
            }
          }}
        >
          {drawer}
        </Drawer>
        <Drawer
          open
          variant='permanent'
          sx={{
            display: { xs: 'none', sm: 'block' },
            '& .MuiDrawer-paper': {
              boxSizing: 'border-box',
              width: drawerWidth,
              transition: 'width .3s',
              backgroundImage: theme => theme.palette.mode === 'dark' ? 'linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05))' : undefined
            }
          }}
        >
          {drawer}
        </Drawer>
      </Box>
      <Box component='main' sx={{ flexGrow: 1, width: '100vw' }}>
        <drawerWidthCtx.Provider value={drawerWidth}>{routes}</drawerWidthCtx.Provider>
        {globalData.hasNBTAPI && <pluginCtx.Provider value={pluginRef.current}>
          <GlobalItems open={globalItemsOpen} onClose={() => setGlobalItemsOpen(false)} />
        </pluginCtx.Provider>}
      </Box>
    </globalCtx.Provider>
  </Box>
})
Example #19
Source File: ProductList.tsx    From Cromwell with MIT License 4 votes vote down vote up
export default function ProductTable() {
    const client = getGraphQLClient();
    const [showFilter, setShowFilter] = useState(false);
    const filterInstRef = useRef<IFrontendFilter | null>(null);
    const [attributes, setAttributes] = useState<TAttribute[] | null>(null);
    const productsRef = useRef<TFilteredProductList | null>(null);
    const attributesFilterInput = useRef<TProductFilter>({});
    const initialFilterRef = useRef<TProductFilter>({});
    const entityListPageRef = useRef<IEntityListPage<TProductFilter> | null>(null);

    useEffect(() => {
        init();

        if (filterInstRef.current && initialFilterRef.current) {
            const filter = initialFilterRef.current;
            if (filter.attributes || filter.minPrice || filter.maxPrice || filter.nameSearch) {
                filterInstRef.current.setFilter(filter);
                attributesFilterInput.current = filter;
                entityListPageRef.current?.resetList?.();
            }
        }
    }, []);

    const init = async () => {
        const attributes = await client.getAttributes();
        setAttributes(attributes);
    }

    const handleToggleFilter = () => {
        setShowFilter(prev => !prev);
    }

    const onFilterMount = () => {
        filterInstRef.current?.updateFilterMeta(productsRef.current);
    }

    const onFilterChange = (params: TProductFilter) => {
        Object.keys(params).forEach(key => {
            attributesFilterInput.current[key] = params[key];
        });
        entityListPageRef.current?.resetList?.();
    }

    return (
        <>
            <EntityTableComp
                entityCategory={EDBEntity.Product}
                entityListRoute={productListInfo.route}
                entityBaseRoute={productPageInfo.baseRoute}
                listLabel="Products"
                entityLabel="Product"
                nameProperty="name"
                getManyFiltered={async (options) => {
                    if (!options.filterParams) options.filterParams = {};
                    options.filterParams.minPrice = attributesFilterInput.current?.minPrice;
                    options.filterParams.maxPrice = attributesFilterInput.current?.maxPrice;
                    options.filterParams.attributes = attributesFilterInput.current?.attributes;
                    options.filterParams.nameSearch = attributesFilterInput.current?.nameSearch;

                    const data = await client.getFilteredProducts(options);
                    filterInstRef.current?.updateFilterMeta(data);
                    productsRef.current = data;
                    return data;
                }}
                deleteOne={client.deleteProduct}
                deleteMany={client.deleteManyProducts}
                deleteManyFiltered={client.deleteManyFilteredProducts}
                getPageListInstance={inst => {
                    entityListPageRef.current = inst;
                    initialFilterRef.current = Object.assign({}, inst.getFilterInput());
                }}
                onClearAllFilters={() => {
                    filterInstRef.current?.setFilter({});
                    attributesFilterInput.current = {};
                }}
                isFilterActive={() => {
                    const filter = attributesFilterInput.current;
                    return !!(filter.nameSearch || filter.attributes || filter.maxPrice || filter.minPrice);
                }}
                columns={[
                    {
                        name: 'mainImage',
                        label: 'Image',
                        type: 'Image',
                        visible: true,
                    },
                    {
                        name: 'name',
                        label: 'Name',
                        type: 'Simple text',
                        visible: true,
                        minWidth: '25%',
                    },
                    {
                        name: 'sku',
                        label: 'SKU',
                        type: 'Simple text',
                        visible: true,
                    },
                    {
                        name: 'price',
                        label: 'Price',
                        type: 'Currency',
                        visible: true,
                    },
                    {
                        name: 'oldPrice',
                        label: 'Old Price',
                        type: 'Currency',
                        visible: false,
                    },
                    {
                        name: 'stockStatus',
                        label: 'Stock status',
                        type: 'Simple text',
                        visible: true,
                        exactSearch: true,
                        searchOptions: [
                            {
                                value: 'In stock',
                                label: 'In stock',
                            },
                            {
                                value: 'Out of stock',
                                label: 'Out of stock',
                            },
                            {
                                value: 'On backorder',
                                label: 'On backorder',
                            },
                        ]
                    },
                    ...baseEntityColumns.map(col => {
                        if (col.name === 'createDate') return { ...col, visible: true }
                        return { ...col, visible: false }
                    }),
                ]}
                customElements={{
                    listLeftActions: (
                        <div>
                            <Tooltip title="Attribute filter">
                                <IconButton
                                className={styles.attributeFilterButton}
                                    onClick={handleToggleFilter}
                                    aria-label="show filter"
                                >
                                    <FilterListIcon />
                                </IconButton>
                            </Tooltip>
                        </div>
                    )
                }}
            />
            <Drawer
                classes={{ paper: styles.filterDrawer }}
                variant="persistent"
                anchor={'left'}
                open={showFilter}
                onClose={() => setShowFilter(false)}>
                <div className={styles.filterHeader}>
                    <h3>Filter</h3>
                    <Tooltip title="Close">
                        <IconButton
                            onClick={handleToggleFilter}
                            aria-label="close filter"
                        >
                            <CloseIcon />
                        </IconButton>
                    </Tooltip>
                </div>
                <ProductFilter
                    instanceSettings={{
                        disableMobile: true,
                        onChange: onFilterChange,
                        getInstance: (inst) => { filterInstRef.current = inst },
                        onMount: onFilterMount,
                    }}
                    data={{
                        attributes
                    }}
                />
            </Drawer>
        </>
    )
}