@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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 "Detect Location" 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
"AS IS". 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 |
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 |
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 |
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>
)
}