diff --git a/web/src/app/wizard/WizardForm.jsx b/web/src/app/wizard/WizardForm.tsx similarity index 84% rename from web/src/app/wizard/WizardForm.jsx rename to web/src/app/wizard/WizardForm.tsx index f53b54a591..1a2dfd6613 100644 --- a/web/src/app/wizard/WizardForm.jsx +++ b/web/src/app/wizard/WizardForm.tsx @@ -1,5 +1,4 @@ import React from 'react' -import p from 'prop-types' import StepIcon from '@mui/material/StepIcon' import FormControl from '@mui/material/FormControl' import FormControlLabel from '@mui/material/FormControlLabel' @@ -11,12 +10,12 @@ import TextField from '@mui/material/TextField' import Typography from '@mui/material/Typography' import { FormContainer, FormField } from '../forms' import WizardScheduleForm from './WizardScheduleForm' -import { value as valuePropType } from './propTypes' import makeStyles from '@mui/styles/makeStyles' import * as _ from 'lodash' import { useIsWidthDown } from '../util/useWidth' import MaterialSelect from '../selection/MaterialSelect' import { useFeatures } from '../util/RequireConfig' +import { RotationType } from '../../schema' const useStyles = makeStyles({ fieldItem: { @@ -28,20 +27,57 @@ const useStyles = makeStyles({ }, }) -export default function WizardForm(props) { +export interface WizardFormRotation { + startDate?: string + favorite?: boolean + type?: RotationType | 'never' + enable?: string + users?: string[] + timeZone?: string | null +} + +export interface WizardFormSchedule { + timeZone: string | null + enable?: string + users: string[] + rotation: WizardFormRotation + followTheSunRotation: WizardFormRotation +} + +export interface WizardFormValue { + teamName: string + primarySchedule: WizardFormSchedule + secondarySchedule: WizardFormSchedule + delayMinutes: number + repeat: string + key: { + label: string + value: string + } | null +} + +interface WizardFormProps { + onChange: (value: WizardFormValue) => void + value: WizardFormValue + errors: Error[] +} + +export default function WizardForm(props: WizardFormProps): React.JSX.Element { const { onChange, value } = props const fullScreen = useIsWidthDown('md') const classes = useStyles() const keyTypes = useFeatures().integrationKeyTypes - const handleSecondaryScheduleToggle = (e) => { + const handleSecondaryScheduleToggle = ( + e: React.ChangeEvent, + ): void => { const newVal = _.cloneDeep(value) newVal.secondarySchedule.enable = e.target.value onChange(newVal) } - const sectionHeading = (text) => { + const sectionHeading = (text: string): React.JSX.Element => { return ( {text} @@ -49,7 +85,7 @@ export default function WizardForm(props) { ) } - const getDelayLabel = () => { + const getDelayLabel = (): string => { if (value.secondarySchedule.enable === 'yes') { return 'How long would you like to wait until escalating to your secondary schedule (in minutes)?' } @@ -180,13 +216,3 @@ export default function WizardForm(props) { ) } - -WizardForm.propTypes = { - onChange: p.func.isRequired, - value: valuePropType, - errors: p.arrayOf( - p.shape({ - message: p.string.isRequired, - }), - ), -} diff --git a/web/src/app/wizard/WizardRouter.jsx b/web/src/app/wizard/WizardRouter.tsx similarity index 77% rename from web/src/app/wizard/WizardRouter.jsx rename to web/src/app/wizard/WizardRouter.tsx index 9b58c5491c..e61f79a38f 100644 --- a/web/src/app/wizard/WizardRouter.jsx +++ b/web/src/app/wizard/WizardRouter.tsx @@ -10,9 +10,9 @@ import DialogActions from '@mui/material/DialogActions' import makeStyles from '@mui/styles/makeStyles' import { DateTime } from 'luxon' import { fieldErrors, nonFieldErrors } from '../util/errutil' -import WizardForm from './WizardForm' +import WizardForm, { WizardFormValue } from './WizardForm' import LoadingButton from '../loading/components/LoadingButton' -import { gql, useMutation } from 'urql' +import { gql, useMutation, UseMutationExecute } from 'urql' import { Form } from '../forms' import { getService, @@ -24,6 +24,7 @@ import DialogTitleWrapper from '../dialogs/components/DialogTitleWrapper' import DialogContentError from '../dialogs/components/DialogContentError' import { useIsWidthDown } from '../util/useWidth' import { Redirect } from 'wouter' +import { CreateEscalationPolicyStepInput } from '../../schema' const mutation = gql` mutation ($input: CreateServiceInput!) { @@ -42,19 +43,19 @@ const useStyles = makeStyles(() => ({ }, })) -export default function WizardRouter() { +export default function WizardRouter(): React.JSX.Element { const classes = useStyles() const fullScreen = useIsWidthDown('md') - const [errorMessage, setErrorMessage] = useState(null) + const [errorMessage, setErrorMessage] = useState(null) const [complete, setComplete] = useState(false) const [redirect, setRedirect] = useState(false) - const [value, setValue] = useState({ + const [value, setValue] = useState({ teamName: '', - delayMinutes: '', + delayMinutes: 0, repeat: '', key: null, primarySchedule: { - timeZone: null, + timeZone: '', users: [], rotation: { startDate: DateTime.local().startOf('day').toISO(), @@ -91,11 +92,11 @@ export default function WizardRouter() { * Handles not returning a second step if the secondary * schedule is not enabled in the form. */ - const getSteps = () => { + const getSteps = (): CreateEscalationPolicyStepInput[] => { const secondary = value.secondarySchedule.enable === 'yes' const steps = [] - const step = (key) => ({ + const step = (key: string): CreateEscalationPolicyStepInput => ({ delayMinutes: value.delayMinutes, newSchedule: { ...getSchedule(key, value, secondary), @@ -119,7 +120,11 @@ export default function WizardRouter() { * * e.g. createService: { newEscalationPolicy: {...} } */ - const submit = (e, isValid, commit) => { + const submit = ( + e: { preventDefault: () => void }, + isValid: boolean, + commit: UseMutationExecute, + ): void => { e.preventDefault() // prevents reloading if (!isValid) return @@ -135,27 +140,33 @@ export default function WizardRouter() { }, } } catch (err) { - setErrorMessage(err.message) + setErrorMessage((err as Error).message) } if (variables) { commit(variables).then((result) => { if (result.error) { - const generalErrors = nonFieldErrors(result.error) - const graphqlErrors = fieldErrors(result.error).map((error) => { - const name = error.field - .split('.') - .pop() // get last occurrence - .replace(/([A-Z])/g, ' $1') // insert a space before all caps - .replace(/^./, (str) => str.toUpperCase()) // uppercase the first character + const nonFieldErrs = nonFieldErrors(result.error).map((e) => ({ + message: e.message, + })) + + const fieldErrs = fieldErrors(result.error) + .map((e) => { + const fieldError = e.field.split('.').pop() + if (!fieldError) return null + + const name = fieldError + .replace(/([A-Z])/g, ' $1') // insert a space before all caps + .replace(/^./, (str) => str.toUpperCase()) // uppercase the first character - return `${name}: ${error.message}` - }) + return { message: `${name}: ${e.message}` } + }) + .filter((error) => error !== null) as { message: string }[] - const errors = generalErrors.concat(graphqlErrors) + const errors = nonFieldErrs.concat(fieldErrs) if (errors.length) { - setErrorMessage(errors.map((e) => e.message || e).join('\n')) + setErrorMessage(errors.map((e) => e.message).join('\n')) } } else { setComplete(true) @@ -164,7 +175,7 @@ export default function WizardRouter() { } } - const onDialogClose = (data) => { + const onDialogClose = (data: { createService: boolean }): void => { if (data && data.createService) { return setRedirect(true) } @@ -174,7 +185,7 @@ export default function WizardRouter() { window.scrollTo(0, 0) } - function renderSubmittedContent() { + function renderSubmittedContent(): React.JSX.Element | undefined { if (complete) { return ( @@ -204,7 +215,6 @@ export default function WizardRouter() { > setValue(value)} diff --git a/web/src/app/wizard/WizardScheduleForm.jsx b/web/src/app/wizard/WizardScheduleForm.tsx similarity index 70% rename from web/src/app/wizard/WizardScheduleForm.jsx rename to web/src/app/wizard/WizardScheduleForm.tsx index 53f1c7b8b1..68335456da 100644 --- a/web/src/app/wizard/WizardScheduleForm.jsx +++ b/web/src/app/wizard/WizardScheduleForm.tsx @@ -1,5 +1,4 @@ import React from 'react' -import p from 'prop-types' import FormControl from '@mui/material/FormControl' import FormControlLabel from '@mui/material/FormControlLabel' import FormHelperText from '@mui/material/FormHelperText' @@ -11,11 +10,12 @@ import Tooltip from '@mui/material/Tooltip' import InfoIcon from '@mui/icons-material/Info' import { TimeZoneSelect, UserSelect } from '../selection' import { FormField } from '../forms' -import { value as valuePropType } from './propTypes' import * as _ from 'lodash' import { ISODateTimePicker } from '../util/ISOPickers' import makeStyles from '@mui/styles/makeStyles' import { useIsWidthDown } from '../util/useWidth' +import { WizardFormValue } from './WizardForm' +import { RotationType } from '../../schema' const useStyles = makeStyles(() => ({ fieldItem: { @@ -30,23 +30,41 @@ const useStyles = makeStyles(() => ({ }, })) +interface WizardScheduleFormProps { + value: WizardFormValue + onChange: (value: WizardFormValue) => void + secondary?: boolean +} + /** * Renders the form fields to be used in the wizard that * can be used for creating a primary and secondary schedule. */ -export default function WizardScheduleForm({ value, onChange, secondary }) { +export default function WizardScheduleForm({ + value, + onChange, + secondary, +}: WizardScheduleFormProps): React.JSX.Element { const fullScreen = useIsWidthDown('md') const classes = useStyles() + const schedType = secondary ? 'secondary' : 'primary' - function renderFollowTheSun(key, schedType) { - if (value[key].followTheSunRotation.enable === 'yes') { + const getScheduleField = (field: string): string => { + return `${secondary ? 'secondarySchedule' : 'primarySchedule'}.${field}` + } + + function renderFollowTheSun(): React.JSX.Element | undefined { + const currentSchedule = secondary + ? value.secondarySchedule + : value.primarySchedule + if (currentSchedule.followTheSunRotation.enable === 'yes') { return ( Who will be on call for your {schedType} follow the sun @@ -56,13 +74,13 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { formLabel fullWidth={fullScreen} required - value={value[key].followTheSunRotation.users} + value={currentSchedule.followTheSunRotation.users} /> What time zone is your {schedType} follow the sun @@ -79,27 +97,38 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { } } - const getKey = () => { - return secondary ? 'secondarySchedule' : 'primarySchedule' - } - - const handleRotationTypeChange = (e) => { + const handleRotationTypeChange = ( + e: React.ChangeEvent, + ): void => { const newVal = _.cloneDeep(value) - newVal[getKey()].rotation.type = e.target.value + if (secondary) { + newVal.secondarySchedule.rotation.type = e.target.value as RotationType + } else { + newVal.primarySchedule.rotation.type = e.target.value as RotationType + } onChange(newVal) } - const handleFollowTheSunToggle = (e) => { + const handleFollowTheSunToggle = ( + e: React.ChangeEvent, + ): void => { const newVal = _.cloneDeep(value) - newVal[getKey()].followTheSunRotation.enable = e.target.value + if (secondary) { + newVal.secondarySchedule.followTheSunRotation.enable = e.target.value + } else { + newVal.primarySchedule.followTheSunRotation.enable = e.target.value + } onChange(newVal) } - function renderRotationFields(key, schedType) { + function renderRotationFields(): React.JSX.Element { + const currentSchedule = secondary + ? value.secondarySchedule + : value.primarySchedule const hideRotationFields = - value[key].users.length <= 1 || - value[key].rotation.type === 'never' || - !value[key].rotation.type + currentSchedule.users.length <= 1 || + currentSchedule.rotation.type === 'never' || + !currentSchedule.rotation.type return ( @@ -116,26 +145,26 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { } label='Weekly' /> } label='Daily' /> } label='Never*' @@ -154,7 +183,7 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { @@ -187,19 +218,19 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { } label='Yes' /> } label='No' @@ -207,7 +238,7 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { - {renderFollowTheSun(key, schedType)} + {renderFollowTheSun()} )} @@ -222,15 +253,12 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { * Ask if second assignment is needed for evening shifts * - repeat choosing users if yes */ - const key = secondary ? 'secondarySchedule' : 'primarySchedule' - const schedType = secondary ? 'secondary' : 'primary' - return ( What time zone is your {schedType} schedule based in? @@ -244,9 +272,9 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { Who will be on call for your {schedType} schedule? @@ -255,16 +283,12 @@ export default function WizardScheduleForm({ value, onChange, secondary }) { formLabel fullWidth={fullScreen} required - value={value[key].users} + value={ + value[secondary ? 'secondarySchedule' : 'primarySchedule'].users + } /> - {renderRotationFields(key, schedType)} + {renderRotationFields()} ) } - -WizardScheduleForm.propTypes = { - onChange: p.func.isRequired, - value: valuePropType, - secondary: p.bool, -} diff --git a/web/src/app/wizard/propTypes.js b/web/src/app/wizard/propTypes.js deleted file mode 100644 index c9d6d5bedd..0000000000 --- a/web/src/app/wizard/propTypes.js +++ /dev/null @@ -1,27 +0,0 @@ -import p from 'prop-types' - -const scheduleShape = p.shape({ - timeZone: p.string, - users: p.array, - rotation: p.shape({ - startDate: p.string, - type: p.string, - }), - followTheSunRotation: p.shape({ - enable: p.string, - users: p.array, - timeZone: p.string, - }), -}) - -export const value = p.shape({ - teamName: p.string, - primarySchedule: scheduleShape, - secondarySchedule: scheduleShape, - delayMinutes: p.string, - repeat: p.string, - key: p.shape({ - label: p.string, - value: p.string, - }), -}).isRequired diff --git a/web/src/app/wizard/util.test.js b/web/src/app/wizard/util.test.ts similarity index 77% rename from web/src/app/wizard/util.test.js rename to web/src/app/wizard/util.test.ts index 43a4f08fd4..edbd148bb6 100644 --- a/web/src/app/wizard/util.test.js +++ b/web/src/app/wizard/util.test.ts @@ -17,8 +17,8 @@ describe('wizard tests', () => { favorite: true, newIntegrationKeys: [ { - type: usersSchedules.key.value, - name: `${usersSchedules.key.label} Integration Key`, + type: usersSchedules.key?.value, + name: `${usersSchedules.key?.label} Integration Key`, }, ], }) @@ -28,12 +28,12 @@ describe('wizard tests', () => { expect(getEscalationPolicy(usersSchedules)).toEqual({ name: 'Test', description, - repeat: usersSchedules.repeat, + repeat: Number(usersSchedules.repeat), }) }) it('get primary schedule', () => { - expect(getSchedule('primarySchedule', usersSchedules)).toEqual({ + expect(getSchedule('primarySchedule', usersSchedules, false)).toEqual({ name: 'Test', description, timeZone: usersSchedules.primarySchedule.timeZone, @@ -42,8 +42,8 @@ describe('wizard tests', () => { }) it('get secondary schedule', () => { - expect(getSchedule('secondarySchedule', usersSchedules)).toEqual({ - name: 'Test', + expect(getSchedule('secondarySchedule', usersSchedules, true)).toEqual({ + name: 'Test Secondary', description, timeZone: usersSchedules.secondarySchedule.timeZone, favorite: true, @@ -51,7 +51,9 @@ describe('wizard tests', () => { }) it('get primary schedule targets as users', () => { - expect(getScheduleTargets('primarySchedule', usersSchedules)).toEqual([ + expect( + getScheduleTargets('primarySchedule', usersSchedules, false), + ).toEqual([ { target: { id: '50322144-1e88-43dc-b638-b16a5be7bad6', @@ -77,7 +79,9 @@ describe('wizard tests', () => { }) it('get secondary schedule targets as users', () => { - expect(getScheduleTargets('secondarySchedule', usersSchedules)).toEqual([ + expect( + getScheduleTargets('secondarySchedule', usersSchedules, true), + ).toEqual([ { target: { id: '50322144-1e88-43dc-b638-b16a5be7bad6', @@ -108,13 +112,15 @@ describe('wizard tests', () => { const type = rotationsNoFTS.primarySchedule.rotation.type const userIDs = rotationsNoFTS.primarySchedule.users - expect(getScheduleTargets('primarySchedule', rotationsNoFTS)).toEqual([ + expect( + getScheduleTargets('primarySchedule', rotationsNoFTS, false), + ).toEqual([ { newRotation: { name: 'Test', description, timeZone, - start: DateTime.fromISO(start).minus({ day: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ day: 1 }).toISO(), type, userIDs, }, @@ -129,13 +135,15 @@ describe('wizard tests', () => { const type = rotationsNoFTS.secondarySchedule.rotation.type const userIDs = rotationsNoFTS.secondarySchedule.users - expect(getScheduleTargets('secondarySchedule', rotationsNoFTS)).toEqual([ + expect( + getScheduleTargets('secondarySchedule', rotationsNoFTS, true), + ).toEqual([ { newRotation: { - name: 'Test', + name: 'Test Secondary', description, timeZone, - start: DateTime.fromISO(start).minus({ week: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ week: 1 }).toISO(), type, userIDs, }, @@ -154,13 +162,15 @@ describe('wizard tests', () => { const ftsUserIDs = rotationsAndFTS.primarySchedule.followTheSunRotation.users - expect(getScheduleTargets('primarySchedule', rotationsAndFTS)).toEqual([ + expect( + getScheduleTargets('primarySchedule', rotationsAndFTS, false), + ).toEqual([ { newRotation: { name: 'Test', description, timeZone, - start: DateTime.fromISO(start).minus({ week: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ week: 1 }).toISO(), type, userIDs, }, @@ -171,7 +181,7 @@ describe('wizard tests', () => { name: 'Test America-Chicago', description, timeZone: ftsTimeZone, - start: DateTime.fromISO(start).minus({ week: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ week: 1 }).toISO(), type, userIDs: ftsUserIDs, }, @@ -190,13 +200,15 @@ describe('wizard tests', () => { const ftsUserIDs = rotationsAndFTS.secondarySchedule.followTheSunRotation.users - expect(getScheduleTargets('secondarySchedule', rotationsAndFTS)).toEqual([ + expect( + getScheduleTargets('secondarySchedule', rotationsAndFTS, true), + ).toEqual([ { newRotation: { - name: 'Test', + name: 'Test Secondary', description, timeZone, - start: DateTime.fromISO(start).minus({ day: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ day: 1 }).toISO(), type, userIDs, }, @@ -206,10 +218,10 @@ describe('wizard tests', () => { // also tests if FTS time zone is the same as the original, prepend FTS // so names don't conflict newRotation: { - name: 'Test Africa-Accra FTS', + name: 'Test Secondary Africa-Accra FTS', description, timeZone: ftsTimeZone, - start: DateTime.fromISO(start).minus({ day: 1 }).toISO(), + start: DateTime.fromISO(start!).minus({ day: 1 }).toISO(), type, userIDs: ftsUserIDs, }, diff --git a/web/src/app/wizard/util.js b/web/src/app/wizard/util.ts similarity index 50% rename from web/src/app/wizard/util.js rename to web/src/app/wizard/util.ts index 3663224930..e0a4b3cb9d 100644 --- a/web/src/app/wizard/util.js +++ b/web/src/app/wizard/util.ts @@ -1,34 +1,50 @@ -import { DateTime } from 'luxon' +import { DateTime, DurationLike } from 'luxon' +import { WizardFormValue } from './WizardForm' +import { + CreateEscalationPolicyInput, + CreateRotationInput, + CreateScheduleInput, + CreateServiceInput, + IntegrationKeyType, + RotationType, + ScheduleTargetInput, +} from '../../schema' const DESC = 'Generated by Setup Wizard' const CHAR_LIMIT = 64 const SECONDARY_CHAR_COUNT = 10 const FTS_CHAR_COUNT = 4 -export function getService(value) { +export function getService(value: WizardFormValue): CreateServiceInput { return { name: value.teamName, description: DESC, newIntegrationKeys: [ { - type: value.key.value, - name: value.key.label + ' Integration Key', + type: value.key?.value as IntegrationKeyType, + name: value.key?.label + ' Integration Key', }, ], favorite: true, } } -export function getEscalationPolicy(value) { +export function getEscalationPolicy( + value: WizardFormValue, +): CreateEscalationPolicyInput { return { name: value.teamName, description: DESC, - repeat: value.repeat, + repeat: Number(value.repeat), } } -export function getSchedule(key, value, secondary) { - const s = value[key] +export function getSchedule( + key: string, + value: WizardFormValue, + secondary: boolean, +): CreateScheduleInput { + const s = secondary ? value.secondarySchedule : value.primarySchedule let name = value.teamName if (secondary) { @@ -38,7 +54,7 @@ export function getSchedule(key, value, secondary) { return { name, description: DESC, - timeZone: s.timeZone, + timeZone: s.timeZone || '', favorite: true, } } @@ -47,9 +63,13 @@ export function getSchedule(key, value, secondary) { * Generates the variables for the targets * to be used while creating a new schedule */ -export function getScheduleTargets(key, value, secondary) { - const s = value[key] - const targets = [] +export function getScheduleTargets( + key: string, + value: WizardFormValue, + secondary: boolean, +): ScheduleTargetInput[] { + const s = secondary ? value.secondarySchedule : value.primarySchedule + const targets = [] as ScheduleTargetInput[] const fts = s.followTheSunRotation.enable === 'yes' // return just the users as schedule targets if rotation type is set to "never" @@ -68,7 +88,7 @@ export function getScheduleTargets(key, value, secondary) { const duration = type === 'daily' ? { day: 1 } : type === 'weekly' ? { week: 1 } : null - const target = (isFTS) => { + const target = (isFTS: boolean): CreateRotationInput => { let tzText = isFTS ? s.followTheSunRotation.timeZone : '' if (isFTS && s.followTheSunRotation.timeZone === s.timeZone) { tzText = tzText + ' FTS' @@ -79,26 +99,40 @@ export function getScheduleTargets(key, value, secondary) { (secondary ? (key.includes('primary') ? ' Primary' : ' Secondary') : '') + (tzText ? ` ${tzText}` : '') + const getErrMsg = (): number => { + const timeZoneLength = isFTS + ? s.followTheSunRotation?.timeZone?.length + : 0 + const timeZoneMatch = + isFTS && s.followTheSunRotation?.timeZone === s.timeZone + ? FTS_CHAR_COUNT + : 0 + const secondaryCharCount = secondary ? SECONDARY_CHAR_COUNT : 0 + + const remainingChars = + CHAR_LIMIT - secondaryCharCount - (timeZoneLength || 0) - timeZoneMatch + + throw new Error(`cannot be more than ${remainingChars} characters`) + } + // name length validation if (name.length > CHAR_LIMIT) { - throw new Error( - `cannot be more than ${ - CHAR_LIMIT - - (secondary ? SECONDARY_CHAR_COUNT : 0) - - (isFTS ? s.followTheSunRotation.timeZone.length : 0) - - (isFTS && s.followTheSunRotation.timeZone === s.timeZone - ? FTS_CHAR_COUNT - : 0) - } characters`, - ) + throw getErrMsg() + } + + const getTimeZone = (): string => { + if (isFTS) return s.followTheSunRotation.timeZone as string + return s.timeZone as string } return { name: name.replace(/\//g, '-'), description: DESC, - timeZone: isFTS ? s.followTheSunRotation.timeZone : s.timeZone, - start: DateTime.fromISO(s.rotation.startDate).minus(duration).toISO(), - type: s.rotation.type, + timeZone: getTimeZone(), + start: DateTime.fromISO(s.rotation?.startDate as string) + .minus(duration as DurationLike) + .toISO(), + type: s.rotation.type as RotationType, userIDs: isFTS ? s.followTheSunRotation.users : s.users, } } diff --git a/web/src/app/wizard/utilTestData.js b/web/src/app/wizard/utilTestData.ts similarity index 88% rename from web/src/app/wizard/utilTestData.js rename to web/src/app/wizard/utilTestData.ts index d49b97734c..5848361202 100644 --- a/web/src/app/wizard/utilTestData.js +++ b/web/src/app/wizard/utilTestData.ts @@ -1,5 +1,6 @@ import { DateTime } from 'luxon' import { Chance } from 'chance' +import { WizardFormValue } from './WizardForm' const c = new Chance() const keys = [ @@ -34,9 +35,9 @@ const users = [ const timeZones = ['America/Chicago', 'Africa/Accra', 'Etc/UTC'] // scheds w/ users -export const usersSchedules = { +export const usersSchedules: WizardFormValue = { teamName: 'Test', - delayMinutes: c.integer({ min: 1, max: 9000 }).toString(), + delayMinutes: c.integer({ min: 1, max: 9000 }), repeat: c.integer({ min: 1, max: 5 }).toString(), key: c.pickone(keys), primarySchedule: { @@ -69,9 +70,9 @@ export const usersSchedules = { } // scheds w/ rotations (no fts) -export const rotationsNoFTS = { +export const rotationsNoFTS: WizardFormValue = { teamName: 'Test', - delayMinutes: c.integer({ min: 1, max: 9000 }).toString(), + delayMinutes: c.integer({ min: 1, max: 9000 }), repeat: c.integer({ min: 1, max: 5 }).toString(), key: c.pickone(keys), primarySchedule: { @@ -104,9 +105,9 @@ export const rotationsNoFTS = { } // scheds w/ rotations + fts -export const rotationsAndFTS = { +export const rotationsAndFTS: WizardFormValue = { teamName: 'Test', - delayMinutes: c.integer({ min: 1, max: 9000 }).toString(), + delayMinutes: c.integer({ min: 1, max: 9000 }), repeat: c.integer({ min: 1, max: 5 }).toString(), key: c.pickone(keys), primarySchedule: {