diff --git a/awx/ui/src/screens/Instances/InstanceAdd/InstanceAdd.js b/awx/ui/src/screens/Instances/InstanceAdd/InstanceAdd.js new file mode 100644 index 0000000000..0fa6f1c630 --- /dev/null +++ b/awx/ui/src/screens/Instances/InstanceAdd/InstanceAdd.js @@ -0,0 +1,45 @@ +import React, { useState } from 'react'; +import { useHistory } from 'react-router-dom'; +import { Card, PageSection } from '@patternfly/react-core'; +import { InstancesAPI } from 'api'; +import InstanceForm from '../Shared/InstanceForm'; + +function InstanceAdd() { + const history = useHistory(); + const [formError, setFormError] = useState(); + const handleSubmit = async (values) => { + const { instanceGroups, executionEnvironment } = values; + values.execution_environment = executionEnvironment?.id; + + try { + const { + data: { id }, + } = await InstancesAPI.create(); + + for (const group of instanceGroups) { + await InstancesAPI.associateInstanceGroup(id, group.id); + } + history.push(`/instances/${id}/details`); + } catch (err) { + setFormError(err); + } + }; + + const handleCancel = () => { + history.push('/instances'); + }; + + return ( + + + + + + ); +} + +export default InstanceAdd; diff --git a/awx/ui/src/screens/Instances/InstanceAdd/index.js b/awx/ui/src/screens/Instances/InstanceAdd/index.js new file mode 100644 index 0000000000..c6ddcff5bc --- /dev/null +++ b/awx/ui/src/screens/Instances/InstanceAdd/index.js @@ -0,0 +1 @@ +export { default } from './InstanceAdd'; diff --git a/awx/ui/src/screens/Instances/Shared/InstanceForm.js b/awx/ui/src/screens/Instances/Shared/InstanceForm.js new file mode 100644 index 0000000000..6d706b39cf --- /dev/null +++ b/awx/ui/src/screens/Instances/Shared/InstanceForm.js @@ -0,0 +1,130 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import { Formik, useField } from 'formik'; +import { Form, FormGroup, CardBody } from '@patternfly/react-core'; +import { FormColumnLayout } from 'components/FormLayout'; +import FormField, { FormSubmitError } from 'components/FormField'; +import FormActionGroup from 'components/FormActionGroup'; +import { required } from 'util/validators'; +import AnsibleSelect from 'components/AnsibleSelect'; +import { + ExecutionEnvironmentLookup, + InstanceGroupsLookup, +} from 'components/Lookup'; + +// This is hard coded because the API does not have the ability to send us a list that contains +// only the types of instances that can be added. Control and Hybrid instances cannot be added. + +const INSTANCE_TYPES = [ + { id: 2, name: t`Execution`, value: 'execution' }, + { id: 3, name: t`Hop`, value: 'hop' }, +]; + +function InstanceFormFields() { + const [instanceType, , instanceTypeHelpers] = useField('type'); + const [instanceGroupsField, , instanceGroupsHelpers] = + useField('instanceGroups'); + const [ + executionEnvironmentField, + executionEnvironmentMeta, + executionEnvironmentHelpers, + ] = useField('executionEnvironment'); + return ( + <> + + + + ({ + key: type.id, + value: type.value, + label: type.name, + isDisabled: false, + }))} + value={instanceType.value} + onChange={(e, opt) => { + instanceTypeHelpers.setValue(opt); + }} + /> + + { + instanceGroupsHelpers.setValue(value); + }} + fieldName="instanceGroups" + /> + executionEnvironmentHelpers.setTouched()} + value={executionEnvironmentField.value} + onChange={(value) => { + executionEnvironmentHelpers.setValue(value); + }} + /> + + ); +} + +function InstanceForm({ + instance = {}, + submitError, + handleCancel, + handleSubmit, +}) { + return ( + + { + handleSubmit(values); + }} + > + {(formik) => ( +
+ + + + + +
+ )} +
+
+ ); +} + +export default InstanceForm;