diff --git a/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.jsx b/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.jsx index c4538b3076..bd9dacc1f3 100644 --- a/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.jsx +++ b/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateList.jsx @@ -8,7 +8,10 @@ import { ExecutionEnvironmentsAPI } from '../../../api'; import { getQSConfig, parseQueryString } from '../../../util/qs'; import useRequest from '../../../util/useRequest'; import DatalistToolbar from '../../../components/DataListToolbar'; -import PaginatedDataList from '../../../components/PaginatedDataList'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../components/PaginatedTable'; import ExecutionEnvironmentTemplateListItem from './ExecutionEnvironmentTemplateListItem'; @@ -74,7 +77,7 @@ function ExecutionEnvironmentTemplateList({ executionEnvironment }) { return ( <> - ( )} - renderItem={template => ( + headerRow={ + + {t`Name`} + {t`Type`} + + } + renderRow={template => ( - - - - {template.name} - - , - - {template.type === 'job_template' - ? t`Job Template` - : t`Workflow Job Template`} - , - ]} - /> - - + + + {template.name} + + + {template.type === 'job_template' + ? t`Job Template` + : t`Workflow Job Template`} + + ); } diff --git a/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.test.jsx b/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.test.jsx index 9c107ab19b..ce14f2e35e 100644 --- a/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.test.jsx +++ b/awx/ui_next/src/screens/ExecutionEnvironment/ExecutionEnvironmentTemplate/ExecutionEnvironmentTemplateListItem.test.jsx @@ -16,33 +16,50 @@ describe('', () => { test('should mount successfully', async () => { await act(async () => { wrapper = mountWithContexts( - + + + + +
); }); expect(wrapper.find('ExecutionEnvironmentTemplateListItem').length).toBe(1); - expect(wrapper.find('DataListCell[aria-label="Name"]').text()).toBe( - template.name - ); expect( - wrapper.find('DataListCell[aria-label="Template type"]').text() + wrapper + .find('Td') + .at(0) + .text() + ).toBe(template.name); + expect( + wrapper + .find('Td') + .at(1) + .text() ).toBe('Job Template'); }); test('should distinguish template types', async () => { await act(async () => { wrapper = mountWithContexts( - + + + + +
); }); expect(wrapper.find('ExecutionEnvironmentTemplateListItem').length).toBe(1); expect( - wrapper.find('DataListCell[aria-label="Template type"]').text() + wrapper + .find('Td') + .at(1) + .text() ).toBe('Workflow Job Template'); }); }); diff --git a/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.jsx b/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.jsx index ca1bb97f21..4f1acf2088 100644 --- a/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.jsx +++ b/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.jsx @@ -3,64 +3,50 @@ import { bool, func, number, oneOfType, string } from 'prop-types'; import { t } from '@lingui/macro'; -import { - Button, - DataListAction, - DataListCheck, - DataListItem, - DataListItemCells, - DataListItemRow, - Tooltip, -} from '@patternfly/react-core'; - +import { Button } from '@patternfly/react-core'; +import { Tr, Td } from '@patternfly/react-table'; import { Link } from 'react-router-dom'; import { PencilAltIcon } from '@patternfly/react-icons'; -import DataListCell from '../../../components/DataListCell'; +import { ActionsTd, ActionItem } from '../../../components/PaginatedTable'; import { Group } from '../../../types'; -function HostGroupItem({ group, inventoryId, isSelected, onSelect }) { +function HostGroupItem({ group, inventoryId, isSelected, onSelect, rowIndex }) { const labelId = `check-action-${group.id}`; const detailUrl = `/inventories/inventory/${inventoryId}/groups/${group.id}/details`; const editUrl = `/inventories/inventory/${inventoryId}/groups/${group.id}/edit`; return ( - - - - - - {group.name} - - , - ]} - /> - + + + {' '} + + {group.name} + + + + - {group.summary_fields.user_capabilities.edit && ( - - - - )} - - - + + + + ); } diff --git a/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.test.jsx b/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.test.jsx index 65946f4e08..467436f5a7 100644 --- a/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.test.jsx +++ b/awx/ui_next/src/screens/Host/HostGroups/HostGroupItem.test.jsx @@ -18,12 +18,16 @@ describe('', () => { beforeEach(() => { wrapper = mountWithContexts( - {}} - /> + + + {}} + /> + +
); }); @@ -40,12 +44,16 @@ describe('', () => { copyMockGroup.summary_fields.user_capabilities.edit = false; wrapper = mountWithContexts( - {}} - /> + + + {}} + /> + +
); expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy(); }); diff --git a/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.jsx b/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.jsx index 07780dee72..8367f74e07 100644 --- a/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.jsx +++ b/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.jsx @@ -11,9 +11,11 @@ import useSelected from '../../../util/useSelected'; import { HostsAPI, InventoriesAPI } from '../../../api'; import AlertModal from '../../../components/AlertModal'; import ErrorDetail from '../../../components/ErrorDetail'; -import PaginatedDataList, { - ToolbarAddButton, -} from '../../../components/PaginatedDataList'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../components/PaginatedTable'; +import { ToolbarAddButton } from '../../../components/PaginatedDataList'; import AssociateModal from '../../../components/AssociateModal'; import DisassociateButton from '../../../components/DisassociateButton'; import DataListToolbar from '../../../components/DataListToolbar'; @@ -82,9 +84,13 @@ function HostGroupsList({ host }) { fetchGroups(); }, [fetchGroups]); - const { selected, isAllSelected, handleSelect, setSelected } = useSelected( - groups - ); + const { + selected, + isAllSelected, + handleSelect, + clearSelected, + selectAll, + } = useSelected(groups); const { isLoading: isDisassociateLoading, @@ -105,7 +111,7 @@ function HostGroupsList({ host }) { const handleDisassociate = async () => { await disassociateHosts(); - setSelected([]); + clearSelected(); }; const fetchGroupsToAssociate = useCallback( @@ -146,13 +152,13 @@ function HostGroupsList({ host }) { return ( <> - ( + headerRow={ + + {t`Name`} + {t`Actions`} + + } + renderRow={(item, index) => ( row.id === item.id)} onSelect={() => handleSelect(item)} + rowIndex={index} /> )} renderToolbar={props => ( @@ -191,9 +198,7 @@ function HostGroupsList({ host }) { {...props} showSelectAll isAllSelected={isAllSelected} - onSelectAll={isSelected => - setSelected(isSelected ? [...groups] : []) - } + onSelectAll={selectAll} qsConfig={QS_CONFIG} additionalControls={[ ...(canAdd diff --git a/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.test.jsx b/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.test.jsx index 4720de35ed..65cf233717 100644 --- a/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.test.jsx +++ b/awx/ui_next/src/screens/Host/HostGroups/HostGroupsList.test.jsx @@ -122,46 +122,63 @@ describe('', () => { test('should check and uncheck the row item', async () => { expect( - wrapper.find('DataListCheck[id="select-group-1"]').props().checked + wrapper + .find('.pf-c-table__check') + .first() + .find('input') + .props().checked ).toBe(false); await act(async () => { - wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')( - true - ); + wrapper + .find('.pf-c-table__check') + .first() + .find('input') + .invoke('onChange')(true); }); wrapper.update(); expect( - wrapper.find('DataListCheck[id="select-group-1"]').props().checked + wrapper + .find('.pf-c-table__check') + .first() + .find('input') + .props().checked ).toBe(true); await act(async () => { - wrapper.find('DataListCheck[id="select-group-1"]').invoke('onChange')( - false - ); + wrapper + .find('.pf-c-table__check') + .first() + .find('input') + .invoke('onChange')(false); }); wrapper.update(); expect( - wrapper.find('DataListCheck[id="select-group-1"]').props().checked + wrapper + .find('.pf-c-table__check') + .first() + .find('input') + .props().checked ).toBe(false); }); test('should check all row items when select all is checked', async () => { - wrapper.find('DataListCheck').forEach(el => { + expect.assertions(9); + wrapper.find('.pf-c-table__check input').forEach(el => { expect(el.props().checked).toBe(false); }); await act(async () => { wrapper.find('Checkbox#select-all').invoke('onChange')(true); }); wrapper.update(); - wrapper.find('DataListCheck').forEach(el => { + wrapper.find('.pf-c-table__check input').forEach(el => { expect(el.props().checked).toBe(true); }); await act(async () => { wrapper.find('Checkbox#select-all').invoke('onChange')(false); }); wrapper.update(); - wrapper.find('DataListCheck').forEach(el => { + wrapper.find('.pf-c-table__check input').forEach(el => { expect(el.props().checked).toBe(false); }); }); @@ -236,17 +253,18 @@ describe('', () => { }); test('expected api calls are made for multi-disassociation', async () => { + expect.assertions(11); expect(HostsAPI.disassociateGroup).toHaveBeenCalledTimes(0); expect(HostsAPI.readAllGroups).toHaveBeenCalledTimes(1); - expect(wrapper.find('DataListCheck').length).toBe(3); - wrapper.find('DataListCheck').forEach(el => { + + wrapper.find('.pf-c-table__check input').forEach(el => { expect(el.props().checked).toBe(false); }); await act(async () => { wrapper.find('Checkbox#select-all').invoke('onChange')(true); }); wrapper.update(); - wrapper.find('DataListCheck').forEach(el => { + wrapper.find('.pf-c-table__check input').forEach(el => { expect(el.props().checked).toBe(true); }); wrapper.find('button[aria-label="Disassociate"]').simulate('click');