Feat: Added Pagination for services page (#1334)

* change ui to support paging for services page

* fix count issue on tab change

* change pagine with load more btn with micro interaction

* made seprate component for load more pagination button

* make seprate type for loading status and miner fix

* miner fix
This commit is contained in:
Shailesh Parmar 2021-11-23 20:00:45 +05:30 committed by GitHub
parent 499c9c546f
commit f6dfc62a4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 150 additions and 8 deletions

View File

@ -0,0 +1,57 @@
import { LoadingState } from 'Models';
import React from 'react';
import { Button } from '../../buttons/Button/Button';
import Loader from '../../Loader/Loader';
type LoadMorePaginationProps = {
isLoading: boolean;
showLoadingText?: boolean;
status: LoadingState;
buttonText: string;
handleClick: () => void;
};
const LoadMorePagination = ({
isLoading,
status,
buttonText,
showLoadingText,
handleClick,
}: LoadMorePaginationProps) => {
return (
<>
{isLoading ? (
<Button
disabled
className="tw-h-10"
size="regular"
theme="primary"
variant="contained">
<Loader size="small" type="white" />
{showLoadingText && <span className="tw-pl-1.5">Loading</span>}
</Button>
) : status === 'success' ? (
<Button
disabled
className="tw-h-10 disabled:tw-opacity-100"
size="regular"
theme="primary"
variant="contained">
<i aria-hidden="true" className="fa fa-check" />
</Button>
) : (
<Button
className="tw-h-10"
data-testid="saveManageTab"
size="regular"
theme="primary"
variant="contained"
onClick={handleClick}>
<span>{buttonText}</span>
</Button>
)}
</>
);
};
export default LoadMorePagination;

View File

@ -118,8 +118,11 @@ declare module 'Models' {
export type Paging = {
after: string;
before: string;
total?: number;
};
export type LoadingState = 'initial' | 'waiting' | 'success';
export type TableDetail = {
description: string;
name: string;

View File

@ -17,8 +17,14 @@
import { AxiosError, AxiosResponse } from 'axios';
import classNames from 'classnames';
import { isNull, lowerCase } from 'lodash';
import { ServiceCollection, ServiceData, ServiceTypes } from 'Models';
import { isNil, isNull, lowerCase } from 'lodash';
import {
LoadingState,
Paging,
ServiceCollection,
ServiceData,
ServiceTypes,
} from 'Models';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import {
@ -29,6 +35,7 @@ import {
updateService,
} from '../../axiosAPIs/serviceAPI';
import { Button } from '../../components/buttons/Button/Button';
import LoadMorePagination from '../../components/common/LoadMorePagination/LoadMorePagination';
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
import Searchbar from '../../components/common/searchbar/Searchbar';
@ -43,6 +50,7 @@ import {
import ConfirmationModal from '../../components/Modals/ConfirmationModal/ConfirmationModal';
import {
getServiceDetailsPath,
pagingObject,
TITLE_FOR_NON_ADMIN_ACTION,
} from '../../constants/constants';
import {
@ -50,6 +58,7 @@ import {
NoDataFoundPlaceHolder,
servicesDisplayName,
} from '../../constants/services.const';
import { CursorType } from '../../enums/pagination.enum';
import { ServiceCategory } from '../../enums/service.enum';
import {
DashboardService,
@ -71,6 +80,13 @@ type ServiceRecord = {
pipelineServices: Array<PipelineService>;
};
type ServicePagingRecord = {
databaseServices: Paging;
messagingServices: Paging;
dashboardServices: Paging;
pipelineServices: Paging;
};
export type ApiData = {
description: string;
href: string;
@ -92,6 +108,12 @@ const ServicesPage = () => {
});
const [serviceName, setServiceName] =
useState<ServiceTypes>('databaseServices');
const [paging, setPaging] = useState<ServicePagingRecord>({
databaseServices: pagingObject,
messagingServices: pagingObject,
dashboardServices: pagingObject,
pipelineServices: pagingObject,
});
const [services, setServices] = useState<ServiceRecord>({
databaseServices: [],
messagingServices: [],
@ -102,6 +124,8 @@ const ServicesPage = () => {
const [editData, setEditData] = useState<ServiceDataObj>();
const [isLoading, setIsLoading] = useState<boolean>(false);
const [searchText, setSearchText] = useState('');
const [currentTabTotalCount, setCurrentTabTotalCount] = useState(0);
const [servicesCount, setServicesCount] = useState({
databaseServices: 0,
messagingServices: 0,
@ -109,6 +133,9 @@ const ServicesPage = () => {
pipelineServices: 0,
});
const [isLoadingMore, setIsLoadingMore] = useState<boolean>(false);
const [status, setStatus] = useState<LoadingState>('initial');
const updateServiceList = (
allServiceCollectionArr: Array<ServiceCollection>
) => {
@ -122,24 +149,34 @@ const ServicesPage = () => {
(result: PromiseSettledResult<AxiosResponse>[]) => {
if (result.length) {
let serviceArr = [];
let servicePagingArr = [];
const serviceRecord = {} as ServiceRecord;
const servicePaging = {} as ServicePagingRecord;
serviceArr = result.map((service) =>
service.status === 'fulfilled' ? service.value?.data?.data : []
);
servicePagingArr = result.map((service) =>
service.status === 'fulfilled' ? service.value?.data?.paging : {}
);
for (let i = 0; i < serviceArr.length; i++) {
serviceRecord[allServiceCollectionArr[i].value as ServiceTypes] =
serviceArr[i];
servicePaging[allServiceCollectionArr[i].value as ServiceTypes] =
servicePagingArr[i];
}
setServices(serviceRecord);
setPaging(servicePaging);
setServicesCount({
databaseServices: serviceRecord.databaseServices.length,
messagingServices: serviceRecord.messagingServices.length,
dashboardServices: serviceRecord.dashboardServices.length,
pipelineServices: serviceRecord.pipelineServices.length,
databaseServices: servicePaging.databaseServices.total || 0,
messagingServices: servicePaging.messagingServices.total || 0,
dashboardServices: servicePaging.dashboardServices.total || 0,
pipelineServices: servicePaging.pipelineServices.total || 0,
});
setServiceList(
serviceRecord[serviceName] as unknown as Array<ServiceDataObj>
);
setCurrentTabTotalCount(servicePaging[serviceName].total || 0);
}
setIsLoading(false);
}
@ -308,7 +345,7 @@ const ServicesPage = () => {
setSearchText('');
setServicesCount({
...servicesCount,
[serviceName]: services[serviceName].length,
[serviceName]: currentTabTotalCount,
});
setServiceName(tabName);
setServiceList(services[tabName] as unknown as Array<ServiceDataObj>);
@ -382,6 +419,35 @@ const ServicesPage = () => {
}
};
const pagingHandler = (cursorType: string) => {
setIsLoadingMore(true);
setStatus('waiting');
const currentServicePaging = paging[serviceName];
const pagingString = `${serviceName}?${cursorType}=${
currentServicePaging[cursorType as keyof Paging]
}`;
getServices(pagingString)
.then((result: AxiosResponse) => {
const currentServices = [...services[serviceName], ...result.data.data];
setServiceList(currentServices);
setServices({
...services,
[serviceName]: currentServices,
});
setPaging({
...paging,
[serviceName]: result.data.paging,
});
setStatus('success');
})
.finally(() => {
setIsLoadingMore(false);
setStatus('initial');
});
};
useEffect(() => {
// fetch all service collection
setIsLoading(true);
@ -406,6 +472,10 @@ const ServicesPage = () => {
});
}, []);
useEffect(() => {
setCurrentTabTotalCount(servicesCount[serviceName]);
}, [serviceName]);
return (
<>
{!isLoading ? (
@ -458,7 +528,7 @@ const ServicesPage = () => {
</div>
{serviceList.length ? (
<div
className="tw-grid tw-grid-cols-4 tw-gap-4"
className="tw-grid tw-grid-cols-4 tw-gap-4 tw-mb-4"
data-testid="data-container">
{serviceList.map((service, index) => (
<div
@ -589,6 +659,18 @@ const ServicesPage = () => {
</div>
)}
{!isNil(paging[serviceName].after) && (
<div className="tw-my-4 tw-flex tw-justify-center tw-items-center">
<LoadMorePagination
showLoadingText
buttonText="Load more"
handleClick={() => pagingHandler(CursorType.AFTER)}
isLoading={isLoadingMore}
status={status}
/>
</div>
)}
{isModalOpen && (
<AddServiceModal
data={editData}