-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(useTable): add use table for offline managing (#10)
- Loading branch information
1 parent
e233cb3
commit bc57577
Showing
6 changed files
with
220 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export interface Page { | ||
page: number; | ||
perPage: number; | ||
} | ||
|
||
export interface SortBy { | ||
index: number; | ||
direction: 'asc' | 'desc'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { useTable } from './useTable'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import { Page } from '../../common/types'; | ||
import { useTable } from './useTable'; | ||
|
||
describe('useTableFilter', () => { | ||
it('Pagination', () => { | ||
const items = [...Array(15)].map((_, index) => index + 1); | ||
const page: Page = { page: 1, perPage: 10 }; | ||
|
||
const { result } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: () => true, | ||
compareToByColumn: () => 1, | ||
}) | ||
); | ||
|
||
// Page1 | ||
expect(result.current.pageItems).toEqual(items.slice(0, 10)); | ||
}); | ||
|
||
it('Filter', () => { | ||
const items = [...Array(15)].map((_, index) => index + 1); | ||
const page: Page = { page: 1, perPage: 10 }; | ||
|
||
const { result } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: (value) => value % 2 === 1, | ||
compareToByColumn: () => 1, | ||
}) | ||
); | ||
|
||
// Page1 | ||
const expectedResult = [1, 3, 5, 7, 9, 11, 13, 15]; | ||
expect(result.current.pageItems).toEqual(expectedResult); | ||
}); | ||
|
||
it('SortBy', () => { | ||
const items = [...Array(15)].map((_, index) => index + 1); | ||
const page: Page = { page: 1, perPage: 10 }; | ||
const filterItem = () => true; | ||
const compareToByColumn = (a: number, b: number, indexCol?: number) => | ||
indexCol === 7 ? a - b : 0; | ||
|
||
// Verify asc | ||
const { result: resultAsc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: filterItem, | ||
currentSortBy: { direction: 'asc', index: 7 }, | ||
compareToByColumn: compareToByColumn, | ||
}) | ||
); | ||
|
||
const expectedAscResult = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | ||
expect(resultAsc.current.pageItems).toEqual(expectedAscResult); | ||
|
||
// Verify desc | ||
const { result: resultDesc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: filterItem, | ||
currentSortBy: { direction: 'desc', index: 7 }, | ||
compareToByColumn: compareToByColumn, | ||
}) | ||
); | ||
|
||
const expectedDescResult = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6]; | ||
expect(resultDesc.current.pageItems).toEqual(expectedDescResult); | ||
}); | ||
|
||
it("SortBy when 'compareToByColumn' return always 0", () => { | ||
const items = [...Array(15)].map((_, index) => index + 1); | ||
const page: Page = { page: 1, perPage: 10 }; | ||
|
||
const expectedResult = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | ||
|
||
// Verify asc | ||
const { result: resultAsc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: () => true, | ||
currentSortBy: { direction: 'asc', index: 7 }, | ||
compareToByColumn: () => 0, // forcing comparison true | ||
}) | ||
); | ||
|
||
expect(resultAsc.current.pageItems).toEqual(expectedResult); | ||
|
||
// Verify desc | ||
const { result: resultDesc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: () => true, | ||
currentSortBy: { direction: 'desc', index: 7 }, | ||
compareToByColumn: () => 0, // forcing comparison true | ||
}) | ||
); | ||
|
||
expect(resultDesc.current.pageItems).toEqual(expectedResult); | ||
}); | ||
|
||
it("SortBy when 'compareToByColumn' return always 0 and 'filter' is applied", () => { | ||
const items = [...Array(25)].map((_, index) => index + 1); | ||
const page: Page = { page: 1, perPage: 10 }; | ||
const filterItem = (val: number) => val % 2 === 0; | ||
const compareToByColumn = () => 0; // forcing comparison true | ||
|
||
const expectedResult = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; | ||
|
||
// Verify asc | ||
const { result: resultAsc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: filterItem, | ||
currentSortBy: { direction: 'asc', index: 7 }, | ||
compareToByColumn: compareToByColumn, | ||
}) | ||
); | ||
|
||
expect(resultAsc.current.pageItems).toEqual(expectedResult); | ||
|
||
// Verify desc | ||
const { result: resultDesc } = renderHook(() => | ||
useTable<number>({ | ||
items: items, | ||
currentPage: page, | ||
filterItem: filterItem, | ||
currentSortBy: { direction: 'desc', index: 7 }, | ||
compareToByColumn: compareToByColumn, | ||
}) | ||
); | ||
|
||
expect(resultDesc.current.pageItems).toEqual(expectedResult); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { useMemo } from 'react'; | ||
import { SortByDirection } from '@patternfly/react-table'; | ||
import { Page, SortBy } from '../../common/types'; | ||
|
||
// Hook | ||
|
||
interface HookArgs<T> { | ||
items?: T[]; | ||
|
||
currentSortBy?: SortBy; | ||
compareToByColumn: (a: T, b: T, columnIndex?: number) => number; | ||
|
||
currentPage: Page; | ||
filterItem: (value: T) => boolean; | ||
} | ||
|
||
interface HookState<T> { | ||
pageItems: T[]; | ||
filteredItems: T[]; | ||
} | ||
|
||
export const useTable = <T>({ | ||
items, | ||
currentSortBy, | ||
currentPage, | ||
filterItem, | ||
compareToByColumn, | ||
}: HookArgs<T>): HookState<T> => { | ||
const state: HookState<T> = useMemo(() => { | ||
const allItems = [...(items || [])]; | ||
|
||
// Filter | ||
const filteredItems = allItems.filter(filterItem); | ||
|
||
// Sort | ||
let orderChanged = false; | ||
|
||
let sortedItems: T[]; | ||
sortedItems = [...filteredItems].sort((a, b) => { | ||
const comparisonResult = compareToByColumn(a, b, currentSortBy?.index); | ||
if (comparisonResult !== 0) { | ||
orderChanged = true; | ||
} | ||
return comparisonResult; | ||
}); | ||
|
||
if (orderChanged && currentSortBy?.direction === SortByDirection.desc) { | ||
sortedItems = sortedItems.reverse(); | ||
} | ||
|
||
// Paginate | ||
const pageItems = sortedItems.slice( | ||
(currentPage.page - 1) * currentPage.perPage, | ||
currentPage.page * currentPage.perPage | ||
); | ||
|
||
return { | ||
pageItems, | ||
filteredItems, | ||
}; | ||
}, [items, currentPage, currentSortBy, compareToByColumn, filterItem]); | ||
|
||
return state; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters