feat(HMS-3401): Add blueprints sidebar pagination

This commit is contained in:
Anna Vítová 2024-03-12 13:11:02 +01:00 committed by Lucas Garfield
parent 7bff1feaf4
commit a3a7ea88c5
9 changed files with 202 additions and 7 deletions

View 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;

View file

@ -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),
[]

View file

@ -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 = () => {

View file

@ -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(

View file

@ -9,3 +9,9 @@
.expand-section {
background-color: var(--pf-global--palette--white);
}
.sidebar-panel {
height: 750px;
overflow: auto;
}

View file

@ -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>