setIsAdHocCommandsOpen(false)}
- credentialTypeId={credentialTypeId}
- moduleOptions={moduleOptions}
- />
- )}
>
);
}
diff --git a/awx/ui_next/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.jsx b/awx/ui_next/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.jsx
index 60fd23d75a..6f7c743a3a 100644
--- a/awx/ui_next/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.jsx
+++ b/awx/ui_next/src/screens/Inventory/SmartInventoryHosts/SmartInventoryHostList.test.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
-import { InventoriesAPI, CredentialTypesAPI } from '../../../api';
+import { InventoriesAPI } from '../../../api';
import {
mountWithContexts,
waitForElement,
@@ -27,17 +27,6 @@ describe('', () => {
InventoriesAPI.readHosts.mockResolvedValue({
data: mockHosts,
});
- InventoriesAPI.readAdHocOptions.mockResolvedValue({
- data: {
- actions: {
- GET: { module_name: { choices: [['module']] } },
- POST: {},
- },
- },
- });
- CredentialTypesAPI.read.mockResolvedValue({
- data: { count: 1, results: [{ id: 1, name: 'cred' }] },
- });
await act(async () => {
wrapper = mountWithContexts(
@@ -60,15 +49,6 @@ describe('', () => {
expect(wrapper.find('SmartInventoryHostListItem').length).toBe(3);
});
- test('should have run command button', () => {
- wrapper.find('DataListCheck').forEach(el => {
- expect(el.props().checked).toBe(false);
- });
- const runCommandsButton = wrapper.find('button[aria-label="Run command"]');
- expect(runCommandsButton.length).toBe(1);
- expect(runCommandsButton.prop('disabled')).toBe(false);
- });
-
test('should select and deselect all items', async () => {
act(() => {
wrapper.find('DataListToolbar').invoke('onSelectAll')(true);
@@ -97,24 +77,4 @@ describe('', () => {
});
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
});
- test('should disable run commands button', async () => {
- InventoriesAPI.readHosts.mockResolvedValue({
- data: { results: [], count: 0 },
- });
- InventoriesAPI.readAdHocOptions.mockResolvedValue({
- data: {
- actions: {
- GET: { module_name: { choices: [['module']] } },
- },
- },
- });
- await act(async () => {
- wrapper = mountWithContexts(
-
- );
- });
- await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
- const runCommandsButton = wrapper.find('button[aria-label="Run command"]');
- expect(runCommandsButton.prop('disabled')).toBe(true);
- });
});
diff --git a/awx/ui_next/src/screens/Inventory/shared/AddDropdown.jsx b/awx/ui_next/src/screens/Inventory/shared/AddDropdown.jsx
new file mode 100644
index 0000000000..1f6820fd7f
--- /dev/null
+++ b/awx/ui_next/src/screens/Inventory/shared/AddDropdown.jsx
@@ -0,0 +1,88 @@
+import React, { useState, useRef, useEffect, Fragment } from 'react';
+import { func, string, arrayOf, shape } from 'prop-types';
+import { withI18n } from '@lingui/react';
+import { t } from '@lingui/macro';
+import {
+ Dropdown,
+ DropdownItem,
+ DropdownPosition,
+ DropdownToggle,
+} from '@patternfly/react-core';
+import { useKebabifiedMenu } from '../../../contexts/Kebabified';
+
+function AddDropdown({ dropdownItems, i18n }) {
+ const { isKebabified } = useKebabifiedMenu();
+ const [isOpen, setIsOpen] = useState(false);
+ const element = useRef(null);
+
+ useEffect(() => {
+ const toggle = e => {
+ if (!isKebabified && (!element || !element.current.contains(e.target))) {
+ setIsOpen(false);
+ }
+ };
+
+ document.addEventListener('click', toggle, false);
+ return () => {
+ document.removeEventListener('click', toggle);
+ };
+ }, [isKebabified]);
+
+ if (isKebabified) {
+ return (
+
+ {dropdownItems.map(item => (
+
+ {item.title}
+
+ ))}
+
+ );
+ }
+
+ return (
+
+ setIsOpen(prevState => !prevState)}
+ >
+ {i18n._(t`Add`)}
+
+ }
+ dropdownItems={dropdownItems.map(item => (
+
+ {item.title}
+
+ ))}
+ />
+
+ );
+}
+
+AddDropdown.propTypes = {
+ dropdownItems: arrayOf(
+ shape({
+ label: string.isRequired,
+ onAdd: func.isRequired,
+ key: string.isRequired,
+ })
+ ).isRequired,
+};
+
+export { AddDropdown as _AddDropdown };
+export default withI18n()(AddDropdown);
diff --git a/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AddHostDropdown.test.jsx b/awx/ui_next/src/screens/Inventory/shared/AddDropdown.test.jsx
similarity index 64%
rename from awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AddHostDropdown.test.jsx
rename to awx/ui_next/src/screens/Inventory/shared/AddDropdown.test.jsx
index 8a7d2c11d4..39b291bc8f 100644
--- a/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AddHostDropdown.test.jsx
+++ b/awx/ui_next/src/screens/Inventory/shared/AddDropdown.test.jsx
@@ -1,17 +1,27 @@
import React from 'react';
import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
-import AddHostDropdown from './AddHostDropdown';
+import AddDropdown from './AddDropdown';
-describe('', () => {
+describe('', () => {
let wrapper;
let dropdownToggle;
- const onAddNew = jest.fn();
- const onAddExisting = jest.fn();
+ const dropdownItems = [
+ {
+ onAdd: () => {},
+ title: 'Add existing group',
+ label: 'group',
+ key: 'existing',
+ },
+ {
+ onAdd: () => {},
+ title: 'Add new group',
+ label: 'group',
+ key: 'new',
+ },
+ ];
beforeEach(() => {
- wrapper = mountWithContexts(
-
- );
+ wrapper = mountWithContexts();
dropdownToggle = wrapper.find('DropdownToggle button');
});
diff --git a/awx/ui_next/src/screens/Inventory/shared/data.relatedGroups.json b/awx/ui_next/src/screens/Inventory/shared/data.relatedGroups.json
new file mode 100644
index 0000000000..835ab95d79
--- /dev/null
+++ b/awx/ui_next/src/screens/Inventory/shared/data.relatedGroups.json
@@ -0,0 +1,181 @@
+{
+ "count": 3,
+ "results": [{
+ "id": 2,
+ "type": "group",
+ "url": "/api/v2/groups/2/",
+ "related": {
+ "created_by": "/api/v2/users/10/",
+ "modified_by": "/api/v2/users/14/",
+ "variable_data": "/api/v2/groups/2/variable_data/",
+ "hosts": "/api/v2/groups/2/hosts/",
+ "potential_children": "/api/v2/groups/2/potential_children/",
+ "children": "/api/v2/groups/2/children/",
+ "all_hosts": "/api/v2/groups/2/all_hosts/",
+ "job_events": "/api/v2/groups/2/job_events/",
+ "job_host_summaries": "/api/v2/groups/2/job_host_summaries/",
+ "activity_stream": "/api/v2/groups/2/activity_stream/",
+ "inventory_sources": "/api/v2/groups/2/inventory_sources/",
+ "ad_hoc_commands": "/api/v2/groups/2/ad_hoc_commands/",
+ "inventory": "/api/v2/inventories/1/"
+ },
+ "summary_fields": {
+ "inventory": {
+ "id": 1,
+ "name": " Inventory 1 Org 0",
+ "description": "",
+ "has_active_failures": false,
+ "total_hosts": 33,
+ "hosts_with_active_failures": 0,
+ "total_groups": 4,
+ "has_inventory_sources": false,
+ "total_inventory_sources": 0,
+ "inventory_sources_with_failures": 0,
+ "organization_id": 1,
+ "kind": ""
+ },
+ "created_by": {
+ "id": 10,
+ "username": "user-4",
+ "first_name": "",
+ "last_name": ""
+ },
+ "modified_by": {
+ "id": 14,
+ "username": "user-8",
+ "first_name": "",
+ "last_name": ""
+ },
+ "user_capabilities": {
+ "edit": true,
+ "delete": true,
+ "copy": true
+ }
+ },
+ "created": "2020-09-23T14:30:55.263148Z",
+ "modified": "2020-09-23T14:30:55.263175Z",
+ "name": " Group 2 Inventory 0",
+ "description": "",
+ "inventory": 1,
+ "variables": ""
+ },
+ {
+ "id": 3,
+ "type": "group",
+ "url": "/api/v2/groups/3/",
+ "related": {
+ "created_by": "/api/v2/users/11/",
+ "modified_by": "/api/v2/users/15/",
+ "variable_data": "/api/v2/groups/3/variable_data/",
+ "hosts": "/api/v2/groups/3/hosts/",
+ "potential_children": "/api/v2/groups/3/potential_children/",
+ "children": "/api/v2/groups/3/children/",
+ "all_hosts": "/api/v2/groups/3/all_hosts/",
+ "job_events": "/api/v2/groups/3/job_events/",
+ "job_host_summaries": "/api/v2/groups/3/job_host_summaries/",
+ "activity_stream": "/api/v2/groups/3/activity_stream/",
+ "inventory_sources": "/api/v2/groups/3/inventory_sources/",
+ "ad_hoc_commands": "/api/v2/groups/3/ad_hoc_commands/",
+ "inventory": "/api/v2/inventories/1/"
+ },
+ "summary_fields": {
+ "inventory": {
+ "id": 1,
+ "name": " Inventory 1 Org 0",
+ "description": "",
+ "has_active_failures": false,
+ "total_hosts": 33,
+ "hosts_with_active_failures": 0,
+ "total_groups": 4,
+ "has_inventory_sources": false,
+ "total_inventory_sources": 0,
+ "inventory_sources_with_failures": 0,
+ "organization_id": 1,
+ "kind": ""
+ },
+ "created_by": {
+ "id": 11,
+ "username": "user-5",
+ "first_name": "",
+ "last_name": ""
+ },
+ "modified_by": {
+ "id": 15,
+ "username": "user-9",
+ "first_name": "",
+ "last_name": ""
+ },
+ "user_capabilities": {
+ "edit": true,
+ "delete": true,
+ "copy": true
+ }
+ },
+ "created": "2020-09-23T14:30:55.281583Z",
+ "modified": "2020-09-23T14:30:55.281615Z",
+ "name": " Group 3 Inventory 0",
+ "description": "",
+ "inventory": 1,
+ "variables": ""
+ },
+ {
+ "id": 4,
+ "type": "group",
+ "url": "/api/v2/groups/4/",
+ "related": {
+ "created_by": "/api/v2/users/12/",
+ "modified_by": "/api/v2/users/16/",
+ "variable_data": "/api/v2/groups/4/variable_data/",
+ "hosts": "/api/v2/groups/4/hosts/",
+ "potential_children": "/api/v2/groups/4/potential_children/",
+ "children": "/api/v2/groups/4/children/",
+ "all_hosts": "/api/v2/groups/4/all_hosts/",
+ "job_events": "/api/v2/groups/4/job_events/",
+ "job_host_summaries": "/api/v2/groups/4/job_host_summaries/",
+ "activity_stream": "/api/v2/groups/4/activity_stream/",
+ "inventory_sources": "/api/v2/groups/4/inventory_sources/",
+ "ad_hoc_commands": "/api/v2/groups/4/ad_hoc_commands/",
+ "inventory": "/api/v2/inventories/1/"
+ },
+ "summary_fields": {
+ "inventory": {
+ "id": 1,
+ "name": " Inventory 1 Org 0",
+ "description": "",
+ "has_active_failures": false,
+ "total_hosts": 33,
+ "hosts_with_active_failures": 0,
+ "total_groups": 4,
+ "has_inventory_sources": false,
+ "total_inventory_sources": 0,
+ "inventory_sources_with_failures": 0,
+ "organization_id": 1,
+ "kind": ""
+ },
+ "created_by": {
+ "id": 12,
+ "username": "user-6",
+ "first_name": "",
+ "last_name": ""
+ },
+ "modified_by": {
+ "id": 16,
+ "username": "user-10",
+ "first_name": "",
+ "last_name": ""
+ },
+ "user_capabilities": {
+ "edit": false,
+ "delete": true,
+ "copy": true
+ }
+ },
+ "created": "2020-09-23T14:30:55.293574Z",
+ "modified": "2020-09-23T14:30:55.293603Z",
+ "name": " Group 4 Inventory 0",
+ "description": "",
+ "inventory": 1,
+ "variables": ""
+ }
+ ]
+}