mirror of
https://github.com/hasura/graphql-engine.git
synced 2025-01-05 22:34:22 +03:00
Fix and improvement on the pagination for tracked table in the new UI
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9890 GitOrigin-RevId: ff1bb64321721718378de6447be9c9cc98e34c32
This commit is contained in:
parent
78323ed1a1
commit
82011af6ed
@ -1,7 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Button } from '../../../../new-components/Button';
|
||||
import { DEFAULT_PAGE_SIZES } from '../constants';
|
||||
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
|
||||
import {
|
||||
FaAngleDoubleLeft,
|
||||
FaAngleDoubleRight,
|
||||
FaAngleLeft,
|
||||
FaAngleRight,
|
||||
} from 'react-icons/fa';
|
||||
import { PaginatedSearchableListProps } from '../hooks/usePaginatedSearchableList';
|
||||
|
||||
export const PageSizeDropdown = ({
|
||||
@ -9,6 +14,8 @@ export const PageSizeDropdown = ({
|
||||
pageSize,
|
||||
decrementPage,
|
||||
incrementPage,
|
||||
goToFirstPage,
|
||||
goToLastPage,
|
||||
setPageSize,
|
||||
dataSize,
|
||||
totalPages,
|
||||
@ -17,6 +24,11 @@ export const PageSizeDropdown = ({
|
||||
<span className="whitespace-nowrap mr-2">
|
||||
Page {pageNumber} of {totalPages}
|
||||
</span>
|
||||
<Button
|
||||
icon={<FaAngleDoubleLeft />}
|
||||
onClick={goToFirstPage}
|
||||
disabled={pageNumber === 1}
|
||||
/>
|
||||
<Button
|
||||
icon={<FaAngleLeft />}
|
||||
onClick={decrementPage}
|
||||
@ -40,5 +52,10 @@ export const PageSizeDropdown = ({
|
||||
onClick={incrementPage}
|
||||
disabled={pageNumber >= dataSize / pageSize}
|
||||
/>
|
||||
<Button
|
||||
icon={<FaAngleDoubleRight />}
|
||||
onClick={goToLastPage}
|
||||
disabled={pageNumber >= dataSize / pageSize}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -0,0 +1,152 @@
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { usePaginatedSearchableList } from './usePaginatedSearchableList';
|
||||
|
||||
const mockData = [
|
||||
{ id: '1', name: 'John' },
|
||||
{ id: '2', name: 'Jane' },
|
||||
{ id: '3', name: 'Bob' },
|
||||
{ id: '4', name: 'Alice' },
|
||||
{ id: '5', name: 'Eve' },
|
||||
{ id: '6', name: 'Carol' },
|
||||
{ id: '7', name: 'Dave' },
|
||||
{ id: '8', name: 'Frank' },
|
||||
{ id: '9', name: 'Grace' },
|
||||
{ id: '10', name: 'Heidi' },
|
||||
{ id: '11', name: 'Ivan' },
|
||||
{ id: '12', name: 'Mallory' },
|
||||
{ id: '13', name: 'Oscar' },
|
||||
{ id: '14', name: 'Peggy' },
|
||||
{ id: '15', name: 'Trent' },
|
||||
];
|
||||
|
||||
describe('usePaginatedSearchableList', () => {
|
||||
it('should return the correct initial state', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.pageNumber).toBe(1);
|
||||
expect(result.current.pageSize).toBe(10);
|
||||
expect(result.current.searchIsActive).toBe(false);
|
||||
expect(result.current.filteredData).toEqual(mockData);
|
||||
expect(result.current.paginatedData).toEqual(mockData.slice(0, 10));
|
||||
expect(result.current.totalPages).toBe(2);
|
||||
expect(result.current.checkData.checkedIds).toEqual([]);
|
||||
expect(result.current.getCheckedItems()).toEqual([]);
|
||||
expect(result.current.dataSize).toBe(mockData.length);
|
||||
});
|
||||
|
||||
it('should go to page 2 and display page 2 data when navigating page', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.incrementPage();
|
||||
});
|
||||
|
||||
expect(result.current.pageNumber).toBe(2);
|
||||
expect(result.current.filteredData).toEqual(mockData);
|
||||
expect(result.current.paginatedData).toEqual(mockData.slice(10, 15));
|
||||
expect(result.current.totalPages).toBe(2);
|
||||
expect(result.current.dataSize).toBe(mockData.length);
|
||||
});
|
||||
|
||||
it('should update the filtered data when search text changes', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.incrementPage();
|
||||
result.current.handleSearch('o');
|
||||
});
|
||||
|
||||
expect(result.current.searchIsActive).toBe(true);
|
||||
expect(result.current.pageNumber).toBe(1);
|
||||
expect(result.current.totalPages).toBe(1);
|
||||
expect(result.current.dataSize).toBe(4);
|
||||
});
|
||||
|
||||
it('should go to page 1 when data are filtered on page 2 and filtered data length < page size', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.handleSearch('o');
|
||||
});
|
||||
|
||||
expect(result.current.searchIsActive).toBe(true);
|
||||
expect(result.current.filteredData).toEqual([
|
||||
{ id: '1', name: 'John' },
|
||||
{ id: '3', name: 'Bob' },
|
||||
{ id: '6', name: 'Carol' },
|
||||
{ id: '12', name: 'Mallory' },
|
||||
]);
|
||||
expect(result.current.paginatedData).toEqual([
|
||||
{ id: '1', name: 'John' },
|
||||
{ id: '3', name: 'Bob' },
|
||||
{ id: '6', name: 'Carol' },
|
||||
{ id: '12', name: 'Mallory' },
|
||||
]);
|
||||
expect(result.current.pageNumber).toBe(1);
|
||||
expect(result.current.totalPages).toBe(1);
|
||||
expect(result.current.dataSize).toBe(4);
|
||||
});
|
||||
|
||||
it('should update the paginated data when page number changes', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.setPageNumber(2);
|
||||
});
|
||||
|
||||
expect(result.current.pageNumber).toBe(2);
|
||||
expect(result.current.paginatedData).toEqual([
|
||||
{ id: '11', name: 'Ivan' },
|
||||
{ id: '12', name: 'Mallory' },
|
||||
{ id: '13', name: 'Oscar' },
|
||||
{ id: '14', name: 'Peggy' },
|
||||
{ id: '15', name: 'Trent' },
|
||||
]);
|
||||
expect(result.current.totalPages).toBe(2);
|
||||
expect(result.current.dataSize).toBe(mockData.length);
|
||||
});
|
||||
|
||||
it('should update the checked items when rows are checked', () => {
|
||||
const { result } = renderHook(() =>
|
||||
usePaginatedSearchableList({
|
||||
data: mockData,
|
||||
filterFn: (searchText, item) => item.name.includes(searchText),
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.checkData.onCheck('1');
|
||||
});
|
||||
|
||||
expect(result.current.checkData.checkedIds).toEqual(['1']);
|
||||
expect(result.current.getCheckedItems()).toEqual([
|
||||
{ id: '1', name: 'John' },
|
||||
]);
|
||||
expect(result.current.dataSize).toBe(mockData.length);
|
||||
});
|
||||
});
|
@ -37,10 +37,10 @@ export function usePaginatedSearchableList<TData extends { id: string }>({
|
||||
[checkData.checkedIds, data]
|
||||
);
|
||||
|
||||
const handleSearch = React.useCallback(
|
||||
(searchQuery: string) => setSearchText(searchQuery),
|
||||
[]
|
||||
);
|
||||
const handleSearch = React.useCallback((searchQuery: string) => {
|
||||
setPageNumber(DEFAULT_PAGE_NUMBER);
|
||||
setSearchText(searchQuery);
|
||||
}, []);
|
||||
|
||||
const incrementPage = React.useCallback(() => {
|
||||
setPageNumber(currentPage =>
|
||||
@ -54,6 +54,14 @@ export function usePaginatedSearchableList<TData extends { id: string }>({
|
||||
);
|
||||
}, []);
|
||||
|
||||
const goToFirstPage = React.useCallback(() => {
|
||||
setPageNumber(() => 1);
|
||||
}, []);
|
||||
|
||||
const goToLastPage = React.useCallback(() => {
|
||||
setPageNumber(() => totalPages);
|
||||
}, [totalPages]);
|
||||
|
||||
return {
|
||||
pageNumber,
|
||||
setPageNumber,
|
||||
@ -61,6 +69,8 @@ export function usePaginatedSearchableList<TData extends { id: string }>({
|
||||
setPageSize,
|
||||
incrementPage,
|
||||
decrementPage,
|
||||
goToFirstPage,
|
||||
goToLastPage,
|
||||
totalPages,
|
||||
searchIsActive,
|
||||
handleSearch,
|
||||
@ -68,7 +78,7 @@ export function usePaginatedSearchableList<TData extends { id: string }>({
|
||||
filteredData,
|
||||
paginatedData,
|
||||
getCheckedItems,
|
||||
dataSize: data.length,
|
||||
dataSize: filteredData.length,
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user