@material-ui/core#Fab JavaScript Examples

The following examples show how to use @material-ui/core#Fab. 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: CoinField.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 6 votes vote down vote up
export function RemoveLiquidityField2(props) {
  // This component is used to selecting a coin and entering a value, the props are explained below:
  //      onClick - (string) => void - Called when the button is clicked
  //      symbol - string - The text displayed on the button
  //      value - string - The value of the text field
  //      onChange - (e) => void - Called when the text field changes
  //      activeField - boolean - Whether text can be entered into this field or not

  const classes = useStyles();
  const { onClick, symbol } = props;

  return (
    <div className={classes.container_blank}>
      <Grid
        container
        direction="row"
        justifyContent="space-between"
        alignItems="center"
        className={classes.grid}
      >
        {/* Button */}
        <Grid item xs={3}>
          <Fab
            size="small"
            variant="extended"
            onClick={onClick}
            className={classes.fab}
          >
            {symbol}
            <ExpandMoreIcon />
          </Fab>
        </Grid>
      </Grid>
    </div>
  );
}
Example #2
Source File: StartButton.js    From budgie-stream with MIT License 6 votes vote down vote up
export default function StartButton() {
  const classes = useStyles();
  const { playback } = useContext(ClientContext);
  const [state, setState] = playback;

  const devices = state.devices.filter((device) => device.selected === true);
  const disabled = !!!devices.length;

  const handleButtonClick = () => {
    togglePlay(devices, !state.playing);
    setState((prevState) => ({
      ...prevState,
      playing: !prevState.playing,
    }));
  };

  return (
    <div className={classes.root}>
      <Fab
        disabled={disabled}
        style={{ color: "#5e81ac" }}
        onClick={handleButtonClick}
      >
        {state.playing ? <Stop /> : <PlayArrow />}
      </Fab>
    </div>
  );
}
Example #3
Source File: OPEdit.js    From Interceptor with MIT License 6 votes vote down vote up
render() {
    //console.log("Rendering OPEdit");
    const { classes } = this.props;
    const op_data = _.cloneDeep(this.state.op_data);
    return (
      <Fragment>
        <div style={{ padding: 20 }}>
          <Grid
            container
            spacing={2}
            direction="row"
            justify="flex-start"
            alignItems="center"
          >
            {this.renderParams(op_data)}
            <Grid item></Grid>
          </Grid>
        </div>
        <Fab variant="extended" color="secondary" className={classes.loadFab} onClick={() => this.props.procData({ opEdit: { loadRequest: true } })}>
          <ArrowDownwardIcon className={classes.extendedIcon} />
          Load
        </Fab>
        <Fab variant="extended" color="secondary" className={classes.saveFab} onClick={() => this.props.procData({ opEdit: this.state.op_data })}>
          <ArrowUpwardIcon className={classes.extendedIcon} />
          Save
        </Fab>
      </Fragment>
    );
  }
Example #4
Source File: TopPanel.js    From to-view-list with MIT License 6 votes vote down vote up
TopPanel = () => {
  const [, dispatch] = useEntryContext();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('xs'));
  const classes = useTopPanelStyles();

  return (
    <Paper className={classes.root}>
      <Search />
      <Filter />
      {!isMobile ? (
        <Button
          className={classes.desktopButton}
          component={RouterLink}
          to="/add_update"
          size="large"
          variant="contained"
          color="primary"
          startIcon={<PostAddIcon />}
          onClick={() => dispatch(resetEditValues())}
        >
          Add Entry
        </Button>
      ) : (
        <HideOnScroll>
          <Fab
            className={classes.fab}
            color="primary"
            component={RouterLink}
            to="/add_update"
            onClick={() => dispatch(resetEditValues())}
          >
            <PostAddIcon />
          </Fab>
        </HideOnScroll>
      )}
    </Paper>
  );
}
Example #5
Source File: ScrollToTop.jsx    From archeage-tools with The Unlicense 6 votes vote down vote up
render() {
    const { scrollY, height } = this.state;

    return (
      <Zoom in={scrollY >= height * 0.5} unmountOnExit>
        <Fab
          color="primary"
          className="fab"
          onClick={this.handleClick}
        >
          <ExpandLessIcon />
        </Fab>
      </Zoom>
    );
  }
Example #6
Source File: CoinField.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export function RemoveLiquidityField1(props) {
  // This component is used to selecting a coin and entering a value, the props are explained below:
  //      onClick - (string) => void - Called when the button is clicked
  //      symbol - string - The text displayed on the button
  //      value - string - The value of the text field
  //      onChange - (e) => void - Called when the text field changes
  //      activeField - boolean - Whether text can be entered into this field or not

  const classes = useStyles();
  const { onClick, symbol, value, onChange, activeField } = props;
  return (
    <div className={classes.container_blank}>
      <Grid
        container
        direction="row"
        justifyContent="space-between"
        alignItems="center"
        className={classes.grid}
      >
        {/* Button */}
        <Grid item xs={3}>
          <Fab
            size="small"
            variant="extended"
            onClick={onClick}
            className={classes.fab}
          >
            {symbol}
            <ExpandMoreIcon />
          </Fab>
        </Grid>
        {/* Text Field */}
        <Grid item xs={9}>
          <InputBase
            value={value}
            onChange={onChange}
            placeholder="0.0"
            disabled={!activeField}
            classes={{
              root: classes.container_input,
              input: classes.inputBase,
            }}
          />
        </Grid>
        {/* </div> */}
      </Grid>
    </div>
  );
}
Example #7
Source File: MapGeojsonMarkers.jsx    From Zulu with MIT License 5 votes vote down vote up
render() {
    var center = [this.state.lat, this.state.lng];

    const basemapsDict = {
      dark: "	https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png",
      osm: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
      hot: "https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",

    }

    return (
      <Map zoom={this.state.zoom} center={center}>
        <div className="leaflet-bottom leaflet-right buttons-container">
          <Container>
            <Fab
              color="primary"
              aria-label="edit"
              tooltip="Add a new story!"
              onClick={this.showModal}>
              <FaPlus />
            </Fab>
          </Container>
        </div>
        {
          <Modal position={[this.state.lat, this.state.lng]} show={this.state.showModal} onHide={this.closeModal.bind(this)}>

            <form onSubmit={this.handleSubmit}>
              <h3> Add your Story. </h3>
              <label>
                <br />
                      Title:
                      <br />
                <input name="storyTitle" type="text" defaultValue={this.state.storyTitle} onChange={this.handleChange} />
                <br />
              </label>
              <label>
                <br />
                      Body:<br />
                <textarea name="storyBody" defaultValue={this.state.storyBody} onChange={this.handleChange} />
                <br />
              </label>
              <label>
                <br />
                      Add a photo: (optional) <br />
                <input type="file" style={{ marginRight: "-95px" }} ref={this.fileInput} />

                <br />
              </label>
              <br />
              <br />
              <input type="submit" value="Submit" />
            </form>
          </Modal>}


        <TileLayer
          attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url={basemapsDict[this.state.basemap]}
        />
        <Basemap basemap={this.state.basemap} onChange={this.onBMChange} />


        <GeojsonLayer lat={center[0]} lng={center[1]} maxDist={5000} cluster={true} />

        <GeoWikipediaLayer lat={center[0]} lng={center[1]} maxDist={5000} cluster={true} />



        <Marker position={center} icon={MyLocationIcon}>
          <Popup>
            <div>Your Location - latitude: {Number(this.state.lat).toFixed(4)} - longitude: {Number(this.state.lng).toFixed(4)}</div>
          </Popup>
        </Marker>
      </Map>
    );
  }
Example #8
Source File: Waifu.jsx    From animeworldz with MIT License 5 votes vote down vote up
function Waifu() {
  const listInnerRef = useRef(null);
  const [picsList, setPicsList] = useState([]);
  const [refreshKey, setRefreshKey] = useState(0);
  const [keyword, setKeyword] = useState("waifu");
  const classes = useStyles();

  const getWaifuPics = () => {
    axios
      .post(`https://api.waifu.pics/many/sfw/${keyword}`, {})
      .then((res) => setPicsList(res.data))
      .catch((err) => console.log(err));
  };

  useEffect(() => {
    getWaifuPics();
  }, [refreshKey, keyword]);

  let temp = [];
  if (picsList.length !== 0) {
    picsList.files.map((img) => {
      temp.push({
        src: img,
        width: 4,
        height: 4,
      });
    });
  }

  const handleChange = (event) => {
    setKeyword(event.target.value);
  };

  const onScroll = () => {
    if (listInnerRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = listInnerRef.current;
      if (scrollTop + clientHeight === scrollHeight) {
        console.log("reached bottom");
      }
    }
  };

  return (
    <div className={classes.root} ref={listInnerRef} onScroll={onScroll}>
      <Gallery photos={temp ? temp : ""} />
      <Select
        value={keyword}
        onChange={handleChange}
        className={classes.select}
        color="secondary"
        variant="outlined"
        autoFocus={true}
      >
        <MenuItem value={"waifu"}>Waifu</MenuItem>
        <MenuItem value={"neko"}>Neko</MenuItem>
        <MenuItem value={"megumin"}>Megumin</MenuItem>
        <MenuItem value={"cuddle"}>Cuddle</MenuItem>
        <MenuItem value={"pat"}>Pat</MenuItem>
        <MenuItem value={"slap"}>Slap</MenuItem>
        <MenuItem value={"dance"}>Dance</MenuItem>
      </Select>
      <Fab
        color="secondary"
        aria-label="refresh"
        className={classes.fab}
        onClick={() => setRefreshKey((prev) => prev + 1)}
      >
        <RefreshRounded />
      </Fab>
    </div>
  );
}
Example #9
Source File: CoinField.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export default function CoinField(props) {
  // This component is used to selecting a token and entering a value, the props are explained below:
  //      onClick - (string) => void - Called when the button is clicked
  //      symbol - string - The text displayed on the button
  //      value - string - The value of the text field
  //      onChange - (e) => void - Called when the text field changes
  //      activeField - boolean - Whether text can be entered into this field or not

  const classes = useStyles();
  const { onClick, symbol, value, onChange, activeField } = props;

  return (
    <div className={classes.container}>
      <Grid
        container
        direction="row"
        justifyContent="space-between"
        alignItems="center"
        className={classes.grid}
      >
        {/* Button */}
        <Grid item xs={3}>
          <Fab
            size="small"
            variant="extended"
            onClick={onClick}
            className={classes.fab}
          >
            {symbol}
            <ExpandMoreIcon />
          </Fab>
        </Grid>

        {/* Text Field */}
        <Grid item xs={9}>
          <InputBase
            value={value}
            onChange={onChange}
            placeholder="0.0"
            disabled={!activeField}
            classes={{ root: classes.input, input: classes.inputBase }}
          />
        </Grid>
      </Grid>
    </div>
  );
}
Example #10
Source File: VidDropzone.js    From youtube-clone with MIT License 5 votes vote down vote up
function StyledDropzone() {
  const dispatch = useDispatch();

  const classes = useStyles();
  const onDrop = ([videoFile]) => {
    if (videoFile) {
      dispatch(uploadVideo(videoFile));
    }
  };
  const {
    getRootProps,
    getInputProps,
    open,
    isDragAccept,
    isDragReject,
  } = useDropzone({
    noClick: true,
    noKeyboard: true,
    accept: "video/mp4",
    maxSize: 25 * 1024 * 1024,
    onDrop,
  });

  return (
    <div className={classes.root}>
      <div
        {...getRootProps({
          className: clsx(classes.content, {
            [classes.acceptStyle]: isDragAccept,
            [classes.rejectStyle]: isDragReject,
          }),
        })}
      >
        <input {...getInputProps()} />

        <Fab className={clsx(classes.button, classes.uploadBtn)} onClick={open}>
          <PublishIcon className={classes.uploadIcon} />
        </Fab>
        <Typography variant="body1">
          Drag and drop a <strong>.mp4 </strong> file to upload
        </Typography>
        <Typography variant="body2" gutterBottom>
          Your videos will be private until you publish them.
        </Typography>
        <Typography variant="caption" gutterBottom>
          * Video Uploads are limited to 25 MB.
        </Typography>

        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          onClick={open}
        >
          Select File
        </Button>
      </div>
    </div>
  );
}
Example #11
Source File: index.jsx    From playground with MIT License 5 votes vote down vote up
export default function TemporaryDrawer(props) {
  const [state, setState] = React.useState({
    right: false,
  });

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

    setState({ ...state, [anchor]: open });
  };

  return (
    <div>
      <React.Fragment>
        <Fab
          style={{
            position: "fixed",
            right: "0.5rem",
            bottom: "1rem",
          }}
          variant="extended"
          size="small"
          color="secondary"
          onClick={toggleDrawer("right", true)}
        >
          Prop Explorer
        </Fab>
        <Drawer
          anchor={"right"}
          open={state["right"]}
          onClose={toggleDrawer("right", false)}
        >
          <div
            style={{
              width: "70vw",
              maxWidth: 700,
              paddingLeft: "1rem",
            }}
          >
            {props.children}
          </div>
        </Drawer>
      </React.Fragment>
    </div>
  );
}
Example #12
Source File: LoanApprovalPage.js    From SESTA-FMS with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    const { classes } = this.props;

    let data = this.state.data;
    let statusValue = this.state.values.selectedStatus;

    return (
      <Layout breadcrumbs={APPROVE_LOAN_BREADCRUMBS}>
        {!this.state.isLoader ? (
          <Grid>
            <div className="App">
              <h5 className={style.loan}>LOANS</h5>
              <h2 className={style.title}>Loan Approval</h2>

              <Card className={classes.mainContent}>
                <Grid
                  container
                  spacing={3}
                  style={{ padding: "20px 0px", alignItems: "center" }}
                >
                  <Grid spacing={1} xs={1}>
                    <PersonIcon className={classes.Icon} />
                  </Grid>
                  <Grid spacing={1} xs={11}>
                    <Grid container spacing={3}>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            LOANEE
                            <br />
                            <span className={classes.fieldValues}>
                              {data.loanee}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            SHG GROUP <br />
                            <span className={classes.fieldValues}>
                              {data.shg}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            VILLAGE <br />
                            <span className={classes.fieldValues}>
                              {data.village}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            VILLAGE ORGANIZATION <br />
                            <span className={classes.fieldValues}>
                              {data.vo}
                            </span>
                          </div>
                        </b>
                      </Grid>
                    </Grid>
                  </Grid>
                </Grid>
                <Divider />
                <Grid
                  container
                  spacing={3}
                  style={{ padding: "20px 0px", alignItems: "center" }}
                >
                  <Grid spacing={1} xs={1}>
                    <MoneyIcon className={classes.Icon} />
                  </Grid>
                  <Grid spacing={1} xs={11}>
                    <Grid container spacing={3}>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            PURPOSE
                            <br />
                            <span className={classes.fieldValues}>
                              {data.purpose}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            APPLICATION DATE <br />
                            <span className={classes.fieldValues}>
                              {data.applicationDate}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            LOAN AMOUNT <br />
                            <span className={classes.fieldValues}>
                              {data.loanAmount}
                            </span>
                          </div>
                        </b>
                      </Grid>
                      <Grid spacing={2} xs={3}>
                        <b>
                          <div className={classes.member}>
                            LOAN DURATION <br />
                            <span className={classes.fieldValues}>
                              {data.duration}
                            </span>
                          </div>
                        </b>
                      </Grid>
                    </Grid>
                  </Grid>
                </Grid>
                <Divider />
                <Grid container spacing={3} style={{ padding: "20px 0px" }}>
                  <Grid item md={12}>
                    <label htmlFor="upload-file">
                      <input
                        style={{ display: "none" }}
                        required
                        type="file"
                        name="upload-file"
                        id="upload-file"
                        onChange={this.onChangeHandler}
                      />
                      <Fab
                        color="primary"
                        size="medium"
                        component="span"
                        aria-label="add"
                        variant="extended"
                      >
                        <FileCopyIcon /> Upload loan application
                      </Fab>
                    </label>{" "}
                    <IconButton
                      aria-label="cancel"
                      color="secondary"
                      style={{ paddingLeft: "2px" }}
                    >
                      <CancelIcon onClick={this.cancelFile} />
                    </IconButton>
                    &nbsp;&nbsp;&nbsp;
                    {this.state.fileName !== "" ? (
                      <label style={{ color: "green", fontSize: "11px" }}>
                        Selected File: {this.state.fileName}
                      </label>
                    ) : (
                      <label style={{ color: "red", fontSize: "11px" }}>
                        No File Selected!
                      </label>
                    )}
                  </Grid>
                  <Grid item md={5} xs={12}>
                    <Autocomplete
                      id="selectStatus"
                      name="loanStatus"
                      options={this.state.loanStatusList}
                      variant="outlined"
                      getOptionLabel={(option) => option.name}
                      placeholder="Select Status"
                      onChange={this.handleStatusChange}
                      value={
                        statusValue
                          ? this.state.loanStatusList[
                              this.state.loanStatusList.findIndex(function (
                                item,
                                i
                              ) {
                                return item.id === statusValue;
                              })
                            ] || null
                          : null
                      }
                      renderInput={(params) => (
                        <Input
                          {...params}
                          fullWidth
                          label="Select Status"
                          name="loanStatus"
                          variant="outlined"
                        />
                      )}
                    />
                  </Grid>
                  <Grid item md={7} xs={12}>
                    <Input
                      fullWidth
                      label="Comment*"
                      name="comment"
                      error={this.hasError("comment")}
                      helperText={
                        this.hasError("comment")
                          ? this.state.errors.comment[0]
                          : null
                      }
                      value={this.state.values.comment || ""}
                      onChange={this.handleChange}
                      variant="outlined"
                    />
                  </Grid>
                </Grid>
                <Divider />
                <br />
                <Grid>
                  <Button onClick={this.onSave.bind(this)}>Save</Button>
                  &nbsp;&nbsp;&nbsp;
                  <Button
                    color="secondary"
                    clicked={this.cancelForm}
                    component={Link}
                    to="/loans"
                  >
                    Cancel
                  </Button>
                </Grid>
              </Card>
            </div>
          </Grid>
        ) : (
          <Spinner />
        )}
      </Layout>
    );
  }
Example #13
Source File: ActivityPage.js    From SESTA-FMS with GNU Affero General Public License v3.0 4 votes vote down vote up
render() {
    let activitytypeFilter = this.state.getActivitytype;
    let addActivitytype = this.state.values.addActivitytype;
    return (
      <Layout
        breadcrumbs={
          this.state.editPage[0]
            ? EDIT_ACTIVITY_BREADCRUMBS
            : ADD_ACTIVITY_BREADCRUMBS
        }
      >
        {!this.state.isLoader ? (
          <Card style={{ maxWidth: "45rem" }}>
            <CardHeader
              title={this.state.editPage[0] ? "Edit Activity" : "Add Activity"}
              subheader={
                this.state.editPage[0]
                  ? "You can edit activity data here!"
                  : "You can add new activity data here!"
              }
            />
            <Divider />
            <CardContent>
              <Grid container spacing={3}>
                <Grid item md={12} xs={12}>
                  {this.state.formSubmitted === false ? (
                    <Snackbar severity="error" Showbutton={false}>
                      {this.state.errorCode}
                    </Snackbar>
                  ) : null}
                </Grid>
                <Grid item md={6} xs={12}>
                  <Autotext
                    id="combo-box-demo"
                    options={activitytypeFilter}
                    variant="outlined"
                    label="Select Activity Type*"
                    getOptionLabel={(option) => option.name}
                    onChange={(event, value) => {
                      this.handleAutocompleteChange(event, value);
                    }}
                    defaultValue={[]}
                    value={
                      addActivitytype
                        ? activitytypeFilter[
                            activitytypeFilter.findIndex(function (item, i) {
                              return item.id === addActivitytype;
                            })
                          ] || null
                        : null
                    }
                    error={this.hasError("addActivitytype")}
                    helperText={
                      this.hasError("addActivitytype")
                        ? this.state.errors.addActivitytype[0]
                        : null
                    }
                    renderInput={(params) => (
                      <Input
                        fullWidth
                        label="Select Activity Type*"
                        name="addActivitytype"
                        variant="outlined"
                      />
                    )}
                  />
                </Grid>
                <Grid item md={6} xs={12}>
                  <Input
                    fullWidth
                    label="Description*"
                    name="addTitle"
                    error={this.hasError("addTitle")}
                    helperText={
                      this.hasError("addTitle")
                        ? this.state.errors.addTitle[0]
                        : null
                    }
                    value={this.state.values.addTitle || ""}
                    onChange={this.handleChange}
                    variant="outlined"
                  />
                </Grid>
                <Grid item md={3} xs={12}>
                  <Datepicker
                    label="Date*"
                    name="addStartDate"
                    error={this.hasError("addStartDate")}
                    helperText={
                      this.hasError("addStartDate")
                        ? this.state.errors.addStartDate[0]
                        : null
                    }
                    value={this.state.values.addStartDate || null}
                    format={"dd MMM yyyy"}
                    onChange={(value) =>
                      this.setState({
                        values: { ...this.state.values, addStartDate: value },
                      })
                    }
                  />
                </Grid>
                <Grid item md={9} xs={12}>
                  <TextField
                    id="outlined-multiline-static"
                    fullWidth
                    label="Status / Comments"
                    rows={10}
                    name="addDescription"
                    value={this.state.values.addDescription || ""}
                    onChange={this.handleChange}
                    variant="outlined"
                  />
                </Grid>
                <Grid item md={12}>
                  <label htmlFor="upload-file">
                    <input
                      style={{ display: "none" }}
                      required
                      type="file"
                      name="upload-file"
                      id="upload-file"
                      onChange={this.onChangeHandler}
                    />
                    <Fab
                      color="primary"
                      size="medium"
                      component="span"
                      aria-label="add"
                      variant="extended"
                    >
                      <FileCopyIcon /> Upload Activity Document
                    </Fab>
                  </label>{" "}
                  <IconButton
                    aria-label="cancel"
                    color="secondary"
                    style={{ paddingLeft: "2px" }}
                  >
                    <CancelIcon onClick={this.cancelFile} />
                  </IconButton>
                  &nbsp;&nbsp;&nbsp;
                  {this.state.fileName !== "" ? (
                    <label style={{ color: "green", fontSize: "11px" }}>
                      Selected File: {this.state.fileName}
                    </label>
                  ) : (
                    <label style={{ color: "red", fontSize: "11px" }}>
                      No File Selected!
                    </label>
                  )}
                </Grid>
              </Grid>
            </CardContent>
            <Divider />
            <CardActions style={{ padding: "15px" }}>
              <Button type="submit" onClick={this.onSave.bind(this)}>
                Save
              </Button>
              <Button
                color="secondary"
                clicked={this.cancelForm}
                component={Link}
                to="/Activities"
              >
                cancel
              </Button>
            </CardActions>
          </Card>
        ) : (
          <Spinner />
        )}
      </Layout>
    );
  }
Example #14
Source File: PageWrapper.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function PageWrapper View
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function PageWrapper(props) {
  const backToTopEl = React.useRef(null);
  const classes = useStyles();
  const common_classes = useCommonStyles();
  const trigger = useScrollTrigger();
  const [searchType, setSearchType] = useState(
    getQueryParams(window.location.href).get('type') || SearchType.PROJECTS,
  );
  const formRef = useRef();
  const token = useSelector(state => state.auth.token);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  const profileMenuOpen = Boolean(anchor_el);

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

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

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

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

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

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

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

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

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

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

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

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

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

        <Zoom in={useScrollTrigger}>
          <div
            onClick={e => handleScrollTopClick(e, backToTopEl)}
            role="presentation"
            className={classes.scrollTopButtonStyle}
          >
            <Fab color="secondary" size="small" aria-label="scroll back to top">
              <KeyboardArrowUpIcon />
            </Fab>
          </div>
        </Zoom>
      </footer>
    </>
  );
}
Example #15
Source File: Project.jsx    From zubhub with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * @function Project Component
 * @author Raymond Ndibe <[email protected]>
 *
 * @todo - describe function's signature
 */
function Project(props) {
  const classes = useStyles();
  const common_classes = useCommonStyles();

  const { project, t } = props;
  return (
    <Link to={`/projects/${project.id}`} className={classes.textDecorationNone}>
      <Card className={classes.root}>
        <CardMedia className={classes.mediaBoxStyle} title={project.title}>
          <Tooltip
            title={getPublishTypeLabel(project.publish.type)}
            placement="right-start"
            arrow
          >
            <Box className={classes.publishStyle}>
              {project.publish.type === publish_type.Draft
                ? t('project.publish.draft')
                : ''}
              {project.publish.type === publish_type.Preview
                ? t('project.publish.preview')
                : ''}
              {project.publish.type ===
              publish_type['Authenticated Creators'] ? (
                <LockIcon />
              ) : (
                ''
              )}
              {project.publish.type === publish_type.Public ? (
                <PublicIcon />
              ) : (
                ''
              )}
            </Box>
          </Tooltip>
          {project.video ? (
            <>
              <img
                className={classes.mediaImageStyle}
                src={buildVideoThumbnailURL(project.video)}
                alt={project.title}
              />
              <img className={classes.playIconStyle} src={playIcon} alt="" />
            </>
          ) : project.images.length > 0 ? (
            <img
              className={classes.mediaImageStyle}
              src={project.images[0].image_url}
              alt={project.title}
            />
          ) : null}
        </CardMedia>
        <CardActionArea className={classes.actionAreaStyle}>
          <CardContent
            className={clsx(classes.contentStyle, classes.positionRelative)}
          >
            <Fab
              className={classes.fabButtonStyle}
              size="small"
              aria-label="save button"
              onClick={(e, id = project.id) => toggleSave(e, id, props)}
            >
              {project.saved_by.includes(props.auth.id) ? (
                <BookmarkIcon aria-label="unsave" />
              ) : (
                <BookmarkBorderIcon aria-label="save" />
              )}
            </Fab>
            <Fab
              className={clsx(classes.fabButtonStyle, classes.likeButtonStyle)}
              size="small"
              aria-label="like button"
              variant="extended"
              onClick={(e, id = project.id) => toggleLike(e, id, props)}
            >
              {project.likes.includes(props.auth.id) ? (
                <ClapIcon arial-label="unlike" />
              ) : (
                <ClapBorderIcon arial-label="like" />
              )}
              {nFormatter(project.likes.length)}
            </Fab>
            <Typography
              className={classes.titleStyle}
              variant="h5"
              component="h2"
            >
              {project.title}
            </Typography>
            <Box className={classes.descriptionStyle}>
              <Typography
                variant="subtitle2"
                color="textSecondary"
                component="p"
              >
                {formatProjectDescription(project.description)}
              </Typography>
            </Box>
            <Link
              to={`/creators/${project.creator.username}`}
              className={classes.textDecorationNone}
            >
              <Box className={classes.creatorBoxStyle}>
                <Avatar
                  className={classes.creatorAvatarStyle}
                  src={project.creator.avatar}
                  alt={project.creator.username}
                />
                <Typography
                  color="textSecondary"
                  variant="caption"
                  component="p"
                >
                  {project.creator.username}
                </Typography>
                <Link
                  className={common_classes.textDecorationNone}
                  to={`/search/?q=${project.creator.tags[0]}&tab=creators`}
                >
                  <Typography
                    className={clsx(common_classes.baseTagStyle, {
                      [common_classes.extendedTagStyle]: !isBaseTag(
                        project.creator.tags[0],
                      ),
                    })}
                    component="h2"
                  >
                    {project.creator.tags[0]}
                  </Typography>
                </Link>
              </Box>
            </Link>
            <Box className={classes.captionStyle}>
              <Box className={classes.captionStyle}>
                <Typography
                  className={clsx(
                    classes.captionIconStyle,
                    classes.VisibilityIconStyle,
                  )}
                  color="textSecondary"
                  variant="caption"
                  component="span"
                >
                  <VisibilityIcon /> {project.views_count}
                </Typography>
                <Typography
                  className={classes.captionIconStyle}
                  color="textSecondary"
                  variant="caption"
                  component="span"
                >
                  <CommentIcon /> {project.comments_count}
                </Typography>
              </Box>
              <Typography
                color="textSecondary"
                variant="caption"
                component="span"
              >
                {`${dFormatter(project.created_on).value} ${t(
                  `date.${dFormatter(project.created_on).key}`,
                )} ${t('date.ago')}`}
              </Typography>
            </Box>
          </CardContent>
        </CardActionArea>
      </Card>
    </Link>
  );
}
Example #16
Source File: ChatMenu.js    From dipact with GNU General Public License v3.0 4 votes vote down vote up
render() {
		return (
			<div
				style={{
					position: "relative",
					height: "100%",
				}}
			>
				<Slide
					direction="up"
					in={!!this.state.activeChannel}
					mountOnEnter
					unmountOnExit
				>
					<div
						style={{
							top: 0,
							left: 0,
							bottom: 0,
							right: 0,
							background: "#ffffff",
							position: "absolute",
							zIndex: 1200,
						}}
					>
						<ChatChannel
							onNewGameState={this.props.onNewGameState}
							gameState={this.props.gameState}
							game={this.props.game}
							phases={this.props.phases}
							isActive={this.props.isActive}
							createMessageLink={this.state.createMessageLink}
							channel={this.state.activeChannel}
							close={this.closeChannel}
							loaded={(_) => {
								this.loadChannels(true);
							}}
							parent={this}
						/>
					</div>
				</Slide>
				{this.state.channels && this.state.channels.length > 0 ? (
					""
				) : (
					<Typography>No chat channels currently.</Typography>
				)}
				<ButtonGroup
					orientation="vertical"
					style={{
						width: "100%",
						height: "100%",
						transform: "translateZ(0)",
						WebkitTransform: "translateZ(0)",
						overflowY: !!this.state.activeChannel
							? "hidden"
							: "scroll",
					}}
				>
					{this.state.channels.map((channel) => {
						return (
							<Button
								style={{
									width: "100%",
									justifyContent: "left",
									paddingTop: "12px",
									paddingBottom: "12px",
									border: "none",
									borderBottom: "1px solid rgb(40,26,26,0.1)",
									borderRadius: "0px",
								}}
								onClick={(_) => {
									this.openChannel(channel);
								}}
								key={channel.Properties.Members.join(",")}
							>
								{this.member &&
								channel.Properties.NMessagesSince &&
								channel.Properties.NMessagesSince.NMessages >
									0 ? (
									<Badge
										badgeContent={
											channel.Properties.NMessagesSince
												.NMessages
										}
										overlap="circle"
										color="primary"
									>
										{this.variant.Properties.Nations
											.length ===
										channel.Properties.Members.length ? (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={
													channel.Properties.Members
												}
											/>
										) : (
											<NationAvatarGroup
												game={this.props.game}
												newGameState={
													this.props.newGameState
												}
												gameState={this.props.gameState}
												variant={this.variant}
												nations={channel.Properties.Members.filter(
													(n) => {
														return (
															!this.member ||
															n !==
																this.member
																	.Nation
														);
													}
												)}
											/>
										)}
									</Badge>
								) : this.variant.Properties.Nations.length ===
								  channel.Properties.Members.length ? (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members}
									/>
								) : (
									<NationAvatarGroup
										game={this.props.game}
										newGameState={this.props.newGameState}
										gameState={this.props.gameState}
										variant={this.variant}
										nations={channel.Properties.Members.filter(
											(n) => {
												return (
													!this.member ||
													n !== this.member.Nation
												);
											}
										)}
									/>
								)}

								{channel.Properties.NMessages &&
								channel.Properties.LatestMessage ? (
									<div
										style={{
											display: "flex",
											flexDirection: "column",
											alignItems: "flex-start",
											marginLeft: "8px",
											minWidth: "0",
										}}
									>
										<Typography
											variant="body1"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{channel.Properties.Members
												.length ===
											this.variant.Properties.Nations
												.length
												? "Everyone"
												: channel.Properties.Members.filter(
														(n) => {
															return (
																!this.member ||
																n !==
																	this.member
																		.Nation
															);
														}
												  ).map((n, i) => {
														if (i === 0) {
															return n;
														} else {
															return ", " + n;
														}
												  })}{" "}
											({channel.Properties.NMessages})
										</Typography>
										<Typography
											variant="body2"
											style={{
												textTransform: "none",
												overflow: "hidden",
												textOverflow: "ellipsis",
												whiteSpace: "nowrap",
												width: "100%",
												textAlign: "left",
											}}
										>
											{this.member ? (
												this.member.Nation ===
												channel.Properties.LatestMessage
													.Sender ? (
													<span
														style={{
															fontStyle: "italic",
														}}
													>
														You:{" "}
													</span>
												) : channel.Properties.Members
														.length > 2 ? (
													channel.Properties
														.LatestMessage.Sender +
													": "
												) : (
													""
												)
											) : (
												channel.Properties.LatestMessage
													.Sender + ": "
											)}
											{
												channel.Properties.LatestMessage
													.Body
											}
										</Typography>
									</div>
								) : (
									""
								)}
							</Button>
						);
					})}
				</ButtonGroup>
				{this.state.createMessageLink ? (
					<React.Fragment>
						<Fab
							style={{
								margin: "0px",
								top: "auto",
								right: "20px",
								bottom: "20px",
								left: "auto",
								position: "fixed",
								display: !!this.state.activeChannel
									? "none"
									: "flex",
							}}
							color="secondary"
							aria-label="edit"
							onClick={(_) => {
								this.createChannelDialog.setState({
									open: true,
								});
							}}
						>
							<CreateMessageIcon />
						</Fab>
						<CreateChannelDialog
							game={this.props.game}
							createChannel={(channel) => {
								const newChannels = this.state.channels;
								const oldChannel = newChannels.find((ch) => {
									return helpers.deepEqual(
										channel.Properties.Members,
										ch.Properties.Members
									);
								});
								if (!oldChannel) {
									newChannels.push(channel);
								}
								const channelToUse = oldChannel || channel;
								this.setState(
									{
										channels: newChannels,
									},
									(_) => {
										gtag("event", "create_chat_channel");
										this.openChannel(channelToUse);
									}
								);
							}}
							parentCB={(c) => {
								this.createChannelDialog = c;
							}}
						/>
					</React.Fragment>
				) : (
					""
				)}
			</div>
		);
	}
Example #17
Source File: Maps.js    From KEDS-Rideshare-KUHacks with MIT License 4 votes vote down vote up
Maps = compose(
  withProps({
    googleMapURL:
      "https://maps.googleapis.com/maps/api/js?key=AIzaSyAUxSCFAa8dpHXlqjdMlRRvuQm1rbUUP7A&v=3.exp&libraries=geometry,drawing,places",
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div style={{ height: `580px` }} />,
    mapElement: <div style={{ height: `100%` }} />
  }),
  withScriptjs,
  withGoogleMap,

  lifecycle({
    componentDidMount() {
      const DirectionsService = new google.maps.DirectionsService();

      DirectionsService.route(
        {
          origin: new google.maps.LatLng(19.1217707406339, 72.83944134193857),
          destination: new google.maps.LatLng(19.17060002212831, 72.79517092313263),
          travelMode: google.maps.TravelMode.DRIVING
        },

        (result, status) => {
          if (status === google.maps.DirectionsStatus.OK) {
            this.setState({
              directions: result,
              distance: result.routes[ 0 ].legs[ 0 ].distance.text,
              time: result.routes[ 0 ].legs[ 0 ].duration.text,
            });
          } else {
            console.error(`error fetching directions ${result}`);
          }
        }
      );
    },

    componentWillMount() {
      const refs = {}

      this.setState({
        bounds: null,
        source: { lat: 19.1217707406339, lng: 72.83944134193857 },
        destination: { lat: 19.17060002212831, lng: 72.79517092313263 },
        center: {
          lat: 41.9, lng: -87.624
        },
        markers: [],
        onMapMounted: ref => {
          refs.map = ref;
        },
        onBoundsChanged: () => {
          this.setState({
            bounds: refs.map.getBounds(),
            center: refs.map.getCenter(),
          })
        },
        onSourceBoxMounted: ref => {
          refs.sourceBox = ref;
        },
        onDestinationBoxMounted: ref => {
          refs.destinationBox = ref;
        },
        onSourcePlacesChanged: () => {
          const places = refs.sourceBox.getPlaces();
          const bounds = new google.maps.LatLngBounds();

          places.forEach(place => {
            if (place.geometry.viewport) {
              bounds.union(place.geometry.viewport)
            } else {
              bounds.extend(place.geometry.location)
            }
          });
          const nextMarkers = places.map(place => ({
            position: place.geometry.location,
          }));
          const nextCenter = _.get(nextMarkers, '0.position', this.state.center);


          let s = { lat: nextCenter.lat(), lng: nextCenter.lng() };
          this.setState({
            center: nextCenter,
            markers: nextMarkers,
            source: s
          });
          refs.map.fitBounds(bounds);
        },
        onDestinationPlacesChanged: () => {
          console.log(refs);
          const places = refs.destinationBox.getPlaces();
          const bounds = new google.maps.LatLngBounds();

          places.forEach(place => {
            if (place.geometry.viewport) {
              bounds.union(place.geometry.viewport)
            } else {
              bounds.extend(place.geometry.location)
            }
          });
          const nextMarkers = places.map(place => ({
            position: place.geometry.location,
          }));
          const nextCenter = _.get(nextMarkers, '0.position', this.state.center);

          console.log(nextCenter);
          let d = { lat: nextCenter.lat(), lng: nextCenter.lng() };
          this.state.getRoute(this.state.source, d);
          this.setState({
            center: nextCenter,
            markers: nextMarkers,
            destination: d,
          });

          refs.map.fitBounds(bounds);
        },
        getRoute: (source, destination) => {
          console.log('Source', source.lat, source.lng);
          console.log('Destination', destination.lat, destination.lng);
          const DirectionsService = new google.maps.DirectionsService();

          DirectionsService.route(
            {
              origin: new google.maps.LatLng(source),
              destination: new google.maps.LatLng(destination),
              travelMode: google.maps.TravelMode.DRIVING
            },
            (result, status) => {
              if (status === google.maps.DirectionsStatus.OK) {
                console.log(result);
                localStorage.setItem('sourceLat', source.lat);
                localStorage.setItem('sourceLng', source.lng);
                localStorage.setItem('destinationLat', destination.lat);
                localStorage.setItem('destinationLng', destination.lng)
                localStorage.setItem('distance', result.routes[ 0 ].legs[ 0 ].distance.text);
                localStorage.setItem('time', result.routes[ 0 ].legs[ 0 ].duration.text);
                this.setState({
                  directions: result,
                  distance: result.routes[ 0 ].legs[ 0 ].distance.text,
                  time: result.routes[ 0 ].legs[ 0 ].duration.text,
                });
              } else {
                console.error(`error fetching directions ${result}`);
              }
            }
          );
        }
      });
    },
  })
)(props => (
  <GoogleMap defaultZoom={8} ref={props.onMapMounted} defaultCenter={{ lat: 72.77587292177071, lng: 18.89286755846978 }}>
    <SearchBox
      ref={props.onSourceBoxMounted}
      bounds={props.bounds}
      controlPosition={google.maps.ControlPosition.TOP_LEFT}
      onPlacesChanged={props.onSourcePlacesChanged}
    >
      <input
        type="text"
        placeholder="Enter Source"
        style={{
          boxSizing: `border-box`,
          border: `1px solid transparent`,
          width: `240px`,
          height: `32px`,
          marginTop: `27px`,
          padding: `0 12px`,
          borderRadius: `3px`,
          boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
          fontSize: `14px`,
          outline: `none`,
          textOverflow: `ellipses`,
        }}
      />
    </SearchBox>
    <SearchBox
      ref={props.onDestinationBoxMounted}
      bounds={props.bounds}
      controlPosition={google.maps.ControlPosition.TOP_LEFT}
      onPlacesChanged={props.onDestinationPlacesChanged}
    >
      <input
        type="text"
        placeholder="Enter Destination"
        style={{
          boxSizing: `border-box`,
          border: `1px solid transparent`,
          width: `240px`,
          height: `32px`,
          marginTop: `27px`,
          marginLeft: '5px',
          padding: `0 12px`,
          borderRadius: `3px`,
          boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
          fontSize: `14px`,
          outline: `none`,
          textOverflow: `ellipses`,
        }}
      />
    </SearchBox>
    <Fab variant="extended"
      color="secondary"
      href="/admin/steps"
      style={{
        position: "absolute",
        right: "55px",
        bottom: "25px"
      }}
    >
      <LocalTaxi />
  Ride Now
</Fab>
    {props.directions && <DirectionsRenderer directions={props.directions} />}
  </GoogleMap>
))
Example #18
Source File: HeaderView.js    From react-code-splitting-2021-04-26 with MIT License 4 votes vote down vote up
Header = ({ classes, isSidebarOpened, toggleSidebar, ...props }) => (
  <AppBar position="fixed" className={classes.appBar}>
    <Toolbar className={classes.toolbar}>
      <IconButton
        color="inherit"
        onClick={toggleSidebar}
        className={classNames(
          classes.headerMenuButton,
          classes.headerMenuButtonCollapse
        )}
      >
        {isSidebarOpened ? (
          <ArrowBackIcon
            classes={{
              root: classNames(classes.headerIcon, classes.headerIconCollapse)
            }}
          />
        ) : (
          <MenuIcon
            classes={{
              root: classNames(classes.headerIcon, classes.headerIconCollapse)
            }}
          />
        )}
      </IconButton>
      <Typography variant="h6" weight="medium" className={classes.logotype}>React Material Admin</Typography>
      <div className={classes.grow} />
      <div
        className={classNames(classes.search, {
          [classes.searchFocused]: props.isSearchOpen
        })}
      >
        <div
          className={classNames(classes.searchIcon, {
            [classes.searchIconOpened]: props.isSearchOpen
          })}
          onClick={props.toggleSearch}
        >
          <SearchIcon classes={{ root: classes.headerIcon }} />
        </div>
        <InputBase
          placeholder="Search…"
          classes={{
            root: classes.inputRoot,
            input: classes.inputInput
          }}
        />
      </div>
      <IconButton
        color="inherit"
        aria-haspopup="true"
        aria-controls="mail-menu"
        onClick={props.openNotificationsMenu}
        className={classes.headerMenuButton}
      >
        <Badge
          badgeContent={
            props.isNotificationsUnread ? notifications.length : null
          }
          colortheme="warning"
        >
          <NotificationsIcon classes={{ root: classes.headerIcon }} />
        </Badge>
      </IconButton>
      <IconButton
        color="inherit"
        aria-haspopup="true"
        aria-controls="mail-menu"
        onClick={props.openMailMenu}
        className={classes.headerMenuButton}
      >
        <Badge
          badgeContent={props.isMailsUnread ? messages.length : null}
          color="secondary"
        >
          <MailIcon classes={{ root: classes.headerIcon }} />
        </Badge>
      </IconButton>
      <IconButton
        aria-haspopup="true"
        color="inherit"
        className={classes.headerMenuButton}
        aria-controls="profile-menu"
        onClick={props.openProfileMenu}
      >
        <AccountIcon classes={{ root: classes.headerIcon }} />
      </IconButton>
      <Menu
        id="mail-menu"
        open={Boolean(props.mailMenu)}
        anchorEl={props.mailMenu}
        onClose={props.closeMailMenu}
        MenuListProps={{ className: classes.headerMenuList }}
        className={classes.headerMenu}
        classes={{ paper: classes.profileMenu }}
        disableAutoFocusItem
      >
        <div className={classes.profileMenuUser}>
          <Typography variant="h4" weight="medium">
            New Messages
          </Typography>
          <Typography
            className={classes.profileMenuLink}
            component="a"
            color="secondary"
          >
            {messages.length} New Messages
          </Typography>
        </div>
        {messages.map(message => (
          <MenuItem key={message.id} className={classes.messageNotification}>
            <div className={classes.messageNotificationSide}>
              <UserAvatar color={message.variant} name={message.name} />
              <Typography size="sm" color="textSecondary">
                {message.time}
              </Typography>
            </div>
            <div
              className={classNames(
                classes.messageNotificationSide,
                classes.messageNotificationBodySide
              )}
            >
              <Typography weight="medium" gutterBottom>
                {message.name}
              </Typography>
              <Typography color="textSecondary">{message.message}</Typography>
            </div>
          </MenuItem>
        ))}
        <Fab
          variant="extended"
          color="primary"
          aria-label="Add"
          className={classes.sendMessageButton}
        >
          Send New Message
          <SendIcon className={classes.sendButtonIcon} />
        </Fab>
      </Menu>
      <Menu
        id="notifications-menu"
        open={Boolean(props.notificationsMenu)}
        anchorEl={props.notificationsMenu}
        onClose={props.closeNotificationsMenu}
        className={classes.headerMenu}
        disableAutoFocusItem
      >
        {notifications.map(notification => (
          <MenuItem
            key={notification.id}
            onClick={props.closeNotificationsMenu}
            className={classes.headerMenuItem}
          >
            <Notification {...notification} typographyVariant="inherit" />
          </MenuItem>
        ))}
      </Menu>
      <Menu
        id="profile-menu"
        open={Boolean(props.profileMenu)}
        anchorEl={props.profileMenu}
        onClose={props.closeProfileMenu}
        className={classes.headerMenu}
        classes={{ paper: classes.profileMenu }}
        disableAutoFocusItem
      >
        <div className={classes.profileMenuUser}>
          <Typography variant="h4" weight="medium">
            John Smith
          </Typography>
          <Typography
            className={classes.profileMenuLink}
            component="a"
            color="primary"
            href="https://flatlogic.com"
          >
            Flalogic.com
          </Typography>
        </div>
        <MenuItem
          className={classNames(
            classes.profileMenuItem,
            classes.headerMenuItem
          )}
        >
          <AccountIcon className={classes.profileMenuIcon} /> Profile
        </MenuItem>
        <MenuItem
          className={classNames(
            classes.profileMenuItem,
            classes.headerMenuItem
          )}
        >
          <AccountIcon className={classes.profileMenuIcon} /> Tasks
        </MenuItem>
        <MenuItem
          className={classNames(
            classes.profileMenuItem,
            classes.headerMenuItem
          )}
        >
          <AccountIcon className={classes.profileMenuIcon} /> Messages
        </MenuItem>
        <div className={classes.profileMenuUser}>
          <Typography
            className={classes.profileMenuLink}
            color="primary"
            onClick={props.signOut}
          >
            Sign Out
          </Typography>
        </div>
      </Menu>
    </Toolbar>
  </AppBar>
)
Example #19
Source File: Header.js    From react-code-splitting-2021-04-26 with MIT License 4 votes vote down vote up
export default function Header(props) {
  var classes = useStyles();

  // global
  var layoutState = useLayoutState();
  var layoutDispatch = useLayoutDispatch();
  var userDispatch = useUserDispatch();

  // local
  var [mailMenu, setMailMenu] = useState(null);
  var [isMailsUnread, setIsMailsUnread] = useState(true);
  var [notificationsMenu, setNotificationsMenu] = useState(null);
  var [isNotificationsUnread, setIsNotificationsUnread] = useState(true);
  var [profileMenu, setProfileMenu] = useState(null);
  var [isSearchOpen, setSearchOpen] = useState(false);

  return (
    <AppBar position="fixed" className={classes.appBar}>
      <Toolbar className={classes.toolbar}>
        <IconButton
          color="inherit"
          onClick={() => toggleSidebar(layoutDispatch)}
          className={classNames(
            classes.headerMenuButtonSandwich,
            classes.headerMenuButtonCollapse,
          )}
        >
          {layoutState.isSidebarOpened ? (
            <ArrowBackIcon
              classes={{
                root: classNames(
                  classes.headerIcon,
                  classes.headerIconCollapse,
                ),
              }}
            />
          ) : (
            <MenuIcon
              classes={{
                root: classNames(
                  classes.headerIcon,
                  classes.headerIconCollapse,
                ),
              }}
            />
          )}
        </IconButton>
        <Typography variant="h6" weight="medium" className={classes.logotype}>
          React Material Admin
        </Typography>
        <div className={classes.grow} />
        <Button component={Link} href="https://flatlogic.com/templates/react-material-admin-full" variant={"outlined"} color={"secondary"} className={classes.purchaseBtn}>Unlock full version</Button>
        <div
          className={classNames(classes.search, {
            [classes.searchFocused]: isSearchOpen,
          })}
        >
          <div
            className={classNames(classes.searchIcon, {
              [classes.searchIconOpened]: isSearchOpen,
            })}
            onClick={() => setSearchOpen(!isSearchOpen)}
          >
            <SearchIcon classes={{ root: classes.headerIcon }} />
          </div>
          <InputBase
            placeholder="Search…"
            classes={{
              root: classes.inputRoot,
              input: classes.inputInput,
            }}
          />
        </div>
        <IconButton
          color="inherit"
          aria-haspopup="true"
          aria-controls="mail-menu"
          onClick={e => {
            setNotificationsMenu(e.currentTarget);
            setIsNotificationsUnread(false);
          }}
          className={classes.headerMenuButton}
        >
          <Badge
            badgeContent={isNotificationsUnread ? notifications.length : null}
            color="warning"
          >
            <NotificationsIcon classes={{ root: classes.headerIcon }} />
          </Badge>
        </IconButton>
        <IconButton
          color="inherit"
          aria-haspopup="true"
          aria-controls="mail-menu"
          onClick={e => {
            setMailMenu(e.currentTarget);
            setIsMailsUnread(false);
          }}
          className={classes.headerMenuButton}
        >
          <Badge
            badgeContent={isMailsUnread ? messages.length : null}
            color="secondary"
          >
            <MailIcon classes={{ root: classes.headerIcon }} />
          </Badge>
        </IconButton>
        <IconButton
          aria-haspopup="true"
          color="inherit"
          className={classes.headerMenuButton}
          aria-controls="profile-menu"
          onClick={e => setProfileMenu(e.currentTarget)}
        >
          <AccountIcon classes={{ root: classes.headerIcon }} />
        </IconButton>
        <Menu
          id="mail-menu"
          open={Boolean(mailMenu)}
          anchorEl={mailMenu}
          onClose={() => setMailMenu(null)}
          MenuListProps={{ className: classes.headerMenuList }}
          className={classes.headerMenu}
          classes={{ paper: classes.profileMenu }}
          disableAutoFocusItem
        >
          <div className={classes.profileMenuUser}>
            <Typography variant="h4" weight="medium">
              New Messages
            </Typography>
            <Typography
              className={classes.profileMenuLink}
              component="a"
              color="secondary"
            >
              {messages.length} New Messages
            </Typography>
          </div>
          {messages.map(message => (
            <MenuItem key={message.id} className={classes.messageNotification}>
              <div className={classes.messageNotificationSide}>
                <UserAvatar color={message.variant} name={message.name} />
                <Typography size="sm" color="text" colorBrightness="secondary">
                  {message.time}
                </Typography>
              </div>
              <div
                className={classNames(
                  classes.messageNotificationSide,
                  classes.messageNotificationBodySide,
                )}
              >
                <Typography weight="medium" gutterBottom>
                  {message.name}
                </Typography>
                <Typography color="text" colorBrightness="secondary">
                  {message.message}
                </Typography>
              </div>
            </MenuItem>
          ))}
          <Fab
            variant="extended"
            color="primary"
            aria-label="Add"
            className={classes.sendMessageButton}
          >
            Send New Message
            <SendIcon className={classes.sendButtonIcon} />
          </Fab>
        </Menu>
        <Menu
          id="notifications-menu"
          open={Boolean(notificationsMenu)}
          anchorEl={notificationsMenu}
          onClose={() => setNotificationsMenu(null)}
          className={classes.headerMenu}
          disableAutoFocusItem
        >
          {notifications.map(notification => (
            <MenuItem
              key={notification.id}
              onClick={() => setNotificationsMenu(null)}
              className={classes.headerMenuItem}
            >
              <Notification {...notification} typographyVariant="inherit" />
            </MenuItem>
          ))}
        </Menu>
        <Menu
          id="profile-menu"
          open={Boolean(profileMenu)}
          anchorEl={profileMenu}
          onClose={() => setProfileMenu(null)}
          className={classes.headerMenu}
          classes={{ paper: classes.profileMenu }}
          disableAutoFocusItem
        >
          <div className={classes.profileMenuUser}>
            <Typography variant="h4" weight="medium">
              John Smith
            </Typography>
            <Typography
              className={classes.profileMenuLink}
              component="a"
              color="primary"
              href="https://flatlogic.com"
            >
              Flalogic.com
            </Typography>
          </div>
          <MenuItem
            className={classNames(
              classes.profileMenuItem,
              classes.headerMenuItem,
            )}
          >
            <AccountIcon className={classes.profileMenuIcon} /> Profile
          </MenuItem>
          <MenuItem
            className={classNames(
              classes.profileMenuItem,
              classes.headerMenuItem,
            )}
          >
            <AccountIcon className={classes.profileMenuIcon} /> Tasks
          </MenuItem>
          <MenuItem
            className={classNames(
              classes.profileMenuItem,
              classes.headerMenuItem,
            )}
          >
            <AccountIcon className={classes.profileMenuIcon} /> Messages
          </MenuItem>
          <div className={classes.profileMenuUser}>
            <Typography
              className={classes.profileMenuLink}
              color="primary"
              onClick={() => signOut(userDispatch, props.history)}
            >
              Sign Out
            </Typography>
          </div>
        </Menu>
      </Toolbar>
    </AppBar>
  );
}
Example #20
Source File: Admin.js    From FireShort with MIT License 4 votes vote down vote up
render() {
    const { classes } = this.props;
    const { inputBackdrop, newPsw } = this.state;

    return (
      <React.Fragment>
        {inputBackdrop ? (
          <div
            style={{
              position: 'fixed',
              width: '100vw',
              height: '100vh',
              background: 'rgb(0,0,0,.5)',
              display: 'grid',
              placeItems: 'center',
              zIndex: 10,
            }}
          >
            <div style={{ padding: "20px", backgroundColor: "white" }}>
              <h3>Protect Link With Password</h3>
              <div style={{ display: "block", padding: "20px" }}>
                <input
                  placeholder='Enter Password...'
                  value={newPsw}
                  style={{ padding: "15px", fontSize: "15px", borderRadius: "2px", width: "100%" }}
                  onChange={(e) => this.setState({ newPsw: e.target.value })}
                />
                <div style={{ marginTop: "25px" }}>
                  <button onClick={(e) => this.onPswSave(e)} style={{ padding: "12px", color: "white", backgroundColor: "black", fontSize: "15px", border: "none", marginRight: "15px", borderRadius: "5px", cursor: "pointer" }}>Save</button>
                  <button onClick={(e) => this.setState({ inputBackdrop: false })} style={{ padding: "12px", color: "white", backgroundColor: "red", fontSize: "15px", border: "none", marginRight: "15px", borderRadius: "5px", cursor: "pointer" }}>Cancel</button>
                </div>
              </div>
            </div>
          </div>
        ) : null}
        <CssBaseline />
        <Header />
        {this.state.loading && <LinearProgress color='secondary' />}
        <main>
          <MainToolBar
            state={this.state}
            updateViewMode={this.updateViewMode}
            refresh={this.updateUrls}
          />
          {this.state.shortUrls.length > 0 ? (
            <>
              {this.state.viewMode === 'module' ? (
                <CardUrls
                  shortUrls={this.props.links}
                  handleEditShortUrl={this.handleEditShortUrl}
                  handleDeleteShortUrl={this.handleDeleteShortUrl}
                  openHits={this.getHits}
                // updateHits={this.updateUrls}
                  toggleSecurity={this.toggleSecurity}
                />
              ) : (
                  <ListUrls
                    shortUrls={this.state.shortUrls}
                    handleEditShortUrl={this.handleEditShortUrl}
                    handleDeleteShortUrl={this.handleDeleteShortUrl}
                    toggleSecurity={this.toggleSecurity}
                    openHits={this.getHits}
                  />
                )}
            </>
          ) : (  
              <>                            
                  {this.state.loading == false &&                      
                    <Container maxWidth='md'>
                      <img src={'/Images/pixeltrue-search.svg'} style={{margin: "30px auto", display: "block", width: "100%", maxHeight: "400px" }} />
                      <Card className={classes.toolBarRoot} style={{marginBottom: "30px"}}>
                        <Typography align="center" style={{padding: "30px 60px"}} variant="h6">
                          Oops! Looks like you don't have any links. Press the "+" icon below to start adding links.
                        </Typography>   
                      </Card>                                
                    </Container>              
                  }
              </>                                
            )}

          <Fab
            aria-label='Add'
            className={classes.fab}
            color='primary'
            onClick={this.handleClickOpen}
          >
            <AddIcon />
          </Fab>

          <Backdrop className={classes.backdrop} open={this.state.backdrop}>
            <CircularProgress color='inherit' />
          </Backdrop>

          <UrlsDialog
            state={this.state}
            handleClose={this.handleClose}
            handleLurlChange={this.handleLurlChange}
            handleCurlChange={this.handleCurlChange}
            handleSubmit={this.handleSubmit}
            handleTrackChange={this.handleTrackChange}
            handleProtectChange={this.handleProtectChange}
            handlePswChange={this.handlePswChange}
          />

          <HitsDialog
            state={this.state}
            hitActivity={this.state.hits}
            handleClose={this.handleClose}
          />

          <Snackbar
            open={this.state.successToast}
            autoHideDuration={6000}
            onClose={this.handleToastClose}
          >
            <Alert onClose={this.handleToastClose} severity='success'>
              Successfully added!
            </Alert>
          </Snackbar>
        </main>
      </React.Fragment>
    );
  }
Example #21
Source File: Dashboard.js    From jobtriage with MIT License 4 votes vote down vote up
Dashboard = () => {
  const showToast = useToast();
  const showLoader = useLoader();
  const classes = useStyles();
  const history = useHistory();
  const [applicationsData, setApplicationsData] = React.useState();
  const [boardData, setBoardData] = useState(data);
  const [openJobAdd, setOpenJobAdd] = React.useState(false);

  const handleJobAddOpen = () => {
    setOpenJobAdd(true);
  };

  const handleJobAddClose = () => {
    setOpenJobAdd(false);
  };

  const getJobApplications = () => {
    showLoader(true);
    APIService.getJobApplications()
      .then(resp => {
        const appData = resp.data;
        setApplicationsData(appData);
        const parsedData = parseApplicationData(appData);
        setBoardData(parsedData);
      }).finally(() => showLoader(false));
  };

  useEffect(() => {
    getJobApplications();
  }, []);

  const handleDrag = (id, source, target) => {
    if (source !== target) {
      APIService.updateApplicationStatus(id, target)
        .catch(() => showToast('Error while deleting updating Job application', ToastConstants.ERROR));
    }
  };

  const cardDelete = id => {
    APIService.deleteApplication(id).catch(() => showToast('Error while deleting Job application', ToastConstants.ERROR));
  };

  const isEmptyBoard = () => {
    return applicationsData.length === 0;
  };

  return (
    <div>
      { applicationsData
        ? (
          <div>
            <Typography color="primary" variant="h5">
              Dashboard
            </Typography>
            { isEmptyBoard() && <EmptyBoard /> }

            {!isEmptyBoard() && (
            <Board
              data={boardData}
              style={{ backgroundColor: '#fff', height: 'auto' }}
              handleDragEnd={handleDrag}
              onCardDelete={cardDelete}
              onCardClick={cardId => history.push(`/application/${cardId}`)}
              laneStyle={{ backgroundColor: '#d9c8f5' }}
              cardStyle={{ backgroundColor: '#ffe' }}
            />
            )}

            <Fab
              color="primary"
              aria-label="Add job"
              className={classes.fab}
              onClick={handleJobAddOpen}
            >
              <Add />
            </Fab>
            <AddJob
              open={openJobAdd}
              onClose={handleJobAddClose}
              onChange={getJobApplications}
            />
          </div>
        )
        : <HorizontalLoader />}
    </div>
  );
}
Example #22
Source File: Employee.js    From inventory-management-web with MIT License 4 votes vote down vote up
export default function Employee() {
  // list of employees got from API
  const [employeeList, setEmployeeList] = useState([]);
  // contains the index of the row, if delete is used
  const [deletedRow, setDeletedRow] = useState([]);
  // true when waiting for an response from API
  const [isLoading, setIsLoading] = useState(false);
  // dialog box
  const [open, setOpen] = useState(false);
  // row to be selected on clicking the delete icon
  const [selectedRow, setSelectedRow] = useState({});

  const history = useHistory();

  const { setSnack } = useContext(SnackContext);

  const handleClickOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  const apiFetch = async () => {
    try {
      setIsLoading(true);
      const response = await getEndPoint('/auth/users/', null, history);
      const { data } = response;
      // map genders got from API
      const genderMapper = { M: 'Male', F: 'Female', Other: 'Other' };
      const list = data.map(val => ({
        firstName: val.first_name,
        lastName: val.last_name,
        name: `${val.first_name} ${val.last_name}`,
        age: val.age,
        gender: genderMapper[val.gender],
        email: val.email,
        isStaff: val.is_staff,
      }));
      setEmployeeList(list);
      setIsLoading(false);
    } catch (e) {
      console.log(e);
    }
  };

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

  const classes = useStyles();

  // handle click on the FAB
  const handleFabClick = () => {
    history.push('/addemployee');
  };

  // handle user edit
  const handleEdit = row => {
    console.log(row);
    // open the create user form and pass the data as props
    history.push('/updateemployee', {
      firstName: row.firstName,
      lastName: row.lastName,
      age: row.age,
      isStaff: row.isStaff,
      email: row.email,
    });
  };

  // handle user delete
  const handleDelete = async row => {
    setIsLoading(true);
    const { email, name } = row;
    setDeletedRow(prevState => [...prevState, employeeList.indexOf(row)]);
    try {
      const formData = new FormData();
      formData.append('email', email);
      await postEndPoint('/auth/user_delete/', formData, null, history);
      setIsLoading(false);
      // add success snackbar on successful request
      setSnack({
        open: true,
        message: `Succesfully deleted ${name}`,
        action: '',
        actionParams: '',
        type: 'success',
      });
    } catch (e) {
      console.log(e);
    }
  };

  return (
    <>
      {isLoading ? <Spinner /> : null}
      <Typography variant='h3' className={classes.heading}>
        Employees
      </Typography>
      <Paper className={classes.paper}>
        <TableContainer>
          <Table className={classes.table} aria-label='simple table'>
            <TableHead>
              <TableRow>
                <TableCell />
                <TableCell>Name</TableCell>
                <TableCell>Gender</TableCell>
                <TableCell>Email</TableCell>
                <TableCell align='right'>Age</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {employeeList.map((row, index) => (
                <TableRow
                  key={row.email}
                  hover
                  className={deletedRow.includes(index) ? 'delete' : ''}
                >
                  <TableCell className={classes.firstColumn}>
                    <Hidden xsDown>
                      <IconButton
                        onClick={() => {
                          handleEdit(row);
                        }}
                      >
                        <EditIcon />
                      </IconButton>
                      <IconButton
                        onClick={() => {
                          setSelectedRow(row);
                          handleClickOpen();
                        }}
                      >
                        <DeleteIcon />
                      </IconButton>
                    </Hidden>
                    <Hidden smUp>
                      <MobileEditMenu
                        handleDelete={() => {
                          setSelectedRow(row);
                          handleClickOpen();
                        }}
                        handleEdit={handleEdit}
                        row={row}
                      />
                    </Hidden>
                  </TableCell>
                  <TableCell>{row.name}</TableCell>
                  <TableCell>{row.gender}</TableCell>
                  <TableCell>{row.email}</TableCell>
                  <TableCell align='right'>{row.age}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      </Paper>

      <DialogBox
        open={open}
        handleClose={handleClose}
        selectedRow={selectedRow}
        handleDelete={handleDelete}
        number='1'
      />

      <Fab
        color='primary'
        aria-label='add'
        className={classes.fab}
        onClick={handleFabClick}
      >
        <AddIcon />
      </Fab>
    </>
  );
}
Example #23
Source File: SetScaleModal.js    From floor-plan-lab with MIT License 4 votes vote down vote up
function SetScaleModal() {
  const classes = useStyles();
  const dispatch = useDispatch();
  const [scaleModalOpen, setScaleModalOpen] = React.useState(false);
  const [feetInput, setFeetInput] = React.useState(1);
  const [inchesInput, setInchesInput] = React.useState(0);
  const scale = useSelector(state => state.sheet.scale);

  const handleClose = () => {
    setScaleModalOpen(false);
  };

  const toggleModal = () => {
    setScaleModalOpen(!scaleModalOpen);
    setFeetInput(scale.ft);
    setInchesInput(scale.in);
  }

  const handleFeetInput = (value) => {
    setFeetInput(value);
  }

  const handleInchesInput = (value) => {
    setInchesInput(value);
  }

  const onSave = () => {
    const feet = parseInt(feetInput);
    const inches = parseInt(inchesInput);
    if (feet > 0 || inches > 0) {
      // Valid number entered
      dispatch(setScale({ ft: feet, in: inches }));
      setScaleModalOpen(false);
    } else {
      // Error
    }
  }

  return (
    <>
      <Tooltip title={<span className={classes.toolTip}>Change Scale</span>} placement='top' arrow>
        <Fab onClick={toggleModal} variant="extended" size='small' className={classes.fab} style={{ paddingLeft: 16, paddingRight: 16, }}>
          <span className="far fa-square" style={{ paddingRight: 8 }}></span>
            = {scale.ft}'{scale.in}"
          </Fab>
      </Tooltip>

      <Modal
        open={scaleModalOpen}
        onClose={handleClose}
        aria-labelledby="change-scale"
      >
        <Paper className={classes.paper}>
          <Grid container spacing={2}>
            <Grid item xs={12}>
              <Typography variant='h6'>
                Grid Scale
              </Typography>
            </Grid>



            <Grid item xs={12}>
              <Grid container>
                <Grid item>
                  <img src={boxSideLengthImg} className={classes.img} />
                </Grid>
                <Grid item>
                  <Grid container className={classes.inputContainer}>
                    <Grid item>
                      <NumericInput strict min={0} max={50} size={3} value={feetInput} onChange={(e) => handleFeetInput(e)} />
                    </Grid>
                    <Grid item xs>
                      <Typography style={{ paddingLeft: 4 }}>Feet</Typography>
                    </Grid>
                  </Grid>
                </Grid>

                <Grid item>
                  <Grid container className={classes.inputContainer}>
                    <Grid item>
                      <NumericInput strict min={0} max={11} size={3} value={inchesInput} onChange={(e) => handleInchesInput(e)} />
                    </Grid>
                    <Grid item xs>
                      <Typography style={{ paddingLeft: 4 }}>Inches</Typography>
                    </Grid>
                  </Grid>
                </Grid>
              </Grid>
            </Grid>

            <Grid item xs={12}>
              <Typography variant='caption' style={{ color: 'red' }}>
                Note: Changing the scale will resize objects but not walls.
              </Typography>
            </Grid>

            <Grid item xs={6}>
              <Button fullWidth variant='contained' color='primary' onClick={onSave}>
                Save
              </Button>
            </Grid>

            <Grid item xs={6}>
              <Button fullWidth variant='contained' onClick={handleClose}>
                Cancel
              </Button>
            </Grid>
          </Grid>
        </Paper>
      </Modal>
    </>
  );
}
Example #24
Source File: resources.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function Resources(props) {
  const [data, setData] = useState([]);
  const [partData, setPartData] = useState([]);
  const [ogData, setOgData] = useState([]);
  const [fetched, setFetched] = useState(false);
  const [city, setCity] = useState('all');
  const [category, setCategory] = useState('all');
  const [nepalstate, setNepalState] = useState('all');
  const [resourcedict, setResourceDict] = useState({});
  const [showTable, setShowTable] = useState(false);
  const [isDesktop, setIsDesktop] = useState(false);
  const [hasScrolled, setHasScrolled] = useState(false);
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [searchValue, setSearchValue] = useState('');

  useEffect(() => {
    if (fetched === false) {
      getResources();
    }
  }, [fetched, data, resourcedict]);

  const checkForResizeEvent = useCallback((event) => {
    if (window.innerWidth > 639) setIsDesktop(true);
    else setIsDesktop(false);
  }, []);

  useEffect(() => {
    if (window.innerWidth > 639) setIsDesktop(true);
    else setIsDesktop(false);
    window.addEventListener('resize', checkForResizeEvent);
    return () => {
      window.removeEventListener('resize', checkForResizeEvent);
    };
  }, [isDesktop, checkForResizeEvent]);

  const checkScrollEvent = useCallback((event) => {
    window.pageYOffset > 100 ? setHasScrolled(true) : setHasScrolled(false);
  }, []);

  useEffect(() => {
    window.pageYOffset > 100 ? setHasScrolled(true) : setHasScrolled(false);
    window.addEventListener('scroll', checkScrollEvent);
    return () => {
      window.removeEventListener('scroll', checkScrollEvent);
    };
  }, [hasScrolled, checkScrollEvent]);

  const getResources = async () => {
    try {
      const [response] = await Promise.all([
        axios.get('https://api.nepalcovid19.org/resources/resources.json'),
      ]);
      // setData(response.data.resources);
      const hashmap = {};
      response.data.resources.forEach((x) => {
        if (typeof hashmap[x['state']] === 'undefined')
          hashmap[x['state']] = {};
        if (typeof hashmap[x['state']][x['city']] === 'undefined')
          hashmap[x['state']][x['city']] = {};
        if (
          typeof hashmap[x['state']][x['city']][x['category']] === 'undefined'
        )
          hashmap[x['state']][x['city']][x['category']] = [];
        if (Array.isArray(hashmap[x['state']][x['city']][x['category']]))
          hashmap[x['state']][x['city']][x['category']].push(x);
      });

      setResourceDict(hashmap);

      setFetched(true);
    } catch (err) {}
  };

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

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

  const isDisclaimerOpen = Boolean(anchorEl);
  const id = isDisclaimerOpen ? 'simple-popover' : undefined;

  function animateScroll() {
    document.body.scrollTo({top: 0, behavior: 'smooth'}); // For Safari
    document.documentElement.scrollTo({top: 0, behavior: 'smooth'}); // For Chrome, Firefox, IE and Opera
  }

  const memocols = React.useMemo(
    () => [
      {
        Header: 'City',
        accessor: 'city',
      },
      {
        Header: 'Category',
        accessor: 'category',
      },
      {
        Header: 'Organisation',
        accessor: 'nameoftheorganisation',
      },
      {
        Header: 'Description',
        accessor: 'descriptionandorserviceprovided',
      },
      {
        Header: 'Phone',
        accessor: 'phonenumber',
      },
      {
        Header: 'Source',
        accessor: 'contact',
        isVisible: false,
      },
    ],
    []
  );
  // const memodata = React.useMemo(() => data, [data])

  const getCityOptions = function () {
    if (nepalstate) {
      if (nepalstate === 'all') return [];
      else {
        return Object.keys(resourcedict[nepalstate])
          .sort()
          .map((x, i) => (
            <option
              key={i}
              value={x}
              style={{
                fontFamily: 'archia',
                fontSize: '11px !important',
                fontWeight: 600,
                textTransform: 'uppercase',
              }}
            >
              {x}
            </option>
          ));
      }
    } else return [];
    // return getCityList().map((x) => <option value={x}>{x}</option>)
  };
  const getnepalstateOptions = function () {
    // let defaultOption = ['Please select']
    return Object.keys(resourcedict)
      .sort()
      .map((x, i) => (
        <option
          key={i}
          value={x}
          style={{
            fontFamily: 'archia',
            fontSize: '11px !important',
            fontWeight: 600,
            textTransform: 'uppercase',
          }}
        >
          {x}
        </option>
      ));
  };
  const getCategoryOptions = function () {
    if (nepalstate && city) {
      if (nepalstate === 'all') {
        const array = [];
        Object.values(resourcedict).forEach((state) => {
          Object.values(state).forEach((citydata) => {
            Object.keys(citydata).forEach((x) => {
              if (array.indexOf(x) === -1) array.push(x);
            });
          });
        });
        return array.sort().map((x, i) => (
          <option
            key={i}
            value={x}
            style={{
              fontFamily: 'archia',
              fontSize: '11px !important',
              fontWeight: 600,
              textTransform: 'uppercase',
            }}
          >
            {x}
          </option>
        ));
      } else {
        if (city === 'all') {
          const array = [];
          Object.values(resourcedict[nepalstate]).forEach((citydata) => {
            Object.keys(citydata).forEach((x) => {
              if (array.indexOf(x) === -1) array.push(x);
            });
          });
          return array.sort().map((x, i) => (
            <option
              key={i}
              value={x}
              style={{
                fontFamily: 'archia',
                fontSize: '11px !important',
                fontWeight: 600,
                textTransform: 'uppercase',
              }}
            >
              {x}
            </option>
          ));
        } else {
          return Object.keys(resourcedict[nepalstate][city])
            .sort()
            .map((x, i) => (
              <option
                key={i}
                value={x}
                style={{
                  fontFamily: 'archia',
                  fontSize: '11px !important',
                  fontWeight: 600,
                  textTransform: 'uppercase',
                }}
              >
                {x}
              </option>
            ));
        }
      }
    } else return [];
  };

  const filterTable = function () {
    let a = [];
    if (category === 'all') {
      if (city === 'all') {
        if (nepalstate === 'all') {
          Object.values(resourcedict).forEach((state) => {
            Object.values(state).forEach((citydata) => {
              Object.values(citydata).forEach((category) => {
                category.forEach((x) => a.push(x));
              });
            });
          });
        } else {
          Object.values(resourcedict[nepalstate]).forEach((citydata) => {
            Object.values(citydata).forEach((category) => {
              category.forEach((x) => a.push(x));
            });
          });
        }
      } else {
        Object.values(resourcedict[nepalstate][city]).forEach((x) => {
          x.forEach((y) => a.push(y));
        });
      }
    } else {
      if (nepalstate === 'all' && city === 'all') {
        Object.values(resourcedict).forEach((state) => {
          Object.values(state).forEach((citydata) => {
            Object.values(citydata).forEach((categorydata) => {
              categorydata.forEach((x) => {
                if (x.category === category) a.push(x);
              });
            });
          });
        });
      } else if (nepalstate !== 'all' && city === 'all') {
        Object.values(resourcedict[nepalstate]).forEach((citydata) => {
          if (category in citydata) {
            citydata[category].forEach((x) => {
              a.push(x);
            });
          }
        });
      } else {
        a = resourcedict[nepalstate][city][category];
      }
    }
    try {
      if ('PAN Nepal' in resourcedict) {
        resourcedict['PAN Nepal']['Multiple']['CoVID-19 Testing Lab'].forEach(
          (element) => {
            a.push(element);
          }
        );
      }
    } catch (err) {}
    setData(a);
    setOgData(a);
    setPartData(a.slice(0, 30));
    setShowTable(true);
    try {
      document.getElementById('input-field-searchbar').value = '';
    } catch {}
    setSearchValue('');
  };

  const changeNepalState = function (changedstateevent) {
    setNepalState(changedstateevent.target.value);
    // setCity(
    //   Object.keys(resourcedict[changedstateevent.target.value]).sort()[0]
    // );
    if (changedstateevent.target.value === '') {
      setCity('');
      document.getElementById('cityselect1').selectedIndex = 0;
      setCategory('');
      document.getElementById('categoryselect').selectedIndex = 0;
    } else {
      setCity('all');
      document.getElementById('cityselect1').selectedIndex = 1;
      setCategory('all');
      document.getElementById('categoryselect').selectedIndex = 1;
    }
  };
  const changeCity = function (changedcityevent) {
    setCity(changedcityevent.target.value);
    setCategory('all');
    document.getElementById('categoryselect').selectedIndex = 1;
  };
  const changeCategory = function (changedcategoryevent) {
    setCategory(changedcategoryevent.target.value);
  };
  const appendData = function () {
    const tempArr = partData.concat(
      data.slice(partData.length, partData.length + 30)
    );
    setPartData(tempArr);
  };

  const openSharingLink = function (message) {
    const shareUri = `https://www.addtoany.com/share#url=${encodeURI(
      'https://www.nepalcovid19.org/essentials'
    )}&title=${encodeURI(message)}`;

    const h = 500;
    const w = 500;
    const left = window.screen.width / 2 - w / 2;
    const top = window.screen.height / 2 - h / 2;
    return window.open(
      shareUri,

      document.title,
      'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' +
        w +
        ', height=' +
        h +
        ', top=' +
        top +
        ', left=' +
        left
    );
  };

  const openSharingTray = function () {
    const message =
      'Discover nearest coronavirus support and essential service providers such as testing lab centres, accommodation shelters and vegetable vendors at ';
    if (navigator.share !== undefined) {
      navigator
        .share({
          title: document.title,
          text: message,
          url: 'https://www.nepalcovid19.org/essentials',
        })
        .then()
        .catch((error) => {});
    } else {
      openSharingLink(message);
    }
  };

  useDebounce(
    () => {
      const newData = getSuggestions(searchValue, ogData);
      setData(newData);
      setPartData(newData.slice(0, 30));
    },
    300,
    [searchValue, ogData]
  );

  return (
    <div className="Resources" id="top-elem">
      <Helmet>
        <title>Essentials - nepalcovid19.org</title>
        <meta name="title" content="Essentials - nepalcovid19.org" />
      </Helmet>

      <div className="filtersection">
        <div className="filtertitle">
          <h3>Service Before Self</h3>
        </div>
        {!isDesktop && (
          <FiltersMobile
            handleDisclaimerClick={handleDisclaimerClick}
            popoverid={id}
            isDisclaimerOpen={isDisclaimerOpen}
            anchorEl={anchorEl}
            handleDisclaimerClose={handleDisclaimerClose}
            nepalstate={nepalstate}
            changeNepalState={changeNepalState}
            stateoptions={getnepalstateOptions()}
            city={city}
            changeCity={changeCity}
            cityoptions={getCityOptions()}
            category={category}
            changeCategory={changeCategory}
            servicesoptions={getCategoryOptions()}
            filterTable={filterTable}
            openSharingTray={openSharingTray}
          />
        )}
        {isDesktop && (
          <FiltersDesktop
            handleDisclaimerClick={handleDisclaimerClick}
            popoverid={id}
            isDisclaimerOpen={isDisclaimerOpen}
            anchorEl={anchorEl}
            handleDisclaimerClose={handleDisclaimerClose}
            nepalstate={nepalstate}
            changeNepalState={changeNepalState}
            stateoptions={getnepalstateOptions()}
            city={city}
            changeCity={changeCity}
            cityoptions={getCityOptions()}
            category={category}
            changeCategory={changeCategory}
            servicesoptions={getCategoryOptions()}
            filterTable={filterTable}
            openSharingTray={openSharingTray}
          />
        )}
      </div>
      {showTable && (
        <React.Fragment>
          <div className="searchbar">
            <TextField
              id="input-field-searchbar"
              label="Search keyword"
              fullWidth={true}
              InputLabelProps={{
                shrink: true,
              }}
              style={{
                width: '100%',
              }}
              variant="outlined"
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <Icon.Search size="0.9em" />
                  </InputAdornment>
                ),
              }}
              onChange={(event) => {
                setInterval(setSearchValue(event.target.value));
              }}
            />
          </div>
          <ResourceTable
            columns={memocols}
            data={partData}
            totalCount={data.length}
            isDesktop={isDesktop}
            onScrollUpdate={appendData}
            searchValue={searchValue}
          />
          <div>
            <Fade in={hasScrolled}>
              <Fab
                color="inherit"
                aria-label="gototop"
                id="gototopbtn"
                onClick={animateScroll}
                size="small"
                style={{
                  position: 'fixed',
                  bottom: '1rem',
                  right: '1rem',
                  zIndex: '1000',
                }}
              >
                <Icon.Navigation2 strokeWidth="2.5" color="#4c75f2" />
              </Fab>
            </Fade>
          </div>
        </React.Fragment>
      )}
    </div>
  );
}
Example #25
Source File: PostFormModal.js    From reddish with MIT License 4 votes vote down vote up
AddPostModal = ({
  actionType,
  handleMenuClose,
  postToEditType,
  postToEditTitle,
  postToEditSub,
  postToEditId,
  textSubmission,
  linkSubmission,
  fromSubreddit,
}) => {
  const [open, setOpen] = useState(false);
  const [postType, setPostType] = useState('Text');
  const user = useSelector((state) => state.user);

  const classes = useDialogStyles();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('xs'));

  const handleClickOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  const handleTextPost = () => {
    setPostType('Text');
    handleClickOpen();
  };

  const handleImagePost = () => {
    setPostType('Image');
    handleClickOpen();
  };

  const handleLinkPost = () => {
    setPostType('Link');
    handleClickOpen();
  };

  const handleMenuClick = () => {
    handleClickOpen();
    handleMenuClose();
  };

  if (!user) {
    return null;
  }

  return (
    <div>
      {actionType === 'edit' ? (
        <MenuItem onClick={handleMenuClick}>
          <ListItemIcon>
            <EditIcon style={{ marginRight: 7 }} />
            Edit Post
          </ListItemIcon>
        </MenuItem>
      ) : isMobile ? (
        <HideOnScroll>
          <Fab
            className={classes.fab}
            color="primary"
            onClick={handleClickOpen}
          >
            <PostAddIcon />
          </Fab>
        </HideOnScroll>
      ) : (
        <Paper variant="outlined" className={classes.createPostWrapper}>
          {user.avatar && user.avatar.exists ? (
            <Avatar
              alt={user.username}
              src={getCircularAvatar(user.avatar.imageLink)}
            />
          ) : (
            <Avatar className={classes.defaultAvatar}>
              {user.username[0]}
            </Avatar>
          )}
          <Button
            color="primary"
            variant="outlined"
            onClick={handleTextPost}
            fullWidth
            className={classes.createBtn}
            startIcon={<PostAddIcon />}
            size="large"
          >
            Create Post
          </Button>
          <div className={classes.iconGroup}>
            <IconButton onClick={handleImagePost}>
              <ImageIcon color="primary" />
            </IconButton>
            <IconButton onClick={handleLinkPost}>
              <LinkIcon color="primary" />
            </IconButton>
          </div>
        </Paper>
      )}
      <Dialog
        open={open}
        onClose={handleClose}
        classes={{ paper: classes.dialogWrapper }}
        maxWidth="md"
        fullWidth={true}
      >
        <DialogTitle onClose={handleClose}>
          {actionType === 'edit' ? 'Update your post' : 'Add a new post'}
        </DialogTitle>
        <DialogContent>
          <PostForm
            actionType={actionType}
            postType={postType}
            postToEditType={postToEditType}
            postToEditTitle={postToEditTitle}
            postToEditSub={postToEditSub}
            postToEditId={postToEditId}
            textSubmission={textSubmission}
            linkSubmission={linkSubmission}
            fromSubreddit={fromSubreddit}
          />
        </DialogContent>
      </Dialog>
    </div>
  );
}
Example #26
Source File: GuideViewer.jsx    From archeage-tools with The Unlicense 4 votes vote down vote up
render() {
    const { mobile, match: { params: { guide: guideSlug } } } = this.props;
    const { toc } = this.state;
    const guideData = Guides[unslug(guideSlug)];
    if (!guideData) {
      return <NotFound />;
    }

    setTitle(`${guideData.name} Guide`);

    return (
      <div className="guide-container">
        <div className="section">
          <div className="guide-viewer">
            {guideData.sections.map((section, sId) => (
              <React.Fragment key={`${slug(guideData.name)}-s${sId}`}>
                <Paper id={`${slug(section.title)}`}>
                  {section.tabContent &&
                  <TabContent title={section.title} tabs={section.tabContent} />}
                  {!section.tabContent && section.paragraphs &&
                  <>
                    <AppBar position="static">
                      <Toolbar variant="dense">
                        <Typography variant="h5" className="title-text">{section.title}</Typography>
                      </Toolbar>
                    </AppBar>
                    <div className="body-container">
                      {section.paragraphs.map((line, pId) => {
                        const key = `${slug(guideData.name)}-s${sId}-p${pId}`;
                        if (typeof line === 'string') {
                          return <Typography key={key}>{line}</Typography>;
                        } else {
                          return <KeyComponent key={key}>{line}</KeyComponent>;
                        }
                      })}
                    </div>
                  </>}
                </Paper>
                {(sId + 1) % 3 === 0 &&
                <AdContainer type="horizontal" />}
              </React.Fragment>
              ),
            )}
          </div>
          {!mobile &&
          <Sticky holderProps={{ className: 'guide-toc' }}>
            <Paper>
              <AppBar position="static">
                <Toolbar variant="dense">
                  <Typography variant="subtitle1" className="title-text">{guideData.name}</Typography>
                </Toolbar>
              </AppBar>
              <div className="body-container">
                <Typography variant="subtitle2">Author: {guideData.meta.author}</Typography>
                <Typography variant="subtitle2">Last Updated: {guideData.meta.lastUpdated}</Typography>
                <Typography variant="subtitle1">Table of Contents</Typography>
                {guideData.sections.map((section, sId) => (
                  <Link
                    to={`#${slug(section.title)}`}
                    onClick={() => this.goSection(slug(section.title))}
                    color="primary"
                    key={`toc-${sId}`}
                  >
                    <Typography>{sId + 1}. {section.title}</Typography>
                  </Link>
                ))}
              </div>
            </Paper>
            <AdContainer type="square" />
          </Sticky>}
        </div>
        <ScrollToTop />
        {mobile &&
        <Fab
          color="primary"
          className="fab-left"
          onClick={this.handleToCClick}
        >
          <MenuIcon />
        </Fab>}
        <Drawer anchor="left" open={mobile && toc} onClose={this.closeToC}>
          <List style={{ width: 250 }}>
            <ListItem><Typography variant="h6">{guideData.name}</Typography></ListItem>
            <ListItem>
              <Typography variant="subtitle2">
                Author: {guideData.meta.author}<br />
                Last Updated: {guideData.meta.lastUpdated}
              </Typography>
            </ListItem>
            <hr />
            {guideData.sections.map((section, sId) => (
              <RouterLink
                to={`#${slug(section.title)}`}
                onClick={() => this.goSection(slug(section.title), 'auto')}
                color="primary"
                className="no-link"
                key={`toc-drawer-${sId}`}
              >
                <ListItem button>
                  <ListItemText primary={`${sId + 1}. ${section.title}`} />
                </ListItem>
              </RouterLink>
            ))}
          </List>
        </Drawer>
      </div>
    );
  }
Example #27
Source File: ImageScroller.js    From treetracker-admin-client with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function ImageScroller(props) {
  const {
    images,
    selectedImage,
    loading = false,
    blankMessage = '',
    imageRotation,
    onSelectChange,
  } = props;
  const classes = useStyle();
  const [maxImages, setMaxImages] = useState(MAX_IMAGES_INCREMENT);
  const imageScrollerRef = useRef(null);
  let [rotation, setRotation] = useState(imageRotation);

  function loadMoreImages() {
    setMaxImages(maxImages + MAX_IMAGES_INCREMENT);
  }

  function scrollImagesLeft() {
    scrollImages(-NUM_IMAGE_CARDS);
  }

  function scrollImagesRight() {
    scrollImages(NUM_IMAGE_CARDS);
  }

  function scrollImages(numImages) {
    const startPos =
      Math.round(imageScrollerRef.current.scrollLeft / IMAGE_CARD_SIZE) *
      IMAGE_CARD_SIZE;
    imageScrollerRef.current.scrollTo({
      top: 0,
      left: startPos + numImages * IMAGE_CARD_SIZE,
      behavior: 'smooth',
    });
  }

  function handleRotationChange() {
    let newRotation = rotation + 90;
    if (newRotation > 270) {
      newRotation = 0;
    }
    setRotation(newRotation);
    onSelectChange('imageRotation', newRotation);
  }

  function handleImageChange(img) {
    onSelectChange('imageUrl', img);
    if (images.length > 1) {
      setRotation(0);
    }
  }

  return (
    <div className={classes.container}>
      <Grid
        item
        className={`image-list ${classes.imageList}`}
        ref={imageScrollerRef}
      >
        {loading ? (
          <div className={classes.placeholder}>
            <CircularProgress id="loading" />
          </div>
        ) : images.length ? (
          images.slice(0, maxImages).map((img, idx) => (
            <Card
              key={`${idx}_${img}`}
              className={`image-card ${classes.imageCard} ${
                img === selectedImage && classes.selectedImageCard
              }`}
            >
              <OptimizedImage
                src={img}
                width={IMAGE_CARD_SIZE}
                height={IMAGE_CARD_SIZE}
                className={classes.image}
                fixed
                rotation={img === selectedImage ? rotation : 0}
                onClick={() => handleImageChange(img)}
              />
              {img === selectedImage ? (
                <Fab
                  id="click-rotate"
                  className={classes.clickRotate}
                  onClick={handleRotationChange}
                >
                  <Rotate90DegreesCcwIcon
                    style={{ transform: `rotateY(180deg)` }}
                  />
                </Fab>
              ) : (
                ''
              )}
            </Card>
          ))
        ) : (
          <div className={classes.placeholder}>{blankMessage}</div>
        )}
        {maxImages < images.length && (
          <Button
            id="load-more"
            className={classes.loadMore}
            onClick={loadMoreImages}
          >
            Load more
          </Button>
        )}
      </Grid>
      {images.length > NUM_IMAGE_CARDS && (
        <>
          <Fab
            id="scroll-left"
            className={`${classes.scrollButton} ${classes.scrollLeft}`}
            onClick={scrollImagesLeft}
          >
            <ChevronLeft />
          </Fab>
          <Fab
            id="scroll-right"
            className={`${classes.scrollButton} ${classes.scrollRight}`}
            onClick={scrollImagesRight}
          >
            <ChevronRight />
          </Fab>
        </>
      )}
    </div>
  );
}