@material-ui/core#ButtonGroup JavaScript Examples

The following examples show how to use @material-ui/core#ButtonGroup. 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: language-component.js    From horondi_client_fe with MIT License 6 votes vote down vote up
LanguageComponent = ({ fromSideBar }) => {
  const language = getFromLocalStorage(LANGUAGE);
  const styles = useStyles({ fromSideBar, language });
  const { i18n } = useTranslation();

  const handleChange = (e) => {
    const targetValue = e.target.value;
    setToLocalStorage(LANGUAGE, targetValue);
    i18n.changeLanguage(targetValue);
  };

  useEffect(() => {
    i18n.changeLanguage(language);
  }, []);

  const mappedLanguages = LANGUAGES_LIST.map((lang) => (
    <Button key={lang} value={lang}>
      {lang}
    </Button>
  ));
  return (
    <div data-cy='language' className={styles.root}>
      <ButtonGroup onClick={handleChange}>{mappedLanguages}</ButtonGroup>
    </div>
  );
}
Example #2
Source File: OrderDialog.js    From dipact with GNU General Public License v3.0 6 votes vote down vote up
render() {
		return (
			<Dialog
				onEntered={helpers.genOnback(this.close)}
				open={this.state.open}
				disableBackdropClick={false}
				onClose={this.close}
			>
				<ButtonGroup orientation="vertical">
					{this.state.options.map(option => {
						return (
							<Button
								key={option}
								xoption={option}
								onClick={this.onClick}
							>
								{option}
							</Button>
						);
					})}
				</ButtonGroup>
			</Dialog>
		);
	}
Example #3
Source File: MainToolBar.js    From fireshort with MIT License 6 votes vote down vote up
export default function MainToolBar(props) {
    const classes = useStyles();

    return (
        <Container maxWidth="md">
            <Card className={classes.toolBarRoot}>
                <ButtonGroup variant="outlined" color="default" style={{boxShadow: "unset !important", justifyContent: "flex-end", display: "flex"}}>
                    <Button onClick={() => props.updateViewMode("module")} disabled = { props.state.viewMode === "module" }>
                        <ViewModuleIcon />
                    </Button>
                    <Button onClick={() => props.updateViewMode("list")}  disabled = { props.state.viewMode === "list" }>
                        <ViewListIcon />
                    </Button>
                </ButtonGroup>
            </Card>
        </Container>
    );
}
Example #4
Source File: MainToolBar.js    From FireShort with MIT License 6 votes vote down vote up
export default function MainToolBar(props) {
    const classes = useStyles();
    
    const filter = useSelector((state) => state.filter)
    const dispatch = useDispatch();

    const changeHandler = (value) => {
        dispatch(setTextFilter(value));
    }

    return (
        <Container maxWidth="md">
            <Card className={classes.toolBarRoot} style={{ display: "grid", gridTemplateColumns: "3fr 1fr" }}>
                <TextField variant="outlined" color="default" value={filter.text} placeholder="Search links" onChange={(e) => changeHandler(e.target.value)} style={{ boxShadow: "unset !important", justifyContent: "flex-start", display: "flex" }} />
                <ButtonGroup variant="outlined" color="default" style={{ boxShadow: "unset !important", justifyContent: "flex-end", display: "flex" }}>
                    <Button onClick={props.refresh}>
                        <Loop />
                    </Button>
                    <Button onClick={() => props.updateViewMode("module")} disabled={props.state.viewMode === "module"}>
                        <ViewModuleIcon />
                    </Button>
                    <Button onClick={() => props.updateViewMode("list")} disabled={props.state.viewMode === "list"}>
                        <ViewListIcon />
                    </Button>
                </ButtonGroup>
            </Card>
        </Container>
    );
}
Example #5
Source File: count-per-page.js    From horondi_client_fe with MIT License 6 votes vote down vote up
CountPerPage = () => {
  const { t } = useTranslation();
  const styles = useStyles();
  const history = useHistory();
  const { search } = useLocation();

  const searchParams = new URLSearchParams(search);
  const { countPerPage, page, defaultPage } = URL_QUERIES_NAME;
  const countPerPageText = t('productListPage.countPerPage');

  const pickQuantity = (value) => {
    searchParams.set(page, defaultPage);
    searchParams.set(countPerPage, value);
    history.push(`?${searchParams.toString()}`);
  };
  const productsOnPage = ITEMS_PER_PAGE.map((item) => (
    <Button
      className={
        Number(searchParams.get('countPerPage')) === item.value ? styles.selectedButton : ''
      }
      data-cy={item.title}
      key={item.value}
      type='button'
      value={item.value}
      onClick={() => pickQuantity(item.value)}
      variant={TEXT_FIELD_VARIANT.OUTLINED}
    >
      {item.value}
    </Button>
  ));
  return (
    <div className={styles.pageCounter}>
      <span>{countPerPageText}</span>
      <ButtonGroup className={styles.items}>{productsOnPage}</ButtonGroup>
    </div>
  );
}
Example #6
Source File: index.jsx    From redive_linebot with MIT License 6 votes vote down vote up
ControlButtons = ({ onDeleteComplete, value }) => {
  const classes = useStyles();
  const [{ data = {}, loading }, doDelete] = useAxios(
    {
      url: `/api/Game/World/Boss/Feature/Message/${value}`,
      method: "DELETE",
    },
    { manual: true }
  );

  const handleDelete = () => {
    doDelete();
  };

  useEffect(() => {
    if (data.message === "success") {
      onDeleteComplete();
    }
  }, [data]);

  return (
    <div className={classes.wrapper}>
      <ButtonGroup color="primary" variant="outlined" disabled={loading}>
        <Button component={Link} to={`/Admin/WorldbossMessage/Update/${value}`}>
          更新
        </Button>
        <Button color="primary" variant="outlined" onClick={handleDelete}>
          刪除
        </Button>
      </ButtonGroup>
      {loading && <CircularProgress size={24} className={classes.buttonProgress} />}
    </div>
  );
}
Example #7
Source File: SortAnsBar.js    From stack-underflow with MIT License 6 votes vote down vote up
SortAnsBar = ({ isMobile, sortBy, setSortBy }) => {
  const handleSortChange = (e) => {
    setSortBy(e.target.innerText.toUpperCase());
  };

  return (
    <div>
      <ButtonGroup
        color="secondary"
        disableElevation
        size={isMobile ? 'small' : 'medium'}
      >
        <Button
          variant={sortBy === 'VOTES' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Votes
        </Button>
        <Button
          variant={sortBy === 'NEWEST' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Newest
        </Button>
        <Button
          variant={sortBy === 'OLDEST' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Oldest
        </Button>
      </ButtonGroup>
    </div>
  );
}
Example #8
Source File: Education.jsx    From Corona-tracker with MIT License 6 votes vote down vote up
FactQuizContainer = () => {
  const [factsOrQuiz, setFactsQuiz] = useState('facts');
  const setQuiz = () => setFactsQuiz('quiz');
  const setFacts = () => setFactsQuiz('facts');
  const classes = useStyles();

  return (
    <Grid>
      <Grid>
        <ButtonGroup>
          <Button className={classes.buttonGroup} onClick={setFacts} variant={factsOrQuiz === 'facts' && 'contained'}>
            Facts
          </Button>
          <Button className={classes.buttonGroup} onClick={setQuiz} variant={factsOrQuiz === 'quiz' && 'contained'}>
            Quiz
          </Button>
        </ButtonGroup>
        <Typography variant="body1" color="textSecondary">
          {factsOrQuiz === 'facts' && `Swipe to the right or left to learn more about COVID-19`}
          {factsOrQuiz === 'quiz' && `QUIZ TIME! Swipe right if true and left if false`}
        </Typography>
      </Grid>
      {factsOrQuiz === 'facts' && <FlashCards mode="facts" cardData={cardData} />}
      {factsOrQuiz === 'quiz' && <FlashCards mode="quiz" cardData={quizData} />}
    </Grid>
  );
}
Example #9
Source File: RepoPicker.js    From git-insights with MIT License 5 votes vote down vote up
export default function RepoPickerList(props) {
  const classes = useStyles();
  const { repos, fetchRepos, pickPrimaryRepo, isLoading } = props;

  const selectPrimaryRepo = (repoId) => {
    // TODO: err if no repo found
    const repo = repos.data.find((repo) => repo.id === repoId);
    pickPrimaryRepo({
      owner: repo.owner.login,
      repo: repo.name
    });
  }

  const getNextPage = () => {
    fetchRepos(repos.nextPage);
  }

  const getPreviousPage = () => {
    fetchRepos(repos.prevPage);
  }

  return (
    !isLoading ?
      <Grid container spacing={1} direction="column" alignItems="center">
        <Grid item container spacing={4}>
          {repos.data.map(repo => {
            return (
              <Grid item xs={12} sm={6} md={4} lg={3} key={repo.id}>
                <Card className={classes.cardRoot}>
                  <CardContent className={classes.cardContent}>
                    <Typography gutterBottom variant="h5" component="h2">
                      {repo.full_name}
                    </Typography>
                    <Typography variant="body2" color="textSecondary"
                      component="p" className={classes.textBlock}>
                        {repo.description}
                    </Typography>
                  </CardContent>
                  <Divider variant="middle" />
                  <CardActions>
                    <Button size="small" color="primary" variant="outlined"
                      startIcon={<LaunchIcon />} href={repo.html_url} target="_blank">
                      Visit
                    </Button>
                    <Button size="small" color="primary" variant="outlined"
                      onClick={() => selectPrimaryRepo(repo.id)}
                    >
                      Connect
                    </Button>
                  </CardActions>
                </Card>
              </Grid>
            );
          })}
        </Grid>
        <Grid item className={classes.buttonGrid}>
          <ButtonGroup>
            {repos.prevPage ? (
              <Button onClick={getPreviousPage}>Previous</Button>
            ) : (
              <Button disabled>Previous</Button>
            )}
            {repos.nextPage ? (
              <Button onClick={getNextPage}>Next</Button>
            ) : (
              <Button disabled>Next</Button>
            )}
          </ButtonGroup>
        </Grid>
      </Grid>
    :
      <Grid container className={classes.loadingContainer}>
        <CircularProgress />
        <br />
        <Typography>Loading...</Typography>
      </Grid>
  );
}
Example #10
Source File: socialShareButtons.jsx    From zubhub with GNU Affero General Public License v3.0 5 votes vote down vote up
SocialButtons = () => {
  const { t } = useTranslation();
  const classes = useStyles();
  const url = window.location.href;
  const mediaQuery = useMediaQuery('(min-width: 1080px)');
  return (
    <>
      <ButtonGroup
        className={classes.buttonGroup}
        orientation={(mediaQuery && 'vertical') || 'horizontal'}
      >
        <IconButton
          className={classes.button}
          onClick={() =>
            window.open(
              'https://www.facebook.com/sharer/sharer.php?u=' +
                url +
                '&quote=' +
                t('projectDetails.socialShare.fbwa'),
            )
          }
        >
          <FacebookIcon />
        </IconButton>
        <IconButton
          className={classes.button}
          onClick={() =>
            window.open(
              'https://web.whatsapp.com/send?text=' +
                t('projectDetails.socialShare.fbwa') +
                url,
            )
          }
        >
          <WhatsAppIcon />
        </IconButton>
        <IconButton
          className={classes.button}
          onClick={() => {
            navigator.clipboard
              .writeText(url)
              .then(() => {
                toast.success(t('projectDetails.socialShare.copySuccess'));
              })
              .catch(() => {
                toast.warning(t('projectDetails.socialShare.copyFail'));
              });
          }}
        >
          <LinkIcon />
        </IconButton>
      </ButtonGroup>
    </>
  );
}
Example #11
Source File: SortQuesBar.js    From stack-underflow with MIT License 5 votes vote down vote up
SortQuesBar = ({ isMobile, sortBy, setSortBy }) => {
  const classes = useQuesListStyles();

  const handleSortChange = (e) => {
    setSortBy(e.target.innerText.toUpperCase());
  };

  return (
    <div className={classes.btnGroupWrapper}>
      <ButtonGroup
        color="secondary"
        disableElevation
        size={isMobile ? 'small' : 'medium'}
        fullWidth={isMobile}
      >
        <Button
          variant={sortBy === 'HOT' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Hot
        </Button>
        <Button
          variant={sortBy === 'VOTES' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Votes
        </Button>
        <Button
          variant={sortBy === 'VIEWS' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Views
        </Button>
        <Button
          variant={sortBy === 'NEWEST' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Newest
        </Button>
        <Button
          variant={sortBy === 'OLDEST' ? 'contained' : 'outlined'}
          onClick={handleSortChange}
        >
          Oldest
        </Button>
      </ButtonGroup>
    </div>
  );
}
Example #12
Source File: Show.js    From Designer-Client with GNU General Public License v3.0 5 votes vote down vote up
export function Show(props) {
  const dispatch = useDispatch();
  const history = useHistory();
  const classes = useStyles();
  const [newMetaOpen, setNewMetaOpen] = useState(false);
  const [dataType, setDataType] = useState();

  const { id } = useParams();
  const api = useSelector(state => state.apis.dict)[id];

  useEffect(() => {
    dispatch(apiActions.getApi(id)).then((response) => {
      if(response.error) {
        /**
         * 문제가 발생하는 경우 목록 페이지로 redirect
         */
        alertActions.handleError(dispatch, response.error);
        history.push("/apis");
        return;
      }
    })
  }, [])

  const handelMeneSelected = (dataType) => {
    setDataType(dataType)
    setNewMetaOpen(true);
  }

  return (
    <Container maxWidth={false}>
      { api &&
        <Box>
          <NewMetaDialog dataType={dataType} api={api} open={newMetaOpen} setOpen={setNewMetaOpen}/>
          
          <Box mt={2}>
            <Grid container>
              <Grid item xs={12} md={6}>
                { api.metas && api.metas.map(el => {
                  return (
                    <MetaBox meta={el}/>
                  )
                })}

                <Paper className={`${classes.defaultPaper} ${classes.spaceBetween}`}>
                  <div>
                    오퍼레이션 추가
                  </div>                  
                  
                  <ButtonGroup color="primary" size="small" aria-label="outlined primary button group">
                    <Button onClick={() => handelMeneSelected("upload")}>파일 직접 등록</Button>
                    <Button onClick={() => handelMeneSelected("url")}>파일 URL 등록</Button>
                    <Button onClick={() => handelMeneSelected("dbms")}>DBMS 접속 정보 등록</Button>
                  </ButtonGroup>
                </Paper>
              </Grid>
              <Grid item xs={12} md={6}>
                <Box textAlign="left">
                  <SwaggerUI url={`${server}/stages/${api.id}/api-docs`}/>
                </Box>
              </Grid>
            </Grid>
          </Box>
        </Box>
      }
    </Container>
  )
}
Example #13
Source File: SwitchButton.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export default function SwitchButton(props) {
  const { setDeploy } = props;

  const changeStyles = (K) => {
    if (K === true) {
      let add_button = document.getElementById("add-button");
      add_button.style.backgroundColor = "#ff0000";

      let remove_button = document.getElementById("remove-button");
      remove_button.style.backgroundColor = "#9e9e9e";
    } else {
      let remove_button = document.getElementById("remove-button");
      remove_button.style.backgroundColor = "#ff0000";

      let add_button = document.getElementById("add-button");
      add_button.style.backgroundColor = "#9e9e9e";
    }
  };

  return (
    <div>
      <ButtonGroup size="large" variant="contained">
        <Button
          id="add-button"
          color="primary"
          text="white"
          onClick={() => {
            setDeploy(true);
            changeStyles(true);
          }}
        >
          Deploy Liquidity
        </Button>

        <Button
          id="remove-button"
          color="secondary"
          text="white"
          onClick={() => {
            setDeploy(false);
            changeStyles(false);
          }}
        >
          Remove Liquidity
        </Button>
      </ButtonGroup>
    </div>
  );
}
Example #14
Source File: ChatChannel.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		if (this.props.channel) {
			return (
				<React.Fragment>
					<ButtonGroup
						orientation="vertical"
						style={{ width: "100%" }}
					>
						<Button
							onClick={this.props.close}
							style={{
								display: "flex",
								justifyContent: "space-between",
								borderTopLeftRadius: "0px",
								borderTopRightRadius: "0px",
								marginTop: "-1px",
							}}
						>
							<span style={{ display: "flex" }}>
								{this.variant.Properties.Nations.length ===
								this.props.channel.Properties.Members.length ? (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={
											this.props.channel.Properties
												.Members
										}
									/>
								) : (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={this.props.channel.Properties.Members.filter(
											(n) => {
												return (
													!this.member ||
													n !== this.member.Nation
												);
											}
										)}
									/>
								)}
							</span>

							{this.props.channel.Properties.Members.length >
							6 ? (
								<span
									style={{
										width: "calc(100% - 96px)",
										textAlign: "left",
										textTransform: "initial",
										lineHeight: "1.2",
									}}
								>
									{this.props.channel.Properties.Members
										.length ===
									this.variant.Properties.Nations.length
										? "Everyone"
										: this.props.channel.Properties.Members.filter(
												(n) => {
													return (
														!this.member ||
														n !== this.member.Nation
													);
												}
										  ).map((n, i) => {
												if (i === 0) {
													return n;
												} else {
													return ", " + n;
												}
										  })}
								</span>
							) : (
								<span
									style={{
										width: "calc(100% - 96px)",
										textAlign: "left",
										textTransform: "initial",
										lineHeight: "1.6",
									}}
								>
									{this.props.channel.Properties.Members
										.length ===
									this.variant.Properties.Nations.length
										? "Everyone"
										: this.props.channel.Properties.Members.filter(
												(n) => {
													return (
														!this.member ||
														n !== this.member.Nation
													);
												}
										  ).map((n, i) => {
												if (i === 0) {
													return n;
												} else {
													return ", " + n;
												}
										  })}
								</span>
							)}

							<ExpandIcon />
						</Button>
					</ButtonGroup>
					<div
						id="messages"
						style={{
							overflowY: "scroll",
							height: "calc(100% - 56px)",
							maxWidth: "962px",
							margin: "auto",
							width: "100%",
							overflowX: "hidden",
						}}
					>
						{this.messageSlice()
							.map((message, idx) => {
								const selfish =
									this.member &&
									this.member.Nation ===
										message.Properties.Sender;
								return (
									<React.Fragment key={message.Properties.ID}>
										{message.phase &&
										(idx === 0 ||
											message.phase.Properties
												.PhaseOrdinal !==
												this.messageSlice()[idx - 1]
													.phase.Properties
													.PhaseOrdinal) ? (
											<div
												style={{
													display: 'flex',
													alignItems: 'center',
													justifyContent: 'center',
												}}
											>
												<Typography
													color="primary"
													display="block"
													variant="subtitle2"
												>
													-------{" "}
													{helpers.phaseName(
														message.phase
													)}{" "}
													------
												</Typography>
											</div>
										) : (
											""
										)}
										{message.Properties.CreatedAt &&
										this.newAfter <
											Date.parse(
												message.Properties.CreatedAt
											) &&
										(idx === 0 ||
											this.newAfter >=
												Date.parse(
													this.messageSlice()[idx - 1]
														.Properties.CreatedAt
												)) ? (
											<div
												style={{
													justifyContent: 'center',
													width: '100%',
													maxWidth: '960px',
													display: 'flex',
													background: 'repeating-linear-gradient( 45deg, rgba(255,0,0,.1), rgba(255,0,0,0.1) 10px, rgba(255,0,0,0) 10px, rgba(255,0,0,0) 20px, rgba(0,0,255,0.1) 20px, rgba(0,0,255,0.1) 30px, rgba(255,255,255,0) 30px, rgba(255,255,255,0) 40px)',
												}}
											>
												<Typography
													variant="subtitle2"
													style={{ color: "#b71c1c" }}
													display="block"
												>
													New messages
												</Typography>
											</div>
										) : (
											""
										)}
										<ChatMessage
											game={this.props.game}
											onNewGameState={
												this.props.onNewGameState
											}
											gameState={this.props.gameState}
											key={message.Properties.ID}
											name={name}
											undelivered={message.undelivered}
											variant={this.variant}
											nation={message.Properties.Sender}
											text={message.Properties.Body}
											time={helpers.timeStrToDateTime(
												message.Properties.CreatedAt
											)}
											sender={selfish ? "self" : ""}
										/>
									</React.Fragment>
								);
							})}
						{this.props.createMessageLink &&
						!(this.props.channel.Properties.Members || []).find(
							(m) => {
								return m === helpers.DiplicitySender;
							}
						) ? (
							<div
								style={{
									display: "flex",
									flexDirection: "column",
									alignItems: "flex-end",
								}}
							>
								<div
									style={{
										display: "flex",
										alignItems: "flex-start",
										maxWidth: "960px",
										width: "calc(100% - 16px)",
										padding: "8px 8px 0px 8px",
										position: "sticky",
										bottom: "0px",
										backgroundColor: "white",
									}}
								>
									<TextField
										id="chat-channel-input-field"
										multiline
										rows="2"
										style={{ flexGrow: 100 }}
										className="chat-channel-input"
										label="Message"
										variant="outlined"
										onKeyDown={this.keyPress}
									/>
									<IconButton
										onClick={this.sendMessage}
										color="primary"
									>
										<SendMessageIcon />
									</IconButton>
								</div>
								<Typography
									id="desktopOnlyInput"
									style={{ marginRight: "56px" }}
									variant="caption"
								>
									Ctrl + Enter to send
								</Typography>
							</div>
						) : (
							""
						)}
					</div>
				</React.Fragment>
			);
		} else {
			return "";
		}
	}
Example #15
Source File: ListUrls.js    From fireshort with MIT License 4 votes vote down vote up
export default function ListUrls(props) {
    const classes = useStyles();

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

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

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

    return (
        <Container className={classes.cardGrid} maxWidth="md">
            <Paper className={classes.root}>
                <TableContainer className={classes.container}>
                    <Table stickyHeader aria-label="sticky table">
                        <TableHead>
                            <TableRow>
                                <TableCell key="curl" align="left" style={{ minWidth: "100px" }}>
                                    Short URL
                                </TableCell>
                                <TableCell key="lurl" align="left" style={{ minWidth: "100px" }}>
                                    Long URL
                                </TableCell>
                                <TableCell key="action" align="right" style={{ minWidth: "100px" }}>
                                    Action
                                </TableCell>
                            </TableRow>
                        </TableHead>
                        <TableBody>
                            {props.shortUrls.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((card) => {
                                return (
                                    <TableRow hover role="checkbox" tabIndex={-1} key={card.id}>
                                        <TableCell key="curl" align="left" style={{ minWidth: "100px" }}>
                                            <Button
                                                startIcon={
                                                    <FileCopyOutlinedIcon />
                                                }
                                                onClick={() => { navigator.clipboard.writeText(window.location.hostname + "/" + card.data.curl) }}
                                                classes={{
                                                    label: classes.label
                                                }}
                                                >{card.data.curl}</Button>
                                        </TableCell>
                                        <TableCell key="lurl" align="left" style={{ minWidth: "100px" }}>
                                            <Box bgcolor="text.primary" color="background.paper" p={2} style={{ overflowX: 'auto', overflowY: 'hidden', whiteSpace: "nowrap" }}>
                                                {card.data.lurl}
                                            </Box>
                                        </TableCell>
                                        <TableCell key="action" align="right" style={{ minWidth: "100px" }}>
                                            <ButtonGroup variant="outlined" color="default">
                                                <Button size="small" color="primary" href={card.data.lurl} target="_blank">
                                                    <VisibilityIcon />
                                                </Button>
                                                <Button size="small" onClick={() => props.handleEditShortUrl(card.data.curl)}>
                                                    <EditIcon />
                                                </Button>
                                                <Button size="small" color="secondary" onClick={() => props.handleDeleteShortUrl(card.data.curl)}>
                                                    <DeleteForeverIcon />
                                                </Button>
                                            </ButtonGroup>
                                        </TableCell>
                                    </TableRow>
                                );
                            })}
                        </TableBody>
                    </Table>
                </TableContainer>
                <TablePagination
                    rowsPerPageOptions={[10, 25, 100]}
                    component="div"
                    count={props.shortUrls.length}
                    rowsPerPage={rowsPerPage}
                    page={page}
                    onChangePage={handleChangePage}
                    onChangeRowsPerPage={handleChangeRowsPerPage}
                />
            </Paper>
        </Container>
    );
}
Example #16
Source File: UserProjects.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function UserProjects View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function UserProjects(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    results: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { results: projects, prev_page, next_page, loading } = state;
  const { t } = props;
  const username = props.match.params.username;
  if (loading) {
    return <LoadingPage />;
  } else if (projects && projects.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container>
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {username}'s {t('userProjects.title')}
              </Typography>
            </Grid>
            {projects.map(project => (
              <Grid
                item
                xs={12}
                sm={6}
                md={4}
                className={classes.projectGridStyle}
                align="center"
              >
                <Project
                  project={project}
                  key={project.id}
                  updateProjects={res =>
                    handleSetState(updateProjects(res, state, props, toast))
                  }
                  {...props}
                />
              </Grid>
            ))}
          </Grid>
          <ButtonGroup
            aria-label={t('userProjects.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) =>
                  handleSetState(fetchPage(page, props))
                }
                primaryButtonStyle
              >
                {t('userProjects.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) =>
                  handleSetState(fetchPage(page, props))
                }
                primaryButtonStyle
              >
                {t('userProjects.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('userProjects.errors.noUserProjects')} />;
  }
}
Example #17
Source File: NewWallet.js    From akashlytics-deploy with GNU General Public License v3.0 4 votes vote down vote up
export function NewWallet() {
  const classes = useStyles();
  const walletsRef = useRef();
  const { enqueueSnackbar } = useSnackbar();
  const [numberOfWords, setNumberOfWords] = useState(12);
  const [error, setError] = useState("");
  const [newWallet, setNewWallet] = useState(null);
  const [shuffledMnemonic, setShuffledMnemonic] = useState([]);
  const [isGeneratingNewWallet, setIsGeneratingNewWallet] = useState(false);
  const [isKeyValidating, setIsKeyValidating] = useState(false);
  const [isKeyValidated, setIsKeyValidated] = useState(false);
  const [isCreatingWallet, setIsCreatingWallet] = useState(false);
  const [selectedWords, setSelectedWords] = useState([]);
  const queryParams = useQueryParams();
  const isAddAccount = !!queryParams.get("add");
  const [hdPath, setHdPath] = useState({ account: 0, change: 0, addressIndex: 0 });
  const history = useHistory();
  const {
    handleSubmit,
    control,
    formState: { errors },
    watch,
    clearErrors
  } = useForm({
    defaultValues: {
      name: "",
      password: "",
      confirmPassword: ""
    }
  });
  const { password } = watch();
  const { setSelectedWallet, setWallets } = useWallet();
  const { setLocalCert, setValidCertificates, setSelectedCertificate, loadLocalCert } = useCertificate();

  useEffect(() => {
    const init = async () => {
      await genNewWallet(numberOfWords);
    };

    if (!isKeyValidating) {
      init();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const genNewWallet = async (numOfWords) => {
    setIsGeneratingNewWallet(true);
    const wallet = await generateNewWallet(numOfWords);
    setNewWallet(wallet);
    const shuffled = wallet.mnemonic
      .split(" ")
      .map((value) => ({ value, sort: Math.random() }))
      .sort((a, b) => a.sort - b.sort)
      .map(({ value }) => value);

    setShuffledMnemonic(shuffled);

    setIsGeneratingNewWallet(false);
  };

  const onNumberChange = async (number) => {
    setNumberOfWords(number);
    await genNewWallet(number);
  };

  const onWordClick = (word, shouldAdd) => {
    setSelectedWords((prevWords) => {
      let newWords;
      if (shouldAdd) {
        newWords = prevWords.concat([word]);
      } else {
        newWords = prevWords.filter((w) => w !== word);
      }

      const originalMnemonic = newWallet.mnemonic.split(" ");
      if (newWords.length === originalMnemonic.length) {
        if (arrayEquals(newWords, originalMnemonic)) {
          setIsKeyValidated(true);
          setError("");
        } else {
          setError("The sequence of words is incorrect.");
        }
      } else {
        setError("");
      }

      return newWords;
    });
  };

  const onBackClick = () => {
    if (isKeyValidating) {
      setIsKeyValidating(false);
      setIsKeyValidated(false);
      setSelectedWords([]);
    } else {
      history.goBack();
    }
  };

  const onHdPathChange = (account, change, addressIndex) => {
    setHdPath({ account, change, addressIndex });
  };

  /**
   * First send to key validation
   * Create new wallet
   */
  const onSubmit = async ({ name, password }) => {
    clearErrors();

    try {
      if (isKeyValidated) {
        setIsCreatingWallet(true);

        const { account, change, addressIndex } = hdPath;

        const importedWallet = await importWallet(newWallet.mnemonic, name, password, account, change, addressIndex);
        const newWallets = walletsRef.current.concat([importedWallet]);

        for (let i = 0; i < newWallets.length; i++) {
          newWallets[i].selected = newWallets[i].address === importedWallet.address;
        }

        setWallets(newWallets);
        setSelectedWallet(importedWallet);
        setValidCertificates([]);
        setSelectedCertificate(null);
        setLocalCert(null);

        // Load local certificates
        loadLocalCert(password);

        await analytics.event("deploy", "create wallet");

        history.replace(UrlService.dashboard());
      } else {
        setIsCreatingWallet(true);

        // validate that all wallets have the same password
        walletsRef.current = await validateWallets(password);

        setIsKeyValidating(true);
        setIsCreatingWallet(false);
      }
    } catch (error) {
      if (error.message === "ciphertext cannot be decrypted using that key") {
        enqueueSnackbar(<Snackbar title="Invalid password" iconVariant="error" />, { variant: "error" });
      } else {
        console.error(error);
        enqueueSnackbar(<Snackbar title="An error has occured" subTitle={error.message} iconVariant="error" />, { variant: "error" });
      }

      setIsCreatingWallet(false);
    }
  };

  return (
    <Layout>
      <div className={classes.root}>
        <TitleLogo />

        <Container maxWidth="xs" className={classes.container}>
          <form onSubmit={handleSubmit(onSubmit)}>
            {isKeyValidating ? (
              <>
                <Typography variant="h6" color="textSecondary">
                  Click your mnemonic seed in the right order
                </Typography>
                <div className={classes.wordBox}>
                  {selectedWords.map((word, i) => (
                    <Button
                      onClick={() => onWordClick(word, false)}
                      variant="contained"
                      color="primary"
                      className={classes.wordButton}
                      key={`selected_word_${i}`}
                      size="small"
                    >
                      {word}
                    </Button>
                  ))}
                </div>

                <hr />

                <div>
                  {shuffledMnemonic
                    .filter((w) => !selectedWords.some((_) => _ === w))
                    .map((word, i) => (
                      <Button onClick={() => onWordClick(word, true)} className={classes.wordButton} variant="outlined" size="small" key={`word_${i}`}>
                        {word}
                      </Button>
                    ))}
                </div>

                <Box marginTop="1rem">
                  {error && (
                    <Alert severity="error" variant="filled">
                      {error}
                    </Alert>
                  )}
                </Box>
              </>
            ) : (
              <>
                <Alert variant="outlined" color="warning" className={classes.alert} icon={false}>
                  <Typography variant="h6" className={classes.alertTitle}>
                    <strong>Backup your mnemonic seed securely</strong>
                  </Typography>

                  <ul className={classes.alertList}>
                    <li>Anyone with your mnemonic seed can take your assets.</li>
                    <li>Lost mnemonic seed can't be recovered.</li>
                    <li>Make sure to write it down somewhere secure.</li>
                    <li>Never share the mnemonic with others or enter it in unverified sites.</li>
                  </ul>
                </Alert>

                <Box display="flex" justifyContent="space-between" marginBottom="1rem">
                  <Typography variant="h5">Mnemonic Seed</Typography>
                  <ButtonGroup variant="contained" size="small">
                    <Button onClick={() => onNumberChange(12)} size="small" color={numberOfWords === 12 ? "primary" : "default"}>
                      12 words
                    </Button>
                    <Button onClick={() => onNumberChange(24)} size="small" color={numberOfWords === 24 ? "primary" : "default"}>
                      24 words
                    </Button>
                  </ButtonGroup>
                </Box>

                <Box marginBottom="1rem">
                  <MnemonicTextarea mnemonic={newWallet?.mnemonic} />
                </Box>

                <FormControl error={!errors.name} className={classes.formControl} fullWidth>
                  <Controller
                    control={control}
                    name="name"
                    rules={{
                      required: true
                    }}
                    render={({ fieldState, field }) => {
                      const helperText = "Account name is required.";

                      return (
                        <TextField
                          {...field}
                          type="text"
                          variant="outlined"
                          label="Account name"
                          autoFocus
                          error={!!fieldState.invalid}
                          helperText={fieldState.invalid && helperText}
                        />
                      );
                    }}
                  />
                </FormControl>

                <FormControl error={!errors.password} className={classes.formControl} fullWidth>
                  <Controller
                    control={control}
                    name="password"
                    rules={{
                      required: true
                    }}
                    render={({ fieldState, field }) => {
                      const helperText = "Password is required.";

                      return (
                        <TextField
                          {...field}
                          type="password"
                          variant="outlined"
                          label="Password"
                          error={!!fieldState.invalid}
                          helperText={fieldState.invalid && helperText}
                        />
                      );
                    }}
                  />
                </FormControl>

                {!isAddAccount && (
                  <FormControl error={!errors.confirmPassword} className={classes.formControl} fullWidth>
                    <Controller
                      control={control}
                      name="confirmPassword"
                      rules={{
                        required: true,
                        validate: (value) => !!value && value === password
                      }}
                      render={({ fieldState, field }) => {
                        const helperText = fieldState.error?.type === "validate" ? "Password doesn't match." : "Confirm password is required.";

                        return (
                          <TextField
                            {...field}
                            type="password"
                            variant="outlined"
                            label="Confirm password"
                            error={!!fieldState.invalid}
                            helperText={fieldState.invalid && helperText}
                          />
                        );
                      }}
                    />
                  </FormControl>
                )}

                <HdPath onChange={onHdPathChange} />
              </>
            )}

            <Box display="flex" alignItems="center" justifyContent="space-between" marginTop="1rem">
              <Box>
                <Button onClick={onBackClick}>Back</Button>
              </Box>

              <Box display="flex" alignItems="center">
                {isKeyValidating && selectedWords.length > 0 && (
                  <Box marginRight=".5rem" display="flex" justifyContent="flex-end">
                    <Button size="small" color="primary" variant="contained" onClick={() => setSelectedWords([])}>
                      Reset
                    </Button>
                  </Box>
                )}

                <Button
                  variant="contained"
                  color="primary"
                  disabled={isGeneratingNewWallet || isCreatingWallet || (isKeyValidating && !isKeyValidated)}
                  type="submit"
                >
                  {isGeneratingNewWallet || isCreatingWallet ? <CircularProgress size="1.5rem" color="primary" /> : <>Next</>}
                </Button>
              </Box>
            </Box>
          </form>
        </Container>
      </div>
    </Layout>
  );
}
Example #18
Source File: UserFollowing.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function UserFollowing View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function UserFollowing(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    following: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { following, prev_page, next_page, loading } = state;
  const { t } = props;

  const username = props.match.params.username;
  if (loading) {
    return <LoadingPage />;
  } else if (following && following.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container spacing={3} justify="center">
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {t('userFollowing.title').replace('<>', username)}
              </Typography>
            </Grid>
            {buildFollowing(following, classes, props, state, handleSetState)}
          </Grid>
          <ButtonGroup
            aria-label={t('userFollowing.ariaLabels.prevNextButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('userFollowing.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('userFollowing.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('userFollowing.errors.noFollowing')} />;
  }
}
Example #19
Source File: UserFollowers.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function UserFollowers View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function UserFollowers(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    followers: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { followers, prev_page, next_page, loading } = state;
  const username = props.match.params.username;
  const { t } = props;
  if (loading) {
    return <LoadingPage />;
  } else if (followers && followers.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container spacing={3} justify="center">
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {username}'s {t('userFollowers.title')}
              </Typography>
            </Grid>
            {buildFollowers(followers, classes, props, state, handleSetState)}
          </Grid>
          <ButtonGroup
            aria-label={t('userFollowers.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('userFollowers.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('userFollowers.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('userFollowers.errors.noFollowers')} />;
  }
}
Example #20
Source File: UserDrafts.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function UserDrafts View
 */
function UserDrafts(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    drafts: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { drafts, prev_page, next_page, loading } = state;
  const { t } = props;
  const username = props.match.params.username;
  if (loading) {
    return <LoadingPage />;
  } else if (drafts && drafts.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container>
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {username}'s {t('userDrafts.title')}
              </Typography>
            </Grid>
            {drafts.map(draft => (
              <Grid
                item
                xs={12}
                sm={6}
                md={4}
                className={classes.projectGridStyle}
                align="center"
              >
                <Project
                  project={draft}
                  key={draft.id}
                  updateProjects={res =>
                    handleSetState(updateDrafts(res, state, props, toast))
                  }
                  {...props}
                />
              </Grid>
            ))}
          </Grid>
          <ButtonGroup
            aria-label={t('userDrafts.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) =>
                  handleSetState(fetchPage(page, props))
                }
                primaryButtonStyle
              >
                {t('userDrafts.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) =>
                  handleSetState(fetchPage(page, props))
                }
                primaryButtonStyle
              >
                {t('userDrafts.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('userDrafts.errors.noUserDrafts')} />;
  }
}
Example #21
Source File: StaffPickDetails.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function StaffPickDetails View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function StaffPickDetails(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    staff_pick: {},
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { staff_pick, loading } = state;
  const { t } = props;
  if (loading) {
    return <LoadingPage />;
  } else if (staff_pick && staff_pick.projects.results.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container>
            <Grid item xs={12}>
              <Typography className={classes.pageHeaderStyle} variant="h3">
                {staff_pick.title}
              </Typography>
            </Grid>
            <Grid item xs={12}>
              <Typography
                className={classes.descriptionBodyStyle}
                color="textSecondary"
                gutterBottom
              >
                {staff_pick.description}
              </Typography>
            </Grid>
            {staff_pick.projects.results.map(project => (
              <Grid
                item
                xs={12}
                sm={6}
                md={4}
                align="center"
                className={classes.projectGridStyle}
              >
                <Project
                  project={project}
                  key={project.id}
                  updateProjects={res =>
                    handleSetState(updateProjects(res, state, props, toast))
                  }
                  {...props}
                />
              </Grid>
            ))}
          </Grid>
          <ButtonGroup
            aria-label={t('staffPickDetails.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {staff_pick.projects.prev ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = staff_pick.projects.prev) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('staffPickDetails.prev')}
              </CustomButton>
            ) : null}
            {staff_pick.projects.next ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = staff_pick.projects.next) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('staffPickDetails.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('staffPickDetails.errors.noStaffPick')} />;
  }
}
Example #22
Source File: SearchResults.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function SearchResults View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function SearchResults(props) {
  const classes = useStyles();
  const common_classes = useCommonStyles();

  const [state, setState] = React.useState({
    results: [],
    count: null,
    previous: null,
    next: null,
    loading: true,
  });

  React.useEffect(() => {
    const params = getQueryParams(window.location.href);

    handleSetState(fetchPage(null, props, params.get('q'), params.get('type')));
  }, []);

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

  const getResults = (type, results) => {
    if (type === SearchType.CREATORS) {
      return buildCreatorProfiles(
        results,
        { classes, common_classes },
        props,
        state,
        handleSetState,
      );
    } else {
      return results.map(project => (
        <Grid
          item
          xs={12}
          sm={6}
          md={4}
          className={classes.projectGridStyle}
          align="center"
        >
          <Project
            project={project}
            key={project.id}
            updateProjects={res =>
              handleSetState(updateProjects(res, state, props, toast))
            }
            {...props}
          />
        </Grid>
      ));
    }
  };

  const {
    count,
    results,
    previous: prev_page,
    next: next_page,
    loading,
  } = state;
  const { t } = props;
  if (loading) {
    return <LoadingPage />;
  } else {
    return (
      <Box className={classes.root}>
        {results && results.length > 0 ? (
          <Container className={classes.mainContainerStyle}>
            <Grid container>
              <Grid item xs={12}>
                <Typography
                  className={classes.pageHeaderStyle}
                  variant="h3"
                  gutterBottom
                >
                  {count}{' '}
                  {count > 1
                    ? t('searchResults.resultsFound')
                    : t('searchResults.resultFound')}{' '}
                  "{getQueryParams(window.location.href).get('q')}"
                </Typography>
              </Grid>
              {getResults(
                getQueryParams(window.location.href).get('type'),
                results,
              )}
            </Grid>
            <ButtonGroup
              aria-label={t('searchResults.ariaLabels.prevNxtButtons')}
              className={classes.buttonGroupStyle}
            >
              {prev_page ? (
                <CustomButton
                  className={classes.floatLeft}
                  size="large"
                  startIcon={<NavigateBeforeIcon />}
                  onClick={(
                    _,
                    page = getQueryParams(prev_page).get('page'),
                  ) => {
                    handleSetState({ loading: true });
                    handleSetState(
                      fetchPage(
                        page,
                        props,
                        getQueryParams(prev_page).get('q'),
                        getQueryParams(window.location.href).get('type'),
                      ),
                    );
                  }}
                  primaryButtonStyle
                >
                  {t('searchResults.prev')}
                </CustomButton>
              ) : null}
              {next_page ? (
                <CustomButton
                  className={classes.floatRight}
                  size="large"
                  endIcon={<NavigateNextIcon />}
                  onClick={(
                    _,
                    page = getQueryParams(next_page).get('page'),
                  ) => {
                    handleSetState({ loading: true });
                    handleSetState(
                      fetchPage(
                        page,
                        props,
                        getQueryParams(next_page).get('q'),
                        getQueryParams(window.location.href).get('type'),
                      ),
                    );
                  }}
                  primaryButtonStyle
                >
                  {t('searchResults.next')}
                </CustomButton>
              ) : null}
            </ButtonGroup>
          </Container>
        ) : (
          <ErrorPage
            style={{ width: '100vw' }}
            error={t('searchResults.errors.noResult')}
          />
        )}
      </Box>
    );
  }
}
Example #23
Source File: SavedProjects.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function SavedProjects View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function SavedProjects(props) {
  const classes = useStyles();

  const [state, setState] = React.useState({
    results: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

  const handleSetState = obj => {
    if (obj) {
      Promise.resolve(obj).then(obj => {
        setState(state => ({ ...state, ...obj }));
      });
    }
  };
  const { results: projects, prev_page, next_page, loading } = state;
  const { t } = props;
  if (loading) {
    return <LoadingPage />;
  } else if (projects && projects.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container>
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {t('savedProjects.title')}
              </Typography>
            </Grid>
            {projects.map(project => (
              <Grid
                item
                xs={12}
                sm={6}
                md={4}
                align="center"
                className={classes.projectGridStyle}
              >
                <Project
                  project={project}
                  key={project.id}
                  updateProjects={res =>
                    handleSetState(updateProjects(res, state, props, toast))
                  }
                  {...props}
                />
              </Grid>
            ))}
          </Grid>
          <ButtonGroup
            aria-label={t('savedProjects.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('savedProjects.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('savedProjects.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return <ErrorPage error={t('savedProjects.errors.noSavedProjects')} />;
  }
}
Example #24
Source File: ChatMenu.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		return (
			<div
				style={{
					position: "relative",
					height: "100%",
				}}
			>
				<Slide
					direction="up"
					in={!!this.state.activeChannel}
					mountOnEnter
					unmountOnExit
				>
					<div
						style={{
							top: 0,
							left: 0,
							bottom: 0,
							right: 0,
							background: "#ffffff",
							position: "absolute",
							zIndex: 1200,
						}}
					>
						<ChatChannel
							onNewGameState={this.props.onNewGameState}
							gameState={this.props.gameState}
							game={this.props.game}
							phases={this.props.phases}
							isActive={this.props.isActive}
							createMessageLink={this.state.createMessageLink}
							channel={this.state.activeChannel}
							close={this.closeChannel}
							loaded={(_) => {
								this.loadChannels(true);
							}}
							parent={this}
						/>
					</div>
				</Slide>
				{this.state.channels && this.state.channels.length > 0 ? (
					""
				) : (
					<Typography>No chat channels currently.</Typography>
				)}
				<ButtonGroup
					orientation="vertical"
					style={{
						width: "100%",
						height: "100%",
						transform: "translateZ(0)",
						WebkitTransform: "translateZ(0)",
						overflowY: !!this.state.activeChannel
							? "hidden"
							: "scroll",
					}}
				>
					{this.state.channels.map((channel) => {
						return (
							<Button
								style={{
									width: "100%",
									justifyContent: "left",
									paddingTop: "12px",
									paddingBottom: "12px",
									border: "none",
									borderBottom: "1px solid rgb(40,26,26,0.1)",
									borderRadius: "0px",
								}}
								onClick={(_) => {
									this.openChannel(channel);
								}}
								key={channel.Properties.Members.join(",")}
							>
								{this.member &&
								channel.Properties.NMessagesSince &&
								channel.Properties.NMessagesSince.NMessages >
									0 ? (
									<Badge
										badgeContent={
											channel.Properties.NMessagesSince
												.NMessages
										}
										overlap="circle"
										color="primary"
									>
										{this.variant.Properties.Nations
											.length ===
										channel.Properties.Members.length ? (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={
													channel.Properties.Members
												}
											/>
										) : (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={channel.Properties.Members.filter(
													(n) => {
														return (
															!this.member ||
															n !==
																this.member
																	.Nation
														);
													}
												)}
											/>
										)}
									</Badge>
								) : this.variant.Properties.Nations.length ===
								  channel.Properties.Members.length ? (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members}
									/>
								) : (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members.filter(
											(n) => {
												return (
													!this.member ||
													n !== this.member.Nation
												);
											}
										)}
									/>
								)}

								{channel.Properties.NMessages &&
								channel.Properties.LatestMessage ? (
									<div
										style={{
											display: "flex",
											flexDirection: "column",
											alignItems: "flex-start",
											marginLeft: "8px",
											minWidth: "0",
										}}
									>
										<Typography
											variant="body1"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{channel.Properties.Members
												.length ===
											this.variant.Properties.Nations
												.length
												? "Everyone"
												: channel.Properties.Members.filter(
														(n) => {
															return (
																!this.member ||
																n !==
																	this.member
																		.Nation
															);
														}
												  ).map((n, i) => {
														if (i === 0) {
															return n;
														} else {
															return ", " + n;
														}
												  })}{" "}
											({channel.Properties.NMessages})
										</Typography>
										<Typography
											variant="body2"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{this.member ? (
												this.member.Nation ===
												channel.Properties.LatestMessage
													.Sender ? (
													<span
														style={{
															fontStyle: "italic",
														}}
													>
														You:{" "}
													</span>
												) : channel.Properties.Members
														.length > 2 ? (
													channel.Properties
														.LatestMessage.Sender +
													": "
												) : (
													""
												)
											) : (
												channel.Properties.LatestMessage
													.Sender + ": "
											)}
											{
												channel.Properties.LatestMessage
													.Body
											}
										</Typography>
									</div>
								) : (
									""
								)}
							</Button>
						);
					})}
				</ButtonGroup>
				{this.state.createMessageLink ? (
					<React.Fragment>
						<Fab
							style={{
								margin: "0px",
								top: "auto",
								right: "20px",
								bottom: "20px",
								left: "auto",
								position: "fixed",
								display: !!this.state.activeChannel
									? "none"
									: "flex",
							}}
							color="secondary"
							aria-label="edit"
							onClick={(_) => {
								this.createChannelDialog.setState({
									open: true,
								});
							}}
						>
							<CreateMessageIcon />
						</Fab>
						<CreateChannelDialog
							game={this.props.game}
							createChannel={(channel) => {
								const newChannels = this.state.channels;
								const oldChannel = newChannels.find((ch) => {
									return helpers.deepEqual(
										channel.Properties.Members,
										ch.Properties.Members
									);
								});
								if (!oldChannel) {
									newChannels.push(channel);
								}
								const channelToUse = oldChannel || channel;
								this.setState(
									{
										channels: newChannels,
									},
									(_) => {
										gtag("event", "create_chat_channel");
										this.openChannel(channelToUse);
									}
								);
							}}
							parentCB={(c) => {
								this.createChannelDialog = c;
							}}
						/>
					</React.Fragment>
				) : (
					""
				)}
			</div>
		);
	}
Example #25
Source File: GroupMembers.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function GroupMembers View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function GroupMembers(props) {
  const classes = useStyles();
  const common_classes = useCommonStyles();

  const [state, setState] = React.useState({
    members: [],
    prev_page: null,
    next_page: null,
    loading: true,
  });

  React.useEffect(() => {
    handleSetState(fetchPage(null, props));
  }, []);

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

  const { members, prev_page, next_page, loading } = state;
  const username = props.match.params.username;
  const { t } = props;
  if (loading) {
    return <LoadingPage />;
  } else if (members && members.length > 0) {
    return (
      <Box className={classes.root}>
        <Container className={classes.mainContainerStyle}>
          <Grid container spacing={3} justify="center">
            <Grid item xs={12}>
              <Typography
                className={classes.pageHeaderStyle}
                variant="h3"
                gutterBottom
              >
                {username}'s {t('groupMembers.title')}
              </Typography>

              {props.auth.members_count !== null &&
              username === props.auth.username ? (
                <CustomButton
                  variant="contained"
                  className={common_classes.floatRight}
                  startIcon={<AddIcon />}
                  primaryButtonStyle
                  onClick={() =>
                    props.history.push(`/creators/${username}/add-members`)
                  }
                >
                  {props.t('groupMembers.newMembers')}
                </CustomButton>
              ) : null}
            </Grid>
            {buildMembers(
              members,
              { classes, common_classes },
              props,
              state,
              handleSetState,
            )}
          </Grid>
          <ButtonGroup
            aria-label={t('groupMembers.ariaLabels.prevNxtButtons')}
            className={classes.buttonGroupStyle}
          >
            {prev_page ? (
              <CustomButton
                className={classes.floatLeft}
                size="large"
                startIcon={<NavigateBeforeIcon />}
                onClick={(e, page = prev_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('groupMembers.prev')}
              </CustomButton>
            ) : null}
            {next_page ? (
              <CustomButton
                className={classes.floatRight}
                size="large"
                endIcon={<NavigateNextIcon />}
                onClick={(e, page = next_page.split('?')[1]) => {
                  handleSetState({ loading: true });
                  handleSetState(fetchPage(page, props));
                }}
                primaryButtonStyle
              >
                {t('groupMembers.next')}
              </CustomButton>
            ) : null}
          </ButtonGroup>
        </Container>
      </Box>
    );
  } else {
    return (
      <>
        {props.auth.members_count !== null &&
        username === props.auth.username ? (
          <CustomButton
            variant="contained"
            className={clsx(
              common_classes.positionAbsolute,
              classes.floatingButtonStyle,
            )}
            startIcon={<AddIcon />}
            primaryButtonStyle
            onClick={() =>
              props.history.push(`/creators/${username}/add-members`)
            }
          >
            {props.t('groupMembers.newMembers')}
          </CustomButton>
        ) : null}
        <ErrorPage error={t('groupMembers.errors.noGroupMembers')} />
      </>
    );
  }
}
Example #26
Source File: DailyTracker.jsx    From archeage-tools with The Unlicense 4 votes vote down vote up
render() {
    const { region, faction, rewards, rewardTypes, showHidden, hideComplete, mobile } = this.props;
    const { setQuestRegion, setQuestFaction, setShowHidden, setHideCompleted, setCollapseCategory } = this.props;
    const { categories, dailyReset, weeklyReset, rewardMenu } = this.state;

    setTitle('Daily Tracker');

    const catIds = categories.map(c => c.id);

    const ResetTimers = (
      <Typography variant="body2" className="reset-timer">
        {dailyReset &&
        <span>Dailies reset in {hhmmssFromDate(dailyReset.diff(moment()))}.</span>}
        {weeklyReset &&
        <span>Weeklies reset in {hhmmssFromDate(weeklyReset.diff(moment()))}.</span>}
      </Typography>
    );

    const ToggleButtons = (
      <>
        <Tooltip title="Collapse All">
          <IconButton onClick={() => setCollapseCategory(catIds, true)} size="small" color="inherit">
            <DoubleArrowIcon />
          </IconButton>
        </Tooltip>
        <Tooltip title="Expand All">
          <IconButton onClick={() => setCollapseCategory(catIds, false)} size="small" color="inherit">
            <DoubleArrowIcon style={{ transform: 'rotate(90deg)' }} />
          </IconButton>
        </Tooltip>
        <Tooltip title={showHidden ? 'Hide Hidden' : 'Show Hidden'}>
          <IconButton onClick={() => setShowHidden(!showHidden)} size="small" color="inherit">
            {showHidden
              ? <VisibilityOffIcon />
              : <VisibilityIcon />}
          </IconButton>
        </Tooltip>
        <Tooltip title={hideComplete ? 'Show Completed' : 'Hide Completed'}>
          <span>
            <IconButton
              onClick={() => setHideCompleted(!hideComplete)} disabled={showHidden} size="small" color="inherit">
              {!showHidden && hideComplete
                ? <RadioButtonUncheckedIcon />
                : <CheckCircleIcon />}
            </IconButton>
          </span>
        </Tooltip>
        <Tooltip title="Filter by Rewards">
          <IconButton onClick={this.handleRewardOpen} size="small" color="inherit">
            <FilterListIcon />
          </IconButton>
        </Tooltip>
        <Menu
          id="reward-filter-menu"
          anchorEl={rewardMenu}
          keepMounted
          open={Boolean(rewardMenu)}
          onClose={this.handleRewardClose}
          variant="menu"
        >
          {Object.values(rewardTypes)
          .filter(type => !HIDDEN_REWARDS.includes(type.name))
          .map(type => (
            <MenuItem
              key={`reward-type-${type.id}`}
              selected={rewards.includes(type.id)}
              onClick={() => this.toggleRewardFilter(type.id)}
            >
              <ListItemIcon style={{ minWidth: 32 }}>
                <span className={cn('dropdown-icon', type.icon)} />
              </ListItemIcon>
              {type.name}
            </MenuItem>
          ))}
          <Divider />
          {CUSTOM_REWARDS
          .map(type => (
            <MenuItem
              key={`reward-type-${type.id}`}
              selected={rewards.includes(type.id)}
              onClick={() => this.toggleRewardFilter(type.id)}
            >
              <ListItemIcon style={{ minWidth: 32 }}>
                <span className={cn('dropdown-icon', type.icon)} />
              </ListItemIcon>
              {type.name}
            </MenuItem>
          ))}
        </Menu>
      </>
    );

    return (
      <div className="daily-container">
        <Paper className="section section-header">
          <AppBar position="static">
            <Toolbar>
              <Typography variant="h5">
                Daily Tracker
              </Typography>
              {!mobile && ResetTimers}
              <div className="title-text" />
              {!mobile && ToggleButtons}
              <FormControl className="color-white">
                <InputLabel id="faction-label">Faction</InputLabel>
                <Select
                  labelId="faction-label"
                  id="faction-select"
                  value={Number(faction) || 1}
                  onChange={(e) => setQuestFaction(e.target.value)}
                >
                  {Object.values(FACTIONS).map(faction =>
                    <MenuItem key={`faction-${faction.id}`} value={faction.id}>{faction.name}</MenuItem>)}
                </Select>
              </FormControl>
              <FormControl className="color-white">
                <InputLabel id="region-label">Publisher</InputLabel>
                <Select
                  labelId="region-label"
                  id="region-select"
                  value={region}
                  onChange={(e) => setQuestRegion(e.target.value)}
                  className="region-opt"
                >
                  {Object.entries(QUEST_REGIONS).map(([region, publisher]) => (
                    <MenuItem key={`region-${region}`} value={region}>{publisher}</MenuItem>
                  ))}
                </Select>
              </FormControl>
            </Toolbar>
          </AppBar>
        </Paper>
        {mobile &&
        <AppBar position="static" className="section">
          <Toolbar>
            {ResetTimers}
            <div className="title-text" />
            {ToggleButtons}
          </Toolbar>
        </AppBar>}
        {mobile &&
        <AppBar position="static" className="section">
          <Toolbar variant="dense" disableGutters style={{ overflowX: 'auto' }}>
            <div className="filter-field padded">
              <ButtonGroup size="small">
                {[...Object.values(rewardTypes), ...CUSTOM_REWARDS]
                .filter(type => !HIDDEN_REWARDS.includes(type.name))
                .map(type => (
                  <Tooltip title={type.name} key={`reward-type-${type.id}`}>
                    <Button
                      variant={rewards.includes(type.id) ? 'contained' : 'outlined'}
                      className={cn({ selected: rewards.includes(type.id) })}
                      onClick={() => this.toggleRewardFilter(type.id)}
                    >
                      <span className={cn('dropdown-icon', type.icon)} />
                    </Button>
                  </Tooltip>
                ))}
              </ButtonGroup>
            </div>
          </Toolbar>
        </AppBar>}
        {categories.length === 0 &&
        <div className="section" style={{ width: 128 }}>
          <CircularProgress size={128} color="primary" />
        </div>}
        {categories.length > 0 &&
        <div className="section daily-grid" ref={this.ref}>
          {categories
          .map((questCat, i) => {
            if (questCat === 'ad') {
              return (
                <div className="daily-category" key={`quest-ad-${i}`}>
                  <AdContainer section={false} content={true} type="feed" />
                </div>
              );
            }
            return (
              <DailyCategory
                key={`quest-cat-${questCat.id}`}
                onUpdate={this._handleResize}
                {...questCat}
              />
            );
          })}
        </div>}
        <ScrollToTop />
        <AdContainer type="horizontal" />
      </div>
    );
  }
Example #27
Source File: Movie.js    From MyMovieTime with MIT License 4 votes vote down vote up
Movie = () => {
  const contextData = useContext(MovieContext);
  const user = useContext(UserContext);
  const classes = useStyles();
  const [mTime, setMTime] = useState({});
  const time = useDebounce(mTime, 500);

  const handleClick = async (val) => {
    var movieId = val.imdbID;
    var movieTime = "";
    var totalMovieTime = 0;
    try {
      const response = await Axios.get(
        `https://www.omdbapi.com/?apikey=${API_KEY}&i=${movieId}`
      );
      if (typeof response.data === "object") {
        contextData.watched.push(response.data);
      }
      if (user) {
        if (contextData.watched.length > 0) {
          addMovieData(contextData.watched, user.uid);
        } else {
          console.log("No Movies Added");
        }
      }

      movieTime = response.data.Runtime;
      totalMovieTime = contextData.totalTime + convertToInt(movieTime);
      contextData.setLoading(false);
      contextData.setTotalTime(totalMovieTime);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    if (time) {
      contextData.setLoading(true);
      handleClick(time);
    }
  }, [time]);

  if (!contextData.loading && contextData.searchArray !== undefined) {
    return (
      <Grid container spacing={4} justify="center">
        {contextData.searchArray.map((item, index) => {
          if (item.Poster !== "N/A") {
            return (
              <Grid item xs={10} sm={4} lg={2} xl={2} key={index}>
                <Card raised={true} className={classes.root}>
                  <CardMedia
                    image={item.Poster}
                    title={item.Title}
                    // height="450px"
                    width="150px"
                    component="img"
                  />
                  <CardContent>
                    <Typography
                      gutterBottom
                      variant="h6"
                      component="h2"
                      noWrap
                      className={classes.titleText}
                    >
                      {item.Title}
                    </Typography>
                    <Typography
                      variant="body2"
                      color="textSecondary"
                      component="p"
                    >
                      {item.Year}
                    </Typography>
                  </CardContent>
                  <CardActions
                    style={{ justifyContent: "center", alignItems: "center" }}
                  >
                    <ButtonGroup
                      orientation="vertical"
                      aria-label="vertical button group"
                      style={{ width: "auto" }}
                    >
                      <Button
                        size="small"
                        variant="contained"
                        color="primary"
                        style={{ marginBottom: "15px" }}
                        onClick={() => {
                          setMTime(item);
                        }}
                      >
                        Add This Movie
                      </Button>
                      <Button
                        size="small"
                        variant="contained"
                        color="primary"
                        style={{ marginBottom: "15px" }}
                      >
                        <a
                          href={`https://www.imdb.com/title/${item.imdbID}`}
                          target="_blank"
                          style={{ textDecoration: "none", color: "white" }}
                        >
                          Check On IMDB
                        </a>
                      </Button>
                    </ButtonGroup>
                  </CardActions>
                </Card>
              </Grid>
            );
          }
        })}
      </Grid>
    );
  } else if (contextData.loading === true) {
    return (
      <div style={{ color: "white", textAlign: "center" }}>
        <img src={loadingImg} alt="loading" />
      </div>
    );
  }
}
Example #28
Source File: ListUrls.js    From FireShort with MIT License 4 votes vote down vote up
export default function ListUrls(props) {
  const classes = useStyles();
  const history = useHistory();

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

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

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

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

                    </TableRow>
                  );
                })}
            </TableBody>
          </Table>
        </TableContainer>
        <TablePagination
          rowsPerPageOptions={[10, 25, 100]}
          component="div"
          count={props.shortUrls.length}
          rowsPerPage={rowsPerPage}
          page={page}
          onChangePage={handleChangePage}
          onChangeRowsPerPage={handleChangeRowsPerPage}
        />
      </Paper>
    </Container>
  );
}
Example #29
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>
  );
}