@material-ui/core#FormControlLabel JavaScript Examples

The following examples show how to use @material-ui/core#FormControlLabel. 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: CardMembers.js    From TrelloClone with MIT License 6 votes vote down vote up
CardMembers = ({ card }) => {
  const classes = useStyles();
  const boardMembers = useSelector((state) => state.board.board.members);
  const members = card.members.map((member) => member.user);
  const dispatch = useDispatch();

  return (
    <div>
      <h3 className={classes.membersTitle}>Members</h3>
      <FormControl component='fieldset'>
        <FormGroup>
          {boardMembers.map((member) => (
            <FormControlLabel
              key={member.user}
              control={
                <Checkbox
                  checked={members.indexOf(member.user) !== -1}
                  onChange={async (e) =>
                    dispatch(
                      addCardMember({
                        add: e.target.checked,
                        cardId: card._id,
                        userId: e.target.name,
                      })
                    )
                  }
                  name={member.user}
                />
              }
              label={member.name}
            />
          ))}
        </FormGroup>
      </FormControl>
    </div>
  );
}
Example #2
Source File: Question.js    From Quizzie with MIT License 6 votes vote down vote up
function Question(props) {
    const [value, setValue] = React.useState('none');
	const handleChange = (event) => {
		setValue(event.target.value);
	};
	return (
        <Grid item xs={10} md={8} lg={7} style={{margin: 0, padding: '2%', backgroundColor: '#111', borderBottom: '5px solid #222', minHeight: '50vh'}}>
            <FormControl style={{margin: 'auto', width:"100%"}} component="fieldset">
                <FormLabel className="label" component="legend">{props.id}</FormLabel>
                <RadioGroup aria-label="correct-choice" value={value} onChange={handleChange}>
                    <FormControlLabel value="op1" control={<Radio className="radio" />} label="Option 1" style={{margin: 0}} />
                    <FormControlLabel value="op2" control={<Radio className="radio" />} label="Option 2" style={{margin: 0}} />
                    <FormControlLabel value="op3" control={<Radio className="radio" />} label="Option 3" style={{margin: 0}} />
                    <FormControlLabel value="op4" control={<Radio className="radio" />} label="Option 4" style={{margin: 0}} />
                </RadioGroup>
            </FormControl>
        </Grid>
	)
}
Example #3
Source File: AppTasks.js    From course-manager with MIT License 6 votes vote down vote up
function TaskItem({ task, checked, formik, ...other }) {
  const { getFieldProps } = formik;

  return (
    <Stack direction="row" justifyContent="space-between" sx={{ py: 0.75 }}>
      <FormControlLabel
        control={
          <Checkbox {...getFieldProps('checked')} value={task} checked={checked} {...other} />
        }
        label={
          <Typography
            variant="body2"
            sx={{
              ...(checked && {
                color: 'text.disabled',
                textDecoration: 'line-through'
              })
            }}
          >
            {task}
          </Typography>
        }
      />
    </Stack>
  );
}
Example #4
Source File: Switcher.js    From web with GNU General Public License v3.0 6 votes vote down vote up
Switcher = ({ checked, disabled, label, name, onChange }) => {
  return (
    <SwitcherWrapper>
      <FormControlLabel
        disabled={disabled}
        control={
          <Switch
            size="medium"
            checked={checked}
            onChange={onChange}
            name={name}
          />
        }
        label={label}
      />
    </SwitcherWrapper>
  );
}
Example #5
Source File: AgentSettings.js    From voicemail-for-amazon-connect with Apache License 2.0 6 votes vote down vote up
FormControlCheckBox = ({label, checked, onChange, name, id, color = "primary"}) => {
    return (
        <FormControlLabel
            control={
                <Checkbox
                    name={name}
                    id={id}
                    onChange={onChange}
                    checked={checked}
                    color="primary"/>
            }
            label={label}/>
    )
}
Example #6
Source File: tagger.js    From graphql-sample-apps with Apache License 2.0 6 votes vote down vote up
Tagger = ({ tags, onChange, selected, expand }) => {
  const classes = useStyles();
  return (
    <Accordion defaultExpanded={expand}>
      <AccordionSummary expandIcon={<ExpandMoreIcon />}>
        <Typography>Filter by Tags</Typography>
      </AccordionSummary>
      <AccordionDetails className={classes.root}>
        <FormControl component="fieldset">
          <RadioGroup onClick={onChange} value={selected}>
            {tags.map(({ name, value }) => (
              <FormControlLabel
                key={value}
                value={value}
                control={<Radio />}
                label={name}
              />
            ))}
          </RadioGroup>
        </FormControl>
      </AccordionDetails>
    </Accordion>
  );
}
Example #7
Source File: checkbox-options.js    From horondi_admin with MIT License 6 votes vote down vote up
CheckboxOptions = ({ options }) => {
  const mappedCheckboxes = options.map(
    ({ color, checked, label, value, handler, dataCy }) => (
      <FormControlLabel
        data-cy={dataCy}
        key={label}
        value={value}
        checked={checked}
        control={<Checkbox color={color} />}
        label={label}
        labelPlacement='end'
        onChange={handler}
      />
    )
  );
  return <>{mappedCheckboxes}</>;
}
Example #8
Source File: register-form.spec.js    From horondi_client_fe with MIT License 6 votes vote down vote up
describe('RegisterForm tests', () => {
  it('should render all fields of Register Form', () => {
    const wrapper = shallow(<RegisterForm {...props} />);
    expect(wrapper.find(Field).length).toEqual(4);
  });
  it('should not render Loader if not loading', () => {
    const wrapper = shallow(<RegisterForm {...props} />);
    expect(wrapper.find(Loader)).toHaveLength(0);
  });
  it('should render Loader if loading', () => {
    const wrapper = shallow(<RegisterForm {...props} loading />);
    expect(wrapper.find(Loader)).toHaveLength(1);
  });
  it('should set checkbox checked', () => {
    const wrapper = shallow(<RegisterForm {...props} />);
    const checkbox = wrapper.find(FormControlLabel);
    checkbox.props().onChange({ target: { checked: true } });
    expect(wrapper.find(FormControlLabel).props().checked).toBeTruthy();
  });
});
Example #9
Source File: CreateGameDialog.js    From dipact with GNU General Public License v3.0 6 votes vote down vote up
checkboxField(name, opts = {}) {
		return (
			<FormControlLabel
				control={
					<Checkbox
						checked={
							opts.invert
								? !this.state.newGameProperties[name]
								: this.state.newGameProperties[name]
						}
						onChange={this.newGamePropertyUpdater(name, opts)}
					/>
				}
				label={opts.label || name}
			/>
		);
	}
Example #10
Source File: DeleteWalletConfirm.js    From akashlytics-deploy with GNU General Public License v3.0 5 votes vote down vote up
DeleteWalletConfirm = ({ isOpen, address, balance, handleCancel, handleConfirmDelete }) => {
  const classes = useStyles();
  const [isConfirmationChecked, setIsConfirmationChecked] = useState(false);
  const [deleteDeployments, setDeleteDeployments] = useState(false);

  return (
    <Dialog
      disableBackdropClick
      disableEscapeKeyDown
      maxWidth="sm"
      aria-labelledby="confirmation-dialog-title"
      open={isOpen}
      onExit={() => setIsConfirmationChecked(false)}
    >
      <DialogTitle id="confirmation-dialog-title">Delete Wallet</DialogTitle>
      <DialogContent dividers className={classes.dialogContent}>
        Are you sure you want to delete this wallet?
        <p>
          Address: <strong>{address}</strong>
          <br />
          {!!balance && (
            <>
              Balance: <strong>{uaktToAKT(balance)} AKT</strong>
            </>
          )}
        </p>
        <Alert severity="warning">
          This wallet will be completely removed from Akashlytics Deploy along with your local certificate and deployments data. If you want to keep access to
          this wallet, make sure you have a backup of the seed phrase or private key.
        </Alert>
        <br />
        <FormControlLabel
          control={<Checkbox checked={deleteDeployments} onChange={(ev, value) => setDeleteDeployments(value)} />}
          label="Delete local deployment data."
        />
        <FormControlLabel
          control={<Checkbox checked={isConfirmationChecked} onChange={(ev, value) => setIsConfirmationChecked(value)} />}
          label="I understand the wallet will be completely removed and I have all the backups I need."
        />
      </DialogContent>
      <DialogActions className={classes.dialogActions}>
        <Button autoFocus onClick={handleCancel} color="primary">
          Cancel
        </Button>
        <Button onClick={() => handleConfirmDelete(deleteDeployments)} disabled={!isConfirmationChecked} variant="contained" color="secondary">
          Delete Wallet
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #11
Source File: FolioHeader.jsx    From archeage-tools with The Unlicense 5 votes vote down vote up
render() {
    const { open, loading, searchType, options } = this.state;
    const { items, mobile } = this.props;

    return (
      <AppBar position="static" className="section folio-header">
        <Toolbar>
          {!mobile &&
          <Typography variant="h5" className="title-text">Folio</Typography>}
          <Autocomplete
            open={open}
            onOpen={() => this.setOpen(true)}
            onClose={() => this.setOpen(false)}
            onChange={this.handleSearch}
            loading={loading}
            options={options}
            getOptionLabel={option => option.name || option}
            filterOptions={(options) => options}
            classes={{
              noOptions: 'folio-no-option',
            }}
            renderOption={option => (
              <div className="item-result" key={option.id}>
                <Item id={option.id} inline />
                {items[option.id]
                  ? <Typography variant="body2">{items[option.id].name}</Typography>
                  : <Skeleton variant="text" />}
              </div>
            )}
            freeSolo
            onInputChange={(e, value) => {
              this._handleQuery(value);
            }}
            renderInput={params => (
              <TextField
                {...params}
                label={`Search by ${searchTypes.find(type => type.value === searchType).label}`}
                fullWidth
                variant="standard"
                size="small"
                margin="none"
                InputProps={{
                  ...params.InputProps,
                  endAdornment: (
                    <>
                      {loading ? <CircularProgress color="inherit" size={20} /> : null}
                      {params.InputProps.endAdornment}
                    </>
                  ),
                }}
                InputLabelProps={{
                  ...params.InputLabelProps,
                }}
              />
            )}
          />
          <RadioGroup name="search-type" value={searchType} onChange={this.handleTypeChange} row={!mobile}>
            {searchTypes.map(searchType => (
              <FormControlLabel
                control={<Radio size="small" color="primary" />}
                {...searchType}
                key={searchType.value}
              />
            ))}
          </RadioGroup>
        </Toolbar>
      </AppBar>
    );
  }
Example #12
Source File: search-checkboxes.jsx    From amadeus-airport-city-search-mern with MIT License 5 votes vote down vote up
SearchCheckboxes = (props) => {
  const { city, airport } = props.search

  // Handle change event on clicking checkboxes
  const onCheckboxChange = (e) => {
    e.persist();
    if (e.target.checked && (city || airport)) {
      props.setSearch(p => ({ ...p, [e.target.value]: e.target.checked }));
      return;
    }
    if (!e.target.checked && !(!city || !airport)) {
      props.setSearch(p => ({ ...p, [e.target.value]: e.target.checked }));
      return;
    }
  };


  return (
    <div>
      <FormControlLabel
        control={
          <Checkbox
            checked={city}
            onChange={onCheckboxChange}
            value={"city"}
          />
        }
        label="City"
      />
      <FormControlLabel
        control={
          <Checkbox
            checked={airport}
            onChange={onCheckboxChange}
            value={"airport"}
          />
        }
        label="Airport"
      />
    </div>
  )
}
Example #13
Source File: FormikMuiFields.js    From reddish with MIT License 5 votes vote down vote up
RadioInput = ({ label, ...props }) => {
  const [field] = useField(props);
  return <FormControlLabel {...field} control={<Radio />} label={label} />;
}
Example #14
Source File: GlobalSettings.js    From voicemail-for-amazon-connect with Apache License 2.0 5 votes vote down vote up
render() {

        let classes = this.props.classes;

        let transcribe = this.state.transcribeEnabled;
        if (this.state.transcribeEnabled === null) {
            transcribe = this.props.transcribeVoicemail
        }

        let encrypt = this.state.encryptionEnabled;
        if (this.state.encryptionEnabled === null) {
            encrypt = this.props.encryptVoicemail
        }

        return (
            <div className={classes.root}>
                <h6 className={classes.title}>Global Configurations</h6>
                <div className={classes.checkBox}>
                    <FormControlLabel
                        control={
                            <Checkbox
                                name="transcribeEnabled"
                                id="transcribe"
                                disabled={this.props.loading || this.props.saving}
                                onChange={this.handleEventInputChange}
                                checked={transcribe}
                                color="primary"/>
                        }
                        label="Allow Voicemail Transcriptions"/>
                    <FormControlLabel
                        control={
                            <Checkbox
                                name="encryptionEnabled"
                                id="encrypt"
                                disabled={this.props.loading || this.props.saving}
                                onChange={this.handleEventInputChange}
                                checked={encrypt}
                                color="primary"/>
                        }
                        label="Enforce Voicemail Encryption"/>
                    <TextField
                        name="deliveryEmail"
                        disabled={this.props.loading || this.props.saving}
                        className={classes.deliveryEmail}
                        fullWidth={true}
                        placeholder={this.props.deliveryEmail}
                        onChange={this.handleEventInputChange}
                        value={this.state.deliveryEmail || this.props.deliveryEmail}
                        label={"Delivery Email"}
                    />
                    <p className={classes.infoCaption}>Important: Delivery Email must be verified via Amazon Simple
                        Email Service before emails can be delivered</p>
                </div>
                <Grid container spacing={5} direction="row">
                    <Grid item>
                        <Button color="secondary" onClick={() => {
                            this.props.showModal(false)
                        }}>Cancel</Button>
                    </Grid>
                    <Grid item>
                        <AsyncButton loading={this.props.saving} color="primary" variant="contained" disabled={this.props.userRole != "Administrator"} onClick={this.handleSave}>Save</AsyncButton>
                    </Grid>
                </Grid>
                <div className={classes.spacer}></div>
                <ContactFlow/>
            </div>
        )
    }
Example #15
Source File: ShippingOptions.js    From beluga with GNU General Public License v3.0 5 votes vote down vote up
function ShippingOptions(props) {
  const { options, shippingOption } = props;

  const selectOption = e => {
    const newOption = options.find(o => o.name === e.target.value);
    props.setShippingOption(newOption)
  }

  const getLabel = o => (
    <div>
      <Label>{o.name}</Label>
      <span>{(o.price/100).toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</span>
    </div>
  )

  return (
    <div style={{ marginTop: "20px"}}>
      <RadioGroup
        value={shippingOption ? shippingOption.name : ""}
        onChange={selectOption}
      >
        { options.map((o,i) => (
          <FormControlLabel
            key={`radio${i}`}
            value={o.name}
            control={<Radio />}
            label={getLabel(o)}
          />
        ))}
      </RadioGroup>
      <Button
        variant="contained" color="primary"
        style={{ marginTop: "40px" }}
        disabled={!shippingOption}
        onClick={props.createOrder}
      >
        Continue
      </Button>
    </div>
  );
}
Example #16
Source File: GraphSettings.js    From Interceptor with MIT License 5 votes vote down vote up
render() {
    //console.log("Rendering GraphSettings");
    return (
      <Dialog
        open={this.props.show}
        aria-labelledby="form-dialog-title"
      >
        <DialogTitle id="form-dialog-title">Graphs settings</DialogTitle>
        <DialogContent>
          <Grid container spacing={2} direction="column" alignItems="flex-start">
            <Grid item>
              <FormControl>
                <InputLabel htmlFor="cols">Graph columns</InputLabel>
                <Input
                  id="cols"
                  value={this.state.cols}
                  onChange={event => this.setState({ cols: Math.min(Math.max(parseInt(event.target.value), 1), 12) })}
                  aria-describedby="cols-helper-text"
                  inputProps={{
                    'aria-label': 'Graph columns',
                  }}
                />
                <FormHelperText id="cols-helper-text">Max: 12</FormHelperText>
              </FormControl>
            </Grid>
            <Grid item>
              <FormControl>
                <InputLabel htmlFor="rateHz">Render rate</InputLabel>
                <Input
                  id="rateHz"
                  value={this.state.rateHz}
                  onChange={event => this.setState({ rateHz: Math.min(Math.max(parseInt(event.target.value), 0.5), 20) })}
                  endAdornment={<InputAdornment position="end">Hz</InputAdornment>}
                  aria-describedby="rateHz-helper-text"
                  inputProps={{
                    'aria-label': 'Render rate',
                  }}
                />
                <FormHelperText id="rateHz-helper-text">Min: 0.5, Max: 20</FormHelperText>
              </FormControl>
            </Grid>
            <Grid item>
              <FormControl>
                <InputLabel htmlFor="max_datapoints">Max data points</InputLabel>
                <Input
                  id="max_datapoints"
                  value={this.state.max_datapoints}
                  onChange={event => this.setState({ max_datapoints: Math.min(Math.max(parseInt(event.target.value), 20), 10000) })}
                  aria-describedby="max_datapoints-helper-text"
                  inputProps={{
                    'aria-label': 'Max data points',
                  }}
                />
                <FormHelperText id="max_datapoints-helper-text">Max: 10000</FormHelperText>
              </FormControl>
            </Grid>
            <Grid item>
              <FormControlLabel
                control={<Switch checked={this.state.webgl} onChange={() => this.setState({ webgl: !this.state.webgl })} name="webGL" />}
                label="WebGL support"
              />
            </Grid>
          </Grid>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => this.props.setSettings(this.state.cols, this.state.rateHz, this.state.max_datapoints, this.state.webgl)} color="default">
            Save
        </Button>
        </DialogActions>
      </Dialog>
    );
  }
Example #17
Source File: AppHeader.js    From mentors-website with MIT License 5 votes vote down vote up
AppHeader = ({darkMode, ModeChange}) => {
    const classes = useStyles();

    return (
        <AppBar position="static" className={classes.appBar}>
            <Container maxWidth='lg'>
                <Toolbar disableGutters className={classes.toolbar_container}>

                    <MUILink href="/" title="CodeHood Mentors" className={classes.brand}>
                        <img src={CodeHoodLogo} alt="Codehood" />
                        <Hidden only={['xs', 'sm']}>
                            <Typography
                                variant={window.innerWidth < 637 ? "h6" : "h4"}
                                className={classes.title}
                            >
                                Mentors
                            </Typography>
                        </Hidden>
                    </MUILink>

                    <FormControlLabel
                        control={
                            <Switch
                                name="switch_dark_mode"
                                checked={darkMode}
                                onChange={ModeChange}
                                aria-label={darkMode ? "Light Mode" : "Dark Mode"}
                                color='default'
                            />
                        }
                        label={
                            darkMode ? (
                                <LightIcon htmlColor='#ffffff' />
                            ) : (
                                <DarkIcon htmlColor='#ffffff' />
                            )
                        }
                    />
                    
                </Toolbar>
            </Container>
        </AppBar>
    )
}
Example #18
Source File: ArmingFlagsView.js    From Nemesis with GNU General Public License v3.0 5 votes vote down vote up
render() {
    return (
      <React.Fragment>
        <Typography variant="h5">
          <FormattedMessage id="pfc.armingflags.title" />
        </Typography>
        <List>
          {this.state.armingFlags.map(flag => (
            <Chip
              onClick={flag.onClick}
              key={flag.label}
              style={{ margin: 4 }}
              label={<FormattedMessage id={flag.label} />}
            />
          ))}
        </List>
        <FormGroup component="fieldset">
          {this.state.debug && (
            <FormControlLabel
              control={
                <Switch
                  checked={this.state.showDebug}
                  onChange={(event, showDebug) => {
                    this.setState({ showDebug });
                  }}
                />
              }
              label={<FormattedMessage id="info.show-debug" />}
            />
          )}
          {this.state.showDebug && (
            <List>
              {this.state.debug.map((debugVal, index) => {
                return (
                  <ListItem className="debug-item" key={index}>
                    DEBUG {index}: {debugVal}
                  </ListItem>
                );
              })}
            </List>
          )}
        </FormGroup>
      </React.Fragment>
    );
  }
Example #19
Source File: additional-price-container.js    From horondi_admin with MIT License 5 votes vote down vote up
AdditionalPriceContainer = ({
  values,
  labels,
  onChange,
  onBlur,
  errors,
  touched,
  radio
}) => {
  const styles = useStyles();
  const dispatch = useDispatch();
  const exchangeRate = useSelector(({ Currencies }) => Currencies.exchangeRate);
  const { materialUiConstants } = config;

  useEffect(() => {
    dispatch(getCurrencies());
  }, [dispatch]);
  return (
    <Paper className={styles.additionalPricePaper}>
      <Box>
        <Typography>{labels.enterPrice}</Typography>
      </Box>
      {radio && (
        <FormControl component='fieldset'>
          <RadioGroup
            name='additionalPriceType'
            className={styles.textField}
            onChange={onChange}
            value={values.additionalPriceType}
          >
            <FormControlLabel
              value='ABSOLUTE'
              label={labels.additionalPriceType.absolutePrice[0].value}
              control={<Radio />}
              key={2}
            />
            <FormControlLabel
              value='RELATIVE'
              label={labels.additionalPriceType.relativePrice[0].value}
              control={<Radio />}
              key={1}
            />
          </RadioGroup>
        </FormControl>
      )}
      <TextField
        data-cy='additionalPrice'
        className={`
                  ${styles.textField}
                  ${styles.additionalPrice} 
                  `}
        id='additionalPrice'
        variant='outlined'
        label={getLabelValue(values, labels.additionalPriceType)}
        type={materialUiConstants.types.number}
        value={values.additionalPrice}
        onChange={onChange}
        onBlur={onBlur}
        error={touched.additionalPrice && errors.additionalPrice}
      />
      {touched.additionalPrice && errors.additionalPrice && (
        <div data-cy='additionalPrice-error' className={styles.error}>
          {errors.additionalPrice}
        </div>
      )}
      <TextField
        id='outlined-basic'
        variant='outlined'
        label={labels.convertationTitle}
        className={`
                  ${styles.textField} 
                  ${styles.currencyField}
                  `}
        value={calculateAddittionalPriceValue(values, exchangeRate)}
        disabled
      />
    </Paper>
  );
}
Example #20
Source File: PopupPage.js    From spl-token-wallet with Apache License 2.0 5 votes vote down vote up
function ApproveConnectionForm({ origin, onApprove }) {
  const wallet = useWallet();
  const { accounts, hardwareWalletAccount } = useWalletSelector();
  // TODO better way to do this
  const account = accounts
    .concat([hardwareWalletAccount])
    .find((account) => account && account.address.equals(wallet.publicKey));
  const classes = useStyles();
  const [autoApprove, setAutoApprove] = useState(false);
  let [dismissed, setDismissed] = useLocalStorageState(
    'dismissedAutoApproveWarning',
    false,
  );
  return (
    <Card>
      <CardContent>
        <Typography variant="h6" component="h1" gutterBottom>
          Allow this site to access your Solana account?
        </Typography>
        <div className={classes.connection}>
          <Typography>{origin}</Typography>
          <ImportExportIcon fontSize="large" />
          <Typography>{account.name}</Typography>
          <Typography variant="caption">
            ({wallet.publicKey.toBase58()})
          </Typography>
        </div>
        <Typography>Only connect with sites you trust.</Typography>
        <Divider className={classes.divider} />
        <FormControlLabel
          control={
            <Switch
              checked={autoApprove}
              onChange={() => setAutoApprove(!autoApprove)}
              color="primary"
            />
          }
          label={`Automatically approve transactions from ${origin}`}
        />
        {!dismissed && autoApprove && (
          <SnackbarContent
            className={classes.warningContainer}
            message={
              <div>
                <span className={classes.warningTitle}>
                  <WarningIcon className={classes.warningIcon} />
                  Use at your own risk.
                </span>
                <Typography className={classes.warningMessage}>
                  This setting allows sending some transactions on your behalf
                  without requesting your permission for the remainder of this
                  session.
                </Typography>
              </div>
            }
            action={[
              <Button onClick={() => setDismissed('1')}>I understand</Button>,
            ]}
            classes={{ root: classes.snackbarRoot }}
          />
        )}
      </CardContent>
      <CardActions className={classes.actions}>
        <Button onClick={window.close}>Cancel</Button>
        <Button
          color="primary"
          onClick={() => onApprove(autoApprove)}
          disabled={!dismissed && autoApprove}
        >
          Connect
        </Button>
      </CardActions>
    </Card>
  );
}
Example #21
Source File: TransactionList.js    From A2 with GNU General Public License v3.0 5 votes vote down vote up
populateBills(bills) {
    const transaction = bills.map(bill => (
      <ExpansionPanel className={styles.bills}>
        <ExpansionPanelSummary>
          <div className={styles.billSummary}>
            <div className={styles.billTitle}>{bill.title}</div>
            <div className={styles.billAmount}>
              ${Number(bill.total).toFixed(2)}
            </div>
          </div>
        </ExpansionPanelSummary>
        <ExpansionPanelDetails className={styles.payments}>
          <div className={styles.paymentsTitle}>
            <div className={styles.paymentHeaders}>
              <Link
                to={{
                  pathname: "split",
                  bill
                }}
              >
                <EditIcon />
              </Link>
              <PaymentIcon />
            </div>
            <div className={styles.runningTotal}>
              <div className={`${styles.billTitle} ${styles.percentage}`}>
                (
                {Math.round(
                  (calculateTotalPaid(bill) / calculateTotalOutstanding(bill)) *
                    100
                )}
                %){" "}
              </div>
              <div className={styles.billTitle}>
                ${calculateTotalPaid(bill).toFixed(2)}/$
                {calculateTotalOutstanding(bill).toFixed(2)}
              </div>
            </div>
          </div>
          {bill.payments.map(payment => {
            const label = `${payment.from} owes ${payment.to} $${Number(
              payment.amount
            ).toFixed(2)}`;
            return (
              <div key={payment.id}>
                <FormControlLabel
                  aria-label="Acknowledge"
                  onClick={() =>
                    this.markPaid({
                      payment_id: payment.payment_id,
                      is_paid: !payment.is_paid
                    })
                  }
                  onFocus={event => event.stopPropagation()}
                  control={<Checkbox checked={payment.is_paid} />}
                  label={label}
                />
              </div>
            );
          })}
        </ExpansionPanelDetails>
      </ExpansionPanel>
    ));

    if (transaction.length === 0) {
      return (
        <div className={styles.noTransactions}>
          You have no outstanding transactions.
        </div>
      );
    }
    return transaction;
  }
Example #22
Source File: Filter.jsx    From Gameplayer with MIT License 5 votes vote down vote up
Filter = ({
  classes,
  onToggleWithName,
  onToggleWithImage,
  onOrderBy,
  withName,
  withImage,
  orderBy,
}) => (
  <Grid item>
    <Grid container direction="row">
      <FormControlLabel
        control={
          <Checkbox
            checked={withName}
            onChange={event => onToggleWithName && onToggleWithName()}
          />
        }
        label="With names"
      />
      <FormControlLabel
        control={
          <Checkbox
            checked={withImage}
            onChange={event => onToggleWithImage && onToggleWithImage()}
          />
        }
        label="With images"
      />
      <FormControlLabel
        control={
          <Select
            className={classes.orderBySelect}
            value={orderBy}
            onChange={event => onOrderBy && onOrderBy(event.target.value)}
          >
            <MenuItem value="id">ID</MenuItem>
            <MenuItem value="imageUrl">Image</MenuItem>
            <MenuItem value="displayName">Name</MenuItem>
            <MenuItem value="owner">Owner</MenuItem>
          </Select>
        }
        label="Order By:"
        labelPlacement="start"
      />
    </Grid>
  </Grid>
)
Example #23
Source File: CreateChannelDialog.js    From dipact with GNU General Public License v3.0 5 votes vote down vote up
render() {
		return (
			<Dialog
				onEntered={helpers.genOnback(this.close)}
				open={this.state.open}
				disableBackdropClick={false}
				onClose={this.close}
			>
				<DialogTitle>Create channel</DialogTitle>
				<DialogContent>
					<DialogContentText>
						Pick the participants of the new channel.
					</DialogContentText>
					<FormGroup>
						{this.variant.Properties.Nations.map((n) => {
							return (
								<FormControlLabel
									key={n}
									control={
										<Checkbox
											disabled={n === this.member.Nation}
											checked={!!this.state.members[n]}
											onChange={this.toggleMember(n)}
										/>
									}
									label={n}
								/>
							);
						})}
					</FormGroup>
				</DialogContent>
				<DialogActions>
					<Button onClick={this.close} color="primary">
						Cancel
					</Button>
					<Button
						onClick={this.createChannel}
						color="primary"
					>
						Create
					</Button>
				</DialogActions>
			</Dialog>
		);
	}
Example #24
Source File: CreateLease.js    From akashlytics-deploy with GNU General Public License v3.0 4 votes vote down vote up
export function CreateLease({ dseq }) {
  const [isSendingManifest, setIsSendingManifest] = useState(false);
  const [isFilteringFavorites, setIsFilteringFavorites] = useState(false);
  const [selectedBids, setSelectedBids] = useState({});
  const [filteredBids, setFilteredBids] = useState([]);
  const [search, setSearch] = useState("");
  const { sendTransaction } = useTransactionModal();
  const { address } = useWallet();
  const { localCert } = useCertificate();
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();
  const history = useHistory();
  const [anchorEl, setAnchorEl] = useState(null);
  const classes = useStyles();
  const [numberOfRequests, setNumberOfRequests] = useState(0);
  const { providers, getProviders } = useAkash();
  const warningRequestsReached = numberOfRequests > WARNING_NUM_OF_BID_REQUESTS;
  const maxRequestsReached = numberOfRequests > MAX_NUM_OF_BID_REQUESTS;
  const { favoriteProviders } = useLocalNotes();
  const { data: bids, isLoading: isLoadingBids } = useBidList(address, dseq, {
    initialData: [],
    refetchInterval: REFRESH_BIDS_INTERVAL,
    onSuccess: () => {
      setNumberOfRequests((prev) => ++prev);
    },
    enabled: !maxRequestsReached
  });
  const { data: deploymentDetail, refetch: getDeploymentDetail } = useDeploymentDetail(address, dseq, { refetchOnMount: false, enabled: false });
  const groupedBids = bids
    .sort((a, b) => a.price.amount - b.price.amount)
    .reduce((a, b) => {
      a[b.gseq] = [...(a[b.gseq] || []), b];
      return a;
    }, {});
  const dseqList = Object.keys(groupedBids);
  const allClosed = bids.length > 0 && bids.every((bid) => bid.state === "closed");

  useEffect(() => {
    getDeploymentDetail();
    getProviders();

    if (favoriteProviders.length > 0) {
      setIsFilteringFavorites(true);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Filter bids by search
  useEffect(() => {
    let fBids = [];
    if ((search || isFilteringFavorites) && providers) {
      bids?.forEach((bid) => {
        let isAdded = false;

        // Filter for search
        if (search) {
          const provider = providers.find((p) => p.owner === bid.provider);
          // Filter by attribute value
          provider?.attributes.forEach((att) => {
            if (att.value?.includes(search)) {
              fBids.push(bid.id);
              isAdded = true;
            }
          });
        }

        // Filter for favorites
        if (!isAdded && isFilteringFavorites) {
          const provider = favoriteProviders.find((p) => p === bid.provider);

          if (provider) {
            fBids.push(bid.id);
          }
        }
      });
    } else {
      fBids = bids?.map((b) => b.id) || [];
    }

    setFilteredBids(fBids);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [search, bids, providers, isFilteringFavorites]);

  const handleBidSelected = (bid) => {
    setSelectedBids({ ...selectedBids, [bid.gseq]: bid });
  };

  async function sendManifest(providerInfo, manifest) {
    try {
      const response = await sendManifestToProvider(providerInfo, manifest, dseq, localCert);

      return response;
    } catch (err) {
      enqueueSnackbar(<ManifestErrorSnackbar err={err} />, { variant: "error", autoHideDuration: null });
      throw err;
    }
  }

  async function handleNext() {
    const bidKeys = Object.keys(selectedBids);

    // Create the lease
    try {
      const messages = bidKeys.map((gseq) => selectedBids[gseq]).map((bid) => TransactionMessageData.getCreateLeaseMsg(bid));
      const response = await sendTransaction(messages);

      if (!response) throw new Error("Rejected transaction");

      await analytics.event("deploy", "create lease");
    } catch (error) {
      // Rejected transaction
      return;
    }

    setIsSendingManifest(true);

    const localDeploymentData = getDeploymentLocalData(dseq);
    if (localDeploymentData && localDeploymentData.manifest) {
      // Send the manifest

      const sendManifestKey = enqueueSnackbar(<Snackbar title="Sending Manifest! ?" subTitle="Please wait a few seconds..." showLoading />, {
        variant: "success",
        autoHideDuration: null
      });

      try {
        const yamlJson = yaml.load(localDeploymentData.manifest);
        const mani = deploymentData.Manifest(yamlJson);

        for (let i = 0; i < bidKeys.length; i++) {
          const currentBid = selectedBids[bidKeys[i]];
          const provider = providers.find((x) => x.owner === currentBid.provider);
          await sendManifest(provider, mani);
        }
      } catch (err) {
        console.error(err);
      }

      closeSnackbar(sendManifestKey);
    }

    setIsSendingManifest(false);

    await analytics.event("deploy", "send manifest");

    history.replace(UrlService.deploymentDetails(dseq, "LOGS", "events"));
  }

  async function handleCloseDeployment() {
    try {
      const message = TransactionMessageData.getCloseDeploymentMsg(address, dseq);
      const response = await sendTransaction([message]);

      if (response) {
        history.replace(UrlService.deploymentList());
      }
    } catch (error) {
      throw error;
    }
  }

  function handleMenuClick(ev) {
    setAnchorEl(ev.currentTarget);
  }

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

  const onSearchChange = (event) => {
    const value = event.target.value;
    setSearch(value);
  };

  return (
    <>
      <Helmet title="Create Deployment - Create Lease" />

      <Box padding="0 1rem">
        {!isLoadingBids && bids.length > 0 && !allClosed && (
          <Box display="flex" alignItems="center" justifyContent="space-between">
            <Box flexGrow={1}>
              <TextField
                label="Search by attribute..."
                disabled={bids.length === 0 || isSendingManifest}
                value={search}
                onChange={onSearchChange}
                type="text"
                variant="outlined"
                autoFocus
                fullWidth
                size="medium"
                InputProps={{
                  endAdornment: search && (
                    <InputAdornment position="end">
                      <IconButton size="small" onClick={() => setSearch("")}>
                        <CloseIcon />
                      </IconButton>
                    </InputAdornment>
                  )
                }}
              />
            </Box>

            <Box display="flex" alignItems="center">
              <Tooltip
                classes={{ tooltip: classes.tooltip }}
                arrow
                interactive
                title={
                  <Alert severity="info" variant="standard">
                    Bids automatically close 5 minutes after the deployment is created if none are selected for a lease.
                  </Alert>
                }
              >
                <InfoIcon className={clsx(classes.tooltipIcon, classes.marginLeft)} />
              </Tooltip>

              <Box margin="0 .5rem">
                <IconButton aria-label="settings" aria-haspopup="true" onClick={handleMenuClick} size="small">
                  <MoreHorizIcon fontSize="large" />
                </IconButton>
              </Box>

              <Menu
                id="bid-actions-menu"
                anchorEl={anchorEl}
                keepMounted
                getContentAnchorEl={null}
                open={Boolean(anchorEl)}
                onClose={handleMenuClose}
                anchorOrigin={{
                  vertical: "bottom",
                  horizontal: "right"
                }}
                transformOrigin={{
                  vertical: "top",
                  horizontal: "right"
                }}
                onClick={handleMenuClose}
              >
                <MenuItem onClick={() => handleCloseDeployment()}>Close Deployment</MenuItem>
              </Menu>

              <Button
                variant="contained"
                color="primary"
                onClick={handleNext}
                classes={{ label: classes.nowrap }}
                disabled={dseqList.some((gseq) => !selectedBids[gseq]) || isSendingManifest || !providers}
              >
                Accept Bid{dseqList.length > 1 ? "s" : ""}
                <Box component="span" marginLeft=".5rem" display="flex" alignItems="center">
                  <ArrowForwardIosIcon fontSize="small" />
                </Box>
              </Button>
            </Box>
          </Box>
        )}

        <Box display="flex" alignItems="center">
          {!isLoadingBids && (allClosed || bids.length === 0) && (
            <Button variant="contained" color={allClosed ? "primary" : "secondary"} onClick={handleCloseDeployment} size="small">
              Close Deployment
            </Button>
          )}

          {!isLoadingBids && allClosed && (
            <Tooltip
              classes={{ tooltip: classes.tooltip }}
              arrow
              interactive
              title={
                <Alert severity="warning">
                  All bids for this deployment are closed. This can happen if no bids are accepted for more than 5 minutes after the deployment creation. You
                  can close this deployment and create a new one.
                </Alert>
              }
            >
              <InfoIcon className={clsx(classes.tooltipIcon, classes.marginLeft)} color="error" />
            </Tooltip>
          )}
        </Box>

        {(isLoadingBids || bids.length === 0) && !maxRequestsReached && (
          <Box textAlign="center" paddingTop="1rem">
            <CircularProgress />
            <Box paddingTop="1rem">
              <Typography variant="body1">Waiting for bids...</Typography>
            </Box>
          </Box>
        )}

        {warningRequestsReached && !maxRequestsReached && bids.length === 0 && (
          <Box paddingTop="1rem">
            <Alert variant="standard" severity="info">
              There should be bids by now... You can wait longer in case a bid shows up or close the deployment and try again with a different configuration.
            </Alert>
          </Box>
        )}

        {maxRequestsReached && bids.length === 0 && (
          <Box paddingTop="1rem">
            <Alert variant="standard" severity="warning">
              There's no bid for the current deployment. You can close the deployment and try again with a different configuration.
            </Alert>
          </Box>
        )}

        {bids.length > 0 && (
          <Box display="flex" alignItems="center" justifyContent="space-between">
            <Box>
              <FormControlLabel
                control={<Checkbox checked={isFilteringFavorites} onChange={(ev, value) => setIsFilteringFavorites(value)} color="primary" size="small" />}
                label="Favorites"
              />
            </Box>

            {!maxRequestsReached && (
              <Box display="flex" alignItems="center" lineHeight="1rem" fontSize=".7rem">
                <div style={{ color: "grey" }}>
                  <Typography variant="caption">Waiting for more bids...</Typography>
                </div>
                <Box marginLeft=".5rem">
                  <CircularProgress size=".7rem" />
                </Box>
              </Box>
            )}
          </Box>
        )}

        <LinearLoadingSkeleton isLoading={isSendingManifest} />
      </Box>

      {dseqList.length > 0 && (
        <ViewPanel bottomElementId="footer" overflow="auto" padding="0 1rem 2rem">
          {dseqList.map((gseq, i) => (
            <BidGroup
              key={gseq}
              gseq={gseq}
              bids={groupedBids[gseq]}
              handleBidSelected={handleBidSelected}
              selectedBid={selectedBids[gseq]}
              disabled={isSendingManifest}
              providers={providers}
              filteredBids={filteredBids}
              deploymentDetail={deploymentDetail}
              isFilteringFavorites={isFilteringFavorites}
              groupIndex={i}
              totalBids={dseqList.length}
            />
          ))}
        </ViewPanel>
      )}
    </>
  );
}
Example #25
Source File: ChecklistItem.js    From TrelloClone with MIT License 4 votes vote down vote up
ChecklistItem = ({ item, card }) => {
  const classes = useStyles();
  const [text, setText] = useState(item.text);
  const [editing, setEditing] = useState(false);
  const dispatch = useDispatch();

  useEffect(() => {
    setText(item.text);
  }, [item.text]);

  const onEdit = async (e) => {
    e.preventDefault();
    dispatch(editChecklistItem(card._id, item._id, { text }));
    setEditing(false);
  };

  const onComplete = async (e) => {
    dispatch(
      completeChecklistItem({
        cardId: card._id,
        complete: e.target.checked,
        itemId: item._id,
      })
    );
  };

  const onDelete = async (e) => {
    dispatch(deleteChecklistItem(card._id, item._id));
  };

  return (
    <div className={classes.checklistItem}>
      {editing ? (
        <form onSubmit={(e) => onEdit(e)} className={classes.checklistFormLabel}>
          <TextField
            variant='filled'
            fullWidth
            multiline
            required
            autoFocus
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyPress={(e) => e.key === 'Enter' && onEdit(e)}
          />
          <div>
            <Button type='submit' variant='contained' color='primary'>
              Save
            </Button>
            <Button
              onClick={() => {
                setEditing(false);
                setText(item.text);
              }}
            >
              <CloseIcon />
            </Button>
          </div>
        </form>
      ) : (
        <Fragment>
          <FormControlLabel
            control={
              <Checkbox
                checked={
                  card.checklist.find((cardItem) => cardItem._id === item._id).complete
                }
                onChange={onComplete}
                name={item._id}
              />
            }
            label={item.text}
            className={classes.checklistFormLabel}
          />
          <div className={classes.itemButtons}>
            <Button className={classes.itemButton} onClick={() => setEditing(true)}>
              <EditIcon />
            </Button>
            <Button color='secondary' className={classes.itemButton} onClick={onDelete}>
              <HighlightOffIcon />
            </Button>
          </div>
        </Fragment>
      )}
    </div>
  );
}
Example #26
Source File: NewRequestPage.js    From app with MIT License 4 votes vote down vote up
function NewRequestPage() {
  const classes = useStyles();
  const location = useLocation();
  const qs = queryString.parse(location.search);
  const defaultValues = {
    needs: {},
    immediacy: '1',
    needFinancialAssistance: 'false',
  };

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

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

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

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

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

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

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

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

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

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

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

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

                <div className={classes.buttons}>
                  <Button
                    type="submit"
                    variant="contained"
                    color="primary"
                    data-test="submit-request"
                    disabled={isSubmitting}>
                    Submit Request
                  </Button>
                </div>
              </Container>
            </form>
          </Container>
        </div>
      </Paper>
    </Container>
  );
}
Example #27
Source File: EditQuiz.js    From Quizzie with MIT License 4 votes vote down vote up
function EditQuiz(props) {
	const quizId = props.match.params.id;

	const [loading, setLoading] = useState(true);
	const [redirect, setRedirect] = useState(false);

	const [quizDetails, setQuizDetails] = useState({});
	const [quizQuestions, setQuizQuestions] = useState([]);

	const [fileError, setFileError] = useState(false);
	const [serverError, setServerError] = useState(false);
	const [popoverAnchor, setPopoverAnchor] = useState(null);
	const popoverOpen = Boolean(popoverAnchor);

	const [questionModal, setQuestionModal] = useState(false);
	const [newQuestion, setNewQuestion] = useState("");
	const [newQuestionError, setNewQuestionError] = useState(false);

	const [option1, setOption1] = useState("");
	const [option1Error, setOption1Error] = useState(false);
	const [option2, setOption2] = useState("");
	const [option2Error, setOption2Error] = useState(false);
	const [option3, setOption3] = useState("");
	const [option3Error, setOption3Error] = useState(false);
	const [option4, setOption4] = useState("");
	const [option4Error, setOption4Error] = useState(false);
	const [correctOption, setCorrectOption] = useState(-1);
	const [correctOptionError, setCorrectOptionError] = useState(false);

	const [update, setUpdate] = useState(false);
	const [updateId, setUpdateId] = useState(null);

	const [deleteModal, setDeleteModal] = useState(false);
	const [deleteQuestionModal, setDeleteQuestionModal] = useState(false);

	const [quizRestartModal, setQuizRestartModal] = useState(false);
	const [closeQuizModal, setCloseQuizModal] = useState(false);

	const [responses, setResponses] = useState([]);

	const [searchData, setSearchData] = useState(responses);
	const [searchText, setSearchText] = useState("");
	const [sortBy, setSortBy] = useState(-1);

	const { executeRecaptcha } = useGoogleReCaptcha();

	const onCloseHandle = () => {
		setQuestionModal(false);
		if (update) {
			setUpdate(false);
			setUpdateId(null);
			clearModal();
		}
	};

	const handlePopover = (event) => {
		setPopoverAnchor(event.currentTarget);
	};

	const handlePopoverClose = () => {
		setPopoverAnchor(null);
	};

	const onQuestionChange = (event) => {
		setNewQuestion(event.target.value);
	};

	const handleOptionChange1 = (event) => {
		setOption1(event.target.value);
	};
	const handleOptionChange2 = (event) => {
		setOption2(event.target.value);
	};
	const handleOptionChange3 = (event) => {
		setOption3(event.target.value);
	};
	const handleOptionChange4 = (event) => {
		setOption4(event.target.value);
	};

	const handleCorrectOption = (event) => {
		setCorrectOption(event.target.value);
	};

	const clearModal = () => {
		setNewQuestion("");
		setNewQuestionError(false);
		setOption1("");
		setOption1Error(false);
		setOption2("");
		setOption2Error(false);
		setOption3("");
		setOption3Error(false);
		setOption4("");
		setOption4Error(false);
		setCorrectOption(-1);
		setCorrectOptionError(false);
	};

	const handleFileDrop = (files) => {
		const reader = new FileReader();

		let questions = [];

		reader.onabort = () => {
			setFileError(true);
			return;
		};
		reader.onerror = () => {
			setFileError(true);
			return;
		};

		reader.onload = () => {
			csv.parse(reader.result, (err, data) => {
				if (data === undefined) {
					setFileError(true);
					return;
				}
				data.map((question) => {
					if (question[0].trim() === "") {
						return null;
					}
					let obj = {
						quizId: quizId,
						description: question[0],
						options: [
							{ text: question[1] },
							{ text: question[2] },
							{ text: question[3] },
							{ text: question[4] },
						],
						correctAnswer: question[5],
					};

					questions.push(obj);
				});
				submitCSV(questions);
			});
		};

		reader.readAsBinaryString(files[0]);
	};

	const submitCSV = async (questions) => {
		setLoading(true);
		let token = localStorage.getItem("authToken");
		let url = "https://quizzie-api.herokuapp.com/question/csv";

		let captcha = await executeRecaptcha("submit_csv");

		let data = {
			questions: questions,
			captcha: captcha,
		};

		try {
			await axios
				.post(url, data, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					console.log(res);
					setLoading(false);
					clearModal();
					onCloseHandle();
					getQuizDetails();
				});
		} catch (error) {
			setServerError(true);
			console.log(error);
		}
	};

	const handleSearchChange = (event) => {
		setSearchText(event.target.value);

		let newRes = responses.filter(
			(response) =>
				response.userId.name
					.toLowerCase()
					.search(event.target.value.trim().toLowerCase()) !== -1 ||
				String(response.marks) ===
					event.target.value.trim().toLowerCase()
		);
		let sorted = sortByFunc(sortBy, newRes);

		setSearchData(sorted);
	};

	const handleSortChange = (event) => {
		setSortBy(event.target.value);

		let newRes = sortByFunc(event.target.value, searchData);

		setSearchData(newRes);
	};

	const sortByFunc = (by, array) => {
		if (by === "score") {
			return array.sort(function (a, b) {
				return b.marks - a.marks;
			});
		} else if (by === "name") {
			return array.sort(function (a, b) {
				return a.userId.name - b.userId.name;
			});
		} else if (by === "recent") {
			return array.sort(function (a, b) {
				return b.timeEnded - a.timeEnded;
			});
		} else {
			return array;
		}
	};

	const handleRestart = async () => {
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/quiz/restart`;

		let captcha = await executeRecaptcha("restart_quiz");

		let data = {
			quizId: quizId,
			captcha: captcha,
		};

		try {
			await axios
				.patch(url, data, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setQuizRestartModal(false);
					getQuizDetails();
				});
		} catch (error) {
			console.log(error);
		}
	};

	const handleQuizClose = async () => {
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/quiz/close`;

		let captcha = await executeRecaptcha("quiz_close");

		let data = {
			quizId: quizId,
			captcha: captcha,
		};

		try {
			await axios
				.patch(url, data, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setCloseQuizModal(false);
					getQuizDetails();
				});
		} catch (error) {
			console.log(error);
		}
	};

	const handleQuestionEditBtn = (question) => {
		setUpdate(true);
		setUpdateId(question._id);
		setNewQuestion(question.description);
		setOption1(question.options[0].text);
		setOption2(question.options[1].text);
		setOption3(question.options[2].text);
		setOption4(question.options[3].text);
		setCorrectOption(question.correctAnswer);
		setQuestionModal(true);
	};

	const handleQuestionDeleteBtn = (question) => {
		setUpdateId(question._id);
		setDeleteQuestionModal(true);
	};

	const handleQuestionModalClose = () => {
		setUpdateId(null);
		setDeleteQuestionModal(false);
	};

	const handleDeleteBtn = () => {
		setDeleteModal(true);
	};

	const handleDeleteQuestion = async () => {
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/question/${updateId}`;

		// let captcha = executeRecaptcha("delete_quiz");

		try {
			await axios
				.delete(url, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setUpdateId(null);
					setDeleteQuestionModal(false);
					getQuizDetails();
				});
		} catch (error) {
			console.log(error);
		}
	};

	const handleDelete = async () => {
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/quiz/delete`;

		let data = {
			quizId: quizId,
		};

		try {
			await axios
				.delete(url, {
					headers: {
						"auth-token": token,
					},
					data: data,
				})
				.then((res) => {
					setRedirect(true);
				});
		} catch (error) {
			console.log(error);
		}
	};

	const handleQuestionUpdate = async () => {
		if (!validate()) return;

		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/question/update/${updateId}`;

		let captcha = await executeRecaptcha("question_update");

		let updateOps = [
			{ propName: "description", value: newQuestion },
			{
				propName: "options",
				value: [
					{
						text: option1,
					},
					{
						text: option2,
					},
					{
						text: option3,
					},
					{
						text: option4,
					},
				],
			},
			{ propName: "correctAnswer", value: correctOption },
		];

		let data = {
			updateOps: updateOps,
			captcha: captcha,
		};

		try {
			await axios
				.patch(url, data, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					onCloseHandle();
					getQuizDetails();
				});
		} catch (error) {
			console.log(error);
		}
	};

	const validate = () => {
		if (newQuestion.trim().length === 0) {
			setNewQuestionError(true);
			return false;
		}

		if (option1.trim().length === 0) {
			setOption1Error(true);
			return false;
		}
		if (option2.trim().length === 0) {
			setOption2Error(true);
			return false;
		}
		if (option3.trim().length === 0) {
			setOption3Error(true);
			return false;
		}
		if (option4.trim().length === 0) {
			setOption4Error(true);
			return false;
		}

		if (correctOption === -1) {
			setCorrectOptionError(true);
			return false;
		}

		return true;
	};

	const handleQuestionSubmit = async () => {
		//TODO: Handle Validation

		if (!validate()) return;

		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/question/add`;

		let captcha = await executeRecaptcha("submit_question");

		let options = [
			{ text: option1 },
			{ text: option2 },
			{ text: option3 },
			{ text: option4 },
		];

		let data = {
			quizId: quizId,
			description: newQuestion,
			options: options,
			correctAnswer: correctOption,
			captcha: captcha,
		};

		try {
			await axios
				.post(url, data, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					clearModal();
					getQuizDetails();
					setQuestionModal(false);
				});
		} catch (error) {
			console.log(error);
		}
	};

	const isOwnerOfQuiz = async () => {
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/quiz/checkAdmin/${quizId}`;

		try {
			await axios
				.get(url, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					return true;
				});
		} catch (error) {
			setRedirect(true);
			return;
		}
	};

	const getQuizDetails = async () => {
		setLoading(true);
		let token = localStorage.getItem("authToken");
		let url = `https://quizzie-api.herokuapp.com/quiz/${quizId}`;

		try {
			await axios
				.get(url, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setQuizDetails(res.data.result);
				});
		} catch (error) {
			console.log(error);
		}

		url = `https://quizzie-api.herokuapp.com/question/all/${quizId}`;

		try {
			await axios
				.get(url, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setQuizQuestions(res.data.result);
				});
		} catch (error) {
			console.log(error);
		}

		url = `https://quizzie-api.herokuapp.com/admin/allStudentsQuizResult/${quizId}`;

		try {
			await axios
				.get(url, {
					headers: {
						"auth-token": token,
					},
				})
				.then((res) => {
					setResponses(res.data.userResults);
					setSearchData(res.data.userResults);
					setLoading(false);
				});
		} catch (error) {
			console.log(error);
		}
	};

	useEffect(() => {
		let token = localStorage.getItem("authToken");
		if (token === null) {
			setLoading(false);
			setRedirect(true);
			return;
		}

		isOwnerOfQuiz();
		getQuizDetails();
	}, []);

	if (loading) {
		return <Loading />;
	} else if (redirect) {
		return <Redirect to="/dashboard" />;
	} else {
		return (
			<Container className="edit-quiz-page">
				<Typography
					variant="h3"
					className="dash-head p-top edit-quiz-head"
				>
					Edit Quiz
				</Typography>
				<div className="edit-btn-bar">
					<Button
						className="edit-details-btn"
						component={Link}
						to={`/updateQuizDetails/${quizId}`}
					>
						<Create className="edit-icon" />
						Edit Details
					</Button>
					<Button
						className="edit-details-btn delete-btn"
						onClick={handleDeleteBtn}
					>
						<Delete className="edit-icon" />
						Delete Quiz
					</Button>
					{quizDetails.quizStatus === 1 ? (
						<Button
							className="edit-details-btn"
							style={{ marginLeft: "3%" }}
							onClick={() => setCloseQuizModal(true)}
						>
							<Replay className="edit-quiz" />
							Close Quiz
						</Button>
					) : quizDetails.quizStatus === 2 ? (
						<Button
							className="edit-details-btn"
							style={{ marginLeft: "3%" }}
							onClick={() => setQuizRestartModal(true)}
						>
							<Replay className="edit-quiz" />
							Restart Quiz
						</Button>
					) : null}
				</div>
				<div className="quiz-details-sec">
					<Typography variant="h6" className="quiz-detail-param">
						Name:{" "}
						<span className="quiz-detail-text">
							{quizDetails.quizName}
						</span>
					</Typography>
					<Typography variant="h6" className="quiz-detail-param">
						Date:{" "}
						<span className="quiz-detail-text">
							{new Date(
								Number(quizDetails.scheduledFor)
							).toDateString()}
						</span>
					</Typography>
					<Typography variant="h6" className="quiz-detail-param">
						Time:{" "}
						<span className="quiz-detail-text">
							{new Date(
								Number(quizDetails.scheduledFor)
							).toLocaleTimeString()}
						</span>
					</Typography>
					<Typography variant="h6" className="quiz-detail-param">
						Duration:{" "}
						<span className="quiz-detail-text">
							{quizDetails.quizDuration} minutes
						</span>
					</Typography>
					<Typography variant="h6" className="quiz-detail-param">
						Type:{" "}
						<span className="quiz-detail-text">
							{quizDetails.quizType}
						</span>
					</Typography>
					{quizDetails.quizType === "private" ? (
						<Typography variant="h6" className="quiz-detail-param">
							Quiz Code:{" "}
							<span className="quiz-detail-text">
								{quizDetails.quizCode}
							</span>
						</Typography>
					) : null}
				</div>
				<div className="quiz-questions-sec">
					<Typography variant="h4" className="quiz-questions-head">
						Questions
					</Typography>
					<div className="quiz-questions-display">
						<div className="add-question-bar">
							<Button
								className="add-question-btn"
								onClick={() => setQuestionModal(true)}
							>
								Add a question
							</Button>
						</div>
						{quizQuestions.length === 0 ? (
							<p style={{ textAlign: "center" }}>
								No questions added yet!
							</p>
						) : (
							<div className="questions-list-display">
								{quizQuestions.map((question) => (
									<ExpansionPanel
										elevation={3}
										className="expansion"
										key={question._id}
									>
										<ExpansionPanelSummary
											className="question-summary"
											expandIcon={<ExpandMore />}
											aria-controls="question-content"
											aria-label="Expand"
										>
											<FormControlLabel
												style={{ marginRight: "0" }}
												aria-label="Edit"
												control={
													<IconButton>
														<Create />
													</IconButton>
												}
												// label={question.description}
												onClick={() =>
													handleQuestionEditBtn(
														question
													)
												}
											/>
											<FormControlLabel
												aria-label="Edit"
												control={
													<IconButton>
														<Delete />
													</IconButton>
												}
												// label={question.description}
												onClick={() =>
													handleQuestionDeleteBtn(
														question
													)
												}
											/>
											<Typography className="question-label">
												{question.description}
											</Typography>
										</ExpansionPanelSummary>
										<ExpansionPanelDetails>
											<List
												component="nav"
												className="options-display"
											>
												{question.options.map(
													(option) => (
														<ListItem
															button
															key={option._id}
														>
															<ListItemIcon>
																<Adjust
																	style={{
																		color:
																			question.correctAnswer ===
																			option.text
																				? "green"
																				: "black",
																	}}
																/>
															</ListItemIcon>
															<ListItemText
																style={{
																	color:
																		question.correctAnswer ===
																		option.text
																			? "green"
																			: "black",
																}}
																primary={
																	option.text
																}
															/>
														</ListItem>
													)
												)}
											</List>
										</ExpansionPanelDetails>
									</ExpansionPanel>
								))}
							</div>
						)}
					</div>
					<Typography
						variant="h4"
						className="quiz-questions-head m-top"
					>
						Submissions
					</Typography>
					<div className="quiz-students-list">
						<div className="add-question-bar">
							<Button
								className="add-question-btn stats-btn"
								component={
									responses.length !== 0 ? Link : Button
								}
								to={{
									pathname: "/quizStats",
									state: { responses: responses },
								}}
							>
								<BarChart />
								View Stats
							</Button>
						</div>
						{responses.length === 0 ? (
							<p
								style={{
									textAlign: "center",
									margin: "0",
									paddingTop: "3%",
									paddingBottom: "3%",
								}}
							>
								No responses yet!
							</p>
						) : (
							<>
								<div className="search-bar">
									<TextField
										placeholder="Search by name or score"
										type="text"
										onChange={handleSearchChange}
										className="search-input"
										value={searchText}
									/>
									<div style={{ marginLeft: "3%" }}>
										<InputLabel id="sort-by">
											Sort by
										</InputLabel>
										<Select
											labelId="sort-by"
											id="sort-select"
											value={sortBy}
											onChange={handleSortChange}
										>
											<MenuItem value={-1}>
												<em>None</em>
											</MenuItem>
											<MenuItem value="recent">
												Recent
											</MenuItem>
											<MenuItem value="score">
												Score
											</MenuItem>
											<MenuItem value="name">
												Name
											</MenuItem>
										</Select>
									</div>
								</div>
								<List aria-label="responses list">
									{searchData.map((response) => (
										<ListItem
											button
											key={response._id}
											component={Link}
											to={{
												pathname: `/studentResponse`,
												state: { response: response },
											}}
										>
											<ListItemText
												primary={response.userId.name}
												secondary={`Scored: ${response.marks}`}
											/>
										</ListItem>
									))}
								</List>
							</>
						)}
					</div>
				</div>
				<Dialog
					open={questionModal}
					onClose={onCloseHandle}
					aria-labelledby="add-question-modal"
					PaperProps={{
						style: {
							backgroundColor: "white",
							color: "#333",
							minWidth: "50%",
						},
					}}
					style={{ width: "100%" }}
				>
					<div className="add-ques-heading">
						<Typography
							variant="h6"
							style={{ textAlign: "center", margin: "2% 5%" }}
						>
							New Question{" "}
						</Typography>
						{!update ? (
							<IconButton onClick={handlePopover}>
								<Info className="add-info-icon" />
							</IconButton>
						) : null}
						<Popover
							id="file-upload-popover"
							open={popoverOpen}
							anchorEl={popoverAnchor}
							onClose={handlePopoverClose}
							anchorOrigin={{
								vertical: "bottom",
								horizontal: "left",
							}}
							disableRestoreFocus
							useLayerForClickAway={false}
							PaperProps={{ style: { maxWidth: "400px" } }}
						>
							<p className="popover-text">
								You can upload a <strong>.csv</strong> file with
								questions. The format should be: the{" "}
								<strong>
									first column should contain the question
									text.
								</strong>{" "}
								The next 4 columns must contain the{" "}
								<strong>four options.</strong> And the sixth
								column should contain{" "}
								<strong>
									the correct answer (it should match one of
									the four options)
								</strong>
								. <br />
								<br />
								<strong>
									NOTE: THE FILE SHOULD EXACTLY MATCH THE
									GIVEN FORMAT.
								</strong>{" "}
								You will be able to see and edit all the
								question though.
							</p>
						</Popover>
					</div>
					{!update ? (
						<>
							<div className="dropzone">
								<Dropzone
									onDrop={(acceptedFiles) =>
										handleFileDrop(acceptedFiles)
									}
								>
									{({ getRootProps, getInputProps }) => (
										<section>
											<div {...getRootProps()}>
												<input {...getInputProps()} />
												<AddCircle className="drop-icon" />
												<p
													style={{
														color:
															"rgb(110, 110, 110)",
													}}
												>
													Drag 'n' drop or click to
													select files
												</p>
											</div>
										</section>
									)}
								</Dropzone>
							</div>
							<p className="manual-head">
								<span>Or manually add the question</span>
							</p>
						</>
					) : null}
					<div className="new-question-form">
						<TextInput
							error={newQuestionError}
							helperText={
								newQuestionError ? "This cannot be empty" : null
							}
							className="new-ques-input"
							variant="outlined"
							label="Question Text"
							value={newQuestion}
							onChange={onQuestionChange}
						/>
						<hr style={{ width: "100%", marginBottom: "3%" }} />
						<Grid container spacing={1}>
							<Grid item xs={12} sm={6}>
								<TextInput
									error={option1Error}
									helperText={
										option1Error
											? "This cannot be empty"
											: null
									}
									className="new-ques-input"
									variant="outlined"
									label="Option 1"
									value={option1}
									onChange={handleOptionChange1}
								/>
							</Grid>
							<Grid item xs={12} sm={6}>
								<TextInput
									error={option2Error}
									helperText={
										option2Error
											? "This cannot be empty"
											: null
									}
									className="new-ques-input"
									variant="outlined"
									label="Option 2"
									value={option2}
									onChange={handleOptionChange2}
								/>
							</Grid>
						</Grid>
						<Grid container spacing={1}>
							<Grid item xs={12} sm={6}>
								<TextInput
									error={option3Error}
									helperText={
										option3Error
											? "This cannot be empty"
											: null
									}
									className="new-ques-input"
									variant="outlined"
									label="Option 3"
									value={option3}
									onChange={handleOptionChange3}
								/>
							</Grid>
							<Grid item xs={12} sm={6}>
								<TextInput
									error={option4Error}
									helperText={
										option4Error
											? "This cannot be empty"
											: null
									}
									className="new-ques-input"
									variant="outlined"
									label="Option 4"
									value={option4}
									onChange={handleOptionChange4}
								/>
							</Grid>
						</Grid>
						<hr style={{ width: "100%", marginBottom: "3%" }} />
						<InputLabel id="correct-option">
							Correct Option
						</InputLabel>
						<Select
							error={correctOptionError}
							className="correct-answer-select"
							style={{ width: "50%" }}
							labelId="correct-option"
							value={correctOption}
							onChange={handleCorrectOption}
						>
							<MenuItem value={-1}>None</MenuItem>
							{option1.trim().length !== 0 ? (
								<MenuItem value={option1}>{option1}</MenuItem>
							) : null}
							{option2.trim().length !== 0 ? (
								<MenuItem value={option2}>{option2}</MenuItem>
							) : null}
							{option3.trim().length !== 0 ? (
								<MenuItem value={option3}>{option3}</MenuItem>
							) : null}
							{option4.trim().length !== 0 ? (
								<MenuItem value={option4}>{option4}</MenuItem>
							) : null}
						</Select>
						{!update ? (
							<Button
								className="add-question-submit"
								onClick={handleQuestionSubmit}
							>
								Add Question
							</Button>
						) : (
							<Button
								className="add-question-submit"
								onClick={handleQuestionUpdate}
							>
								Update Question
							</Button>
						)}
					</div>
				</Dialog>
				<Dialog
					open={deleteModal}
					onClose={() => setDeleteModal(false)}
					aria-labelledby="delete-quiz-modal"
					PaperProps={{
						style: {
							backgroundColor: "white",
							color: "black",
							minWidth: "10%",
						},
					}}
				>
					<DialogTitle>
						Are you sure you want to delete this quiz?
					</DialogTitle>
					<div className="btn-div">
						<Button
							className="logout-btn m-right bg-red-btn"
							onClick={handleDelete}
						>
							Yes
						</Button>
						<Button
							className="cancel-btn m-left"
							onClick={() => setDeleteModal(false)}
						>
							No
						</Button>
					</div>
				</Dialog>
				<Dialog
					open={deleteQuestionModal}
					onClose={handleQuestionModalClose}
					aria-labelledby="delete-quiz-modal"
					PaperProps={{
						style: {
							backgroundColor: "white",
							color: "black",
							minWidth: "10%",
						},
					}}
				>
					<DialogTitle>
						Are you sure you want to delete this question?
					</DialogTitle>
					<div className="btn-div">
						<Button
							className="logout-btn m-right bg-red-btn"
							onClick={handleDeleteQuestion}
						>
							Yes
						</Button>
						<Button
							className="cancel-btn m-left"
							onClick={handleQuestionModalClose}
						>
							No
						</Button>
					</div>
				</Dialog>
				<Dialog
					open={quizRestartModal}
					onClose={() => setQuizRestartModal(false)}
					aria-labelledby="restart-quiz-modal"
					PaperProps={{
						style: {
							backgroundColor: "white",
							color: "black",
							minWidth: "10%",
						},
					}}
				>
					<DialogTitle>
						Are you sure you want to restart this quiz?
					</DialogTitle>
					<div className="btn-div">
						<Button
							className="logout-btn m-right bg-green-btn"
							onClick={handleRestart}
						>
							Yes
						</Button>
						<Button
							className="cancel-btn m-left bg-red-btn"
							onClick={() => setQuizRestartModal(false)}
						>
							No
						</Button>
					</div>
				</Dialog>
				<Dialog
					open={closeQuizModal}
					onClose={() => setCloseQuizModal(false)}
					aria-labelledby="restart-quiz-modal"
					PaperProps={{
						style: {
							backgroundColor: "white",
							color: "black",
							minWidth: "10%",
						},
					}}
				>
					<DialogTitle>
						Are you sure you want to close this quiz?
					</DialogTitle>
					<div className="btn-div">
						<Button
							className="logout-btn m-right bg-green-btn"
							onClick={handleQuizClose}
						>
							Yes
						</Button>
						<Button
							className="cancel-btn m-left bg-red-btn"
							onClick={() => setCloseQuizModal(false)}
						>
							No
						</Button>
					</div>
				</Dialog>
				<Snackbar
					open={fileError}
					autoHideDuration={3000}
					onClose={() => setFileError(false)}
					anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
				>
					<Alert
						variant="filled"
						severity="error"
						onClose={() => setFileError(false)}
					>
						There was some problem with the file. Try again...
					</Alert>
				</Snackbar>
				<Snackbar
					open={serverError}
					autoHideDuration={3000}
					onClose={() => setServerError(false)}
					anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
				>
					<Alert
						variant="filled"
						severity="error"
						onClose={() => setServerError(false)}
					>
						There was some problem with the server. Try again...
					</Alert>
				</Snackbar>
			</Container>
		);
	}
}
Example #28
Source File: MetaRowForm.js    From Designer-Client with GNU General Public License v3.0 4 votes vote down vote up
export default function MetaRowForm(props) {
  const [col, setCol] = useState(props.col);
  const formHeaders = props.formHeaders;
  const classes = props.classes;
  const idx = props.idx;

  const getType = (val) => {
    switch (val) {
      case "varchar":
        return "text";
      default:
        return val;
    }
  };

  const getTypeLength = (type) => {
    const parsedType = getType(type);
    if (TypeLengthMap[type]) {
      return TypeLengthMap[type];
    }

    return "";
  }

  const getFormat = (type) => {
    switch (type) {
      case "datetime":
        return "yyyy-MM-dd HH:mm:ss";
      case "date":
        return "yyyy-MM-dd";
      case "time":
        return "HH:mm:ss";
      default:
        return "";
    }
  }

  const isDisableDate = (type) => {
    return ["datetime", "date", "time"].indexOf(type) < 0;
  }

  const handleChange = (e) => {
    let value = null;
    switch(e.target.name) {
      case 'nullable':
        value = e.target.checked;
        break;
      default:
        value = e.target.value.trim();
        break;
    }

    const updatedCol = {
      ...col,
      [e.target.name]: value,
    };

    setCol(updatedCol);

    props.updateCol(idx, updatedCol);
  };

  return (
    <div className={classes.flexTable} key={`meta-sample-meta-row-${col.id}`}>
      <div className={`${classes.flexRow} text`}>{col.originalColumnName}</div>
      <div className={classes.flexRow}>
        <FormControl className={classes.formControl}>
          <InputLabel
            htmlFor={`meta-${col.id}-input-columnName`}
            className="label"
          >
            {formHeaders[1].name}
          </InputLabel>
          <Input
            id={`meta-${col.id}-input-columnName`}
            className="form"
            name="columnName"
            value={col.columnName}
            onChange={handleChange}
          />
          <FormHelperText className="helpText">
            {formHeaders[1].tooltip}
          </FormHelperText>
        </FormControl>
      </div>
      <div className={classes.flexRow}>
        <FormControl className={classes.formControl}>
          <InputLabel id={`label-meta-${col.id}-input-type`} className="label">
            {formHeaders[2].name}
          </InputLabel>
          <Select
            labelId={`label-meta-${col.id}-input-type`}
            id={`meta-${col.id}-input-type`}
            name="type"
            value={getType(col.type)}
            className="form"
            onChange={handleChange}
          >
            <MenuItem value={"int"}>숫자(정수)</MenuItem>
            <MenuItem value={"double"}>숫자(부동소수)</MenuItem>
            <MenuItem value={"text"}>문자</MenuItem>
            <MenuItem value={"datetime"}>날짜(시간포함)</MenuItem>
            <MenuItem value={"date"}>날짜(시간 미포함)</MenuItem>
            <MenuItem value={"time"}>시간(시간 미포함)</MenuItem>
          </Select>
        </FormControl>
      </div>
      <div className={classes.flexRow}>
        <FormControl className={classes.formControl}>
          <InputLabel htmlFor={`meta-${col.id}-input-length`} className="label">
            {formHeaders[3].name}
          </InputLabel>
          <Input
            id={`meta-${col.id}-input-length`}
            value={col.length || getTypeLength(col.type)}
            name="length"
            className="form"
            onChange={handleChange}
          />
        </FormControl>
      </div>
      <div className={classes.flexRow}>
        <FormControl className={classes.formControl}>
          <InputLabel htmlFor={`meta-${col.id}-input-format`} className="label">
            {formHeaders[4].name}
          </InputLabel>
          <Input
            id={`meta-${col.id}-input-format`}
            value={col.format || getFormat(col.type)}
            name="format"
            className="form"
            onChange={handleChange}
            disabled={isDisableDate(col.type)}
          />
          <FormHelperText className="helpText">
            {formHeaders[4].tooltip}
          </FormHelperText>
        </FormControl>
      </div>
      <div className={`${classes.flexRow} last`}>
        <FormControlLabel
          control={
            <Checkbox
              id={`meta-${col.id}-input-nullable`}
              checked={col.nullable}
              name="nullable"
              onChange={handleChange}
              color="primary"
            />
          }
          label={
            <Typography style={{ fontSize: "0.875rem" }}>빈값 허용</Typography>
          }
        />
      </div>
      <div className={`${classes.flexRow} last`}>
        <FormControl className={classes.formControl}>
          <Button variant="outlined" startIcon={<SettingsIcon />}>
            검색조건
          </Button>
        </FormControl>
      </div>
    </div>
  );
}
Example #29
Source File: CsvDownloader.js    From covid with GNU General Public License v3.0 4 votes vote down vote up
CsvDownloader = () => {
    const [checkboxes, setCheckboxes] = useState({
        cases:false,        
            covid_confirmed_1p3a: false,
            covid_confirmed_1p3a_state: false,
            covid_confirmed_cdc: false,
            covid_confirmed_cdc_state: false,
            covid_confirmed_nyt: false,
            covid_confirmed_nyt_state: false,
            covid_confirmed_usafacts: false,
            covid_confirmed_usafacts_state: false,
        deaths:false,
            covid_deaths_1p3a: false,
            covid_deaths_1p3a_state: false,
            covid_deaths_cdc: false,
            covid_deaths_cdc_state: false,
            covid_deaths_nyt: false,
            covid_deaths_nyt_state: false,
            covid_deaths_usafacts: false,
            covid_deaths_usafacts_state: false,
        berkeley_predictions: false,
        health_context: false,
            chr_health_context: false,
            chr_health_context_state: false,
            chr_health_factors: false,
            chr_health_factors_state: false,
            chr_life: false,
            chr_life_state: false,
        testing:false,
            covid_tcap_cdc: false,
            covid_tcap_cdc_state: false,
            covid_testing_cdc: false,
            covid_testing_cdc_state: false,
            covid_wk_pos_cdc: false,
            covid_wk_pos_cdc_state: false,
            covid_ccpt_cdc: false,
            covid_ccpt_cdc_state: false,
        vaccination:false,
            vaccination_fully_vaccinated_cdc: false,
            vaccination_one_or_more_doses_cdc: false,
            vaccination_fully_vaccinated_cdc_h: false,
            vaccination_one_or_more_doses_cdc_h: false,
            vaccination_fully_vaccinated_cdc_state: false,
            vaccination_one_or_more_doses_cdc_state: false,
            vaccination_to_be_distributed_cdc_state: false,
        hospitals_clinics:false,
            context_fqhc_clinics_hrsa: false,
            context_hospitals_covidcaremap: false,
        essential_workers_parent:false,
            context_essential_workers_acs: false,
      });

    const [isDownloading, setIsDownloading] = useState(false)
    const handleChange = (event) => {
        setCheckboxes(prev => ({ ...prev, [event.target.name]: event.target.checked }));
    };
    const handleSetChange = (index) => {
        setCheckboxes(prev => {
            const onOrOff = prev[checkboxSets[index].name] ? false : true;

            let newSet = {
                ...prev,
                [checkboxSets[index].name]: onOrOff
            }
            for (let i=0;i<checkboxSets[index].subset.length;i++){
                newSet[checkboxSets[index].subset[i].name] = onOrOff
            }
            return newSet
        });
    }
    
    async function GetFiles(fileList){
        setIsDownloading(true)
        // init zip and folders
        // get links from github
        const dataLinks = await fetch('https://api.github.com/repos/geodacenter/covid/contents/public/csv')
            .then(r=>r.json())
            .then(items => 
                items.filter(d => fileList[d.name.split('.csv')[0]])
                    .map(d => ({'name':d.name, 'url': d.download_url}))
                    .filter(x => x !== undefined)
            )
        const docsLinks = await fetch('https://api.github.com/repos/geodacenter/covid/contents/data-docs').then(r=>r.json()).then(items => items.map(d => ({'name':d.name, 'url': d.download_url})))
        
        // declare promises
        const dataPromises = await dataLinks.map(link => fetch(link.url).then(r=>r.blob()))
        const docsPromises = await docsLinks.map(link => fetch(link.url).then(r=>r.blob()))
        
        // fetch data and docs
        const data = await Promise.all(dataPromises).then(values => values.map((v,i) => ({'name':`${dataLinks[i].name.slice(0,-4)}-${new Date().toISOString().slice(0,10)}.csv`, 'data':v})))
        const docs = await Promise.all(docsPromises).then(values => values.map((v,i) => ({'name':docsLinks[i].name, 'data':v})))
        const license = await fetch('https://raw.githubusercontent.com/GeoDaCenter/covid/master/LICENSE').then(r => r.blob())
        
        var zip = new JSZip();
        zip.file('LICENSE.txt', license)
        zip.file('readme.md', readme)
        var dataFolder = zip.folder("data");
        var docsFolder = zip.folder("docs");
        data.forEach(d => dataFolder.file(d.name, d.data))
        docs.forEach(d => docsFolder.file(d.name, d.data))
        import('file-saver').then(fileSaver  => {
            zip.generateAsync({type:"blob"}).then(function(content) {
                // see FileSaver.js
                fileSaver.saveAs(content, `us_covid_atlas_data_${new Date().toISOString().slice(0,10)}.zip`);
            });
        })
        setIsDownloading(false)
    }

    return (
        <CsvDownloaderContainer className={isDownloading ? 'passive' : ''}>
            <h2>Bulk Data Download</h2>
            <Gutter h={20}/>
            <Grid container spacing={2}>
                <Grid item xs={12} md={8}>
                    <p>This menu allows you to download bulk CSVs of the data available on the Atlas. Select your datasets of interest with the checkboxes below and
                        then click download data to receive a ZIP archive with your CSV files and data documentation. Please note that the full dataset is currently
                        over 70MB, and may be slow to load.     
                    </p>
                </Grid>
                <Grid item xs={12} md={4}>
                    <button onClick={() => GetFiles(checkboxes)} ping="https://theuscovidatlas.org/trackdownloads.html">Download Data</button>
                </Grid>
            </Grid>
            <Gutter h={20}/>
            <Grid container spacing={5}>
            {checkboxSets.map((checkboxSet, i) => 
                    <Grid item xs={12} md={4}>
                        <FormControl component="fieldset">
                            <FormControlLabel
                                control={<Checkbox checked={checkboxes[checkboxSet.name]} onChange={() => handleSetChange(i)} name={checkboxSet.name} />}
                                label={checkboxSet.label}
                            />
                        </FormControl>
                        <br/>
                        <FormControl component="fieldset" className="inset">
                            <FormGroup>
                            {checkboxSet.subset.map(checkboxItem => 
                                <FormControlLabel
                                    control={<Checkbox checked={checkboxes[checkboxItem.name]} onChange={handleChange} name={checkboxItem.name} />}
                                    label={checkboxItem.label}
                                />
                            )}
                            </FormGroup>
                        </FormControl>
                </Grid>
            )}
            </Grid>
        </CsvDownloaderContainer>
    )
}