2
2
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
3
3
*/
4
4
5
+ import { has , get , isUndefined , omit } from 'lodash' ;
6
+
5
7
import { flux } from '../Firefly.js' ;
6
- import { updateSet } from '../util/WebUtil.js' ;
8
+ import { updateSet , updateMerge } from '../util/WebUtil.js' ;
9
+
10
+ import * as TablesCntlr from '../tables/TablesCntlr.js' ;
7
11
8
12
export const CHART_SPACE_PATH = 'charts' ;
9
13
export const UI_PREFIX = `${ CHART_SPACE_PATH } .ui` ;
10
14
11
15
export const CHART_UI_EXPANDED = `${ UI_PREFIX } .expanded` ;
16
+ export const CHART_MOUNTED = `${ UI_PREFIX } /mounted` ;
17
+ export const CHART_UNMOUNTED = `${ UI_PREFIX } /unmounted` ;
18
+ export const DELETE = `${ UI_PREFIX } /delete` ;
12
19
13
20
/**
14
21
* request to put a chart into an expanded mode.
@@ -21,15 +28,132 @@ export function dispatchChartExpanded(chartId, tblId, chartType, optionsPopup) {
21
28
flux . process ( { type : CHART_UI_EXPANDED , payload : { chartId, tblId, chartType, optionsPopup} } ) ;
22
29
}
23
30
31
+ /*
32
+ * Dispatched when chart becomes visible (is rendered for the first time after being invisible)
33
+ * When chart is mounted, its data need to be in sync with the related table
34
+ * @param {string } tblId - table id (table data for this chart)
35
+ * @param {string } chartId - chart id
36
+ * @param {string } chartType - chart type, ex. scatter, histogram
37
+ */
38
+ export function dispatchChartMounted ( tblId , chartId , chartType , dispatcher = flux . process ) {
39
+ dispatcher ( { type : CHART_MOUNTED , payload : { tblId, chartId, chartType} } ) ;
40
+ }
41
+
42
+ /*
43
+ * Dispatched when chart becomes invisible
44
+ * When chart is unmounted, its data synced with the related table only when it becomes mounted again
45
+ * @param {string } tblId - table id (table data for this chart)
46
+ * @param {string } chartId - chart id
47
+ * @param {string } chartType - chart type, ex. scatter, histogram
48
+ */
49
+ export function dispatchChartUnmounted ( tblId , chartId , chartType , dispatcher = flux . process ) {
50
+ dispatcher ( { type : CHART_UNMOUNTED , payload : { tblId, chartId, chartType} } ) ;
51
+ }
52
+
53
+ /*
54
+ * Delete chart and related data
55
+ * @param {string } tblId - table id (table data for this chart)
56
+ * @param {string } chartId - chart id
57
+ * @param {string } chartType - chart type, ex. scatter, histogram
58
+ */
59
+ export function dispatchDelete ( tblId , chartId , chartType , dispatcher = flux . process ) {
60
+ dispatcher ( { type : DELETE , payload : { tblId, chartId, chartType} } ) ;
61
+ }
62
+
63
+ const uniqueId = ( chartId , chartType ) => { return `${ chartType } |${ chartId } ` ; } ;
64
+ const isChartType = ( uChartId , chartType ) => { return uChartId . startsWith ( chartType ) ; } ;
65
+
66
+ const chartActions = [ CHART_UI_EXPANDED , CHART_MOUNTED , CHART_UNMOUNTED , DELETE ] ;
67
+
24
68
export function reducer ( state = { ui :{ } } , action = { } ) {
25
- //var root = state.ui;
26
- switch ( action . type ) {
27
- case ( CHART_UI_EXPANDED ) :
28
- const { chartId, tblId, chartType, optionsPopup} = action . payload ;
29
- //return updateSet(root, 'expanded', {chartId, tblId});
30
- return updateSet ( state , 'ui.expanded' , { chartId, tblId, chartType, optionsPopup} ) ;
31
- default :
32
- //return root;
33
- return state ;
69
+ if ( action . type === TablesCntlr . TABLE_REMOVE ) {
70
+ const { tbl_id} = action . payload ;
71
+ if ( has ( state , tbl_id ) ) {
72
+ return Object . assign ( { } , omit ( state , [ tbl_id ] ) ) ;
73
+ }
74
+ return state ;
75
+ } else if ( chartActions . indexOf ( action . type ) > - 1 ) {
76
+ const { chartId, tblId, chartType} = action . payload ;
77
+ const uChartId = uniqueId ( chartId , chartType ) ;
78
+ switch ( action . type ) {
79
+
80
+ case ( CHART_UI_EXPANDED ) :
81
+ const { optionsPopup} = action . payload ;
82
+ //return updateSet(root, 'expanded', {chartId, tblId});
83
+ return updateSet ( state , 'ui.expanded' , { chartId, tblId, chartType, optionsPopup} ) ;
84
+ case ( CHART_MOUNTED ) :
85
+
86
+ if ( ! has ( state , [ 'tbl' , tblId ] ) ) {
87
+ return updateSet ( state , [ 'tbl' , tblId ] , { [ uChartId ] : { mounted : true } } ) ;
88
+ } else {
89
+ if ( get ( state , [ 'tbl' , tblId , uChartId , 'mounted' ] ) ) {
90
+ //other version of the same chart is mounted
91
+ let n = get ( state , [ 'tbl' , tblId , uChartId , 'n' ] ) ;
92
+ n = n ? Number ( n ) : 1 ;
93
+ return updateMerge ( state , [ 'tbl' , tblId , uChartId ] , { upToDate : true , n : n + 1 } ) ;
94
+ } else {
95
+ return updateSet ( state , [ 'tbl' , tblId , uChartId ] , { mounted : true } ) ;
96
+ }
97
+ }
98
+ case ( CHART_UNMOUNTED ) :
99
+ if ( has ( state , [ 'tbl' , tblId ] ) ) {
100
+ if ( get ( state , [ 'tbl' , tblId , uChartId , 'mounted' ] ) ) {
101
+ let n = get ( state , [ 'tbl' , tblId , uChartId , 'n' ] ) ;
102
+ n = n ? Number ( n ) : 1 ;
103
+ if ( n > 1 ) {
104
+ //multiple versions of the same chart are mounted
105
+ return updateMerge ( state , [ 'tbl' , tblId , uChartId ] , { n : n - 1 } ) ;
106
+ }
107
+ } else {
108
+ return updateSet ( state , [ 'tbl' , tblId , uChartId ] , { mounted : false } ) ;
109
+ }
110
+ }
111
+ return state ;
112
+ case ( DELETE ) :
113
+ if ( has ( state , [ 'tbl' , tblId , uChartId ] ) ) {
114
+ if ( Object . keys ( state [ 'tbl' ] [ tblId ] ) . length > 1 ) {
115
+ return updateSet ( state , [ 'tbl' , tblId ] , omit ( state [ 'tbl' ] [ tblId ] , [ uChartId ] ) ) ;
116
+ } else {
117
+ return updateSet ( state , 'tbl' , omit ( state [ 'tbl' ] , [ tblId ] ) ) ;
118
+ }
119
+ }
120
+ return state ;
121
+ default :
122
+ return state ;
123
+ }
124
+ } else {
125
+ return state ;
34
126
}
127
+ }
128
+
129
+
130
+ export function getExpandedChartProps ( ) {
131
+ return get ( flux . getState ( ) , [ CHART_SPACE_PATH , 'ui' , 'expanded' ] ) ;
132
+ }
133
+
134
+
135
+ export function getNumRelatedCharts ( tblId , mounted , chartType ) {
136
+ let numRelated = 0 ;
137
+ const byTblSpace = get ( flux . getState ( ) , [ CHART_SPACE_PATH , 'tbl' ] ) ;
138
+ if ( byTblSpace ) {
139
+ if ( isUndefined ( tblId ) ) {
140
+ Object . keys ( byTblSpace ) . forEach ( ( tblId ) => {
141
+ numRelated += getNumRelatedCharts ( tblId , mounted ) ;
142
+ } ) ;
143
+ } else if ( byTblSpace [ tblId ] ) {
144
+ Object . keys ( byTblSpace [ tblId ] ) . forEach ( ( uChartId ) => {
145
+ if ( isUndefined ( mounted ) || byTblSpace [ tblId ] [ uChartId ] . mounted === mounted ) {
146
+ if ( isUndefined ( chartType ) || isChartType ( uChartId , chartType ) ) {
147
+ numRelated ++ ;
148
+ }
149
+ }
150
+ } ) ;
151
+ }
152
+ }
153
+ return numRelated ;
154
+ }
155
+
156
+ export function isChartMounted ( tblId , chartId , chartType ) {
157
+ const uChartId = uniqueId ( chartId , chartType ) ;
158
+ return Boolean ( get ( flux . getState ( ) , [ CHART_SPACE_PATH , 'tbl' , tblId , uChartId , 'mounted' ] ) ) ;
35
159
}
0 commit comments