mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 03:10:42 -03:30
convert InstanceList to table
This commit is contained in:
parent
d3b20e6585
commit
8078daa733
@ -5,9 +5,11 @@ import { useLocation, useParams } from 'react-router-dom';
|
||||
import 'styled-components/macro';
|
||||
|
||||
import DataListToolbar from '../../../components/DataListToolbar';
|
||||
import PaginatedDataList, {
|
||||
ToolbarAddButton,
|
||||
} from '../../../components/PaginatedDataList';
|
||||
import PaginatedTable, {
|
||||
HeaderRow,
|
||||
HeaderCell,
|
||||
} from '../../../components/PaginatedTable';
|
||||
import { ToolbarAddButton } from '../../../components/PaginatedDataList';
|
||||
import DisassociateButton from '../../../components/DisassociateButton';
|
||||
import AssociateModal from '../../../components/AssociateModal';
|
||||
import AlertModal from '../../../components/AlertModal';
|
||||
@ -73,9 +75,13 @@ function InstanceList() {
|
||||
}
|
||||
);
|
||||
|
||||
const { selected, isAllSelected, handleSelect, setSelected } = useSelected(
|
||||
instances
|
||||
);
|
||||
const {
|
||||
selected,
|
||||
isAllSelected,
|
||||
handleSelect,
|
||||
clearSelected,
|
||||
selectAll,
|
||||
} = useSelected(instances);
|
||||
|
||||
useEffect(() => {
|
||||
fetchInstances();
|
||||
@ -116,7 +122,7 @@ function InstanceList() {
|
||||
|
||||
const handleDisassociate = async () => {
|
||||
await disassociateInstances();
|
||||
setSelected([]);
|
||||
clearSelected();
|
||||
};
|
||||
|
||||
const { error, dismissError } = useDismissableError(
|
||||
@ -140,14 +146,14 @@ function InstanceList() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaginatedDataList
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading || isDisassociateLoading}
|
||||
items={instances}
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Instances`}
|
||||
qsConfig={QS_CONFIG}
|
||||
onRowClick={handleSelect}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
@ -168,9 +174,7 @@ function InstanceList() {
|
||||
{...props}
|
||||
showSelectAll
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={isSelected =>
|
||||
setSelected(isSelected ? [...instances] : [])
|
||||
}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
@ -200,7 +204,18 @@ function InstanceList() {
|
||||
}
|
||||
/>
|
||||
)}
|
||||
renderItem={instance => (
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Type`}</HeaderCell>
|
||||
<HeaderCell>{t`Running Jobs`}</HeaderCell>
|
||||
<HeaderCell>{t`Total Jobs`}</HeaderCell>
|
||||
<HeaderCell>{t`Capacity Adjustment`}</HeaderCell>
|
||||
<HeaderCell>{t`Used Capacity`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(instance, index) => (
|
||||
<InstanceListItem
|
||||
key={instance.id}
|
||||
value={instance.hostname}
|
||||
@ -208,6 +223,7 @@ function InstanceList() {
|
||||
onSelect={() => handleSelect(instance)}
|
||||
isSelected={selected.some(row => row.id === instance.id)}
|
||||
fetchInstances={fetchInstances}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@ -4,19 +4,14 @@ import { t, Plural } from '@lingui/macro';
|
||||
import styled from 'styled-components';
|
||||
import 'styled-components/macro';
|
||||
import {
|
||||
Badge as PFBadge,
|
||||
Progress,
|
||||
ProgressMeasureLocation,
|
||||
ProgressSize,
|
||||
DataListAction as PFDataListAction,
|
||||
DataListCheck,
|
||||
DataListItem as PFDataListItem,
|
||||
DataListItemRow as PFDataListItemRow,
|
||||
DataListItemCells as PFDataListItemCells,
|
||||
Slider,
|
||||
} from '@patternfly/react-core';
|
||||
import { Tr, Td } from '@patternfly/react-table';
|
||||
|
||||
import _DataListCell from '../../../components/DataListCell';
|
||||
import { ActionsTd, ActionItem } from '../../../components/PaginatedTable';
|
||||
import InstanceToggle from '../../../components/InstanceToggle';
|
||||
import { Instance } from '../../../types';
|
||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||
@ -26,44 +21,10 @@ import { useConfig } from '../../../contexts/Config';
|
||||
import AlertModal from '../../../components/AlertModal';
|
||||
import ErrorDetail from '../../../components/ErrorDetail';
|
||||
|
||||
const DataListItem = styled(PFDataListItem)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const DataListItemRow = styled(PFDataListItemRow)`
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const DataListItemCells = styled(PFDataListItemCells)`
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const DataListAction = styled(PFDataListAction)`
|
||||
align-items: center;
|
||||
`;
|
||||
const Unavailable = styled.span`
|
||||
color: var(--pf-global--danger-color--200);
|
||||
`;
|
||||
|
||||
const DataListCell = styled(_DataListCell)`
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Badge = styled(PFBadge)`
|
||||
margin-left: 8px;
|
||||
`;
|
||||
|
||||
const ListGroup = styled.span`
|
||||
margin-left: 12px;
|
||||
|
||||
&:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const SliderHolder = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -86,7 +47,13 @@ function computeForks(memCapacity, cpuCapacity, selectedCapacityAdjustment) {
|
||||
);
|
||||
}
|
||||
|
||||
function InstanceListItem({ instance, isSelected, onSelect, fetchInstances }) {
|
||||
function InstanceListItem({
|
||||
instance,
|
||||
isSelected,
|
||||
onSelect,
|
||||
fetchInstances,
|
||||
rowIndex,
|
||||
}) {
|
||||
const { me = {} } = useConfig();
|
||||
const [forks, setForks] = useState(
|
||||
computeForks(
|
||||
@ -137,92 +104,64 @@ function InstanceListItem({ instance, isSelected, onSelect, fetchInstances }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<DataListItem
|
||||
aria-labelledby={labelId}
|
||||
id={`${instance.id}`}
|
||||
key={instance.id}
|
||||
>
|
||||
<DataListItemRow>
|
||||
<DataListCheck
|
||||
aria-labelledby={labelId}
|
||||
checked={isSelected}
|
||||
id={`instances-${instance.id}`}
|
||||
onChange={onSelect}
|
||||
/>
|
||||
|
||||
<DataListItemCells
|
||||
dataListCells={[
|
||||
<DataListCell key="name" aria-label={t`instance host name`}>
|
||||
<b>{instance.hostname}</b>
|
||||
</DataListCell>,
|
||||
<DataListCell key="type" aria-label={t`instance type`}>
|
||||
<b css="margin-right: 24px">{t`Type`}</b>
|
||||
<span id={labelId}>
|
||||
{instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
</span>
|
||||
</DataListCell>,
|
||||
<DataListCell
|
||||
key="related-field-counts"
|
||||
aria-label={t`instance counts`}
|
||||
width={3}
|
||||
>
|
||||
<ListGroup>
|
||||
<b>{t`Running jobs`}</b>
|
||||
<Badge isRead>{instance.jobs_running}</Badge>
|
||||
</ListGroup>
|
||||
<ListGroup>
|
||||
<b>{t`Total jobs`}</b>
|
||||
<Badge isRead>{instance.jobs_total}</Badge>
|
||||
</ListGroup>
|
||||
</DataListCell>,
|
||||
<DataListCell
|
||||
key="capacity-adjustment"
|
||||
aria-label={t`capacity adjustment`}
|
||||
width={4}
|
||||
>
|
||||
<SliderHolder data-cy="slider-holder">
|
||||
<div data-cy="cpu-capacity">{t`CPU ${instance.cpu_capacity}`}</div>
|
||||
<SliderForks data-cy="slider-forks">
|
||||
<div data-cy="number-forks">
|
||||
<Plural value={forks} one="# fork" other="# forks" />
|
||||
</div>
|
||||
<Slider
|
||||
areCustomStepsContinuous
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
value={instance.capacity_adjustment}
|
||||
onChange={handleChangeValue}
|
||||
isDisabled={!me?.is_superuser || !instance.enabled}
|
||||
data-cy="slider"
|
||||
/>
|
||||
</SliderForks>
|
||||
|
||||
<div data-cy="mem-capacity">{t`RAM ${instance.mem_capacity}`}</div>
|
||||
</SliderHolder>
|
||||
</DataListCell>,
|
||||
|
||||
<DataListCell
|
||||
key="capacity"
|
||||
aria-label={t`instance group used capacity`}
|
||||
>
|
||||
{usedCapacity(instance)}
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
<DataListAction
|
||||
aria-label={t`actions`}
|
||||
aria-labelledby={labelId}
|
||||
id={labelId}
|
||||
>
|
||||
<Tr id={`instance-row-${instance.id}`}>
|
||||
<Td
|
||||
select={{
|
||||
rowIndex,
|
||||
isSelected,
|
||||
onSelect,
|
||||
disable: false,
|
||||
}}
|
||||
dataLabel={t`Selected`}
|
||||
/>
|
||||
<Td id={labelId} dataLabel={t`Name`}>
|
||||
{instance.hostname}
|
||||
</Td>
|
||||
<Td dataLabel={t`Type`}>
|
||||
{instance.managed_by_policy ? t`Auto` : t`Manual`}
|
||||
</Td>
|
||||
<Td dataLabel={t`Running Jobs`}>{instance.jobs_running}</Td>
|
||||
<Td dataLabel={t`Total Jobs`}>{instance.jobs_total}</Td>
|
||||
<Td dataLabel={t`Capacity Adjustment`}>
|
||||
<SliderHolder data-cy="slider-holder">
|
||||
<div data-cy="cpu-capacity">{t`CPU ${instance.cpu_capacity}`}</div>
|
||||
<SliderForks data-cy="slider-forks">
|
||||
<div data-cy="number-forks">
|
||||
<Plural value={forks} one="# fork" other="# forks" />
|
||||
</div>
|
||||
<Slider
|
||||
areCustomStepsContinuous
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.1}
|
||||
value={instance.capacity_adjustment}
|
||||
onChange={handleChangeValue}
|
||||
isDisabled={!me?.is_superuser || !instance.enabled}
|
||||
data-cy="slider"
|
||||
/>
|
||||
</SliderForks>
|
||||
<div data-cy="mem-capacity">{t`RAM ${instance.mem_capacity}`}</div>
|
||||
</SliderHolder>
|
||||
</Td>
|
||||
<Td
|
||||
dataLabel={t`Instance group used capacity`}
|
||||
css="--pf-c-table--cell--MinWidth: 175px;"
|
||||
>
|
||||
{usedCapacity(instance)}
|
||||
</Td>
|
||||
<ActionsTd
|
||||
dataLabel={t`Actions`}
|
||||
css="--pf-c-table--cell--Width: 125px"
|
||||
>
|
||||
<ActionItem visible>
|
||||
<InstanceToggle
|
||||
css="display: inline-flex;"
|
||||
fetchInstances={fetchInstances}
|
||||
instance={instance}
|
||||
/>
|
||||
</DataListAction>
|
||||
</DataListItemRow>
|
||||
</DataListItem>
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
</Tr>
|
||||
{updateError && (
|
||||
<AlertModal
|
||||
variant="error"
|
||||
|
||||
@ -49,12 +49,16 @@ describe('<InstanceListItem/>', () => {
|
||||
test('should mount successfully', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
<table>
|
||||
<tbody>
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('InstanceListItem').length).toBe(1);
|
||||
@ -63,12 +67,16 @@ describe('<InstanceListItem/>', () => {
|
||||
test('should calculate number of forks when slide changes', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
<table>
|
||||
<tbody>
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('InstanceListItem').length).toBe(1);
|
||||
@ -105,30 +113,41 @@ describe('<InstanceListItem/>', () => {
|
||||
test('should render the proper data instance', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
<table>
|
||||
<tbody>
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
});
|
||||
expect(
|
||||
wrapper.find('PFDataListCell[aria-label="instance host name"]').text()
|
||||
wrapper
|
||||
.find('Td')
|
||||
.at(1)
|
||||
.text()
|
||||
).toBe('awx');
|
||||
expect(wrapper.find('Progress').prop('value')).toBe(40);
|
||||
expect(
|
||||
wrapper.find('PFDataListCell[aria-label="instance type"]').text()
|
||||
).toBe('TypeAuto');
|
||||
expect(wrapper.find('input#instances-1').prop('checked')).toBe(false);
|
||||
wrapper
|
||||
.find('Td')
|
||||
.at(2)
|
||||
.text()
|
||||
).toBe('Auto');
|
||||
expect(
|
||||
wrapper
|
||||
.find('PFDataListCell[aria-label="capacity adjustment"]')
|
||||
.find('Td')
|
||||
.at(5)
|
||||
.containsMatchingElement(<div>CPU 24</div>)
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('PFDataListCell[aria-label="capacity adjustment"]')
|
||||
.find('Td')
|
||||
.at(5)
|
||||
.containsMatchingElement(<div>RAM 24</div>)
|
||||
);
|
||||
expect(wrapper.find('InstanceListItem__SliderForks').text()).toContain(
|
||||
@ -136,18 +155,27 @@ describe('<InstanceListItem/>', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('should be checked', async () => {
|
||||
test('should render checkbox', async () => {
|
||||
const onSelect = jest.fn();
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
<table>
|
||||
<tbody>
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
onSelect={onSelect}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('input#instances-1').prop('checked')).toBe(true);
|
||||
expect(
|
||||
wrapper
|
||||
.find('Td')
|
||||
.first()
|
||||
.prop('select').onSelect
|
||||
).toEqual(onSelect);
|
||||
});
|
||||
|
||||
test('should display instance toggle', () => {
|
||||
@ -176,12 +204,16 @@ describe('<InstanceListItem/>', () => {
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>,
|
||||
<table>
|
||||
<tbody>
|
||||
<InstanceListItem
|
||||
instance={instance[0]}
|
||||
isSelected={false}
|
||||
onSelect={() => {}}
|
||||
fetchInstances={() => {}}
|
||||
/>
|
||||
</tbody>
|
||||
</table>,
|
||||
{ context: { network: { handleHttpError: () => {} } } }
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user