From 11752e123dab9d314448edf96c0310931852deb9 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Fri, 1 May 2020 15:30:48 -0700 Subject: [PATCH] converting prompt steps to hook-based approach --- .../LaunchPrompt/LaunchPrompt.ORIGINAL.jsx | 223 ++++++++++++++++++ .../components/LaunchPrompt/LaunchPrompt.jsx | 188 ++------------- .../src/components/LaunchPrompt/hooks.js | 70 ++++++ .../{ => steps}/CredentialsStep.jsx | 0 .../{ => steps}/CredentialsStep.test.jsx | 0 .../{ => steps}/InventoryStep.jsx | 0 .../{ => steps}/InventoryStep.test.jsx | 0 .../{ => steps}/OtherPromptsStep.jsx | 0 .../{ => steps}/OtherPromptsStep.test.jsx | 0 .../LaunchPrompt/{ => steps}/PreviewStep.jsx | 2 +- .../LaunchPrompt/{ => steps}/SurveyStep.jsx | 0 .../LaunchPrompt/steps/useCredentialsStep.jsx | 34 +++ .../LaunchPrompt/steps/useInventoryStep.jsx | 34 +++ .../steps/useOtherPromptsStep.jsx | 67 ++++++ .../LaunchPrompt/steps/usePreviewStep.jsx | 33 +++ .../LaunchPrompt/steps/useSurveyStep.jsx | 60 +++++ 16 files changed, 548 insertions(+), 163 deletions(-) create mode 100644 awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.ORIGINAL.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/hooks.js rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/CredentialsStep.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/CredentialsStep.test.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/InventoryStep.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/InventoryStep.test.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/OtherPromptsStep.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/OtherPromptsStep.test.jsx (100%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/PreviewStep.jsx (92%) rename awx/ui_next/src/components/LaunchPrompt/{ => steps}/SurveyStep.jsx (100%) create mode 100644 awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.ORIGINAL.jsx b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.ORIGINAL.jsx new file mode 100644 index 0000000000..8666c838ea --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.ORIGINAL.jsx @@ -0,0 +1,223 @@ +import React, { useState, useCallback, useEffect } from 'react'; +import { Wizard } from '@patternfly/react-core'; +import { withI18n } from '@lingui/react'; +import { t } from '@lingui/macro'; +import { Formik } from 'formik'; +import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api'; +import useRequest from '@util/useRequest'; +import ContentError from '@components/ContentError'; +import ContentLoading from '@components/ContentLoading'; +import { required } from '@util/validators'; +import InventoryStep from './InventoryStep'; +import CredentialsStep from './CredentialsStep'; +import OtherPromptsStep from './OtherPromptsStep'; +import SurveyStep from './SurveyStep'; +import PreviewStep from './PreviewStep'; +import PromptFooter from './PromptFooter'; +import mergeExtraVars from './mergeExtraVars'; + +const STEPS = { + INVENTORY: 'inventory', + CREDENTIALS: 'credentials', + PASSWORDS: 'passwords', + OTHER_PROMPTS: 'other', + SURVEY: 'survey', + PREVIEW: 'preview', +}; + +function showOtherPrompts(config) { + return ( + config.ask_job_type_on_launch || + config.ask_limit_on_launch || + config.ask_verbosity_on_launch || + config.ask_tags_on_launch || + config.ask_skip_tags_on_launch || + config.ask_variables_on_launch || + config.ask_scm_branch_on_launch || + config.ask_diff_mode_on_launch + ); +} + +function getInitialVisitedSteps(config) { + const visited = {}; + if (config.ask_inventory_on_launch) { + visited[STEPS.INVENTORY] = false; + } + if (config.ask_credential_on_launch) { + visited[STEPS.CREDENTIALS] = false; + } + if (showOtherPrompts(config)) { + visited[STEPS.OTHER_PROMPTS] = false; + } + if (config.survey_enabled) { + visited[STEPS.SURVEY] = false; + } + return visited; +} + +function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { + const [formErrors, setFormErrors] = useState({}); + const [visitedSteps, setVisitedSteps] = useState( + getInitialVisitedSteps(config) + ); + + const { + result: survey, + request: fetchSurvey, + error: surveyError, + } = useRequest( + useCallback(async () => { + if (!config.survey_enabled) { + return {}; + } + const { data } = + resource.type === 'workflow_job_template' + ? await WorkflowJobTemplatesAPI.readSurvey(resource.id) + : await JobTemplatesAPI.readSurvey(resource.id); + return data; + }, [config.survey_enabled, resource]) + ); + useEffect(() => { + fetchSurvey(); + }, [fetchSurvey]); + + if (surveyError) { + return ; + } + if (config.survey_enabled && !survey) { + return ; + } + + const steps = []; + const initialValues = {}; + if (config.ask_inventory_on_launch) { + initialValues.inventory = resource?.summary_fields?.inventory || null; + steps.push({ + id: STEPS.INVENTORY, + name: i18n._(t`Inventory`), + component: , + }); + } + if (config.ask_credential_on_launch) { + initialValues.credentials = resource?.summary_fields?.credentials || []; + steps.push({ + id: STEPS.CREDENTIALS, + name: i18n._(t`Credentials`), + component: , + }); + } + + // TODO: Add Credential Passwords step + + if (config.ask_job_type_on_launch) { + initialValues.job_type = resource.job_type || ''; + } + if (config.ask_limit_on_launch) { + initialValues.limit = resource.limit || ''; + } + if (config.ask_verbosity_on_launch) { + initialValues.verbosity = resource.verbosity || 0; + } + if (config.ask_tags_on_launch) { + initialValues.job_tags = resource.job_tags || ''; + } + if (config.ask_skip_tags_on_launch) { + initialValues.skip_tags = resource.skip_tags || ''; + } + if (config.ask_variables_on_launch) { + initialValues.extra_vars = resource.extra_vars || '---'; + } + if (config.ask_scm_branch_on_launch) { + initialValues.scm_branch = resource.scm_branch || ''; + } + if (config.ask_diff_mode_on_launch) { + initialValues.diff_mode = resource.diff_mode || false; + } + if (showOtherPrompts(config)) { + steps.push({ + id: STEPS.OTHER_PROMPTS, + name: i18n._(t`Other Prompts`), + component: , + }); + } + if (config.survey_enabled) { + initialValues.survey = {}; + // survey.spec.forEach(question => { + // initialValues[`survey_${question.variable}`] = question.default; + // }) + steps.push({ + id: STEPS.SURVEY, + name: i18n._(t`Survey`), + component: , + }); + } + steps.push({ + id: STEPS.PREVIEW, + name: i18n._(t`Preview`), + component: ( + + ), + enableNext: Object.keys(formErrors).length === 0, + nextButtonText: i18n._(t`Launch`), + }); + + const validate = values => { + // return {}; + return { limit: ['required field'] }; + }; + + const submit = values => { + const postValues = {}; + const setValue = (key, value) => { + if (typeof value !== 'undefined' && value !== null) { + postValues[key] = value; + } + }; + setValue('inventory_id', values.inventory?.id); + setValue('credentials', values.credentials?.map(c => c.id)); + setValue('job_type', values.job_type); + setValue('limit', values.limit); + setValue('job_tags', values.job_tags); + setValue('skip_tags', values.skip_tags); + setValue('extra_vars', mergeExtraVars(values.extra_vars, values.survey)); + onLaunch(postValues); + }; + console.log('formErrors:', formErrors); + + return ( + + {({ errors, values, touched, validateForm, handleSubmit }) => ( + { + // console.log(`${prevStep.prevName} -> ${nextStep.name}`); + // console.log('errors', errors); + // console.log('values', values); + const newErrors = await validateForm(); + setFormErrors(newErrors); + // console.log('new errors:', newErrors); + }} + onGoToStep={async (newStep, prevStep) => { + // console.log('errors', errors); + // console.log('values', values); + const newErrors = await validateForm(); + setFormErrors(newErrors); + }} + title={i18n._(t`Prompts`)} + steps={steps} + // footer={} + /> + )} + + ); +} + +export { LaunchPrompt as _LaunchPrompt }; +export default withI18n()(LaunchPrompt); diff --git a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx index 8666c838ea..bc77a30555 100644 --- a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx @@ -3,174 +3,42 @@ import { Wizard } from '@patternfly/react-core'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Formik } from 'formik'; -import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api'; -import useRequest from '@util/useRequest'; +// import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api'; +// import useRequest from '@util/useRequest'; import ContentError from '@components/ContentError'; import ContentLoading from '@components/ContentLoading'; -import { required } from '@util/validators'; -import InventoryStep from './InventoryStep'; -import CredentialsStep from './CredentialsStep'; -import OtherPromptsStep from './OtherPromptsStep'; -import SurveyStep from './SurveyStep'; -import PreviewStep from './PreviewStep'; -import PromptFooter from './PromptFooter'; +// import { required } from '@util/validators'; +// import InventoryStep from './InventoryStep'; +// import CredentialsStep from './CredentialsStep'; +// import OtherPromptsStep from './OtherPromptsStep'; +// import SurveyStep from './SurveyStep'; +// import PreviewStep from './PreviewStep'; +// import PromptFooter from './PromptFooter'; import mergeExtraVars from './mergeExtraVars'; - -const STEPS = { - INVENTORY: 'inventory', - CREDENTIALS: 'credentials', - PASSWORDS: 'passwords', - OTHER_PROMPTS: 'other', - SURVEY: 'survey', - PREVIEW: 'preview', -}; - -function showOtherPrompts(config) { - return ( - config.ask_job_type_on_launch || - config.ask_limit_on_launch || - config.ask_verbosity_on_launch || - config.ask_tags_on_launch || - config.ask_skip_tags_on_launch || - config.ask_variables_on_launch || - config.ask_scm_branch_on_launch || - config.ask_diff_mode_on_launch - ); -} - -function getInitialVisitedSteps(config) { - const visited = {}; - if (config.ask_inventory_on_launch) { - visited[STEPS.INVENTORY] = false; - } - if (config.ask_credential_on_launch) { - visited[STEPS.CREDENTIALS] = false; - } - if (showOtherPrompts(config)) { - visited[STEPS.OTHER_PROMPTS] = false; - } - if (config.survey_enabled) { - visited[STEPS.SURVEY] = false; - } - return visited; -} +import { useSteps, useVisitedSteps } from './hooks'; function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { - const [formErrors, setFormErrors] = useState({}); - const [visitedSteps, setVisitedSteps] = useState( - getInitialVisitedSteps(config) + const { steps, initialValues, isReady, contentError } = useSteps( + config, + resource, + i18n ); + const [visitedSteps, visitStep] = useVisitedSteps(config); - const { - result: survey, - request: fetchSurvey, - error: surveyError, - } = useRequest( - useCallback(async () => { - if (!config.survey_enabled) { - return {}; - } - const { data } = - resource.type === 'workflow_job_template' - ? await WorkflowJobTemplatesAPI.readSurvey(resource.id) - : await JobTemplatesAPI.readSurvey(resource.id); - return data; - }, [config.survey_enabled, resource]) - ); - useEffect(() => { - fetchSurvey(); - }, [fetchSurvey]); - - if (surveyError) { - return ; + if (contentError) { + return ; } - if (config.survey_enabled && !survey) { + if (!isReady) { return ; } - const steps = []; - const initialValues = {}; - if (config.ask_inventory_on_launch) { - initialValues.inventory = resource?.summary_fields?.inventory || null; - steps.push({ - id: STEPS.INVENTORY, - name: i18n._(t`Inventory`), - component: , - }); - } - if (config.ask_credential_on_launch) { - initialValues.credentials = resource?.summary_fields?.credentials || []; - steps.push({ - id: STEPS.CREDENTIALS, - name: i18n._(t`Credentials`), - component: , - }); - } - - // TODO: Add Credential Passwords step - - if (config.ask_job_type_on_launch) { - initialValues.job_type = resource.job_type || ''; - } - if (config.ask_limit_on_launch) { - initialValues.limit = resource.limit || ''; - } - if (config.ask_verbosity_on_launch) { - initialValues.verbosity = resource.verbosity || 0; - } - if (config.ask_tags_on_launch) { - initialValues.job_tags = resource.job_tags || ''; - } - if (config.ask_skip_tags_on_launch) { - initialValues.skip_tags = resource.skip_tags || ''; - } - if (config.ask_variables_on_launch) { - initialValues.extra_vars = resource.extra_vars || '---'; - } - if (config.ask_scm_branch_on_launch) { - initialValues.scm_branch = resource.scm_branch || ''; - } - if (config.ask_diff_mode_on_launch) { - initialValues.diff_mode = resource.diff_mode || false; - } - if (showOtherPrompts(config)) { - steps.push({ - id: STEPS.OTHER_PROMPTS, - name: i18n._(t`Other Prompts`), - component: , - }); - } - if (config.survey_enabled) { - initialValues.survey = {}; - // survey.spec.forEach(question => { - // initialValues[`survey_${question.variable}`] = question.default; - // }) - steps.push({ - id: STEPS.SURVEY, - name: i18n._(t`Survey`), - component: , - }); - } - steps.push({ - id: STEPS.PREVIEW, - name: i18n._(t`Preview`), - component: ( - - ), - enableNext: Object.keys(formErrors).length === 0, - nextButtonText: i18n._(t`Launch`), - }); - + // TODO move into hook? const validate = values => { // return {}; return { limit: ['required field'] }; }; + // TODO move into hook? const submit = values => { const postValues = {}; const setValue = (key, value) => { @@ -187,7 +55,6 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { setValue('extra_vars', mergeExtraVars(values.extra_vars, values.survey)); onLaunch(postValues); }; - console.log('formErrors:', formErrors); return ( @@ -197,22 +64,19 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { onClose={onCancel} onSave={handleSubmit} onNext={async (nextStep, prevStep) => { - // console.log(`${prevStep.prevName} -> ${nextStep.name}`); - // console.log('errors', errors); - // console.log('values', values); + console.log(prevStep); + visitStep(prevStep.id); const newErrors = await validateForm(); - setFormErrors(newErrors); - // console.log('new errors:', newErrors); + // updatePromptErrors(prevStep.prevName, newErrors); }} onGoToStep={async (newStep, prevStep) => { - // console.log('errors', errors); - // console.log('values', values); + console.log(prevStep); + visitStep(prevStep.id); const newErrors = await validateForm(); - setFormErrors(newErrors); + // updatePromptErrors(prevStep.prevName, newErrors); }} title={i18n._(t`Prompts`)} steps={steps} - // footer={} /> )} diff --git a/awx/ui_next/src/components/LaunchPrompt/hooks.js b/awx/ui_next/src/components/LaunchPrompt/hooks.js new file mode 100644 index 0000000000..5248c588bc --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/hooks.js @@ -0,0 +1,70 @@ +import { useState } from 'react'; +import useInventoryStep from './steps/useInventoryStep'; +import useCredentialsStep from './steps/useCredentialsStep'; +import useOtherPromptsStep from './steps/useOtherPromptsStep'; +import useSurveyStep from './steps/useSurveyStep'; +import usePreviewStep from './steps/usePreviewStep'; + +// const INVENTORY = 'inventory'; +// const CREDENTIALS = 'credentials'; +// const PASSWORDS = 'passwords'; +// const OTHER_PROMPTS = 'other'; +// const SURVEY = 'survey'; +// const PREVIEW = 'preview'; + +export function useSteps(config, resource, i18n) { + // TODO pass in form errors? + const formErrors = {}; + const inventory = useInventoryStep(config, resource, i18n); + const credentials = useCredentialsStep(config, resource, i18n); + const otherPrompts = useOtherPromptsStep(config, resource, i18n); + const survey = useSurveyStep(config, resource, i18n); + const preview = usePreviewStep( + config, + resource, + survey.survey, + 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; + + return { steps, initialValues, isReady, contentError }; +} + +export function usePromptErrors(config) { + const [promptErrors, setPromptErrors] = useState({}); + const updatePromptErrors = () => {}; + return [promptErrors, updatePromptErrors]; +} + +// TODO this interrelates with usePromptErrors +// merge? or pass result from one into the other? +export function useVisitedSteps(config) { + return [[], () => {}]; +} diff --git a/awx/ui_next/src/components/LaunchPrompt/CredentialsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/CredentialsStep.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/CredentialsStep.test.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/CredentialsStep.test.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/InventoryStep.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/InventoryStep.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/InventoryStep.test.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/InventoryStep.test.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/OtherPromptsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/OtherPromptsStep.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/OtherPromptsStep.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/OtherPromptsStep.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/OtherPromptsStep.test.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/OtherPromptsStep.test.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/OtherPromptsStep.test.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/OtherPromptsStep.test.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/PreviewStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/PreviewStep.jsx similarity index 92% rename from awx/ui_next/src/components/LaunchPrompt/PreviewStep.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/PreviewStep.jsx index 26d0572457..95e73509fb 100644 --- a/awx/ui_next/src/components/LaunchPrompt/PreviewStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/PreviewStep.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { useFormikContext } from 'formik'; import yaml from 'js-yaml'; import PromptDetail from '@components/PromptDetail'; -import mergeExtraVars, { maskPasswords } from './mergeExtraVars'; +import mergeExtraVars, { maskPasswords } from '../mergeExtraVars'; function PreviewStep({ resource, config, survey, formErrors }) { const { values } = useFormikContext(); diff --git a/awx/ui_next/src/components/LaunchPrompt/SurveyStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/SurveyStep.jsx similarity index 100% rename from awx/ui_next/src/components/LaunchPrompt/SurveyStep.jsx rename to awx/ui_next/src/components/LaunchPrompt/steps/SurveyStep.jsx diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx new file mode 100644 index 0000000000..9fb9d88ecd --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useCredentialsStep.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import CredentialsStep from './CredentialsStep'; + +const STEP_ID = 'credentials'; + +export default function useCredentialsStep(config, resource, i18n) { + return { + step: getStep(config, i18n), + initialValues: getInitialValues(config, resource), + isReady: true, + error: null, + }; +} + +function getStep(config, i18n) { + if (!config.ask_credential_on_launch) { + return null; + } + return { + id: STEP_ID, + name: i18n._(t`Credentials`), + component: , + }; +} + +function getInitialValues(config, resource) { + if (!config.ask_credential_on_launch) { + return {}; + } + return { + credentials: resource?.summary_fields?.credentials || [], + }; +} diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx new file mode 100644 index 0000000000..7aaed7d8e3 --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useInventoryStep.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import InventoryStep from './InventoryStep'; + +const STEP_ID = 'inventory'; + +export default function useInventoryStep(config, resource, i18n) { + return { + step: getStep(config, i18n), + initialValues: getInitialValues(config, resource), + isReady: true, + error: null, + }; +} + +function getStep(config, i18n) { + if (!config.ask_inventory_on_launch) { + return null; + } + return { + id: STEP_ID, + name: i18n._(t`Inventory`), + component: , + }; +} + +function getInitialValues(config, resource) { + if (!config.ask_inventory_on_launch) { + return {}; + } + return { + inventory: resource?.summary_fields?.inventory || null, + }; +} diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx new file mode 100644 index 0000000000..7b5f5d2cce --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useOtherPromptsStep.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import OtherPromptsStep from './OtherPromptsStep'; + +const STEP_ID = 'other'; + +export default function useOtherPrompt(config, resource, i18n) { + return { + step: getStep(config, i18n), + initialValues: getInitialValues(config, resource), + isReady: true, + error: null, + }; +} + +function getStep(config, i18n) { + if (!shouldShowPrompt(config)) { + return null; + } + return { + id: STEP_ID, + name: i18n._(t`Other Prompts`), + component: , + }; +} + +function shouldShowPrompt(config) { + return ( + config.ask_job_type_on_launch || + config.ask_limit_on_launch || + config.ask_verbosity_on_launch || + config.ask_tags_on_launch || + config.ask_skip_tags_on_launch || + config.ask_variables_on_launch || + config.ask_scm_branch_on_launch || + config.ask_diff_mode_on_launch + ); +} + +function getInitialValues(config, resource) { + const initialValues = {}; + if (config.ask_job_type_on_launch) { + initialValues.job_type = resource.job_type || ''; + } + if (config.ask_limit_on_launch) { + initialValues.limit = resource.limit || ''; + } + if (config.ask_verbosity_on_launch) { + initialValues.verbosity = resource.verbosity || 0; + } + if (config.ask_tags_on_launch) { + initialValues.job_tags = resource.job_tags || ''; + } + if (config.ask_skip_tags_on_launch) { + initialValues.skip_tags = resource.skip_tags || ''; + } + if (config.ask_variables_on_launch) { + initialValues.extra_vars = resource.extra_vars || '---'; + } + if (config.ask_scm_branch_on_launch) { + initialValues.scm_branch = resource.scm_branch || ''; + } + if (config.ask_diff_mode_on_launch) { + initialValues.diff_mode = resource.diff_mode || false; + } + return initialValues; +} diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx new file mode 100644 index 0000000000..ec34d8e7d5 --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/steps/usePreviewStep.jsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import PreviewStep from './PreviewStep'; + +const STEP_ID = 'preview'; + +export default function usePreviewStep( + config, + resource, + survey, + formErrors, + i18n +) { + return { + step: { + id: STEP_ID, + name: i18n._(t`Preview`), + component: ( + + ), + enableNext: Object.keys(formErrors).length === 0, + nextButtonText: i18n._(t`Launch`), + }, + initialValues: {}, + isReady: true, + error: null, + }; +} diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx new file mode 100644 index 0000000000..5383e629ba --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/steps/useSurveyStep.jsx @@ -0,0 +1,60 @@ +import React, { useEffect, useCallback } from 'react'; +import { t } from '@lingui/macro'; +import useRequest from '@util/useRequest'; +import { JobTemplatesAPI, WorkflowJobTemplatesAPI } from '@api'; +import SurveyStep from './SurveyStep'; + +const STEP_ID = 'survey'; + +export default function useSurveyStep(config, resource, i18n) { + const { result: survey, request: fetchSurvey, isLoading, error } = useRequest( + useCallback(async () => { + if (!config.survey_enabled) { + return {}; + } + const { data } = + resource.type === 'workflow_job_template' + ? await WorkflowJobTemplatesAPI.readSurvey(resource.id) + : await JobTemplatesAPI.readSurvey(resource.id); + return data; + }, [config.survey_enabled, resource]) + ); + + useEffect(() => { + fetchSurvey(); + }, [fetchSurvey]); + + return { + step: getStep(config, survey, i18n), + initialValues: getInitialValues(config, survey), + survey, + isReady: !isLoading && !!survey, + error, + }; +} + +function getStep(config, survey, i18n) { + if (!config.survey_enabled) { + return null; + } + return { + id: STEP_ID, + name: i18n._(t`Survey`), + component: , + }; +} + +function getInitialValues(config, survey) { + if (!config.survey_enabled || !survey) { + return {}; + } + const values = {}; + survey.spec.forEach(question => { + if (question.type === 'multiselect') { + values[`survey_${question.variable}`] = question.default.split('\n'); + } else { + values[`survey_${question.variable}`] = question.default; + } + }); + return values; +}