feat(ui): new pagination with page number and page size (#10921)

* feat(ui): new pagination with page number and page size

* fix unit tests

* fix unit tests

* fix pagination issue

---------

Co-authored-by: Shailesh Parmar <shailesh.parmar.webdev@gmail.com>
This commit is contained in:
Chirag Madlani 2023-04-14 16:24:14 +05:30 committed by GitHub
parent 6b8b9a179b
commit fa93a37fcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 66 deletions

View File

@ -27,7 +27,6 @@ import unique from 'fork-ts-checker-webpack-plugin/lib/utils/array/unique';
import { import {
isEmpty, isEmpty,
isNil, isNil,
isNumber,
isString, isString,
isUndefined, isUndefined,
lowerCase, lowerCase,
@ -81,7 +80,6 @@ const Explore: React.FC<ExploreProps> = ({
onChangeSortValue, onChangeSortValue,
onChangeShowDeleted, onChangeShowDeleted,
showDeleted, showDeleted,
page = 1,
onChangePage = noop, onChangePage = noop,
loading, loading,
quickFilters, quickFilters,
@ -400,19 +398,12 @@ const Explore: React.FC<ExploreProps> = ({
<SearchedData <SearchedData
isFilterSelected isFilterSelected
showResultCount showResultCount
currentPage={page}
data={searchResults?.hits.hits ?? []} data={searchResults?.hits.hits ?? []}
handleSummaryPanelDisplay={handleSummaryPanelDisplay} handleSummaryPanelDisplay={handleSummaryPanelDisplay}
isSummaryPanelVisible={showSummaryPanel} isSummaryPanelVisible={showSummaryPanel}
paginate={(value) => {
if (isNumber(value)) {
onChangePage(value);
} else if (!isNaN(Number.parseInt(value))) {
onChangePage(Number.parseInt(value));
}
}}
selectedEntityId={entityDetails?.id || ''} selectedEntityId={entityDetails?.id || ''}
totalValue={searchResults?.hits.total.value ?? 0} totalValue={searchResults?.hits.total.value ?? 0}
onPaginationChange={onChangePage}
/> />
) : ( ) : (
<Loader /> <Loader />

View File

@ -82,8 +82,7 @@ export interface ExploreProps {
showDeleted: boolean; showDeleted: boolean;
onChangeShowDeleted: (showDeleted: boolean) => void; onChangeShowDeleted: (showDeleted: boolean) => void;
page?: number; onChangePage?: (page: number, size?: number) => void;
onChangePage?: (page: number) => void;
loading?: boolean; loading?: boolean;

View File

@ -73,9 +73,8 @@ export interface SearchedDataProps {
children?: ReactNode; children?: ReactNode;
selectedEntityId: string; selectedEntityId: string;
data: SearchHitBody<ExploreSearchIndex, SourceType>[]; data: SearchHitBody<ExploreSearchIndex, SourceType>[];
currentPage: number;
isLoading?: boolean; isLoading?: boolean;
paginate: (value: string | number) => void; onPaginationChange: (value: number, pageSize?: number) => void;
totalValue: number; totalValue: number;
fetchLeftPanel?: () => ReactNode; fetchLeftPanel?: () => ReactNode;
isSummaryPanelVisible: boolean; isSummaryPanelVisible: boolean;

View File

@ -106,7 +106,7 @@ const MOCK_PROPS = {
currentPage: 0, currentPage: 0,
data: mockData, data: mockData,
handleSummaryPanelDisplay: mockHandleSummaryPanelDisplay, handleSummaryPanelDisplay: mockHandleSummaryPanelDisplay,
paginate: mockPaginate, onPaginationChange: mockPaginate,
selectedEntityId: 'name1', selectedEntityId: 'name1',
totalValue: 10, totalValue: 10,
}; };
@ -145,19 +145,6 @@ describe('Test SearchedData Component', () => {
expect(getByText(container, /hello world/i)).toBeInTheDocument(); expect(getByText(container, /hello world/i)).toBeInTheDocument();
}); });
it('Pagination Should be there if data is more than 10 count', () => {
const { container } = render(
<SearchedData {...MOCK_PROPS} totalValue={11}>
<p>hello world</p>
</SearchedData>,
{
wrapper: MemoryRouter,
}
);
expect(getByText(container, /Pagination/i)).toBeInTheDocument();
});
it('Onboarding component should display if there is showOnboardingTemplate is true', () => { it('Onboarding component should display if there is showOnboardingTemplate is true', () => {
const { container } = render( const { container } = render(
<SearchedData <SearchedData

View File

@ -11,18 +11,17 @@
* limitations under the License. * limitations under the License.
*/ */
import { Pagination } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import { ELASTICSEARCH_ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum'; import { ELASTICSEARCH_ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
import { isUndefined } from 'lodash'; import { isNumber, isUndefined } from 'lodash';
import PropTypes from 'prop-types'; import Qs from 'qs';
import React from 'react'; import React, { useMemo } from 'react';
import { getEntityName } from 'utils/EntityUtils'; import { getEntityName } from 'utils/EntityUtils';
import { PAGE_SIZE } from '../../constants/constants'; import { PAGE_SIZE } from '../../constants/constants';
import { MAX_RESULT_HITS } from '../../constants/explore.constants'; import { MAX_RESULT_HITS } from '../../constants/explore.constants';
import { Paging } from '../../generated/type/paging';
import { pluralize } from '../../utils/CommonUtils'; import { pluralize } from '../../utils/CommonUtils';
import ErrorPlaceHolderES from '../common/error-with-placeholder/ErrorPlaceHolderES'; import ErrorPlaceHolderES from '../common/error-with-placeholder/ErrorPlaceHolderES';
import NextPrevious from '../common/next-previous/NextPrevious';
import TableDataCardV2 from '../common/table-data-card-v2/TableDataCardV2'; import TableDataCardV2 from '../common/table-data-card-v2/TableDataCardV2';
import Loader from '../Loader/Loader'; import Loader from '../Loader/Loader';
import Onboarding from '../onboarding/Onboarding'; import Onboarding from '../onboarding/Onboarding';
@ -38,9 +37,8 @@ const ASSETS_NAME = [
const SearchedData: React.FC<SearchedDataProps> = ({ const SearchedData: React.FC<SearchedDataProps> = ({
children, children,
data, data,
currentPage,
isLoading = false, isLoading = false,
paginate, onPaginationChange,
showResultCount = false, showResultCount = false,
showOnboardingTemplate = false, showOnboardingTemplate = false,
showOnlyChildren = false, showOnlyChildren = false,
@ -51,7 +49,7 @@ const SearchedData: React.FC<SearchedDataProps> = ({
selectedEntityId, selectedEntityId,
handleSummaryPanelDisplay, handleSummaryPanelDisplay,
}) => { }) => {
const highlightSearchResult = () => { const searchResultCards = useMemo(() => {
return data.map(({ _source: table, highlight }, index) => { return data.map(({ _source: table, highlight }, index) => {
let tDesc = table.description ?? ''; let tDesc = table.description ?? '';
const highLightedTexts = highlight?.description || []; const highLightedTexts = highlight?.description || [];
@ -108,7 +106,12 @@ const SearchedData: React.FC<SearchedDataProps> = ({
</div> </div>
); );
}); });
}; }, [
data,
isSummaryPanelVisible,
handleSummaryPanelDisplay,
selectedEntityId,
]);
const ResultCount = () => { const ResultCount = () => {
if (showResultCount && (isFilterSelected || searchText)) { if (showResultCount && (isFilterSelected || searchText)) {
@ -122,6 +125,16 @@ const SearchedData: React.FC<SearchedDataProps> = ({
} }
}; };
const { page, size } = useMemo(
() =>
Qs.parse(
location.search.startsWith('?')
? location.search.substr(1)
: location.search
),
[location.search]
);
return ( return (
<> <>
{isLoading ? ( {isLoading ? (
@ -138,17 +151,20 @@ const SearchedData: React.FC<SearchedDataProps> = ({
<div <div
className="tw-grid tw-grid-rows-1 tw-grid-cols-1" className="tw-grid tw-grid-rows-1 tw-grid-cols-1"
data-testid="search-results"> data-testid="search-results">
{highlightSearchResult()} {searchResultCards}
{totalValue > PAGE_SIZE && data.length > 0 && ( <Pagination
<NextPrevious hideOnSinglePage
isNumberBased className="text-center"
currentPage={currentPage} current={isNumber(Number(page)) ? Number(page) : 1}
pageSize={PAGE_SIZE} pageSize={
paging={{} as Paging} size && isNumber(Number(size))
pagingHandler={paginate} ? Number(size)
totalCount={totalValue} : PAGE_SIZE
/> }
)} pageSizeOptions={[10, 25, 50]}
total={totalValue}
onChange={onPaginationChange}
/>
</div> </div>
) : ( ) : (
<Onboarding /> <Onboarding />
@ -171,16 +187,4 @@ const SearchedData: React.FC<SearchedDataProps> = ({
); );
}; };
SearchedData.propTypes = {
children: PropTypes.element,
data: PropTypes.array.isRequired,
currentPage: PropTypes.number.isRequired,
isLoading: PropTypes.bool,
paginate: PropTypes.func.isRequired,
showResultCount: PropTypes.bool,
showOnboardingTemplate: PropTypes.bool,
totalValue: PropTypes.number.isRequired,
fetchLeftPanel: PropTypes.func,
};
export default SearchedData; export default SearchedData;

View File

@ -119,8 +119,10 @@ const ExplorePage: FunctionComponent = () => {
[facetFilters] [facetFilters]
); );
const handlePageChange: ExploreProps['onChangePage'] = (page) => { const handlePageChange: ExploreProps['onChangePage'] = (page, size) => {
history.push({ search: Qs.stringify({ ...parsedSearch, page }) }); history.push({
search: Qs.stringify({ ...parsedSearch, page, size: size ?? PAGE_SIZE }),
});
}; };
// Filters that can be common for all the Entities Ex. Tables, Topics, etc. // Filters that can be common for all the Entities Ex. Tables, Topics, etc.
@ -234,9 +236,18 @@ const ExplorePage: FunctionComponent = () => {
return Number.parseInt(pageParam); return Number.parseInt(pageParam);
}, [parsedSearch.page]); }, [parsedSearch.page]);
const size = useMemo(() => {
const sizeParam = parsedSearch.size;
if (!isString(sizeParam) || isNaN(Number.parseInt(sizeParam))) {
return PAGE_SIZE;
}
return Number.parseInt(sizeParam);
}, [parsedSearch.size]);
useEffect(() => { useEffect(() => {
handlePageChange(page); handlePageChange(page, size);
}, [page]); }, [page, size]);
const showDeleted = useMemo(() => { const showDeleted = useMemo(() => {
const showDeletedParam = parsedSearch.showDeleted; const showDeletedParam = parsedSearch.showDeleted;
@ -305,7 +316,7 @@ const ExplorePage: FunctionComponent = () => {
sortField: sortValue, sortField: sortValue,
sortOrder, sortOrder,
pageNumber: page, pageNumber: page,
pageSize: PAGE_SIZE, pageSize: size,
includeDeleted: showDeleted, includeDeleted: showDeleted,
}) })
.then((res) => res) .then((res) => res)
@ -373,6 +384,7 @@ const ExplorePage: FunctionComponent = () => {
elasticsearchQueryFilter, elasticsearchQueryFilter,
searchIndex, searchIndex,
page, page,
size,
]); ]);
const handleAdvanceSearchQuickFiltersChange = useCallback( const handleAdvanceSearchQuickFiltersChange = useCallback(
@ -422,7 +434,6 @@ const ExplorePage: FunctionComponent = () => {
aggregations={updatedAggregations} aggregations={updatedAggregations}
facetFilters={facetFilters} facetFilters={facetFilters}
loading={isLoading} loading={isLoading}
page={page}
quickFilters={advancesSearchQuickFilters} quickFilters={advancesSearchQuickFilters}
searchIndex={searchIndex} searchIndex={searchIndex}
searchResults={searchResults} searchResults={searchResults}