@material-ui/core#Zoom JavaScript Examples

The following examples show how to use @material-ui/core#Zoom. 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: SocialIcons.js    From personal-website-react with MIT License 6 votes vote down vote up
SocialIcons = () => {
  const classes = useStyles();

  const socialItems = Resume.basics.profiles.map((socialItem) => (
    <Link
      href={socialItem.url}
      key={socialItem.network.toLowerCase()}
      target='_blank'
      rel='noopener noreferrer'
      underline='none'
      color='inherit'
    >
      <Tooltip
        title={socialItem.username}
        placement='left'
        TransitionComponent={Zoom}
      >
        <IconButton
          color='inherit'
          aria-label={socialItem.network}
          className={classes.iconButton}
        >
          <i className={`${classes.icon} ${socialItem.x_icon}`}></i>
        </IconButton>
      </Tooltip>
    </Link>
  ));

  return <div className={classes.socialIcons}>{socialItems}</div>;
}
Example #2
Source File: LogoLink.js    From personal-website-react with MIT License 6 votes vote down vote up
LogoLink = () => {
    const classes = useStyles();

    return (
        <Tooltip
            title={Resume.basics.name}
            placement="right"
            TransitionComponent={Zoom}
        >
            <Link
                variant="h6"
                href={Resume.basics.url}
                underline="none"
                color="inherit"
                noWrap
                className={classes.svg}
            >
                <Logo />
            </Link>
        </Tooltip>
    );
}
Example #3
Source File: ThemeToggle.js    From personal-website-react with MIT License 6 votes vote down vote up
ThemeToggle = () => {
    const { theme, toggleTheme } = useContext(ThemeContext);
    const classes = useStyles();

    return (
        <Tooltip
            title={"Toggle theme"}
            placement="right"
            TransitionComponent={Zoom}
        >
            <IconButton
                color="inherit"
                onClick={toggleTheme}
                aria-label={"Toggle theme"}
                className={classes.iconButton}
            >
                {theme === "light" ? (
                    <Brightness4 className={classes.icon} />
                ) : (
                    <Brightness7 className={classes.icon} />
                )}
            </IconButton>
        </Tooltip>
    );
}
Example #4
Source File: Lightbox.jsx    From archeage-tools with The Unlicense 6 votes vote down vote up
render() {
    const { image, title, caption, elevation, float } = this.props;
    const { open } = this.state;

    return (
      <>
        <Paper
          className={cn('lightbox-thumb', { [float]: Boolean(float) })}
          elevation={elevation}
        >
          <img src={image || NoImage} alt={title} onClick={this.handleOpen} />
          <Typography variant="caption">{title}</Typography>
        </Paper>
        <Dialog
          open={open}
          onClose={this.handleClose}
          maxWidth="xl"
          TransitionComponent={Zoom}
        >
          <AppBar position="static">
            <Toolbar variant="dense">
              <Typography variant="subtitle1" className="title-text">{title}</Typography>
              <IconButton color="inherit" aria-label="Close" onClick={this.handleClose}>
                <CloseIcon />
              </IconButton>
            </Toolbar>
          </AppBar>
          <DialogContent>
            <img src={image} alt={title} />
            <Typography>{caption}</Typography>
          </DialogContent>
        </Dialog>
      </>
    );
  }
Example #5
Source File: ScrollToTop.jsx    From archeage-tools with The Unlicense 6 votes vote down vote up
render() {
    const { scrollY, height } = this.state;

    return (
      <Zoom in={scrollY >= height * 0.5} unmountOnExit>
        <Fab
          color="primary"
          className="fab"
          onClick={this.handleClick}
        >
          <ExpandLessIcon />
        </Fab>
      </Zoom>
    );
  }
Example #6
Source File: index.js    From News24x7-Client with MIT License 6 votes vote down vote up
// const NavButton = styled.button`
//     align-content:center;
//     color: ${colors.BASE_BLUE};
//     background-color:white;
//     margin-right:15px;
// `;

function ScrollTop(props) {
  const { children } = props;
  const classes = useStyles();
  const trigger = useScrollTrigger({
    disableHysteresis: true,
    threshold: 100,
  });

  const handleClick = (event) => {
    const anchor = (event.target.ownerDocument || document).querySelector(
      "#back-to-top-anchor"
    );

    if (anchor) {
      anchor.scrollIntoView({ behavior: "smooth", block: "center" });
    }
  };

  return (
    <Zoom in={trigger}>
      <div onClick={handleClick} role="presentation" className={classes.root}>
        {children}
      </div>
    </Zoom>
  );
}
Example #7
Source File: Landing.js    From Portfolio with MIT License 5 votes vote down vote up
export default function Landing() {

    const classes = useStyles();
    const theme = useTheme();
    const mdDown = useMediaQuery(theme.breakpoints.down('sm'));

    return (
        <Grid container justify="center" alignItems="center" className={classes.cont}>
            <Grid item xs={12} lg={6}>
                <Typography variant={mdDown ? "h2" : "h1"}>
                    {landing.title}
                </Typography>
                <Typography variant={mdDown ? "h5" : "h4"} component="h2" className={classes.subtitle}>

                    <ReactTyped
                        strings={landing.subtitles}
                        typeSpeed={40}
                        backSpeed={50}
                        loop
                    />
                </Typography>
                <Grid container direction="row" spacing={2}>
                    {
                        professionalDetails.map(({ alt, icon, link }, i) =>
                            <Grid item key={i}>
                                <a href={link} target="_blank" rel="noopener noreferrer">
                                    <Zoom in={true} style={{ transitionDelay: `${100 * i}ms` }}>
                                        <Tooltip title={alt} placement="top">
                                            <Avatar variant="rounded" className={clsx([classes.avatar, classes[alt]])}>
                                                {icon}
                                            </Avatar>
                                        </Tooltip>
                                    </Zoom>
                                </a>
                            </Grid>
                        )
                    }
                </Grid>
            </Grid>

            <Hidden mdDown>
                <Fade in={true} style={{ transitionDelay: '100ms' }}>
                    <Grid item lg={6}>
                        <Image
                            src="/landing.svg"
                            alt="Landing"
                            width="900.94"
                            height="787"
                        />
                    </Grid>
                </Fade>
            </Hidden>
        </Grid>
    )
}
Example #8
Source File: Skills.js    From Portfolio with MIT License 5 votes vote down vote up
export default function Skills() {

    const classes = useStyles()
    const theme = useTheme()
    const mdDown = useMediaQuery(theme.breakpoints.down('md'))
    const align = mdDown ? "center" : "flex-end"
    const textAlign = mdDown ? "center" : "right"

    const animRef = useRef(null)
    const animate = useAnimate(animRef)

    return (
        <Grid container justify="center" alignItems="center" spacing={10} className={classes.cont}>
            <Grid item xs={12} lg={6} ref={animRef}>
                <Typography variant="h2" gutterBottom align="center">
                    Skills
                </Typography>
                <Hidden mdDown>
                    <Fade in={animate} style={{ transitionDelay: '100ms' }}>
                        <div>
                            <Image
                                alt="Skills"
                                src="/skill.svg"
                                width="1139"
                                height="655"
                            />
                        </div>
                    </Fade>
                </Hidden>
            </Grid>
            <Grid container item xs={12} lg={6} direction="column" spacing={1} alignItems={align}>
                {
                    Object.getOwnPropertyNames(wrappedSkills).map((title, id) =>
                        <Grid item key={id} className={classes.skobj}>
                            <Typography variant="h4" align={textAlign} gutterBottom component="p">
                                {title}
                            </Typography>
                            <Grid container item direction="row" spacing={1} justify="center">
                                {
                                    wrappedSkills[title].map(({ alt, icon }, i) =>
                                        <Grid item key={i}>
                                            <Zoom in={animate} style={{ transitionDelay: `${150 * i}ms` }}>
                                                <Tooltip title={alt.replace("_", " ")} placement="top">
                                                    <Avatar variant="rounded" className={clsx([classes.avatar, classes[alt]])}>
                                                        {icon}
                                                    </Avatar>
                                                </Tooltip>
                                            </Zoom>
                                        </Grid>
                                    )
                                }
                            </Grid>
                        </Grid>
                    )
                }
            </Grid>
        </Grid>
    )
}
Example #9
Source File: NewRequestPage.js    From app with MIT License 4 votes vote down vote up
function NewRequestPage() {
  const classes = useStyles();
  const location = useLocation();
  const qs = queryString.parse(location.search);
  const defaultValues = {
    needs: {},
    immediacy: '1',
    needFinancialAssistance: 'false',
  };

  // Append needs from query string type
  if (qs && qs.type) {
    defaultValues.needs = { [qs.type]: true };
  }

  const {
    register,
    handleSubmit,
    errors,
    watch,
    control,
    formState: { isValid, isSubmitting, dirty },
  } = useForm({
    validationSchema: requestValidationSchema,
    defaultValues,
  });

  const {
    submitRequest,
    handleLocationChange,
    requestLocation,
    requestLocationLoading,
  } = useNewRequestPage();
  const currentNeeds = watch('needs');
  const groceryPickup = currentNeeds && currentNeeds['grocery-pickup'];

  return (
    <Container maxWidth="md">
      <Helmet>
        <title>Request Assistance</title>
      </Helmet>
      <Typography variant="h5" color="textPrimary" gutterBottom>
        Request Help
      </Typography>
      <Paper className={classes.paper} data-test="request-form">
        <div className={classes.heroContent}>
          <Container maxWidth="md">
            <form onSubmit={handleSubmit(submitRequest)}>
              <Container>
                <FormGroup>
                  <Typography
                    variant="h5"
                    gutterBottom
                    className={classes.otherComments}>
                    What do you need help with?
                  </Typography>
                  {Object.keys(activeCategoryMap).map((optionKey) => (
                    <FormControlLabel
                      key={optionKey}
                      control={
                        <Checkbox
                          inputRef={register}
                          name={`needs.${optionKey}`}
                          data-test={`need-${optionKey}`}
                          defaultChecked={defaultValues.needs[optionKey]}
                        />
                      }
                      label={
                        activeCategoryMap[optionKey].inputCaption
                          ? activeCategoryMap[optionKey].inputCaption
                          : activeCategoryMap[optionKey].description
                      }
                    />
                  ))}
                </FormGroup>
                {!!errors.needs && (
                  <FormHelperText error>{errors.needs.message}</FormHelperText>
                )}

                <Typography
                  variant="h5"
                  className={classes.otherComments}
                  gutterBottom={!groceryPickup}>
                  Details
                </Typography>
                <Zoom in={groceryPickup} unmountOnExit>
                  <Typography variant="subtitle1" gutterBottom>
                    For grocery pickup, please provide the list of groceries
                    that you would like the volunteer to get. Please be as
                    specific as possible.
                  </Typography>
                </Zoom>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <TextField
                      name="otherDetails"
                      data-test="otherDetails"
                      multiline
                      placeholder="Please be as specific as possible."
                      fullWidth
                      rows="4"
                      variant="outlined"
                      inputRef={register}
                    />
                  </Grid>
                </Grid>

                {/* <Zoom in={hasFinancialComponent} unmountOnExit> */}
                <div>
                  <Divider className={classes.optionalDivider} />
                  <Typography variant="h5" gutterBottom>
                    Will you be able to pay for your items?
                  </Typography>
                  <Typography variant="body1" gutterBottom>
                    This service is free, but the items still cost money. Are
                    you able to pay for your items? If not, we will do our best
                    to match you with organizations and volunteers who can also
                    provide financial assistance.
                  </Typography>
                  <Controller
                    as={
                      <RadioGroup
                        aria-label="Need Financial Assistance"
                        component="fieldset">
                        <FormControlLabel
                          value="false"
                          control={<Radio />}
                          label="Yes, I can pay and only need help with the delivery."
                        />
                        <FormControlLabel
                          value="true"
                          control={<Radio />}
                          label="No, I need help paying for the items."
                        />
                      </RadioGroup>
                    }
                    control={control}
                    onChange={([event]) => event.target.value}
                    name="needFinancialAssistance"
                  />
                  {!!errors.needFinancialAssistance && (
                    <FormHelperText error>
                      {errors.needFinancialAssistance}
                    </FormHelperText>
                  )}
                </div>
                {/* </Zoom> */}

                <Divider className={classes.optionalDivider} />
                <Typography variant="h5" gutterBottom>
                  Immediacy of Need
                </Typography>
                <Typography variant="body1" gutterBottom>
                  Please let us know how urgently you need us to fulfill the
                  request. We will do our best to connect you with a volunteer
                  as soon as possible, however, we cannot guarantee anything
                  because we are dependent on volunteer availability.
                </Typography>
                <Controller
                  as={
                    <RadioGroup>
                      <FormControlLabel
                        value="1"
                        control={<Radio />}
                        label="Low"
                      />
                      <FormControlLabel
                        value="5"
                        control={<Radio />}
                        label="Medium - Not very urgent"
                      />
                      <FormControlLabel
                        value="10"
                        control={<Radio />}
                        label="High - Urgent"
                      />
                    </RadioGroup>
                  }
                  control={control}
                  name="immediacy"
                />

                {!!errors.immediacy && (
                  <FormHelperText error>
                    {errors.immediacy.message}
                  </FormHelperText>
                )}

                <Divider className={classes.optionalDivider} />
                <Typography variant="h5" gutterBottom>
                  Your Location
                </Typography>
                <Typography className={classes.intro}>
                  A rough location is needed to allow us to efficiently and
                  quickly find a match for your need. You can do this in three
                  ways: by entering your address in the address field, by
                  clicking the &quot;Detect Location&quot; button, or by
                  clicking on the map. If you decide to enter the address, we
                  will not save the actual address and instead use it to get the
                  location.
                </Typography>
                <Grid container spacing={3}>
                  <Grid item xs={12}>
                    <Card>
                      {requestLocationLoading ? (
                        <LoadingSpinner />
                      ) : (
                        <ClickableMap
                          locationInfo={requestLocation}
                          onLocationChange={handleLocationChange}
                        />
                      )}
                    </Card>
                  </Grid>
                </Grid>
                <Divider className={classes.optionalDivider} />
                <Typography variant="h5" gutterBottom>
                  Contact Information
                </Typography>
                <Typography gutterBottom>
                  To minimize exposing your contact information, we do not
                  display it unless a volunteer specifically requests to see it.
                  To further discourage any abuse, we do not display your last
                  name and also keep track of all the volunteers who have looked
                  up your contact information.
                </Typography>

                <Grid container spacing={2}>
                  <Grid item xs={12} sm={6}>
                    <TextField
                      name="firstName"
                      data-test="firstName"
                      type="text"
                      label="First Name"
                      variant="outlined"
                      inputRef={register}
                      error={!!errors.firstName}
                      fullWidth
                      helperText={errors?.firstName?.message}
                    />
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <TextField
                      name="lastName"
                      data-test="lastName"
                      type="text"
                      label="Last Name"
                      variant="outlined"
                      fullWidth
                      inputRef={register}
                      error={!!errors.lastName}
                      helperText={errors?.firstName?.message}
                    />
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <TextField
                      name="phone"
                      data-test="phone"
                      type="text"
                      label="Phone Number"
                      variant="outlined"
                      fullWidth
                      inputRef={register}
                      error={!!errors.phone}
                      helperText={errors?.phone?.message}
                    />
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <TextField
                      name="email"
                      type="text"
                      data-test="email"
                      label="Email"
                      variant="outlined"
                      fullWidth
                      inputRef={register}
                      error={!!errors.email}
                      helperText={errors?.email?.message}
                    />
                  </Grid>
                </Grid>

                <Typography className={classes.warrantyInfo}>
                  Note: This website and all related work products are provided
                  &quot;AS IS&quot;. The provider of this service makes no other
                  warranties, express or implied, and hereby disclaims all
                  implied warranties, including any warranty of merchantability
                  and warranty of fitness for a particular purpose.
                </Typography>

                {dirty && !!Object.keys(errors).length && !isValid && (
                  <Typography variant="body2" className={classes.errorText}>
                    Please fix the errors above.
                  </Typography>
                )}

                <div className={classes.buttons}>
                  <Button
                    type="submit"
                    variant="contained"
                    color="primary"
                    data-test="submit-request"
                    disabled={isSubmitting}>
                    Submit Request
                  </Button>
                </div>
              </Container>
            </form>
          </Container>
        </div>
      </Paper>
    </Container>
  );
}
Example #10
Source File: Mounts.jsx    From archeage-tools with The Unlicense 4 votes vote down vote up
render() {
    const { search, mountType, obtainTypes, speed, order, orderBy } = this.state;
    const {
      match: { params: { mount } },
      displayGrid,
      setDisplayGrid,
      onlyObtainable,
      setOnlyObtainable,
      mobile,
    } = this.props;
    const { mounts: mountData, types, mountObtainTypes } = this.props;

    if (!mount) {
      setTitle('Mounts');
    }

    const mounts = Object.entries(mountData).filter(([, mountList]) => {
      const [mount] = mountList;
      const mountObtain = MOUNT_OBTAIN.find(m => m.name === mount.name);
      if (search.length > 2 && mount.name.toLowerCase().indexOf(search.toLowerCase()) === -1 && pathOr('', ['itemName'])(mountObtain).toLowerCase().indexOf(search.toLowerCase()) === -1) {
        return false;
      }

      if (mountType > 0 && !mount.typeIds.includes(mountType)) {
        return false;
      }

      if (obtainTypes.length && !mount.obtainIds.some(r => obtainTypes.includes(r))) {
        return false;
      }

      if (speed > 0 && Number.parseFloat(mount.moveSpeed) !== Number.parseFloat(speed)) {
        return false;
      }

      return !(onlyObtainable && mount.obtainIds.length === 0);
    }).sort(([, x], [, y]) => {
      const [a] = x;
      const [b] = y;
      if (displayGrid) {
        if (a.moveSpeed === b.moveSpeed) {
          return this.sort(a.name.toLowerCase(), b.name.toLowerCase());
        } else {
          if (a.moveSpeed === 0) return 1;
          if (b.moveSpeed === 0) return -1;
          return a.moveSpeed - b.moveSpeed;
        }
      } else {
        const f = orderBy === 'name' ? 'moveSpeed' : 'name';

        if (a[orderBy] === b[orderBy]) {
          if (f === 'name') {
            return this.sort(a.name.toLowerCase(), b.name.toLowerCase());
          } else {
            if (a[f] === 0) return 1;
            if (b[f] === 0) return -1;
            return a[f] - b[f];
          }
        } else {
          let sort;
          if (orderBy === 'name') {
            sort = this.sort(a.name.toLowerCase(), b.name.toLowerCase());
          } else if (a.moveSpeed === 0) {
            sort = 1;
          } else if (b.moveSpeed === 0) {
            sort = -1;
          } else {
            sort = a.moveSpeed - b.moveSpeed;
          }
          return sort * (order !== 'asc' ? -1 : 1);
        }
      }
    });

    return (
      <>
        <Paper className="section">
          <AppBar position="static">
            <Toolbar>
              <Typography variant="h5" className="title-text">Mounts</Typography>
              <Tabs
                value={Number(!displayGrid)}
                indicatorColor="secondary"
                onChange={(e, value) => setDisplayGrid(Boolean(!value))}
              >
                <Tooltip title="Grid View">
                  <Tab icon={<AppsIcon />} aria-label="grid" />
                </Tooltip>
                <Tooltip title="List View">
                  <Tab icon={<ListIcon />} aria-label="list" />
                </Tooltip>
              </Tabs>
            </Toolbar>
          </AppBar>
          <div className="mount-filters">
            <TextField
              label="Search"
              className="mount-search"
              value={search}
              onChange={this.setSearch}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <SearchIcon />
                  </InputAdornment>
                ),
                endAdornment: (
                  <InputAdornment position="end">
                    <Tooltip title="Clear">
                      <CancelIcon className="clear-input" onClick={() => this.setSearch({ target: { value: '' } })} />
                    </Tooltip>
                  </InputAdornment>
                ),
              }}
            />
            <SelectField
              id="mount-type"
              label="Mount Type"
              value={mountType}
              options={{ 0: 'All', ...types }}
              onChange={this.setType}
              renderValue={(v) => (v === 0) ? 'All' : types[v]}
            />
            <SelectField
              id="mount-speed"
              label="Base Speed"
              value={speed}
              options={this.speedTiers}
              onChange={this.setSpeed}
              controlClassName="small"
              renderValue={(v) => this.speedTiers.get(v)}
            />
            <FormControlLabel
              control={
                <Checkbox
                  checked={onlyObtainable}
                  onChange={(e, checked) => setOnlyObtainable(checked)}
                  color="primary"
                />
              }
              label="Obtainable Only"
            />
            <div className="filter-field">
              <InputLabel shrink style={{ marginBottom: 4 }}>Obtain By</InputLabel>
              <ButtonGroup size="small">
                {Object.values(mountObtainTypes).map(obtainBy => (
                  <Tooltip title={obtainBy.name} key={`obt-${obtainBy.id}`}>
                    <Button
                      variant={obtainTypes.includes(obtainBy.id) ? 'contained' : 'outlined'}
                      className={cn({ selected: obtainTypes.includes(obtainBy.id) })}
                      onClick={() => this.handleObtainChange(obtainBy.id)}
                    >
                      <span className={cn('dropdown-icon', obtainBy.icon)} />
                    </Button>
                  </Tooltip>
                ))}
              </ButtonGroup>
            </div>
          </div>
        </Paper>
        {mobile &&
        <AdContainer type="feed" />}
        {displayGrid
          ? <div className="section">
            <div className="mount-grid">
              {mounts.map(([mountId, mountList]) => {
                const [mount] = mountList;
                return (
                  <Zoom in unmountOnExit key={mount.id}>
                    <Paper className="mount">
                      <Link to={`/mounts/${mountId}`}>
                        <div className="portrait">
                          <img
                            src={Portrait[pascalCase(mount.name)] || NoPortrait}
                            alt={mount.name}
                          />
                          {mount.obtainIds.length > 0 &&
                          <div className="obtainables">
                            {mount.obtainIds.sort(sortNumber).map(obtainId => (
                              <Tooltip
                                title={mountObtainTypes[obtainId].name}
                                key={`${pascalCase(mountId)}-${obtainId}`}>
                                <span className={cn('dropdown-icon', mountObtainTypes[obtainId].icon)} />
                              </Tooltip>
                            ))}
                          </div>}
                          <Typography className="name">{mount.name}</Typography>
                          <Typography className="speed" variant="caption">{mount.moveSpeed} m/s</Typography>
                        </div>
                      </Link>
                    </Paper>
                  </Zoom>
                );
              })}
            </div>
            {mounts.length === 0 &&
            <Paper>
              {!objectHasProperties(mountData)
                ? <CircularProgress color="primary" className="no-results" />
                : <Typography className="no-results">
                  No mounts meet the criteria.
                </Typography>
              }
            </Paper>}
          </div>
          : <Paper className="section mount-table">
            <Table size="small">
              <TableHead>
                <TableRow>
                  <TableCell />
                  <TableCell>
                    <TableSortLabel
                      active={orderBy === 'name'}
                      direction={order}
                      onClick={this.handleSort('name')}
                    >
                      Name
                    </TableSortLabel>
                  </TableCell>
                  <TableCell>
                    <TableSortLabel
                      active={orderBy === 'moveSpeed'}
                      direction={order}
                      onClick={this.handleSort('moveSpeed')}
                    >
                      Speed
                    </TableSortLabel>
                  </TableCell>
                  <TableCell>Skills</TableCell>
                  <TableCell>Obtain By</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {mounts.map(([mountId, mountList]) => {
                  const [mount] = mountList;
                  return (
                    <TableRow key={mountId} onClick={() => this.props.history.push(`/mounts/${mountId}`)}>
                      <TableCell className="mount-icon">
                        <Tooltip
                          title={<img
                            src={Portrait[pascalCase(mount.name)] || NoPortrait}
                            alt={mount.name}
                            className="portrait-tooltip"
                          />}
                          placement="right"
                        >
                          <img src={`/images/icon/${mount.icon}.png`} alt={mount.name} />
                        </Tooltip>
                      </TableCell>
                      <TableCell>
                        {mount.name}
                      </TableCell>
                      <TableCell>
                        {mount.moveSpeed} m/s
                      </TableCell>
                      <TableCell>
                        <div className="mount-skills">
                          {mount.skillIds.map(skillId => (
                            <SkillIcon key={`${mount.id}-${skillId}`} id={skillId} className="size-sm" />
                          ))}
                        </div>
                      </TableCell>
                      <TableCell>
                        {mount.obtainIds.sort(sortNumber).map(obtainId => (
                          <Tooltip
                            title={mountObtainTypes[obtainId].name}
                            key={`${pascalCase(mountId)}-${obtainId}`}>
                            <span className={cn('dropdown-icon', mountObtainTypes[obtainId].icon)} />
                          </Tooltip>
                        ))}
                      </TableCell>
                    </TableRow>
                  );
                })}
                {!objectHasProperties(mountData) &&
                <TableRow className="no-results">
                  <TableCell colSpan="5" align="center">
                    {mountData.length === 0
                      ? <CircularProgress color="primary" />
                      : 'No mounts meet the criteria.'
                    }
                  </TableCell>
                </TableRow>}
              </TableBody>
            </Table>
          </Paper>
        }
        <MountViewer
          id={mount}
          onClose={() => this.props.history.push('/mounts')}
        />
        <AdContainer type="horizontal" />
      </>
    );
  }
Example #11
Source File: SyntaxEditor.js    From SyntaxMeets with MIT License 4 votes vote down vote up
SyntaxEditor = (props) => {
  const [theme, setTheme] = useState("monokai");
  const [popup, setPopup] = useState([false, ""]);
  const [filePopup, setFilePopup] = useState(false);
  const [fileHandleError, setFileHandleError] = useState("");
  const [fullscreen,setFullscreen] = useState(false); // maintain state of screen in syntax Editor
  const [modalIsOpen,setModalIsOpen] = useState(false)
  const [shareURL,setshareURL] = useState("")
  const [isLoading,setIsLoading]=useState(false)

  // This will resend a message to update the code of the newly joined user
  useEffect(() => {
    let UpdatedCode = props.code;
    if (props.previousUser.id === props.id) {
      props.socket.emit("message", UpdatedCode);
    }
    // if the user was connected then over reloading the page this block is called
    else if(sessionStorage.getItem('isconnected'))
    {
      //it used to save the code in sessionStorage when only one user is using there in a room
      props.setCode(sessionStorage.getItem('code'));
    }
  }, [props.previousUser]);

  const classes = useStyles();
  useEffect(() => {
    props.socket.on("message", (newValue) => {
      props.setCode(newValue);
    });
  }, []);

  const handleChange = (newValue) => {
    props.setCode(newValue);
    sessionStorage.setItem('code',newValue);
    props.socket.emit("message", newValue);
  };

  const copyCode = (value) => {
    copy(value);
    setPopup([true, "Code Copied Sucessfully"]);
  };

  const fetchSharedCodeLink=async (content) =>{
    var response = await fetch("https://dpaste.com/api/v2/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: "content=" + encodeURIComponent(content)
    });
    return response.text();
  }
  
  const shareCode = (value) => {
    setModalIsOpen(true)
    setIsLoading(true)
    fetchSharedCodeLink(value).then(url => {setIsLoading(false);setshareURL(url) });
  }

  const handleCodeRun = () => {
    props.executeCode(langId[props.currLang], props.code, props.codeInput);
  };

  const handleCodeDownload = () => {
    // download code here...
    const element = document.createElement("a");
    const file = new Blob([props.code], {
      type: "text/plain;charset=utf-8",
    });
    element.href = URL.createObjectURL(file);
    element.download = `syntaxmeets-code.${getExtensionByLangCode(
      props.currLang
    )}`;
    document.body.appendChild(element);
    element.click();
  };

  const IONavbar = (props) => {
    return (
      <AppBar position="static" style={{ backgroundColor: "#000A29" }}>
        <Typography
          variant="h6"
          style={{
            fontFamily: "poppins",
            color: "white",
            marginRight: "auto",
            marginTop: "auto",
            marginBottom: "auto",
            marginLeft: "auto",
            fontWeight: "400",
            padding: "3px 2px",
          }}
        >
          {props.type}
        </Typography>
      </AppBar>
    );
  };

  const uploadFile = () => {
    document.querySelector("#upload").click();
  };

  const checkValidFileExtension = (file) => {
    const validExtensions = Object.keys(langExtensionDict);
    var name = file.name;
    var valid = false;
    if (name.length > 0) {
      for (var i = 0; i < validExtensions.length; ++i) {
        var ext = validExtensions[i];
        if (
          name.substr(name.length - ext.length, ext.length).toLowerCase() ==
          ext.toLowerCase()
        ) {
          valid = true;
          break;
        }
      }
    }
    return valid;
  };

  const handleFileChange = () => {
    var file = document.querySelector("#upload").files[0];

    if (file) {
      var reader = new FileReader();

      reader.onload = function (e) {
        if (file.size > 10000) {
          setFilePopup(true);
          setFileHandleError("Error: File size greater than 10KB!");
          return;
        }

        if (!checkValidFileExtension(file)) {
          setFilePopup(true);
          setFileHandleError("Error: Not a Valid File Extension!");
          return;
        }

        handleChange(e.target.result);
        const fileNameArr = file.name.split(".");
        const ext = `.${fileNameArr[fileNameArr.length - 1]}`;
        props.setLanguage(langExtensionDict[ext]);
      };

      reader.onerror = function (e) {
        console.error("An error ocurred reading the file", e);
      };

      reader.readAsText(file, "UTF-8");
    }
  };

  // handle fullscreen mode
  const handleFullscreen = (props) =>{
    fullscreen ? setFullscreen(false) : setFullscreen(true);
    props.toggleFocusMode();
  }

  return (
    <Fragment>
      <Dialog fullWidth={true} maxWidth={"sm"} open={props.isCompiling}>
        <DialogTitle style={{ align: "center" }}>Compiling ...</DialogTitle>
        <div className={localClasses.loader}>
          <div>
            <span style={{ paddingLeft: "190px" }}>
              <ShareIcon style={{ fontSize: "125px" }} />
            </span>
            <span className={localClasses.arrow}>&gt;</span>
          </div>
        </div>
      </Dialog>
      <Dialog maxWidth={"sm"} open={props.isError}>
        <DialogTitle>Oops Error Occured</DialogTitle>
        <span style={{ marginLeft: "15px" }}>{props.codeError}</span>
        <DialogActions>
          <Button
            onClick={() => props.setIsError(false)}
            variant="contained"
            size="large"
            color="primary"
          >
            Close
          </Button>
        </DialogActions>
      </Dialog>
      <Snackbar
        open={popup[0]}
        autoHideDuration={2000}
        onClose={() => {
          setPopup([false, ""]);
        }}
      >
        <Alert
          onClose={() => {
            setPopup([false, ""]);
          }}
          severity="success"
          variant="filled"
        >
          {popup[1]}
        </Alert>
      </Snackbar>
      <Snackbar
        open={filePopup}
        autoHideDuration={2000}
        onClose={() => {
          setFilePopup(false);
        }}
      >
        <Alert
          onClose={() => {
            setFilePopup(false);
          }}
          severity="error"
          variant="filled"
        >
          {fileHandleError}
        </Alert>
      </Snackbar>
      <AppBar position="static" style={{ backgroundColor: "#000A29" }}>
        <div className={`${localClasses.Editor__navbar} row`}>
          <Typography
            variant="h5"
            style={{
              fontFamily: "poppins",
              color: "white",
              marginRight: "auto",
              marginTop: "auto",
              marginBottom: "auto",
              marginLeft: "30px",
              fontWeight: "800",
            }}
          >
            &nbsp;Syntax<span style={{ color: "#FFD500" }}>Editor</span>
          </Typography>
          <Toolbar>
            <FormControl
              size="small"
              variant="outlined"
              className={classes.formControl}
            >
              <InputLabel
                id="mode-label"
                style={{ fontFamily: "poppins", color: "#FFD500" }}
              >
                Language
              </InputLabel>
              <Select
                name="mode"
                labelId="mode-label"
                id="select-mode"
                value={props.currLang}
                onChange={(e) => {
                  props.setLanguage(e.target.value);
                }}
                label="Language"
                style={{ fontFamily: "poppins", color: "#ffffff" }}
              >
                {LangOptions.map((language) => (
                  <MenuItem value={language} key={language}>
                    <span className={localClasses.Menu__options}>
                      {language}
                    </span>
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <FormControl
              size="small"
              variant="outlined"
              className={classes.formControl}
            >
              <InputLabel
                id="theme-label"
                style={{ fontFamily: "poppins", color: "#FFD500" }}
              >
                Theme
              </InputLabel>
              <Select
                name="Theme"
                labelId="theme-label"
                id="select-theme"
                onChange={(e) => setTheme(e.target.value)}
                value={theme}
                label="Theme"
                style={{ fontFamily: "poppins", color: "#ffffff" }}
              >
                {themes.map((lang) => (
                  <MenuItem key={lang} value={lang}>
                    <span className={localClasses.Menu__options}> {lang} </span>
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
            <FormControl
              size="small"
              variant="outlined"
              className={classes.formControl}
            >
              <InputLabel
                id="font-label"
                style={{ fontFamily: "poppins", color: "#FFD500" }}
              >
                Font Size
              </InputLabel>
              <Select
                name="Theme"
                labelId="font-label"
                id="select-font"
                onChange={(e) => props.setFontSize(e.target.value)}
                value={props.fontSize}
                label="Font Size"
                style={{ fontFamily: "poppins", color: "#ffffff" }}
              >
                {[10, 12, 14, 16, 18, 20, 24, 28, 32, 40].map((size) => (
                  <MenuItem key={size} value={size}>
                    <span className={localClasses.Menu__options}> {size} </span>
                  </MenuItem>
                ))}
              </Select>
            </FormControl>
          </Toolbar>
        </div>
      </AppBar>
      <Dialog fullWidth={true} maxWidth={"xs"} open={modalIsOpen}>
        <CloseIcon style={{fontSize: "2em", position: "absolute", right: "5px", top: "5px"}} onClick={()=>{
          setModalIsOpen(false)
          setshareURL("")
        }}/>
        <DialogTitle style={{ textAlign: "center", marginTop: "10px" }}>
          Share Your Code
        </DialogTitle>
        <DialogContent>
        <div style={{display: "flex", alignItems: "center", margin: "20px"}}>
        {isLoading ? 
        <BeatLoader color='red' loading={true} css={override} size={50} /> :
          <>
            <Typography style={{ padding: "5px 10px", background: "#eee", borderRadius: "3px" }}>{shareURL}</Typography>
            <Tooltip title="Copy Url" arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                onClick={() => {
                  copy(shareURL)
                  setPopup([true, "Url Copied !!!"])
                }}
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                >
                <FileCopyIcon />
              </Button>
            </Tooltip>
          </>
        }
        </div>
        </DialogContent>
      </Dialog>
      <AceEditor
        mode={langMode[props.currLang]}
        theme={theme}
        height="550px"
        width={"auto"}
        value={props.code}
        onChange={handleChange}
        fontSize={props.fontSize}
        showPrintMargin
        showGutter
        highlightActiveLine
        name="CODEEDITOR"
        setOptions={{
          useWorker: false,
          enableLiveAutocompletion: props.autoCompletion,
        }}
      />
      <AppBar
        position="static"
        style={{ backgroundColor: "#000A29", marginBottom: "10px" }}
      >
        <Toolbar>
          <FormControlLabel
            control={
              <Switch
                color="primary"
                checked={props.autoCompletion}
                onChange={() => {
                  props.setAutoCompletion(!props.autoCompletion);
                }}
                name="EnableAutoCompletion"
              />
            }
            label={
              <Typography>
                <span style={{ color: "white" }}>Auto-complete</span>
              </Typography>
            }
          />
          <input
            type="file"
            id="upload"
            onChange={() => handleFileChange()}
            hidden
            accept=".c, .cpp, .java, .js, .ts, .clj, .cljs, .cs, .cbl, .cob, .cpy, .erl, .hrl, .go, .py, .f90, .f95, .f03, .txt, .groovy, .gvy, .gy, .gsh, 	.kt, .kts, .ktm, .php, .r, .rb, .sql, .swift"
          />
          <ButtonGroup
            style={{ marginLeft: "auto" }}
            variant="contained"
            color="primary"
          >
            <Tooltip title="Upload Code" arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                onClick={() => uploadFile()}
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                >
                <CloudUploadIcon />
              </Button>
            </Tooltip>
            <Tooltip title="Share Code" arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                onClick={() => shareCode(props.code)}
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                >
                <ShareIcon />
              </Button>
            </Tooltip>
            <Tooltip title="Copy Code" arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                onClick={() => copyCode(props.code)}
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                >
                <FileCopyIcon />
              </Button>
            </Tooltip>
            <Tooltip title="Download Code" arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                onClick={handleCodeDownload}
                >
                <CloudDownloadRounded style={{ fontSize: 24 }} />
              </Button>
            </Tooltip>
            <Tooltip title={fullscreen ? "Exit Full Screen" : "Full Screen"} arrow TransitionComponent={Zoom}>
              <Button
                variant="contained"
                color="primary"
                style={{
                  fontFamily: "poppins",
                  marginLeft: "auto",
                  fontWeight: "600",
                  color: "white",
                }}
                onClick={() => handleFullscreen(props)}
              >
                {fullscreen
                  ?<FullscreenExitRounded style={{ fontSize: 24 }}/>
                  :<FullscreenRounded style={{ fontSize: 24 }}/>
                }
              </Button>
            </Tooltip>
          </ButtonGroup>
          <Button
            variant="contained"
            color="primary"
            onClick={handleCodeRun}
            startIcon={<PlayArrowIcon style={{ fontSize: 24 }} />}
            style={{
              fontFamily: "poppins",
              marginLeft: "10px",
              fontWeight: "600",
              color: "#fff",
              backgroundColor: "#FFD500",
            }}
          >
            Run
          </Button>
        </Toolbar>
      </AppBar>

      <Grid container spacing={0}>
        <Grid item xs={12} sm={12} md={6}>
          <IONavbar type={"Input"} />
          <INPUT />
        </Grid>
        <Grid item xs={12} sm={12} md={6}>
          <IONavbar type={"Output"} />
          <OUTPUT />
        </Grid>
      </Grid>
    </Fragment>
  );
}
Example #12
Source File: PageWrapper.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function PageWrapper View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function PageWrapper(props) {
  const backToTopEl = React.useRef(null);
  const classes = useStyles();
  const common_classes = useCommonStyles();
  const trigger = useScrollTrigger();
  const [searchType, setSearchType] = useState(
    getQueryParams(window.location.href).get('type') || SearchType.PROJECTS,
  );
  const formRef = useRef();
  const token = useSelector(state => state.auth.token);

  const [state, setState] = React.useState({
    username: null,
    anchor_el: null,
    loading: false,
    open_search_form: false,
  });

  const [options, setOptions] = useState([]);
  const [query, setQuery] = useState('');
  const [queryInput, setQueryInput] = useState('');

  const throttledFetchOptions = useMemo(
    () =>
      throttle(async (query, searchType) => {
        if (query.length === 0) {
          setOptions([]);
          return;
        }

        const api = new API();
        let completions = [];
        if (searchType === SearchType.TAGS) {
          completions = await api.autocompleteTags({ query, token });
          completions = completions.map(({ name }) => ({
            title: name,
          }));
        } else if (searchType === SearchType.PROJECTS) {
          completions = await api.autocompleteProjects({ query, token });
          completions = completions.map(({ id, title, creator, images }) => ({
            title,
            shortInfo: creator.username,
            image: images.length > 0 ? images[0].image_url : null,
            link: `/projects/${id}`,
          }));
        } else {
          completions = await api.autocompleteCreators({ query, token });
          completions = completions.map(({ username, avatar }) => ({
            title: username,
            image: avatar,
            link: `/creators/${username}`,
          }));
        }
        setOptions(completions);
      }, 2),
    [],
  );

  useEffect(() => {
    throttledFetchOptions(
      query ||
        (props.location.search &&
          getQueryParams(window.location.href).get('q')),
      searchType,
    );
  }, [query, searchType]);

  useEffect(() => {
    throttledFetchOptions.cancel();
  }, []);

  useEffect(() => {
    handleSetState({ loading: true });
    fetchHero(props)
      .then(() => {
        if (props.auth.token) {
          return props.getAuthUser(props);
        }
      })
      .finally(() => {
        handleSetState({ loading: false });
      });
  }, [props.auth.token]);

  React.useEffect(() => {
    handleSetState(handleProfileMenuClose());
  }, [trigger]);

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };

  const onSearchOptionClick = async (_, option) => {
    if (!option || !option.title) return;

    await new Promise(resolve => setTimeout(resolve, 100));
    if (option.link) {
      window.history.pushState({}, '', option.link);
      window.location.reload();
      return;
    }

    const queryParams = new URLSearchParams({
      type: searchType,
      q: option.title,
    });
    window.history.pushState({}, '', `/search?${queryParams}`);
    window.location.reload();
  };

  const handleSubmit = e => {
    e.preventDefault();
    const queryParams = new URLSearchParams({
      type: searchType,
      q: query,
    });

    window.history.pushState({}, '', `/search?${queryParams}`);
    window.location.reload();
  };

  const { anchor_el, loading, open_search_form } = state;
  const { t } = props;
  const { zubhub, hero } = props.projects;

  const profileMenuOpen = Boolean(anchor_el);

  return (
    <>
      <ToastContainer />
      <CssBaseline />
      <AppBar className={classes.navBarStyle}>
        <Container className={classes.mainContainerStyle}>
          <Toolbar className={classes.toolBarStyle}>
            <Box className={classes.logoStyle}>
              <Link to="/">
                <img
                  src={zubhub?.header_logo_url ? zubhub.header_logo_url : logo}
                  alt="logo"
                />
              </Link>
              <Box
                className={clsx(
                  classes.languageSelectBoxStyle,
                  common_classes.displayInlineFlex,
                  common_classes.alignCenter,
                  common_classes.addOnSmallScreen,
                )}
              >
                <TranslateIcon />
                <Select
                  className={classes.languageSelectStyle}
                  value=""
                  onChange={e => handleChangeLanguage({ e, props })}
                >
                  {Object.keys(languageMap).map((ln, index) => (
                    <MenuItem key={index} value={ln}>
                      {languageMap[ln]}
                    </MenuItem>
                  ))}
                </Select>
              </Box>
              <Box
                className={clsx(
                  classes.languageSelectBoxStyle,
                  common_classes.displayInlineFlex,
                  common_classes.alignCenter,
                  common_classes.removeOnSmallScreen,
                )}
              >
                <TranslateIcon />
                <Select
                  className={classes.languageSelectStyle}
                  value={props.i18n.language}
                  onChange={e => handleChangeLanguage({ e, props })}
                >
                  {Object.keys(languageMap).map((ln, index) => (
                    <MenuItem key={index} value={ln}>
                      {languageMap[ln]}
                    </MenuItem>
                  ))}
                </Select>
              </Box>
              <form
                action="/search"
                className={clsx(classes.searchFormStyle, classes.removeOn894)}
                role="search"
                onSubmit={handleSubmit}
                ref={formRef}
              >
                <FormControl variant="outlined">
                  <InputLabel
                    htmlFor="q"
                    className={classes.searchFormLabelStyle}
                  >
                    {t('pageWrapper.inputs.search.label')}
                  </InputLabel>
                  <FormGroup row>
                    <FormControl variant="outlined">
                      <InputSelect
                        searchType={searchType}
                        onSearchTypeChange={setSearchType}
                        name="type"
                      >
                        <MenuItem value={SearchType.PROJECTS}>
                          Projects
                        </MenuItem>
                        <MenuItem value={SearchType.CREATORS}>
                          Creators
                        </MenuItem>
                        <MenuItem value={SearchType.TAGS}>Tags</MenuItem>
                      </InputSelect>
                    </FormControl>
                    <Autocomplete
                      options={options}
                      defaultValue={{
                        title:
                          props.location.search &&
                          getQueryParams(window.location.href).get('q'),
                      }}
                      renderOption={(option, { inputValue }) => (
                        <Option
                          option={option}
                          inputValue={inputValue}
                          onOptionClick={onSearchOptionClick}
                        />
                      )}
                      onChange={onSearchOptionClick}
                    >
                      {params => (
                        <TextField
                          name="q"
                          id="q"
                          type="search"
                          variant="outlined"
                          {...params}
                          InputProps={{
                            ...params.InputProps,
                            className: clsx(
                              classes.searchFormInputStyle,
                              'search-form-input',
                            ),
                            endAdornment: (
                              <InputAdornment position="end">
                                <IconButton
                                  type="submit"
                                  className={classes.searchFormSubmitStyle}
                                  aria-label={t(
                                    'pageWrapper.inputs.search.label',
                                  )}
                                >
                                  <SearchIcon />
                                </IconButton>
                              </InputAdornment>
                            ),
                            pattern: '(.|s)*S(.|s)*',
                            defaultValue: {
                              title:
                                props.location.search &&
                                getQueryParams(window.location.href).get('q'),
                            },
                          }}
                          onChange={e => setQuery(e.target.value)}
                          placeholder={`${t(
                            'pageWrapper.inputs.search.label',
                          )}...`}
                        />
                      )}
                    </Autocomplete>
                  </FormGroup>
                </FormControl>
              </form>
            </Box>
            <div className={classes.navActionStyle}>
              {!props.auth.token ? (
                <>
                  <IconButton
                    className={clsx(
                      classes.toggleSearchFormStyle,
                      classes.addOn894,
                    )}
                    id="toggle-search"
                    aria-label="toggle search form"
                    onClick={() =>
                      handleSetState(handleToggleSearchForm(state))
                    }
                  >
                    <SearchIcon />
                  </IconButton>
                  <Link
                    className={clsx(
                      classes.textDecorationNone,
                      common_classes.removeOnSmallScreen,
                    )}
                    to="/login"
                  >
                    <CustomButton
                      variant="outlined"
                      size="large"
                      secondaryButtonStyle
                      customButtonStyle
                    >
                      {t('pageWrapper.navbar.login')}
                    </CustomButton>
                  </Link>
                  <Link
                    className={clsx(
                      classes.textDecorationNone,
                      common_classes.removeOnSmallScreen,
                    )}
                    to="/signup"
                  >
                    <CustomButton
                      variant="contained"
                      size="large"
                      primaryButtonStyle
                      customButtonStyle
                      className={common_classes.marginLeft1em}
                    >
                      {t('pageWrapper.navbar.signup')}
                    </CustomButton>
                  </Link>

                  <MenuRoundedIcon
                    className={common_classes.addOnSmallScreen}
                    aria-label={t('pageWrapper.navbar.menu')}
                    aria-controls="menu"
                    aria-haspopup="true"
                    onClick={e => handleSetState(handleProfileMenuOpen(e))}
                  />
                  <Menu
                    className={common_classes.addOnSmallScreen}
                    disableScrollLock={true}
                    id="menu"
                    anchorEl={anchor_el}
                    anchorOrigin={{
                      vertical: 'top',
                      horizontal: 'right',
                    }}
                    keepMounted
                    transformOrigin={{
                      vertical: 'top',
                      horizontal: 'right',
                    }}
                    open={profileMenuOpen}
                    onClose={e => handleSetState(handleProfileMenuClose(e))}
                  >
                    <MenuItem>
                      <Link className={classes.textDecorationNone} to="/login">
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.login')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem>
                      <Link className={classes.textDecorationNone} to="/signup">
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.signup')}
                        </Typography>
                      </Link>
                    </MenuItem>
                  </Menu>
                </>
              ) : (
                <>
                  <Link
                    className={clsx(
                      classes.textDecorationNone,
                      common_classes.marginRight1em,
                      common_classes.removeOnSmallScreen,
                    )}
                    to="/projects/create"
                  >
                    <CustomButton
                      variant="contained"
                      primaryButtonStyle
                      customButtonStyle
                      size="small"
                    >
                      {t('pageWrapper.navbar.createProject')}
                    </CustomButton>
                  </Link>
                  <IconButton
                    className={clsx(
                      classes.toggleSearchFormStyle,
                      classes.addOn894,
                    )}
                    id="toggle-search"
                    aria-label="toggle search form"
                    onClick={() =>
                      handleSetState(handleToggleSearchForm(state))
                    }
                  >
                    <SearchIcon />
                  </IconButton>
                  <NotificationButton
                    className={clsx(
                      common_classes.marginRight1em,
                      common_classes.removeOnSmallScreen,
                    )}
                  />
                  <Avatar
                    className={clsx(
                      classes.avatarStyle,
                      common_classes.removeOnSmallScreen,
                    )}
                    aria-label={`${props.auth.username}' Avatar`}
                    aria-controls="profile_menu"
                    aria-haspopup="true"
                    onClick={e => handleSetState(handleProfileMenuOpen(e))}
                    src={props.auth.avatar}
                    alt={props.auth.username}
                  />
                  <Menu
                    className={classes.profileMenuStyle}
                    disableScrollLock={true}
                    id="profile_menu"
                    anchorEl={anchor_el}
                    anchorOrigin={{
                      vertical: 'top',
                      horizontal: 'right',
                    }}
                    keepMounted
                    transformOrigin={{
                      vertical: 'top',
                      horizontal: 'right',
                    }}
                    open={profileMenuOpen}
                    onClose={e => handleSetState(handleProfileMenuClose(e))}
                  >
                    <MenuItem>
                    <Tooltip title={props.auth.username} placement="top">
                      <Typography
                        variant="subtitle2"
                        color="textPrimary"
                        component="span"
                        className={classes.profileStyle}
                      >
                        {props.auth.username }
                      </Typography>
                      </Tooltip>
                    </MenuItem>
                    <MenuItem>
                      <a className={classes.textDecorationNone} href="/profile">
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.profile')}
                        </Typography>
                      </a>
                    </MenuItem>
                    <MenuItem className={common_classes.addOnSmallScreen}>
                      <Link
                        className={classes.textDecorationNone}
                        to="/projects/create"
                      >
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.createProject')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem>
                      <Link
                        className={classes.textDecorationNone}
                        to={`/creators/${props.auth.username}/projects`}
                      >
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.projects')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem>
                      <Link
                        className={classes.textDecorationNone}
                        to={`/creators/${props.auth.username}/followers`}
                      >
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.followers')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem>
                      <Link
                        className={classes.textDecorationNone}
                        to={`/creators/${props.auth.username}/following`}
                      >
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.following')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem>
                      <Link
                        className={classes.textDecorationNone}
                        to="/projects/saved"
                      >
                        <Typography
                          variant="subtitle2"
                          color="textPrimary"
                          component="span"
                        >
                          {t('pageWrapper.navbar.savedProjects')}
                        </Typography>
                      </Link>
                    </MenuItem>
                    <MenuItem className={classes.logOutStyle}>
                      <Typography
                        className={common_classes.colorRed}
                        variant="subtitle2"
                        component="span"
                        onClick={e => logout(e, props)}
                      >
                        {t('pageWrapper.navbar.logout')}
                      </Typography>
                    </MenuItem>
                  </Menu>
                </>
              )}
            </div>
          </Toolbar>
          {open_search_form ? (
            <ClickAwayListener
              onClickAway={e => handleSetState(closeSearchFormOrIgnore(e))}
            >
              <form
                action="/search"
                className={clsx(classes.smallSearchFormStyle, classes.addOn894)}
                role="search"
                ref={formRef}
              >
                <FormControl variant="outlined" style={{ minWidth: 'unset' }}>
                  <InputSelect
                    searchType={searchType}
                    onSearchTypeChange={setSearchType}
                    name="type"
                  >
                    <MenuItem value={SearchType.PROJECTS}>Projects</MenuItem>
                    <MenuItem value={SearchType.CREATORS}>Creators</MenuItem>
                    <MenuItem value={SearchType.TAGS}>Tags</MenuItem>
                  </InputSelect>
                </FormControl>
                <FormControl
                  variant="outlined"
                  style={{ flex: '1 1 auto', maxWidth: '350px' }}
                >
                  <InputLabel
                    htmlFor="q"
                    className={classes.searchFormLabelStyle}
                  >
                    {t('pageWrapper.inputs.search.label')}
                  </InputLabel>
                  <Autocomplete
                    options={options}
                    defaultValue={
                      props.location.search &&
                      getQueryParams(window.location.href).get('q')
                    }
                    renderOption={(option, { inputValue }) => (
                      <Option
                        option={option}
                        inputValue={inputValue}
                        onOptionClick={onSearchOptionClick}
                      />
                    )}
                    onChange={onSearchOptionClick}
                  >
                    {params => (
                      <TextField
                        name="q"
                        id="q"
                        type="search"
                        variant="outlined"
                        {...params}
                        InputProps={{
                          ...params.InputProps,
                          className: clsx(
                            classes.smallSearchFormInputStyle,
                            'search-form-input',
                          ),
                          endAdornment: (
                            <InputAdornment position="end">
                              <IconButton
                                type="submit"
                                className={classes.searchFormSubmitStyle}
                                aria-label={t(
                                  'pageWrapper.inputs.search.label',
                                )}
                              >
                                <SearchIcon />
                              </IconButton>
                            </InputAdornment>
                          ),
                          pattern: '(.|s)*S(.|s)*',
                        }}
                        placeholder={`${t(
                          'pageWrapper.inputs.search.label',
                        )}...`}
                        onChange={e => setQuery(e.target.value)}
                      />
                    )}
                  </Autocomplete>
                </FormControl>
              </form>
            </ClickAwayListener>
          ) : null}
        </Container>
      </AppBar>
      <Toolbar ref={backToTopEl} />

      {loading ? <LoadingPage /> : props.children}

      <footer className={clsx('footer-distributed', classes.footerStyle)}>
        <Box>
          <a href="https://unstructured.studio">
            <img
              src={
                zubhub?.footer_logo_url
                  ? zubhub.footer_logo_url
                  : unstructuredLogo
              }
              className={classes.footerLogoStyle}
              alt="unstructured-studio-logo"
            />
          </a>
          <div>
            <Box
              className={clsx(
                classes.languageSelectBoxStyle,
                common_classes.displayInlineFlex,
                common_classes.alignCenter,
                common_classes.addOnSmallScreen,
              )}
            >
              <TranslateIcon />
              <Select
                className={classes.languageSelectStyle}
                value=""
                onChange={e => handleChangeLanguage({ e, props })}
              >
                {Object.keys(languageMap).map((ln, index) => (
                  <MenuItem key={index} value={ln}>
                    {languageMap[ln]}
                  </MenuItem>
                ))}
              </Select>
            </Box>
            <Box
              className={clsx(
                classes.languageSelectBoxStyle,
                common_classes.displayInlineFlex,
                common_classes.alignCenter,
                common_classes.removeOnSmallScreen,
              )}
            >
              <TranslateIcon />
              <Select
                className={classes.languageSelectStyle}
                value={props.i18n.language}
                onChange={e => handleChangeLanguage({ e, props })}
              >
                {Object.keys(languageMap).map((ln, index) => (
                  <MenuItem key={index} value={ln}>
                    {languageMap[ln]}
                  </MenuItem>
                ))}
              </Select>
            </Box>
          </div>
        </Box>

        <section className={classes.footerSectionStyle}>
          <Box className={classes.footerBoxStyle}>
            <Typography
              variant="subtitle2"
              color="textPrimary"
              className={classes.footerTitleStyle}
            >
              {t('pageWrapper.footer.privacy')}
            </Typography>

            <Link
              to={`/privacy_policy`}
              className={common_classes.textDecorationNone}
            >
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.guidelines')}
              </Typography>
            </Link>

            <Link
              to={`/terms_of_use`}
              className={common_classes.textDecorationNone}
            >
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.termsOfUse')}
              </Typography>
            </Link>
          </Box>

          <Box className={classes.footerBoxStyle}>
            <Typography
              variant="subtitle2"
              color="textPrimary"
              className={classes.footerTitleStyle}
            >
              {t('pageWrapper.footer.about')}
            </Typography>

            <Link to="/about" className={common_classes.textDecorationNone}>
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.zubhub')}
              </Typography>
            </Link>
          </Box>

          <Box className={classes.footerBoxStyle}>
            <Typography
              variant="subtitle2"
              color="textPrimary"
              className={classes.footerTitleStyle}
            >
              {t('pageWrapper.footer.help')}
            </Typography>

            <a
              target="__blank"
              rel="noreferrer"
              href={
                hero.tinkering_resource_url
                  ? hero.tinkering_resource_url
                  : 'https://kriti.unstructured.studio/'
              }
              className={common_classes.textDecorationNone}
            >
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.resources')}
              </Typography>
            </a>

            <Link
              to={`/faqs`}
              className={clsx(
                common_classes.textDecorationNone,
                common_classes.displayNone,
              )}
            >
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.faqs')}
              </Typography>
            </Link>

            <a
              href="mailto:[email protected]"
              className={common_classes.textDecorationNone}
            >
              <Typography
                variant="subtitle2"
                color="textPrimary"
                className={classes.footerLinkStyle}
              >
                {t('pageWrapper.footer.contactUs')}
              </Typography>
            </a>
          </Box>
        </section>

        <Zoom in={useScrollTrigger}>
          <div
            onClick={e => handleScrollTopClick(e, backToTopEl)}
            role="presentation"
            className={classes.scrollTopButtonStyle}
          >
            <Fab color="secondary" size="small" aria-label="scroll back to top">
              <KeyboardArrowUpIcon />
            </Fab>
          </div>
        </Zoom>
      </footer>
    </>
  );
}
Example #13
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>
		);
	}