Skip to content

Commit

Permalink
Merge pull request #9182 from keithjgrant/6189-hosts-users-teams-tables
Browse files Browse the repository at this point in the history
Convert Hosts/Users/Teams list to tables

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
  • Loading branch information
2 parents 9fc8144 + 13131e9 commit 2c9ef3b
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 378 deletions.
24 changes: 15 additions & 9 deletions awx/ui_next/src/screens/Host/HostList/HostList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import { HostsAPI } from '../../../api';
import AlertModal from '../../../components/AlertModal';
import DataListToolbar from '../../../components/DataListToolbar';
import ErrorDetail from '../../../components/ErrorDetail';
import PaginatedDataList, {
import {
ToolbarAddButton,
ToolbarDeleteButton,
} from '../../../components/PaginatedDataList';
import PaginatedTable, {
HeaderRow,
HeaderCell,
} from '../../../components/PaginatedTable';
import useRequest, { useDeleteItems } from '../../../util/useRequest';
import {
encodeQueryString,
Expand Down Expand Up @@ -130,7 +134,7 @@ function HostList({ i18n }) {
return (
<PageSection>
<Card>
<PaginatedDataList
<PaginatedTable
contentError={contentError}
hasContentLoading={isLoading || isDeleteLoading}
items={hosts}
Expand All @@ -157,14 +161,15 @@ function HostList({ i18n }) {
key: 'modified_by__username__icontains',
},
]}
toolbarSortColumns={[
{
name: i18n._(t`Name`),
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Inventory`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
<DataListToolbar
{...props}
Expand Down Expand Up @@ -193,13 +198,14 @@ function HostList({ i18n }) {
]}
/>
)}
renderItem={host => (
renderRow={(host, index) => (
<HostListItem
key={host.id}
host={host}
detailUrl={`${match.url}/${host.id}/details`}
isSelected={selected.some(row => row.id === host.id)}
onSelect={() => handleSelect(host)}
rowIndex={index}
/>
)}
emptyStateControls={
Expand Down
10 changes: 6 additions & 4 deletions awx/ui_next/src/screens/Host/HostList/HostList.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ describe('<HostList />', () => {

act(() => {
wrapper
.find('input#select-host-1')
.closest('DataListCheck')
.find('.pf-c-table__check')
.first()
.find('input')
.invoke('onChange')();
});
wrapper.update();
Expand All @@ -147,8 +148,9 @@ describe('<HostList />', () => {
).toEqual(true);
act(() => {
wrapper
.find('input#select-host-1')
.closest('DataListCheck')
.find('.pf-c-table__check')
.first()
.find('input')
.invoke('onChange')();
});
wrapper.update();
Expand Down
128 changes: 52 additions & 76 deletions awx/ui_next/src/screens/Host/HostList/HostListItem.jsx
Original file line number Diff line number Diff line change
@@ -1,91 +1,67 @@
import 'styled-components/macro';
import React, { Fragment } from 'react';
import React from 'react';
import { string, bool, func } from 'prop-types';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
Button,
DataListAction as _DataListAction,
DataListCheck,
DataListItem,
DataListItemRow,
DataListItemCells,
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 styled from 'styled-components';
import DataListCell from '../../../components/DataListCell';

import Sparkline from '../../../components/Sparkline';
import { ActionsTd, ActionItem } from '../../../components/PaginatedTable';
import { Host } from '../../../types';
import HostToggle from '../../../components/HostToggle';

const DataListAction = styled(_DataListAction)`
align-items: center;
display: grid;
grid-gap: 24px;
grid-template-columns: 92px 40px;
`;

function HostListItem({ i18n, host, isSelected, onSelect, detailUrl }) {
function HostListItem({
i18n,
host,
isSelected,
onSelect,
detailUrl,
rowIndex,
}) {
const labelId = `check-action-${host.id}`;

return (
<DataListItem key={host.id} aria-labelledby={labelId} id={`${host.id}`}>
<DataListItemRow>
<DataListCheck
id={`select-host-${host.id}`}
checked={isSelected}
onChange={onSelect}
aria-labelledby={labelId}
/>
<DataListItemCells
dataListCells={[
<DataListCell key="name">
<Link to={`${detailUrl}`}>
<b>{host.name}</b>
</Link>
</DataListCell>,
<DataListCell key="recentJobs">
<Sparkline jobs={host.summary_fields.recent_jobs} />
</DataListCell>,
<DataListCell key="inventory">
{host.summary_fields.inventory && (
<Fragment>
<b css="margin-right: 24px">{i18n._(t`Inventory`)}</b>
<Link
to={`/inventories/inventory/${host.summary_fields.inventory.id}/details`}
>
{host.summary_fields.inventory.name}
</Link>
</Fragment>
)}
</DataListCell>,
]}
/>
<DataListAction
aria-label={i18n._(t`actions`)}
aria-labelledby={labelId}
id={labelId}
<Tr id={`host-row-${host.id}`}>
<Td
select={{
rowIndex,
isSelected,
onSelect,
}}
dataLabel={i18n._(t`Selected`)}
/>
<Td id={labelId} dataLabel={i18n._(t`Name`)}>
<Link to={`${detailUrl}`}>
<b>{host.name}</b>
</Link>
</Td>
<Td dataLabel={i18n._(t`Inventory`)}>
{host.summary_fields.inventory && (
<Link
to={`/inventories/inventory/${host.summary_fields.inventory.id}/details`}
>
{host.summary_fields.inventory.name}
</Link>
)}
</Td>
<ActionsTd dataLabel={i18n._(t`Actions`)} gridColumns="auto 40px">
<HostToggle host={host} />
<ActionItem
visible={host.summary_fields.user_capabilities.edit}
tooltip={i18n._(t`Edit Host`)}
>
<HostToggle host={host} />
{host.summary_fields.user_capabilities.edit ? (
<Tooltip content={i18n._(t`Edit Host`)} position="top">
<Button
aria-label={i18n._(t`Edit Host`)}
variant="plain"
component={Link}
to={`/hosts/${host.id}/edit`}
>
<PencilAltIcon />
</Button>
</Tooltip>
) : (
''
)}
</DataListAction>
</DataListItemRow>
</DataListItem>
<Button
aria-label={i18n._(t`Edit Host`)}
variant="plain"
component={Link}
to={`/hosts/${host.id}/edit`}
>
<PencilAltIcon />
</Button>
</ActionItem>
</ActionsTd>
</Tr>
);
}

Expand Down
32 changes: 20 additions & 12 deletions awx/ui_next/src/screens/Host/HostList/HostListItem.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ describe('<HostsListItem />', () => {

beforeEach(() => {
wrapper = mountWithContexts(
<HostsListItem
isSelected={false}
detailUrl="/host/1"
onSelect={() => {}}
host={mockHost}
/>
<table>
<tbody>
<HostsListItem
isSelected={false}
detailUrl="/host/1"
onSelect={() => {}}
host={mockHost}
/>
</tbody>
</table>
);
});

Expand All @@ -46,12 +50,16 @@ describe('<HostsListItem />', () => {
const copyMockHost = Object.assign({}, mockHost);
copyMockHost.summary_fields.user_capabilities.edit = false;
wrapper = mountWithContexts(
<HostsListItem
isSelected={false}
detailUrl="/host/1"
onSelect={() => {}}
host={copyMockHost}
/>
<table>
<tbody>
<HostsListItem
isSelected={false}
detailUrl="/host/1"
onSelect={() => {}}
host={copyMockHost}
/>
</tbody>
</table>
);
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
});
Expand Down
34 changes: 20 additions & 14 deletions awx/ui_next/src/screens/Team/TeamList/TeamList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import useRequest, { useDeleteItems } from '../../../util/useRequest';
import AlertModal from '../../../components/AlertModal';
import DataListToolbar from '../../../components/DataListToolbar';
import ErrorDetail from '../../../components/ErrorDetail';
import PaginatedDataList, {
import PaginatedTable, {
HeaderRow,
HeaderCell,
} from '../../../components/PaginatedTable';
import {
ToolbarAddButton,
ToolbarDeleteButton,
} from '../../../components/PaginatedDataList';
Expand Down Expand Up @@ -112,7 +116,7 @@ function TeamList({ i18n }) {
<Fragment>
<PageSection>
<Card>
<PaginatedDataList
<PaginatedTable
contentError={contentError}
hasContentLoading={hasContentLoading}
items={teams}
Expand Down Expand Up @@ -143,14 +147,15 @@ function TeamList({ i18n }) {
key: 'modified_by__username__icontains',
},
]}
toolbarSortColumns={[
{
name: i18n._(t`Name`),
key: 'name',
},
]}
toolbarSearchableKeys={searchableKeys}
toolbarRelatedSearchableKeys={relatedSearchableKeys}
headerRow={
<HeaderRow qsConfig={QS_CONFIG}>
<HeaderCell sortKey="name">{i18n._(t`Name`)}</HeaderCell>
<HeaderCell>{i18n._(t`Organization`)}</HeaderCell>
<HeaderCell>{i18n._(t`Actions`)}</HeaderCell>
</HeaderRow>
}
renderToolbar={props => (
<DataListToolbar
{...props}
Expand All @@ -176,13 +181,14 @@ function TeamList({ i18n }) {
]}
/>
)}
renderItem={o => (
renderRow={(team, index) => (
<TeamListItem
key={o.id}
team={o}
detailUrl={`${match.url}/${o.id}`}
isSelected={selected.some(row => row.id === o.id)}
onSelect={() => handleSelect(o)}
key={team.id}
team={team}
detailUrl={`${match.url}/${team.id}`}
isSelected={selected.some(row => row.id === team.id)}
onSelect={() => handleSelect(team)}
rowIndex={index}
/>
)}
emptyStateControls={
Expand Down
Loading

0 comments on commit 2c9ef3b

Please sign in to comment.