From e90ee5113d3f4ac2ffccb3cfa743532f231a8e33 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Sat, 22 Feb 2020 17:20:23 -0500 Subject: [PATCH] Adds subform restore functionality and addresses PR issues --- .../src/api/mixins/InstanceGroups.mixin.js | 7 +- .../screens/Template/WorkflowJobTemplate.jsx | 4 +- .../shared/WorkflowJobTemplateForm.jsx | 303 ++++++++++-------- .../shared/WorkflowJobTemplateForm.test.jsx | 44 ++- 4 files changed, 184 insertions(+), 174 deletions(-) diff --git a/awx/ui_next/src/api/mixins/InstanceGroups.mixin.js b/awx/ui_next/src/api/mixins/InstanceGroups.mixin.js index e3b2be1cb5..e6745ac522 100644 --- a/awx/ui_next/src/api/mixins/InstanceGroups.mixin.js +++ b/awx/ui_next/src/api/mixins/InstanceGroups.mixin.js @@ -1,10 +1,9 @@ const InstanceGroupsMixin = parent => class extends parent { readInstanceGroups(resourceId, params) { - return this.http.get( - `${this.baseUrl}${resourceId}/instance_groups/`, - params - ); + return this.http.get(`${this.baseUrl}${resourceId}/instance_groups/`, { + params, + }); } associateInstanceGroup(resourceId, instanceGroupId) { diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplate.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplate.jsx index 1586551455..35e0336d36 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplate.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplate.jsx @@ -25,6 +25,7 @@ class WorkflowJobTemplate extends Component { contentError: null, hasContentLoading: true, template: null, + webhook_key: null, }; this.loadTemplate = this.loadTemplate.bind(this); this.loadSchedules = this.loadSchedules.bind(this); @@ -66,7 +67,6 @@ class WorkflowJobTemplate extends Component { ); data.summary_fields.webhook_credential.kind = name; } - setBreadcrumb(data); this.setState({ template: data }); setBreadcrumb(data); } catch (err) { @@ -141,7 +141,7 @@ class WorkflowJobTemplate extends Component { return ( - + {cardHeader} label { - grid-column: 1 / -1; - } - - && { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - } -`; +import CheckboxField from '../../../components/FormField/CheckboxField'; function WorkflowJobTemplateForm({ handleSubmit, @@ -53,25 +47,17 @@ function WorkflowJobTemplateForm({ submitError, }) { const { id } = useParams(); + const wfjtAddMatch = useRouteMatch('/templates/workflow_job_template/add'); + const urlOrigin = window.location.origin; + const [contentError, setContentError] = useState(null); - const [inventory, setInventory] = useState( - template?.summary_fields?.inventory || null - ); - const [organization, setOrganization] = useState( - template?.summary_fields?.organization || null - ); - const [webHookKey, setWebHookKey] = useState(webhook_key); + const [webhookKey, setWebHookKey] = useState(webhook_key); const [credTypeId, setCredentialTypeId] = useState(); const [webhookService, setWebHookService] = useState( template.webhook_service || '' ); - const [hasWebhooks, setHasWebhooks] = useState( - webhookService !== '' || false - ); - const [webhookCredential, setWebHookCredential] = useState( - template?.summary_fields?.webhook_credential || null - ); + const [hasWebhooks, setHasWebhooks] = useState(Boolean(webhookService)); const webhookServiceOptions = [ { @@ -83,14 +69,12 @@ function WorkflowJobTemplateForm({ { value: 'github', key: 'github', - namespace: 'git_hub', label: i18n._(t`GitHub`), isDisabled: false, }, { value: 'gitlab', key: 'gitlab', - namespace: 'git_lab', label: i18n._(t`Git Lab`), isDisabled: false, }, @@ -105,9 +89,7 @@ function WorkflowJobTemplateForm({ const { data: { results }, } = await CredentialTypesAPI.read({ - namespace: webhookService.includes('hub') - ? 'github_token' - : 'gitlab_token', + namespace: `${webhookService}_token`, }); setCredentialTypeId(results[0].id); } catch (err) { @@ -128,20 +110,67 @@ function WorkflowJobTemplateForm({ } }; + let initialWebhookKey = webhook_key; + + const setWebhookValues = (form, webhookServiceValue) => { + if ( + webhookServiceValue === form.initialValues.webhook_service || + webhookServiceValue === '' + ) { + form.setFieldValue( + 'webhook_credential', + form.initialValues.webhook_credential + ); + form.setFieldValue('webhook_url', form.initialValues.webhook_url); + form.setFieldValue('webhook_service', form.initialValues.webhook_service); + + setWebHookKey(initialWebhookKey); + } else { + form.setFieldValue('webhook_credential', null); + form.setFieldValue( + 'webhook_url', + `${urlOrigin}/api/v2/workflow_job_templates/${template.id}/${webhookServiceValue}/` + ); + + setWebHookKey('A NEW WEBHOOK KEY WILL BE GENERATED ON SAVE'); + } + }; + + const handleWebhookEnablement = ( + form, + enabledWebhooks, + webhookServiceValue + ) => { + if (!enabledWebhooks) { + initialWebhookKey = webhookKey; + form.setFieldValue('webhook_credential', null); + form.setFieldValue('webhook_service', ''); + form.setFieldValue('webhook_url', ''); + setWebHookService(''); + setWebHookKey(''); + } else { + setWebhookValues(form, webhookServiceValue); + } + }; + if (contentError) { return ; } - return ( { + values.webhook_credential = values?.webhook_credential?.id; + values.organization = values?.organization?.id; + values.inventory = values?.inventory?.id; + return handleSubmit(values); + }} initialValues={{ name: template.name || '', description: template.description || '', - inventory: template.summary_fields?.inventory?.id || '', - organization: template.summary_fields?.organization?.id || '', + inventory: template?.summary_fields?.inventory || null, + organization: template?.summary_fields?.organization || null, labels: template.summary_fields?.labels?.results || [], - variables: template.variables || '---', + extra_vars: template.variables || '---', limit: template.limit || '', scmBranch: template.scm_branch || '', allow_simultaneous: template.allow_simultaneous || false, @@ -149,8 +178,8 @@ function WorkflowJobTemplateForm({ template?.related?.webhook_receiver && `${urlOrigin}${template?.related?.webhook_receiver}`, webhook_credential: - template?.summary_fields?.webhook_credential?.id || null, - webhook_service: webhookService, + template?.summary_fields?.webhook_credential || null, + webhook_service: template.webhook_service || '', ask_limit_on_launch: template.ask_limit_on_launch || false, ask_inventory_on_launch: template.ask_inventory_on_launch || false, ask_variables_on_launch: template.ask_variables_on_launch || false, @@ -159,7 +188,7 @@ function WorkflowJobTemplateForm({ > {formik => (
- + - {({ form }) => ( + {({ form, field }) => ( form.setFieldTouched('organization')} onChange={value => { - form.setFieldValue('organization', value?.id || null); - setOrganization(value); + form.setFieldValue('organization', value); }} - value={organization} + value={field.value} touched={form.touched.organization} error={form.errors.organization} /> )} - - - {({ form }) => ( + {({ form, field }) => ( { - form.setFieldValue('inventory', value?.id || null); - form.setFieldValue( - 'organizationId', - value?.organization || null - ); - setInventory(value); + form.setFieldValue('inventory', value); + form.setFieldValue('organizationId', value.organization); }} error={form.errors.inventory} /> @@ -249,9 +271,8 @@ function WorkflowJobTemplateForm({ name="scmBranch" /> - - - + + {({ form, field }) => ( )} - - + + - - + - - {i18n._(t`Webhooks`)}   - - - } - isChecked={hasWebhooks} - onChange={checked => { - setHasWebhooks(checked); - }} - /> - - {({ field, form }) => ( + name="hasWebhooks" + label={i18n._(t`Webhooks`)} + > + {({ form }) => ( - {i18n._(t`Enable Concurrent Jobs`)}   + {i18n._(t`Webhooks`)} +   } - isChecked={field.value} - onChange={value => { - form.setFieldValue('allow_simultaneous', value); + id="wfjt-enabled-webhooks" + isChecked={ + Boolean(form.values.webhook_service) || hasWebhooks + } + onChange={checked => { + setHasWebhooks(checked); + handleWebhookEnablement(form, checked, webhookService); }} /> )} - + + + {hasWebhooks && ( - <> - - {template.related && ( + + + {({ form, field }) => ( + + + { + setWebHookService(val); + setWebhookValues(form, val); + + form.setFieldValue('webhook_service', val); + }} + /> + + )} + + {!wfjtAddMatch && ( + <> - )} - {template.related && ( - )} - - {({ form }) => ( + + )} + {credTypeId && ( + + {({ form, field }) => ( - - { - setWebHookService(val); - setWebHookCredential(null); - form.setFieldValue('webhook_service', val); - form.setFieldValue('webhook_credential', null); + { + form.setFieldValue('webhook_credential', value); }} + value={field.value} /> )} - - {credTypeId && ( - - - {({ form }) => ( - - { - setWebHookCredential(value); - form.setFieldValue('webhook_credential', value.id); - }} - value={webhookCredential} - /> - - )} - - )} - + )} ', () => { }); test('all the fields render successfully', () => { const fields = [ - 'name', - 'description', - 'organization', - 'inventory', - 'limit', - 'scmBranch', - 'labels', - 'variables', + 'FormField[name="name"]', + 'FormField[name="description"]', + 'Field[name="organization"]', + 'Field[name="inventory"]', + 'FormField[name="limit"]', + 'FormField[name="scmBranch"]', + 'Field[name="labels"]', + 'VariablesField', ]; - const assertField = (field, index) => { - expect( - wrapper - .find('Field') - .at(index) - .prop('name') - ).toBe(`${field}`); + const assertField = field => { + expect(wrapper.find(`${field}`).length).toBe(1); }; fields.map((field, index) => assertField(field, index)); }); @@ -162,12 +157,15 @@ describe('', () => { test('webhooks and enable concurrent jobs functions properly', async () => { act(() => { - wrapper.find('Checkbox[name="has_webhooks"]').invoke('onChange')(true); - wrapper.find('Checkbox[name="allow_simultaneous"]').invoke('onChange')( - true - ); + wrapper.find('Checkbox[aria-label="Webhooks"]').invoke('onChange')(true, { + currentTarget: { value: true, type: 'change', checked: true }, + }); }); wrapper.update(); + expect( + wrapper.find('Checkbox[aria-label="Webhooks"]').prop('isChecked') + ).toBe(true); + expect( wrapper.find('input[aria-label="wfjt-webhook-key"]').prop('readOnly') ).toBe(true); @@ -188,12 +186,6 @@ describe('', () => { wrapper.update(); - expect( - wrapper.find('Checkbox[name="has_webhooks"]').prop('isChecked') - ).toBe(true); - expect( - wrapper.find('Checkbox[name="allow_simultaneous"]').prop('isChecked') - ).toBe(true); expect(wrapper.find('Field[name="webhook_service"]').length).toBe(1); act(() => wrapper.find('AnsibleSelect').prop('onChange')({}, 'gitlab')); @@ -203,7 +195,7 @@ describe('', () => { }); test('handleSubmit is called on submit button click', async () => { act(() => { - wrapper.find('Formik').prop('onSubmit')(); + wrapper.find('Formik').prop('onSubmit')({}); }); wrapper.update(); sleep(0);