diff --git a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx
index 507af78334..84d9c7c882 100644
--- a/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx
+++ b/awx/ui_next/src/screens/Credential/CredentialEdit/CredentialEdit.jsx
@@ -158,7 +158,7 @@ function CredentialEdit({ credential }) {
}, {});
return { credentialTypes: creds, loadedInputSources: inputSources };
}, [credId, me.id]),
- { credentialTypes: {}, loadedInputSources: {} }
+ {}
);
useEffect(() => {
@@ -178,7 +178,7 @@ function CredentialEdit({ credential }) {
return ;
}
- if (isLoading) {
+ if (isLoading || !credentialTypes) {
return ;
}
diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
index abe76c9644..9d69aa7d13 100644
--- a/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
+++ b/awx/ui_next/src/screens/Credential/shared/CredentialForm.jsx
@@ -1,4 +1,5 @@
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
+import { useLocation } from 'react-router-dom';
import { shape } from 'prop-types';
import { Formik, useField, useFormikContext } from 'formik';
import { withI18n } from '@lingui/react';
@@ -11,6 +12,7 @@ import {
Select as PFSelect,
SelectOption as PFSelectOption,
SelectVariant,
+ Tooltip,
} from '@patternfly/react-core';
import styled from 'styled-components';
import FormField, { FormSubmitError } from '../../../components/FormField';
@@ -27,6 +29,7 @@ const Select = styled(PFSelect)`
ul {
max-width: 495px;
}
+ ${props => (props.isDisabled ? `cursor: not-allowed` : null)}
`;
const SelectOption = styled(PFSelectOption)`
@@ -35,7 +38,8 @@ const SelectOption = styled(PFSelectOption)`
overflow: hidden;
`;
-function CredentialFormFields({ i18n, credentialTypes }) {
+function CredentialFormFields({ i18n, initialTypeId, credentialTypes }) {
+ const { pathname } = useLocation();
const { setFieldValue, initialValues, setFieldTouched } = useFormikContext();
const [isSelectOpen, setIsSelectOpen] = useState(false);
const [credTypeField, credTypeMeta, credTypeHelpers] = useField({
@@ -43,9 +47,10 @@ function CredentialFormFields({ i18n, credentialTypes }) {
validate: required(i18n._(t`Select a value for this field`), i18n),
});
+ const [credentialTypeId, setCredentialTypeId] = useState(initialTypeId);
+
const isGalaxyCredential =
- !!credTypeField.value &&
- credentialTypes[credTypeField.value]?.kind === 'galaxy';
+ !!credentialTypeId && credentialTypes[credentialTypeId]?.kind === 'galaxy';
const [orgField, orgMeta, orgHelpers] = useField({
name: 'organization',
@@ -67,42 +72,58 @@ function CredentialFormFields({ i18n, credentialTypes }) {
})
.sort((a, b) => (a.label.toLowerCase() > b.label.toLowerCase() ? 1 : -1));
- const resetSubFormFields = newCredentialType => {
- const fields = credentialTypes[newCredentialType].inputs.fields || [];
- fields.forEach(
- ({ ask_at_runtime, type, id, choices, default: defaultValue }) => {
- if (parseInt(newCredentialType, 10) === initialValues.credential_type) {
- setFieldValue(`inputs.${id}`, initialValues.inputs[id]);
- if (ask_at_runtime) {
- setFieldValue(
- `passwordPrompts.${id}`,
- initialValues.passwordPrompts[id]
- );
- }
- } else {
- switch (type) {
- case 'string':
- setFieldValue(`inputs.${id}`, defaultValue || '');
- break;
- case 'boolean':
- setFieldValue(`inputs.${id}`, defaultValue || false);
- break;
- default:
- break;
- }
+ const resetSubFormFields = useCallback(
+ newCredentialTypeId => {
+ const fields = credentialTypes[newCredentialTypeId].inputs.fields || [];
+ fields.forEach(
+ ({ ask_at_runtime, type, id, choices, default: defaultValue }) => {
+ if (parseInt(newCredentialTypeId, 10) === initialTypeId) {
+ setFieldValue(`inputs.${id}`, initialValues.inputs[id]);
+ if (ask_at_runtime) {
+ setFieldValue(
+ `passwordPrompts.${id}`,
+ initialValues.passwordPrompts[id]
+ );
+ }
+ } else {
+ switch (type) {
+ case 'string':
+ setFieldValue(`inputs.${id}`, defaultValue || '');
+ break;
+ case 'boolean':
+ setFieldValue(`inputs.${id}`, defaultValue || false);
+ break;
+ default:
+ break;
+ }
- if (choices) {
- setFieldValue(`inputs.${id}`, defaultValue);
- }
+ if (choices) {
+ setFieldValue(`inputs.${id}`, defaultValue);
+ }
- if (ask_at_runtime) {
- setFieldValue(`passwordPrompts.${id}`, false);
+ if (ask_at_runtime) {
+ setFieldValue(`passwordPrompts.${id}`, false);
+ }
}
+ setFieldTouched(`inputs.${id}`, false);
}
- setFieldTouched(`inputs.${id}`, false);
- }
- );
- };
+ );
+ },
+ [
+ credentialTypes,
+ initialTypeId,
+ initialValues.inputs,
+ initialValues.passwordPrompts,
+ setFieldTouched,
+ setFieldValue,
+ ]
+ );
+
+ useEffect(() => {
+ if (credentialTypeId) {
+ resetSubFormFields(credentialTypeId);
+ }
+ }, [resetSubFormFields, credentialTypeId]);
const onOrganizationChange = useCallback(
value => {
@@ -111,6 +132,38 @@ function CredentialFormFields({ i18n, credentialTypes }) {
[setFieldValue]
);
+ const isCredentialTypeDisabled = pathname.includes('edit');
+ const credentialTypeSelect = (
+
+ );
+
return (
<>
-
+ {isCredentialTypeDisabled ? (
+
+ {credentialTypeSelect}
+
+ ) : (
+ credentialTypeSelect
+ )}
- {credTypeField.value !== undefined &&
- credTypeField.value !== '' &&
- credentialTypes[credTypeField.value]?.inputs?.fields && (
+ {credentialTypeId !== undefined &&
+ credentialTypeId !== '' &&
+ credentialTypes[credentialTypeId]?.inputs?.fields && (
)}
>
@@ -197,12 +235,14 @@ function CredentialForm({
isOrgLookupDisabled,
...rest
}) {
+ const initialTypeId = credential?.credential_type;
+
const [showExternalTestModal, setShowExternalTestModal] = useState(false);
const initialValues = {
name: credential.name || '',
description: credential.description || '',
organization: credential?.summary_fields?.organization || null,
- credential_type: credential?.credential_type || '',
+ credential_type: credentialTypes[initialTypeId]?.name || '',
inputs: credential?.inputs || {},
passwordPrompts: {},
isOrgLookupDisabled: isOrgLookupDisabled || false,
@@ -253,7 +293,14 @@ function CredentialForm({
{
- onSubmit(values);
+ const { credential_type, ...actualValues } = values;
+ // credential_type could be the raw id or the displayed name value.
+ // If it's the name, replace it with the id before making the request.
+ actualValues.credential_type =
+ Object.keys(credentialTypes).find(
+ key => credentialTypes[key].name === credential_type
+ ) || credential_type;
+ onSubmit(actualValues);
}}
>
{formik => (
@@ -261,6 +308,7 @@ function CredentialForm({