@cdc/dashboard 4.25.6-2 → 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.
- package/dist/cdcdashboard.js +65154 -42764
- package/package.json +9 -9
- package/src/CdcDashboardComponent.tsx +11 -8
- package/src/components/Header/Header.tsx +2 -2
- package/src/components/VisualizationRow.tsx +324 -324
- package/src/helpers/getVizConfig.ts +1 -0
- package/src/helpers/getVizRowColumnLocator.ts +10 -10
- package/src/helpers/reloadURLHelpers.ts +124 -124
- package/src/store/dashboard.reducer.ts +288 -288
- package/src/types/ConfigRow.ts +19 -19
- package/src/types/Dashboard.ts +11 -11
- package/examples/private/DEV-10120.json +0 -1294
- package/examples/private/DEV-10527.json +0 -845
- package/examples/private/DEV-10586.json +0 -54319
- package/examples/private/DEV-10856.json +0 -54319
- package/examples/private/DEV-9199.json +0 -606
- package/examples/private/DEV-9644.json +0 -20092
- package/examples/private/DEV-9684.json +0 -2135
- package/examples/private/DEV-9932.json +0 -95
- package/examples/private/DEV-9989.json +0 -229
- package/examples/private/art-dashboard.json +0 -18174
- package/examples/private/art-scratch.json +0 -2406
- package/examples/private/bird-flu-2.json +0 -440
- package/examples/private/bird-flu.json +0 -413
- package/examples/private/crashing-sidebar.json +0 -975
- package/examples/private/d.json +0 -1561
- package/examples/private/dashboard-config-ehdi.json +0 -29915
- package/examples/private/dashboard-map-filter.json +0 -815
- package/examples/private/dashboard-margins.js +0 -15
- package/examples/private/dataset.json +0 -1452
- package/examples/private/dev-10856-2.json +0 -1348
- package/examples/private/ehdi-data.json +0 -29502
- package/examples/private/exposure-source-h5-data.csv +0 -26
- package/examples/private/fatal-data.csv +0 -3159
- package/examples/private/feelings.json +0 -1
- package/examples/private/gaza-issue.json +0 -1214
- package/examples/private/josh.json +0 -6175
- package/examples/private/map-issue.json +0 -628
- package/examples/private/markup.json +0 -115
- package/examples/private/mpox.json +0 -429
- package/examples/private/nhis.json +0 -1792
- package/examples/private/testing-pie.json +0 -436
- package/examples/private/workforce.json +0 -2041
|
@@ -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)
|
package/src/types/ConfigRow.ts
CHANGED
|
@@ -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
|
package/src/types/Dashboard.ts
CHANGED
|
@@ -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
|
+
}
|