Skip to content

Commit 1eb9358

Browse files
authored
Merge pull request #300 from topcoder-platform/GAME-107_bjcs
GAME-107
2 parents 40ef0de + 5ac9f54 commit 1eb9358

27 files changed

+288
-157
lines changed

src-ts/lib/pagination/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
export * from './infinite-page-dao.model'
2+
export * from './infinite-page-handler.model'
13
export * from './page.model'
24
export * from './sort.model'
5+
export * from './use-infinite-page.hook'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface InfinitePageDao<T> {
2+
count: number
3+
// TODO: rename this 'items' so it can be used in a grid/card view
4+
rows: ReadonlyArray<T>
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface InfinitePageHandler<T> {
2+
data?: ReadonlyArray<T>
3+
getAndSetNext: () => void
4+
hasMore: boolean
5+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { flatten, map } from 'lodash'
2+
// tslint:disable-next-line: no-submodule-imports
3+
import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite'
4+
5+
import { InfinitePageDao } from './infinite-page-dao.model'
6+
import { InfinitePageHandler } from './infinite-page-handler.model'
7+
8+
export function useGetInfinitePage<T>(getKey: (index: number, previousPageData: InfinitePageDao<T>) => string | undefined):
9+
InfinitePageHandler<T> {
10+
11+
const { data, setSize, size }: SWRInfiniteResponse<InfinitePageDao<T>> = useSWRInfinite(getKey, { revalidateFirstPage: false })
12+
13+
// flatten version of badges paginated data
14+
const outputData: ReadonlyArray<T> = flatten(map(data, dao => dao.rows))
15+
16+
function getAndSetNext(): void {
17+
setSize(size + 1)
18+
}
19+
20+
return {
21+
data: outputData,
22+
getAndSetNext,
23+
hasMore: outputData.length < (data?.[0]?.count || 0),
24+
}
25+
}

src-ts/lib/table/Table.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import classNames from 'classnames'
22
import { Dispatch, MouseEvent, SetStateAction, useEffect, useState } from 'react'
33

4-
import { Button, ButtonSize, ButtonStyle } from '../button'
4+
import { Button } from '../button'
55
import { Sort } from '../pagination'
66
import '../styles/_includes.scss'
77
import { IconOutline } from '../svgs'
@@ -16,13 +16,10 @@ import styles from './Table.module.scss'
1616
interface TableProps<T> {
1717
readonly columns: ReadonlyArray<TableColumn<T>>
1818
readonly data: ReadonlyArray<T>
19-
readonly loadMoreBtnLabel?: string
20-
readonly loadMoreBtnSize?: ButtonSize
21-
readonly loadMoreBtnStyle?: ButtonStyle
2219
readonly moreToLoad?: boolean
23-
readonly onLoadMoreClick?: (data: T) => void
20+
readonly onLoadMoreClick?: () => void
2421
readonly onRowClick?: (data: T) => void
25-
readonly onToggleSort?: (sort: Sort | undefined) => void
22+
readonly onToggleSort?: (sort: Sort) => void
2623
}
2724

2825
interface DefaultSortDirectionMap {
@@ -41,7 +38,7 @@ const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) =
4138
Dispatch<SetStateAction<DefaultSortDirectionMap | undefined>>
4239
]
4340
= useState<DefaultSortDirectionMap | undefined>()
44-
const [sortedData, setSortData]: [ReadonlyArray<T>, Dispatch<SetStateAction<ReadonlyArray<T>>>]
41+
const [sortedData, setSortedData]: [ReadonlyArray<T>, Dispatch<SetStateAction<ReadonlyArray<T>>>]
4542
= useState<ReadonlyArray<T>>(props.data)
4643

4744
useEffect(() => {
@@ -54,7 +51,11 @@ const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) =
5451
setDefaultSortDirectionMap(map)
5552
}
5653

57-
setSortData(tableGetSorted(data, columns, sort))
54+
// if we have a sort handler, don't worry about getting the sorted data;
55+
// otherwise, get the sorted data for the table
56+
const sorted: ReadonlyArray<T> = !!props.onToggleSort ? data : tableGetSorted(data, columns, sort)
57+
58+
setSortedData(sorted)
5859
},
5960
[
6061
columns,
@@ -84,9 +85,7 @@ const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) =
8485
setSort(newSort)
8586

8687
// call the callback to notify parent for sort update
87-
if (props.onToggleSort) {
88-
props.onToggleSort(newSort)
89-
}
88+
props.onToggleSort?.(newSort)
9089
}
9190

9291
const headerRow: Array<JSX.Element> = props.columns
@@ -95,13 +94,12 @@ const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) =
9594
const isCurrentlySorted: boolean = isSortable && col.propertyName === sort?.fieldName
9695
const colorClass: string = isCurrentlySorted ? 'black-100' : 'black-60'
9796
const sortableClass: string | undefined = isSortable ? styles.sortable : undefined
98-
const centerClass: string | undefined = col.centerHeader ? styles.centerHeader : undefined
9997
return (
10098
<th
10199
className={styles.th}
102100
key={index}
103101
>
104-
<div className={classNames(styles['header-container'], styles[col.type], colorClass, sortableClass, centerClass)}>
102+
<div className={classNames(styles['header-container'], styles[col.type], colorClass, sortableClass)}>
105103
{col.label}
106104
{!!col.tooltip && (
107105
<div className={styles.tooltip}>
@@ -172,9 +170,16 @@ const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) =
172170
</tbody>
173171
</table>
174172
{
175-
props.moreToLoad && <div className={styles['loadBtnWrap']}>
176-
<Button buttonStyle={props.loadMoreBtnStyle} label={props.loadMoreBtnLabel} size={props.loadMoreBtnSize} onClick={props.onLoadMoreClick} />
177-
</div>
173+
!!props.moreToLoad && !!props.onLoadMoreClick && (
174+
<div className={styles['loadBtnWrap']}>
175+
<Button
176+
buttonStyle='tertiary'
177+
label='Load More'
178+
size='lg'
179+
onClick={props.onLoadMoreClick}
180+
/>
181+
</div>
182+
)
178183
}
179184
</div>
180185
)

src-ts/lib/table/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './table-column.model'
2+
export { tableGetDefaultSort } from './table-functions'
23
export { default as Table } from './Table'

src-ts/lib/table/table-column.model.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { TableCellType } from './table-cell.type'
22

33
export interface TableColumn<T> {
4-
readonly centerHeader?: boolean
54
readonly defaultSortDirection?: 'asc' | 'desc'
65
readonly isDefaultSort?: boolean
76
readonly label?: string

src-ts/lib/table/table-functions/table.functions.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { Sort } from '../../pagination'
22
import { TableColumn } from '../table-column.model'
33

4-
export function getDefaultSort<T>(columns: ReadonlyArray<TableColumn<T>>): Sort | undefined {
4+
export function getDefaultSort<T>(columns: ReadonlyArray<TableColumn<T>>): Sort {
55

66
const defaultSortColumn: TableColumn<T> | undefined = columns.find(col => col.isDefaultSort)
77
|| columns.find(col => !!col.propertyName)
8+
|| columns?.[0]
89

9-
const defaultSort: Sort | undefined = !defaultSortColumn?.propertyName
10-
? undefined
11-
: {
12-
direction: defaultSortColumn.defaultSortDirection || 'asc',
13-
fieldName: defaultSortColumn.propertyName,
14-
}
10+
// if we didn't find a default sort, we have a problem
11+
if (!defaultSortColumn) {
12+
throw new Error('A table must have at least one column.')
13+
}
14+
15+
const defaultSort: Sort = {
16+
direction: defaultSortColumn.defaultSortDirection || 'asc',
17+
fieldName: defaultSortColumn.propertyName || '',
18+
}
1519

1620
return defaultSort
1721
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export interface GamificationConfigModel {
22
ORG_ID: string
3+
PAGE_SIZE: number
34
}

0 commit comments

Comments
 (0)