@material-ui/core#Badge TypeScript 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: TabBar.tsx    From Demae with MIT License 6 votes vote down vote up
CartIcon = () => {
	const [cart] = useContext(CartContext)
	const items = cart?.items() || []
	const badgeContent = items.reduce((prev, current) => {
		return current.quantity + prev
	}, 0)
	return (
		<Badge badgeContent={badgeContent} color="secondary">
			<ShoppingCartIcon />
		</Badge>
	)
}
Example #2
Source File: ServerListItemSingle.tsx    From shadowsocks-electron with GNU General Public License v3.0 6 votes vote down vote up
StyledBadge = withStyles((theme: Theme) =>
  createStyles({
    badge: {
      right: -20,
      top: 12,
      borderRadius: 3,
      padding: '0 5',
      border: `solid 1px #8f8f8f`,
      backgroundColor: 'inherit',
      color: '#8f8f8f'
    },
  }),
)(Badge)
Example #3
Source File: StatusBarConnection.tsx    From shadowsocks-electron with GNU General Public License v3.0 6 votes vote down vote up
StyledBadge = withStyles((theme: Theme) =>
  createStyles({
    badge: {
      left: -8,
      bottom: 8,
      color: grey[500],
      backgroundColor: green[400]
    }
  }),
)(Badge)
Example #4
Source File: ReportHelpModal.tsx    From neodash with Apache License 2.0 6 votes vote down vote up
NeoReportHelpModal = ({ open, handleClose }) => {

    return (
        <Dialog maxWidth={"lg"} open={open == true} onClose={handleClose} aria-labelledby="form-dialog-title">
            <DialogTitle id="form-dialog-title">
                About Reports
                <IconButton onClick={handleClose} style={{ padding: "3px", float: "right" }}>
                    <Badge badgeContent={""} >
                        <CloseIcon />
                    </Badge>
                </IconButton>
            </DialogTitle>
            <DialogContent style={{ width: "1000px" }}>
                <DialogContentText> A report is the smallest building block of your dashboard.
                    Each report runs a single Cypher query that loads data from your database.
                    By changing the report type, different visualizations can be created for the data.
                    See the <a href="https://github.com/neo4j-labs/neodash/wiki/Reports">Documentation</a> for more on reports.
                    <br></br><br></br>
                    <table>
                        <tr>
                            <td>
                                <b>Moving Reports</b>
                                <img src='movereport.gif' style={{ width: "100%" }}></img>
                            </td>
                            <td>
                                <b>Resizing Reports</b>
                                <img src='resizereport.gif' style={{ width: "100%" }}></img>
                            </td>
                        </tr>
                    </table>


                </DialogContentText>


            </DialogContent>
        </Dialog>
    );
}
Example #5
Source File: ActionItems.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
AlertStatusButton = ({
  title,
  amount,
  icon,
  onClick,
  ...buttonProps
}: AlertStatusButtonProps) => (
  <Tooltip title={title}>
    <IconButton
      onClick={onClick}
      role="button"
      aria-hidden={false}
      {...buttonProps}
    >
      <Badge badgeContent={amount}>{icon}</Badge>
    </IconButton>
  </Tooltip>
)
Example #6
Source File: NotificationButton.tsx    From clearflask with Apache License 2.0 6 votes vote down vote up
render() {
    if (!this.props.isLoggedIn) return null;

    return (
      <Collapse
        in={!!this.props.notifications?.length}
        className={this.props.className}
      >
        <IconButton
          aria-label='Notifications'
          onClick={e => this.setState({ notificationAnchorEl: !!this.state.notificationAnchorEl ? undefined : e.currentTarget })}
        >
          <Badge
            badgeContent={this.props.notifications ? this.props.notifications.length : 0}
            color='secondary'
            variant={this.props.showCount ? 'standard' : 'dot'}
            max={999}
          >
            <NotificationsIcon fontSize='inherit' />
            <NotificationPopup
              server={this.props.server}
              anchorEl={this.state.notificationAnchorEl}
              onClose={() => this.setState({ notificationAnchorEl: undefined })}
            />
          </Badge>
        </IconButton>
      </Collapse>
    );
  }
Example #7
Source File: AttendeeChip.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
AttendeeChip = ({ user }: AttendeeChipProps) => {
  const classes = useStyles({ responseStatus: user.responseStatus });

  return (
    <Badge
      classes={{
        root: classes.responseStatus,
        badge: classes.badge,
      }}
      badgeContent={<ResponseIcon responseStatus={user.responseStatus} />}
    >
      <Chip
        size="small"
        variant="outlined"
        label={user.email}
        color="primary"
      />
    </Badge>
  );
}
Example #8
Source File: Topbar.tsx    From knests with MIT License 5 votes vote down vote up
Topbar = (props) => {
  const { className, onSidebarOpen, ...rest } = props;

  const classes = useStyles();

  const [notifications] = useState([]);

  const router = useRouter();

  const handleSignOut = () => {
    router.push('/login');
    localStorage.removeItem('token');
  };

  return (
    <AppBar
      {...rest}
      className={clsx(classes.root, className)}
    >
      <Toolbar>
        <Link href="/">
          <a >
            <img
              alt="Logo"
              src="/images/logos/logo--white.svg"
            />
          </a>
        </Link>
        <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"
            onClick={handleSignOut}
          >
            <InputIcon />
          </IconButton>
        </Hidden>
        <Hidden lgUp>
          <IconButton
            color="inherit"
            onClick={onSidebarOpen}
          >
            <MenuIcon />
          </IconButton>
        </Hidden>
      </Toolbar>
    </AppBar>
  );
}
Example #9
Source File: DashboardHeaderTitleBar.tsx    From neodash with Apache License 2.0 5 votes vote down vote up
NeoDashboardHeaderTitleBar = ({ dashboardTitle, downloadImageEnabled, onDownloadImage, open, setDashboardTitle, connection, editable, standalone, handleDrawerOpen, onConnectionModalOpen }) => {

    const [dashboardTitleText, setDashboardTitleText] = React.useState(dashboardTitle);
    const debouncedDashboardTitleUpdate = useCallback(
        debounce(setDashboardTitle, 250),
        [],
    );

    useEffect(() => {
        // Reset text to the dashboard state when the page gets reorganized.
        if (dashboardTitle !== dashboardTitleText) {
            setDashboardTitleText(dashboardTitle);
        }
    }, [dashboardTitle])


    const content = <Toolbar key={1} style={{ paddingRight: 24, minHeight: "64px", background: '#0B297D', zIndex: 1201 }}>
        {!standalone ? <IconButton
            edge="start"
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            style={
                (open) ? {
                    display: 'none',
                } : {
                    marginRight: 36,
                    marginLeft: -19,
                }
            }
        >
            <MenuIcon />
        </IconButton> : <></>}
        <InputBase
            id="center-aligned"
            style={{ textAlign: 'center', fontSize: "22px", flexGrow: 1, color: "white" }}
            placeholder="Dashboard Name..."
            fullWidth
            maxRows={4}
            value={dashboardTitleText}
            onChange={(event) => {
                if (editable) {
                    setDashboardTitleText(event.target.value);
                    debouncedDashboardTitleUpdate(event.target.value);
                }
            }}
        />
        {downloadImageEnabled ? <Tooltip title={"Download Dashboard as Image"}>
    <IconButton style={{background: "#ffffff22", padding: "3px", marginRight: "3px"}} onClick={(e) => onDownloadImage()}>
        <ImageIcon style={{ padding: 6, color: "#ffffffdd", width: "36px", height: "36px", fontSize: "1.3rem", zIndex: 5 }} fontSize="small">
        </ImageIcon>
    </IconButton>
</Tooltip> : <></>}

        <Tooltip title={connection.protocol + "://" + connection.url + ":" + connection.port} placement="left" aria-label="host">
            <IconButton style={{ background: "#ffffff22", padding: "3px" }} onClick={(e) => {
                if (!standalone) {
                    onConnectionModalOpen();
                }
            }}>
                <Badge badgeContent={""} >
                    <img style={{ width: "36px", height: "36px" }} src="neo4j-icon.png" />
                </Badge>
            </IconButton>
        </Tooltip>
    </Toolbar>;
    return content;
}
Example #10
Source File: Menu.tsx    From ra-enterprise-demo with MIT License 5 votes vote down vote up
StyledBadgeForText = withStyles(theme => ({
    badge: {
        top: 13,
        right: 13,
        border: `1px solid ${theme.palette.background.paper}`,
        padding: '0 4px',
    },
}))(Badge)
Example #11
Source File: CostInsightsNavigation.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
CostInsightsNavigation = React.memo(
  ({ alerts, products }: CostInsightsNavigationProps) => {
    const classes = useStyles();
    const { icons } = useConfig();
    const [isOpen, setOpen] = useState(false);

    const defaultNavigationItems = getDefaultNavigationItems(alerts);
    const productNavigationItems: NavigationItem[] =
      products?.map(product => ({
        title: product.name,
        navigation: product.kind,
        icon: findAlways(icons, i => i.kind === product.kind).component,
      })) ?? [];

    useEffect(
      function toggleProductMenuItems() {
        if (products?.length) {
          setOpen(true);
        } else {
          setOpen(false);
        }
      },
      [products],
    );

    return (
      <MenuList className={classes.menuList}>
        {defaultNavigationItems.map(item => (
          <NavigationMenuItem
            key={`navigation-menu-item-${item.navigation}`}
            navigation={item.navigation}
            title={item.title}
            icon={
              item.navigation === DefaultNavigation.AlertInsightsHeader ? (
                <Badge badgeContent={alerts} color="secondary">
                  {React.cloneElement(item.icon, {
                    className: classes.navigationIcon,
                  })}
                </Badge>
              ) : (
                React.cloneElement(item.icon, {
                  className: classes.navigationIcon,
                })
              )
            }
          />
        ))}
        <Collapse in={isOpen} timeout={850}>
          {productNavigationItems.map((item: NavigationItem) => (
            <NavigationMenuItem
              key={`navigation-menu-item-${item.navigation}`}
              navigation={item.navigation}
              icon={React.cloneElement(item.icon, {
                className: classes.navigationIcon,
              })}
              title={item.title}
            />
          ))}
        </Collapse>
      </MenuList>
    );
  },
)
Example #12
Source File: Header.tsx    From storefront with MIT License 5 votes vote down vote up
Header: React.VFC = () => {
  const styles = useStyles();
  const { settings } = useSettings();
  const [open, toggleOpen] = useToggle(false);

  const { data: menu } = useMenuQuery({
    variables: { location: MenuLocationEnum.PRIMARY_NAVIGATION },
  });

  const { data: { cart } = { cart: undefined } } = useCartQuery({
    fetchPolicy: 'no-cache',
    ssr: false,
  });

  return (
    <AppBar color="default" position="relative">
      <Toolbar
        className={styles.toolbar}
        sx={{
          minHeight: { xs: 60, md: 110 },
          mx: 'auto',
          width: '100%',
        }}
      >
        <Box sx={{ display: { md: 'none' }, flexGrow: 1 }}>
          <IconButton aria-label="Menu" onClick={toggleOpen}>
            <Menu />
          </IconButton>
        </Box>
        <Link href="/" underline="none">
          <Logo className={styles.logo} aria-label={settings.title} />
        </Link>
        <Box
          sx={{
            alignItems: 'center',
            alignSelf: 'stretch',
            display: 'flex',
            flexGrow: 1,
            justifyContent: 'flex-end',
          }}
        >
          <Box sx={{ display: { xs: 'none', md: 'flex' }, height: '100%' }}>
            <HeaderMenu menu={menu} />
          </Box>
          <IconButton href="/cart" color="inherit" aria-label="Cart">
            <Badge badgeContent={cart?.contents?.itemCount}>
              <Cart />
            </Badge>
          </IconButton>
        </Box>
      </Toolbar>
      <Collapse unmountOnExit in={open} timeout="auto">
        <HeaderMenu menu={menu} />
      </Collapse>
    </AppBar>
  );
}
Example #13
Source File: CommentsPopper.tsx    From frontend with Apache License 2.0 5 votes vote down vote up
CommentsPopper: React.FunctionComponent<IProps> = ({
  text,
  onSave,
}) => {
  const classes = useStyles();
  const popupState = usePopupState({
    variant: "popper",
    popupId: "commentPopper",
  });
  const [comment, setComment] = React.useState("");

  React.useEffect(() => setComment(text ? text : ""), [text]);

  return (
    <React.Fragment>
      <Badge
        color="secondary"
        variant="dot"
        badgeContent=" "
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "right",
        }}
        invisible={!comment || comment === ""}
      >
        <Button {...bindToggle(popupState)} color="primary">
          Comments
        </Button>
      </Badge>
      <Popper
        {...bindPopper(popupState)}
        transition
        disablePortal
        className={classes.popperContainer}
      >
        {({ TransitionProps }) => (
          <Fade {...TransitionProps} timeout={350}>
            <Paper className={classes.contentContainer}>
              <React.Fragment>
                <TextField
                  id="comment"
                  name="comment"
                  variant="outlined"
                  value={comment}
                  placeholder={"Add any additional data here"}
                  multiline
                  rows={4}
                  rowsMax={10}
                  fullWidth
                  onChange={(event) =>
                    setComment((event.target as HTMLInputElement).value)
                  }
                  inputProps={{
                    "data-testid": "comment",
                  }}
                />
                <Button
                  onClick={() => {
                    onSave(comment).then(() => popupState.close());
                  }}
                >
                  Save
                </Button>
              </React.Fragment>
            </Paper>
          </Fade>
        )}
      </Popper>
    </React.Fragment>
  );
}
Example #14
Source File: TransactionItem.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 5 votes vote down vote up
TransactionItem: React.FC<TransactionProps> = ({ transaction }) => {
  const classes = useStyles();
  const history = useHistory();

  const showTransactionDetail = (transactionId: string) => {
    history.push(`/transaction/${transactionId}`);
  };

  return (
    <ListItem
      data-test={`transaction-item-${transaction.id}`}
      alignItems="flex-start"
      onClick={() => showTransactionDetail(transaction.id)}
    >
      <Paper className={classes.paper} elevation={0}>
        <Grid container spacing={2}>
          <Grid item>
            <ListItemAvatar>
              <Badge
                overlap="circle"
                anchorOrigin={{
                  vertical: "bottom",
                  horizontal: "right",
                }}
                badgeContent={<SmallAvatar src={transaction.receiverAvatar} />}
              >
                <Avatar src={transaction.senderAvatar} />
              </Badge>
            </ListItemAvatar>
          </Grid>
          <Grid item xs={12} sm container>
            <Grid item xs container direction="column" spacing={2}>
              <Grid item xs>
                <TransactionTitle transaction={transaction} />
                <Typography variant="body2" color="textSecondary" gutterBottom>
                  {transaction.description}
                </Typography>
                <Grid
                  container
                  direction="row"
                  justify="flex-start"
                  alignItems="flex-start"
                  spacing={1}
                  className={classes.socialStats}
                >
                  <Grid item>
                    <LikeIcon className={classes.countIcons} />
                  </Grid>
                  <Grid item>
                    <Typography data-test="transaction-like-count" className={classes.countText}>
                      {transaction.likes.length}
                    </Typography>
                  </Grid>
                  <Grid item>
                    <CommentIcon className={classes.countIcons} />
                  </Grid>
                  <Grid item>
                    <Typography data-test="transaction-comment-count" className={classes.countText}>
                      {transaction.comments.length}
                    </Typography>
                  </Grid>
                </Grid>
              </Grid>
            </Grid>
            <Grid item>
              <TransactionAmount transaction={transaction} />
            </Grid>
          </Grid>
        </Grid>
      </Paper>
    </ListItem>
  );
}
Example #15
Source File: PlayersContainer.tsx    From cards-against-formality-pwa with BSD 2-Clause "Simplified" License 5 votes vote down vote up
MobilePlayer = ({ player, isHost, isCzar, onPlayerKick, isCurrentUserHost }: any) => {
  const anchorEl = useRef<any>();
  const [isOpen, setIsOpen] = useState(false);
  if (!player) {
    return null;
  }

  function renderKick() {
    if (isHost || !isCurrentUserHost) {
      return null;
    }

    return <List>
      <ListItem style={{ padding: 0 }}>
        <Button size="small" color="secondary" onClick={() => { onPlayerKick(player?._id) }}>Kick</Button>
      </ListItem>
    </List>;
  }

  return <>
    <div className={`player ${isCzar ? 'special' : ''}`} ref={anchorEl} onClick={() => setIsOpen(prev => !prev)}>
      <Badge badgeContent={player.score} color="error">
        {player?.username}
      </Badge>
    </div>
    <Popover
      anchorEl={anchorEl.current}
      open={isHost || !isCurrentUserHost ? false : isOpen}
      onClose={() => setIsOpen(false)}
      anchorOrigin={{
        vertical: 'top',
        horizontal: 'right',
      }}
      transformOrigin={{
        vertical: 'bottom',
        horizontal: 'left',
      }}
    >
      {renderKick()}
    </Popover>
  </>
}
Example #16
Source File: index.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
Notification = () => {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
    null
  );

  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? "simple-popover" : undefined;

  const notifications: Notification[] = [
    {
      title: "a",
      subtitle: "a",
      variant: "error",
      link:
        "https://console.cloud.google.com/cloud-build/builds;region=global/f7b8fd9b-eb6e-401f-a889-73c4bf75f232?project=antler-vc",
    },
  ];

  const notificationsCount = notifications.length;
  return (
    <>
      <IconButton onClick={handleClick}>
        <Badge
          color={"primary"}
          variant="standard"
          badgeContent={notificationsCount}
        >
          <BellIcon />
        </Badge>
      </IconButton>
      <Popover
        id={id}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "center",
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "center",
        }}
      >
        <List>
          {notifications.map((notification) => (
            <ListItem>
              <ListItemAvatar>
                <Avatar>
                  <ErrorIcon />
                </Avatar>
              </ListItemAvatar>
              <ListItemText
                primary={notification.title}
                secondary={notification.subtitle}
              />
              <ListItemSecondaryAction>
                <IconButton edge="end" aria-label="delete">
                  <DeleteIcon />
                </IconButton>
              </ListItemSecondaryAction>
            </ListItem>
          ))}
        </List>
      </Popover>
    </>
  );
}
Example #17
Source File: Header.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const isLanding = !!this.props.page?.landing;

    var menu;
    if (this.props.config?.style.templates?.menu) {
      menu = (
        <TemplateLiquid
          template={this.props.config.style.templates.menu}
          customPageSlug={this.props.pageSlug}
        />
      );
    } else if (this.props.config && this.props.config.layout.menu.length > 0) {
      var currentTabValue = this.props.page
        ? this.props.page.slug
        : false;
      var tabs;
      tabs = this.props.config.layout.menu.map(menu => {
        if (!menu.pageIds || menu.pageIds.length === 0) return null;
        if (menu.pageIds.length === 1) {
          const page = this.props.config!.layout.pages.find(p => p.pageId === menu.pageIds[0]);
          if (page === undefined) return null;
          const icon = menu.icon || page.icon;
          return (
            <Tab
              key={page.slug}
              className={this.props.classes.tab}
              component={Link}
              to={`/${page.slug}`}
              value={page.slug}
              disableRipple
              label={(
                <>
                  {!!icon && (
                    <DynamicMuiIcon name={icon} />
                  )}
                  {this.props.t(menu.name || page.name as any)}
                </>
              )}
              classes={{
                root: this.props.classes.tabRoot,
                wrapper: this.props.classes.tabWrapper,
              }}
            />
          );
        }
        const dropdownItems = menu.pageIds.map(pageId => {
          const page = this.props.config!.layout.pages.find(p => p.pageId === pageId);
          if (!page) {
            return undefined;
          }
          if (this.props.page && this.props.page.pageId === page.pageId) {
            currentTabValue = menu.menuId;
          }
          return {
            name: this.props.t(page.name as any),
            val: page.slug,
            icon: page.icon,
          };
        })
          .filter(notEmpty);
        return (
          <DropdownTab
            key={menu.menuId}
            className={this.props.classes.tab}
            value={menu.menuId}
            selectedValue={this.props.page && this.props.page.slug}
            label={menu.name}
            icon={!menu.icon ? undefined : (<DynamicMuiIcon name={menu.icon} />)}
            links={dropdownItems}
            onDropdownTabSelect={value => this.props.pageChanged(value)}
          />
        );
      });
      menu = (
        <div className={this.props.classes.menu}>
          <Collapse in={!isLanding}>
            <Tabs
              // centered
              variant='standard'
              scrollButtons='off'
              classes={{
                flexContainer: this.props.classes.tabsFlexContainer,
                indicator: this.props.classes.indicator,
              }}
              value={currentTabValue}
              onChange={(event, value) => this.props.pageChanged(value)}
              indicatorColor="primary"
              textColor="primary"
            // Shorten indicator size
            // TabIndicatorProps={{ children: <span /> }}
            >
              {tabs}
            </Tabs>
          </Collapse>
        </div>
      );
    }

    var header;
    if (this.props.config?.style.templates?.header) {
      header = (
        <TemplateLiquid
          template={this.props.config.style.templates.header}
          customPageSlug={this.props.pageSlug}
        />
      );
    } else {
      const languageSelect = this.props.config?.langWhitelist?.langs.length === 0 ? undefined : (
        <LanguageSelect noFade whitelist={this.props.config?.langWhitelist?.langs} />
      );
      var rightSide;
      if (this.props.config && this.props.loggedInUser) {
        rightSide = (
          <div className={this.props.classes.actions}>
            <Collapse classes={{ wrapperInner: this.props.classes.actions }} in={!isLanding}>
              <NotificationButton
                className={this.props.classes.actionButton}
                server={this.props.server}
              />
              <IconButton
                className={this.props.classes.actionButton}
                aria-label='Account'
                component={Link}
                to='/account'
              >
                <Badge
                  color='secondary'
                  invisible={!!this.props.loggedInUser.isExternal || !!this.props.loggedInUser.name}
                  variant='dot'
                >
                  <AccountIcon fontSize='inherit' />
                </Badge>
              </IconButton>
            </Collapse>
            {languageSelect}
          </div>
        );
      } else if (this.props.config && !this.props.loggedInUser) {
        rightSide = (
          <div className={this.props.classes.actions}>
            <IconButton
              className={this.props.classes.actionButton}
              aria-label='Account'
              onClick={() => this.setState({ logInOpen: true })}
            >
              <AccountIcon fontSize='inherit' />
            </IconButton>
            <LogIn
              server={this.props.server}
              open={this.state.logInOpen}
              onClose={() => this.setState({ logInOpen: false })}
              onLoggedInAndClose={() => this.setState({ logInOpen: false })}
            />
            {/* {// TODO this should only show when Admin logged in, not mod
              this.props.server.isModOrAdminLoggedIn() && (
                <IconButton
                  className={this.props.classes.actionButton}
                  aria-label='Dashboard'
                  onClick={() => !windowIso.isSsr && windowIso.open(`https://${windowIso.parentDomain}/dashboard?projectId=${this.props.server.getProjectId()}`, '_self')}
                >
                  <SettingsIcon fontSize='inherit' />
                </IconButton>
              )} */}
            {languageSelect}
          </div>
        );
      }
      rightSide = (
        <div className={this.props.classes.actionsContainer}>
          {rightSide}
        </div>
      );

      header = (
        <div className={this.props.classes.headerSpacing}>
          <div className={this.props.classes.header}>
            <div className={this.props.classes.logoAndMenu}>
              <HeaderLogo config={this.props.config} large={isLanding} />
              {menu}
            </div>
            {rightSide}
          </div>
          {/* <Divider className={classNames(
            this.props.classes.menuDivider,
            isLanding && this.props.classes.menuDividerLanding,
          )} /> */}
        </div>
      );
    }

    return (
      <InViewObserver ref={this.inViewObserverRef} disabled={!this.props.settings.demoMenuAnimate}>
        {header}
      </InViewObserver>
    );
  }
Example #18
Source File: AvatarDisplay.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const userName = DisplayUserName(this.props.user);
    const size = this.props.size || 25;
    var avatar;
    switch (this.props.user?.pic ? 'image' : this.props.type) {
      default:
      case 'beam':
        avatar = (
          <BoringAvatar
            name={userName.replace(/ /g, '')}
            variant='beam'
            size={size}
            colors={[
              darken(this.props.theme.palette.primary.main, 0.6),
              darken(this.props.theme.palette.primary.main, 0.3),
              this.props.theme.palette.primary.main,
              lighten(this.props.theme.palette.primary.main, 0.3),
              lighten(this.props.theme.palette.primary.main, 0.6),
            ]}
          />
        );
        break;
      case 'bauhaus':
        avatar = (
          <BoringAvatar
            name={userName.replace(/ /g, '')}
            variant='bauhaus'
            size={size}
            colors={[
              this.props.theme.palette.primary.dark,
              this.props.theme.palette.primary.light,
              lighten(this.props.theme.palette.primary.main, 0.6),
              lighten(this.props.theme.palette.primary.main, 0.8),
            ]}
          />
        );
        break;
      case 'image':
      case 'initials':
        var backgroundColor;
        if (!this.props.user?.pic) {
          backgroundColor = DeterministicColorFromUser(this.props.user);
          backgroundColor = !backgroundColor ? undefined
            : (this.props.theme.palette.type === 'dark'
              ? darken(backgroundColor, 0.5)
              : lighten(backgroundColor, 0.5));
        }
        avatar = (
          <MuiAvatar
            variant='circle'
            className={classNames(this.props.classes.muiAvatar)}
            style={{
              width: size,
              height: size,
              backgroundColor: backgroundColor,
            }}
            alt={userName}
            src={this.props.user?.pic}
          >{Initial(this.props.user)}</MuiAvatar>
        );
        break;
    }
    if (this.props.user?.isMod) {
      const modSize = size * 0.5;
      const starSize = size * 0.6;
      avatar = (
        <Badge
          classes={{
            root: this.props.classes.backgroundColor,
            badge: classNames(this.props.classes.badge, this.props.classes.backgroundColor),
          }}
          overlap='circle'
          anchorOrigin={{
            vertical: 'bottom',
            horizontal: 'right',
          }}
          badgeContent={(
            <MuiAvatar alt='Moderator' className={classNames(this.props.classes.backgroundColor)} style={{
              width: modSize,
              height: modSize,
              fontSize: starSize,
            }}>
              <StarIcon className={this.props.classes.modAvatar} fontSize='inherit' color='primary' />
            </MuiAvatar>
          )}
        >
          {avatar}
        </Badge>
      );
    }
    return avatar;
  }
Example #19
Source File: Menu.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const activeSlug = [this.props.activePath, ...this.props.activeSubPath].join('/');
    return (
      <List dense component='nav' style={{ padding: '0px' }}>
        {this.props.items.map((item, index) => {
          if (item.type === 'item') {
            var component;
            var componentProps = {};
            if (item.slug !== undefined) {
              component = Link;
              componentProps = {
                to: `/dashboard/${item.slug}`,
              };
            } else if (item.ext) {
              component = MuiLink;
              componentProps = {
                href: item.ext,
                target: '_blank',
              };
            }
            const isSelected = item.slug === activeSlug;
            return (
              <ListItem
                key={`${index}-${item.slug || item.ext || 'empty'}`}
                button
                disabled={item.disabled}
                // selected={isSelected}
                onClick={this.props.onAnyClick}
                className={classNames(
                  this.props.classes.link,
                  this.props.classes.menuItem,
                  isSelected && this.props.classes.isSelected,
                )}
                component={component}
                {...componentProps}
              >
                <ListItemText style={paddingForLevel(item.offset)} primary={(
                  <>
                    <span>{item.name}</span>
                    <Badge
                      color='primary'
                      variant='dot'
                      invisible={!item.hasNotification}
                    >
                      &nbsp;&nbsp;
                    </Badge>
                  </>
                )} />
              </ListItem>
            );
          } else if (item.type === 'project') {
            const activePath = !activeSlug.startsWith(item.slug) ? undefined
              : activeSlug.slice(item.slug.length)
                .split('/')
                .filter(value => value !== '')
                .map(value => /^\d+$/.test(value) ? parseInt(value) : value);
            return (
              <MenuPage
                key={`${index}-${item.page.key}`}
                overrideName={item.name}
                offset={item.offset}
                page={item.page}
                hasUnsavedChanges={item.hasUnsavedChanges}
                activePath={activePath}
                slug={item.slug}
                onAnyClick={this.props.onAnyClick}
              />
            );
          } else if (item.type === 'heading') {
            return (
              <ListItem
                key={`${index}-${item.text}`}
                disabled
                className={this.props.classes.menuItem}
              >
                <ListItemText style={paddingForLevel(item.offset)} primary={(
                  <>
                    {item.text}
                    <Badge
                      color='primary'
                      variant='dot'
                      invisible={!item.hasUnsavedChanges}
                    >
                      &nbsp;&nbsp;
                    </Badge>
                  </>
                )} />
              </ListItem>
            );
          } else {
            return null;
          }
        })}
      </List>
    );
  }
Example #20
Source File: Menu.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const hasChildren = this.props.page.getChildren().pages.filter(p => !p.hide).some(p => !!p.value)
      || this.props.page.getChildren().groups.filter(p => !p.hide).some(p => !!p.value);
    const autoExpandLevel = 0; // Disabled for now
    const expandedDontShow = !hasChildren || this.props.page.path.length < autoExpandLevel;
    const expanded = expandedDontShow
      || (this.state.expanded !== undefined
        ? this.state.expanded
        : this.isSelectedOrParent(this.props.page.path));
    const padding = paddingForLevel(this.props.offset || 0);
    const color = this.props.page.getColor();
    const { classes, ...menuProps } = this.props;
    const isSelected = this.isSelected(this.props.page.path);
    return (
      <Collapse in={this.props.page.required || this.props.page.value === true} timeout="auto" mountOnEnter unmountOnExit>
        <ListItem
          // selected={isSelected}
          className={classNames(
            this.props.classes.menuItem,
            isSelected && this.props.classes.isSelected,
          )}
          button
          component={Link}
          to={`/dashboard/${[this.props.slug, ...this.props.page.path].join('/')}`}
          onClick={() => {
            this.props.onAnyClick && this.props.onAnyClick();
            if (!this.state.expanded) {
              this.setState({ expanded: true });
            }
          }}
        >
          <ListItemText style={padding} primary={(
            <>
              <span className={this.props.classes.text} style={{ color }}>
                {!expandedDontShow && (
                  <ExpandIcon
                    IconButtonProps={{
                      className: this.props.classes.expandButton,
                      onClick: e => {
                        e.preventDefault();
                        e.stopPropagation();
                        this.setState({ expanded: !this.state.expanded });
                      },
                    }}
                    IconProps={{
                      fontSize: 'inherit',
                    }}
                    expanded={expanded}
                  />
                )}
                {this.props.overrideName !== undefined ? this.props.overrideName : this.props.t(this.props.page.getDynamicName() as any)}
              </span>
              {this.props.hasUnsavedChanges && (
                <Badge
                  variant='dot'
                  color='primary'
                >
                  &nbsp;&nbsp;
                </Badge>
              )}
            </>
          )} />
        </ListItem>
        <Collapse in={expanded} timeout="auto" mountOnEnter unmountOnExit>
          {this.props.page.getChildren().all
            .map(child => {
              if (child.hide) return null;
              switch (child.type) {
                case ConfigEditor.PageType:
                  return (<MenuPage
                    {...menuProps}
                    key={child.key}
                    offset={(this.props.offset || 0) + 1}
                    overrideName={undefined}
                    hasUnsavedChanges={false}
                    page={child}
                  />);
                case ConfigEditor.PageGroupType:
                  return (<MenuPageGroup
                    {...menuProps}
                    key={child.key}
                    offset={(this.props.offset || 0) + 1}
                    pageGroup={child}
                  />);
                default:
                  return null;
              }
            })}
        </Collapse>
      </Collapse>
    );
  }
Example #21
Source File: index.tsx    From uno-game with MIT License 4 votes vote down vote up
Chat: React.FC = () => {
	const classes = useStyles()
	const socket = useSocket()
	const socketStore = useSocketStore()
	const backButton = useBackButton()

	const [drawerOpened, setDrawerOpened] = useState(false)
	const [content, setContent] = useState("")
	const [notSeenMessagesCount, setNotSeenMessagesCount] = useState(0)

	const messageContainerRef = useRef<HTMLElement>(null)

	const chatId = socketStore.game?.chatId
	const chat = socket.getChat(chatId)

	const scrollChatToBottom = () => {
		if (messageContainerRef.current) {
			messageContainerRef.current.scroll(0, messageContainerRef.current?.scrollHeight)
		}
	}

	const resetNotSeenMessagesCount = () => {
		setNotSeenMessagesCount(0)
	}

	const handleCloseChat = () => {
		resetNotSeenMessagesCount()

		setDrawerOpened(false)
	}

	const handleOpenChat = () => {
		setDrawerOpened(true)

		/**
		 * Workaround to delay this function calling,
		 * in order to make it to be called after the drawer opens
		 */
		setTimeout(() => scrollChatToBottom(), 0)

		if (DeviceUtil.isMobile) {
			backButton.handleBackButton(
				() => handleCloseChat(),
			)
		}
	}

	const handleSendChatMessage = () => {
		if (!content || !chatId) {
			return
		}

		socket.sendChatMessage(chatId, content)

		setContent("")
	}

	const increaseNotSeenMessagesCount = (amount: number) => {
		setNotSeenMessagesCount(lastState => lastState + amount)
	}

	const handleNewChatMessage = () => {
		scrollChatToBottom()

		increaseNotSeenMessagesCount(+1)
	}

	const onNewChatMessage = () => {
		socket.onNewChatMessage(() => handleNewChatMessage())
	}

	const handleChangeContent = (value: string) => {
		setContent(value)
	}

	const handleSubmit = (event: React.FormEvent) => {
		event.preventDefault()

		handleSendChatMessage()
	}

	const onInputFocus = () => {
		backButton.setActive(false)
	}

	const onInputBlur = () => {
		backButton.setActive(true)
	}

	useDidMount(() => {
		onNewChatMessage()
	})

	return (
		<>
			{chat && (
				<Grid
					className={classes.openChatButtonContainer}
				>
					<IconButton
						onClick={handleOpenChat}
						className={classes.chatIcon}
					>
						<Badge
							badgeContent={notSeenMessagesCount}
							color="primary"
						>
							<ChatIcon />
						</Badge>
					</IconButton>
				</Grid>
			)}

			<Drawer
				open={drawerOpened}
				onClose={handleCloseChat}
				anchor="right"
				PaperProps={{
					className: classes.drawerPaper,
				}}
				className={classes.drawer}
			>
				<Grid
					container
					alignItems="center"
					className={classes.drawerHeaderContainer}
				>
					<IconButton
						onClick={handleCloseChat}
						size="medium"
						color="primary"
					>
						<GoBackIcon />
					</IconButton>

					<Typography
						variant="h6"
					>
						Chat
					</Typography>
				</Grid>

				<Grid
					className={classes.drawerBodyContainer}
					innerRef={messageContainerRef}
				>
					{chat?.messages?.map((message, index) => (
						<React.Fragment key={index}>
							<Typography
								variant="body1"
							>
								<b>{message.playerName}:</b> {message.content}
							</Typography>

							<Divider orientation="horizontal" size={1} />
						</React.Fragment>
					))}
				</Grid>

				<Grid
					component="form"
					container
					alignItems="center"
					className={classes.drawerFooterContainer}
					onSubmit={handleSubmit}
				>
					<TextField
						value={content}
						onChange={({ target }) => handleChangeContent(target.value)}
						placeholder="Type something..."
						variant="outlined"
						className={classes.messageInput}
						size="small"
						onFocus={() => onInputFocus()}
						onBlur={() => onInputBlur()}
					/>

					<IconButton
						size="medium"
						onClick={handleSendChatMessage}
						color="primary"
					>
						<SendIcon />
					</IconButton>
				</Grid>

			</Drawer>
		</>
	)
}
Example #22
Source File: UserMenu.tsx    From firetable with Apache License 2.0 4 votes vote down vote up
export default function UserMenu(props: IconButtonProps) {
  const classes = useStyles();

  const anchorEl = useRef<HTMLButtonElement>(null);
  const [open, setOpen] = useState(false);
  const [themeSubMenu, setThemeSubMenu] = useState<EventTarget | null>(null);
  const [latestUpdate] = useLatestUpdateState<null | Record<string, any>>();

  const {
    currentUser,
    userDoc,
    theme,
    themeOverridden,
    setTheme,
    setThemeOverridden,
  } = useAppContext();
  if (!currentUser || !userDoc || !userDoc?.state?.doc)
    return <div className={classes.spacer} />;

  const displayName = userDoc?.state?.doc?.user?.displayName;
  const avatarUrl = userDoc?.state?.doc?.user?.photoURL;
  const email = userDoc?.state?.doc?.user?.email;

  const avatar = avatarUrl ? (
    <Avatar src={avatarUrl} className={classes.avatar} />
  ) : (
    <AccountCircleIcon color="secondary" />
  );

  const changeTheme = (option: "system" | "light" | "dark") => {
    switch (option) {
      case "system":
        setThemeOverridden(false);
        return;

      case "light":
        setTheme("light");
        break;

      case "dark":
        setTheme("dark");
        break;

      default:
        break;
    }
    setThemeOverridden(true);
  };

  return (
    <>
      <IconButton
        aria-label="Open user menu"
        aria-controls="user-menu"
        aria-haspopup="true"
        edge="end"
        {...props}
        ref={anchorEl}
        onClick={() => setOpen(true)}
        className={classes.iconButton}
      >
        {latestUpdate?.tag_name > "v" + meta.version ? (
          <Badge color="primary" overlap="circular" variant="dot">
            {avatar}
          </Badge>
        ) : (
          avatar
        )}
      </IconButton>

      <Menu
        anchorEl={anchorEl.current}
        id="user-menu"
        keepMounted
        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
        getContentAnchorEl={null}
        transformOrigin={{ vertical: "top", horizontal: "right" }}
        open={open}
        onClose={() => setOpen(false)}
        classes={{ paper: classes.paper }}
      >
        <MenuItem
          component="a"
          href={`https://console.firebase.google.com/project/${projectId}/firestore/data/~2F_FT_USERS~2F${currentUser.uid}`}
          target="_blank"
          rel="noopener"
        >
          <ListItemAvatar>{avatar}</ListItemAvatar>
          <ListItemText primary={displayName} secondary={email} />
        </MenuItem>

        <Divider className={classes.divider} />

        <MenuItem onClick={(e) => setThemeSubMenu(e.target)}>
          Theme
          <ListItemSecondaryAction className={classes.secondaryAction}>
            <ArrowRightIcon className={classes.secondaryIcon} />
          </ListItemSecondaryAction>
        </MenuItem>

        {themeSubMenu && (
          <Menu
            anchorEl={themeSubMenu as any}
            id="theme-sub-menu"
            anchorOrigin={{ vertical: "top", horizontal: "left" }}
            getContentAnchorEl={null}
            transformOrigin={{ vertical: "top", horizontal: "right" }}
            open
            onClose={() => setThemeSubMenu(null)}
            classes={{ paper: classes.subMenu }}
          >
            <MenuItem onClick={() => changeTheme("system")}>
              <ListItemIcon>{!themeOverridden && <CheckIcon />}</ListItemIcon>
              System
            </MenuItem>
            <MenuItem onClick={() => changeTheme("light")}>
              <ListItemIcon>
                {themeOverridden && theme === "light" && <CheckIcon />}
              </ListItemIcon>
              Light
            </MenuItem>
            <MenuItem onClick={() => changeTheme("dark")}>
              <ListItemIcon>
                {themeOverridden && theme === "dark" && <CheckIcon />}
              </ListItemIcon>
              Dark
            </MenuItem>
          </Menu>
        )}

        <MenuItem component={Link} to={routes.signOut}>
          Sign out
        </MenuItem>

        <Divider className={classes.divider} />

        <UpdateChecker />
      </Menu>
    </>
  );
}