mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-30 03:46:10 +00:00
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:
parent
6b8b9a179b
commit
fa93a37fcd
@ -27,7 +27,6 @@ import unique from 'fork-ts-checker-webpack-plugin/lib/utils/array/unique';
|
||||
import {
|
||||
isEmpty,
|
||||
isNil,
|
||||
isNumber,
|
||||
isString,
|
||||
isUndefined,
|
||||
lowerCase,
|
||||
@ -81,7 +80,6 @@ const Explore: React.FC<ExploreProps> = ({
|
||||
onChangeSortValue,
|
||||
onChangeShowDeleted,
|
||||
showDeleted,
|
||||
page = 1,
|
||||
onChangePage = noop,
|
||||
loading,
|
||||
quickFilters,
|
||||
@ -400,19 +398,12 @@ const Explore: React.FC<ExploreProps> = ({
|
||||
<SearchedData
|
||||
isFilterSelected
|
||||
showResultCount
|
||||
currentPage={page}
|
||||
data={searchResults?.hits.hits ?? []}
|
||||
handleSummaryPanelDisplay={handleSummaryPanelDisplay}
|
||||
isSummaryPanelVisible={showSummaryPanel}
|
||||
paginate={(value) => {
|
||||
if (isNumber(value)) {
|
||||
onChangePage(value);
|
||||
} else if (!isNaN(Number.parseInt(value))) {
|
||||
onChangePage(Number.parseInt(value));
|
||||
}
|
||||
}}
|
||||
selectedEntityId={entityDetails?.id || ''}
|
||||
totalValue={searchResults?.hits.total.value ?? 0}
|
||||
onPaginationChange={onChangePage}
|
||||
/>
|
||||
) : (
|
||||
<Loader />
|
||||
|
@ -82,8 +82,7 @@ export interface ExploreProps {
|
||||
showDeleted: boolean;
|
||||
onChangeShowDeleted: (showDeleted: boolean) => void;
|
||||
|
||||
page?: number;
|
||||
onChangePage?: (page: number) => void;
|
||||
onChangePage?: (page: number, size?: number) => void;
|
||||
|
||||
loading?: boolean;
|
||||
|
||||
|
@ -73,9 +73,8 @@ export interface SearchedDataProps {
|
||||
children?: ReactNode;
|
||||
selectedEntityId: string;
|
||||
data: SearchHitBody<ExploreSearchIndex, SourceType>[];
|
||||
currentPage: number;
|
||||
isLoading?: boolean;
|
||||
paginate: (value: string | number) => void;
|
||||
onPaginationChange: (value: number, pageSize?: number) => void;
|
||||
totalValue: number;
|
||||
fetchLeftPanel?: () => ReactNode;
|
||||
isSummaryPanelVisible: boolean;
|
||||
|
@ -106,7 +106,7 @@ const MOCK_PROPS = {
|
||||
currentPage: 0,
|
||||
data: mockData,
|
||||
handleSummaryPanelDisplay: mockHandleSummaryPanelDisplay,
|
||||
paginate: mockPaginate,
|
||||
onPaginationChange: mockPaginate,
|
||||
selectedEntityId: 'name1',
|
||||
totalValue: 10,
|
||||
};
|
||||
@ -145,19 +145,6 @@ describe('Test SearchedData Component', () => {
|
||||
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', () => {
|
||||
const { container } = render(
|
||||
<SearchedData
|
||||
|
@ -11,18 +11,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Pagination } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { ELASTICSEARCH_ERROR_PLACEHOLDER_TYPE } from 'enums/common.enum';
|
||||
import { isUndefined } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { isNumber, isUndefined } from 'lodash';
|
||||
import Qs from 'qs';
|
||||
import React, { useMemo } from 'react';
|
||||
import { getEntityName } from 'utils/EntityUtils';
|
||||
import { PAGE_SIZE } from '../../constants/constants';
|
||||
import { MAX_RESULT_HITS } from '../../constants/explore.constants';
|
||||
import { Paging } from '../../generated/type/paging';
|
||||
import { pluralize } from '../../utils/CommonUtils';
|
||||
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 Loader from '../Loader/Loader';
|
||||
import Onboarding from '../onboarding/Onboarding';
|
||||
@ -38,9 +37,8 @@ const ASSETS_NAME = [
|
||||
const SearchedData: React.FC<SearchedDataProps> = ({
|
||||
children,
|
||||
data,
|
||||
currentPage,
|
||||
isLoading = false,
|
||||
paginate,
|
||||
onPaginationChange,
|
||||
showResultCount = false,
|
||||
showOnboardingTemplate = false,
|
||||
showOnlyChildren = false,
|
||||
@ -51,7 +49,7 @@ const SearchedData: React.FC<SearchedDataProps> = ({
|
||||
selectedEntityId,
|
||||
handleSummaryPanelDisplay,
|
||||
}) => {
|
||||
const highlightSearchResult = () => {
|
||||
const searchResultCards = useMemo(() => {
|
||||
return data.map(({ _source: table, highlight }, index) => {
|
||||
let tDesc = table.description ?? '';
|
||||
const highLightedTexts = highlight?.description || [];
|
||||
@ -108,7 +106,12 @@ const SearchedData: React.FC<SearchedDataProps> = ({
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
}, [
|
||||
data,
|
||||
isSummaryPanelVisible,
|
||||
handleSummaryPanelDisplay,
|
||||
selectedEntityId,
|
||||
]);
|
||||
|
||||
const ResultCount = () => {
|
||||
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 (
|
||||
<>
|
||||
{isLoading ? (
|
||||
@ -138,17 +151,20 @@ const SearchedData: React.FC<SearchedDataProps> = ({
|
||||
<div
|
||||
className="tw-grid tw-grid-rows-1 tw-grid-cols-1"
|
||||
data-testid="search-results">
|
||||
{highlightSearchResult()}
|
||||
{totalValue > PAGE_SIZE && data.length > 0 && (
|
||||
<NextPrevious
|
||||
isNumberBased
|
||||
currentPage={currentPage}
|
||||
pageSize={PAGE_SIZE}
|
||||
paging={{} as Paging}
|
||||
pagingHandler={paginate}
|
||||
totalCount={totalValue}
|
||||
/>
|
||||
)}
|
||||
{searchResultCards}
|
||||
<Pagination
|
||||
hideOnSinglePage
|
||||
className="text-center"
|
||||
current={isNumber(Number(page)) ? Number(page) : 1}
|
||||
pageSize={
|
||||
size && isNumber(Number(size))
|
||||
? Number(size)
|
||||
: PAGE_SIZE
|
||||
}
|
||||
pageSizeOptions={[10, 25, 50]}
|
||||
total={totalValue}
|
||||
onChange={onPaginationChange}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<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;
|
||||
|
@ -119,8 +119,10 @@ const ExplorePage: FunctionComponent = () => {
|
||||
[facetFilters]
|
||||
);
|
||||
|
||||
const handlePageChange: ExploreProps['onChangePage'] = (page) => {
|
||||
history.push({ search: Qs.stringify({ ...parsedSearch, page }) });
|
||||
const handlePageChange: ExploreProps['onChangePage'] = (page, size) => {
|
||||
history.push({
|
||||
search: Qs.stringify({ ...parsedSearch, page, size: size ?? PAGE_SIZE }),
|
||||
});
|
||||
};
|
||||
|
||||
// Filters that can be common for all the Entities Ex. Tables, Topics, etc.
|
||||
@ -234,9 +236,18 @@ const ExplorePage: FunctionComponent = () => {
|
||||
return Number.parseInt(pageParam);
|
||||
}, [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(() => {
|
||||
handlePageChange(page);
|
||||
}, [page]);
|
||||
handlePageChange(page, size);
|
||||
}, [page, size]);
|
||||
|
||||
const showDeleted = useMemo(() => {
|
||||
const showDeletedParam = parsedSearch.showDeleted;
|
||||
@ -305,7 +316,7 @@ const ExplorePage: FunctionComponent = () => {
|
||||
sortField: sortValue,
|
||||
sortOrder,
|
||||
pageNumber: page,
|
||||
pageSize: PAGE_SIZE,
|
||||
pageSize: size,
|
||||
includeDeleted: showDeleted,
|
||||
})
|
||||
.then((res) => res)
|
||||
@ -373,6 +384,7 @@ const ExplorePage: FunctionComponent = () => {
|
||||
elasticsearchQueryFilter,
|
||||
searchIndex,
|
||||
page,
|
||||
size,
|
||||
]);
|
||||
|
||||
const handleAdvanceSearchQuickFiltersChange = useCallback(
|
||||
@ -422,7 +434,6 @@ const ExplorePage: FunctionComponent = () => {
|
||||
aggregations={updatedAggregations}
|
||||
facetFilters={facetFilters}
|
||||
loading={isLoading}
|
||||
page={page}
|
||||
quickFilters={advancesSearchQuickFilters}
|
||||
searchIndex={searchIndex}
|
||||
searchResults={searchResults}
|
||||
|
Loading…
x
Reference in New Issue
Block a user