@@ -8,72 +8,75 @@ import { Tooltip } from '../tooltip'
8
8
9
9
import { TableCell } from './table-cell'
10
10
import { TableColumn } from './table-column.model'
11
- import { tableGetSorted } from './table-functions'
11
+ import { tableGetDefaultSort , tableGetSorted } from './table-functions'
12
12
import { TableSort } from './table-sort'
13
13
import styles from './Table.module.scss'
14
14
15
15
interface TableProps < T > {
16
16
readonly columns : ReadonlyArray < TableColumn < T > >
17
17
readonly data : ReadonlyArray < T >
18
- readonly defaultSort : Sort
19
18
readonly onRowClick ?: ( data : T ) => void
20
19
}
21
20
21
+ interface DefaultSortDirectionMap {
22
+ [ columnProperty : string ] : 'asc' | 'desc'
23
+ }
24
+
22
25
const Table : < T extends { [ propertyName : string ] : any } > ( props : TableProps < T > ) => JSX . Element
23
26
= < T extends { [ propertyName : string ] : any } > ( props : TableProps < T > ) => {
24
27
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 > ( )
28
32
const [ sortedData , setSortData ] : [ ReadonlyArray < T > , Dispatch < SetStateAction < ReadonlyArray < T > > > ]
29
33
= useState < ReadonlyArray < T > > ( props . data )
30
34
31
35
useEffect ( ( ) => {
32
36
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 )
41
43
}
42
44
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 ) )
58
46
} ,
59
47
[
48
+ defaultSortDirectionMap ,
60
49
sort ,
61
50
props . data ,
62
51
] )
63
52
64
53
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
+
65
67
const newSort : Sort = {
66
- direction : sortMap [ fieldName ] ? 'desc' : 'asc' ,
68
+ direction,
67
69
fieldName,
68
70
}
69
71
setSort ( newSort )
70
72
}
71
73
72
74
const headerRow : Array < JSX . Element > = props . columns
73
75
. 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
75
78
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
77
80
return (
78
81
< th className = { styles . th } >
79
82
< div className = { classNames ( styles [ 'header-container' ] , styles [ col . type ] , colorClass , sortableClass ) } >
0 commit comments