@@ -8,72 +8,75 @@ import { Tooltip } from '../tooltip'
88
99import { TableCell } from './table-cell'
1010import { TableColumn } from './table-column.model'
11- import { tableGetSorted } from './table-functions'
11+ import { tableGetDefaultSort , tableGetSorted } from './table-functions'
1212import { TableSort } from './table-sort'
1313import styles from './Table.module.scss'
1414
1515interface 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+
2225const 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 ) } >
0 commit comments