@material-ui/core#Badge JavaScript Examples

The following examples show how to use @material-ui/core#Badge. 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: NationAvatar.js    From dipact with GNU General Public License v3.0 6 votes vote down vote up
badger(content) {
		if (
			this.props.gameState &&
			(this.props.gameState.Properties.Muted || []).indexOf(
				this.props.nation
			) !== -1
		) {
			return this.buttoner(
				<Badge
					badgeContent={<MuteIcon />}
					overlap="circle"
				>
					{content}
				</Badge>
			);
		} else {
			return this.buttoner(content);
		}
	}
Example #2
Source File: OftadehAvatarBadge.jsx    From oftadeh-react-admin with MIT License 6 votes vote down vote up
StyledBadge = withStyles(theme => ({
  badge: {
    backgroundColor: "#44b700",
    color: "#44b700",
    boxShadow: `0 0 0 2px ${theme.palette.background.paper}`,
    "&::after": {
      position: "absolute",
      top: 0,
      left: 0,
      width: "100%",
      height: "100%",
      borderRadius: "50%",
      animation: "$ripple 1.2s infinite ease-in-out",
      border: "1px solid currentColor",
      content: '""'
    }
  },
  "@keyframes ripple": {
    "0%": {
      transform: "scale(.8)",
      opacity: 1
    },
    "100%": {
      transform: "scale(2.4)",
      opacity: 0
    }
  }
}))(Badge)
Example #3
Source File: Header.js    From pwa with MIT License 6 votes vote down vote up
render() {
    return (
      <div className="HeaderWrapper" name="close" onClick={this.handleOpen}>
        <div className="notif-button-wrapper">
          <Badge variant="dot" color="primary">
            <button type="button" name="open" onClick={this.handleOpen}>
              <img
                src={notification}
                className="notif-btn"
                alt="Notification"
              />
            </button>
          </Badge>
          <div className="logo">
            <img src={logo} alt="logo" />
          </div>
          <Typography variant="subtitle2" className="beta-version">
            نسخه آزمایشی
          </Typography>
        </div>

        <Dialog open={this.state.isDialogOpen}>
          <Box ml={3} className="notif-msg">
            این برنامه در حال به روز رسانی می‌باشد، برای بهره‌مندی از جدیدترین
            امکانات، به‌روز باشید!
          </Box>
        </Dialog>
      </div>
    );
  }
Example #4
Source File: NavigationFrame.js    From spl-token-wallet with Apache License 2.0 6 votes vote down vote up
function ConnectionsButton() {
  const classes = useStyles();
  const setPage = usePage()[1];
  const onClick = () => setPage('connections');
  const connectedWallets = useConnectedWallets();

  const connectionAmount = Object.keys(connectedWallets).length;

  return (
    <>
      <Hidden smUp>
        <Tooltip title="Manage Connections">
          <IconButton color="inherit" onClick={onClick}>
            <Badge
              badgeContent={connectionAmount}
              classes={{ badge: classes.badge }}
            >
              <ConnectionIcon />
            </Badge>
          </IconButton>
        </Tooltip>
      </Hidden>
      <Hidden xsDown>
        <Badge
          badgeContent={connectionAmount}
          classes={{ badge: classes.badge }}
        >
          <Button color="inherit" onClick={onClick} className={classes.button}>
            Connections
          </Button>
        </Badge>
      </Hidden>
    </>
  );
}
Example #5
Source File: FilterButton.js    From AED-Map with MIT License 6 votes vote down vote up
FilterButton = ({ isOpen, setIsOpen, filter }) => {
  const tooltipMessage = isOpen
    ? 'Закрити фільтр'
    : 'Відкрити фільтр';

  const toggleFilter = () => {
    setIsOpen(prevState => !prevState);
  };

  return (
    <IconButton
      color="primary"
      aria-label="filter"
      onClick={toggleFilter}
    >
      {filter ? (
        <Badge color="secondary" variant="dot">
          <Tooltip title={tooltipMessage}>
            <FilterListIcon />
          </Tooltip>
        </Badge>
      ) : (
        <Tooltip title={tooltipMessage}>
          <FilterListIcon />
        </Tooltip>
      )}
    </IconButton>
  );
}
Example #6
Source File: TopBar.js    From paper-and-ink with MIT License 6 votes vote down vote up
function Topbar(props) {
  const { className, children, openSidebar, onToggleSidebar } = props;
  const classes = useStyles(props);
  const [notifications] = useState([{ message: 'A Message', status: 'success' }]);
  return (
    <AppBar className={clsx(classes.root, className)}>
      <Toolbar className={classes.toolbar}>
        <div className={classes.brandWrapper}>
          <div className={classes.logo}>Paper & Ink</div>
          <IconButton className={classes.menuButton} aria-label="Menu" onClick={onToggleSidebar}>
            {openSidebar ? <CloseIcon /> : <MenuIcon />}
          </IconButton>
        </div>
        <ThemeToggler className={classes.themeToggler} />
        <IconButton className={classes.notificationsButton}>
          <Badge badgeContent={notifications.length} color="primary" variant="dot">
            <NotificationsIcon />
          </Badge>
        </IconButton>
        <IconButton className={classes.signOutButton}>
          <InputIcon />
        </IconButton>
      </Toolbar>
      {children}
    </AppBar>
  );
}
Example #7
Source File: DevicesBadge.js    From budgie-stream with MIT License 6 votes vote down vote up
DevicesBadge = () => {
  const { playback } = useContext(ClientContext);
  const [state] = playback;
  const [nbrDevices, setNbrDevices] = useState("0");
  // eslint-disable-next-line
  const getNbrOfDevices = () => {
    const count = state.devices.filter((device) => device.selected === true)
      .length;
    setNbrDevices(count);
  };

  useEffect(() => {
    getNbrOfDevices();
  }, [state.devices, getNbrOfDevices]);

  return (
    <>
      <Tooltip title="Devices/Groups Selected" aria-label="Devices">
        <Badge color="secondary" badgeContent={nbrDevices}>
          <SpeakerIcon />
        </Badge>
      </Tooltip>
    </>
  );
}
Example #8
Source File: ProductCartWidget.js    From course-manager with MIT License 6 votes vote down vote up
// ----------------------------------------------------------------------

export default function CartWidget() {
  return (
    <RootStyle>
      <Badge showZero badgeContent={0} color="error" max={99}>
        <Icon icon={shoppingCartFill} width={24} height={24} />
      </Badge>
    </RootStyle>
  );
}
Example #9
Source File: VisualizerOptionSelectionGrid.js    From Otto with MIT License 6 votes vote down vote up
StyledBadge = withStyles((theme) => ({
  badge: {
    width: 10,
    "&::after": {
      position: "absolute",
      top: 0,
      left: 0,
      width: "100%",
      height: "100%",
      borderRadius: "50%",
      content: '""',
    },
  },
}))(Badge)
Example #10
Source File: NavBar.js    From inventory-management-web with MIT License 5 votes vote down vote up
NavBar = ({ mobileOpen, setMobileOpen, tabletOpen, setTabletOpen }) => {
  // used to check current url
  const location = useLocation();

  const theme = useTheme();
  // true if in tablet mode
  const tablet = useMediaQuery(theme.breakpoints.only('sm'));
  const mobile = useMediaQuery(theme.breakpoints.only('xs'));
  const isLoggedIn = location.pathname !== '/login';
  const classes = useStyles(isLoggedIn);

  const { expiryListBadge } = useContext(ExpiryListContext);

  // handle opening and closing of drawer
  const handleDrawerToggle = () => {
    if (tablet) {
      setTabletOpen(!tabletOpen);
    } else {
      setMobileOpen(!mobileOpen);
    }
  };

  return (
    <div className={classes.root}>
      <AppBar position='fixed'>
        <Toolbar>
          <Hidden mdUp>
            <IconButton
              edge='start'
              className={classes.menuButton}
              color='inherit'
              onClick={handleDrawerToggle}
            >
              {tabletOpen ? (
                <ChevronLeftIcon />
              ) : (
                <Badge
                  badgeContent={expiryListBadge}
                  color='primary'
                  overlap='circle'
                  className={classes.tabBadge}
                  invisible={!mobile}
                >
                  <MenuIcon />
                </Badge>
              )}
            </IconButton>
          </Hidden>
          <Typography variant='h6' className={classes.title}>
            Inventory Management Web App
          </Typography>

          <AlertDialog />
        </Toolbar>
      </AppBar>
    </div>
  );
}
Example #11
Source File: Topbar.js    From telar-cli with MIT License 5 votes vote down vote up
Topbar = props => {
  const { className, onSidebarOpen, ...rest } = props;

  const classes = useStyles();

  const [notifications] = useState([]);

  return (
    <AppBar
      {...rest}
      className={clsx(classes.root, className)}
    >
      <Toolbar>
        <RouterLink to="/">
          <h1 style={{color:'white'}}>Telar</h1>
        </RouterLink>
        <div className={classes.flexGrow} />
        <Hidden mdDown>
          <IconButton color="inherit">
            <Badge
              badgeContent={notifications.length}
              color="primary"
              variant="dot"
            >
              <NotificationsIcon />
            </Badge>
          </IconButton>
          <IconButton
            className={classes.signOutButton}
            color="inherit"
          >
            <InputIcon />
          </IconButton>
        </Hidden>
        <Hidden lgUp>
          <IconButton
            color="inherit"
            onClick={onSidebarOpen}
          >
            <MenuIcon />
          </IconButton>
        </Hidden>
      </Toolbar>
    </AppBar>
  );
}
Example #12
Source File: nav-filter-by-values.js    From horondi_admin with MIT License 5 votes vote down vote up
NavFilterByValues = ({
  filterByMultipleOptions: {
    filters,
    setFilterHandler,
    label,
    selectItems,
    objForTranslateRenderItems
  }
}) => {
  const styles = useStyles();

  const { optionHandler, setRenderValue } = useFilter(
    selectItems,
    setFilterHandler
  );

  return (
    <div className={styles.formblock}>
      <Badge
        badgeContent={filters.length}
        color={materialUiConstants.styleError}
        anchorOrigin={badgePosition}
      >
        <FormControl style={{ minWidth: 170 }} className={styles.formControl}>
          <InputLabel id={materialUiConstants.checkBoxLabel}>
            {label}
          </InputLabel>
          <Select
            labelId={materialUiConstants.checkBoxLabel}
            id={materialUiConstants.checkBoxId}
            multiple
            value={filters}
            onChange={optionHandler}
            renderValue={(selected) =>
              setRenderValue(selected, objForTranslateRenderItems)
            }
            input={<Input />}
            autoWidth
            MenuProps={MenuProps}
          >
            {selectItems.map((item) => (
              <MenuItem key={item.key} value={item.key}>
                <Checkbox checked={filters.indexOf(item.key) > -1} />
                <ListItemText primary={item.value} />
              </MenuItem>
            ))}
          </Select>
        </FormControl>
      </Badge>
    </div>
  );
}
Example #13
Source File: options-picker.js    From horondi_admin with MIT License 5 votes vote down vote up
OptionsPicker = ({ value, handler, label, options }) => {
  const styles = useStyles();

  const { optionHandler, setRenderValue } = useFilter(options, handler);

  const filteredOptions = {};
  options.map((option) =>
    Object.assign(filteredOptions, { [option.value]: option.label })
  );

  return (
    <Badge
      badgeContent={value.length}
      color={materialUiConstants.styleError}
      anchorOrigin={badgePosition}
    >
      <FormControl className={styles.container}>
        <InputLabel id={materialUiConstants.checkBoxLabel}>{label}</InputLabel>
        <Select
          labelId={materialUiConstants.checkBoxLabel}
          id={materialUiConstants.checkBoxId}
          multiple
          value={value}
          onChange={optionHandler}
          renderValue={(selected) => setRenderValue(selected, filteredOptions)}
          input={<Input />}
          autoWidth
          MenuProps={MenuProps}
        >
          {options.map((item) => (
            <MenuItem key={item.value} value={item.value}>
              <Checkbox checked={value.indexOf(item.value) > -1} />
              <ListItemText primary={item.label} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </Badge>
  );
}
Example #14
Source File: positions.jsx    From GraphVega with MIT License 5 votes vote down vote up
Positions = props => {
  const [show, setShow] = useState(false);

  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

  const displayQuantity = index => {
    return props.positions[index].position === "long" ? (
      <div className="text-success">+{props.positions[index].quantity}</div>
    ) : (
      <div className="text-danger">{props.positions[index].quantity}</div>
    );
  };
  return (
    <>
      <Badge badgeContent={props.positions.length} color="secondary">
        <Button onClick={handleShow} variant="contained" color="primary">
          Positions
        </Button>
      </Badge>

      <Modal
        show={show}
        onHide={handleClose}
        style={{ background: "rgba(0, 0, 0,0.5)" }}
      >
        <Modal.Body>
          <h4>
            <b>Positions</b>
          </h4>
          <br />
          {props.positions[0]?
            ""
            :<div className="text-secondary">Looks like you have not added any positions yet! </div>
          }
          <Table>
            {props.positions.map((option, index) => {
              return (
                <tr>
                  <th>
                    {displayQuantity(index)}
                  </th>
                  <th>
                    {option["description"]}
                  </th>
                  <th>
                    <Button
                      size="small"
                      // variant="outlined"
                      color="secondary"
                      onClick={() => {
                        props.onRemovePosition(index);
                      }}
                    >
                      <ClearIcon fontSize="small"/>  Remove 
                    </Button>
                  </th>
                </tr>
              );
            })}
          </Table>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            Close
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}
Example #15
Source File: CardUrls.js    From FireShort with MIT License 5 votes vote down vote up
export default function CardUrls(props) {
    const history = useHistory();
    const classes = useStyles();

    return (
        <Container className={classes.cardGrid} maxWidth="lg">
            <Grid container spacing={4}>
                {props.shortUrls.map((card) => (
                    <Grid item key={card.id} xs={12} sm={6} md={4}>
                        <Card className={classes.card}>
                            <CardHeader
                                action={
                                    <Tooltip title={"Copy to clipboard"}>
                                        <IconButton color="primary" className={classes.copyButton} onClick={() => { navigator.clipboard.writeText(window.location.origin + "/" + card.data.curl) }}>
                                            <FileCopyOutlinedIcon />
                                        </IconButton>
                                    </Tooltip>
                                }
                                title={
                                    <Tooltip title={card.data.track === true ? "Link Tracking ON" : "Link Tracking OFF"}>
                                        <Badge color={card.data.track === true ? "primary" : "error"} variant="dot">
                                            <Typography>{card.data.curl}</Typography>
                                        </Badge>
                                    </Tooltip>
                                }
                                titleTypographyProps={{
                                    variant: "subtitle1"
                                }}
                            >

                            </CardHeader>
                            <CardContent className={classes.cardContent}>
                                <Box bgcolor="text.primary" color="background.paper" p={2} style={{ overflowX: 'auto', overflowY: 'hidden', whiteSpace: "nowrap" }}>
                                    {card.data.lurl}
                                </Box>
                            </CardContent>
                            <CardActions className={classes.cardActions}>
                                <Tooltip title={"Preview link"}>
                                    <IconButton size="small" color="primary" href={card.data.lurl} target="_blank">
                                        <VisibilityIcon />
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title={"Edit link"}>
                                    <IconButton size="small" onClick={() => props.handleEditShortUrl(card.data.curl)}>
                                        <EditIcon />
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title={"Analytics"}>
                                    <IconButton size="small" disabled={!card.data.track} onClick={() => history.push(`/analytics/${card.data.curl}`)}>
                                        <AnalyticsIcon />
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title={"Delete link"}>
                                    <IconButton size="small" color="secondary" onClick={() => props.handleDeleteShortUrl(card.data.curl)}>
                                        <DeleteForeverIcon />
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title={card.data.hits + " Hits"}>
                                    <IconButton onClick={() => { props.openHits(card.data.curl) }} style={{ cursor: "pointer" }}>
                                        <Badge badgeContent={card.data.hits} color="secondary" max={Infinity} showZero>
                                            <OpenInBrowser />
                                        </Badge>
                                    </IconButton>
                                </Tooltip>
                                <Tooltip title={"Password protect"}>
                                    <IconButton size='small' color='default' onClick={() => props.toggleSecurity(card.data.curl)}>
                                        {card.data.locked ? <LockIcon /> : <LockOpenIcon />}
                                    </IconButton>
                                </Tooltip>
                            </CardActions>
                        </Card>
                    </Grid>
                ))}
            </Grid>
        </Container>
    );
}
Example #16
Source File: ChatMenu.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		return (
			<div
				style={{
					position: "relative",
					height: "100%",
				}}
			>
				<Slide
					direction="up"
					in={!!this.state.activeChannel}
					mountOnEnter
					unmountOnExit
				>
					<div
						style={{
							top: 0,
							left: 0,
							bottom: 0,
							right: 0,
							background: "#ffffff",
							position: "absolute",
							zIndex: 1200,
						}}
					>
						<ChatChannel
							onNewGameState={this.props.onNewGameState}
							gameState={this.props.gameState}
							game={this.props.game}
							phases={this.props.phases}
							isActive={this.props.isActive}
							createMessageLink={this.state.createMessageLink}
							channel={this.state.activeChannel}
							close={this.closeChannel}
							loaded={(_) => {
								this.loadChannels(true);
							}}
							parent={this}
						/>
					</div>
				</Slide>
				{this.state.channels && this.state.channels.length > 0 ? (
					""
				) : (
					<Typography>No chat channels currently.</Typography>
				)}
				<ButtonGroup
					orientation="vertical"
					style={{
						width: "100%",
						height: "100%",
						transform: "translateZ(0)",
						WebkitTransform: "translateZ(0)",
						overflowY: !!this.state.activeChannel
							? "hidden"
							: "scroll",
					}}
				>
					{this.state.channels.map((channel) => {
						return (
							<Button
								style={{
									width: "100%",
									justifyContent: "left",
									paddingTop: "12px",
									paddingBottom: "12px",
									border: "none",
									borderBottom: "1px solid rgb(40,26,26,0.1)",
									borderRadius: "0px",
								}}
								onClick={(_) => {
									this.openChannel(channel);
								}}
								key={channel.Properties.Members.join(",")}
							>
								{this.member &&
								channel.Properties.NMessagesSince &&
								channel.Properties.NMessagesSince.NMessages >
									0 ? (
									<Badge
										badgeContent={
											channel.Properties.NMessagesSince
												.NMessages
										}
										overlap="circle"
										color="primary"
									>
										{this.variant.Properties.Nations
											.length ===
										channel.Properties.Members.length ? (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={
													channel.Properties.Members
												}
											/>
										) : (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={channel.Properties.Members.filter(
													(n) => {
														return (
															!this.member ||
															n !==
																this.member
																	.Nation
														);
													}
												)}
											/>
										)}
									</Badge>
								) : this.variant.Properties.Nations.length ===
								  channel.Properties.Members.length ? (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members}
									/>
								) : (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members.filter(
											(n) => {
												return (
													!this.member ||
													n !== this.member.Nation
												);
											}
										)}
									/>
								)}

								{channel.Properties.NMessages &&
								channel.Properties.LatestMessage ? (
									<div
										style={{
											display: "flex",
											flexDirection: "column",
											alignItems: "flex-start",
											marginLeft: "8px",
											minWidth: "0",
										}}
									>
										<Typography
											variant="body1"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{channel.Properties.Members
												.length ===
											this.variant.Properties.Nations
												.length
												? "Everyone"
												: channel.Properties.Members.filter(
														(n) => {
															return (
																!this.member ||
																n !==
																	this.member
																		.Nation
															);
														}
												  ).map((n, i) => {
														if (i === 0) {
															return n;
														} else {
															return ", " + n;
														}
												  })}{" "}
											({channel.Properties.NMessages})
										</Typography>
										<Typography
											variant="body2"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{this.member ? (
												this.member.Nation ===
												channel.Properties.LatestMessage
													.Sender ? (
													<span
														style={{
															fontStyle: "italic",
														}}
													>
														You:{" "}
													</span>
												) : channel.Properties.Members
														.length > 2 ? (
													channel.Properties
														.LatestMessage.Sender +
													": "
												) : (
													""
												)
											) : (
												channel.Properties.LatestMessage
													.Sender + ": "
											)}
											{
												channel.Properties.LatestMessage
													.Body
											}
										</Typography>
									</div>
								) : (
									""
								)}
							</Button>
						);
					})}
				</ButtonGroup>
				{this.state.createMessageLink ? (
					<React.Fragment>
						<Fab
							style={{
								margin: "0px",
								top: "auto",
								right: "20px",
								bottom: "20px",
								left: "auto",
								position: "fixed",
								display: !!this.state.activeChannel
									? "none"
									: "flex",
							}}
							color="secondary"
							aria-label="edit"
							onClick={(_) => {
								this.createChannelDialog.setState({
									open: true,
								});
							}}
						>
							<CreateMessageIcon />
						</Fab>
						<CreateChannelDialog
							game={this.props.game}
							createChannel={(channel) => {
								const newChannels = this.state.channels;
								const oldChannel = newChannels.find((ch) => {
									return helpers.deepEqual(
										channel.Properties.Members,
										ch.Properties.Members
									);
								});
								if (!oldChannel) {
									newChannels.push(channel);
								}
								const channelToUse = oldChannel || channel;
								this.setState(
									{
										channels: newChannels,
									},
									(_) => {
										gtag("event", "create_chat_channel");
										this.openChannel(channelToUse);
									}
								);
							}}
							parentCB={(c) => {
								this.createChannelDialog = c;
							}}
						/>
					</React.Fragment>
				) : (
					""
				)}
			</div>
		);
	}
Example #17
Source File: Game.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		if (this.state.game) {
			return (
				<React.Fragment>
					<AppBar
						key="app-bar"
						position="fixed"
						color={this.state.laboratoryMode ? "secondary" : "primary"}
					>
						<Toolbar>
							{!this.state.laboratoryMode ? (
								<IconButton
									onClick={this.props.close}
									key="close"
									edge="start"
									color="secondary"
								>
									<CloseIcon />
								</IconButton>
							) : (
								<IconButton
									onClick={(_) => {
										this.setState(
											{
												moreMenuAnchorEl: null,
												laboratoryMode: !this.state.laboratoryMode,
											},
											(_) => {
												if (!this.state.laboratoryMode) {
													this.loadGame();
												} else {
													gtag("event", "enable_lab_mode");
												}
											}
										);
									}}
									key="close"
									edge="start"
									color="primary"
								>
									<CloseIcon />
								</IconButton>
							)}
							{!this.state.laboratoryMode &&
							this.state.activePhase &&
							this.state.activePhase.Properties.PhaseOrdinal > 1 ? (
								<IconButton
									onClick={this.phaseJumper(-1)}
									key="previous"
									edge="start"
									color="secondary"
								>
									<PreviousIcon />
								</IconButton>
							) : !this.state.laboratoryMode ? (
								<Box key="prev-spacer"></Box>
							) : (
								""
							)}

							{this.state.laboratoryMode ? (
								<Typography variant="h6" style={{ marginRight: "8px" }}>
									Sandbox
								</Typography>
							) : (
								""
							)}
							{this.state.activePhase ? (
								<Select
									/* TODO: This might be a stretch, but Laboratory mode has SOME "real" and some "fake" turns. E.g. in spring 1902 I can move back to Spring 1901 and create an "alternative" 1901 and commit that. 
                  Is it possible to make all the "hypothetical" phases to change color? Maybe let me know in the Discord chat and we can discuss more. */
									/*
									 * Yes it is - 'real' phases have .Properties.ID, while fake phases don't (IIRC).
									 */
									style={
										this.state.laboratoryMode
											? {
													width: "100%",
													minWidth: "0",
													borderBottom: "1px solid rgba(253, 226, 181, 0.7)",
													color: "rgb(40, 26, 26)",
											  }
											: {
													width: "100%",
													minWidth: "0",
													borderBottom: "1px solid rgba(253, 226, 181, 0.7)",
													color: "#FDE2B5",
											  }
									}
									key="phase-select"
									value={this.state.activePhase.Properties.PhaseOrdinal}
									onChange={this.changePhase}
									label={helpers.phaseName(this.state.activePhase)}
								>
									{this.state.phases.map((phase) => {
										return (
											<MenuItem
												key={phase.Properties.PhaseOrdinal}
												style={{
													textOverflow: "ellipsis",
												}}
												value={phase.Properties.PhaseOrdinal}
											>
												{helpers.phaseName(phase)}
												{!this.state.game.Properties.Started ||
												phase.Properties.Resolved ? (
													""
												) : (
													<span
														dataat={
															new Date().getTime() +
															phase.Properties.NextDeadlineIn * 1e-6
														}
														style={{
															position: "relative",
															top: "-6px",
															fontSize: "xx-small",
															left: "-5px",
															zIndex: "1",
															backgroundColor: "red",
															borderRadius: "7px",
															padding: "0 2px 1px 2px",
														}}
													>
														{helpers.minutesToDuration(
															(phase.Properties.NextDeadlineIn * 1e-9) / 60.0,
															true
														)}
													</span>
												)}
											</MenuItem>
										);
									})}
								</Select>
							) : !this.state.laboratoryMode ? (
								<Box key="curr-spacer" width="100%"></Box>
							) : (
								""
							)}
							{this.state.activePhase &&
							this.state.activePhase.Properties.PhaseOrdinal <
								this.state.phases[this.state.phases.length - 1].Properties
									.PhaseOrdinal ? (
								<IconButton
									onClick={this.phaseJumper(1)}
									edge="end"
									key="next"
									color="secondary"
								>
									<NextIcon />
								</IconButton>
							) : !this.state.laboratoryMode ? (
								<Box key="next-spacer"></Box>
							) : (
								""
							)}

							{!this.state.laboratoryMode ? (
								<IconButton
									edge="end"
									key="more-icon"
									color="secondary"
									onClick={(ev) => {
										this.setState({
											moreMenuAnchorEl: ev.currentTarget,
										});
									}}
								>
									<SettingsIcon />
								</IconButton>
							) : (
								""
							)}
							<Menu
								anchorEl={this.state.moreMenuAnchorEl}
								anchorOrigin={{
									vertical: "top",
									horizontal: "right",
								}}
								transformOrigin={{
									vertical: "top",
									horizontal: "right",
								}}
								onClose={(_) => {
									this.setState({ moreMenuAnchorEl: null });
								}}
								open={!!this.state.moreMenuAnchorEl}
							>
								<MenuItem
									key="game-metadata"
									onClick={(_) => {
										this.setState({
											moreMenuAnchorEl: null,
										});
										if (this.state.game.Properties.Started) {
											this.gamePlayersDialog.setState({
												open: true,
											});
										} else {
											this.metadataDialog.setState({
												open: true,
											});
										}
									}}
								>
									Game & player info
								</MenuItem>
								{this.state.game.Properties.Started
									? [
											<MenuItem
												key="scores"
												onClick={(_) => {
													this.setState({
														moreMenuAnchorEl: null,
													});
													this.preliminaryScores.setState({
														open: true,
													});
												}}
											>
												Scores
											</MenuItem>,
											this.state.game.Properties.Finished ? (
												<MenuItem
													key="results"
													onClick={(_) => {
														this.setState({
															moreMenuAnchorEl: null,
														});
														this.gameResults.setState({
															open: true,
														});
													}}
												>
													Results
												</MenuItem>
											) : (
												""
											),
									  ]
									: ""}
								<Divider />
								<MenuItem key="game-id" onClick={this.shareNative}>
									{this.state.game.Properties.Started
										? "Share game"
										: "Invite players"}
								</MenuItem>

								<MenuItem
									key="download-map"
									onClick={(_) => {
										this.setState({
											moreMenuAnchorEl: null,
										});
										this.dip_map.downloadMap();
										gtag("event", "download_map");
									}}
								>
									Download map
								</MenuItem>
								<MenuItem
									key="laboratory-mode"
									onClick={(_) => {
										this.setState(
											{
												moreMenuAnchorEl: null,
												laboratoryMode: !this.state.laboratoryMode,
											},
											(_) => {
												if (!this.state.laboratoryMode) {
													this.loadGame();
												} else {
													gtag("event", "enable_lab_mode");
												}
											}
										);
									}}
								>
									{this.state.laboratoryMode
										? "Turn off sandbox mode"
										: "Sandbox mode"}
								</MenuItem>
								<Divider />
								<MenuItem
									key="How to play"
									onClick={(_) => {
										window.open(
											"https://diplicity.notion.site/How-to-play-39fbc4d1f1924c928c3953095062a983",
											"_blank"
										);
									}}
								>
									How to play
								</MenuItem>
								<MenuItem
									key="debug-data"
									onClick={(_) => {
										helpers
											.copyToClipboard(JSON.stringify(this.debugCounters))
											.then((_) => {
												this.setState({
													moreMenuAnchorEl: null,
												});
												helpers.snackbar("Debug data copied to clipboard");
											});
									}}
								>
									Debug
								</MenuItem>
							</Menu>
							{this.state.laboratoryMode ? (
								<React.Fragment>
									<IconButton
										onClick={(_) => {
											this.dip_map.downloadMap();
											gtag("event", "download_map");
										}}
										color="primary"
										edge="end"
										style={{ marginLeft: "auto" }}
									>
										<DownloadIcon />
									</IconButton>
									<IconButton
										onClick={(_) => {
											this.dip_map.labShare();
										}}
										color="primary"
										edge="end"
										style={{ marginLeft: "auto" }}
									>
										<ShareIcon />
									</IconButton>
								</React.Fragment>
							) : (
								""
							)}
						</Toolbar>
						{!this.state.laboratoryMode ? (
							<React.Fragment>
								{!this.state.game.Properties.Started ||
								this.state.game.Links.find((l) => {
									return l.Rel === "join";
								}) ? (
									<Toolbar
										style={{
											display: "flex",
											justifyContent: "space-between",
											minHeight: "53px",
										}}
									>
										<div>
											{this.state.game.Links.find((l) => {
												return l.Rel === "join";
											}) ? (
												<Button
													variant="outlined"
													color="secondary"
													key="join"
													onClick={this.join}
												>
													Join
												</Button>
											) : (
												""
											)}
											{this.state.game.Links.find((l) => {
												return l.Rel === "leave";
											}) ? (
												<Button
													variant="outlined"
													color="secondary"
													key="leave"
													onClick={this.leave}
												>
													Leave
												</Button>
											) : (
												""
											)}
										</div>
										<div
											style={{
												display: "flex",
												alignItems: "center",
											}}
										>
											<NumMembersIcon />{" "}
											<Typography
											//TODO: Change this to not NMembers but Nmembers - replaceable.
												variant="body2"
												style={{ paddingLeft: "2px" }}
											>
												{this.state.game.Properties.NMembers}/
												{this.state.variant.Properties.Nations.length}{" "}
											</Typography>
										</div>
									</Toolbar>
								) : (
									""
								)}
								<Tabs
									key="tabs"
									value={this.state.activeTab}
									onChange={this.changeTab}
									display="flex"
									variant="fullWidth"
								>
									<Tab value="map" icon={<MapIcon />} />
									<Tab
										value="chat"
										icon={
											this.state.member && this.state.unreadMessages > 0 ? (
												<Badge badgeContent={this.state.unreadMessages}>
													<ChatIcon />
												</Badge>
											) : (
												<ChatIcon />
											)
										}
									/>
									{this.state.game.Properties.Started ? (
										this.state.member &&
										!this.state.activePhase.Properties.Resolved ? (
											this.state.member.NewestPhaseState.OnProbation ||
											!this.state.member.NewestPhaseState.ReadyToResolve ? (
												<Tab
													value="orders"
													icon={
														<SvgIcon>
															<path
																d="M9,0 C10.3,0 11.4,0.84 11.82,2 L11.82,2 L16,2 C17.1045695,2 18,2.8954305 18,4 L18,4 L18,18 C18,19.1045695 17.1045695,20 16,20 L16,20 L2,20 C0.8954305,20 0,19.1045695 0,18 L0,18 L0,4 C0,2.8954305 0.8954305,2 2,2 L2,2 L6.18,2 C6.6,0.84 7.7,0 9,0 Z M5,14 L3,14 L3,16 L5,16 L5,14 Z M15,14 L7,14 L7,16 L15,16 L15,14 Z M5,6 L3,6 L3,12 L5,12 L5,6 Z M15,10 L7,10 L7,12 L15,12 L15,10 Z M15,6 L7,6 L7,8 L15,8 L15,6 Z M9,2 C8.44771525,2 8,2.44771525 8,3 C8,3.55228475 8.44771525,4 9,4 C9.55228475,4 10,3.55228475 10,3 C10,2.44771525 9.55228475,2 9,2 Z"
																id="order_open"
															></path>
														</SvgIcon>
													}
												/>
											) : (
												<Tab
													value="orders"
													icon={
														<SvgIcon>
															<path
																d="M9,0 C10.3,0 11.4,0.84 11.82,2 L11.82,2 L16,2 C17.1045695,2 18,2.8954305 18,4 L18,4 L18,18 C18,19.1045695 17.1045695,20 16,20 L16,20 L2,20 C0.8954305,20 0,19.1045695 0,18 L0,18 L0,4 C0,2.8954305 0.8954305,2 2,2 L2,2 L6.18,2 C6.6,0.84 7.7,0 9,0 Z M13.4347826,7 L7.70608696,12.7391304 L4.56521739,9.60869565 L3,11.173913 L7.70608696,15.8695652 L15,8.56521739 L13.4347826,7 Z M9,2 C8.44771525,2 8,2.44771525 8,3 C8,3.55228475 8.44771525,4 9,4 C9.55228475,4 10,3.55228475 10,3 C10,2.44771525 9.55228475,2 9,2 Z"
																id="order_confirmed"
															></path>
														</SvgIcon>
													}
												/>
											)
										) : (
											<Tab value="orders" icon={<EventIcon />} />
										)
									) : (
										""
									)}
								</Tabs>
							</React.Fragment>
						) : (
							<Toolbar>
								<Typography variant="body1" style={{ marginRight: "8px" }}>
									Edit
								</Typography>
								<FormControlLabel
									key="edit-mode"
									control={
										<Switch
											onChange={(ev) => {
												this.setState({
													labEditMode: !ev.target.checked,
												});
												this.dip_map.setState({
													labEditMode: !ev.target.checked,
												});
											}}
											color="primary"
											checked={!this.state.labEditMode}
										/>
									}
									label="Play as"
								/>
								{!this.state.labEditMode ? (
									<FormControl
										key="play-as"
										style={{
											flexGrow: 1,
										}}
									>
										<Select
											value={this.state.labPlayAs}
											onChange={(ev) => {
												this.setState({
													labPlayAs: ev.target.value,
												});
												this.dip_map.setState({
													labPlayAs: ev.target.value,
												});
											}}
											style={{
												width: "100%",
												minWidth: "0",
												borderBottom: "1px solid rgba(253, 226, 181, 0.7)",
												color: "rgb(40, 26, 26)",
											}}
										>
											{this.state.variant.Properties.Nations.map((nation) => {
												return (
													<MenuItem key={nation} value={nation}>
														{nation}
													</MenuItem>
												);
											})}
										</Select>
									</FormControl>
								) : (
									""
								)}

								<IconButton
									edge="end"
									onClick={(ev) => {
										this.dip_map.labResolve();
									}}
									style={{
										marginLeft: "auto",
										color: "rgb(40, 26, 26)",
									}}
								>
									<FastForwardIcon />
								</IconButton>
							</Toolbar>
						)}
					</AppBar>

					<div
						key="map-container"
						style={
							this.state.laboratoryMode
								? {
										marginTop: "" + this.state.marginTop + "px",
										height: "calc(100% - " + this.state.marginTop + "px)",
										backgroundColor: "black",
										display: this.state.activeTab === "map" ? "block" : "none",
								  }
								: {
										marginTop: "" + this.state.marginTop + "px",
										height: "calc(100% - " + this.state.marginTop + "px)",
										backgroundColor: "black",
										display: this.state.activeTab === "map" ? "block" : "none",
								  }
						}
					>
						<DipMap
							parentCB={(c) => {
								this.dip_map = c;
							}}
							onLeaveProbation={(_) => {
								this.loadGame();
							}}
							debugCount={this.debugCount}
							labPhaseResolve={this.labPhaseResolve}
							serializePhaseState={this.serializePhaseState}
							laboratoryMode={this.state.laboratoryMode}
							isActive={this.state.activeTab === "map"}
							game={this.state.game}
							phase={this.state.activePhase}
							corroborateSubscriber={this.receiveCorroboration}
							variant={this.state.variant}
						/>
					</div>
					<React.Fragment>
						<div
							key="chat-container"
							style={{
								marginTop: "" + this.state.marginTop + "px",
								height: "calc(100% - " + this.state.marginTop + "px)",
								display: this.state.activeTab === "chat" ? "block" : "none",
							}}
						>
							<ChatMenu
								onNewGameState={this.onNewGameState}
								gameState={
									this.state.member && this.state.gameStates
										? this.state.gameStates.find((gs) => {
												return (
													gs.Properties.Nation === this.state.member.Nation
												);
										  })
										: null
								}
								isActive={this.state.activeTab === "chat"}
								unreadMessages={this.setUnreadMessages}
								phases={this.state.phases}
								game={this.state.game}
								parent={this}
							/>
						</div>
						{this.state.game.Properties.Started ? (
							<div
								key="orders-container"
								style={{
									marginTop: "" + this.state.marginTop + "px",
									height: "calc(100% - " + this.state.marginTop + "px)",
									display: this.state.activeTab === "orders" ? "flex" : "none",
									flexDirection: "column",
									justifyContent: "space-between",
								}}
							>
								<OrderList
									isActive={this.state.activeTab === "orders"}
									member={this.state.member}
									phase={this.state.activePhase}
									corroboration={this.state.corroboration}
									newPhaseStateHandler={(phaseState) => {
										this.setState((state, props) => {
											state = Object.assign({}, state);
											state.member.NewestPhaseState = phaseState.Properties;
											return state;
										});
										if (this.props.onChangeReady) {
											this.props.onChangeReady();
										}
									}}
									variant={this.state.variant}
								/>
							</div>
						) : (
							""
						)}
						<GamePlayers
							gameStates={this.state.gameStates}
							game={this.state.game}
							variant={this.state.variant}
							onNewGameState={this.onNewGameState}
							parentCB={(c) => {
								this.gamePlayersDialog = c;
							}}
						/>
						<PreliminaryScores
							phases={this.state.phases}
							variant={this.state.variant}
							parentCB={(c) => {
								this.preliminaryScores = c;
							}}
						/>
					</React.Fragment>
					{!this.state.game.Properties.Started ? (
						<React.Fragment>
							<NationPreferencesDialog
								parentCB={(c) => {
									this.nationPreferencesDialog = c;
								}}
								onSelected={null}
							/>
							<MetadataDialog
								game={this.state.game}
								parentCB={(c) => {
									this.metadataDialog = c;
								}}
							/>
						</React.Fragment>
					) : (
						""
					)}
					{!this.state.member ||
					!this.state.game.Properties.Started ||
					this.state.game.Properties.Mustered ? (
						""
					) : (
						<MusteringPopup
							viewOrders={(_) => {
								this.setState({
									activeTab: "orders",
									readyReminder: false,
								});
							}}
						/>
					)}
					<GameResults
						onNewGameState={this.onNewGameState}
						gameState={
							this.state.member && this.state.gameStates
								? this.state.gameStates.find((gs) => {
										return gs.Properties.Nation === this.state.member.Nation;
								  })
								: null
						}
						game={this.state.game}
						variant={this.state.variant}
						parentCB={(c) => {
							this.gameResults = c;
						}}
					/>
					<Snackbar
						anchorOrigin={{
							vertical: "bottom",
							horizontal: "center",
						}}
						open={this.state.readyReminder}
						autoHideDuration={30000}
						onClose={(_) => {
							this.setState({ readyReminder: false });
						}}
						message={[
							<Typography key="ready-warning">
								You haven't confirmed your orders yet.
								{this.state.game.Properties.Mustered
									? ""
									: " For the game to start, all players have to confirm as ready to play."}
							</Typography>,
						].concat(
							this.state.phaseMessages.map((m) => {
								return <Typography key={m}>{m}</Typography>;
							})
						)}
						action={
							<React.Fragment>
								<Button
									color="secondary"
									size="small"
									onClick={(_) => {
										this.setState({
											activeTab: "orders",
											readyReminder: false,
										});
									}}
								>
									View orders
								</Button>
								<IconButton
									size="small"
									aria-label="close"
									color="inherit"
									onClick={(_) => {
										this.setState({ readyReminder: false });
									}}
								>
									<CloseIcon />
								</IconButton>
							</React.Fragment>
						}
					/>
				</React.Fragment>
			);
		} else {
			return "";
		}
	}
Example #18
Source File: Menu.js    From qasong with ISC License 4 votes vote down vote up
function MobileMenu({ queueLength, setShowAboutUs, setShowSettings, setShowFeedback }) {
  const classes = useStyles();

  let history = useHistory();

  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);

  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

  const handleMobileMenuClose = () => {
    setMobileMoreAnchorEl(null);
  };

  const handleMobileMenuOpen = (event) => {
    setMobileMoreAnchorEl(event.currentTarget);
  };

  function handleQueueButtonClick() {
    history.push("/queue");
    handleMobileMenuClose();
  }

  function handleBillboardClick() {
    history.push("/billboard");
    handleMobileMenuClose();
  }

  function handlePlaylistClick() {
    history.push("/playlists");
    handleMobileMenuClose();
  }

  function handleSettingsClick() {
    setShowSettings(true);
    history.push("/");
  }

  function handleAboutUsClick() {
    setShowAboutUs(true);
    history.push("/");
  }

  function handleFeedbackClick() {
    setShowFeedback(true);
    history.push("/");
    handleMobileMenuClose();
  }

  const mobileMenuId = "primary-search-account-menu-mobile";
  return (
    <div>
      <Menu
        anchorEl={mobileMoreAnchorEl}
        anchorOrigin={{
          vertical: "top",
          horizontal: "right",
        }}
        id={mobileMenuId}
        keepMounted
        transformOrigin={{
          vertical: "top",
          horizontal: "right",
        }}
        open={isMobileMenuOpen}
        onClose={handleMobileMenuClose}
        className={classes.backdrop}
      >
        {/* QUEUE */}

        <MenuItem onClick={handleQueueButtonClick}>
          queue
          <IconButton target="_blank" color="inherit" size="small">
            <Badge badgeContent={queueLength} color="secondary">
              <QueueMusicIcon />
            </Badge>
          </IconButton>
        </MenuItem>
        <MenuItem onClick={handlePlaylistClick}>playlists</MenuItem>
        <MenuItem onClick={handleBillboardClick}>billboard top 100</MenuItem>
        <MenuItem onClick={handleSettingsClick}>settings</MenuItem>
        <MenuItem onClick={handleFeedbackClick}>feedback</MenuItem>
        <MenuItem onClick={handleAboutUsClick}>about us</MenuItem>
      </Menu>

      <IconButton
        aria-label="show more"
        aria-controls={mobileMenuId}
        aria-haspopup="true"
        onClick={handleMobileMenuOpen}
        color="inherit"
      >
        <Badge badgeContent={queueLength} color="secondary">
          <MoreIcon style={{ fontSize: 36 }} />
        </Badge>
      </IconButton>
    </div>
  );
}
Example #19
Source File: GameListElement.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		const { classes } = this.props;
		let itemKey = 0;
		let buttons = [];
		if (
			this.state.game.Properties.Open &&
			this.state.game.Properties.ActiveBans &&
			this.state.game.Properties.ActiveBans.length > 0
		) {
			buttons.push(
				<Typography key="banned-notice" style={noticeClass}>
					You can't join because you banned or are banned by a player.
				</Typography>
			);
		}
		if (
			!this.state.game.Properties.Closed &&
			this.state.game.Properties.FailedRequirements
		) {
			buttons.push(
				<Typography
					variant="subtitle2"
					key="requirement-notice"
					style={noticeClass}
				>
					You can't join this game because{" "}
					{this.state.game.Properties.FailedRequirements.map((req) => {
						return this.failureExplanations()[req];
					}).join(" ")}
				</Typography>
			);
		}

		if (!this.state.dead) {
			buttons.push(
				<Button
					variant="outlined"
					style={{
						marginRight: "16px",
						minWidth: "100px",
						marginBottom: "4px",
					}}
					color="primary"
					onClick={this.viewGame}
					key={itemKey++}
				>
					View
				</Button>
			);
			if (this.state.member) {
				buttons.push(
					<Button
						variant="outlined"
						style={{
							marginRight: "16px",
							minWidth: "100px",
							marginBottom: "4px",
						}}
						color="primary"
						onClick={this.renameGame}
						key={itemKey++}
					>
						Rename
					</Button>
				);
			}
		}
		let replaceablePlayers = 0;
					if (this.state.game.Properties.Members !== null) {
					replaceablePlayers = this.state.game.Properties.Members.filter(member => 
  					member.Replaceable == true
					).length;
					} else {
						replaceablePlayers = 0;
					}
		if (!this.state.game.Properties.Closed || replaceablePlayers > 0) {
			buttons.push(
				<Button
					variant="outlined"
					style={{
						marginRight: "16px",
						minWidth: "100px",
						marginBottom: "4px",
					}}
					color="primary"
					onClick={this.shareNative}
					key={itemKey++}
				>
					Invite
				</Button>
			);
		}
		let hasInviteDialog = false;
		this.state.game.Links.forEach((link) => {
			if (link.Rel === "join") {
				if (
					this.state.game.Properties.PhaseLengthMinutes < 60 * 12 ||
					(this.state.game.Properties.NonMovementPhaseLengthMinutes !== 0 &&
						this.state.game.Properties.NonMovementPhaseLengthMinutes < 60 * 12)
				) {
					buttons.unshift(
						<Typography key="deadline-warning" style={warningClass}>
							WARNING: This game has short deadlines (less than 12 hours). If it
							starts while you're unavailable, you might miss parts of the game
							greatly impacting your reliability score.
						</Typography>
					);
				}
				if (
					!this.state.game.Properties.Private &&
					this.state.game.Properties.MinReliability === 0 &&
					Globals.userStats.Properties.Reliability >= 10
				) {
					buttons.unshift(
						<Typography key="reliability-warning" style={warningClass}>
							WARNING: We advise you to join a different game, because this game
							might have (some) absent players. You have high reliability so can
							join a better game.
						</Typography>
					);
				}
				buttons.push(
					<Button
						key={itemKey++}
						variant="outlined"
						color="primary"
						style={{ marginRight: "16px", minWidth: "100px" }}
						onClick={(_) => {
							this.joinGame(link);
						}}
					>
						Join
					</Button>
				);
			} else if (link.Rel === "edit-newest-phase-deadline-at") {
				buttons.push(
					//TODO: Add confirmdialog.js before we accidentally move a turn forwards.. (how?)
					<React.Fragment>
						<Divider style={{marginBottom: "4px"}} />
						<Button
							key={itemKey++}
							variant="contained"
							color="primary"
							style={{
								marginRight: "16px",
								minWidth: "100px",
								marginBottom: "4px",
							}}
							onClick={(_) => {
								this.nextturn(link);
							}}
						>
							End Current Phase
						</Button>
						<Button
							key={itemKey++}
							variant="contained"
							color="primary"
							style={{
								marginRight: "16px",
								minWidth: "100px",
								marginBottom: "4px",
							}}
							onClick={(_) => {
								this.reschedule(link);
							}}
						>
							Change deadline
						</Button>
					</React.Fragment>
				);
			} else if (link.Rel === "leave") {
				buttons.push(
					<Button
						key={itemKey++}
						variant="outlined"
						color="primary"
						style={{
							marginRight: "16px",
							minWidth: "100px",
							marginBottom: "4px",
						}}
						onClick={(_) => {
							this.leaveGame(link);
						}}
					>
						Leave
					</Button>
				);
			} else if (link.Rel === "delete-game") {
				buttons.push(
					//TODO: add confirmdialog.js before we accidentally DELETE THE WHOLE (ONGOING) GAME (how)?
					<Button
						key={itemKey++}
						variant="outlined"
						color="primary"
						style={{
							marginRight: "16px",
							minWidth: "100px",
							marginBottom: "4px",
						}}
						onClick={(_) => {
							this.deleteGame(link);
						}}
					>
						Delete
					</Button>
				);
			} else if (
				link.Rel === "invite-user" ||
				link.Rel.indexOf("uninvite-") === 0
			) {
				hasInviteDialog = true;
			}
		});
		if (hasInviteDialog) {
			buttons.push(
				<Button
					key={itemKey++}
					variant="contained"
					color="primary"
					style={{
						marginRight: "16px",
						minWidth: "100px",
						marginBottom: "4px",
					}}
					onClick={(_) => {
						this.manageInvitations();
					}}
				>
					Assign players
				</Button>
			);
		}
		const buttonDiv = (
			<div
				key={itemKey++}
				style={{
					dispay: "flex",
					justifyContent: "space-evenly",
					marginBottom: "8px",
				}}
			>
				{buttons}
			</div>
		);

		let summary = (
			<div
				style={{
					display: "flex",
					flexDirection: "column",
					width: "100%",

					marginTop: "8px",
				}}
			>
				{((_) => {
					if (this.state.game.Properties.Started && replaceablePlayers == 0) {
						return (
							<React.Fragment>
								{/* IF STARTED */}
								<div
									style={{
										display: "flex",
										flexDirection: "row",
										justifyContent: "space-between",
									}}
								>
									{this.state.member && this.state.member.UnreadMessages > 0 ? (
										<Badge
											key={itemKey++}
											badgeContent={this.state.member.UnreadMessages}
											color="primary"
											style={{
												maxWidth: "calc(100% - 70px)",
											}}
										>
											<Typography
												textroverflow="ellipsis"
												noWrap
												style={{
													color: "rgba(40, 26, 26, 1)",
												}}
											>
												{helpers.gameDesc(this.state.game)}
											</Typography>
										</Badge>
									) : (
										<Typography
											key={itemKey++}
											textroverflow="ellipsis"
											noWrap={true}
											style={{
												minWidth: "60px",
												color: "rgba(40, 26, 26, 1)",
											}}
										>
											{helpers.gameDesc(this.state.game)}
										</Typography>
									)}

									<div
										id="Timer"
										key={itemKey++}
										style={{
											alignSelf: "center",
											display: "flex",
											alignItems: "center",
											color: "#281A1A",
										}}
									>
										{this.state.member &&
										this.state.game.Properties.Started &&
										!this.state.game.Properties.Finished ? (
											this.state.member.NewestPhaseState.OnProbation ? (
												<SvgIcon>
													<path
														d="M2.98188996,2.24133335 L21.3666663,20.6261097 L20.0261097,21.9666663 L19.0573333,20.998 L19,21 L5,21 C3.95,21 3.0822314,20.1799587 3.00551277,19.1486946 L3,19 L3,5 L3.00233335,4.942 L1.64133335,3.58188996 L2.98188996,2.24133335 Z M12,1 C13.235,1 14.2895,1.7581 14.75196,2.828465 L14.82,3 L19,3 C20.05,3 20.9177686,3.82004132 20.9944872,4.85130541 L21,5 L21,17.963 L16.037,13 L17,13 L17,11 L14.037,11 L12.037,9 L17,9 L17,7 L10.037,7 L6.037,3 L9.18,3 C9.579,1.898 10.5917,1.0848 11.80656,1.006235 L12,1 Z M13.0593333,15 L7,15 L7,17 L15.0593333,17 L13.0593333,15 Z M11.0593333,13 L9.06033335,11 L7,11 L7,13 L11.0593333,13 Z M12,3 C11.45,3 11,3.45 11,4 C11,4.55 11.45,5 12,5 C12.55,5 13,4.55 13,4 C13,3.45 12.55,3 12,3 Z"
														id="Shape"
														fill="#b71c1c"
														fillRule="nonzero"
													></path>
												</SvgIcon>
											) : this.state.member.NewestPhaseState.ReadyToResolve ? (
												<SvgIcon>
													<path
														d="M9,0 C10.3,0 11.4,0.84 11.82,2 L11.82,2 L16,2 C17.1045695,2 18,2.8954305 18,4 L18,4 L18,18 C18,19.1045695 17.1045695,20 16,20 L16,20 L2,20 C0.8954305,20 0,19.1045695 0,18 L0,18 L0,4 C0,2.8954305 0.8954305,2 2,2 L2,2 L6.18,2 C6.6,0.84 7.7,0 9,0 Z M13.4347826,7 L7.70608696,12.7391304 L4.56521739,9.60869565 L3,11.173913 L7.70608696,15.8695652 L15,8.56521739 L13.4347826,7 Z M9,2 C8.44771525,2 8,2.44771525 8,3 C8,3.55228475 8.44771525,4 9,4 C9.55228475,4 10,3.55228475 10,3 C10,2.44771525 9.55228475,2 9,2 Z"
														fill="#281A1A"
														id="Combined-Shape"
													></path>
												</SvgIcon>
											) : (
												<StartedAtIcon />
											)
										) : (
											""
										)}
										<Typography
											variant="body2"
											style={{
												paddingLeft: "2px",
												color: "rgba(40, 26, 26, 1)",
											}}
										>
											{this.state.game.Properties.Finished
												? helpers.minutesToDuration(
														-this.state.game.Properties.FinishedAgo /
															1000000000 /
															60,
														true
												  )
												: helpers.minutesToDuration(
														this.state.game.Properties.NewestPhaseMeta[0]
															.NextDeadlineIn /
															1000000000 /
															60,
														true
												  )}
										</Typography>
									</div>
								</div>
								<div key={itemKey++} style={secondRowSummaryClass}>
									<Typography
										textroverflow="ellipsis"
										noWrap={true}
										display="inline"
										variant="caption"
										id="variant"
										style={secondRowSummaryColorClass}
									>
										{this.state.game.Properties.Variant}{" "}
										{helpers.phaseLengthDisplay(this.state.game.Properties)}
									</Typography>
									<div style={summaryIconsAndPhaseClass}>
										<div style={summaryIconsClass}>{this.getIcons()}</div>
										<Typography
											variant="caption"
											style={secondRowSummaryColorClass}
										>
											{this.state.game.Properties.NewestPhaseMeta[0].Season}{" "}
											{this.state.game.Properties.NewestPhaseMeta[0].Year},{" "}
											{this.state.game.Properties.NewestPhaseMeta[0].Type}
										</Typography>
									</div>
								</div>
								{!this.state.member || this.state.game.Properties.Mustered ? (
									""
								) : (this.state.game.Properties.Members || []).find((m) => {
										return m.User.Id === Globals.user.Id;
								  }).NewestPhaseState.ReadyToResolve ? (
									<Typography
										className={this.props.classes.sixteenBySixteenClass}
									>
										Confirmed ready <ConfirmedReadyIcon />
									</Typography>
								) : (
									<Button
										variant="outlined"
										style={{
											marginRight: "16px",
											minWidth: "100px",
											marginBottom: "4px",
										}}
										color="primary"
										onClick={(ev) => {
											ev.stopPropagation();
											helpers
												.safeFetch(
													helpers.createRequest(
														"/Game/" +
															this.state.game.Properties.ID +
															"/Phase/" +
															this.state.game.Properties.NewestPhaseMeta[0]
																.PhaseOrdinal +
															"/PhaseState",
														{
															headers: {
																"Content-Type": "application/json",
															},
															method: "PUT",
															body: JSON.stringify({
																ReadyToResolve: true,
															}),
														}
													)
												)
												.then(this.reloadGame);
										}}
										key={itemKey++}
									>
										Confirm ready
									</Button>
								)}
							</React.Fragment>
						);
					} else {
						return (
							<React.Fragment>
								{/* IF STARTED */}
								<div
									style={{
										display: "flex",
										flexDirection: "row",
										justifyContent: "space-between",
									}}
								>
									<Typography
										key={itemKey++}
										textroverflow="ellipsis"
										noWrap={true}
										style={{}}
									>
										{helpers.gameDesc(this.state.game)}
									</Typography>

									<div
										id="Join"
										key={itemKey++}
										style={{
											alignSelf: "center",
											display: "flex",
											alignItems: "center",
										}}
									>
										<NumMembersIcon style={replaceablePlayers == 0 ? {color: "primary"} : {color: "red"} } />
										<Typography variant="body2" style={replaceablePlayers == 0 ? { paddingLeft: "2px", } : { paddingLeft: "2px", color: "red"}}>
											{replaceablePlayers == 0 ? this.state.game.Properties.NMembers : this.state.game.Properties.NMembers - replaceablePlayers}/
											{this.variant.Properties.Nations.length}{" "}
										</Typography>
									</div>
								</div>
								<div
									style={{
										display: "flex",
										flexDirection: "row",
										justifyContent: "space-between",
									}}
								>
									<Typography
										textroverflow="ellipsis"
										noWrap={true}
										display="inline"
										variant="caption"
										style={{
											color: "rgba(40, 26, 26, 0.7)",
										}}
									>
										{this.state.game.Properties.Variant}{" "}
										{helpers.phaseLengthDisplay(this.state.game.Properties)}
									</Typography>
									<div> {this.getIcons()}</div>
								</div>
							</React.Fragment>
						);
					}
				})()}

				<div></div>
			</div>
		);

		let gameView = (
			<Zoom in={this.state.viewOpen} mountOnEnter unmountOnExit>
				<div
					style={{
						position: "fixed",
						zIndex: 1300,
						right: 0,
						bottom: 0,
						top: 0,
						left: 0,
						background: "#ffffff",
					}}
				>
					<Game
						onChangeReady={this.reloadGame}
						onJoinGame={this.reloadGame}
						onLeaveGame={(_) => {
							if (this.state.game.Properties.Members.length > 1) {
								this.reloadGame();
							} else {
								this.setState({ dead: true });
							}
						}}
						unreadMessagesUpdate={this.reloadGame}
						gamePromise={(reload) => {
							if (reload) {
								return helpers
									.safeFetch(
										helpers.createRequest(
											this.state.game.Links.find((l) => {
												return l.Rel === "self";
											}).URL
										)
									)
									.then((resp) => resp.json());
							} else {
								return new Promise((res, rej) => {
									res(this.state.game);
								});
							}
						}}
						close={this.closeGame}
					/>
				</div>
			</Zoom>
		);

		if (this.props.summaryOnly) {
			return (
				<React.Fragment>
					<div style={{ width: "100%" }} onClick={this.viewGame}>
						{summary}
					</div>
					{this.state.viewOpen ? gameView : ""}
				</React.Fragment>
			);
		}
		return (
			<React.Fragment>
				<Accordion
					key="game-details"
					onChange={(ev, exp) => {
						this.setState({ expanded: exp });
					}}
					square
					style={{
						border: "none",
						boxShadow: "none",
						padding: "0px",
						margin: "0px",
					}}
				>
					<AccordionSummary
						classes={{
							root: classes.accordionSummaryRoot,
							content: classes.accordionSummaryContent,
						}}
						expandIcon={<ExpandIcon />}
					>
						{summary}
					</AccordionSummary>
					<AccordionDetails className={classes.accordionDetails}>
						{this.state.expanded ? (
							<div>
								<div
									style={{
										display: "flex",
										flexDirection: "row",
										justifyContent: "space-between",
										flexWrap: "wrap",
										maxWidth: "960px",
										width: "100%",
										marginBottom: "16px",
									}}
								>
									<div
										style={{
											maxWidth: "460px",
										}}
									>
										{buttonDiv}
										{this.state.dead ? (
											<Typography style={{ color: "red" }}>Deleted</Typography>
										) : (
											""
										)}
										<GameMetadata
											game={this.state.game}
											withKickButtons={true}
											reloadGame={this.reloadGame}
										/>
									</div>
								</div>
								<Divider />
							</div>
						) : (
							""
						)}
					</AccordionDetails>
				</Accordion>
				{this.state.viewOpen ? gameView : ""}
				<NationPreferencesDialog
					parentCB={(c) => {
						this.nationPreferencesDialog = c;
					}}
					onSelected={null}
				/>
				{this.state.member ? (
					<RenameGameDialog
						onRename={this.reloadGame}
						game={this.state.game}
						parentCB={(c) => {
							this.renameGameDialog = c;
						}}
					/>
				) : (
					""
				)}
				{this.state.game.Properties.GameMaster &&
				this.state.game.Properties.GameMaster.Id === Globals.user.Id ? (
					<React.Fragment>
						<RescheduleDialog
							parentCB={(c) => {
								this.rescheduleDialog = c;
							}}
							onSubmit={this.onRescheduleSubmit}
						/>
						<ManageInvitationsDialog
							game={this.state.game}
							parentCB={(c) => {
								this.manageInvitationsDialog = c;
							}}
							reloadGame={this.reloadGame}
						/>
					</React.Fragment>
				) : (
					""
				)}
			</React.Fragment>
		);
	}
Example #20
Source File: Header.js    From facebook-clone with MIT License 4 votes vote down vote up
Header = () => {
  const classes = Style();
  const dispatch = useDispatch();
  const mode = useSelector((state) => state.util);
  const { photoURL } = useSelector((state) => state.user);

  const changeTheme = () => {
    dispatch(ToggleTheme());
  };

  const logout = () => {
    auth.signOut();
  };

  return (
    <Paper elevation={0} style={{ borderRadius: 0, width: "100%", height: "100%" }}>
      <Grid container className={classes.header}>
        {/*----Logo & Search icon--------*/}
        <Hidden xsDown>
          <Grid item className={classes.header__logo} sm={2} md={3}>
            <img className={classes.logo__image} src={logo} alt="facebook-logo" />
            <Hidden smDown>
              <div className={classes.logo__search}>
                <SearchIcon />
                <input placeholder="Search facebook ..." />
              </div>
            </Hidden>
          </Grid>
        </Hidden>
        {/*----Nav-Bar--------*/}
        <Grid item className={classes.header__nav} xs={12} sm={8} md={6}>
          <div className={`${classes.nav__links} ${classes.nav__links__specail}`}>
            <Avatar src={logo} />
          </div>
          <div className={classes.nav__links}>
            <HomeOutlined />
          </div>
          <div className={classes.nav__links}>
            <PlayCircleFilledWhiteOutlined />
          </div>
          <Hidden xsDown>
            <div className={classes.nav__links}>
              <StoreMallDirectoryOutlined />
            </div>
            <div className={classes.nav__links}>
              <SupervisedUserCircleOutlined />
            </div>
          </Hidden>
          <div className={classes.nav__links} onClick={changeTheme}>
            {mode ? <Brightness4Icon /> : <BrightnessHighIcon />}
          </div>
          <div className={`${classes.nav__links} ${classes.nav__links__specail}`}>
            <Avatar src={photoURL} onClick={logout} />
          </div>
        </Grid>
        {/*----Userinfo and options--------*/}
        <Hidden xsDown>
          <Grid item className={classes.header__userinfo} sm={2} md={3}>
            <Tooltip
              placement="left"
              TransitionComponent={Zoom}
              TransitionProps={{ timeout: 300 }}
              title={"logout"}
              arrow
            >
              <Avatar src={photoURL} onClick={logout} />
            </Tooltip>
            <Hidden smDown>
              <div className={classes.userinfo__options}>
                <AddIcon />
                <TelegramIcon />
                <Badge badgeContent={10} max={9} {...defaultProps} />

                <ArrowDropDownRoundedIcon />
              </div>
            </Hidden>
          </Grid>
        </Hidden>
      </Grid>
    </Paper>
  );
}
Example #21
Source File: ListUrls.js    From FireShort with MIT License 4 votes vote down vote up
export default function ListUrls(props) {
  const classes = useStyles();
  const history = useHistory();

  const [page, setPage] = React.useState(0);
  const [rowsPerPage, setRowsPerPage] = React.useState(10);

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event) => {
    setRowsPerPage(+event.target.value);
    setPage(0);
  };

  return (
    <Container className={classes.cardGrid} maxWidth="lg">
      <Paper className={classes.root}>
        <TableContainer className={classes.container}>
          <Table stickyHeader aria-label="sticky table">
            <TableHead>
              <TableRow>
                <TableCell
                  key="curl"
                  align="left"
                  style={{
                    minWidth: "100px",
                  }}
                >
                  Short URL
                </TableCell>
                <TableCell
                  key="action"
                  align="center"
                  style={{
                    minWidth: "100px",
                  }}
                >
                  Action
                </TableCell>
                <TableCell
                  key="lurl"
                  align="left"
                  style={{ minWidth: "100px" }}
                >
                  Long URL
                </TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {props.shortUrls
                .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                .map((card) => {
                  return (
                    <TableRow hover role="checkbox" tabIndex={-1} key={card.id}>
                      <TableCell
                        key="curl"
                        align="left"
                        style={{ minWidth: "100px" }}
                      >
                        <Tooltip title="Copy to clipboard">
                          <Button
                            startIcon={<FileCopyOutlinedIcon />}
                            onClick={() => {
                              navigator.clipboard.writeText(
                                window.location.origin + "/" + card.data.curl
                              );
                            }}
                            classes={{ label: classes.label }}
                          >
                            {card.data.curl}
                          </Button>
                        </Tooltip>
                        <Tooltip title={card.data.hits + " Hits"}>
                          <IconButton onClick={() => { props.openHits(card.data.curl) }} style={{ cursor: "pointer" }}>
                            <Badge
                              badgeContent={card.data.hits}
                              color="secondary"
                              max={Infinity}
                              showZero
                            >
                              <OpenInBrowser />
                            </Badge>
                          </IconButton>
                        </Tooltip>
                      </TableCell>
                      <TableCell
                        key="action"
                        align="right"
                        style={{ minWidth: "100px" }}
                      >
                        <ButtonGroup variant="outlined" color="default">
                          <Tooltip title="Preview link">
                            <Button
                              size="small"
                              color="primary"
                              href={card.data.lurl}
                              target="_blank"
                            >
                              <VisibilityIcon />
                            </Button>
                          </Tooltip>
                          <Tooltip title="Analytics">
                            <Button
                              size='small'
                              disabled={!card.data.track}
                              onClick={() => history.push(`/analytics/${card.data.curl}`)}
                            >
                              <AnalyticsIcon />
                            </Button>
                          </Tooltip>
                          <Tooltip title="Edit link">
                            <Button
                              size="small"
                              onClick={() =>
                                props.handleEditShortUrl(card.data.curl)
                              }
                            >
                              <EditIcon />
                            </Button>
                          </Tooltip>
                          <Tooltip title="Delete link">
                            <Button
                              size="small"
                              color="secondary"
                              onClick={() =>
                                props.handleDeleteShortUrl(card.data.curl)
                              }
                            >
                              <DeleteForeverIcon />
                            </Button>
                          </Tooltip>
                          <Tooltip title="Toggle link protection">
                            <Button
                              size="small"
                              color="default"
                              onClick={() => props.toggleSecurity(card.data.curl)}
                            >
                              {card.data.locked ? <LockIcon /> : <LockOpenIcon />}
                            </Button>
                          </Tooltip>
                        </ButtonGroup>
                      </TableCell>
                      <TableCell
                        key="lurl"
                        align="left"
                        style={{ minWidth: "100px" }}
                      >
                        <Box
                          bgcolor="text.primary"
                          color="background.paper"
                          p={2}
                          style={{
                            overflowX: "auto",
                            overflowY: "hidden",
                            whiteSpace: "nowrap",
                          }}
                        >
                          {card.data.lurl}
                        </Box>
                      </TableCell>

                    </TableRow>
                  );
                })}
            </TableBody>
          </Table>
        </TableContainer>
        <TablePagination
          rowsPerPageOptions={[10, 25, 100]}
          component="div"
          count={props.shortUrls.length}
          rowsPerPage={rowsPerPage}
          page={page}
          onChangePage={handleChangePage}
          onChangeRowsPerPage={handleChangeRowsPerPage}
        />
      </Paper>
    </Container>
  );
}
Example #22
Source File: nav-menu.spec.js    From horondi_admin with MIT License 4 votes vote down vote up
describe('Nav menu test', () => {
  const useDispatchMock = jest.spyOn(reactRedux, 'useDispatch');
  const mockHandleDrawerToggle = jest.fn();
  let wrapper;

  beforeEach(() => {
    useDispatchMock.mockReturnValue(mockHandleDrawerToggle);
    wrapper = mount(
      <Router>
        <NavMenu width={mockWidth} />
      </Router>
    );
  });

  afterEach(() => {
    wrapper.unmount();
  });

  it('Should render component', () => {
    expect(wrapper).toBeDefined();
  });

  it('Should render Drawer', () => {
    expect(wrapper.exists(Drawer)).toBe(true);
  });

  it('Should render Divider component', () => {
    expect(wrapper.exists(Divider)).toBe(true);
  });

  it('Should render List component', () => {
    expect(wrapper.exists(List)).toBe(true);
  });

  it('Should render ListItem component', () => {
    expect(wrapper.exists(ListItem)).toBe(true);
  });

  it('Should render ListItemIcon component', () => {
    expect(wrapper.exists(ListItemIcon)).toBe(true);
  });

  it('Should render Collapse component', () => {
    expect(wrapper.exists(Collapse)).toBe(true);
  });

  it('Should render ListItemText component and it should be string', () => {
    expect(typeof wrapper.find(ListItemText).at(0).text()).toBe('string');
  });

  it('Should render Badge component for Запитання покупців item', () => {
    wrapper.find(ListItemText).at(0).text() === clientsQuestions &&
      expect(wrapper.exists(Badge)).toBe(true);
  });

  it("Should be text 'Домашня сторінка'", () => {
    expect(wrapper.find(ListItemText).at(0).text()).toBe(homePage);
  });

  it('Should render ExpandLess when click on Клієнти', () => {
    wrapper.find(ListItem).at(8).invoke('onClick')();
    expect(wrapper.exists(ExpandLess)).toBe(true);
  });

  it('Should render ExpandLess when click on Каталог', () => {
    wrapper.find(ListItem).at(9).invoke('onClick')();
    expect(wrapper.exists(ExpandLess)).toBe(true);
  });

  it('Should render ExpandLess when click on Сертифікати', () => {
    wrapper.find(ListItem).at(10).invoke('onClick')();
    expect(wrapper.exists(ExpandLess)).toBe(true);
  });

  it('Should render ExpandLess when click on Конструктор', () => {
    wrapper.find(ListItem).at(11).invoke('onClick')();
    expect(wrapper.exists(ExpandLess)).toBe(true);
  });

  it('Should render ExpandLess when click on Статичні сторінки', () => {
    wrapper.find(ListItem).at(11).invoke('onClick')();
    expect(wrapper.exists(ExpandLess)).toBe(true);
  });

  it('Should render ExpandMore by default', () => {
    expect(wrapper.exists(ExpandMore)).toBe(true);
  });

  it('Should handle click on ListItem component', () => {
    wrapper.find(ListItem).at(0).invoke('onClick')();
    expect(mockHandleDrawerToggle).toHaveBeenCalledTimes(2);
  });
  it('Should handle close Drawer', () => {
    wrapper.find(Drawer).prop('onClose')();
    expect(mockHandleDrawerToggle).toHaveBeenCalledTimes(1);
  });
});
Example #23
Source File: OftadehAppBar.jsx    From oftadeh-react-admin with MIT License 4 votes vote down vote up
OftadehAppBar = (props) => {
  const classes = useStyles(props);
  const { open, handleDrawerToggle, handleRightPanelOpen } = React.useContext(
    NavigationContext
  );

  const { setThemeName, curThemeName } = React.useContext(ThemeContext);

  return (
    <AppBar
      position="fixed"
      className={clsx(classes.appBar, {
        [classes.appBarShift]: open,
      })}
    >
      <Toolbar>
        <IconButton
          color="inherit"
          aria-label="open drawer"
          onClick={handleDrawerToggle}
          edge="start"
          className={classes.menuButton}
        >
          <MenuIcon />
        </IconButton>
        <div className={classes.search}>
          <div className={classes.searchIcon}>
            <SearchIcon />
          </div>
          <InputBase
            placeholder="Search…"
            classes={{
              root: classes.inputRoot,
              input: classes.inputInput,
            }}
            inputProps={{ "aria-label": "search" }}
          />
        </div>
        <div className={classes.grow} />
        <div className={classes.appbarSection}>
          <IconButton
            aria-haspopup="true"
            onClick={() =>
              curThemeName === "dark"
                ? setThemeName("light")
                : setThemeName("dark")
            }
            color="inherit"
          >
            {curThemeName === "dark" ? (
              <Brightness7Icon />
            ) : (
              <Brightness4Icon />
            )}
          </IconButton>
          <div className={classes.appbarToday}>
            <IconButton
              aria-haspopup="true"
              onClick={(event) => handleRightPanelOpen(event, 0)}
              color="inherit"
            >
              <TodayIcon />
            </IconButton>
            <IconButton
              aria-haspopup="true"
              onClick={(event) => handleRightPanelOpen(event, 2)}
              aria-label="show 4 new messages"
              color="inherit"
            >
              <Badge badgeContent={4} color="secondary">
                <MailIcon />
              </Badge>
            </IconButton>
          </div>
          <IconButton
            aria-haspopup="true"
            onClick={(event) => handleRightPanelOpen(event, 1)}
            aria-label="show 17 new notifications"
            color="inherit"
          >
            <Badge badgeContent={17} color="secondary">
              <NotificationsIcon />
            </Badge>
          </IconButton>
          <OftadehAvatarMenu />
        </div>
      </Toolbar>
    </AppBar>
  );
}
Example #24
Source File: products-filters-container.js    From horondi_admin with MIT License 4 votes vote down vote up
ProductsFiltersContainer = ({
  buttonName,
  labels,
  productFilter,
  list,
  filterHandler,
  clearFilter
}) => {
  const styles = useStyles();
  const { filters } = useSelector(({ Products }) => ({
    filters: Products.filters
  }));
  const { categoryFilter } = filters;

  const formGroupOptions = list.map((item, idx) => {
    const condition = item._id || item;
    return (
      <MenuItem key={condition} value={condition}>
        <Checkbox
          size='small'
          checked={!!productFilter.find((filter) => filter === condition)}
        />
        <ListItemText
          primary={labels.length ? labels[idx] : item}
          className={styles.menuItems}
        />
      </MenuItem>
    );
  });

  const renderFilters = useMemo(
    () => (selected) =>
      buttonName === CATEGORIES
        ? list
            .filter(({ _id }) =>
              categoryFilter.some((category) => category === _id)
            )
            .map(({ name }) => name[0].value)
            .join(', ')
        : selected.join(', '),
    [categoryFilter, list, buttonName]
  );

  return (
    <Grid
      item
      xs={12}
      sm={6}
      md={6}
      lg={3}
      container
      alignItems='center'
      className={styles.container}
    >
      <Badge
        badgeContent={productFilter.length}
        color='error'
        anchorOrigin={badgePosition}
        className={styles.badge}
      >
        {productFilter.length ? (
          <Tooltip title={deleteFilter}>
            <RemoveCircleOutlineIcon
              onClick={clearFilter}
              color='error'
              className={styles.filterIcon}
            />
          </Tooltip>
        ) : null}
        <FormControl className={styles.formControl}>
          <InputLabel id='multiple-checkbox-label'>{buttonName}</InputLabel>
          <Select
            labelId='multiple-checkbox-label'
            id='multiple-checkbox'
            multiple
            MenuProps={MenuProps}
            value={productFilter}
            onChange={filterHandler}
            input={<Input />}
            renderValue={renderFilters}
            className={styles.menuItems}
          >
            {formGroupOptions}
          </Select>
        </FormControl>
      </Badge>
    </Grid>
  );
}
Example #25
Source File: product-options-container.js    From horondi_admin with MIT License 4 votes vote down vote up
ProductOptionsContainer = ({
  selectedOptions,
  setOptions,
  additions,
  toggleFieldsChanged
}) => {
  const styles = useStyles();
  const productOptions = useSelector(({ Products }) => Products.productOptions);
  const { sizes, bottomMaterials } = productOptions;

  const handleOptionChange = (event, name) => {
    toggleFieldsChanged(true);
    setOptions({ ...selectedOptions, [name]: event.target.value });
  };

  const handleAdditionChange = (event) => {
    toggleFieldsChanged(true);
    const { name, checked } = event.target;
    setOptions({ ...selectedOptions, [name]: checked });
  };

  const handleDeleteOption = (option, name) => {
    toggleFieldsChanged(true);
    const currentOption = selectedOptions[option];
    const sizeToRemove = currentOption.indexOf(name);
    setOptions({
      ...selectedOptions,
      [option]: [
        ...currentOption.slice(0, sizeToRemove),
        ...currentOption.slice(sizeToRemove + 1)
      ]
    });
  };

  const getCardItems = (items, option, labels) =>
    items
      .filter(({ name }) =>
        selectedOptions[option].some((item) => item === name)
      )
      .map((item) => {
        const cardContent = labels.map(({ label, name }) => (
          <Typography key={name}>
            {label}: {item[name]}
          </Typography>
        ));
        const priceDetail = (
          <Typography>
            {ADDITIONAL_PRICE}: {item.additionalPrice[0].value / 100}
          </Typography>
        );

        return (
          <Grid item key={item.name}>
            <Card>
              <CardContent>
                <Grid container justify='flex-end'>
                  <Tooltip title={DELETE_PRODUCT_BTN} placement='top'>
                    <IconButton
                      className={styles.removeIcon}
                      onClick={() => handleDeleteOption(option, item.name)}
                    >
                      <CloseIcon />
                    </IconButton>
                  </Tooltip>
                </Grid>
                {cardContent}
                {priceDetail}
              </CardContent>
            </Card>
          </Grid>
        );
      });

  const getOptions = (name, _id) => (
    <MenuItem value={name} key={_id}>
      {name}
    </MenuItem>
  );

  const sortSizes = (a, b) => {
    if (a.name > b.name) {
      return -1;
    }
    if (b.name > a.name) {
      return 1;
    }
    return 0;
  };

  const sizesOptions = useMemo(
    () =>
      sizes
        .slice()
        .sort(sortSizes)
        .map(({ name, _id }) => getOptions(name, _id)),
    [sizes]
  );

  const bottomMaterialsOptions = useMemo(
    () =>
      bottomMaterials.map(({ name, _id }) => getOptions(name[0].value, _id)),
    [bottomMaterials]
  );

  const formattedMaterials = useMemo(
    () =>
      bottomMaterials.map((item) => ({ ...item, name: item.name[0].value })),
    [bottomMaterials]
  );

  const optionsToMap = useMemo(
    () => [sizesOptions, bottomMaterialsOptions],
    [sizesOptions, bottomMaterialsOptions]
  );
  const cardLabels = useMemo(() => [sizeCardsLabels, materialsLabels], []);
  const cardOptions = useMemo(
    () => [sizes, formattedMaterials],
    [sizes, formattedMaterials]
  );

  return (
    <div>
      {optionsLabels.map(({ label, name }, idx) => (
        <div key={name}>
          {!!selectedOptions[name].length && <Box mt={2.5} />}
          <Grid container className={styles.select}>
            <Grid item>
              <Badge
                color='error'
                anchorOrigin={badgePosition}
                badgeContent={selectedOptions[name].length}
              >
                <FormControl className={styles.formControl}>
                  <InputLabel id='multiple-checkbox-label'>{label}</InputLabel>
                  <Select
                    required
                    labelId='multiple-checkbox-label'
                    id='multiple-checkbox'
                    multiple
                    value={selectedOptions[name]}
                    onChange={(e) => handleOptionChange(e, name)}
                    input={<Input />}
                  >
                    {optionsToMap[idx]}
                  </Select>
                </FormControl>
              </Badge>
            </Grid>
            <Grid item container spacing={2} className={styles.gridContainer}>
              {getCardItems(cardOptions[idx], name, cardLabels[idx])}
            </Grid>
          </Grid>
        </div>
      ))}
      <Grid container className={styles.checkbox}>
        <FormControlLabel
          control={
            <Checkbox
              checked={selectedOptions.additions}
              onChange={handleAdditionChange}
              name='additions'
              color='primary'
            />
          }
          label={
            !!(additions && additions.length) && (
              <div>
                {additions[0].name[0].value}
                <span>
                  (
                  <span className={styles.additionalPrice}>
                    +{additions[0].additionalPrice[0].value / 100}
                    {` ${UAH}`}
                  </span>
                  )
                </span>
              </div>
            )
          }
        />
      </Grid>
    </div>
  );
}
Example #26
Source File: TransactionModal.js    From akashlytics-deploy with GNU General Public License v3.0 4 votes vote down vote up
export function TransactionModal({ isOpen, onConfirmTransaction, messages, onClose }) {
  const [isSendingTransaction, setIsSendingTransaction] = useState(false);
  const [tabIndex, setTabIndex] = useState(0);
  const [memo, setMemo] = useState("");
  const [showMemoWarning, setShowMemoWarning] = useState(false);
  const [customGas, setCustomGas] = useState(null); // Set once we calculate fees
  const [customFee, setCustomFee] = useState(null); // Set once we calculate fees
  const [isSettingCustomFee, setIsCustomFee] = useState(false);
  const [isCalculatingFees, setIsCalculatingFees] = useState(true);
  const [calculatedFees, setCalculatedFees] = useState(null);
  const [currentFee, setCurrentFee] = useState("average");
  const { settings } = useSettings();
  const { address, selectedWallet, refreshBalance } = useWallet();
  const classes = useStyles();
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();
  const isCustomFeeValid = customFee && parseFloat(customFee) > 0;
  const isGasValid = customGas && parseInt(customGas) > 0;

  useEffect(() => {
    (async () => {
      const client = await SigningStargateClient.connectWithSigner(settings.rpcEndpoint, selectedWallet, {
        registry: customRegistry,
        broadcastTimeoutMs: 300_000 // 5min
      });

      const gasEstimation = await client.simulate(
        address,
        messages.map((m) => m.message),
        memo
      );
      const estimatedGas = Math.round(gasEstimation * gasPaddingMultiplier);

      const fees = {
        low: calculateFee(estimatedGas, gasPrices.low),
        average: calculateFee(estimatedGas, gasPrices.average),
        high: calculateFee(estimatedGas, gasPrices.high)
      };

      setCalculatedFees(fees);
      setIsCalculatingFees(false);

      setCustomFee(uaktToAKT(fees.average.amount[0].amount));
      setCustomGas(estimatedGas);
    })();

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  async function handleSubmit(ev) {
    ev.preventDefault();
    setIsSendingTransaction(true);

    let pendingSnackbarKey = enqueueSnackbar(<Snackbar title="Broadcasting transaction..." subTitle="Please wait a few seconds" showLoading />, {
      variant: "info",
      autoHideDuration: null
    });

    try {
      // Setup client
      const client = await SigningStargateClient.connectWithSigner(settings.rpcEndpoint, selectedWallet, {
        registry: customRegistry,
        broadcastTimeoutMs: 300_000 // 5min
      });

      const fee = isSettingCustomFee ? createCustomFee(aktToUakt(customFee), customGas) : calculatedFees[currentFee];

      const response = await client.signAndBroadcast(
        address,
        messages.map((m) => m.message),
        fee,
        memo
      );
      const transactionHash = response.transactionHash;
      const isError = response.code !== 0;

      console.log(response);

      if (isError) {
        throw new BroadcastingError("Code " + response.code + " : " + response.rawLog, transactionHash);
      }

      showTransactionSnackbar("Transaction succeeds!", "", transactionHash, "success");

      await analytics.event("deploy", "successful transaction");

      refreshBalance();

      // return response message
      onConfirmTransaction(response);
    } catch (err) {
      console.error(err);

      const transactionHash = err.txHash;
      let errorMsg = "An error has occured";

      await analytics.event("deploy", "failed transaction");

      if (err.message.includes("was submitted but was not yet found on the chain")) {
        errorMsg = "Transaction timeout";
      } else {
        try {
          const reg = /Broadcasting transaction failed with code (.+?) \(codespace: (.+?)\)/i;
          const match = err.message.match(reg);
          const log = err.message.substring(err.message.indexOf("Log"), err.message.length);

          if (match) {
            const code = parseInt(match[1]);
            const codeSpace = match[2];

            if (codeSpace === "sdk") {
              const errorMessages = {
                5: "Insufficient funds",
                9: "Unknown address",
                11: "Out of gas",
                12: "Memo too large",
                13: "Insufficient fee",
                19: "Tx already in mempool",
                25: "Invalid gas adjustment"
              };

              if (code in errorMessages) {
                errorMsg = errorMessages[code];
              }
            }
          }

          if (log) {
            errorMsg += `. ${log}`;
          }
        } catch (err) {
          console.error(err);
        }
      }

      showTransactionSnackbar("Transaction has failed...", errorMsg, transactionHash, "error");

      setIsSendingTransaction(false);
    } finally {
      closeSnackbar(pendingSnackbarKey);
    }
  }

  const showTransactionSnackbar = (snackTitle, snackMessage, transactionHash, snackVariant) => {
    enqueueSnackbar(
      <Snackbar
        title={snackTitle}
        subTitle={<TransactionSnackbarContent snackMessage={snackMessage} transactionHash={transactionHash} />}
        iconVariant={snackVariant}
      />,
      {
        variant: snackVariant,
        autoHideDuration: 10000
      }
    );
  };

  const handleTabChange = (event, newValue) => {
    setTabIndex(newValue);
  };

  const onSetGasClick = (event) => {
    event.preventDefault();
    setIsCustomFee(!isSettingCustomFee);
  };

  const onMemoChange = (event) => {
    const newValue = event.target.value;
    setMemo(newValue);

    const splittedValue = (newValue || "").trim().split(" ");
    setShowMemoWarning(splittedValue.length === 12 || splittedValue.length === 24);
  };

  return (
    <Dialog
      open={isOpen}
      onClose={!isSendingTransaction && !isCalculatingFees ? onClose : null}
      maxWidth="xs"
      fullWidth
      aria-labelledby="transaction-modal"
      aria-describedby="transaction modal description"
    >
      <DialogTitle id="transaction-modal">
        <span className={classes.title}>Akash Transaction</span>
      </DialogTitle>
      <DialogContent dividers classes={{ root: classes.tabContent }}>
        <AppBar position="static" color="default">
          <Tabs
            value={tabIndex}
            onChange={handleTabChange}
            indicatorColor="primary"
            textColor="primary"
            variant="fullWidth"
            aria-label="Akash transaction data"
          >
            <Tab label="Details" {...a11yProps(`${a11yPrefix}-${0}`)} disabled={isCalculatingFees} />
            <Tab label="Data" {...a11yProps(`${a11yPrefix}-${1}`)} disabled={isCalculatingFees} />
          </Tabs>
        </AppBar>

        <TabPanel value={tabIndex} index={0} className={classes.tabPanel}>
          <Badge color="primary" badgeContent={messages.length} classes={{ badge: classes.badge }}>
            <Typography variant="h4" className={classes.label}>
              Messages
            </Typography>
          </Badge>

          <List dense className={classes.messages}>
            {messages.map(({ message }, i) => {
              return <TransactionMessage key={`message_${i}`} message={message} />;
            })}
          </List>

          <Box padding="1rem 0">
            <TextField
              label="Memo"
              disabled={isSendingTransaction}
              value={memo}
              onChange={onMemoChange}
              type="text"
              variant="outlined"
              inputProps={{
                maxLength: 256
              }}
              InputProps={{
                endAdornment: (
                  <InputAdornment position="end">
                    <Tooltip
                      classes={{ tooltip: classes.tooltip }}
                      arrow
                      title="Memo field is usually used for specifying a customer ID for certain centralized exchanges.
                      Never enter your mnemonic seed phrase / passphrase / password or anything sensitive!
                      Everything in this field becomes permanently public, accessible by anyone!"
                    >
                      {showMemoWarning ? <WarningIcon fontSize="small" color="error" /> : <HelpIcon fontSize="small" color="primary" />}
                    </Tooltip>
                  </InputAdornment>
                )
              }}
              classes={{ root: classes.fullWidth }}
            />
          </Box>

          {isCalculatingFees ? (
            <Box display="flex" alignItems="center" justifyContent="center">
              <CircularProgress size="24px" color="primary" />
            </Box>
          ) : (
            <>
              <Box>
                <ButtonGroup
                  size="large"
                  color="primary"
                  aria-label="large outlined primary button group"
                  classes={{ root: classes.fullWidth }}
                  disabled={isSettingCustomFee}
                >
                  <Button
                    disabled={isSendingTransaction}
                    classes={{ root: classes.feeButton, label: classes.feeButtonLabel }}
                    variant={currentFee === "low" ? "contained" : "outlined"}
                    onClick={() => setCurrentFee("low")}
                  >
                    <Box>Low</Box>
                    <Box>
                      <Typography variant="caption">
                        <PriceValue value={uaktToAKT(calculatedFees.low.amount[0].amount, 4)} showLt />
                      </Typography>
                    </Box>
                    <div className={clsx(classes.feeButtonLabelAmount, { [classes.textWhite]: currentFee === "low" })}>
                      {uaktToAKT(calculatedFees.low.amount[0].amount, 4)}AKT
                    </div>
                  </Button>
                  <Button
                    disabled={isSendingTransaction}
                    classes={{ root: classes.feeButton, label: classes.feeButtonLabel }}
                    variant={currentFee === "average" ? "contained" : "outlined"}
                    onClick={() => setCurrentFee("average")}
                  >
                    <Box>Avg</Box>
                    <Box>
                      <Typography variant="caption">
                        <PriceValue value={uaktToAKT(calculatedFees.average.amount[0].amount, 4)} showLt />
                      </Typography>
                    </Box>
                    <div className={clsx(classes.feeButtonLabelAmount, { [classes.textWhite]: currentFee === "average" })}>
                      {uaktToAKT(calculatedFees.average.amount[0].amount, 4)}AKT
                    </div>
                  </Button>
                  <Button
                    disabled={isSendingTransaction}
                    classes={{ root: classes.feeButton, label: classes.feeButtonLabel }}
                    variant={currentFee === "high" ? "contained" : "outlined"}
                    onClick={() => setCurrentFee("high")}
                  >
                    <Box>High</Box>
                    <Box>
                      <Typography variant="caption">
                        <PriceValue value={uaktToAKT(calculatedFees.high.amount[0].amount, 4)} showLt />
                      </Typography>
                    </Box>
                    <div className={clsx(classes.feeButtonLabelAmount, { [classes.textWhite]: currentFee === "high" })}>
                      {uaktToAKT(calculatedFees.high.amount[0].amount, 4)}AKT
                    </div>
                  </Button>
                </ButtonGroup>
              </Box>
              <Box>
                {!isSendingTransaction && (
                  <Typography className={classes.setGasLink}>
                    <Link href="#" onClick={onSetGasClick}>
                      Set custom fee
                    </Link>
                  </Typography>
                )}
                {!isSendingTransaction && isSettingCustomFee && (
                  <>
                    <Box marginBottom=".5rem">
                      <TextField
                        label="Fee (AKT)"
                        value={customFee}
                        onChange={(ev) => setCustomFee(ev.target.value)}
                        type="number"
                        variant="outlined"
                        error={!isCustomFeeValid}
                        inputProps={{
                          step: 0.001,
                          min: 0
                        }}
                        classes={{ root: classes.fullWidth }}
                      />
                    </Box>

                    <Box>
                      <TextField
                        label="Gas"
                        value={customGas}
                        onChange={(ev) => setCustomGas(ev.target.value)}
                        type="number"
                        variant="outlined"
                        error={!isGasValid}
                        inputProps={{
                          step: 1,
                          min: 1
                        }}
                        classes={{ root: classes.fullWidth }}
                      />
                    </Box>
                  </>
                )}
              </Box>
            </>
          )}
        </TabPanel>
        <TabPanel value={tabIndex} index={1} className={clsx(classes.tabPanel)}>
          <Box className={classes.messagesData}>
            {JSON.stringify(
              messages.map((m) => m.message),
              null,
              2
            )}
          </Box>
        </TabPanel>
      </DialogContent>
      <DialogActions>
        <Button variant="outlined" color="secondary" onClick={onClose} disabled={isSendingTransaction} type="button" classes={{ root: classes.actionButton }}>
          Reject
        </Button>
        <Button
          variant="contained"
          color="primary"
          onClick={handleSubmit}
          disabled={isSendingTransaction || !isGasValid || isCalculatingFees}
          classes={{ root: classes.actionButton }}
        >
          {isSendingTransaction ? <CircularProgress size="24px" color="primary" /> : "Approve"}
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #27
Source File: nav-menu.js    From horondi_admin with MIT License 4 votes vote down vote up
NavMenu = ({ width }) => {
  const classes = useStyles();
  const dispatch = useDispatch();

  const [navbarTab, setNavbarTab] = useState({
    clientTab: false,
    catalogTab: false,
    certificatesTab: false,
    constructorTab: false,
    staticTab: false,
    materialsTab: false,
    promoTab: false
  });

  const staticArray = {
    clientTab: false,
    catalogTab: false,
    certificatesTab: false,
    constructorTab: false,
    staticTab: false,
    materialsTab: false,
    promoTab: false
  };

  const { sideMenuStatus, pendingQuestionsCount } = useSelector(
    ({ Theme, EmailQuestions }) => ({
      sideMenuStatus: Theme.sideMenuStatus,
      pendingQuestionsCount: EmailQuestions.pendingCount
    })
  );

  const returnedList = (pathTitle, pathTo, PathIcon, nested) => (
    <ListItem
      onClick={() => {
        dispatch(setSideMenuStatus(!sideMenuStatus));
        dispatch(resetPagination());
        if (!nested) {
          setNavbarTab({
            ...staticArray
          });
        }
      }}
      button
      key={pathTitle}
      component={NavLink}
      to={pathTo}
      className={pathTitle === 'Слайдер' ? classes.sliderTab : nested || null}
      activeClassName={classes.selectedCategory}
      isActive={(props) => (props ? props.url === pathTo : null)}
    >
      <ListItemIcon>
        <PathIcon />
      </ListItemIcon>
      <ListItemText primary={pathTitle} />
      {pathTitle === titles.emailQuestionsTitles.mainPageTitle && (
        <Badge badgeContent={pendingQuestionsCount} color='error' />
      )}
    </ListItem>
  );

  const menuItems = config.menuCategories.map((category) =>
    returnedList(category[0], category[1], category[2])
  );

  const materialMenuItems = config.materialMenuCategories.map((category) =>
    returnedList(...category, classes.nested)
  );

  const clientMenuItems = config.clientMenuCategories.map((category) =>
    returnedList(category[0], category[1], category[2], classes.nested)
  );

  const catalogMenuItems = config.catalogMenuCategories.map((category) =>
    returnedList(category[0], category[1], category[2], classes.nested)
  );

  const promoMenuItems = config.promoMenuCategories.map((category) =>
    returnedList(...category, classes.nested)
  );

  const staticPagesMenuItems = config.staticPagesCategories.map((category) =>
    returnedList(category[0], category[1], category[2], classes.nested)
  );

  const constructorPagesMenuItems = config.constructorMenuCategories.map(
    (category) =>
      returnedList(category[0], category[1], category[2], classes.nested)
  );

  const certificatesMenuItems = config.certificatesMenuCategories.map(
    (category) =>
      returnedList(category[0], category[1], category[2], classes.nested)
  );

  const parentMenuTabsProperties = [
    [
      () =>
        setNavbarTab({
          ...staticArray,
          clientTab: !navbarTab.clientTab
        }),
      navbarTab.clientTab,
      clientMenuItems,
      MENU_TABS.CLIENTS,
      AccessibilityNewIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          catalogTab: !navbarTab.catalogTab
        }),
      navbarTab.catalogTab,
      catalogMenuItems,
      MENU_TABS.CATALOG,
      ImportContactsIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          certificatesTab: !navbarTab.certificatesTab
        }),
      navbarTab.certificatesTab,
      certificatesMenuItems,
      MENU_TABS.CERTIFICATES,
      TuneIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          promoTab: !navbarTab.promoTab
        }),
      navbarTab.promoTab,
      promoMenuItems,
      MENU_TABS.PROMOCODE,
      PromoIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          constructorTab: !navbarTab.constructorTab
        }),
      navbarTab.constructorTab,
      constructorPagesMenuItems,
      MENU_TABS.CONSTRUCTOR,
      AccessibilityNewIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          materialsTab: !navbarTab.materialsTab
        }),
      navbarTab.materialsTab,
      materialMenuItems,
      MENU_TABS.MATERIALS,
      ExtensionIcon
    ],
    [
      () =>
        setNavbarTab({
          ...staticArray,
          staticTab: !navbarTab.staticTab
        }),
      navbarTab.staticTab,
      staticPagesMenuItems,
      MENU_TABS.STATIC_PAGES,
      LayersIcon
    ]
  ];

  const parentMenuItems = parentMenuTabsProperties.map((category) => {
    const handleClick = category[0];
    const stateMenu = category[1];
    const subList = category[2];
    const primary = category[3];
    const ItemIcon = category[4];

    return (
      <Fragment key={category.toString()}>
        <ListItem button onClick={handleClick}>
          <ListItemIcon>
            <ItemIcon />
          </ListItemIcon>
          <ListItemText primary={primary} />
          {stateMenu ? <ExpandLess /> : <ExpandMore />}
        </ListItem>
        <Collapse in={stateMenu} timeout='auto' unmountOnExit>
          <List>{subList}</List>
        </Collapse>
      </Fragment>
    );
  });

  const handleDrawerToggle = () => {
    dispatch(setSideMenuStatus(!sideMenuStatus));
  };

  const checkWidth = () =>
    TEMPORARY_WIDTHS.find((element) => element === width);
  const drawerVariant = checkWidth() ? DRAWER_TEMPORARY : DRAWER_PERMANENT;

  return (
    <Drawer
      id='menuDrawer'
      className={classes.drawer}
      variant={drawerVariant}
      open={sideMenuStatus}
      onClose={handleDrawerToggle}
      classes={{
        paper: classes.drawerPaper
      }}
    >
      <div className={classes.toolbar} />
      <Divider />
      <List>
        {menuItems}
        {parentMenuItems}
      </List>
      <Divider />
    </Drawer>
  );
}
Example #28
Source File: NavAppBar.js    From yasn with MIT License 4 votes vote down vote up
export default function NavAppBar(props) {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);

  const isMenuOpen = Boolean(anchorEl);
  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

  const [mobileOpen, setMobileOpen] = React.useState(false);

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

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

  const handleMobileMenuClose = () => {
    setMobileMoreAnchorEl(null);
  };

  const handleMenuClose = () => {
    setAnchorEl(null);
    handleMobileMenuClose();
  };

  const handleMobileMenuOpen = (event) => {
    setMobileMoreAnchorEl(event.currentTarget);
  };

  const handleLogOut = () => {
    setMobileMoreAnchorEl(null);
    cookies.remove("userCookie");
    cookies.remove("userDetails");
    window.location.reload();
  };

  const menuId = "primary-search-account-menu";
  const renderMenu = (
    <Menu
      anchorEl={anchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={menuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMenuOpen}
      onClose={handleMenuClose}
    >
      <Link to={`/profile`} className={classes.link}>
        <MenuItem onClick={handleMenuClose}>Profile</MenuItem>
      </Link>
      <MenuItem onClick={handleMenuClose} onClick={handleLogOut}>
        Log Out
      </MenuItem>
    </Menu>
  );

  const mobileMenuId = "primary-search-account-menu-mobile";
  const renderMobileMenu = (
    <Menu
      anchorEl={mobileMoreAnchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={mobileMenuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMobileMenuOpen}
      onClose={handleMobileMenuClose}
    >
      <Link to="/chat" className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton aria-label="show 4 new mails" color="inherit">
            <Badge badgeContent={"ßeta"} color="secondary">
              <MailIcon />
            </Badge>
          </IconButton>
          <p>Messages</p>
        </MenuItem>
      </Link>
      <Link to="/add" className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton aria-label="show 11 new notifications" color="inherit">
            {/* <Badge badgeContent={11} color="secondary"> */}
            <PostAddIcon />
            {/* </Badge> */}
          </IconButton>
          <p>Add Post</p>
        </MenuItem>
      </Link>

      <Link to={`/profile`} className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton
            aria-label="account of current user"
            aria-controls="primary-search-account-menu"
            aria-haspopup="true"
            color="inherit"
          >
            <AccountCircle />
          </IconButton>
          <p>Profile</p>
        </MenuItem>
      </Link>
      <MenuItem onClick={handleLogOut}>
        <IconButton aria-label="show 11 new notifications" color="inherit">
          <ExitToAppIcon />
        </IconButton>
        <p>Log Out</p>
      </MenuItem>
    </Menu>
  );

  const { container } = props;

  const theme = useTheme();

  const drawer = (
    <div>
      <div className={classes.toolbar} />
      <List>
        <ListItem>
          <Typography>Browse by Category</Typography>
        </ListItem>
      </List>

      <Divider />
      <List>
        {/* <Link to="/home/Project"> */}
        <a href="/home/Project">
          <ListItem button key={"Projects"}>
            <ListItemIcon>
              <GitHubIcon />
            </ListItemIcon>
            <ListItemText primary={"Projects"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Writings"> */}
        <a href="/home/Writings">
          <ListItem button key={"Writings"}>
            <ListItemIcon>
              <CreateIcon />
            </ListItemIcon>
            <ListItemText primary={"Writings"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Artwork" onClick={handleTagLink}> */}
        <a href="/home/Artwork">
          <ListItem button key={"Artwork"}>
            <ListItemIcon>
              <GestureIcon />
            </ListItemIcon>
            <ListItemText primary={"Artwork"} />
          </ListItem>
        </a>
        {/* </Link> */}
      </List>
      <Divider />

      <List>
        {/* <Link to="/home/Music"> */}
        <a href="/home/Music">
          <ListItem button key={"Music"}>
            <ListItemIcon>
              <MusicNoteIcon />
            </ListItemIcon>
            <ListItemText primary={"Music"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Dance"> */}
        <a href="/home/Dance">
          <ListItem button key={"Dance"}>
            <ListItemIcon>
              <DirectionsWalkIcon />
            </ListItemIcon>
            <ListItemText primary={"Dance"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Other"> */}
        <a href="/home/Other">
          <ListItem button key={"Other"}>
            <ListItemIcon>
              <CallSplitIcon />
            </ListItemIcon>
            <ListItemText primary={"Other"} />
          </ListItem>
        </a>
        {/* </Link> */}
      </List>
      <Divider />
    </div>
  );

  const userCookie = cookies.get("userCookie");
  const googleToken = userCookie.Token;
  const email = userCookie.Email;

  const [searchResults, setSearchResults] = useState([]);

  const searchUsers = debounce((searchString) => {
    axios
      .get(
        `${ConnectServerUrl}/searchUsers?` +
          queryString.stringify(
            { searchString, googleToken, email },
            { withCredentials: true }
          )
      )
      .then((res) => {
        setSearchResults(res.data);
      })
      .catch(console.log);
  }, 400);

  const onSearchInputChange = (event) => {
    const searchString = event.target.value;
    if (searchString) {
      searchUsers(searchString);
    }
  };

  return (
    <div className={classes.root}>
      <CssBaseline />
      <div className={classes.grow}>
        <AppBar position="fixed" className={classes.appBar}>
          <Toolbar>
            <IconButton
              edge="start"
              className={handleDrawerToggle}
              color="inherit"
              aria-label="open drawer"
              onClick={handleDrawerToggle}
              // eslint-disable-next-line
              className={classes.menuButton}
            >
              <MenuIcon />
            </IconButton>
            <Link to="/">
              <IconButton edge="start">
                <DonutSmallIcon style={{ color: "white" }} />
              </IconButton>
            </Link>
            <Typography className={classes.title} variant="h6" noWrap>
              Connect
            </Typography>
            <div className={classes.search}>
              <div className={classes.searchIcon}>
                <SearchIcon />
              </div>
              <Autocomplete
                id="free-solo-demo"
                freeSolo
                clearOnBlur
                options={searchResults}
                className="searchBox"
                classes={{
                  root: classes.inputRoot,
                  input: classes.inputInput,
                  endAdornment: classes.endAdornment,
                }}
                getOptionLabel={(option) => option.name}
                renderOption={(option, state) => (
                  <Link to={`/user/${option.username}`}>
                    <Typography>{option.name}</Typography>
                  </Link>
                )}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    onChange={onSearchInputChange}
                    placeholder="Search DAIICTians"
                  />
                )}
              />
            </div>
            <div className={classes.grow} />
            <div className={classes.sectionDesktop}>
              <Link to="/chat">
                <IconButton aria-label="show 4 new mails" color="inherit">
                  <Badge badgeContent={"ßeta"} color="secondary">
                    <MailIcon />
                  </Badge>
                </IconButton>
              </Link>
              <Link to="/add">
                <IconButton
                  aria-label="show 17 new notifications"
                  color="inherit"
                >
                  {/* <Badge badgeContent={17} color="secondary"> */}
                  <PostAddIcon />
                  {/* </Badge> */}
                </IconButton>
              </Link>
              <IconButton
                edge="end"
                aria-label="account of current user"
                aria-controls={menuId}
                aria-haspopup="true"
                onClick={handleProfileMenuOpen}
                color="inherit"
              >
                <AccountCircle />
              </IconButton>
            </div>
            <div className={classes.sectionMobile}>
              <IconButton
                aria-label="show more"
                aria-controls={mobileMenuId}
                aria-haspopup="true"
                onClick={handleMobileMenuOpen}
                color="inherit"
              >
                <MoreIcon />
              </IconButton>
            </div>
          </Toolbar>
        </AppBar>
        {renderMobileMenu}
        {renderMenu}
      </div>
      <nav className={classes.drawer} aria-label="mailbox folders">
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === "rtl" ? "right" : "left"}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
      <main className={classes.content}>
        {props.children}
        {/* <div className={classes.toolbar} /> */}
      </main>
    </div>
  );
}
Example #29
Source File: Drawer.js    From inventory-management-web with MIT License 4 votes vote down vote up
function NavDrawer({ mobileOpen, setMobileOpen, tabletOpen }) {
  const classes = useStyles({ tab: tabletOpen });
  const theme = useTheme();
  // true if in tablet mode
  const tablet = useMediaQuery(theme.breakpoints.only('sm'));

  // links and labels for each link in drawer
  const [list, setList] = useState({
    links: ['/', '/inventory', '/transaction'],
    labels: ['Home', 'Inventory', 'Transactions'],
  });

  // function to handle drawer state on mobile
  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };
  // array of drawer icons
  const listIcons = [
    <HomeIcon className={classes.icons} />,
    <ListIcon className={classes.icons} />,
    <PersonIcon className={classes.icons} />,
    <ReceiptIcon className={classes.icons} />,
  ];

  useEffect(() => {
    // Add Admin protected links to the list only if isStaff is true
    const isAdmin = localStorage.getItem('isStaff');
    if (isAdmin === 'true') {
      setList({
        labels: ['Home', 'Inventory', 'Employees', 'Transactions'],
        links: ['/', '/inventory', '/employee', '/transaction'],
      });
    }
  }, []);

  const { expiryListBadge, setExpiryListBadge, update } = useContext(
    ExpiryListContext
  );

  const history = useHistory();

  const apiFetch = async () => {
    try {
      const response = await getEndPoint('/api/explist/', null, history);
      const { data } = response;
      setExpiryListBadge(data.count);
    } catch (e) {
      console.log(e);
    }
  };

  // call API on component load
  useEffect(() => {
    apiFetch();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [update]);

  const drawer = (
    <div>
      <List>
        {list.labels.map((text, index) => (
          <Link
            to={list.links[index]}
            className={classes.link}
            key={text}
            onClick={handleDrawerToggle}
          >
            <ListItem button key={text}>
              <ListItemIcon className={classes.listIcon}>
                <Badge
                  badgeContent={expiryListBadge}
                  color='primary'
                  overlap='circle'
                  className={classes.tabBadge}
                  invisible={!(text === 'Inventory' && !tabletOpen && tablet)}
                >
                  {listIcons[index]}
                </Badge>
              </ListItemIcon>
              <Badge
                badgeContent={expiryListBadge}
                color='primary'
                overlap='circle'
                className={classes.badge}
                invisible={text !== 'Inventory'}
              >
                <ListItemText primary={text} className={classes.listText} />
              </Badge>
            </ListItem>
          </Link>
        ))}
      </List>
    </div>
  );

  return (
    <nav className={classes.drawer}>
      <Hidden smUp>
        <Drawer
          variant='temporary'
          open={mobileOpen}
          onClose={handleDrawerToggle}
          classes={{
            paper: classes.drawerPaper,
          }}
          ModalProps={{
            keepMounted: true, // Better open performance on mobile.
          }}
        >
          <div className={classes.drawerHeader}>
            <IconButton onClick={handleDrawerToggle}>
              <ChevronLeftIcon />
            </IconButton>
          </div>
          {drawer}
        </Drawer>
      </Hidden>
      <Hidden xsDown>
        <Drawer
          classes={{
            paper: classes.drawerPaper,
          }}
          variant='permanent'
          open
        >
          <div className={classes.toolbar} />
          {drawer}
        </Drawer>
      </Hidden>
    </nav>
  );
}