diff --git a/src/components/InventoryGroups/Modals/AddHostToGroupModal.js b/src/components/InventoryGroups/Modals/AddHostToGroupModal.js
index 0d8dc8eb5..36ea5541d 100644
--- a/src/components/InventoryGroups/Modals/AddHostToGroupModal.js
+++ b/src/components/InventoryGroups/Modals/AddHostToGroupModal.js
@@ -3,9 +3,8 @@ import PropTypes from 'prop-types';
import Modal from './Modal';
import { addHostToGroup } from '../utils/api';
import apiWithToast from '../utils/apiWithToast';
-import { useDispatch } from 'react-redux';
+import { useDispatch, useSelector } from 'react-redux';
import { CreateGroupButton } from '../SmallComponents/CreateGroupButton';
-import SearchInput from './SearchInput';
import { fetchGroups } from '../../../store/inventory-actions';
import { addHostSchema } from './ModalSchemas/schemes';
import CreateGroupModal from './CreateGroupModal';
@@ -16,22 +15,24 @@ const AddHostToGroupModal = ({
modalState,
reloadData
}) => {
+
const dispatch = useDispatch();
//we have to fetch groups to make them available in state
useEffect(() => {
dispatch(fetchGroups());
-
}, []);
- const [isCreateGroupModalOpen, setIsCreateGroupModalOpen] = useState(false);
+ const groups = useSelector(({ groups }) => groups?.data?.results);
+
+ const [isCreateGroupModalOpen, setIsCreateGroupModalOpen] = useState(false);
const handleAddDevices = (values) => {
const { group } = values;
const statusMessages = {
onSuccess: {
title: 'Success',
- description: `System(s) have been added to ${group.toString()} successfully`
+ description: `System(s) have been added to ${group.name} successfully`
},
- onError: { title: 'Error', description: `Failed to add ${modalState.name} to ${modalState.groupName}` }
+ onError: { title: 'Error', description: `Failed to add ${modalState.name} to ${group.name}` }
};
apiWithToast(
@@ -48,11 +49,8 @@ const AddHostToGroupModal = ({
closeModal={() => setIsModalOpen(false)}
title="Add to group"
submitLabel="Add"
- schema={addHostSchema(modalState.name)}
+ schema={addHostSchema(modalState.name, groups)}
additionalMappers={{
- 'search-input': {
- component: SearchInput
- },
'create-group-btn': {
component: CreateGroupButton,
closeModal: () => {
@@ -70,6 +68,10 @@ const AddHostToGroupModal = ({
isModalOpen={isCreateGroupModalOpen}
setIsModalOpen={setIsCreateGroupModalOpen}
reloadData={() => console.log('data reloaded')}
+ //modal before prop tells create group modal that it should
+ //reopen add host modal when user closes create group modal
+ modalBefore={true}
+ setterOfModalBefore={setIsModalOpen}
/>
)}
>
diff --git a/src/components/InventoryGroups/Modals/CreateGroupModal.js b/src/components/InventoryGroups/Modals/CreateGroupModal.js
index 48dd78803..678e20d68 100644
--- a/src/components/InventoryGroups/Modals/CreateGroupModal.js
+++ b/src/components/InventoryGroups/Modals/CreateGroupModal.js
@@ -13,7 +13,9 @@ import awesomeDebouncePromise from 'awesome-debounce-promise';
const CreateGroupModal = ({
isModalOpen,
setIsModalOpen,
- reloadData
+ reloadData,
+ modalBefore = false,
+ setterOfModalBefore
}) => {
const dispatch = useDispatch();
@@ -46,10 +48,19 @@ const CreateGroupModal = ({
return createGroupSchema(d);
}, []);
+ const onClose = () => {
+ if (modalBefore) {
+ setIsModalOpen(false);
+ setterOfModalBefore(true);
+ } else {
+ setIsModalOpen(false);
+ }
+ };
+
return (
setIsModalOpen(false)}
+ closeModal={onClose}
title="Create group"
submitLabel="Create"
schema={schema}
@@ -64,5 +75,7 @@ export default CreateGroupModal;
CreateGroupModal.propTypes = {
isModalOpen: PropTypes.bool,
setIsModalOpen: PropTypes.func,
- reloadData: PropTypes.func
+ reloadData: PropTypes.func,
+ modalBefore: PropTypes.bool,
+ setterOfModalBefore: PropTypes.func
};
diff --git a/src/components/InventoryGroups/Modals/Modal.js b/src/components/InventoryGroups/Modals/Modal.js
index a562a8860..71bcd3300 100644
--- a/src/components/InventoryGroups/Modals/Modal.js
+++ b/src/components/InventoryGroups/Modals/Modal.js
@@ -52,6 +52,7 @@ const RepoModal = ({
closeModal();
}}
onCancel={() => closeModal()}
+ subscription={{ values: true }}
/>
);
@@ -70,7 +71,6 @@ RepoModal.propTypes = {
size: PropTypes.string,
additionalMappers: PropTypes.object,
titleIconVariant: PropTypes.any,
- validatorMapper: PropTypes.object,
customFormTemplate: PropTypes.node
};
diff --git a/src/components/InventoryGroups/Modals/ModalSchemas/schemes.js b/src/components/InventoryGroups/Modals/ModalSchemas/schemes.js
index 02f6c5512..7d52f187e 100644
--- a/src/components/InventoryGroups/Modals/ModalSchemas/schemes.js
+++ b/src/components/InventoryGroups/Modals/ModalSchemas/schemes.js
@@ -53,7 +53,7 @@ const createDescription = (systemName) => {
//this is a custom schema that is passed via additional mappers to the Modal component
//it allows to create custom item types in the modal
-export const addHostSchema = (systemName) => ({
+export const addHostSchema = (systemName, groups) => ({
fields: [
{
component: componentTypes.PLAIN_TEXT,
@@ -61,12 +61,20 @@ export const addHostSchema = (systemName) => ({
label: createDescription(systemName)
},
{
- component: 'search-input',
+ component: 'select',
name: 'group',
label: 'Select a group',
+ simpleValue: true,
+ isSearchable: true, // enables typeahead
isRequired: true,
+ isClearable: true,
+ placeholder: 'Type or click to select a group',
+ options: (groups || []).map(({ id, name }) => ({
+ label: name,
+ value: { name, id }
+ })),
validate: [{ type: validatorTypes.REQUIRED }]
},
- { component: 'create-group-btn', name: 'create-group-btn' }
+ { component: 'create-group-btn', name: 'create-group-btn', isRequired: true }
]
});
diff --git a/src/components/InventoryGroups/Modals/SearchInput.js b/src/components/InventoryGroups/Modals/SearchInput.js
deleted file mode 100644
index ee08987c4..000000000
--- a/src/components/InventoryGroups/Modals/SearchInput.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import { useSelector } from 'react-redux';
-import {
- HelperText,
- HelperTextItem,
- Select,
- SelectOption
-} from '@patternfly/react-core';
-import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
-
-const SearchInput = () => {
- const { change } = useFormApi();
- const [isLoading, setIsLoading] = useState(true);
- //fetch data from the store
- const storeGroups = useSelector(({ groups }) => groups?.data?.results);
-
- //select options is a constructed array of objects with values for dropdown
- const [selectOptions, setSelectOptions] = useState([]);
- //when storeGroups is changed - we create selectOptions
- useEffect(() => {
- setSelectOptions(
- (storeGroups || []).reduce((acc, group) => {
- acc.push({
- DeviceGroup: {
- ID: group.id,
- Name: group.name,
- UpdatedAt: group.updated_at,
- CreatedAt: group.created_at
- }
- });
- return acc;
- }, [])
- );
- setIsLoading(false);
- }, [storeGroups]);
-
- const [isOpen, setIsOpen] = useState(false);
- const [selected, setSelected] = useState(null);
- const [searchTerm, setSearchTerm] = useState('');
-
- const onToggle = (isOpen) => {
- setIsOpen(isOpen);
- };
-
- const updateSelection = (value) => {
- // Update state when an option has been selected.
- setSelected(value);
- setIsOpen(false);
- //this is requried to make select component pass the saved data up to the modal
- change('group', value);
- };
-
- const clearSelection = () => {
- setSearchTerm('');
- updateSelection(null);
- setIsOpen(false);
- };
-
- const onSelect = (_event, selection, isPlaceholder) => {
- if (isPlaceholder) {
- clearSelection();
- }
- else {
- updateSelection(selection);
- }
- };
-
- return (
- <>
-
- {!isLoading && !selected && isOpen && selectOptions.length ? (
-
- Over {selectOptions.length} results found. Refine your search.
-
- ) : (
-
- Select a group
-
- )}
-
-
- >
- );
-};
-
-export default SearchInput;
diff --git a/src/components/InventoryGroups/Modals/__tests__/SearchInput.test.js b/src/components/InventoryGroups/Modals/__tests__/SearchInput.test.js
deleted file mode 100644
index b5d927ab4..000000000
--- a/src/components/InventoryGroups/Modals/__tests__/SearchInput.test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable camelcase */
-
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import SearchInput from '../SearchInput';
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
-import groups from '../../../../../cypress/fixtures/groups.json';
-
-describe('SearchInput', () => {
- let mockStore;
- const initialStore = {
- groups
- };
- beforeEach(() => {
- mockStore = configureStore();
- });
-
- test('displays select options when the user clicks on the component', async () => {
- const store = mockStore(initialStore);
- render();
- fireEvent.click(screen.getByRole('textbox', { placeholder: 'Type or click to select a group' }));
- const options = await screen.findAllByRole('option');
- expect(options).toHaveLength(1);
- });
-});