@cdc/dashboard 4.25.6 → 4.25.7-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,288 +1,288 @@
1
- import _ from 'lodash'
2
- import { getUpdateConfig } from '../helpers/getUpdateConfig'
3
- import { MultiDashboard, MultiDashboardConfig } from '../types/MultiDashboard'
4
- import DashboardActions from './dashboard.actions'
5
- import { devToolsWrapper } from '@cdc/core/helpers/withDevTools'
6
- import { Tab } from '../types/Tab'
7
- import { Dashboard } from '../types/Dashboard'
8
- import { ConfigRow } from '../types/ConfigRow'
9
- import { AnyVisualization } from '@cdc/core/types/Visualization'
10
- import { initialState } from '../DashboardContext'
11
-
12
- type BlankMultiConfig = {
13
- dashboard: Partial<Dashboard>
14
- rows: Partial<ConfigRow>[]
15
- visualizations: Record<string, Object>
16
- table: Object
17
- }
18
-
19
- const createBlankDashboard: () => BlankMultiConfig = () => ({
20
- dashboard: { sharedFilters: [] },
21
- rows: [{ columns: [{ width: 12 }] }],
22
- visualizations: {},
23
- table: {
24
- label: 'Data Table',
25
- show: false,
26
- showDownloadUrl: false,
27
- showVertical: true
28
- }
29
- })
30
-
31
- export type DashboardState = {
32
- config: MultiDashboardConfig
33
- data: Record<string, any[]>
34
- filteredData: Object
35
- loading: boolean
36
- preview: boolean
37
- tabSelected: Tab
38
- }
39
-
40
- const reducer = (state: DashboardState, action: DashboardActions): DashboardState => {
41
- switch (action.type) {
42
- case 'ADD_NEW_DASHBOARD': {
43
- const currentMultiDashboards = state.config.multiDashboards
44
- const label = 'New Dashboard ' + (currentMultiDashboards.length + 1)
45
- const newMultiDashboards = [...currentMultiDashboards, { ...createBlankDashboard(), label }]
46
- return applyMultiDashboards(state, newMultiDashboards)
47
- }
48
- case 'UPDATE_CONFIG': {
49
- const [config, filteredData] = getUpdateConfig(state)(...action.payload)
50
- return { ...state, config: saveMultiChanges(config, state.config.activeDashboard), filteredData }
51
- }
52
- case 'APPLY_CONFIG': {
53
- // using advanced editor. Wipe all existing data and apply new config
54
- const [config, filteredData] = getUpdateConfig(state)(...action.payload)
55
- // get the default data state
56
- const data = [...Object.values(config.visualizations), ...config.rows]
57
- .map(viz => viz.dataKey)
58
- .reduce((acc, key) => {
59
- const data = state.data[key] || state.config.datasets[key]?.data
60
- if (data) acc[key] = data
61
- return acc
62
- }, {})
63
- return { ...initialState, config: saveMultiChanges(config, state.config.activeDashboard), filteredData, data }
64
- }
65
- case 'SET_CONFIG': {
66
- if (
67
- action.payload.activeDashboard === undefined ||
68
- state.config.activeDashboard === action.payload.activeDashboard
69
- ) {
70
- return {
71
- ...state,
72
- config: saveMultiChanges({ ...state.config, ...action.payload }, action.payload.activeDashboard)
73
- }
74
- } else return state // ignore SET_CONFIG calls that have the wrong activeDashboard due to async api fetching
75
- }
76
- case 'SET_DATA': {
77
- return { ...state, data: action.payload }
78
- }
79
- case 'SET_FILTERED_DATA': {
80
- return { ...state, filteredData: action.payload }
81
- }
82
- case 'SET_LOADING': {
83
- return { ...state, loading: action.payload }
84
- }
85
- case 'SET_PREVIEW': {
86
- return { ...state, preview: action.payload }
87
- }
88
- case 'SET_SHARED_FILTERS': {
89
- const newSharedFilters = action.payload
90
- const newDashboardConfig = { ...state.config.dashboard, sharedFilters: newSharedFilters }
91
- return {
92
- ...state,
93
- config: saveMultiChanges({ ...state.config, dashboard: newDashboardConfig }, state.config.activeDashboard)
94
- }
95
- }
96
- case 'SET_TAB_SELECTED': {
97
- return { ...state, tabSelected: action.payload }
98
- }
99
- case 'REMOVE_MULTIDASHBOARD_AT_INDEX': {
100
- const newMultiDashboards = [...state.config.multiDashboards]
101
- _.remove(newMultiDashboards, (_, index) => {
102
- return index === action.payload
103
- })
104
- const config = {
105
- ...state.config,
106
- multiDashboards: newMultiDashboards,
107
- ...newMultiDashboards[0],
108
- activeDashboard: 0
109
- }
110
- if (newMultiDashboards.length === 0) return { ...state, config: _.omit(state.config, 'multiDashboards') }
111
- return applyMultiDashboards({ ...state, config }, newMultiDashboards)
112
- }
113
- case 'RENAME_DASHBOARD_TAB': {
114
- const newMultiDashboards = state.config.multiDashboards.map(dashboard => {
115
- if (dashboard.label === action.payload.current) {
116
- dashboard.label = action.payload.new
117
- }
118
- return dashboard
119
- })
120
- const newConfig = { ...state.config, label: action.payload.new } // make sure active label is updated
121
- return applyMultiDashboards({ ...state, newConfig }, newMultiDashboards)
122
- }
123
- case 'REORDER_MULTIDASHBOARDS': {
124
- const { newIndex, currentIndex } = action.payload
125
- const newMultiDashboards = [...state.config.multiDashboards]
126
- newMultiDashboards.splice(newIndex, 0, newMultiDashboards.splice(currentIndex, 1)[0])
127
- // set activeDashboard to newIndex
128
- const config = { ...state.config, activeDashboard: newIndex }
129
- return applyMultiDashboards({ ...state, config }, newMultiDashboards)
130
- }
131
- case 'SAVE_CURRENT_CHANGES': {
132
- const saveSlot = state.config.activeDashboard
133
- const newMultiDashboards = [...state.config.multiDashboards]
134
- const label = newMultiDashboards[saveSlot].label
135
- const toSave = _.pick(state.config, ['dashboard', 'visualizations', 'rows'])
136
- newMultiDashboards[saveSlot] = { ...toSave, label }
137
- const newConfig = saveMultiChanges(state.config, saveSlot)
138
- return { ...state, config: newConfig }
139
- }
140
- case 'INITIALIZE_MULTIDASHBOARDS': {
141
- const label = 'New Dashboard 1'
142
- const toSave = _.pick(state.config, ['dashboard', 'visualizations', 'rows'])
143
- const newMultiDashboards = [{ ...toSave, label }]
144
- const config = { ...state.config, activeDashboard: 0 }
145
- return applyMultiDashboards({ ...state, config }, newMultiDashboards)
146
- }
147
- case 'SWITCH_CONFIG': {
148
- const slot = action.payload
149
- const newConfigFields = state.config.multiDashboards[slot]
150
- const _newDatasets = _.cloneDeep(state.data)
151
- return { ...state, data: _newDatasets, config: { ...state.config, ...newConfigFields, activeDashboard: slot } }
152
- }
153
- case 'TOGGLE_ROW': {
154
- const { rowIndex, colIndex } = action.payload
155
- const newRows = state.config.rows.map((row, index) => {
156
- if (index === rowIndex) {
157
- const newColumns = row.columns.map((col, i) => ({ ...col, hide: i === colIndex }))
158
- return { ...row, columns: newColumns }
159
- }
160
- return row
161
- })
162
- return { ...state, config: { ...state.config, rows: newRows } }
163
- }
164
- case 'ADD_VISUALIZATION': {
165
- const { newViz, rowIdx, colIdx } = action.payload
166
- const vizKey = newViz.uid
167
- const newRows = _.cloneDeep(state.config.rows)
168
- newRows[rowIdx].columns[colIdx].widget = vizKey
169
- return {
170
- ...state,
171
- config: saveMultiChanges(
172
- { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: newViz }, rows: newRows },
173
- state.config.activeDashboard
174
- )
175
- }
176
- }
177
- case 'MOVE_VISUALIZATION': {
178
- const { rowIdx, colIdx, widget } = action.payload
179
- const newRows = _.cloneDeep(state.config.rows)
180
- newRows[widget.rowIdx].columns[widget.colIdx].widget = null
181
- newRows[rowIdx].columns[colIdx].widget = widget.uid
182
- return {
183
- ...state,
184
- config: saveMultiChanges({ ...state.config, rows: newRows }, state.config.activeDashboard)
185
- }
186
- }
187
- case 'RESET_VISUALIZATION': {
188
- const { vizKey } = action.payload
189
- const updatedViz = { ...state.config.visualizations[vizKey] } as AnyVisualization
190
- delete updatedViz.data
191
- delete updatedViz.dataKey
192
- delete updatedViz.dataDescription
193
- delete updatedViz.formattedData
194
- return {
195
- ...state,
196
- config: saveMultiChanges(
197
- { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: updatedViz } },
198
- state.config.activeDashboard
199
- )
200
- }
201
- }
202
- case 'UPDATE_VISUALIZATION': {
203
- const { vizKey, configureData } = action.payload
204
- const updatedViz = { ...state.config.visualizations[vizKey], ...configureData } as AnyVisualization
205
- return {
206
- ...state,
207
- config: saveMultiChanges(
208
- { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: updatedViz } },
209
- state.config.activeDashboard
210
- )
211
- }
212
- }
213
- case 'UPDATE_ROW': {
214
- const { rowIndex, rowData } = action.payload
215
- const newRows = state.config.rows.map((row, index) => {
216
- if (index === rowIndex) {
217
- return { ...row, ...rowData }
218
- }
219
- return row
220
- })
221
- return { ...state, config: saveMultiChanges({ ...state.config, rows: newRows }, state.config.activeDashboard) }
222
- }
223
- case 'DELETE_WIDGET': {
224
- const { uid } = action.payload
225
- const newRows = _.cloneDeep(state.config.rows)
226
- const newVisualizations = _.cloneDeep(state.config.visualizations)
227
- delete newVisualizations[uid]
228
- const newSharedFilters = _.cloneDeep(state.config.dashboard.sharedFilters)
229
- if (newSharedFilters && newSharedFilters.length > 0) {
230
- newSharedFilters.forEach(sharedFilter => {
231
- if (sharedFilter.usedBy && sharedFilter.usedBy.indexOf(uid) !== -1) {
232
- sharedFilter.usedBy.splice(sharedFilter.usedBy.indexOf(uid), 1)
233
- }
234
- })
235
- }
236
-
237
- const filteredRows = _.map(newRows, row => ({
238
- ...row,
239
- columns: _.filter(row.columns, column => column.widget !== uid)
240
- }))
241
-
242
- return {
243
- ...state,
244
- config: saveMultiChanges(
245
- {
246
- ...state.config,
247
- dashboard: { ...state.config.dashboard, sharedFilters: newSharedFilters },
248
- visualizations: newVisualizations,
249
- rows: filteredRows
250
- },
251
- state.config.activeDashboard
252
- )
253
- }
254
- }
255
- case 'UPDATE_TOGGLE_NAME': {
256
- const { rowIndex, columnIndex, toggleName } = action.payload
257
- const newRows = state.config.rows.map((row, index) => {
258
- if (index === rowIndex) {
259
- const newColumns = row.columns.map((col, i) => ({
260
- ...col,
261
- toggleName: i === columnIndex ? toggleName : col.toggleName
262
- }))
263
- return { ...row, columns: newColumns }
264
- }
265
- return row
266
- })
267
- return { ...state, config: { ...state.config, rows: newRows } }
268
- }
269
- default:
270
- return state
271
- }
272
- }
273
-
274
- const saveMultiChanges = (config: MultiDashboardConfig, saveSlot?: number): MultiDashboardConfig => {
275
- if (saveSlot === undefined || !config.multiDashboards) return config
276
- const newMultiDashboards = [...config.multiDashboards]
277
- const label = newMultiDashboards[saveSlot].label
278
- const toSave = _.pick(config, ['dashboard', 'visualizations', 'rows'])
279
- newMultiDashboards[saveSlot] = { ...toSave, label }
280
- return { ...config, multiDashboards: newMultiDashboards }
281
- }
282
-
283
- const applyMultiDashboards = (state: DashboardState, newMultiDashboards: MultiDashboard[]): DashboardState => ({
284
- ...state,
285
- config: { ...state.config, multiDashboards: newMultiDashboards }
286
- })
287
-
288
- export default devToolsWrapper<DashboardState, DashboardActions>(reducer)
1
+ import _ from 'lodash'
2
+ import { getUpdateConfig } from '../helpers/getUpdateConfig'
3
+ import { MultiDashboard, MultiDashboardConfig } from '../types/MultiDashboard'
4
+ import DashboardActions from './dashboard.actions'
5
+ import { devToolsWrapper } from '@cdc/core/helpers/withDevTools'
6
+ import { Tab } from '../types/Tab'
7
+ import { Dashboard } from '../types/Dashboard'
8
+ import { ConfigRow } from '../types/ConfigRow'
9
+ import { AnyVisualization } from '@cdc/core/types/Visualization'
10
+ import { initialState } from '../DashboardContext'
11
+
12
+ type BlankMultiConfig = {
13
+ dashboard: Partial<Dashboard>
14
+ rows: Partial<ConfigRow>[]
15
+ visualizations: Record<string, Object>
16
+ table: Object
17
+ }
18
+
19
+ const createBlankDashboard: () => BlankMultiConfig = () => ({
20
+ dashboard: { sharedFilters: [] },
21
+ rows: [{ columns: [{ width: 12 }] }],
22
+ visualizations: {},
23
+ table: {
24
+ label: 'Data Table',
25
+ show: false,
26
+ showDownloadUrl: false,
27
+ showVertical: true
28
+ }
29
+ })
30
+
31
+ export type DashboardState = {
32
+ config: MultiDashboardConfig
33
+ data: Record<string, any[]>
34
+ filteredData: Object
35
+ loading: boolean
36
+ preview: boolean
37
+ tabSelected: Tab
38
+ }
39
+
40
+ const reducer = (state: DashboardState, action: DashboardActions): DashboardState => {
41
+ switch (action.type) {
42
+ case 'ADD_NEW_DASHBOARD': {
43
+ const currentMultiDashboards = state.config.multiDashboards
44
+ const label = 'New Dashboard ' + (currentMultiDashboards.length + 1)
45
+ const newMultiDashboards = [...currentMultiDashboards, { ...createBlankDashboard(), label }]
46
+ return applyMultiDashboards(state, newMultiDashboards)
47
+ }
48
+ case 'UPDATE_CONFIG': {
49
+ const [config, filteredData] = getUpdateConfig(state)(...action.payload)
50
+ return { ...state, config: saveMultiChanges(config, state.config.activeDashboard), filteredData }
51
+ }
52
+ case 'APPLY_CONFIG': {
53
+ // using advanced editor. Wipe all existing data and apply new config
54
+ const [config, filteredData] = getUpdateConfig(state)(...action.payload)
55
+ // get the default data state
56
+ const data = [...Object.values(config.visualizations), ...config.rows]
57
+ .map(viz => viz.dataKey)
58
+ .reduce((acc, key) => {
59
+ const data = state.data[key] || state.config.datasets[key]?.data
60
+ if (data) acc[key] = data
61
+ return acc
62
+ }, {})
63
+ return { ...initialState, config: saveMultiChanges(config, state.config.activeDashboard), filteredData, data }
64
+ }
65
+ case 'SET_CONFIG': {
66
+ if (
67
+ action.payload.activeDashboard === undefined ||
68
+ state.config.activeDashboard === action.payload.activeDashboard
69
+ ) {
70
+ return {
71
+ ...state,
72
+ config: saveMultiChanges({ ...state.config, ...action.payload }, action.payload.activeDashboard)
73
+ }
74
+ } else return state // ignore SET_CONFIG calls that have the wrong activeDashboard due to async api fetching
75
+ }
76
+ case 'SET_DATA': {
77
+ return { ...state, data: action.payload }
78
+ }
79
+ case 'SET_FILTERED_DATA': {
80
+ return { ...state, filteredData: action.payload }
81
+ }
82
+ case 'SET_LOADING': {
83
+ return { ...state, loading: action.payload }
84
+ }
85
+ case 'SET_PREVIEW': {
86
+ return { ...state, preview: action.payload }
87
+ }
88
+ case 'SET_SHARED_FILTERS': {
89
+ const newSharedFilters = action.payload
90
+ const newDashboardConfig = { ...state.config.dashboard, sharedFilters: newSharedFilters }
91
+ return {
92
+ ...state,
93
+ config: saveMultiChanges({ ...state.config, dashboard: newDashboardConfig }, state.config.activeDashboard)
94
+ }
95
+ }
96
+ case 'SET_TAB_SELECTED': {
97
+ return { ...state, tabSelected: action.payload }
98
+ }
99
+ case 'REMOVE_MULTIDASHBOARD_AT_INDEX': {
100
+ const newMultiDashboards = [...state.config.multiDashboards]
101
+ _.remove(newMultiDashboards, (_, index) => {
102
+ return index === action.payload
103
+ })
104
+ const config = {
105
+ ...state.config,
106
+ multiDashboards: newMultiDashboards,
107
+ ...newMultiDashboards[0],
108
+ activeDashboard: 0
109
+ }
110
+ if (newMultiDashboards.length === 0) return { ...state, config: _.omit(state.config, 'multiDashboards') }
111
+ return applyMultiDashboards({ ...state, config }, newMultiDashboards)
112
+ }
113
+ case 'RENAME_DASHBOARD_TAB': {
114
+ const newMultiDashboards = state.config.multiDashboards.map(dashboard => {
115
+ if (dashboard.label === action.payload.current) {
116
+ dashboard.label = action.payload.new
117
+ }
118
+ return dashboard
119
+ })
120
+ const newConfig = { ...state.config, label: action.payload.new } // make sure active label is updated
121
+ return applyMultiDashboards({ ...state, newConfig }, newMultiDashboards)
122
+ }
123
+ case 'REORDER_MULTIDASHBOARDS': {
124
+ const { newIndex, currentIndex } = action.payload
125
+ const newMultiDashboards = [...state.config.multiDashboards]
126
+ newMultiDashboards.splice(newIndex, 0, newMultiDashboards.splice(currentIndex, 1)[0])
127
+ // set activeDashboard to newIndex
128
+ const config = { ...state.config, activeDashboard: newIndex }
129
+ return applyMultiDashboards({ ...state, config }, newMultiDashboards)
130
+ }
131
+ case 'SAVE_CURRENT_CHANGES': {
132
+ const saveSlot = state.config.activeDashboard
133
+ const newMultiDashboards = [...state.config.multiDashboards]
134
+ const label = newMultiDashboards[saveSlot].label
135
+ const toSave = _.pick(state.config, ['dashboard', 'visualizations', 'rows'])
136
+ newMultiDashboards[saveSlot] = { ...toSave, label }
137
+ const newConfig = saveMultiChanges(state.config, saveSlot)
138
+ return { ...state, config: newConfig }
139
+ }
140
+ case 'INITIALIZE_MULTIDASHBOARDS': {
141
+ const label = 'New Dashboard 1'
142
+ const toSave = _.pick(state.config, ['dashboard', 'visualizations', 'rows'])
143
+ const newMultiDashboards = [{ ...toSave, label }]
144
+ const config = { ...state.config, activeDashboard: 0 }
145
+ return applyMultiDashboards({ ...state, config }, newMultiDashboards)
146
+ }
147
+ case 'SWITCH_CONFIG': {
148
+ const slot = action.payload
149
+ const newConfigFields = state.config.multiDashboards[slot]
150
+ const _newDatasets = _.cloneDeep(state.data)
151
+ return { ...state, data: _newDatasets, config: { ...state.config, ...newConfigFields, activeDashboard: slot } }
152
+ }
153
+ case 'TOGGLE_ROW': {
154
+ const { rowIndex, colIndex } = action.payload
155
+ const newRows = state.config.rows.map((row, index) => {
156
+ if (index === rowIndex) {
157
+ const newColumns = row.columns.map((col, i) => ({ ...col, hide: i === colIndex }))
158
+ return { ...row, columns: newColumns }
159
+ }
160
+ return row
161
+ })
162
+ return { ...state, config: { ...state.config, rows: newRows } }
163
+ }
164
+ case 'ADD_VISUALIZATION': {
165
+ const { newViz, rowIdx, colIdx } = action.payload
166
+ const vizKey = newViz.uid
167
+ const newRows = _.cloneDeep(state.config.rows)
168
+ newRows[rowIdx].columns[colIdx].widget = vizKey
169
+ return {
170
+ ...state,
171
+ config: saveMultiChanges(
172
+ { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: newViz }, rows: newRows },
173
+ state.config.activeDashboard
174
+ )
175
+ }
176
+ }
177
+ case 'MOVE_VISUALIZATION': {
178
+ const { rowIdx, colIdx, widget } = action.payload
179
+ const newRows = _.cloneDeep(state.config.rows)
180
+ newRows[widget.rowIdx].columns[widget.colIdx].widget = null
181
+ newRows[rowIdx].columns[colIdx].widget = widget.uid
182
+ return {
183
+ ...state,
184
+ config: saveMultiChanges({ ...state.config, rows: newRows }, state.config.activeDashboard)
185
+ }
186
+ }
187
+ case 'RESET_VISUALIZATION': {
188
+ const { vizKey } = action.payload
189
+ const updatedViz = { ...state.config.visualizations[vizKey] } as AnyVisualization
190
+ delete updatedViz.data
191
+ delete updatedViz.dataKey
192
+ delete updatedViz.dataDescription
193
+ delete updatedViz.formattedData
194
+ return {
195
+ ...state,
196
+ config: saveMultiChanges(
197
+ { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: updatedViz } },
198
+ state.config.activeDashboard
199
+ )
200
+ }
201
+ }
202
+ case 'UPDATE_VISUALIZATION': {
203
+ const { vizKey, configureData } = action.payload
204
+ const updatedViz = { ...state.config.visualizations[vizKey], ...configureData } as AnyVisualization
205
+ return {
206
+ ...state,
207
+ config: saveMultiChanges(
208
+ { ...state.config, visualizations: { ...state.config.visualizations, [vizKey]: updatedViz } },
209
+ state.config.activeDashboard
210
+ )
211
+ }
212
+ }
213
+ case 'UPDATE_ROW': {
214
+ const { rowIndex, rowData } = action.payload
215
+ const newRows = state.config.rows.map((row, index) => {
216
+ if (index === rowIndex) {
217
+ return { ...row, ...rowData }
218
+ }
219
+ return row
220
+ })
221
+ return { ...state, config: saveMultiChanges({ ...state.config, rows: newRows }, state.config.activeDashboard) }
222
+ }
223
+ case 'DELETE_WIDGET': {
224
+ const { uid } = action.payload
225
+ const newRows = _.cloneDeep(state.config.rows)
226
+ const newVisualizations = _.cloneDeep(state.config.visualizations)
227
+ delete newVisualizations[uid]
228
+ const newSharedFilters = _.cloneDeep(state.config.dashboard.sharedFilters)
229
+ if (newSharedFilters && newSharedFilters.length > 0) {
230
+ newSharedFilters.forEach(sharedFilter => {
231
+ if (sharedFilter.usedBy && sharedFilter.usedBy.indexOf(uid) !== -1) {
232
+ sharedFilter.usedBy.splice(sharedFilter.usedBy.indexOf(uid), 1)
233
+ }
234
+ })
235
+ }
236
+
237
+ const filteredRows = _.map(newRows, row => ({
238
+ ...row,
239
+ columns: _.filter(row.columns, column => column.widget !== uid)
240
+ }))
241
+
242
+ return {
243
+ ...state,
244
+ config: saveMultiChanges(
245
+ {
246
+ ...state.config,
247
+ dashboard: { ...state.config.dashboard, sharedFilters: newSharedFilters },
248
+ visualizations: newVisualizations,
249
+ rows: filteredRows
250
+ },
251
+ state.config.activeDashboard
252
+ )
253
+ }
254
+ }
255
+ case 'UPDATE_TOGGLE_NAME': {
256
+ const { rowIndex, columnIndex, toggleName } = action.payload
257
+ const newRows = state.config.rows.map((row, index) => {
258
+ if (index === rowIndex) {
259
+ const newColumns = row.columns.map((col, i) => ({
260
+ ...col,
261
+ toggleName: i === columnIndex ? toggleName : col.toggleName
262
+ }))
263
+ return { ...row, columns: newColumns }
264
+ }
265
+ return row
266
+ })
267
+ return { ...state, config: { ...state.config, rows: newRows } }
268
+ }
269
+ default:
270
+ return state
271
+ }
272
+ }
273
+
274
+ const saveMultiChanges = (config: MultiDashboardConfig, saveSlot?: number): MultiDashboardConfig => {
275
+ if (saveSlot === undefined || !config.multiDashboards) return config
276
+ const newMultiDashboards = [...config.multiDashboards]
277
+ const label = newMultiDashboards[saveSlot].label
278
+ const toSave = _.pick(config, ['dashboard', 'visualizations', 'rows'])
279
+ newMultiDashboards[saveSlot] = { ...toSave, label }
280
+ return { ...config, multiDashboards: newMultiDashboards }
281
+ }
282
+
283
+ const applyMultiDashboards = (state: DashboardState, newMultiDashboards: MultiDashboard[]): DashboardState => ({
284
+ ...state,
285
+ config: { ...state.config, multiDashboards: newMultiDashboards }
286
+ })
287
+
288
+ export default devToolsWrapper<DashboardState, DashboardActions>(reducer)
@@ -1,19 +1,19 @@
1
- import { ConfigureData } from '@cdc/core/types/ConfigureData'
2
-
3
- type Col = {
4
- equalHeight?: boolean
5
- width: number | null
6
- hide?: boolean
7
- widget?: string
8
- toggleName?: string
9
- uuid?: string | number
10
- }
11
-
12
- export type ConfigRow = {
13
- columns: Col[]
14
- expandCollapseAllButtons: boolean
15
- uuid?: string | number
16
- toggle?: boolean
17
- equalHeight?: boolean
18
- multiVizColumn?: string
19
- } & ConfigureData
1
+ import { ConfigureData } from '@cdc/core/types/ConfigureData'
2
+
3
+ type Col = {
4
+ equalHeight?: boolean
5
+ width: number | null
6
+ hide?: boolean
7
+ widget?: string
8
+ toggleName?: string
9
+ uuid?: string | number
10
+ }
11
+
12
+ export type ConfigRow = {
13
+ columns: Col[]
14
+ expandCollapseAllButtons: boolean
15
+ uuid?: string | number
16
+ toggle?: boolean
17
+ equalHeight?: boolean
18
+ multiVizColumn?: string
19
+ } & ConfigureData
@@ -1,11 +1,11 @@
1
- import { DataSet } from '@cdc/core/types/DataSet'
2
- import { SharedFilter } from './SharedFilter'
3
-
4
- export type Dashboard = {
5
- sharedFilters: SharedFilter[]
6
- datasets: Record<string, DataSet>
7
- description: any
8
- title: any
9
- theme: any
10
- filters: any // deprecate
11
- }
1
+ import { DataSet } from '@cdc/core/types/DataSet'
2
+ import { SharedFilter } from './SharedFilter'
3
+
4
+ export type Dashboard = {
5
+ sharedFilters: SharedFilter[]
6
+ datasets: Record<string, DataSet>
7
+ description: any
8
+ title: any
9
+ theme: any
10
+ filters: any // deprecate
11
+ }