feat(HMS-3401): Add blueprints sidebar pagination
This commit is contained in:
parent
7bff1feaf4
commit
a3a7ea88c5
9 changed files with 202 additions and 7 deletions
56
src/Components/Blueprints/BlueprintsPagination.tsx
Normal file
56
src/Components/Blueprints/BlueprintsPagination.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import React from 'react';
|
||||
|
||||
import {
|
||||
OnSetPage,
|
||||
Pagination,
|
||||
PaginationVariant,
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
import {
|
||||
selectBlueprintSearchInput,
|
||||
selectLimit,
|
||||
selectOffset,
|
||||
setBlueprintLimit,
|
||||
setBlueprintsOffset,
|
||||
} from '../../store/BlueprintSlice';
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import { useGetBlueprintsQuery } from '../../store/imageBuilderApi';
|
||||
|
||||
const BlueprintsPagination = () => {
|
||||
const blueprintSearchInput = useAppSelector(selectBlueprintSearchInput);
|
||||
const blueprintsOffset = useAppSelector(selectOffset) || 0;
|
||||
const blueprintsLimit = useAppSelector(selectLimit) || 10;
|
||||
const currPage = Math.floor(blueprintsOffset / blueprintsLimit) + 1;
|
||||
const { data: blueprintsData } = useGetBlueprintsQuery({
|
||||
search: blueprintSearchInput,
|
||||
limit: blueprintsLimit,
|
||||
offset: blueprintsOffset,
|
||||
});
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const blueprintsTotal = blueprintsData?.meta?.count || 0;
|
||||
const onSetPage: OnSetPage = (_, page) => {
|
||||
const direction = page > currPage ? 1 : -1; // Calculate offset based on direction of paging
|
||||
const nextOffset = blueprintsOffset + direction * blueprintsLimit;
|
||||
dispatch(setBlueprintsOffset(nextOffset));
|
||||
};
|
||||
const onPerPageSelect: OnSetPage = (_, perPage) => {
|
||||
dispatch(setBlueprintsOffset(0));
|
||||
dispatch(setBlueprintLimit(perPage));
|
||||
};
|
||||
return (
|
||||
<Pagination
|
||||
variant={PaginationVariant.bottom}
|
||||
itemCount={blueprintsTotal}
|
||||
perPage={blueprintsLimit}
|
||||
page={currPage}
|
||||
onSetPage={onSetPage}
|
||||
onPerPageSelect={onPerPageSelect}
|
||||
widgetId="blueprints-pagination-bottom"
|
||||
data-testid="blueprints-pagination-bottom"
|
||||
isCompact
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlueprintsPagination;
|
||||
|
|
@ -20,13 +20,18 @@ import debounce from 'lodash/debounce';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import BlueprintCard from './BlueprintCard';
|
||||
import BlueprintsPagination from './BlueprintsPagination';
|
||||
|
||||
import {
|
||||
selectBlueprintSearchInput,
|
||||
selectLimit,
|
||||
selectOffset,
|
||||
selectSelectedBlueprintId,
|
||||
setBlueprintId,
|
||||
setBlueprintSearchInput,
|
||||
setBlueprintsOffset,
|
||||
} from '../../store/BlueprintSlice';
|
||||
import { imageBuilderApi } from '../../store/enhancedImageBuilderApi';
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import {
|
||||
useGetBlueprintsQuery,
|
||||
|
|
@ -49,8 +54,12 @@ type emptyBlueprintStateProps = {
|
|||
const BlueprintsSidebar = () => {
|
||||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const blueprintSearchInput = useAppSelector(selectBlueprintSearchInput);
|
||||
const blueprintsOffset = useAppSelector(selectOffset);
|
||||
const blueprintsLimit = useAppSelector(selectLimit);
|
||||
const { data: blueprintsData, isLoading } = useGetBlueprintsQuery({
|
||||
search: blueprintSearchInput,
|
||||
limit: blueprintsLimit,
|
||||
offset: blueprintsOffset,
|
||||
});
|
||||
const dispatch = useAppDispatch();
|
||||
const blueprints = blueprintsData?.data;
|
||||
|
|
@ -82,7 +91,6 @@ const BlueprintsSidebar = () => {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack hasGutter>
|
||||
|
|
@ -124,6 +132,7 @@ const BlueprintsSidebar = () => {
|
|||
<BlueprintCard blueprint={blueprint} />
|
||||
</StackItem>
|
||||
))}
|
||||
<BlueprintsPagination />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
|
|
@ -136,6 +145,8 @@ const BlueprintSearch = ({ blueprintsTotal }: blueprintSearchProps) => {
|
|||
const dispatch = useAppDispatch();
|
||||
const debouncedSearch = useCallback(
|
||||
debounce((filter) => {
|
||||
dispatch(setBlueprintsOffset(0));
|
||||
dispatch(imageBuilderApi.util.invalidateTags([{ type: 'Blueprints' }]));
|
||||
dispatch(setBlueprintSearchInput(filter.length > 0 ? filter : undefined));
|
||||
}, 300),
|
||||
[]
|
||||
|
|
|
|||
|
|
@ -9,9 +9,12 @@ import {
|
|||
|
||||
import {
|
||||
selectBlueprintSearchInput,
|
||||
selectLimit,
|
||||
selectOffset,
|
||||
selectSelectedBlueprintId,
|
||||
setBlueprintId,
|
||||
} from '../../store/BlueprintSlice';
|
||||
import { imageBuilderApi } from '../../store/enhancedImageBuilderApi';
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import {
|
||||
useDeleteBlueprintMutation,
|
||||
|
|
@ -28,9 +31,15 @@ export const DeleteBlueprintModal: React.FunctionComponent<
|
|||
> = ({ setShowDeleteModal, isOpen }: DeleteBlueprintModalProps) => {
|
||||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const blueprintSearchInput = useAppSelector(selectBlueprintSearchInput);
|
||||
const blueprintsOffset = useAppSelector(selectOffset);
|
||||
const blueprintsLimit = useAppSelector(selectLimit);
|
||||
const dispatch = useAppDispatch();
|
||||
const { blueprintName } = useGetBlueprintsQuery(
|
||||
{ search: blueprintSearchInput },
|
||||
{
|
||||
search: blueprintSearchInput,
|
||||
limit: blueprintsLimit,
|
||||
offset: blueprintsOffset,
|
||||
},
|
||||
{
|
||||
selectFromResult: ({ data }) => ({
|
||||
blueprintName: data?.data?.find(
|
||||
|
|
@ -48,6 +57,7 @@ export const DeleteBlueprintModal: React.FunctionComponent<
|
|||
setShowDeleteModal(false);
|
||||
await deleteBlueprint({ id: selectedBlueprintId });
|
||||
dispatch(setBlueprintId(undefined));
|
||||
dispatch(imageBuilderApi.util.invalidateTags([{ type: 'Blueprints' }]));
|
||||
}
|
||||
};
|
||||
const onDeleteClose = () => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ import {
|
|||
selectBlueprintSearchInput,
|
||||
selectBlueprintVersionFilter,
|
||||
selectBlueprintVersionFilterAPI,
|
||||
selectLimit,
|
||||
selectOffset,
|
||||
selectSelectedBlueprintId,
|
||||
} from '../../store/BlueprintSlice';
|
||||
import { useAppSelector } from '../../store/hooks';
|
||||
|
|
@ -73,9 +75,15 @@ const ImagesTable = () => {
|
|||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const blueprintSearchInput = useAppSelector(selectBlueprintSearchInput);
|
||||
const blueprintVersionFilter = useAppSelector(selectBlueprintVersionFilter);
|
||||
const blueprintsOffset = useAppSelector(selectOffset);
|
||||
const blueprintsLimit = useAppSelector(selectLimit);
|
||||
|
||||
const { selectedBlueprintVersion } = useGetBlueprintsQuery(
|
||||
{ search: blueprintSearchInput },
|
||||
{
|
||||
search: blueprintSearchInput,
|
||||
limit: blueprintsLimit,
|
||||
offset: blueprintsOffset,
|
||||
},
|
||||
{
|
||||
selectFromResult: ({ data }) => ({
|
||||
selectedBlueprintVersion: data?.data?.find(
|
||||
|
|
|
|||
|
|
@ -9,3 +9,9 @@
|
|||
.expand-section {
|
||||
background-color: var(--pf-global--palette--white);
|
||||
}
|
||||
|
||||
.sidebar-panel {
|
||||
height: 750px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,12 @@ export const LandingPage = () => {
|
|||
</PageSection>
|
||||
<PageSection className="pf-v5-u-pt-0">
|
||||
<Sidebar hasBorder className="pf-v5-u-background-color-100">
|
||||
<SidebarPanel hasPadding width={{ default: 'width_25' }}>
|
||||
<SidebarPanel
|
||||
variant="sticky"
|
||||
hasPadding
|
||||
width={{ default: 'width_25' }}
|
||||
className="sidebar-panel"
|
||||
>
|
||||
<BlueprintsSidebar />
|
||||
</SidebarPanel>
|
||||
<SidebarContent>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue