Skip to content

Commit 79e2bcc

Browse files
Merge pull request #390 from topcoder-platform/PROD-1515_sorting
PROD0-1515 sorting -> qa
2 parents 0ede0a4 + ebafc09 commit 79e2bcc

File tree

7 files changed

+66
-44
lines changed

7 files changed

+66
-44
lines changed

src-ts/lib/table/Table.tsx

+34-31
Original file line numberDiff line numberDiff line change
@@ -8,72 +8,75 @@ import { Tooltip } from '../tooltip'
88

99
import { TableCell } from './table-cell'
1010
import { TableColumn } from './table-column.model'
11-
import { tableGetSorted } from './table-functions'
11+
import { tableGetDefaultSort, tableGetSorted } from './table-functions'
1212
import { TableSort } from './table-sort'
1313
import styles from './Table.module.scss'
1414

1515
interface TableProps<T> {
1616
readonly columns: ReadonlyArray<TableColumn<T>>
1717
readonly data: ReadonlyArray<T>
18-
readonly defaultSort: Sort
1918
readonly onRowClick?: (data: T) => void
2019
}
2120

21+
interface DefaultSortDirectionMap {
22+
[columnProperty: string]: 'asc' | 'desc'
23+
}
24+
2225
const Table: <T extends { [propertyName: string]: any }>(props: TableProps<T>) => JSX.Element
2326
= <T extends { [propertyName: string]: any }>(props: TableProps<T>) => {
2427

25-
const [sort, setSort]: [Sort, Dispatch<SetStateAction<Sort>>] = useState<Sort>(props.defaultSort)
26-
const [sortMap, setSortMap]: [{ [fieldame: string]: boolean }, Dispatch<SetStateAction<{ [fieldame: string]: boolean }>>]
27-
= useState<{ [fieldame: string]: boolean }>({})
28+
const [sort, setSort]: [Sort | undefined, Dispatch<SetStateAction<Sort | undefined>>]
29+
= useState<Sort | undefined>(tableGetDefaultSort(props.columns))
30+
const [defaultSortDirectionMap, setDefaultSortDirectionMap]: [DefaultSortDirectionMap | undefined, Dispatch<SetStateAction<DefaultSortDirectionMap | undefined>>]
31+
= useState<DefaultSortDirectionMap | undefined>()
2832
const [sortedData, setSortData]: [ReadonlyArray<T>, Dispatch<SetStateAction<ReadonlyArray<T>>>]
2933
= useState<ReadonlyArray<T>>(props.data)
3034

3135
useEffect(() => {
3236

33-
// sort the data
34-
setSortData(tableGetSorted(props.data, sort, props.columns))
35-
36-
// create the sortmap to remember the last
37-
// sort direction of a column that is not
38-
// the currently sorted column
39-
const map: { [fieldame: string]: boolean } = {
40-
[sort.fieldName]: sort.direction === 'asc',
37+
if (!defaultSortDirectionMap) {
38+
const map: DefaultSortDirectionMap = {}
39+
props.columns
40+
.filter(col => !!col.propertyName)
41+
.forEach(col => map[col.propertyName as string] = col.defaultSortDirection || 'asc')
42+
setDefaultSortDirectionMap(map)
4143
}
4244

43-
// A) if column X is sorted in one direction,
44-
// then column Y is sorted,
45-
// then column X is sorted again,
46-
// the 2nd sort of column X will toggle its sort
47-
// direction
48-
// B) all columns default to sorting ascending, so if there
49-
// not a last known sort for a column, set it to descending
50-
// so the next toggle toggles it ascending.
51-
props.columns
52-
.filter(col => !!col.propertyName && col.propertyName !== sort.fieldName)
53-
.forEach(col => {
54-
const currentAscending: boolean | undefined = sortMap[col.propertyName as string]
55-
map[col.propertyName as string] = !!currentAscending
56-
})
57-
setSortMap(map)
45+
setSortData(tableGetSorted(props.data, props.columns, sort))
5846
},
5947
[
48+
defaultSortDirectionMap,
6049
sort,
6150
props.data,
6251
])
6352

6453
function toggleSort(fieldName: string): void {
54+
55+
// if we don't have anything to sort by, we shouldn't be here
56+
if (!sort) {
57+
return
58+
}
59+
60+
// get the sort direction
61+
const direction: 'asc' | 'desc' = fieldName === sort.fieldName
62+
// this is the current sort, so just toggle it
63+
? sort.direction === 'asc' ? 'desc' : 'asc'
64+
// get the default sort for the field... this will never be undefined
65+
: (defaultSortDirectionMap as DefaultSortDirectionMap)[fieldName]
66+
6567
const newSort: Sort = {
66-
direction: sortMap[fieldName] ? 'desc' : 'asc',
68+
direction,
6769
fieldName,
6870
}
6971
setSort(newSort)
7072
}
7173

7274
const headerRow: Array<JSX.Element> = props.columns
7375
.map(col => {
74-
const isCurrentlySorted: boolean = col.propertyName === sort.fieldName
76+
const isSortable: boolean = !!col.propertyName
77+
const isCurrentlySorted: boolean = isSortable && col.propertyName === sort?.fieldName
7578
const colorClass: string = isCurrentlySorted ? 'black-100' : 'black-60'
76-
const sortableClass: string | undefined = !!col.propertyName ? styles.sortable : undefined
79+
const sortableClass: string | undefined = isSortable ? styles.sortable : undefined
7780
return (
7881
<th className={styles.th}>
7982
<div className={classNames(styles['header-container'], styles[col.type], colorClass, sortableClass)}>

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

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { TableCellType } from './table-cell.type'
22

33
export interface TableColumn<T> {
4+
readonly defaultSortDirection?: 'asc' | 'desc'
5+
readonly isDefaultSort?: boolean
46
readonly label?: string
57
readonly propertyName?: string
68
readonly renderer?: (data: T, params?: any) => JSX.Element | undefined
+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
export { getSorted as tableGetSorted } from './table.functions'
1+
export {
2+
getDefaultSort as tableGetDefaultSort,
3+
getSorted as tableGetSorted,
4+
} from './table.functions'

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

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
11
import { Sort } from '../../pagination'
22
import { TableColumn } from '../table-column.model'
33

4+
export function getDefaultSort<T>(columns: ReadonlyArray<TableColumn<T>>): Sort | undefined {
5+
6+
const defaultSortColumn: TableColumn<T> | undefined = columns.find(col => col.isDefaultSort)
7+
|| columns.find(col => !!col.propertyName)
8+
9+
const defaultSort: Sort | undefined = !defaultSortColumn?.propertyName
10+
? undefined
11+
: {
12+
direction: defaultSortColumn.defaultSortDirection || 'asc',
13+
fieldName: defaultSortColumn.propertyName,
14+
}
15+
16+
return defaultSort
17+
}
18+
419
export function getSorted<T extends { [propertyName: string]: any }>(
520
data: ReadonlyArray<T>,
6-
sort: Sort,
7-
cols: ReadonlyArray<TableColumn<T>>
21+
cols: ReadonlyArray<TableColumn<T>>,
22+
sort?: Sort,
823
): ReadonlyArray<T> {
924

1025
// get the sort column
11-
const sortColumn: TableColumn<T> | undefined = cols.find(col => col.propertyName === sort.fieldName)
26+
const sortColumn: TableColumn<T> | undefined = !!sort
27+
? cols.find(col => col.propertyName === sort.fieldName)
28+
: undefined
1229

1330
const sortedData: Array<T> = [...data]
1431

15-
// this should never happen, but
16-
// if we didn't find a column, don't sort
17-
if (!sortColumn) {
32+
// if we don't have a column to sort, don't sort
33+
if (!sort || !sortColumn) {
1834
return sortedData
1935
}
2036

src-ts/lib/table/table-sort/TableSort.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ interface TableSortProps {
88
iconClass: string
99
isCurrentlySorted: boolean
1010
propertyName?: string
11-
sort: Sort
11+
sort?: Sort
1212
toggleSort: (fieldName: string) => void
1313
}
1414

1515
const TableSort: FC<TableSortProps> = (props: TableSortProps) => {
1616

17-
if (!props.propertyName) {
17+
if (!props.propertyName || !props.sort) {
1818
return <></>
1919
}
2020

src-ts/tools/work/work-table/WorkTable.tsx

-4
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ const WorkTable: FC<{}> = () => {
137137
<Table
138138
columns={columns}
139139
data={filteredResults}
140-
defaultSort={{
141-
direction: 'desc',
142-
fieldName: 'created',
143-
}}
144140
onRowClick={viewWorkDetails}
145141
/>
146142
)

src-ts/tools/work/work-table/work-table.config.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export const workListColumns: ReadonlyArray<TableColumn<Work>> = [
3535
type: 'text',
3636
},
3737
{
38+
defaultSortDirection: 'desc',
39+
isDefaultSort: true,
3840
label: 'Created',
3941
propertyName: 'created',
4042
type: 'date',

0 commit comments

Comments
 (0)