diff --git a/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.js b/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.js
index f2ed08cbe8..b3e0f78900 100644
--- a/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.js
+++ b/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.js
@@ -9,7 +9,7 @@ function ProjectEdit({ project }) {
const [formSubmitError, setFormSubmitError] = useState(null);
const history = useHistory();
- const handleSubmit = async (values) => {
+ const handleSubmit = async ({ ...values }) => {
if (values.scm_type === 'manual') {
values.scm_type = '';
}
diff --git a/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.test.js b/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.test.js
index 4b7193dc12..26d4b58c92 100644
--- a/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.test.js
+++ b/awx/ui/src/screens/Project/ProjectEdit/ProjectEdit.test.js
@@ -31,6 +31,7 @@ describe('', () => {
summary_fields: {
credential: {
id: 100,
+ name: 'insights',
credential_type_id: 5,
kind: 'insights',
},
diff --git a/awx/ui/src/screens/Project/shared/ProjectForm.js b/awx/ui/src/screens/Project/shared/ProjectForm.js
index 88d8732eab..d231d87cf7 100644
--- a/awx/ui/src/screens/Project/shared/ProjectForm.js
+++ b/awx/ui/src/screens/Project/shared/ProjectForm.js
@@ -1,7 +1,6 @@
/* eslint no-nested-ternary: 0 */
import React, { useCallback, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
-
import { t } from '@lingui/macro';
import { Formik, useField, useFormikContext } from 'formik';
import { Form, FormGroup, Title } from '@patternfly/react-core';
@@ -17,6 +16,7 @@ import ExecutionEnvironmentLookup from 'components/Lookup/ExecutionEnvironmentLo
import { CredentialTypesAPI, ProjectsAPI } from 'api';
import { required } from 'util/validators';
import { FormColumnLayout, SubFormLayout } from 'components/FormLayout';
+import useRequest from 'hooks/useRequest';
import getProjectHelpText from './Project.helptext';
import {
GitSubForm,
@@ -26,67 +26,12 @@ import {
ManualSubForm,
} from './ProjectSubForms';
-const fetchCredentials = async (credential) => {
- const [
- {
- data: {
- results: [scmCredentialType],
- },
- },
- {
- data: {
- results: [insightsCredentialType],
- },
- },
- {
- data: {
- results: [cryptographyCredentialType],
- },
- },
- ] = await Promise.all([
- CredentialTypesAPI.read({ kind: 'scm' }),
- CredentialTypesAPI.read({ name: 'Insights' }),
- CredentialTypesAPI.read({ kind: 'cryptography' }),
- ]);
-
- if (!credential) {
- return {
- scm: { typeId: scmCredentialType.id },
- insights: { typeId: insightsCredentialType.id },
- cryptography: { typeId: cryptographyCredentialType.id },
- };
- }
-
- const { credential_type_id } = credential;
- return {
- scm: {
- typeId: scmCredentialType.id,
- value: credential_type_id === scmCredentialType.id ? credential : null,
- },
- insights: {
- typeId: insightsCredentialType.id,
- value:
- credential_type_id === insightsCredentialType.id ? credential : null,
- },
- cryptography: {
- typeId: cryptographyCredentialType.id,
- value:
- credential_type_id === cryptographyCredentialType.id
- ? credential
- : null,
- },
- };
-};
-
function ProjectFormFields({
project,
project_base_dir,
project_local_paths,
- formik,
- setCredentials,
- setSignatureValidationCredentials,
- credentials,
- signatureValidationCredentials,
+ credentialTypeIds,
+
scmTypeOptions,
setScmSubFormState,
scmSubFormState,
@@ -96,8 +41,7 @@ function ProjectFormFields({
scm_url: '',
scm_branch: '',
scm_refspec: '',
- credential: '',
- signature_validation_credential: '',
+ credential: null,
scm_clean: false,
scm_delete_on_update: false,
scm_track_submodules: false,
@@ -105,7 +49,8 @@ function ProjectFormFields({
allow_override: false,
scm_update_cache_timeout: 0,
};
- const { setFieldValue, setFieldTouched } = useFormikContext();
+ const { setFieldValue, setFieldTouched, values, initialValues } =
+ useFormikContext();
const [scmTypeField, scmTypeMeta, scmTypeHelpers] = useField({
name: 'scm_type',
@@ -121,11 +66,11 @@ function ProjectFormFields({
] = useField('default_environment');
/* Save current scm subform field values to state */
- const saveSubFormState = (form) => {
+ const saveSubFormState = () => {
const currentScmFormFields = { ...scmFormFields };
Object.keys(currentScmFormFields).forEach((label) => {
- currentScmFormFields[label] = form.values[label];
+ currentScmFormFields[label] = values[label];
});
setScmSubFormState(currentScmFormFields);
@@ -137,58 +82,27 @@ function ProjectFormFields({
* If scm type is === the initial scm type value,
* reset scm subform field values to scmSubFormState.
*/
- const resetScmTypeFields = (value, form) => {
- if (form.values.scm_type === form.initialValues.scm_type) {
- saveSubFormState(formik);
+ const resetScmTypeFields = (value) => {
+ if (values.scm_type === initialValues.scm_type) {
+ saveSubFormState();
}
Object.keys(scmFormFields).forEach((label) => {
- if (value === form.initialValues.scm_type) {
- form.setFieldValue(label, scmSubFormState[label]);
+ if (value === initialValues.scm_type) {
+ setFieldValue(label, scmSubFormState[label]);
} else {
- form.setFieldValue(label, scmFormFields[label]);
+ setFieldValue(label, scmFormFields[label]);
}
- form.setFieldTouched(label, false);
+ setFieldTouched(label, false);
});
};
- const handleCredentialSelection = useCallback(
- (type, value) => {
- setCredentials({
- ...credentials,
- [type]: {
- ...credentials[type],
- value,
- },
- });
- },
- [credentials, setCredentials]
- );
-
- const handleSignatureValidationCredentialSelection = useCallback(
- (type, value) => {
- setSignatureValidationCredentials({
- ...signatureValidationCredentials,
- [type]: {
- ...signatureValidationCredentials[type],
- value,
- },
- });
- },
- [signatureValidationCredentials, setSignatureValidationCredentials]
- );
-
const handleSignatureValidationCredentialChange = useCallback(
- (value) => {
- handleSignatureValidationCredentialSelection('cryptography', value);
- setFieldValue('signature_validation_credential', value);
+ (cred) => {
+ setFieldValue('signature_validation_credential', cred);
setFieldTouched('signature_validation_credential', true, false);
},
- [
- handleSignatureValidationCredentialSelection,
- setFieldValue,
- setFieldTouched,
- ]
+ [setFieldTouched, setFieldValue]
);
const handleOrganizationUpdate = useCallback(
@@ -281,18 +195,18 @@ function ProjectFormFields({
]}
onChange={(event, value) => {
scmTypeHelpers.setValue(value);
- resetScmTypeFields(value, formik);
+ resetScmTypeFields(value);
}}
/>
- {formik.values.scm_type !== '' && (
+ {values.scm_type !== '' && (
{t`Type Details`}
@@ -302,43 +216,39 @@ function ProjectFormFields({
{
manual: (
),
git: (
),
svn: (
),
archive: (
),
insights: (
),
- }[formik.values.scm_type]
+ }[values.scm_type]
}
@@ -348,16 +258,13 @@ function ProjectFormFields({
}
function ProjectForm({ project, submitError, ...props }) {
const { handleCancel, handleSubmit } = props;
- const { summary_fields = {} } = project;
+
const { project_base_dir, project_local_paths } = useConfig();
- const [contentError, setContentError] = useState(null);
- const [isLoading, setIsLoading] = useState(true);
const [scmSubFormState, setScmSubFormState] = useState({
scm_url: '',
scm_branch: '',
scm_refspec: '',
- credential: '',
- signature_validation_credential: '',
+ credential: null,
scm_clean: false,
scm_delete_on_update: false,
scm_track_submodules: false,
@@ -365,27 +272,16 @@ function ProjectForm({ project, submitError, ...props }) {
allow_override: false,
scm_update_cache_timeout: 0,
});
- const [scmTypeOptions, setScmTypeOptions] = useState(null);
- const [credentials, setCredentials] = useState({
- scm: { typeId: null, value: null },
- insights: { typeId: null, value: null },
- cryptography: { typeId: null, value: null },
- });
- const [signatureValidationCredentials, setSignatureValidationCredentials] =
- useState({
- scm: { typeId: null, value: null },
- insights: { typeId: null, value: null },
- cryptography: { typeId: null, value: null },
- });
- useEffect(() => {
- async function fetchData() {
- try {
- const credentialResponse = fetchCredentials(summary_fields.credential);
- const signatureValidationCredentialResponse = fetchCredentials(
- summary_fields.signature_validation_credential
- );
- const {
+ const {
+ result: { scmTypeOptions, credentialTypeIds },
+ error: contentError,
+ isLoading,
+ request: fetchData,
+ } = useRequest(
+ useCallback(async () => {
+ const [
+ {
data: {
actions: {
GET: {
@@ -393,25 +289,47 @@ function ProjectForm({ project, submitError, ...props }) {
},
},
},
- } = await ProjectsAPI.readOptions();
-
- setCredentials(await credentialResponse);
- setSignatureValidationCredentials(
- await signatureValidationCredentialResponse
- );
- setScmTypeOptions(choices);
- } catch (error) {
- setContentError(error);
- } finally {
- setIsLoading(false);
- }
+ },
+ {
+ data: {
+ results: [scmCredentialType],
+ },
+ },
+ {
+ data: {
+ results: [insightsCredentialType],
+ },
+ },
+ {
+ data: {
+ results: [cryptographyCredentialType],
+ },
+ },
+ ] = await Promise.all([
+ ProjectsAPI.readOptions(),
+ CredentialTypesAPI.read({ kind: 'scm' }),
+ CredentialTypesAPI.read({ name: 'Insights' }),
+ CredentialTypesAPI.read({ kind: 'cryptography' }),
+ ]);
+ return {
+ scmTypeOptions: choices,
+ credentialTypeIds: {
+ scm: scmCredentialType.id,
+ insights: insightsCredentialType.id,
+ cryptography: cryptographyCredentialType.id,
+ },
+ };
+ }, []),
+ {
+ scmTypeOptions: [],
+ credentialTypeIds: { scm: '', insights: '', cryptography: '' },
+ isLoading: true,
}
+ );
+ useEffect(() => {
fetchData();
- }, [
- summary_fields.credential,
- summary_fields.signature_validation_credential,
- ]);
+ }, [fetchData]);
if (isLoading) {
return ;
@@ -426,11 +344,11 @@ function ProjectForm({ project, submitError, ...props }) {
initialValues={{
allow_override: project.allow_override || false,
base_dir: project_base_dir || '',
- credential: project.credential || '',
+ credential: project?.summary_fields?.credential || null,
description: project.description || '',
local_path: project.local_path || '',
name: project.name || '',
- organization: project.summary_fields?.organization || null,
+ organization: project?.summary_fields?.organization || null,
scm_branch: project.scm_branch || '',
scm_clean: project.scm_clean || false,
scm_delete_on_update: project.scm_delete_on_update || false,
@@ -446,7 +364,7 @@ function ProjectForm({ project, submitError, ...props }) {
scm_update_on_launch: project.scm_update_on_launch || false,
scm_url: project.scm_url || '',
signature_validation_credential:
- project.signature_validation_credential || '',
+ project?.summary_fields?.signature_validation_credential || null,
default_environment:
project.summary_fields?.default_environment || null,
}}
@@ -459,13 +377,7 @@ function ProjectForm({ project, submitError, ...props }) {
project={project}
project_base_dir={project_base_dir}
project_local_paths={project_local_paths}
- formik={formik}
- setCredentials={setCredentials}
- setSignatureValidationCredentials={
- setSignatureValidationCredentials
- }
- credentials={credentials}
- signatureValidationCredentials={signatureValidationCredentials}
+ credentialTypeIds={credentialTypeIds}
scmTypeOptions={scmTypeOptions}
setScmSubFormState={setScmSubFormState}
scmSubFormState={scmSubFormState}
diff --git a/awx/ui/src/screens/Project/shared/ProjectForm.test.js b/awx/ui/src/screens/Project/shared/ProjectForm.test.js
index d75047be4f..16c31351ad 100644
--- a/awx/ui/src/screens/Project/shared/ProjectForm.test.js
+++ b/awx/ui/src/screens/Project/shared/ProjectForm.test.js
@@ -132,8 +132,7 @@ describe('', () => {
);
});
-
- expect(wrapper.find('ProjectForm').length).toBe(1);
+ waitForElement(wrapper, 'ProjectForm', (el) => el.length === 1);
});
test('new form displays primary form fields', async () => {
@@ -149,6 +148,10 @@ describe('', () => {
expect(wrapper.find('FormGroup[label="Source Control Type"]').length).toBe(
1
);
+ expect(
+ wrapper.find('FormGroup[label="Content Signature Validation Credential"]')
+ .length
+ ).toBe(1);
expect(wrapper.find('FormGroup[label="Ansible Environment"]').length).toBe(
0
);
@@ -163,7 +166,7 @@ describe('', () => {
});
await waitForElement(wrapper, 'ContentLoading', (el) => el.length === 0);
await act(async () => {
- await wrapper.find('AnsibleSelect[id="scm_type"]').invoke('onChange')(
+ wrapper.find('AnsibleSelect[id="scm_type"]').invoke('onChange')(
null,
'git'
);
@@ -178,17 +181,9 @@ describe('', () => {
expect(
wrapper.find('FormGroup[label="Source Control Refspec"]').length
).toBe(1);
- expect(
- wrapper.find('FormGroup[label="Content Signature Validation Credential"]')
- .length
- ).toBe(1);
expect(
wrapper.find('FormGroup[label="Source Control Credential"]').length
).toBe(1);
- expect(
- wrapper.find('FormGroup[label="Content Signature Validation Credential"]')
- .length
- ).toBe(1);
expect(wrapper.find('FormGroup[label="Options"]').length).toBe(1);
});
diff --git a/awx/ui/src/screens/Project/shared/ProjectSubForms/ArchiveSubForm.js b/awx/ui/src/screens/Project/shared/ProjectSubForms/ArchiveSubForm.js
index 4bc35817d2..50c72aaab1 100644
--- a/awx/ui/src/screens/Project/shared/ProjectSubForms/ArchiveSubForm.js
+++ b/awx/ui/src/screens/Project/shared/ProjectSubForms/ArchiveSubForm.js
@@ -8,19 +8,12 @@ import {
ScmTypeOptions,
} from './SharedFields';
-const ArchiveSubForm = ({
- credential,
- onCredentialSelection,
- scmUpdateOnLaunch,
-}) => {
+const ArchiveSubForm = ({ credentialTypeId, scmUpdateOnLaunch }) => {
const projectHelpText = getProjectHelpText();
return (
<>
-
+
>
);
diff --git a/awx/ui/src/screens/Project/shared/ProjectSubForms/GitSubForm.js b/awx/ui/src/screens/Project/shared/ProjectSubForms/GitSubForm.js
index 7a41b08090..a0467804a5 100644
--- a/awx/ui/src/screens/Project/shared/ProjectSubForms/GitSubForm.js
+++ b/awx/ui/src/screens/Project/shared/ProjectSubForms/GitSubForm.js
@@ -13,11 +13,7 @@ import {
} from './SharedFields';
import getProjectHelpStrings from '../Project.helptext';
-const GitSubForm = ({
- credential,
- onCredentialSelection,
- scmUpdateOnLaunch,
-}) => {
+const GitSubForm = ({ credentialTypeId, scmUpdateOnLaunch }) => {
const docsURL = `${getDocsBaseUrl(
useConfig()
)}/html/userguide/projects.html#manage-playbooks-using-source-control`;
@@ -35,10 +31,7 @@ const GitSubForm = ({
tooltipMaxWidth="400px"
tooltip={projectHelpStrings.sourceControlRefspec(docsURL)}
/>
-
+
>
);
diff --git a/awx/ui/src/screens/Project/shared/ProjectSubForms/InsightsSubForm.js b/awx/ui/src/screens/Project/shared/ProjectSubForms/InsightsSubForm.js
index aab479d331..3020883ac5 100644
--- a/awx/ui/src/screens/Project/shared/ProjectSubForms/InsightsSubForm.js
+++ b/awx/ui/src/screens/Project/shared/ProjectSubForms/InsightsSubForm.js
@@ -1,39 +1,37 @@
import React, { useCallback } from 'react';
import { t } from '@lingui/macro';
-import { useField, useFormikContext } from 'formik';
+import { useFormikContext, useField } from 'formik';
import CredentialLookup from 'components/Lookup/CredentialLookup';
import { required } from 'util/validators';
import { ScmTypeOptions } from './SharedFields';
const InsightsSubForm = ({
- credential,
- onCredentialSelection,
+ credentialTypeId,
scmUpdateOnLaunch,
autoPopulateCredential,
}) => {
const { setFieldValue, setFieldTouched } = useFormikContext();
- const [, credMeta, credHelpers] = useField('credential');
+ const [credField, credMeta, credHelpers] = useField('credential');
const onCredentialChange = useCallback(
(value) => {
- onCredentialSelection('insights', value);
setFieldValue('credential', value);
setFieldTouched('credential', true, false);
},
- [onCredentialSelection, setFieldValue, setFieldTouched]
+ [setFieldValue, setFieldTouched]
);
return (
<>
credHelpers.setTouched()}
onChange={onCredentialChange}
- value={credential.value}
+ value={credField.value}
required
autoPopulate={autoPopulateCredential}
validate={required(t`Select a value for this field`)}
diff --git a/awx/ui/src/screens/Project/shared/ProjectSubForms/SharedFields.js b/awx/ui/src/screens/Project/shared/ProjectSubForms/SharedFields.js
index 1db0242bb8..908c36e7bd 100644
--- a/awx/ui/src/screens/Project/shared/ProjectSubForms/SharedFields.js
+++ b/awx/ui/src/screens/Project/shared/ProjectSubForms/SharedFields.js
@@ -35,27 +35,23 @@ export const BranchFormField = ({ label }) => {
);
};
-export const ScmCredentialFormField = ({
- credential,
- onCredentialSelection,
-}) => {
- const { setFieldValue, setFieldTouched } = useFormikContext();
+export const ScmCredentialFormField = ({ credentialTypeId }) => {
+ const { setFieldValue, setFieldTouched, values } = useFormikContext();
- const onCredentialChange = useCallback(
+ const handleChange = useCallback(
(value) => {
- onCredentialSelection('scm', value);
setFieldValue('credential', value);
setFieldTouched('credential', true, false);
},
- [onCredentialSelection, setFieldValue, setFieldTouched]
+ [setFieldValue, setFieldTouched]
);
return (
);
};
diff --git a/awx/ui/src/screens/Project/shared/ProjectSubForms/SvnSubForm.js b/awx/ui/src/screens/Project/shared/ProjectSubForms/SvnSubForm.js
index 9de7098a9d..299d12f8c9 100644
--- a/awx/ui/src/screens/Project/shared/ProjectSubForms/SvnSubForm.js
+++ b/awx/ui/src/screens/Project/shared/ProjectSubForms/SvnSubForm.js
@@ -10,20 +10,13 @@ import {
ScmTypeOptions,
} from './SharedFields';
-const SvnSubForm = ({
- credential,
- onCredentialSelection,
- scmUpdateOnLaunch,
-}) => {
+const SvnSubForm = ({ credentialTypeId, scmUpdateOnLaunch }) => {
const projectHelpStrings = getProjectHelpStrings();
return (
<>
-
+
>
);