mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 19:30:39 -03:30
Fixes erroneous disabling of name input field on container and instance group forms
This commit is contained in:
parent
326d12382f
commit
c40785b6eb
@ -30,13 +30,16 @@ function ContainerGroup({ setBreadcrumb }) {
|
||||
isLoading,
|
||||
error: contentError,
|
||||
request: fetchInstanceGroups,
|
||||
result: { instanceGroup, defaultExecution },
|
||||
result: { instanceGroup, defaultControlPlane, defaultExecution },
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const [
|
||||
{ data },
|
||||
{
|
||||
data: { DEFAULT_EXECUTION_QUEUE_NAME },
|
||||
data: {
|
||||
DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
},
|
||||
},
|
||||
] = await Promise.all([
|
||||
InstanceGroupsAPI.readDetail(id),
|
||||
@ -44,6 +47,7 @@ function ContainerGroup({ setBreadcrumb }) {
|
||||
]);
|
||||
return {
|
||||
instanceGroup: data,
|
||||
defaultControlPlane: DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
defaultExecution: DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
};
|
||||
}, [id]),
|
||||
@ -123,6 +127,7 @@ function ContainerGroup({ setBreadcrumb }) {
|
||||
<Route path="/instance_groups/container_group/:id/edit">
|
||||
<ContainerGroupEdit
|
||||
instanceGroup={instanceGroup}
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
@ -11,7 +11,7 @@ import { jsonToYaml, isJsonString } from 'util/yaml';
|
||||
|
||||
import ContainerGroupForm from '../shared/ContainerGroupForm';
|
||||
|
||||
function ContainerGroupAdd() {
|
||||
function ContainerGroupAdd({ defaultExecution, defaultControlPlane }) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
|
||||
@ -93,6 +93,8 @@ function ContainerGroupAdd() {
|
||||
<Card>
|
||||
<CardBody>
|
||||
<ContainerGroupForm
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
initialPodSpec={initialPodSpec}
|
||||
onSubmit={handleSubmit}
|
||||
submitError={submitError}
|
||||
|
||||
@ -9,7 +9,11 @@ import ContentError from 'components/ContentError';
|
||||
import ContentLoading from 'components/ContentLoading';
|
||||
import ContainerGroupForm from '../shared/ContainerGroupForm';
|
||||
|
||||
function ContainerGroupEdit({ instanceGroup }) {
|
||||
function ContainerGroupEdit({
|
||||
instanceGroup,
|
||||
defaultControlPlane,
|
||||
defaultExecution,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
const detailsIUrl = `/instance_groups/container_group/${instanceGroup.id}/details`;
|
||||
@ -77,6 +81,8 @@ function ContainerGroupEdit({ instanceGroup }) {
|
||||
return (
|
||||
<CardBody>
|
||||
<ContainerGroupForm
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
instanceGroup={instanceGroup}
|
||||
initialPodSpec={initialPodSpec}
|
||||
onSubmit={handleSubmit}
|
||||
|
||||
@ -6,7 +6,7 @@ import { CardBody } from 'components/Card';
|
||||
import { InstanceGroupsAPI } from 'api';
|
||||
import InstanceGroupForm from '../shared/InstanceGroupForm';
|
||||
|
||||
function InstanceGroupAdd() {
|
||||
function InstanceGroupAdd({ defaultExecution, defaultControlPlane }) {
|
||||
const history = useHistory();
|
||||
const [submitError, setSubmitError] = useState(null);
|
||||
|
||||
@ -28,6 +28,8 @@ function InstanceGroupAdd() {
|
||||
<Card>
|
||||
<CardBody>
|
||||
<InstanceGroupForm
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
onSubmit={handleSubmit}
|
||||
submitError={submitError}
|
||||
onCancel={handleCancel}
|
||||
|
||||
@ -19,13 +19,21 @@ function InstanceGroups() {
|
||||
request: settingsRequest,
|
||||
isLoading: isSettingsRequestLoading,
|
||||
error: settingsRequestError,
|
||||
result: isKubernetes,
|
||||
result: { isKubernetes, defaultControlPlane, defaultExecution },
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const {
|
||||
data: { IS_K8S },
|
||||
data: {
|
||||
IS_K8S,
|
||||
DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
},
|
||||
} = await SettingsAPI.readCategory('all');
|
||||
return IS_K8S;
|
||||
return {
|
||||
isKubernetes: IS_K8S,
|
||||
defaultControlPlane: DEFAULT_CONTROL_PLANE_QUEUE_NAME,
|
||||
defaultExecution: DEFAULT_EXECUTION_QUEUE_NAME,
|
||||
};
|
||||
}, []),
|
||||
{ isLoading: true }
|
||||
);
|
||||
@ -75,16 +83,22 @@ function InstanceGroups() {
|
||||
/>
|
||||
<Switch>
|
||||
<Route path="/instance_groups/container_group/add">
|
||||
<ContainerGroupAdd />
|
||||
<ContainerGroupAdd
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="/instance_groups/container_group/:id">
|
||||
<ContainerGroup setBreadcrumb={buildBreadcrumbConfig} />
|
||||
</Route>
|
||||
{!isSettingsRequestLoading && !isKubernetes ? (
|
||||
{!isSettingsRequestLoading && !isKubernetes && (
|
||||
<Route path="/instance_groups/add">
|
||||
<InstanceGroupAdd />
|
||||
<InstanceGroupAdd
|
||||
defaultControlPlane={defaultControlPlane}
|
||||
defaultExecution={defaultExecution}
|
||||
/>
|
||||
</Route>
|
||||
) : null}
|
||||
)}
|
||||
<Route path="/instance_groups/:id">
|
||||
<InstanceGroup setBreadcrumb={buildBreadcrumbConfig} />
|
||||
</Route>
|
||||
|
||||
@ -11,7 +11,7 @@ import FormField, {
|
||||
CheckboxField,
|
||||
} from 'components/FormField';
|
||||
import FormActionGroup from 'components/FormActionGroup';
|
||||
import { required } from 'util/validators';
|
||||
import { combine, required, protectedResourceName } from 'util/validators';
|
||||
import {
|
||||
FormColumnLayout,
|
||||
FormFullWidthLayout,
|
||||
@ -21,12 +21,20 @@ import {
|
||||
import CredentialLookup from 'components/Lookup/CredentialLookup';
|
||||
import { VariablesField } from 'components/CodeEditor';
|
||||
|
||||
function ContainerGroupFormFields({ instanceGroup }) {
|
||||
function ContainerGroupFormFields({
|
||||
instanceGroup,
|
||||
defaultControlPlane,
|
||||
defaultExecution,
|
||||
}) {
|
||||
const { setFieldValue, setFieldTouched } = useFormikContext();
|
||||
const [credentialField, credentialMeta, credentialHelpers] =
|
||||
useField('credential');
|
||||
|
||||
const [nameField] = useField('name');
|
||||
const [, { initialValue }] = useField('name');
|
||||
|
||||
const isProtected =
|
||||
initialValue === `${defaultControlPlane}` ||
|
||||
initialValue === `${defaultExecution}`;
|
||||
|
||||
const [overrideField] = useField('override');
|
||||
|
||||
@ -42,11 +50,21 @@ function ContainerGroupFormFields({ instanceGroup }) {
|
||||
<>
|
||||
<FormField
|
||||
name="name"
|
||||
helperText={
|
||||
isProtected
|
||||
? t`This is a protected Instance Group. The name cannot be changed.`
|
||||
: ''
|
||||
}
|
||||
id="container-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isDisabled={nameField.value === 'default'}
|
||||
validate={combine([
|
||||
required(null),
|
||||
protectedResourceName(
|
||||
t`This is a protected name for Container Groups. Please use a different name.`,
|
||||
[defaultControlPlane, defaultExecution]
|
||||
),
|
||||
])}
|
||||
isRequired
|
||||
/>
|
||||
<CredentialLookup
|
||||
|
||||
@ -3,42 +3,48 @@ import { func, shape } from 'prop-types';
|
||||
import { Formik, useField } from 'formik';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import { Form, Tooltip } from '@patternfly/react-core';
|
||||
import { Form } from '@patternfly/react-core';
|
||||
|
||||
import FormField, { FormSubmitError } from 'components/FormField';
|
||||
import FormActionGroup from 'components/FormActionGroup';
|
||||
import { required, minMaxValue } from 'util/validators';
|
||||
import {
|
||||
combine,
|
||||
required,
|
||||
protectedResourceName,
|
||||
minMaxValue,
|
||||
} from 'util/validators';
|
||||
import { FormColumnLayout } from 'components/FormLayout';
|
||||
|
||||
function InstanceGroupFormFields({ defaultControlPlane, defaultExecution }) {
|
||||
const [{ value }, ,] = useField('name');
|
||||
const isDisabled =
|
||||
value === defaultExecution || value === defaultControlPlane;
|
||||
const [, { initialValue }] = useField('name');
|
||||
const isProtected =
|
||||
initialValue === `${defaultControlPlane}` ||
|
||||
initialValue === `${defaultExecution}`;
|
||||
|
||||
const validators = combine([
|
||||
required(null),
|
||||
protectedResourceName(
|
||||
[defaultControlPlane, defaultExecution],
|
||||
t`This is a protected name for Instance Groups. Please use a different name.`
|
||||
),
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isDisabled ? (
|
||||
<Tooltip content={t`Name cannot be changed on this Instance Group`}>
|
||||
<FormField
|
||||
name="name"
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<FormField
|
||||
name="name"
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={required(null)}
|
||||
isRequired
|
||||
/>
|
||||
)}
|
||||
<FormField
|
||||
name="name"
|
||||
helperText={
|
||||
isProtected
|
||||
? t`This is a protected Instance Group. The name cannot be changed.`
|
||||
: ''
|
||||
}
|
||||
id="instance-group-name"
|
||||
label={t`Name`}
|
||||
type="text"
|
||||
validate={validators}
|
||||
isRequired
|
||||
isDisabled={isProtected}
|
||||
/>
|
||||
<FormField
|
||||
id="instance-group-policy-instance-minimum"
|
||||
label={t`Policy instance minimum`}
|
||||
@ -66,7 +72,6 @@ function InstanceGroupFormFields({ defaultControlPlane, defaultExecution }) {
|
||||
|
||||
function InstanceGroupForm({
|
||||
instanceGroup = {},
|
||||
|
||||
onSubmit,
|
||||
onCancel,
|
||||
submitError,
|
||||
|
||||
@ -60,6 +60,7 @@ describe('<InstanceGroupForm/>', () => {
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('Initially renders successfully', () => {
|
||||
|
||||
@ -186,3 +186,8 @@ export function regExp() {
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
export function protectedResourceName(message, names = []) {
|
||||
return (value) =>
|
||||
names.some((name) => value.trim() === `${name}`) ? message : undefined;
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
regExp,
|
||||
requiredEmail,
|
||||
validateTime,
|
||||
protectedResourceName,
|
||||
} from './validators';
|
||||
|
||||
describe('validators', () => {
|
||||
@ -187,4 +188,21 @@ describe('validators', () => {
|
||||
expect(validateTime()('12.15 PM')).toEqual('Invalid time format');
|
||||
expect(validateTime()('12;15 PM')).toEqual('Invalid time format');
|
||||
});
|
||||
test('protectedResourceName should validate properly', () => {
|
||||
expect(
|
||||
protectedResourceName('failed validation', ['Alex'])('Apollo')
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
protectedResourceName('failed validation', ['Alex', 'Athena'])('alex')
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
protectedResourceName('failed validation', ['Alex', 'Athena'])('Alex')
|
||||
).toEqual('failed validation');
|
||||
expect(
|
||||
protectedResourceName('failed validation', ['Alex'])('Alex')
|
||||
).toEqual('failed validation');
|
||||
expect(
|
||||
protectedResourceName('failed validation', ['Alex'])('Alex ')
|
||||
).toEqual('failed validation');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user