diff --git a/awx/ui_next/src/screens/Template/shared/ProjectLookup.jsx b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx
similarity index 78%
rename from awx/ui_next/src/screens/Template/shared/ProjectLookup.jsx
rename to awx/ui_next/src/components/Lookup/ProjectLookup.jsx
index 0bcc42dd84..3493c2d531 100644
--- a/awx/ui_next/src/screens/Template/shared/ProjectLookup.jsx
+++ b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx
@@ -2,16 +2,11 @@ import React from 'react';
import { string, func, bool } from 'prop-types';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
-import { FormGroup, Tooltip } from '@patternfly/react-core';
-import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
+import { FormGroup } from '@patternfly/react-core';
import { ProjectsAPI } from '@api';
import { Project } from '@types';
import Lookup from '@components/Lookup';
-import styled from 'styled-components';
-
-const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
- margin-left: 10px;
-`;
+import { FieldTooltip } from '@components/FormField';
const loadProjects = async params => ProjectsAPI.read(params);
@@ -36,11 +31,7 @@ class ProjectLookup extends React.Component {
isValid={isValid}
label={i18n._(t`Project`)}
>
- {tooltip && (
-
-
-
- )}
+ {tooltip && }
label {
@@ -72,7 +76,6 @@ class JobTemplateForm extends Component {
removedLabels: [],
project: props.template.summary_fields.project,
inventory: props.template.summary_fields.inventory,
- relatedProjectPlaybooks: props.relatedProjectPlaybooks,
relatedInstanceGroups: [],
allowCallbacks: !!props.template.host_config_key,
};
@@ -81,9 +84,6 @@ class JobTemplateForm extends Component {
this.removeLabel = this.removeLabel.bind(this);
this.handleProjectValidation = this.handleProjectValidation.bind(this);
this.loadRelatedInstanceGroups = this.loadRelatedInstanceGroups.bind(this);
- this.loadRelatedProjectPlaybooks = this.loadRelatedProjectPlaybooks.bind(
- this
- );
this.handleInstanceGroupsChange = this.handleInstanceGroupsChange.bind(
this
);
@@ -204,15 +204,6 @@ class JobTemplateForm extends Component {
}
}
- async loadRelatedProjectPlaybooks(project) {
- try {
- const { data: playbooks = [] } = await ProjectsAPI.readPlaybooks(project);
- this.setState({ relatedProjectPlaybooks: playbooks });
- } catch (contentError) {
- this.setState({ contentError });
- }
- }
-
handleProjectValidation() {
const { i18n, touched } = this.props;
const { project } = this.state;
@@ -258,7 +249,6 @@ class JobTemplateForm extends Component {
hasContentLoading,
inventory,
project,
- relatedProjectPlaybooks = [],
relatedInstanceGroups,
allowCallbacks,
} = this.state;
@@ -284,28 +274,6 @@ class JobTemplateForm extends Component {
isDisabled: false,
},
];
- const playbookOptions = relatedProjectPlaybooks
- .map(playbook => {
- return {
- value: playbook,
- key: playbook,
- label: playbook,
- isDisabled: false,
- };
- })
- .reduce(
- (arr, playbook) => {
- return arr.concat(playbook);
- },
- [
- {
- value: '',
- key: '',
- label: i18n._(t`Choose a playbook`),
- isDisabled: false,
- },
- ]
- );
const verbosityOptions = [
{ value: '0', key: '0', label: i18n._(t`0 (Normal)`) },
@@ -412,7 +380,6 @@ class JobTemplateForm extends Component {
tooltip={i18n._(t`Select the project containing the playbook
you want this job to execute.`)}
onChange={value => {
- this.loadRelatedProjectPlaybooks(value.id);
form.setFieldValue('project', value.id);
this.setState({ project: value });
}}
@@ -439,13 +406,8 @@ class JobTemplateForm extends Component {
t`Select the playbook to be executed by this job.`
)}
/>
-
+
);
}}
diff --git a/awx/ui_next/src/screens/Template/shared/PlaybookSelect.jsx b/awx/ui_next/src/screens/Template/shared/PlaybookSelect.jsx
new file mode 100644
index 0000000000..7b9c89f110
--- /dev/null
+++ b/awx/ui_next/src/screens/Template/shared/PlaybookSelect.jsx
@@ -0,0 +1,51 @@
+import React, { useState, useEffect } from 'react';
+import { number, string, oneOfType } from 'prop-types';
+import { withI18n } from '@lingui/react';
+import { t } from '@lingui/macro';
+import AnsibleSelect from '@components/AnsibleSelect';
+import { ProjectsAPI } from '@api';
+
+function PlaybookSelect({ projectId, isValid, form, field, onError, i18n }) {
+ const [options, setOptions] = useState([]);
+ useEffect(() => {
+ (async () => {
+ try {
+ const { data } = await ProjectsAPI.readPlaybooks(projectId);
+ const opts = (data || []).map(playbook => ({
+ value: playbook,
+ key: playbook,
+ label: playbook,
+ isDisabled: false,
+ }));
+ opts.unshift({
+ value: '',
+ key: '',
+ label: i18n._(t`Choose a playbook`),
+ isDisabled: false,
+ });
+ setOptions(opts);
+ } catch (contentError) {
+ onError(contentError);
+ }
+ })();
+ }, [projectId]);
+
+ return (
+
+ );
+}
+PlaybookSelect.propTypes = {
+ projectId: oneOfType([number, string]),
+};
+PlaybookSelect.defaultProps = {
+ projectId: null,
+};
+
+export { PlaybookSelect as _PlaybookSelect };
+export default withI18n()(PlaybookSelect);