Skip to content

Commit

Permalink
Refs #38107 - Make booted container images rows expandable
Browse files Browse the repository at this point in the history
  • Loading branch information
ianballou committed Dec 23, 2024
1 parent 05759e3 commit c1f2053
Showing 1 changed file with 161 additions and 34 deletions.
195 changes: 161 additions & 34 deletions webpack/scenes/BootedContainerImages/BootedContainerImagesPage.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import React from 'react';
import { TableComposable, Thead, Th, Tbody, Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableIndexPage';
import { Table } from 'foremanReact/components/PF4/TableIndexPage/Table/Table';
import {
useSetParamsAndApiAndSearch,
useTableIndexAPIResponse,
} from 'foremanReact/components/PF4/TableIndexPage/Table/TableIndexHooks';
import {
useUrlParams,
useSet,
} from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
import {
getColumnHelpers,
} from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
import {
useTableSort,
} from 'foremanReact/components/PF4/Helpers/useTableSort';
import Pagination from 'foremanReact/components/Pagination';
import EmptyPage from 'foremanReact/routes/common/EmptyPage';
import { translate as __ } from 'foremanReact/common/I18n';
import BOOTED_CONTAINER_IMAGES_KEY, { BOOTED_CONTAINER_IMAGES_API_PATH } from './BootedContainerImagesConstants';

Expand All @@ -29,12 +38,6 @@ const BootedContainerImagesPage = () => {
},
};

const STATUS = {
PENDING: 'PENDING',
RESOLVED: 'RESOLVED',
ERROR: 'ERROR',
};

const {
searchParam: urlSearchQuery = '',
page: urlPage,
Expand All @@ -44,15 +47,34 @@ const BootedContainerImagesPage = () => {
if (urlPage) defaultParams.page = Number(urlPage);
if (urlPerPage) defaultParams.per_page = Number(urlPerPage);
const apiOptions = { key: BOOTED_CONTAINER_IMAGES_KEY };

const response = useTableIndexAPIResponse({
apiUrl: BOOTED_CONTAINER_IMAGES_API_PATH,
apiOptions,
defaultParams,
});
const columnsToSortParams = {};
Object.keys(columns).forEach(key => {
if (columns[key].isSorted) {
columnsToSortParams[columns[key].title] = key;
}
});
const { pfSortParams } = useTableSort({
allColumns: Object.keys(columns).map(k => columns[k].title),
columnsToSortParams,
onSort,
});
const expandedImages = useSet([]);
const imageIsExpanded = image_name => expandedImages.has(image_name);
const STATUS = {
PENDING: 'PENDING',
RESOLVED: 'RESOLVED',
ERROR: 'ERROR',
};

const {
response: {
results,
results = [],
per_page: perPage,
page,
subtotal,
Expand All @@ -68,40 +90,145 @@ const BootedContainerImagesPage = () => {
setAPIOptions: response.setAPIOptions,
});

const [columnNamesKeys, keysToColumnNames] = getColumnHelpers(columns);
const onSort = (_event, index, direction) => {
setParamsAndAPI({
...params,
order: `${Object.keys(columns)[index]} ${direction}`,
});
};
const onPagination = newPagination => {
setParamsAndAPI({ ...params, ...newPagination });
};
const bottomPagination = (
<Pagination
key="table-bottom-pagination"
page={params.page}
perPage={params.perPage}
itemCount={subtotal}
onChange={onPagination}
updateParamsByUrl={true}
/>
);

return (
<TableIndexPage
apiUrl={BOOTED_CONTAINER_IMAGES_API_PATH}
apiOptions={{ key: BOOTED_CONTAINER_IMAGES_KEY }}
apiOptions={apiOptions}
header={__('Booted container images')}
createable={false}
isDeleteable={false}
controller="/katello/api/v2/host_bootc_images"
>
<Table
ouiaId="booted-container-images-table"
isEmbedded={false}
params={{
...params,
page,
perPage,
}}
setParams={setParamsAndAPI}
itemCount={subtotal}
results={results}
url={BOOTED_CONTAINER_IMAGES_API_PATH}
isDeleteable={false}
refreshData={() =>
setAPIOptions({
...apiOptions,
params: { urlSearchQuery },
})
}
columns={columns}
errorMessage={
status === STATUS.ERROR && errorMessage ? errorMessage : null
}
isPending={status === STATUS.PENDING}
/>
<>
<TableComposable variant="compact" ouiaId="booted-containers-table" isStriped>
<Thead>
<Tr ouiaId="table-header">
<>
<Th />
{columnNamesKeys.map(k => (
<Th
key={k}
sort={
Object.values(columnsToSortParams).includes(k) &&
pfSortParams(keysToColumnNames[k])
}
>
{keysToColumnNames[k]}
</Th>
))}
</>
</Tr>
</Thead>
<Tbody>
{status === STATUS.PENDING && results.length === 0 && (
<Tr ouiaId="table-loading">
<Td colSpan={100}>
<EmptyPage
message={{
type: 'loading',
text: __('Loading...'),
}}
/>
</Td>
</Tr>
)}
{!status === STATUS.PENDING &&
results.length === 0 &&
!errorMessage && (
<Tr ouiaId="table-empty">
<Td colSpan={100}>
<EmptyPage
message={{
type: 'empty',
}}
/>
</Td>
</Tr>
)}
{errorMessage && (
<Tr ouiaId="table-error">
<Td colSpan={100}>
<EmptyPage message={{ type: 'error', text: errorMessage }} />
</Td>
</Tr>
)}
</Tbody>
{results?.map((result, rowIndex) => {
const { image_name, digests } = result;
const isExpanded = imageIsExpanded(image_name);
return (
<Tbody key={`bootable-container-images-body-${rowIndex}`} isExpanded={isExpanded}>
<Tr key={image_name} ouiaId={`table-row-${rowIndex}`}>
<>
<Td
expand={digests.length > 0 && {
rowIndex,
isExpanded,
onToggle: (_event, _rInx, isOpen,) => expandedImages.onToggle(isOpen, image_name),
expandId: 'booted-containers-expander'
}}
/>
{columnNamesKeys.map(k => (
<Td
key={k}
dataLabel={keysToColumnNames[k]}
>
{columns[k].wrapper ? columns[k].wrapper(result) : result[k]}
</Td>
))}
</>
</Tr>
{digests ? <Tr isExpanded={isExpanded}>
<Td colSpan={3}>
<ExpandableRowContent>
<TableComposable variant="compact" isStriped>
<Thead>
<Tr>
<Th>{__('Image digest')}</Th>
<Th>{__('Hosts')}</Th>
</Tr>
</Thead>
<Tbody>
{digests.map((digest, index) => (
<Tr key={index}>
<Td>{digest.bootc_booted_digest}</Td>
<Td>
<a href={`/hosts?search=bootc_booted_digest%20=%20${digest.bootc_booted_digest}`}>{digest.host_count}</a>
</Td>
</Tr>
))}
</Tbody>
</TableComposable>
</ExpandableRowContent>
</Td>
</Tr> : null}
</Tbody>
);
})}
</TableComposable>
{results.length > 0 && !errorMessage && bottomPagination}
</>
</TableIndexPage>
);
};
Expand Down

0 comments on commit c1f2053

Please sign in to comment.