Merge pull request #10180 from AlexSCorey/10162-ConvertOptionsList

Converts Options lists and other modal lists to tables

SUMMARY
This addresses #10162.  Note this issue I found while working on this #10181
Kicked Off E2E
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

UI

AWX VERSION
ADDITIONAL INFORMATION

Reviewed-by: Jake McDermott <yo@jakemcdermott.me>
Reviewed-by: Keith Grant <keithjgrant@gmail.com>
Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
softwarefactory-project-zuul[bot]
2021-05-26 15:11:46 +00:00
committed by GitHub
24 changed files with 212 additions and 192 deletions

View File

@@ -206,7 +206,8 @@ describe('<AdHocCommands />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
@@ -224,7 +225,8 @@ describe('<AdHocCommands />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-4"]') .find('td#check-action-item-4')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
@@ -373,7 +375,8 @@ describe('<AdHocCommands />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,
@@ -395,7 +398,8 @@ describe('<AdHocCommands />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-4"]') .find('td#check-action-item-4')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,

View File

@@ -153,7 +153,8 @@ describe('<AdHocCommandsWizard/>', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
@@ -178,7 +179,8 @@ describe('<AdHocCommandsWizard/>', () => {
expect(wrapper.find('Button[type="submit"]').prop('isDisabled')).toBe(true); expect(wrapper.find('Button[type="submit"]').prop('isDisabled')).toBe(true);
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });

View File

@@ -96,12 +96,12 @@ describe('<_AddResourceRole />', () => {
// Step 2 // Step 2
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
act(() => act(() =>
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true)
); );
wrapper.update(); wrapper.update();
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( expect(
true wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected')
); ).toBe(true);
act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); act(() => wrapper.find('Button[type="submit"]').prop('onClick')());
wrapper.update(); wrapper.update();
@@ -162,12 +162,12 @@ describe('<_AddResourceRole />', () => {
// Step 2 // Step 2
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
act(() => act(() =>
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true)
); );
wrapper.update(); wrapper.update();
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( expect(
true wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected')
); ).toBe(true);
act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); act(() => wrapper.find('Button[type="submit"]').prop('onClick')());
wrapper.update(); wrapper.update();
@@ -214,12 +214,12 @@ describe('<_AddResourceRole />', () => {
// Step 2 // Step 2
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
act(() => act(() =>
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true)
); );
wrapper.update(); wrapper.update();
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( expect(
true wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected')
); ).toBe(true);
await act(async () => await act(async () =>
wrapper.find('PFWizard').prop('onGoToStep')({ id: 1 }) wrapper.find('PFWizard').prop('onGoToStep')({ id: 1 })
); );
@@ -280,12 +280,12 @@ describe('<_AddResourceRole />', () => {
// Step 2 // Step 2
await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0); await waitForElement(wrapper, 'EmptyStateBody', el => el.length === 0);
act(() => act(() =>
wrapper.find('DataListCheck[name="foo"]').invoke('onChange')(true) wrapper.find('CheckboxListItem[name="foo"]').invoke('onSelect')(true)
); );
wrapper.update(); wrapper.update();
expect(wrapper.find('DataListCheck[name="foo"]').prop('checked')).toBe( expect(
true wrapper.find('CheckboxListItem[name="foo"]').prop('isSelected')
); ).toBe(true);
act(() => wrapper.find('Button[type="submit"]').prop('onClick')()); act(() => wrapper.find('Button[type="submit"]').prop('onClick')());
wrapper.update(); wrapper.update();

View File

@@ -5,11 +5,11 @@ import { t } from '@lingui/macro';
import useRequest from '../../util/useRequest'; import useRequest from '../../util/useRequest';
import { SearchColumns, SortColumns } from '../../types'; import { SearchColumns, SortColumns } from '../../types';
import PaginatedDataList from '../PaginatedDataList';
import DataListToolbar from '../DataListToolbar'; import DataListToolbar from '../DataListToolbar';
import CheckboxListItem from '../CheckboxListItem'; import CheckboxListItem from '../CheckboxListItem';
import SelectedList from '../SelectedList'; import SelectedList from '../SelectedList';
import { getQSConfig, parseQueryString } from '../../util/qs'; import { getQSConfig, parseQueryString } from '../../util/qs';
import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable';
const QS_Config = sortColumns => { const QS_Config = sortColumns => {
return getQSConfig('resource', { return getQSConfig('resource', {
@@ -86,7 +86,8 @@ function SelectResourceStep({
selected={selectedResourceRows} selected={selectedResourceRows}
/> />
)} )}
<PaginatedDataList
<PaginatedTable
hasContentLoading={isLoading} hasContentLoading={isLoading}
contentError={error} contentError={error}
items={resources} items={resources}
@@ -97,11 +98,21 @@ function SelectResourceStep({
toolbarSortColumns={sortColumns} toolbarSortColumns={sortColumns}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
renderItem={item => ( headerRow={
<HeaderRow qsConfig={QS_Config(sortColumns)}>
{sortColumns.map(({ name, key }) => (
<HeaderCell sortKey={key}>{name}</HeaderCell>
))}
</HeaderRow>
}
renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
isSelected={selectedResourceRows.some(i => i.id === item.id)} isSelected={selectedResourceRows.some(i => i.id === item.id)}
itemId={item.id} itemId={item.id}
item={item}
rowIndex={index}
key={item.id} key={item.id}
columns={sortColumns}
name={item[displayKey]} name={item[displayKey]}
label={item[displayKey]} label={item[displayKey]}
onSelect={() => onRowClick(item)} onSelect={() => onRowClick(item)}

View File

@@ -1,34 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import styled from 'styled-components'; import { t } from '@lingui/macro';
import { import { Td, Tr } from '@patternfly/react-table';
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;
}
`;
const CheckboxListItem = ({ const CheckboxListItem = ({
isDisabled = false, isDisabled = false,
@@ -38,43 +11,38 @@ const CheckboxListItem = ({
label, label,
name, name,
onDeselect, onDeselect,
rowIndex,
onSelect, onSelect,
columns,
item,
}) => { }) => {
const CheckboxRadio = isRadio ? Radio : DataListCheck;
return ( return (
<DataListItem <Tr ouiaId={`list-item-${itemId}`} id={`list-item-${itemId}`}>
key={itemId} <Td
aria-labelledby={`check-action-item-${itemId}`} id={`check-action-item-${itemId}`}
id={`${itemId}`} select={{
> rowIndex,
<DataListItemRow> isSelected,
<CheckboxRadio onSelect: isSelected ? onDeselect : onSelect,
aria-label={`check-action-item-${itemId}`} disable: isDisabled,
aria-labelledby={`check-action-item-${itemId}`} variant: isRadio ? 'radio' : 'checkbox',
checked={isSelected} }}
isDisabled={isDisabled} name={name}
id={`selected-${itemId}`} dataLabel={t`Selected`}
isChecked={isSelected} />
name={name}
onChange={isSelected ? onDeselect : onSelect} {columns?.length > 0 ? (
value={itemId} columns.map(col => (
/> <Td aria-label={col.name} dataLabel={col.key}>
<DataListItemCells {item[col.key]}
dataListCells={[ </Td>
<DataListCell key="name"> ))
<Label ) : (
id={`check-action-item-${itemId}`} <Td aria-labelledby={itemId} dataLabel={label}>
htmlFor={`selected-${itemId}`} <b>{label}</b>
className="check-action-item" </Td>
isDisabled={isDisabled} )}
> </Tr>
<b>{label}</b>
</Label>
</DataListCell>,
]}
/>
</DataListItemRow>
</DataListItem>
); );
}; };

View File

@@ -181,7 +181,8 @@ describe('CredentialsStep', () => {
expect(wrapper.find('Alert').length).toBe(0); expect(wrapper.find('Alert').length).toBe(0);
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
wrapper.update(); wrapper.update();
@@ -241,7 +242,8 @@ describe('CredentialsStep', () => {
).toBe(true); ).toBe(true);
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-5"]') .find('td#check-action-item-5')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
wrapper.update(); wrapper.update();
@@ -317,7 +319,8 @@ describe('CredentialsStep', () => {
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-33"]') .find('td#check-action-item-33')
.find('input')
.simulate('change', { target: { checked: true } }); .simulate('change', { target: { checked: true } });
}); });
wrapper.update(); wrapper.update();

View File

@@ -12,10 +12,10 @@ import styled from 'styled-components';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import SelectedList from '../SelectedList'; import SelectedList from '../SelectedList';
import PaginatedDataList from '../PaginatedDataList';
import CheckboxListItem from '../CheckboxListItem'; import CheckboxListItem from '../CheckboxListItem';
import DataListToolbar from '../DataListToolbar'; import DataListToolbar from '../DataListToolbar';
import { QSConfig, SearchColumns, SortColumns } from '../../types'; import { QSConfig, SearchColumns, SortColumns } from '../../types';
import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable';
const ModalList = styled.div` const ModalList = styled.div`
.pf-c-toolbar__content { .pf-c-toolbar__content {
@@ -56,7 +56,7 @@ function OptionsList({
displayKey={displayKey} displayKey={displayKey}
/> />
)} )}
<PaginatedDataList <PaginatedTable
contentError={contentError} contentError={contentError}
items={options} items={options}
itemCount={optionCount} itemCount={optionCount}
@@ -67,10 +67,16 @@ function OptionsList({
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
hasContentLoading={isLoading} hasContentLoading={isLoading}
headerRow={
<HeaderRow qsConfig={qsConfig}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
onRowClick={selectItem} onRowClick={selectItem}
renderItem={item => ( renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
key={item.id} key={item.id}
rowIndex={index}
itemId={item.id} itemId={item.id}
name={multiple ? item[displayKey] : name} name={multiple ? item[displayKey] : name}
label={item[displayKey]} label={item[displayKey]}

View File

@@ -27,7 +27,7 @@ describe('<OptionsList />', () => {
name="Item" name="Item"
/> />
); );
expect(wrapper.find('PaginatedDataList').prop('items')).toEqual(options); expect(wrapper.find('PaginatedTable').prop('items')).toEqual(options);
expect(wrapper.find('SelectedList')).toHaveLength(0); expect(wrapper.find('SelectedList')).toHaveLength(0);
}); });

View File

@@ -35,7 +35,6 @@ function PaginatedTable({
toolbarRelatedSearchableKeys, toolbarRelatedSearchableKeys,
pluralizedItemName, pluralizedItemName,
showPageSizeOptions, showPageSizeOptions,
renderToolbar, renderToolbar,
emptyContentMessage, emptyContentMessage,
ouiaId, ouiaId,

View File

@@ -339,7 +339,8 @@ describe('<ScheduleAdd />', () => {
).toBe(true); ).toBe(true);
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,
@@ -349,7 +350,8 @@ describe('<ScheduleAdd />', () => {
wrapper.update(); wrapper.update();
expect( expect(
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.prop('checked') .prop('checked')
).toBe(true); ).toBe(true);
await act(async () => await act(async () =>

View File

@@ -471,7 +471,8 @@ describe('<ScheduleEdit />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,
@@ -482,7 +483,8 @@ describe('<ScheduleEdit />', () => {
expect( expect(
wrapper wrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.prop('checked') .prop('checked')
).toBe(true); ).toBe(true);
await act(async () => await act(async () =>
@@ -502,13 +504,15 @@ describe('<ScheduleEdit />', () => {
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.simulate('click'); .simulate('click');
}); });
wrapper.update(); wrapper.update();
expect( expect(
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.prop('checked') .prop('checked')
).toBe(true); ).toBe(true);
await act(async () => await act(async () =>
@@ -599,7 +603,8 @@ describe('<ScheduleEdit />', () => {
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,
@@ -610,7 +615,8 @@ describe('<ScheduleEdit />', () => {
expect( expect(
wrapper wrapper
.find('input[aria-labelledby="check-action-item-2"]') .find('td#check-action-item-2')
.find('input')
.prop('checked') .prop('checked')
).toBe(true); ).toBe(true);
await act(async () => await act(async () =>

View File

@@ -330,7 +330,8 @@ describe('<ScheduleForm />', () => {
).toBe(true); ).toBe(true);
await act(async () => { await act(async () => {
promptWrapper promptWrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.simulate('change', { .simulate('change', {
target: { target: {
checked: true, checked: true,
@@ -340,7 +341,8 @@ describe('<ScheduleForm />', () => {
promptWrapper.update(); promptWrapper.update();
expect( expect(
promptWrapper promptWrapper
.find('input[aria-labelledby="check-action-item-1"]') .find('td#check-action-item-1')
.find('input')
.prop('checked') .prop('checked')
).toBe(true); ).toBe(true);
await act(async () => await act(async () =>

View File

@@ -19,15 +19,7 @@ import { CredentialPluginPrompt } from './CredentialPluginPrompt';
import CredentialPluginSelected from './CredentialPluginSelected'; import CredentialPluginSelected from './CredentialPluginSelected';
function CredentialPluginInput(props) { function CredentialPluginInput(props) {
const { const { children, isDisabled, isRequired, validated, fieldOptions } = props;
children,
isDisabled,
isRequired,
validated,
fieldOptions,
} = props;
const [showPluginWizard, setShowPluginWizard] = useState(false); const [showPluginWizard, setShowPluginWizard] = useState(false);
const [inputField, meta, helpers] = useField(`inputs.${fieldOptions.id}`); const [inputField, meta, helpers] = useField(`inputs.${fieldOptions.id}`);
const [passwordPromptField] = useField(`passwordPrompts.${fieldOptions.id}`); const [passwordPromptField] = useField(`passwordPrompts.${fieldOptions.id}`);

View File

@@ -114,7 +114,7 @@ describe('<CredentialPluginPrompt />', () => {
test('credentials step renders correctly', () => { test('credentials step renders correctly', () => {
expect(wrapper.find('CredentialsStep').length).toBe(1); expect(wrapper.find('CredentialsStep').length).toBe(1);
expect(wrapper.find('DataListItem').length).toBe(3); expect(wrapper.find('CheckboxListItem').length).toBe(3);
expect( expect(
wrapper.find('Radio').filterWhere(radio => radio.isChecked).length wrapper.find('Radio').filterWhere(radio => radio.isChecked).length
).toBe(0); ).toBe(0);
@@ -129,18 +129,19 @@ describe('<CredentialPluginPrompt />', () => {
expect(onClose).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledTimes(1);
}); });
test('clicking credential row enables next button', async () => { test('clicking credential row enables next button', async () => {
await waitForElement(wrapper, 'CheckboxListItem', el => el.length > 0);
await act(async () => { await act(async () => {
wrapper wrapper
.find('Radio') .find('td#check-action-item-1')
.at(0) .find('input')
.invoke('onChange')(true); .invoke('onChange')(true);
}); });
wrapper.update(); wrapper.update();
expect( expect(
wrapper wrapper
.find('Radio') .find('td#check-action-item-1')
.at(0) .find('input')
.prop('isChecked') .prop('checked')
).toBe(true); ).toBe(true);
expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe( expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe(
false false
@@ -168,8 +169,7 @@ describe('<CredentialPluginPrompt />', () => {
await act(async () => { await act(async () => {
wrapper.find('Button[children="OK"]').simulate('click'); wrapper.find('Button[children="OK"]').simulate('click');
}); });
// expect(wrapper.debug()).toBe(false);
// wrapper.find('Button[children="OK"]').simulate('click');
expect(onSubmit).toHaveBeenCalledWith( expect(onSubmit).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
credential: selectedCredential, credential: selectedCredential,
@@ -218,14 +218,16 @@ describe('<CredentialPluginPrompt />', () => {
expect(steps[0].name).toEqual('Credential'); expect(steps[0].name).toEqual('Credential');
expect(steps[1].name).toEqual('Metadata'); 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('CredentialsStep').length).toBe(1);
expect(wrapper.find('DataListItem').length).toBe(3); expect(wrapper.find('CheckboxListItem').length).toBe(3);
expect( expect(
wrapper wrapper
.find('Radio') .find('td#check-action-item-1')
.at(0) .find('input')
.prop('isChecked') .prop('checked')
).toBe(true); ).toBe(true);
expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe( expect(wrapper.find('Button[children="Next"]').prop('isDisabled')).toBe(
false false

View File

@@ -7,9 +7,12 @@ import { CredentialsAPI } from '../../../../../api';
import CheckboxListItem from '../../../../../components/CheckboxListItem'; import CheckboxListItem from '../../../../../components/CheckboxListItem';
import ContentError from '../../../../../components/ContentError'; import ContentError from '../../../../../components/ContentError';
import DataListToolbar from '../../../../../components/DataListToolbar'; import DataListToolbar from '../../../../../components/DataListToolbar';
import PaginatedDataList from '../../../../../components/PaginatedDataList';
import { getQSConfig, parseQueryString } from '../../../../../util/qs'; import { getQSConfig, parseQueryString } from '../../../../../util/qs';
import useRequest from '../../../../../util/useRequest'; import useRequest from '../../../../../util/useRequest';
import PaginatedTable, {
HeaderCell,
HeaderRow,
} from '../../../../../components/PaginatedTable';
const QS_CONFIG = getQSConfig('credential', { const QS_CONFIG = getQSConfig('credential', {
page: 1, page: 1,
@@ -59,15 +62,20 @@ function CredentialsStep() {
} }
return ( return (
<PaginatedDataList <PaginatedTable
contentError={credentialsError} contentError={credentialsError}
hasContentLoading={isCredentialsLoading} hasContentLoading={isCredentialsLoading}
itemCount={count} itemCount={count}
items={credentials} items={credentials}
onRowClick={row => selectedCredentialHelper.setValue(row)}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
renderItem={credential => ( headerRow={
<HeaderRow isExpandable={false} qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
renderRow={(credential, index) => (
<CheckboxListItem <CheckboxListItem
rowIndex={index}
isSelected={selectedCredential?.value?.id === credential.id} isSelected={selectedCredential?.value?.id === credential.id}
itemId={credential.id} itemId={credential.id}
key={credential.id} key={credential.id}
@@ -95,12 +103,6 @@ function CredentialsStep() {
key: 'modified_by__username__icontains', key: 'modified_by__username__icontains',
}, },
]} ]}
toolbarSortColumns={[
{
name: t`Name`,
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
/> />

View File

@@ -253,10 +253,6 @@ describe('NodeModal', () => {
}); });
await waitForElement(wrapper, 'PFWizard'); await waitForElement(wrapper, 'PFWizard');
}); });
afterEach(() => {
// jest.clearAllMocks();
// onSave.mockClear();
});
test('Can successfully create a new job template node', async () => { test('Can successfully create a new job template node', async () => {
act(() => { act(() => {
@@ -268,7 +264,10 @@ describe('NodeModal', () => {
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
wrapper.find('Radio').simulate('click'); wrapper
.find('td#check-action-item-1')
.find('input')
.prop('onChange')(true);
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
@@ -333,8 +332,12 @@ describe('NodeModal', () => {
wrapper.find('AnsibleSelect').prop('onChange')(null, 'project'); wrapper.find('AnsibleSelect').prop('onChange')(null, 'project');
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
wrapper.find('Radio').simulate('click'); wrapper
.find('td#check-action-item-1')
.find('input')
.prop('onChange')(true);
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
@@ -370,7 +373,10 @@ describe('NodeModal', () => {
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
wrapper.find('Radio').simulate('click'); wrapper
.find('td#check-action-item-1')
.find('input')
.prop('onChange')(true);
}); });
wrapper.update(); wrapper.update();
await act(async () => { await act(async () => {
@@ -405,7 +411,12 @@ describe('NodeModal', () => {
); );
}); });
wrapper.update(); 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(); wrapper.update();
await act(async () => { await act(async () => {
@@ -659,7 +670,10 @@ describe('Edit existing node', () => {
'workflow_job_template' 'workflow_job_template'
); );
await act(async () => { await act(async () => {
newWrapper.find('Radio').simulate('click'); newWrapper
.find('td#check-action-item-1')
.find('input')
.prop('onChange')();
newWrapper.update(); newWrapper.update();
}); });
newWrapper.update(); newWrapper.update();

View File

@@ -6,9 +6,12 @@ import { func, shape } from 'prop-types';
import { InventorySourcesAPI } from '../../../../../../api'; import { InventorySourcesAPI } from '../../../../../../api';
import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs';
import useRequest from '../../../../../../util/useRequest'; import useRequest from '../../../../../../util/useRequest';
import PaginatedDataList from '../../../../../../components/PaginatedDataList';
import DataListToolbar from '../../../../../../components/DataListToolbar'; import DataListToolbar from '../../../../../../components/DataListToolbar';
import CheckboxListItem from '../../../../../../components/CheckboxListItem'; import CheckboxListItem from '../../../../../../components/CheckboxListItem';
import PaginatedTable, {
HeaderCell,
HeaderRow,
} from '../../../../../../components/PaginatedTable';
const QS_CONFIG = getQSConfig('inventory-sources', { const QS_CONFIG = getQSConfig('inventory-sources', {
page: 1, page: 1,
@@ -55,16 +58,21 @@ function InventorySourcesList({ nodeResource, onUpdateNodeResource }) {
}, [fetchInventorySources]); }, [fetchInventorySources]);
return ( return (
<PaginatedDataList <PaginatedTable
contentError={error} contentError={error}
hasContentLoading={isLoading} hasContentLoading={isLoading}
itemCount={count} itemCount={count}
items={inventorySources} items={inventorySources}
onRowClick={row => onUpdateNodeResource(row)}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
showPageSizeOptions={false} showPageSizeOptions={false}
renderItem={item => ( headerRow={
<HeaderRow isExpandable={false} qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
rowIndex={index}
isSelected={!!(nodeResource && nodeResource.id === item.id)} isSelected={!!(nodeResource && nodeResource.id === item.id)}
itemId={item.id} itemId={item.id}
key={item.id} key={item.id}
@@ -99,12 +107,6 @@ function InventorySourcesList({ nodeResource, onUpdateNodeResource }) {
], ],
}, },
]} ]}
toolbarSortColumns={[
{
name: t`Name`,
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
/> />

View File

@@ -66,7 +66,7 @@ describe('InventorySourcesList', () => {
).toBe(false); ).toBe(false);
wrapper wrapper
.find('CheckboxListItem[name="Test Inventory Source 2"]') .find('CheckboxListItem[name="Test Inventory Source 2"]')
.simulate('click'); .prop('onSelect')();
expect(onUpdateNodeResource).toHaveBeenCalledWith({ expect(onUpdateNodeResource).toHaveBeenCalledWith({
id: 2, id: 2,
name: 'Test Inventory Source 2', name: 'Test Inventory Source 2',

View File

@@ -6,9 +6,12 @@ import { func, shape } from 'prop-types';
import { JobTemplatesAPI } from '../../../../../../api'; import { JobTemplatesAPI } from '../../../../../../api';
import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs';
import useRequest from '../../../../../../util/useRequest'; import useRequest from '../../../../../../util/useRequest';
import PaginatedDataList from '../../../../../../components/PaginatedDataList';
import DataListToolbar from '../../../../../../components/DataListToolbar'; import DataListToolbar from '../../../../../../components/DataListToolbar';
import CheckboxListItem from '../../../../../../components/CheckboxListItem'; import CheckboxListItem from '../../../../../../components/CheckboxListItem';
import PaginatedTable, {
HeaderCell,
HeaderRow,
} from '../../../../../../components/PaginatedTable';
const QS_CONFIG = getQSConfig('job-templates', { const QS_CONFIG = getQSConfig('job-templates', {
page: 1, page: 1,
@@ -57,15 +60,20 @@ function JobTemplatesList({ nodeResource, onUpdateNodeResource }) {
}, [fetchJobTemplates]); }, [fetchJobTemplates]);
return ( return (
<PaginatedDataList <PaginatedTable
contentError={error} contentError={error}
hasContentLoading={isLoading} hasContentLoading={isLoading}
itemCount={count} itemCount={count}
items={jobTemplates} items={jobTemplates}
onRowClick={row => onUpdateNodeResource(row)}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
renderItem={item => ( headerRow={
<HeaderRow isExpandable={false} qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
rowIndex={index}
isSelected={!!(nodeResource && nodeResource.id === item.id)} isSelected={!!(nodeResource && nodeResource.id === item.id)}
itemId={item.id} itemId={item.id}
key={`${item.id}-listItem`} key={`${item.id}-listItem`}
@@ -97,12 +105,6 @@ function JobTemplatesList({ nodeResource, onUpdateNodeResource }) {
key: 'modified_by__username__icontains', key: 'modified_by__username__icontains',
}, },
]} ]}
toolbarSortColumns={[
{
name: t`Name`,
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
/> />

View File

@@ -61,7 +61,6 @@ describe('JobTemplatesList', () => {
); );
}); });
wrapper.update(); wrapper.update();
// expect(wrapper.debug()).toBe(false);
expect( expect(
wrapper.find('CheckboxListItem[name="Test Job Template"]').props() wrapper.find('CheckboxListItem[name="Test Job Template"]').props()
.isSelected .isSelected
@@ -72,7 +71,7 @@ describe('JobTemplatesList', () => {
).toBe(false); ).toBe(false);
wrapper wrapper
.find('CheckboxListItem[name="Test Job Template 2"]') .find('CheckboxListItem[name="Test Job Template 2"]')
.simulate('click'); .prop('onSelect')();
expect(onUpdateNodeResource).toHaveBeenCalledWith({ expect(onUpdateNodeResource).toHaveBeenCalledWith({
id: 2, id: 2,
name: 'Test Job Template 2', name: 'Test Job Template 2',

View File

@@ -6,9 +6,12 @@ import { func, shape } from 'prop-types';
import { ProjectsAPI } from '../../../../../../api'; import { ProjectsAPI } from '../../../../../../api';
import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs';
import useRequest from '../../../../../../util/useRequest'; import useRequest from '../../../../../../util/useRequest';
import PaginatedDataList from '../../../../../../components/PaginatedDataList';
import DataListToolbar from '../../../../../../components/DataListToolbar'; import DataListToolbar from '../../../../../../components/DataListToolbar';
import CheckboxListItem from '../../../../../../components/CheckboxListItem'; import CheckboxListItem from '../../../../../../components/CheckboxListItem';
import PaginatedTable, {
HeaderCell,
HeaderRow,
} from '../../../../../../components/PaginatedTable';
const QS_CONFIG = getQSConfig('projects', { const QS_CONFIG = getQSConfig('projects', {
page: 1, page: 1,
@@ -55,15 +58,20 @@ function ProjectsList({ nodeResource, onUpdateNodeResource }) {
}, [fetchProjects]); }, [fetchProjects]);
return ( return (
<PaginatedDataList <PaginatedTable
contentError={error} contentError={error}
hasContentLoading={isLoading} hasContentLoading={isLoading}
itemCount={count} itemCount={count}
items={projects} items={projects}
onRowClick={row => onUpdateNodeResource(row)}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
renderItem={item => ( headerRow={
<HeaderRow isExpandable={false} qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
rowIndex={index}
isSelected={!!(nodeResource && nodeResource.id === item.id)} isSelected={!!(nodeResource && nodeResource.id === item.id)}
itemId={item.id} itemId={item.id}
key={item.id} key={item.id}
@@ -106,12 +114,6 @@ function ProjectsList({ nodeResource, onUpdateNodeResource }) {
key: 'created_by__username__icontains', key: 'created_by__username__icontains',
}, },
]} ]}
toolbarSortColumns={[
{
name: t`Name`,
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
/> />

View File

@@ -62,7 +62,7 @@ describe('ProjectsList', () => {
expect( expect(
wrapper.find('CheckboxListItem[name="Test Project 2"]').props().isSelected wrapper.find('CheckboxListItem[name="Test Project 2"]').props().isSelected
).toBe(false); ).toBe(false);
wrapper.find('CheckboxListItem[name="Test Project 2"]').simulate('click'); wrapper.find('CheckboxListItem[name="Test Project 2"]').prop('onSelect')();
expect(onUpdateNodeResource).toHaveBeenCalledWith({ expect(onUpdateNodeResource).toHaveBeenCalledWith({
id: 2, id: 2,
name: 'Test Project 2', name: 'Test Project 2',

View File

@@ -6,9 +6,12 @@ import { func, shape } from 'prop-types';
import { WorkflowJobTemplatesAPI } from '../../../../../../api'; import { WorkflowJobTemplatesAPI } from '../../../../../../api';
import { getQSConfig, parseQueryString } from '../../../../../../util/qs'; import { getQSConfig, parseQueryString } from '../../../../../../util/qs';
import useRequest from '../../../../../../util/useRequest'; import useRequest from '../../../../../../util/useRequest';
import PaginatedDataList from '../../../../../../components/PaginatedDataList';
import DataListToolbar from '../../../../../../components/DataListToolbar'; import DataListToolbar from '../../../../../../components/DataListToolbar';
import CheckboxListItem from '../../../../../../components/CheckboxListItem'; import CheckboxListItem from '../../../../../../components/CheckboxListItem';
import PaginatedTable, {
HeaderCell,
HeaderRow,
} from '../../../../../../components/PaginatedTable';
const QS_CONFIG = getQSConfig('workflow-job-templates', { const QS_CONFIG = getQSConfig('workflow-job-templates', {
page: 1, page: 1,
@@ -62,15 +65,20 @@ function WorkflowJobTemplatesList({ nodeResource, onUpdateNodeResource }) {
}, [fetchWorkflowJobTemplates]); }, [fetchWorkflowJobTemplates]);
return ( return (
<PaginatedDataList <PaginatedTable
contentError={error} contentError={error}
hasContentLoading={isLoading} hasContentLoading={isLoading}
itemCount={count} itemCount={count}
items={workflowJobTemplates} items={workflowJobTemplates}
onRowClick={row => onUpdateNodeResource(row)}
qsConfig={QS_CONFIG} qsConfig={QS_CONFIG}
renderItem={item => ( headerRow={
<HeaderRow isExpandable={false} qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
</HeaderRow>
}
renderRow={(item, index) => (
<CheckboxListItem <CheckboxListItem
rowIndex={index}
isSelected={!!(nodeResource && nodeResource.id === item.id)} isSelected={!!(nodeResource && nodeResource.id === item.id)}
itemId={item.id} itemId={item.id}
key={item.id} key={item.id}
@@ -106,12 +114,6 @@ function WorkflowJobTemplatesList({ nodeResource, onUpdateNodeResource }) {
key: 'modified_by__username__icontains', key: 'modified_by__username__icontains',
}, },
]} ]}
toolbarSortColumns={[
{
name: t`Name`,
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys} toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys} toolbarRelatedSearchableKeys={relatedSearchableKeys}
/> />

View File

@@ -68,7 +68,7 @@ describe('WorkflowJobTemplatesList', () => {
).toBe(false); ).toBe(false);
wrapper wrapper
.find('CheckboxListItem[name="Test Workflow Job Template 2"]') .find('CheckboxListItem[name="Test Workflow Job Template 2"]')
.simulate('click'); .prop('onSelect')();
expect(onUpdateNodeResource).toHaveBeenCalledWith({ expect(onUpdateNodeResource).toHaveBeenCalledWith({
id: 2, id: 2,
name: 'Test Workflow Job Template 2', name: 'Test Workflow Job Template 2',