diff options
Diffstat (limited to 'src/containers')
-rw-r--r-- | src/containers/BsuFantomSection/EventForm.tsx | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/src/containers/BsuFantomSection/EventForm.tsx b/src/containers/BsuFantomSection/EventForm.tsx index 09bb87b..9fc18b5 100644 --- a/src/containers/BsuFantomSection/EventForm.tsx +++ b/src/containers/BsuFantomSection/EventForm.tsx @@ -1,6 +1,9 @@ import React from 'react'; -import { Grid, TextField, Button } from '@material-ui/core'; +import _ from 'lodash'; +import cronstrue from 'cronstrue'; +import * as Yup from 'yup'; import { Formik, Form, Field } from 'formik'; +import { Grid, TextField, Button, Link } from '@material-ui/core'; import { post } from '../../requests'; import { Event } from '../../types'; @@ -15,7 +18,36 @@ interface Fields { conferenceId: string; } +const describeCrontab = (crontab: string) => { + try { + return cronstrue.toString(crontab); + } catch { + return false; + } +}; + +const validationSchema = Yup.object({ + name: Yup.string().required('This field is required'), + conferenceId: Yup.string().required('This field is required'), + attendanceId: Yup.string(), + schedule: Yup.string() + .required('This field is required') + .test('cron', 'Invalid crontab', value => !!describeCrontab(value || '')) +}); + const EventForm: React.FC<PropTypes> = ({ mutate }) => { + + const describeSchedule = (schedule: string) => { + const description = describeCrontab(schedule); + if (description) return `Event will run ${_.lowerFirst(description)}`; + const link = <Link href="https://crontab.guru">crontab.guru</Link>; + return ( + <> + The schedule is invalid. Check out {link} for more help with cron scheduling. + </> + ); + }; + const handleSubmit = (fields: Fields, { resetForm }: any) => { const { name, schedule, attendanceId, conferenceId } = fields; @@ -41,9 +73,10 @@ const EventForm: React.FC<PropTypes> = ({ mutate }) => { return ( <Formik initialValues={{ name: '', schedule: '* * * * *', attendanceId: '', conferenceId: '' }} + validationSchema={validationSchema} onSubmit={handleSubmit} > - {({ values, errors, touched, isSubmitting }) => ( + {({ values, errors, touched, isValid }) => ( <Form autoComplete="off"> <Grid container spacing={2}> <Grid item sm={6} xs={12}> @@ -51,6 +84,8 @@ const EventForm: React.FC<PropTypes> = ({ mutate }) => { name="name" label="Name" value={values.name} + error={touched.name && !!errors.name} + helperText={touched.name && errors.name} variant="outlined" fullWidth required @@ -62,6 +97,10 @@ const EventForm: React.FC<PropTypes> = ({ mutate }) => { name="schedule" label="Schedule" value={values.schedule} + error={touched.schedule && !!errors.schedule} + helperText={ + (touched.schedule && errors.schedule) || "Should be a valid crontab, for example: 30 12 * * Mon" + } variant="outlined" fullWidth required @@ -73,6 +112,8 @@ const EventForm: React.FC<PropTypes> = ({ mutate }) => { name="conferenceId" label="Conference ID" value={values.conferenceId} + error={touched.conferenceId && !!errors.conferenceId} + helperText={touched.conferenceId && errors.conferenceId} variant="outlined" fullWidth required @@ -89,9 +130,13 @@ const EventForm: React.FC<PropTypes> = ({ mutate }) => { as={TextField} /> </Grid> + <Grid item xs={12}> + {describeSchedule(values.schedule)} + </Grid> <Grid item sm={2} xs={12}> <Button type="submit" + disabled={!isValid} variant="contained" size="large" color="primary" |