1
1
import * as R from 'ramda' ;
2
2
3
- import { memoizeOneFactory } from 'core/memoizer' ;
3
+ import { memoizeOne } from 'core/memoizer' ;
4
+ import memoizerCache from 'core/cache/memoizer' ;
5
+ import SyntaxTree from 'core/syntax-tree' ;
6
+
7
+ import {
8
+ IConditionalDropdown
9
+ } from 'dash-table/components/CellDropdown/types' ;
4
10
5
11
import {
6
12
Data ,
7
13
Datum ,
8
14
VisibleColumns ,
9
15
ColumnId ,
10
16
Indices ,
11
- IColumnDropdown ,
12
- IConditionalColumnDropdown ,
13
- IDropdownProperties ,
14
- DropdownValues
17
+ DropdownValues ,
18
+ IBaseVisibleColumn ,
19
+ IVisibleColumn
15
20
} from 'dash-table/components/Table/props' ;
16
- import SyntaxTree from 'core/syntax-tree' ;
17
- import memoizerCache from 'core/memoizerCache' ;
18
- import { IConditionalDropdown } from 'dash-table/components/CellDropdown/types' ;
19
21
20
22
const mapData = R . addIndex < Datum , ( DropdownValues | undefined ) [ ] > ( R . map ) ;
21
23
22
- const getDropdown = (
23
- astCache : ( key : [ ColumnId , number ] , query : string ) => SyntaxTree ,
24
- conditionalDropdowns : IConditionalDropdown [ ] ,
25
- datum : Datum ,
26
- property : ColumnId ,
27
- staticDropdown : DropdownValues | undefined
28
- ) : DropdownValues | undefined => {
29
- const dropdowns = [
30
- ...( staticDropdown ? [ staticDropdown ] : [ ] ) ,
31
- ...R . map (
32
- ( [ cd ] ) => cd . dropdown ,
33
- R . filter (
34
- ( [ cd , i ] ) => astCache ( [ property , i ] , cd . condition ) . evaluate ( datum ) ,
35
- R . addIndex < IConditionalDropdown , [ IConditionalDropdown , number ] > ( R . map ) (
36
- ( cd , i ) => [ cd , i ] ,
37
- conditionalDropdowns
38
- ) )
39
- )
40
- ] ;
24
+ export default ( ) => new Dropdowns ( ) . get ;
41
25
42
- return dropdowns . length ? dropdowns . slice ( - 1 ) [ 0 ] : undefined ;
43
- } ;
26
+ class Dropdowns {
27
+ /**
28
+ * Return the dropdown for each cell in the table.
29
+ */
30
+ get = memoizeOne ( (
31
+ columns : VisibleColumns ,
32
+ data : Data ,
33
+ indices : Indices ,
34
+ columnConditionalDropdown : any ,
35
+ columnStaticDropdown : any ,
36
+ dropdown_properties : any
37
+ ) => mapData ( ( datum , rowIndex ) => R . map ( column => {
38
+ const applicable = this . applicable . get ( column . id , rowIndex ) (
39
+ column ,
40
+ indices [ rowIndex ] ,
41
+ columnConditionalDropdown ,
42
+ columnStaticDropdown ,
43
+ dropdown_properties
44
+ ) ;
44
45
45
- const getter = (
46
- astCache : ( key : [ ColumnId , number ] , query : string ) => SyntaxTree ,
47
- columns : VisibleColumns ,
48
- data : Data ,
49
- indices : Indices ,
50
- columnConditionalDropdown : IConditionalColumnDropdown [ ] ,
51
- columnStaticDropdown : IColumnDropdown [ ] ,
52
- dropdown_properties : IDropdownProperties
53
- ) : ( DropdownValues | undefined ) [ ] [ ] => mapData ( ( datum , rowIndex ) => R . map ( column => {
54
- const realIndex = indices [ rowIndex ] ;
46
+ return this . dropdown . get ( column . id , rowIndex ) (
47
+ applicable ,
48
+ column ,
49
+ datum
50
+ ) ;
51
+ } , columns ) , data ) ) ;
55
52
56
- let legacyDropdown = (
57
- (
58
- dropdown_properties &&
59
- dropdown_properties [ column . id ] &&
53
+ /**
54
+ * Returns the list of applicable dropdowns for a cell.
55
+ */
56
+ private readonly applicable = memoizerCache < [ ColumnId , number ] > ( ) ( (
57
+ column : IBaseVisibleColumn ,
58
+ realIndex : number ,
59
+ columnConditionalDropdown : any ,
60
+ columnStaticDropdown : any ,
61
+ dropdown_properties : any
62
+ ) : [ any , any ] => {
63
+ let legacyDropdown = (
60
64
(
61
- dropdown_properties [ column . id ] . length > realIndex ?
62
- dropdown_properties [ column . id ] [ realIndex ] :
63
- null
64
- )
65
- ) || column
66
- ) . options ;
65
+ dropdown_properties &&
66
+ dropdown_properties [ column . id ] &&
67
+ (
68
+ dropdown_properties [ column . id ] . length > realIndex ?
69
+ dropdown_properties [ column . id ] [ realIndex ] :
70
+ null
71
+ )
72
+ ) || column
73
+ ) . options ;
67
74
68
- const conditional = columnConditionalDropdown . find ( ( cs : any ) => cs . id === column . id ) ;
69
- const base = columnStaticDropdown . find ( ( ss : any ) => ss . id === column . id ) ;
75
+ const conditional = columnConditionalDropdown . find ( ( cs : any ) => cs . id === column . id ) ;
76
+ const base = columnStaticDropdown . find ( ( ss : any ) => ss . id === column . id ) ;
70
77
71
- const conditionalDropdowns = ( conditional && conditional . dropdowns ) || [ ] ;
72
- const staticDropdown = legacyDropdown || ( base && base . dropdown ) ;
78
+ return [
79
+ legacyDropdown || ( base && base . dropdown ) ,
80
+ ( conditional && conditional . dropdowns ) || [ ]
81
+ ] ;
82
+ } ) ;
73
83
74
- return getDropdown ( astCache , conditionalDropdowns , datum , column . id , staticDropdown ) ;
75
- } , columns ) , data ) ;
84
+ /**
85
+ * Returns the highest priority dropdown from the
86
+ * applicable dropdowns.
87
+ */
88
+ private readonly dropdown = memoizerCache < [ ColumnId , number ] > ( ) ( (
89
+ applicableDropdowns : [ any , any ] ,
90
+ column : IVisibleColumn ,
91
+ datum : Datum
92
+ ) => {
93
+ const [ staticDropdown , conditionalDropdowns ] = applicableDropdowns ;
76
94
77
- const getterFactory = memoizeOneFactory ( getter ) ;
95
+ const matches = [
96
+ ...( staticDropdown ? [ staticDropdown ] : [ ] ) ,
97
+ ...R . map (
98
+ ( [ cd ] ) => cd . dropdown ,
99
+ R . filter (
100
+ ( [ cd , i ] ) => this . evaluation . get ( column . id , i ) (
101
+ this . ast . get ( column . id , i ) ( cd . condition ) ,
102
+ datum
103
+ ) ,
104
+ R . addIndex < IConditionalDropdown , [ IConditionalDropdown , number ] > ( R . map ) (
105
+ ( cd , i ) => [ cd , i ] ,
106
+ conditionalDropdowns
107
+ ) )
108
+ )
109
+ ] ;
78
110
79
- const decoratedGetter = ( _id : string ) : ( (
80
- columns : VisibleColumns ,
81
- data : Data ,
82
- indices : Indices ,
83
- columnConditionalDropdown : any ,
84
- columnStaticDropdown : any ,
85
- dropdown_properties : any
86
- ) => ( DropdownValues | undefined ) [ ] [ ] ) => {
87
- const astCache = memoizerCache < [ ColumnId , number ] , [ string ] , SyntaxTree > (
88
- ( query : string ) => new SyntaxTree ( query )
89
- ) ;
111
+ return matches . length ? matches . slice ( - 1 ) [ 0 ] : undefined ;
112
+ } ) ;
90
113
91
- return getterFactory ( ) . bind ( undefined , astCache ) ;
92
- } ;
114
+ /**
115
+ * Get the query's AST.
116
+ */
117
+ private readonly ast = memoizerCache < [ ColumnId , number ] > ( ) ( (
118
+ query : string
119
+ ) => new SyntaxTree ( query ) ) ;
93
120
94
- export default memoizeOneFactory ( decoratedGetter ) ;
121
+ /**
122
+ * Evaluate if the query matches the cell's data.
123
+ */
124
+ private readonly evaluation = memoizerCache < [ ColumnId , number ] > ( ) ( (
125
+ ast : SyntaxTree ,
126
+ datum : Datum
127
+ ) => ast . evaluate ( datum ) ) ;
128
+ }
0 commit comments