@patternfly/react-core#Skeleton JavaScript Examples
The following examples show how to use
@patternfly/react-core#Skeleton.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ToolbarFooter.js From edge-frontend with Apache License 2.0 | 6 votes |
ToolbarFooter = ({
isLoading,
count,
perPage,
setPerPage,
page,
setPage,
}) => {
return (
<Toolbar style={{ padding: '16px' }} id="toolbar-footer">
<ToolbarContent>
<ToolbarItem variant="pagination" align={{ default: 'alignRight' }}>
{isLoading ? (
<Skeleton width="400px" />
) : count > 0 ? (
<Pagination
data-testid="pagination-footer-test-id"
itemCount={count}
perPage={perPage}
page={page}
onSetPage={(_e, pageNumber) => setPage(pageNumber)}
widgetId="pagination-options-menu-top"
onPerPageSelect={(_e, perPage) => setPerPage(perPage)}
/>
) : null}
</ToolbarItem>
</ToolbarContent>
</Toolbar>
);
}
Example #2
Source File: ToolbarHeader.js From edge-frontend with Apache License 2.0 | 5 votes |
ToolbarHeader = ({
toolbarButtons,
filters,
setFilterValues,
filterValues,
chipsArray,
setChipsArray,
isLoading,
count,
perPage,
setPerPage,
page,
setPage,
toggleButton,
toggleAction,
toggleState,
children,
kebabItems,
}) => {
return (
<Toolbar
style={{ padding: '16px' }}
id="toolbar-header"
data-testid="toolbar-header-testid"
>
<ToolbarContent>
<FilterControls
filters={filters}
filterValues={filterValues}
setFilterValues={setFilterValues}
>
{children}
</FilterControls>
{toolbarButtons && <ToolbarButtons buttons={toolbarButtons} />}
{toggleButton && (
<ToggleGroup>
{toggleButton.map((btn) => (
<ToggleGroupItem
key={btn.key}
text={btn.title}
isSelected={toggleState === btn.key}
onChange={() => toggleAction(btn.key)}
/>
))}
</ToggleGroup>
)}
{kebabItems && <ToolbarKebab kebabItems={kebabItems} />}
<ToolbarItem variant="pagination" align={{ default: 'alignRight' }}>
{isLoading ? (
<Skeleton width="200px" />
) : count > 0 ? (
<Pagination
data-testid="pagination-header-test-id"
itemCount={count}
perPage={perPage}
page={page}
onSetPage={(_e, pageNumber) => setPage(pageNumber)}
widgetId="pagination-options-menu-top"
onPerPageSelect={(_e, perPage) => setPerPage(perPage)}
isCompact
/>
) : null}
</ToolbarItem>
</ToolbarContent>
<ToolbarContent>
<ToolbarItem variant="chip-group" spacer={{ default: 'spacerNone' }}>
<FilterChip
filterValues={filterValues}
setFilterValues={setFilterValues}
chipsArray={chipsArray}
setChipsArray={setChipsArray}
setPage={setPage}
/>
</ToolbarItem>
</ToolbarContent>
</Toolbar>
);
}
Example #3
Source File: LogsTable.js From sed-frontend with Apache License 2.0 | 5 votes |
LogsTable = () => {
const [opened, setOpened] = useState([]);
const dispatch = useDispatch();
const logLoaded = useSelector(
({ logReducer }) => logReducer?.loaded || false
);
const rows = useSelector(({ logReducer }) => logReducer?.results || []);
const pagination = useSelector(
({ logReducer }) => ({
itemCount: logReducer?.total,
perPage: logReducer?.limit,
page:
Math.floor((logReducer?.offset || 0) / (logReducer?.limit || 0)) + 1,
}),
shallowEqual
);
useEffect(() => {
dispatch(fetchLog());
}, []);
const onCollapse = (_e, _key, isOpen, { id }) => {
setOpened(() =>
isOpen ? [...opened, id] : opened.filter((openId) => openId !== id)
);
};
const setPage = useCallback(
(_e, pageNumber) =>
dispatch(fetchLog({ page: pageNumber, perPage: pagination.perPage })),
[dispatch, pagination.perPage]
);
const setPerPage = useCallback(
(_e, perPage) => dispatch(fetchLog({ page: 1, perPage })),
[dispatch]
);
return (
<Fragment>
<PrimaryToolbar
pagination={
logLoaded ? (
{
...pagination,
onSetPage: setPage,
onPerPageSelect: setPerPage,
}
) : (
<Skeleton width="33%" />
)
}
/>
{logLoaded ? (
<Table
aria-label="Logs table"
variant={TableVariant.compact}
rows={rowsMapper(rows, opened)}
cells={columns}
onCollapse={onCollapse}
>
<TableHeader />
<TableBody />
</Table>
) : (
<SkeletonTable colSize={3} rowSize={10} />
)}
<TableToolbar isFooter>
{logLoaded ? (
<Pagination
{...pagination}
variant={PaginationVariant.bottom}
onSetPage={setPage}
onPerPageSelect={setPerPage}
/>
) : (
<Skeleton width="33%" />
)}
</TableToolbar>
</Fragment>
);
}
Example #4
Source File: GroupsDetail.js From edge-frontend with Apache License 2.0 | 4 votes |
GroupsDetail = () => {
const dispatch = useDispatch();
const params = useParams();
const history = useHistory();
const { groupId } = params;
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
const [removeModal, setRemoveModal] = useState({
isOpen: false,
name: '',
deviceId: null,
});
const [updateModal, setUpdateModal] = useState({
isOpen: false,
deviceData: null,
imageData: null,
});
const [response, fetchDevices] = useApi({
api: getGroupById,
id: groupId,
tableReload: true,
});
const { data, isLoading, hasError } = response;
const groupName = data?.DeviceGroup?.Name;
const [deviceIds, getDeviceIds] = useState([]);
const [hasModalSubmitted, setHasModalSubmitted] = useState(false);
const [modalState, setModalState] = useState({ id: null, name: '' });
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isRenameModalOpen, setIsRenameModalOpen] = useState(false);
const handleDeleteModal = (id, name) => {
setModalState({ id, name });
setIsDeleteModalOpen(true);
};
const handleRenameModal = (id, name) => {
setModalState({ id, name });
setIsRenameModalOpen(true);
};
const removeDeviceLabel = () =>
`Do you want to remove ${
deviceIds.length > 0
? `${deviceIds.length} system${deviceIds.length === 1 ? '' : 's'}`
: `${removeModal.name}`
} from ${groupName}?`;
useEffect(() => {
history.push({
pathname: history.location.pathname,
search: stateToUrlSearch('add_system_modal=true', isAddModalOpen),
});
}, [isAddModalOpen]);
const handleSingleDeviceRemoval = () => {
const statusMessages = {
onSuccess: {
title: 'Success',
description: `${removeModal.name} has been removed successfully`,
},
onError: { title: 'Error', description: 'Failed to remove device' },
};
apiWithToast(
dispatch,
() => removeDeviceFromGroupById(groupId, removeModal.deviceId),
statusMessages
);
setTimeout(() => setHasModalSubmitted(true), 800);
};
const handleBulkDeviceRemoval = () => {
const statusMessages = {
onSuccess: {
title: 'Success',
description: `${deviceIds.length} systems have been removed successfully`,
},
onError: { title: 'Error', description: 'failed to remove systems' },
};
apiWithToast(
dispatch,
() =>
removeDevicesFromGroup(
parseInt(groupId),
deviceIds.map((device) => ({ ID: device.deviceID }))
),
statusMessages
);
setTimeout(() => setHasModalSubmitted(true), 800);
};
return (
<>
<PageHeader className="pf-m-light">
{groupName ? (
<Breadcrumb>
<BreadcrumbItem>
<Link to={`${paths['fleet-management']}`}>Groups</Link>
</BreadcrumbItem>
<BreadcrumbItem>{groupName}</BreadcrumbItem>
</Breadcrumb>
) : (
<Breadcrumb isActive>
<Skeleton width="100px" />
</Breadcrumb>
)}
<Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
<FlexItem>
{groupName ? (
<PageHeaderTitle title={groupName} />
) : (
<Skeleton width="150px" />
)}
</FlexItem>
<FlexItem>
<Dropdown
position={DropdownPosition.right}
toggle={
<DropdownToggle
id="image-set-details-dropdown"
toggleIndicator={CaretDownIcon}
onToggle={(newState) => setIsDropdownOpen(newState)}
isDisabled={false}
>
Actions
</DropdownToggle>
}
isOpen={isDropdownOpen}
dropdownItems={[
<DropdownItem
key="delete-device-group"
onClick={() => handleDeleteModal(groupId, groupName)}
>
Delete group
</DropdownItem>,
<DropdownItem
key="rename-device-group"
onClick={() => handleRenameModal(groupId, groupName)}
>
Rename group
</DropdownItem>,
<DropdownItem
key="update-all-devices"
isDisabled={canUpdateSelectedDevices({
deviceData: data?.DevicesView?.devices?.map((device) => ({
imageSetId: device?.ImageSetID,
})),
imageData: data?.DevicesView?.devices?.some(
(device) => device.ImageID
),
})}
onClick={() => {
setIsDropdownOpen(false);
setUpdateModal((prevState) => ({
...prevState,
isOpen: true,
deviceData: data?.DevicesView?.devices?.map((device) => ({
id: device?.DeviceUUID,
display_name:
device?.DeviceName === ''
? 'localhost'
: device?.DeviceName,
})),
imageSetId: data?.DevicesView?.devices.find(
(device) => device.ImageSetID
)?.ImageSetID,
}));
}}
>
Update
</DropdownItem>,
]}
/>
</FlexItem>
</Flex>
</PageHeader>
<Main className="edge-devices">
{!emptyStateNoFliters(
isLoading,
data?.DeviceGroup?.Devices.length,
history
) ? (
<DeviceTable
data={data?.DevicesView?.devices || []}
count={data?.DevicesView?.total}
isLoading={isLoading}
hasError={hasError}
hasCheckbox={true}
handleSingleDeviceRemoval={handleSingleDeviceRemoval}
kebabItems={[
{
isDisabled: !(deviceIds.length > 0),
title: 'Remove from group',
onClick: () =>
setRemoveModal({
name: '',
deviceId: null,
isOpen: true,
}),
},
{
isDisabled: canUpdateSelectedDevices({
deviceData: deviceIds,
imageData: deviceIds[0]?.updateImageData,
}),
title: 'Update selected',
onClick: () =>
setUpdateModal((prevState) => ({
...prevState,
isOpen: true,
deviceData: [...deviceIds],
imageSetId: deviceIds.find((device) => device?.imageSetId)
.imageSetId,
})),
},
]}
selectedItems={getDeviceIds}
setRemoveModal={setRemoveModal}
setIsAddModalOpen={setIsAddModalOpen}
setUpdateModal={setUpdateModal}
hasModalSubmitted={hasModalSubmitted}
setHasModalSubmitted={setHasModalSubmitted}
fetchDevices={fetchDevices}
isAddSystemsView={true}
/>
) : (
<Flex justifyContent={{ default: 'justifyContentCenter' }}>
<Empty
icon="plus"
title="Add systems to the group"
body="Create groups to help manage your systems more effectively."
primaryAction={{
text: 'Add systems',
click: () => setIsAddModalOpen(true),
}}
secondaryActions={[
{
type: 'link',
title: 'Learn more about system groups',
link: 'https://access.redhat.com/documentation/en-us/edge_management/2022/html-single/working_with_systems_in_the_edge_management_application/index',
},
]}
/>
</Flex>
)}
</Main>
{isAddModalOpen && (
<AddSystemsToGroupModal
groupId={groupId}
closeModal={() => setIsAddModalOpen(false)}
isOpen={isAddModalOpen}
reloadData={fetchDevices}
groupName={data?.DeviceGroup?.Name}
/>
)}
{removeModal.isOpen && (
<Modal
isOpen={removeModal.isOpen}
openModal={() => setRemoveModal(false)}
title={'Remove from group'}
submitLabel={'Remove'}
variant="danger"
schema={{
fields: [
{
component: componentTypes.PLAIN_TEXT,
name: 'warning-text',
label: removeDeviceLabel(),
},
],
}}
onSubmit={
removeModal.deviceId
? handleSingleDeviceRemoval
: handleBulkDeviceRemoval
}
reloadData={fetchDevices}
/>
)}
{updateModal.isOpen && (
<Suspense
fallback={
<Bullseye>
<Spinner />
</Bullseye>
}
>
<UpdateDeviceModal
navigateBack={() => {
history.push({ pathname: history.location.pathname });
setUpdateModal((prevState) => {
return {
...prevState,
isOpen: false,
};
});
}}
setUpdateModal={setUpdateModal}
updateModal={updateModal}
refreshTable={fetchDevices}
/>
</Suspense>
)}
{isDeleteModalOpen && (
<DeleteGroupModal
isModalOpen={isDeleteModalOpen}
setIsModalOpen={setIsDeleteModalOpen}
reloadData={() => history.push(paths['fleet-management'])}
modalState={modalState}
/>
)}
{isRenameModalOpen && (
<RenameGroupModal
isModalOpen={isRenameModalOpen}
setIsModalOpen={setIsRenameModalOpen}
reloadData={() => fetchDevices()}
modalState={modalState}
/>
)}
</>
);
}
Example #5
Source File: DetailsHeader.js From edge-frontend with Apache License 2.0 | 4 votes |
DetailsHead = ({ imageData, imageVersion, openUpdateWizard }) => {
const [isOpen, setIsOpen] = useState(false);
const [data, setData] = useState({});
useEffect(() => {
setData(imageData?.data?.Data);
}, [imageData]);
return (
<>
{!imageData.isLoading && imageData.hasError ? (
<Breadcrumb>
<BreadcrumbItem>
<Link to={paths['manage-images']}>Back to Manage Images</Link>
</BreadcrumbItem>
</Breadcrumb>
) : (
<>
<Breadcrumb>
<BreadcrumbItem>
<Link to={paths['manage-images']}>Manage Images</Link>
</BreadcrumbItem>
{imageVersion ? (
<BreadcrumbItem>
<Link to={`${paths['manage-images']}/${data?.image_set?.ID}`}>
{data?.image_set?.Name}
</Link>
</BreadcrumbItem>
) : (
<BreadcrumbItem isActive>
{data?.image_set?.Name || <Skeleton width="100px" />}
</BreadcrumbItem>
)}
{imageVersion && (
<BreadcrumbItem isActive>
{imageVersion?.image?.Version}
</BreadcrumbItem>
)}
</Breadcrumb>
<TextContent>
<Split>
<SplitItem>
<TextList component="dl">
<TextListItem
component="h1"
className="grid-align-center pf-u-mb-0"
>
{data?.image_set?.Name || <Skeleton width="150px" />}
</TextListItem>
<TextListItem className="pf-u-pt-sm" component="dd">
{data?.Status || data?.images?.[0]?.image?.Status ? (
<Status
type={data?.images?.[0]?.image?.Status.toLowerCase()}
/>
) : (
<Skeleton width="100px" />
)}
</TextListItem>
{imageVersion?.image?.UpdatedAt ||
data?.images?.[0].image?.UpdatedAt ? (
<TextListItem component="p">
{`Last updated `}
<DateFormat
date={
imageVersion
? imageVersion?.image?.UpdatedAt
: data?.images?.[0].image?.UpdatedAt
}
/>
</TextListItem>
) : (
<Skeleton width="200px" />
)}
</TextList>
</SplitItem>
<SplitItem isFilled></SplitItem>
<SplitItem>
<Dropdown
position={DropdownPosition.right}
toggle={
<DropdownToggle
id="image-set-details-dropdown"
toggleIndicator={CaretDownIcon}
onToggle={(newState) => setIsOpen(newState)}
isDisabled={
(imageVersion
? imageVersion?.image?.Status
: data?.Images?.[0]?.Status) === 'BUILDING' || false
}
>
Actions
</DropdownToggle>
}
isOpen={isOpen}
dropdownItems={dropdownItems(
data,
imageVersion,
openUpdateWizard
)}
/>
</SplitItem>
</Split>
</TextContent>
</>
)}
</>
);
}
Example #6
Source File: ImageDetailTab.js From edge-frontend with Apache License 2.0 | 4 votes |
ImageDetailTab = ({ imageData, imageVersion }) => {
const [data, setData] = useState({});
useEffect(() => {
imageVersion
? setData(imageVersion)
: setData(imageData?.data?.Data?.images?.[0]);
}, [imageData, imageVersion]);
const createSkeleton = (rows) =>
[...Array(rows * 2)].map((_, key) => <Skeleton width="180px" key={key} />);
const dateFormat = () => <DateFormat date={data?.image?.['CreatedAt']} />;
const detailsMapper = {
Version: 'Version',
Created: () => dateFormat(),
'Type(s)': () =>
data?.image?.['OutputTypes']?.map((outputType, index) => (
<div key={index}>{outputType}</div>
)),
Release: () => distributionMapper?.[data?.image?.['Distribution']],
//Size: 'Size',
Description: 'Description',
};
const userInfoMapper = {
Username: () => data?.image?.Installer?.Username,
'SSH key': () => data?.image?.Installer?.SshKey,
};
const renderAdditionalPackageLink = () => {
return (
<Link
to={`${paths['manage-images']}/${data?.image?.ImageSetID}/versions/${data?.image?.ID}/packages/additional`}
>
{data?.additional_packages}
</Link>
);
};
const renderTotalPackageLink = () => {
return (
<Link
to={`${paths['manage-images']}/${data?.image?.ImageSetID}/versions/${data?.image?.ID}/packages/all`}
>
{data?.packages}
</Link>
);
};
const packageMapper = {
'Total additional packages': renderAdditionalPackageLink,
'Total packages': renderTotalPackageLink,
};
const packageDiffMapper = {
Added: () => data?.update_added,
Removed: () => data?.update_removed,
Updated: () => data?.update_updated,
};
if (data?.image?.Installer?.Checksum) {
detailsMapper['SHA-256 checksum'] = () => data?.image?.Installer?.Checksum;
}
if (data?.image?.Commit?.OSTreeCommit) {
detailsMapper['Ostree commit hash'] = () =>
data?.image?.Commit?.OSTreeCommit;
}
const buildTextList = (labelsToValueMapper) =>
data
? Object.entries(labelsToValueMapper).map(([label, value], index) => {
return (
<Fragment key={index}>
<TextListItem
className="details-label"
component={TextListItemVariants.dt}
>
{label}
</TextListItem>
{label === 'SHA-256 checksum' ||
label === 'Ostree commit hash' ||
(label === 'SSH key' && value()) ? (
<TextListItem component={TextListItemVariants.dd}>
<ClipboardCopy
hoverTip="Copy"
clickTip="Copied"
variant="expansion"
className="pf-u-text-break-word"
id={`${label
.replace(/\s+/g, '-')
.toLowerCase()}-clipboard-copy`}
>
{typeof value === 'function'
? value() || 'Unavailable'
: data?.image?.[value] || 'Unavailable'}
</ClipboardCopy>
</TextListItem>
) : (
<TextListItem
className="pf-u-text-break-word"
component={TextListItemVariants.dd}
>
{typeof value === 'function'
? value() === 0
? 0
: value() || 'Unavailable'
: data?.image?.[value] || 'Unavailable'}
</TextListItem>
)}
</Fragment>
);
})
: null;
return (
<TextContent className="pf-u-ml-lg pf-u-mt-md">
<Grid span={12}>
<GridItem span={5}>
<Text component={TextVariants.h2}>
{imageVersion ? 'Details' : 'Most recent image'}
</Text>
<TextList component={TextListVariants.dl}>
{buildTextList(detailsMapper) || createSkeleton(6)}
</TextList>
<Text component={TextVariants.h2}>User information </Text>
<TextList component={TextListVariants.dl}>
{buildTextList(userInfoMapper) || createSkeleton(2)}
</TextList>
</GridItem>
<GridItem span={1} />
<GridItem span={6}>
<Text component={TextVariants.h2}>Packages </Text>
<TextList component={TextListVariants.dl}>
{buildTextList(packageMapper) || createSkeleton(3)}
</TextList>
<Text component={TextVariants.h2}>Changes from previous version</Text>
<TextList component={TextListVariants.dl}>
{buildTextList(packageDiffMapper) || createSkeleton(3)}
</TextList>
</GridItem>
</Grid>
</TextContent>
);
}
Example #7
Source File: ImageDetailTabs.js From edge-frontend with Apache License 2.0 | 4 votes |
ImageDetailTabs = ({
imageData,
openUpdateWizard,
imageVersion,
isLoading,
}) => {
const location = useLocation();
const history = useHistory();
const [activeTabKey, setActiveTabkey] = useState(tabs.details);
const activeTab = imageVersion ? 'imageTab' : 'imageSetTab';
const keys = [
'baseURL',
'imageSetVersion',
'imageSetTab',
'imageVersion',
'imageTab',
'packagesToggle',
];
const imageUrlMapper = mapUrlToObj(location.pathname, keys);
const handleTabClick = (_event, tabIndex) => {
const selectedTab =
tabIndex === 0 ? 'details' : imageVersion ? 'packages' : 'versions';
imageUrlMapper[activeTab] = selectedTab;
history.push(imageUrlMapper.buildUrl());
setActiveTabkey(tabIndex);
};
useEffect(() => {
imageUrlMapper['imageTab']
? setActiveTabkey(tabs[imageUrlMapper['imageTab']])
: setActiveTabkey(tabs[imageUrlMapper['imageSetTab']]);
}, [location.pathname]);
return (
<>
{!imageData.isLoading && imageData.hasError ? (
<EmptyState
icon="question"
title="Image not found"
body="Please check you have the correct link with the correct image Id."
primaryAction={{
text: 'Back to Manage Images',
href: paths['manage-images'],
}}
secondaryActions={[]}
/>
) : (
<div className="edge-c-device--detail add-100vh">
<Tabs
className="pf-u-ml-md"
activeKey={activeTabKey}
onSelect={handleTabClick}
>
<Tab
eventKey={tabs.details}
title={<TabTitleText>Details</TabTitleText>}
>
<ImageDetailTab
imageData={imageData}
imageVersion={imageVersion}
/>
</Tab>
{isLoading ? (
<Tab
title={
<TabTitleText>
<Skeleton width="75px" />
</TabTitleText>
}
></Tab>
) : imageVersion ? (
<Tab
eventKey={tabs.packages}
title={<TabTitleText>Packages</TabTitleText>}
>
<ImagePackagesTab imageVersion={imageVersion} />
</Tab>
) : (
<Tab
eventKey={tabs.versions}
title={<TabTitleText>Versions</TabTitleText>}
>
<ImageVersionTab
imageData={imageData}
openUpdateWizard={openUpdateWizard}
/>
</Tab>
)}
</Tabs>
</div>
)}
</>
);
}
Example #8
Source File: GeneralTable.js From edge-frontend with Apache License 2.0 | 4 votes |
GeneralTable = ({
apiFilterSort,
urlParam,
filters,
loadTableData,
tableData,
columnNames,
rows,
toolbarButtons,
actionResolver,
areActionsDisabled,
defaultSort,
emptyFilterState,
toggleButton,
toggleAction,
toggleState,
hasCheckbox = false,
skeletonRowQuantity,
selectedItems,
initSelectedItems,
kebabItems,
hasModalSubmitted,
setHasModalSubmitted,
isUseApi,
}) => {
const defaultCheckedRows = initSelectedItems ? initSelectedItems : [];
const [filterValues, setFilterValues] = useState(createFilterValues(filters));
const [chipsArray, setChipsArray] = useState([]);
const [sortBy, setSortBy] = useState(defaultSort);
const [perPage, setPerPage] = useState(20);
const [page, setPage] = useState(1);
const [checkedRows, setCheckedRows] = useState(defaultCheckedRows);
const dispatch = useDispatch();
const history = useHistory();
useEffect(() => {
if (
//!history.location.search.includes('add_system_modal=true') &&
!history.location.search.includes('create_image=true') &&
!history.location.search.includes('update_image=true')
) {
history.push({
pathname: history.location.pathname,
search: stateToUrlSearch('has_filters=true', chipsArray.length > 0),
});
}
const query = apiFilterSort
? {
...filterParams(chipsArray),
limit: perPage,
offset: (page - 1) * perPage,
...transformSort({
direction: sortBy.direction,
name: columns[sortBy.index].type,
}),
}
: null;
if (query?.status === 'updateAvailable') {
delete query.status;
query.update_available = 'true';
}
if (isUseApi) {
loadTableData(query);
return;
}
apiFilterSort && urlParam
? loadTableData(dispatch, urlParam, query)
: apiFilterSort
? loadTableData(dispatch, query)
: null;
}, [chipsArray, perPage, page, sortBy]);
useEffect(() => {
setCheckedRows(defaultCheckedRows);
}, [hasModalSubmitted]);
useEffect(() => {
selectedItems && selectedItems(checkedRows);
hasModalSubmitted && setHasModalSubmitted(false);
}, [checkedRows]);
const { count, isLoading, hasError } = tableData;
//Used for repos until the api can sort and filter
const filteredByName = () => {
const activeFilters = filterValues.filter(
(filter) =>
(filter?.type === 'text' && filter?.value !== '') ||
(filter?.type === 'checkbox' &&
filter?.value.find((checked) => checked.isChecked))
);
const filteredArray = rows.filter((row) => {
if (activeFilters.length > 0) {
return activeFilters?.every((filter) => {
if (filter.type === 'text') {
return row.noApiSortFilter[
columnNames.findIndex((row) => row.title === filter.label)
]
.toLowerCase()
.includes(filter.value.toLowerCase());
} else if (filter.type === 'checkbox') {
return filter.value.some(
(value) =>
value.isChecked &&
row.noApiSortFilter[
columnNames.findIndex((row) => row.title === filter.label) - 1
].toLowerCase() === value.value.toLowerCase()
);
}
});
} else {
return row;
}
});
return filteredArray;
};
const filteredByNameRows = !apiFilterSort && filteredByName();
//non-api sort function
const sortedByDirection = (rows) =>
rows.sort((a, b) => {
const index = hasCheckbox ? sortBy.index - 1 : sortBy.index;
return typeof a?.noApiSortFilter[index] === 'number'
? sortBy.direction === 'asc'
? a?.noApiSortFilter[index] - b?.noApiSortFilter[index]
: b?.noApiSortFilter[index] - a?.noApiSortFilter[index]
: sortBy.direction === 'asc'
? a?.noApiSortFilter[index].localeCompare(
b?.noApiSortFilter[index],
undefined,
{ sensitivity: 'base' }
)
: b?.noApiSortFilter[index].localeCompare(
a?.noApiSortFilter[index],
undefined,
{ sensitivity: 'base' }
);
});
const nonApiCount = !apiFilterSort
? sortedByDirection(filteredByNameRows)?.length
: 0;
const handleSort = (_event, index, direction) => {
index = hasCheckbox ? index - 1 : index;
setSortBy({ index, direction });
};
const toShowSort =
isLoading || hasError || (count?.length > 0 && filters.length > 0);
const columns = columnNames.map((columnName) => ({
title: columnName.title,
type: columnName.type,
transforms: toShowSort ? [] : columnName.sort ? [sortable] : [],
columnTransforms: columnName.columnTransforms
? columnName.columnTransforms
: [],
}));
const filteredRows = apiFilterSort
? rows
: rows.length > 0
? sortedByDirection(filteredByNameRows).slice(
(page - 1) * perPage,
(page - 1) * perPage + perPage
)
: rows;
const checkboxRows = () =>
filteredRows.map((row) =>
checkedRows.some((checkedRow) => checkedRow.id === row.rowInfo.id)
? {
...row,
selected: true,
}
: {
...row,
selected: false,
}
);
const handleSelect = (_event, isSelecting, rowIndex) => {
setCheckedRows((prevState) => {
return isSelecting
? [...prevState, { ...filteredRows[rowIndex].rowInfo }]
: prevState.filter(
(row) => row.id !== filteredRows[rowIndex].rowInfo.id
);
});
};
const handlePageSelect = () => {
setCheckedRows((prevState) => {
const checkedIds = prevState.map((row) => row.id);
const rowIsNotIncluded = (id) => !checkedIds.includes(id);
const newRows = [];
filteredRows.forEach((filtered) => {
if (rowIsNotIncluded(filtered.rowInfo.id)) {
newRows.push({
...filtered.rowInfo,
});
}
});
return [...prevState, ...newRows];
});
};
const handleBulkSelect = () => {
setCheckedRows(
rows.map((row) => ({
...row.rowInfo,
}))
);
};
const handleNoneSelect = () => {
setCheckedRows([]);
};
const loadingRows = (perPage) =>
[...Array(skeletonRowQuantity ?? perPage)].map(() => ({
cells: columnNames.map(() => ({ title: <Skeleton width="100%" /> })),
}));
const emptyFilterView = () => {
hasCheckbox = false;
return [
{
heightAuto: true,
cells: [
{
props: {
colSpan: 8,
},
title: (
<CustomEmptyState
data-testid="general-table-empty-state-no-match"
bgColor="white"
icon={emptyFilterState?.icon ?? 'search'}
title={emptyFilterState?.title ?? 'No match found'}
body={emptyFilterState?.body ?? ''}
secondaryActions={
toggleAction
? []
: [
{
title: 'Clear all filters',
onClick: () =>
setFilterValues(createFilterValues(filters)),
},
]
}
/>
),
},
],
},
];
};
const tableRows = isLoading
? loadingRows(perPage)
: !filteredRows?.length > 0
? emptyFilterView()
: hasCheckbox
? checkboxRows()
: filteredRows;
return (
<>
<ToolbarHeader
count={apiFilterSort ? count : nonApiCount}
toolbarButtons={toolbarButtons}
filters={filters}
filterValues={filterValues}
setFilterValues={setFilterValues}
chipsArray={chipsArray}
setChipsArray={setChipsArray}
isLoading={isLoading}
perPage={perPage}
setPerPage={setPerPage}
page={page}
setPage={setPage}
toggleButton={toggleButton}
toggleAction={toggleAction}
toggleState={toggleState}
kebabItems={kebabItems}
>
{!isLoading && hasCheckbox ? (
<BulkSelect
checkedRows={checkedRows}
handleBulkSelect={handleBulkSelect}
handlePageSelect={handlePageSelect}
handleNoneSelect={handleNoneSelect}
displayedRowsLength={filteredRows.length}
/>
) : null}
</ToolbarHeader>
<Table
data-testid="general-table-testid"
variant="compact"
aria-label="General Table Component"
sortBy={hasCheckbox ? { ...sortBy, index: sortBy.index + 1 } : sortBy}
onSort={handleSort}
actionResolver={actionResolver ? actionResolver : null}
areActionsDisabled={areActionsDisabled}
cells={columns}
rows={tableRows}
onSelect={!isLoading && hasCheckbox && handleSelect}
canSelectAll={false}
>
<TableHeader />
<TableBody />
</Table>
<ToolbarFooter
isLoading={isLoading}
count={apiFilterSort ? count : nonApiCount}
setFilterValues={setFilterValues}
perPage={perPage}
setPerPage={setPerPage}
page={page}
setPage={setPage}
/>
</>
);
}