set fields touched when steps marked as visited

This commit is contained in:
Keith Grant
2020-05-07 16:36:34 -07:00
parent 59e3306a3c
commit 0b207e02ab
7 changed files with 70 additions and 53 deletions

View File

@@ -45,14 +45,14 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) {
return ( return (
<Formik initialValues={initialValues} onSubmit={submit} validate={validate}> <Formik initialValues={initialValues} onSubmit={submit} validate={validate}>
{({ validateForm, handleSubmit }) => ( {({ validateForm, setTouched, handleSubmit }) => (
<Wizard <Wizard
isOpen isOpen
onClose={onCancel} onClose={onCancel}
onSave={handleSubmit} onSave={handleSubmit}
onNext={async (nextStep, prevStep) => { onNext={async (nextStep, prevStep) => {
if (nextStep.id === 'preview') { if (nextStep.id === 'preview') {
visitAllSteps(); visitAllSteps(setTouched);
} else { } else {
visitStep(prevStep.prevId); visitStep(prevStep.prevId);
} }
@@ -60,7 +60,7 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) {
}} }}
onGoToStep={async (newStep, prevStep) => { onGoToStep={async (newStep, prevStep) => {
if (newStep.id === 'preview') { if (newStep.id === 'preview') {
visitAllSteps(); visitAllSteps(setTouched);
} else { } else {
visitStep(prevStep.prevId); visitStep(prevStep.prevId);
} }

View File

@@ -20,6 +20,11 @@ export default function useCredentialsStep(
validate, validate,
isReady: true, isReady: true,
error: null, error: null,
setTouched: setFieldsTouched => {
setFieldsTouched({
credentials: true,
});
},
}; };
} }

View File

@@ -25,6 +25,11 @@ export default function useInventoryStep(config, resource, visitedSteps, i18n) {
validate, validate,
isReady: true, isReady: true,
error: null, error: null,
setTouched: setFieldsTouched => {
setFieldsTouched({
inventory: true,
});
},
}; };
} }

View File

@@ -25,6 +25,17 @@ export default function useOtherPrompt(config, resource, visitedSteps, i18n) {
validate, validate,
isReady: true, isReady: true,
error: null, error: null,
setTouched: setFieldsTouched => {
setFieldsTouched({
job_type: true,
limit: true,
verbosity: true,
diff_mode: true,
job_tags: true,
skip_tags: true,
extra_vars: true,
});
},
}; };
} }

View File

@@ -27,7 +27,9 @@ export default function usePreviewStep(
nextButtonText: i18n._(t`Launch`), nextButtonText: i18n._(t`Launch`),
}, },
initialValues: {}, initialValues: {},
validate: () => ({}),
isReady: true, isReady: true,
error: null, error: null,
setTouched: () => {},
}; };
} }

View File

@@ -55,6 +55,16 @@ export default function useSurveyStep(config, resource, visitedSteps, i18n) {
survey, survey,
isReady: !isLoading && !!survey, isReady: !isLoading && !!survey,
error, error,
setTouched: setFieldsTouched => {
if (!survey) {
return;
}
const fields = {};
survey.spec.forEach(question => {
fields[`survey_${question.variable}`] = true;
});
setFieldsTouched(fields);
},
}; };
} }

View File

@@ -7,70 +7,53 @@ import usePreviewStep from './steps/usePreviewStep';
export default function useSteps(config, resource, i18n) { export default function useSteps(config, resource, i18n) {
const [visited, setVisited] = useState({}); const [visited, setVisited] = useState({});
const inventory = useInventoryStep(config, resource, visited, i18n); const steps = [
const credentials = useCredentialsStep(config, resource, visited, i18n); useInventoryStep(config, resource, visited, i18n),
const otherPrompts = useOtherPromptsStep(config, resource, visited, i18n); useCredentialsStep(config, resource, visited, i18n),
const survey = useSurveyStep(config, resource, visited, i18n); useOtherPromptsStep(config, resource, visited, i18n),
const preview = usePreviewStep( useSurveyStep(config, resource, visited, i18n),
config, ];
resource, steps.push(
survey.survey, usePreviewStep(
{}, // TODO: formErrors ? config,
i18n resource,
steps[3].survey,
{}, // TODO: formErrors ?
i18n
)
); );
// TODO useState for steps to track dynamic steps (credentialPasswords)? const pfSteps = steps.map(s => s.step).filter(s => s != null);
const steps = [ const initialValues = steps.reduce((acc, cur) => {
inventory.step, return {
credentials.step, ...acc,
otherPrompts.step, ...cur.initialValues,
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),
}; };
// 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) { if (Object.keys(errors).length) {
return errors; return errors;
} }
return false; return false;
}; };
// TODO move visited flags into each step hook
return { return {
steps, steps: pfSteps,
initialValues, initialValues,
isReady, isReady,
validate, validate,
visitStep: stepId => setVisited({ ...visited, [stepId]: true }), visitStep: stepId => setVisited({ ...visited, [stepId]: true }),
visitAllSteps: () => { visitAllSteps: setFieldsTouched => {
setVisited({ setVisited({
inventory: true, inventory: true,
credentials: true, credentials: true,
@@ -78,6 +61,7 @@ export default function useSteps(config, resource, i18n) {
survey: true, survey: true,
preview: true, preview: true,
}); });
steps.forEach(s => s.setTouched(setFieldsTouched));
}, },
contentError, contentError,
}; };