diff --git a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx index 8e89cf87b9..d568dc1810 100644 --- a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx @@ -45,14 +45,14 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { return ( - {({ validateForm, handleSubmit }) => ( + {({ validateForm, setTouched, handleSubmit }) => ( { if (nextStep.id === 'preview') { - visitAllSteps(); + visitAllSteps(setTouched); } else { visitStep(prevStep.prevId); } @@ -60,7 +60,7 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { }} onGoToStep={async (newStep, prevStep) => { if (newStep.id === 'preview') { - visitAllSteps(); + visitAllSteps(setTouched); } else { visitStep(prevStep.prevId); } diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx index e17a9861a1..f63d85599b 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx @@ -20,6 +20,11 @@ export default function useCredentialsStep( validate, isReady: true, error: null, + setTouched: setFieldsTouched => { + setFieldsTouched({ + credentials: true, + }); + }, }; } diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx index 3098f2b0f6..e0d0ea009b 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx @@ -25,6 +25,11 @@ export default function useInventoryStep(config, resource, visitedSteps, i18n) { validate, isReady: true, error: null, + setTouched: setFieldsTouched => { + setFieldsTouched({ + inventory: true, + }); + }, }; } diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx index b92f1e2eb9..516238ca7a 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx @@ -25,6 +25,17 @@ export default function useOtherPrompt(config, resource, visitedSteps, i18n) { validate, isReady: true, error: null, + setTouched: setFieldsTouched => { + setFieldsTouched({ + job_type: true, + limit: true, + verbosity: true, + diff_mode: true, + job_tags: true, + skip_tags: true, + extra_vars: true, + }); + }, }; } diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx index ec34d8e7d5..a7ae2c61d1 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx @@ -27,7 +27,9 @@ export default function usePreviewStep( nextButtonText: i18n._(t`Launch`), }, initialValues: {}, + validate: () => ({}), isReady: true, error: null, + setTouched: () => {}, }; } diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx index dd824616f8..8b4014b251 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx @@ -55,6 +55,16 @@ export default function useSurveyStep(config, resource, visitedSteps, i18n) { survey, isReady: !isLoading && !!survey, error, + setTouched: setFieldsTouched => { + if (!survey) { + return; + } + const fields = {}; + survey.spec.forEach(question => { + fields[`survey_${question.variable}`] = true; + }); + setFieldsTouched(fields); + }, }; } diff --git a/awx/ui_next/src/components/LaunchPrompt/useSteps.js b/awx/ui_next/src/components/LaunchPrompt/useSteps.js index 871ce8c5a1..ed61a01804 100644 --- a/awx/ui_next/src/components/LaunchPrompt/useSteps.js +++ b/awx/ui_next/src/components/LaunchPrompt/useSteps.js @@ -7,70 +7,53 @@ import usePreviewStep from './steps/usePreviewStep'; export default function useSteps(config, resource, i18n) { const [visited, setVisited] = useState({}); - const inventory = useInventoryStep(config, resource, visited, i18n); - const credentials = useCredentialsStep(config, resource, visited, i18n); - const otherPrompts = useOtherPromptsStep(config, resource, visited, i18n); - const survey = useSurveyStep(config, resource, visited, i18n); - const preview = usePreviewStep( - config, - resource, - survey.survey, - {}, // TODO: formErrors ? - i18n + const steps = [ + useInventoryStep(config, resource, visited, i18n), + useCredentialsStep(config, resource, visited, i18n), + useOtherPromptsStep(config, resource, visited, i18n), + useSurveyStep(config, resource, visited, i18n), + ]; + steps.push( + usePreviewStep( + config, + resource, + steps[3].survey, + {}, // TODO: formErrors ? + i18n + ) ); - // TODO useState for steps to track dynamic steps (credentialPasswords)? - const steps = [ - inventory.step, - credentials.step, - otherPrompts.step, - survey.step, - preview.step, - ].filter(step => step !== null); - const initialValues = { - ...inventory.initialValues, - ...credentials.initialValues, - ...otherPrompts.initialValues, - ...survey.initialValues, - }; - const isReady = - inventory.isReady && - credentials.isReady && - otherPrompts.isReady && - survey.isReady && - preview.isReady; - const contentError = - inventory.error || - credentials.error || - otherPrompts.error || - survey.error || - preview.error; - - // TODO: store error state in each step's hook. - // but continue to return values here (async?) so form errors can be returned - // out and set into Formik - const validate = values => { - const errors = { - ...inventory.validate(values), - ...credentials.validate(values), - ...otherPrompts.validate(values), - ...survey.validate(values), + const pfSteps = steps.map(s => s.step).filter(s => s != null); + const initialValues = steps.reduce((acc, cur) => { + return { + ...acc, + ...cur.initialValues, }; - // setFormErrors(errors); + }, {}); + const isReady = !steps.some(s => !s.isReady); + const stepWithError = steps.find(s => s.error); + const contentError = stepWithError ? stepWithError.error : null; + + const validate = values => { + const errors = steps.reduce((acc, cur) => { + return { + ...acc, + ...cur.validate(values), + }; + }, {}); if (Object.keys(errors).length) { return errors; } return false; }; - // TODO move visited flags into each step hook return { - steps, + steps: pfSteps, initialValues, isReady, validate, visitStep: stepId => setVisited({ ...visited, [stepId]: true }), - visitAllSteps: () => { + visitAllSteps: setFieldsTouched => { setVisited({ inventory: true, credentials: true, @@ -78,6 +61,7 @@ export default function useSteps(config, resource, i18n) { survey: true, preview: true, }); + steps.forEach(s => s.setTouched(setFieldsTouched)); }, contentError, };