From c456b944a57f8f6c46aca67593bc41b2ce567c36 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 11 May 2021 13:18:19 -0400 Subject: [PATCH 1/2] Converts all Lists inside a modal, mostly components that use OptionsList, to paginated tables --- .../AdHocCommands/AdHocCommands.test.jsx | 12 ++- .../AdHocCommandsWizard.test.jsx | 6 +- .../AddRole/AddResourceRole.test.jsx | 32 +++---- .../CheckboxListItem/CheckboxListItem.jsx | 83 +++++-------------- .../steps/CredentialsStep.test.jsx | 9 +- .../components/OptionsList/OptionsList.jsx | 12 ++- .../OptionsList/OptionsList.test.jsx | 2 +- .../PaginatedTable/PaginatedTable.jsx | 1 - .../Schedule/ScheduleAdd/ScheduleAdd.test.jsx | 6 +- .../ScheduleEdit/ScheduleEdit.test.jsx | 18 ++-- .../Schedule/shared/ScheduleForm.test.jsx | 6 +- .../CredentialPluginField.jsx | 10 +-- .../CredentialPluginPrompt.test.jsx | 28 ++++--- .../CredentialsStep.jsx | 22 ++--- .../Modals/NodeModals/NodeModal.test.jsx | 32 +++++-- .../NodeTypeStep/InventorySourcesList.jsx | 22 ++--- .../InventorySourcesList.test.jsx | 2 +- .../NodeTypeStep/JobTemplatesList.jsx | 22 ++--- .../NodeTypeStep/JobTemplatesList.test.jsx | 3 +- .../NodeModals/NodeTypeStep/ProjectsList.jsx | 22 ++--- .../NodeTypeStep/ProjectsList.test.jsx | 2 +- .../NodeTypeStep/WorkflowJobTemplatesList.jsx | 22 ++--- .../WorkflowJobTemplatesList.test.jsx | 2 +- 23 files changed, 187 insertions(+), 189 deletions(-) diff --git a/awx/ui_next/src/components/AdHocCommands/AdHocCommands.test.jsx b/awx/ui_next/src/components/AdHocCommands/AdHocCommands.test.jsx index fdd2be33b7..e03b2bf945 100644 --- a/awx/ui_next/src/components/AdHocCommands/AdHocCommands.test.jsx +++ b/awx/ui_next/src/components/AdHocCommands/AdHocCommands.test.jsx @@ -206,7 +206,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .simulate('change', { target: { checked: true } }); }); @@ -224,7 +225,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-4"]') + .find('td#check-action-item-4') + .find('input') .simulate('change', { target: { checked: true } }); }); @@ -373,7 +375,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .simulate('change', { target: { checked: true, @@ -395,7 +398,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-4"]') + .find('td#check-action-item-4') + .find('input') .simulate('change', { target: { checked: true, diff --git a/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx b/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx index db8d7edd17..f1fe18338d 100644 --- a/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx +++ b/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx @@ -153,7 +153,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .simulate('change', { target: { checked: true } }); }); @@ -178,7 +179,8 @@ describe('', () => { expect(wrapper.find('Button[type="submit"]').prop('isDisabled')).toBe(true); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .simulate('change', { target: { checked: true } }); }); diff --git a/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx b/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx index 0e168d974c..5be9c860d1 100644 --- a/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx +++ b/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx @@ -96,12 +96,12 @@ describe('<_AddResourceRole />', () => { // Step 2 await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); act(() => - wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) + wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true) ); wrapper.update(); - expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( - true - ); + expect( + wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected') + ).toBe(true); act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); wrapper.update(); @@ -162,12 +162,12 @@ describe('<_AddResourceRole />', () => { // Step 2 await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); act(() => - wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) + wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true) ); wrapper.update(); - expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( - true - ); + expect( + wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected') + ).toBe(true); act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); wrapper.update(); @@ -214,12 +214,12 @@ describe('<_AddResourceRole />', () => { // Step 2 await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); act(() => - wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) + wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true) ); wrapper.update(); - expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( - true - ); + expect( + wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected') + ).toBe(true); await act(async () => wrapper.find('PFWizard').prop('onGoToStep')({ id: 1 }) ); @@ -280,12 +280,12 @@ describe('<_AddResourceRole />', () => { // Step 2 await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); act(() => - wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) + wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true) ); wrapper.update(); - expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( - true - ); + expect( + wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected') + ).toBe(true); act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); wrapper.update(); diff --git a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx index 3675b9037e..ac167e61de 100644 --- a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx +++ b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx @@ -1,34 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import styled from 'styled-components'; -import { - DataListItem, - DataListItemRow as PFDataListItemRow, - DataListItemCells, - DataListCheck, - Radio, -} from '@patternfly/react-core'; -import _DataListCell from '../DataListCell'; - -const Label = styled.label` - ${({ isDisabled }) => - isDisabled && - ` - opacity: 0.5; - `} -`; - -const DataListItemRow = styled(PFDataListItemRow)` - && { - align-items: center; - } -`; - -const DataListCell = styled(_DataListCell)` - && { - margin-left: 10px; - } -`; +import { t } from '@lingui/macro'; +import { Td, Tr } from '@patternfly/react-table'; const CheckboxListItem = ({ isDisabled = false, @@ -38,43 +11,27 @@ const CheckboxListItem = ({ label, name, onDeselect, + rowIndex, onSelect, }) => { - const CheckboxRadio = isRadio ? Radio : DataListCheck; return ( - - - - - - , - ]} - /> - - + + + + {label} + + ); }; diff --git a/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx b/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx index 0ff65f2815..1b6e37c15f 100644 --- a/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/steps/CredentialsStep.test.jsx @@ -181,7 +181,8 @@ describe('CredentialsStep', () => { expect(wrapper.find('Alert').length).toBe(0); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .simulate('change', { target: { checked: true } }); }); wrapper.update(); @@ -241,7 +242,8 @@ describe('CredentialsStep', () => { ).toBe(true); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-5"]') + .find('td#check-action-item-5') + .find('input') .simulate('change', { target: { checked: true } }); }); wrapper.update(); @@ -317,7 +319,8 @@ describe('CredentialsStep', () => { wrapper.update(); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-33"]') + .find('td#check-action-item-33') + .find('input') .simulate('change', { target: { checked: true } }); }); wrapper.update(); diff --git a/awx/ui_next/src/components/OptionsList/OptionsList.jsx b/awx/ui_next/src/components/OptionsList/OptionsList.jsx index ef6f23da75..ccd6fd8ff9 100644 --- a/awx/ui_next/src/components/OptionsList/OptionsList.jsx +++ b/awx/ui_next/src/components/OptionsList/OptionsList.jsx @@ -12,10 +12,10 @@ import styled from 'styled-components'; import { t } from '@lingui/macro'; import SelectedList from '../SelectedList'; -import PaginatedDataList from '../PaginatedDataList'; import CheckboxListItem from '../CheckboxListItem'; import DataListToolbar from '../DataListToolbar'; import { QSConfig, SearchColumns, SortColumns } from '../../types'; +import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable'; const ModalList = styled.div` .pf-c-toolbar__content { @@ -56,7 +56,7 @@ function OptionsList({ displayKey={displayKey} /> )} - + {t`Name`} + + } onRowClick={selectItem} - renderItem={item => ( + renderRow={(item, index) => ( ', () => { name="Item" /> ); - expect(wrapper.find('PaginatedDataList').prop('items')).toEqual(options); + expect(wrapper.find('PaginatedTable').prop('items')).toEqual(options); expect(wrapper.find('SelectedList')).toHaveLength(0); }); diff --git a/awx/ui_next/src/components/PaginatedTable/PaginatedTable.jsx b/awx/ui_next/src/components/PaginatedTable/PaginatedTable.jsx index 5bced479a6..871e2bfbb2 100644 --- a/awx/ui_next/src/components/PaginatedTable/PaginatedTable.jsx +++ b/awx/ui_next/src/components/PaginatedTable/PaginatedTable.jsx @@ -35,7 +35,6 @@ function PaginatedTable({ toolbarRelatedSearchableKeys, pluralizedItemName, showPageSizeOptions, - renderToolbar, emptyContentMessage, ouiaId, diff --git a/awx/ui_next/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.jsx b/awx/ui_next/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.jsx index a84a50a466..4ecd88cf3a 100644 --- a/awx/ui_next/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.jsx +++ b/awx/ui_next/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.jsx @@ -339,7 +339,8 @@ describe('', () => { ).toBe(true); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .simulate('change', { target: { checked: true, @@ -349,7 +350,8 @@ describe('', () => { wrapper.update(); expect( wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .prop('checked') ).toBe(true); await act(async () => diff --git a/awx/ui_next/src/components/Schedule/ScheduleEdit/ScheduleEdit.test.jsx b/awx/ui_next/src/components/Schedule/ScheduleEdit/ScheduleEdit.test.jsx index 4e050cb372..85de8346fe 100644 --- a/awx/ui_next/src/components/Schedule/ScheduleEdit/ScheduleEdit.test.jsx +++ b/awx/ui_next/src/components/Schedule/ScheduleEdit/ScheduleEdit.test.jsx @@ -471,7 +471,8 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .simulate('change', { target: { checked: true, @@ -482,7 +483,8 @@ describe('', () => { expect( wrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .prop('checked') ).toBe(true); await act(async () => @@ -502,13 +504,15 @@ describe('', () => { await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .simulate('click'); }); wrapper.update(); expect( wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .prop('checked') ).toBe(true); await act(async () => @@ -599,7 +603,8 @@ describe('', () => { wrapper.update(); await act(async () => { wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .simulate('change', { target: { checked: true, @@ -610,7 +615,8 @@ describe('', () => { expect( wrapper - .find('input[aria-labelledby="check-action-item-2"]') + .find('td#check-action-item-2') + .find('input') .prop('checked') ).toBe(true); await act(async () => diff --git a/awx/ui_next/src/components/Schedule/shared/ScheduleForm.test.jsx b/awx/ui_next/src/components/Schedule/shared/ScheduleForm.test.jsx index 5455919ebc..c650c3ceaa 100644 --- a/awx/ui_next/src/components/Schedule/shared/ScheduleForm.test.jsx +++ b/awx/ui_next/src/components/Schedule/shared/ScheduleForm.test.jsx @@ -330,7 +330,8 @@ describe('', () => { ).toBe(true); await act(async () => { promptWrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .simulate('change', { target: { checked: true, @@ -340,7 +341,8 @@ describe('', () => { promptWrapper.update(); expect( promptWrapper - .find('input[aria-labelledby="check-action-item-1"]') + .find('td#check-action-item-1') + .find('input') .prop('checked') ).toBe(true); await act(async () => diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx index c944f26ce2..caea121978 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginField.jsx @@ -19,15 +19,7 @@ import { CredentialPluginPrompt } from './CredentialPluginPrompt'; import CredentialPluginSelected from './CredentialPluginSelected'; function CredentialPluginInput(props) { - const { - children, - - isDisabled, - isRequired, - validated, - fieldOptions, - } = props; - + const { children, isDisabled, isRequired, validated, fieldOptions } = props; const [showPluginWizard, setShowPluginWizard] = useState(false); const [inputField, meta, helpers] = useField(`inputs.${fieldOptions.id}`); const [passwordPromptField] = useField(`passwordPrompts.${fieldOptions.id}`); diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.test.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.test.jsx index 8a1a6ccac6..ce765d19b9 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.test.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialPluginPrompt.test.jsx @@ -114,7 +114,7 @@ describe('', () => { test('credentials step renders correctly', () => { expect(wrapper.find('CredentialsStep').length).toBe(1); - expect(wrapper.find('DataListItem').length).toBe(3); + expect(wrapper.find('CheckboxListItem').length).toBe(3); expect( wrapper.find('Radio').filterWhere(radio => radio.isChecked).length ).toBe(0); @@ -129,18 +129,19 @@ describe('', () => { expect(onClose).toHaveBeenCalledTimes(1); }); test('clicking credential row enables next button', async () => { + await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0); await act(async () => { wrapper - .find('Radio') - .at(0) + .find('td#check-action-item-1') + .find('input') .invoke('onChange')(true); }); wrapper.update(); expect( wrapper - .find('Radio') - .at(0) - .prop('isChecked') + .find('td#check-action-item-1') + .find('input') + .prop('checked') ).toBe(true); expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe( false @@ -168,8 +169,7 @@ describe('', () => { await act(async () => { wrapper.find('Button[children="OK"]').simulate('click'); }); - // expect(wrapper.debug()).toBe(false); - // wrapper.find('Button[children="OK"]').simulate('click'); + expect(onSubmit).toHaveBeenCalledWith( expect.objectContaining({ credential: selectedCredential, @@ -218,14 +218,16 @@ describe('', () => { expect(steps[0].name).toEqual('Credential'); expect(steps[1].name).toEqual('Metadata'); }); - test('credentials step renders correctly', () => { + test('credentials step renders correctly', async () => { + await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0); + expect(wrapper.find('CredentialsStep').length).toBe(1); - expect(wrapper.find('DataListItem').length).toBe(3); + expect(wrapper.find('CheckboxListItem').length).toBe(3); expect( wrapper - .find('Radio') - .at(0) - .prop('isChecked') + .find('td#check-action-item-1') + .find('input') + .prop('checked') ).toBe(true); expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe( false diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialsStep.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialsStep.jsx index 93173a37f9..ae8c9d1e63 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialsStep.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialPlugins/CredentialPluginPrompt/CredentialsStep.jsx @@ -7,9 +7,12 @@ import { CredentialsAPI } from '../../../../../api'; import CheckboxListItem from '../../../../../components/CheckboxListItem'; import ContentError from '../../../../../components/ContentError'; import DataListToolbar from '../../../../../components/DataListToolbar'; -import PaginatedDataList from '../../../../../components/PaginatedDataList'; import { getQSConfig, parseQueryString } from '../../../../../util/qs'; import useRequest from '../../../../../util/useRequest'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../../../components/PaginatedTable'; const QS_CONFIG = getQSConfig('credential', { page: 1, @@ -59,15 +62,20 @@ function CredentialsStep() { } return ( - selectedCredentialHelper.setValue(row)} qsConfig={QS_CONFIG} - renderItem={credential => ( + headerRow={ + + {t`Name`} + + } + renderRow={(credential, index) => ( diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx index c9b51236d6..1885a52219 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeModal.test.jsx @@ -253,10 +253,6 @@ describe('NodeModal', () => { }); await waitForElement(wrapper, 'PFWizard'); }); - afterEach(() => { - // jest.clearAllMocks(); - // onSave.mockClear(); - }); test('Can successfully create a new job template node', async () => { act(() => { @@ -268,7 +264,10 @@ describe('NodeModal', () => { }); wrapper.update(); await act(async () => { - wrapper.find('Radio').simulate('click'); + wrapper + .find('td#check-action-item-1') + .find('input') + .prop('onChange')(true); }); wrapper.update(); await act(async () => { @@ -333,8 +332,12 @@ describe('NodeModal', () => { wrapper.find('AnsibleSelect').prop('onChange')(null, 'project'); }); wrapper.update(); + await act(async () => { - wrapper.find('Radio').simulate('click'); + wrapper + .find('td#check-action-item-1') + .find('input') + .prop('onChange')(true); }); wrapper.update(); await act(async () => { @@ -370,7 +373,10 @@ describe('NodeModal', () => { }); wrapper.update(); await act(async () => { - wrapper.find('Radio').simulate('click'); + wrapper + .find('td#check-action-item-1') + .find('input') + .prop('onChange')(true); }); wrapper.update(); await act(async () => { @@ -405,7 +411,12 @@ describe('NodeModal', () => { ); }); wrapper.update(); - await act(async () => wrapper.find('Radio').simulate('click')); + await act(async () => + wrapper + .find('td#check-action-item-1') + .find('input') + .prop('onChange')(true) + ); wrapper.update(); await act(async () => { @@ -659,7 +670,10 @@ describe('Edit existing node', () => { 'workflow_job_template' ); await act(async () => { - newWrapper.find('Radio').simulate('click'); + newWrapper + .find('td#check-action-item-1') + .find('input') + .prop('onChange')(); newWrapper.update(); }); newWrapper.update(); diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.jsx index fb27d2521a..34df62f4fa 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.jsx @@ -6,9 +6,12 @@ import { func, shape } from 'prop-types'; import { InventorySourcesAPI } from '../../../../../../api'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import useRequest from '../../../../../../util/useRequest'; -import PaginatedDataList from '../../../../../../components/PaginatedDataList'; import DataListToolbar from '../../../../../../components/DataListToolbar'; import CheckboxListItem from '../../../../../../components/CheckboxListItem'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../../../../components/PaginatedTable'; const QS_CONFIG = getQSConfig('inventory-sources', { page: 1, @@ -55,16 +58,21 @@ function InventorySourcesList({ nodeResource, onUpdateNodeResource }) { }, [fetchInventorySources]); return ( - onUpdateNodeResource(row)} qsConfig={QS_CONFIG} showPageSizeOptions={false} - renderItem={item => ( + headerRow={ + + {t`Name`} + + } + renderRow={(item, index) => ( diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.test.jsx index ad6fd57211..e5237734b0 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/InventorySourcesList.test.jsx @@ -66,7 +66,7 @@ describe('InventorySourcesList', () => { ).toBe(false); wrapper .find('CheckboxListItem[name="Test Inventory Source 2"]') - .simulate('click'); + .prop('onSelect')(); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 2, name: 'Test Inventory Source 2', diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.jsx index ede270eee1..7dd74221ea 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.jsx @@ -6,9 +6,12 @@ import { func, shape } from 'prop-types'; import { JobTemplatesAPI } from '../../../../../../api'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import useRequest from '../../../../../../util/useRequest'; -import PaginatedDataList from '../../../../../../components/PaginatedDataList'; import DataListToolbar from '../../../../../../components/DataListToolbar'; import CheckboxListItem from '../../../../../../components/CheckboxListItem'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../../../../components/PaginatedTable'; const QS_CONFIG = getQSConfig('job-templates', { page: 1, @@ -57,15 +60,20 @@ function JobTemplatesList({ nodeResource, onUpdateNodeResource }) { }, [fetchJobTemplates]); return ( - onUpdateNodeResource(row)} qsConfig={QS_CONFIG} - renderItem={item => ( + headerRow={ + + {t`Name`} + + } + renderRow={(item, index) => ( diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.test.jsx index 58606c2e2c..b66a6b1c38 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/JobTemplatesList.test.jsx @@ -61,7 +61,6 @@ describe('JobTemplatesList', () => { ); }); wrapper.update(); - // expect(wrapper.debug()).toBe(false); expect( wrapper.find('CheckboxListItem[name="Test Job Template"]').props() .isSelected @@ -72,7 +71,7 @@ describe('JobTemplatesList', () => { ).toBe(false); wrapper .find('CheckboxListItem[name="Test Job Template 2"]') - .simulate('click'); + .prop('onSelect')(); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 2, name: 'Test Job Template 2', diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.jsx index 73d79b3bb3..1c32d24398 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.jsx @@ -6,9 +6,12 @@ import { func, shape } from 'prop-types'; import { ProjectsAPI } from '../../../../../../api'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import useRequest from '../../../../../../util/useRequest'; -import PaginatedDataList from '../../../../../../components/PaginatedDataList'; import DataListToolbar from '../../../../../../components/DataListToolbar'; import CheckboxListItem from '../../../../../../components/CheckboxListItem'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../../../../components/PaginatedTable'; const QS_CONFIG = getQSConfig('projects', { page: 1, @@ -55,15 +58,20 @@ function ProjectsList({ nodeResource, onUpdateNodeResource }) { }, [fetchProjects]); return ( - onUpdateNodeResource(row)} qsConfig={QS_CONFIG} - renderItem={item => ( + headerRow={ + + {t`Name`} + + } + renderRow={(item, index) => ( diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.test.jsx index 765a329d3d..a6761c999e 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/ProjectsList.test.jsx @@ -62,7 +62,7 @@ describe('ProjectsList', () => { expect( wrapper.find('CheckboxListItem[name="Test Project 2"]').props().isSelected ).toBe(false); - wrapper.find('CheckboxListItem[name="Test Project 2"]').simulate('click'); + wrapper.find('CheckboxListItem[name="Test Project 2"]').prop('onSelect')(); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 2, name: 'Test Project 2', diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.jsx index 56a6642c28..f3a3569a2f 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.jsx @@ -6,9 +6,12 @@ import { func, shape } from 'prop-types'; import { WorkflowJobTemplatesAPI } from '../../../../../../api'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import useRequest from '../../../../../../util/useRequest'; -import PaginatedDataList from '../../../../../../components/PaginatedDataList'; import DataListToolbar from '../../../../../../components/DataListToolbar'; import CheckboxListItem from '../../../../../../components/CheckboxListItem'; +import PaginatedTable, { + HeaderCell, + HeaderRow, +} from '../../../../../../components/PaginatedTable'; const QS_CONFIG = getQSConfig('workflow-job-templates', { page: 1, @@ -62,15 +65,20 @@ function WorkflowJobTemplatesList({ nodeResource, onUpdateNodeResource }) { }, [fetchWorkflowJobTemplates]); return ( - onUpdateNodeResource(row)} qsConfig={QS_CONFIG} - renderItem={item => ( + headerRow={ + + {t`Name`} + + } + renderRow={(item, index) => ( diff --git a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.test.jsx b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.test.jsx index 121c62cce6..a844f56a11 100644 --- a/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.test.jsx +++ b/awx/ui_next/src/screens/Template/WorkflowJobTemplateVisualizer/Modals/NodeModals/NodeTypeStep/WorkflowJobTemplatesList.test.jsx @@ -68,7 +68,7 @@ describe('WorkflowJobTemplatesList', () => { ).toBe(false); wrapper .find('CheckboxListItem[name="Test Workflow Job Template 2"]') - .simulate('click'); + .prop('onSelect')(); expect(onUpdateNodeResource).toHaveBeenCalledWith({ id: 2, name: 'Test Workflow Job Template 2', From 0a276a6276ee8f4866aa56fab95028f7eeedc079 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 25 May 2021 15:21:01 -0400 Subject: [PATCH 2/2] resolves some poor styling on some lists --- .../components/AddRole/SelectResourceStep.jsx | 17 ++++++++++++++--- .../CheckboxListItem/CheckboxListItem.jsx | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx b/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx index 3a0ec2c5fe..7489b707a8 100644 --- a/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx +++ b/awx/ui_next/src/components/AddRole/SelectResourceStep.jsx @@ -5,11 +5,11 @@ import { t } from '@lingui/macro'; import useRequest from '../../util/useRequest'; import { SearchColumns, SortColumns } from '../../types'; -import PaginatedDataList from '../PaginatedDataList'; import DataListToolbar from '../DataListToolbar'; import CheckboxListItem from '../CheckboxListItem'; import SelectedList from '../SelectedList'; import { getQSConfig, parseQueryString } from '../../util/qs'; +import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable'; const QS_Config = sortColumns => { return getQSConfig('resource', { @@ -86,7 +86,8 @@ function SelectResourceStep({ selected={selectedResourceRows} /> )} - ( + headerRow={ + + {sortColumns.map(({ name, key }) => ( + {name} + ))} + + } + renderRow={(item, index) => ( i.id === item.id)} itemId={item.id} + item={item} + rowIndex={index} key={item.id} + columns={sortColumns} name={item[displayKey]} label={item[displayKey]} onSelect={() => onRowClick(item)} diff --git a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx index ac167e61de..c76a542ea2 100644 --- a/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx +++ b/awx/ui_next/src/components/CheckboxListItem/CheckboxListItem.jsx @@ -13,6 +13,8 @@ const CheckboxListItem = ({ onDeselect, rowIndex, onSelect, + columns, + item, }) => { return ( @@ -28,9 +30,18 @@ const CheckboxListItem = ({ name={name} dataLabel={t`Selected`} /> - - {label} - + + {columns?.length > 0 ? ( + columns.map(col => ( + + {item[col.key]} + + )) + ) : ( + + {label} + + )} ); };