@cdc/dashboard 4.24.3 → 4.24.5

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.
Files changed (37) hide show
  1. package/dist/cdcdashboard.js +148123 -105018
  2. package/examples/chart-data.json +5409 -0
  3. package/examples/full-dash-test.json +14643 -0
  4. package/examples/full-dashboard.json +10036 -0
  5. package/index.html +2 -2
  6. package/package.json +9 -9
  7. package/src/CdcDashboard.tsx +8 -3
  8. package/src/CdcDashboardComponent.tsx +141 -290
  9. package/src/_stories/Dashboard.stories.tsx +52 -7
  10. package/src/_stories/_mock/markup-include.json +78 -0
  11. package/src/_stories/_mock/multi-dashboards.json +914 -0
  12. package/src/_stories/_mock/multi-viz.json +378 -0
  13. package/src/_stories/_mock/pivot-filter.json +2 -2
  14. package/src/_stories/_mock/standalone-table.json +2 -0
  15. package/src/components/DataDesignerModal.tsx +145 -0
  16. package/src/components/Grid.tsx +3 -1
  17. package/src/components/Header/FilterModal.tsx +63 -33
  18. package/src/components/MultiConfigTabs/MultiTabs.tsx +3 -2
  19. package/src/components/Row.tsx +50 -25
  20. package/src/components/Toggle/Toggle.tsx +6 -7
  21. package/src/components/VisualizationRow.tsx +183 -0
  22. package/src/components/VisualizationsPanel.tsx +26 -3
  23. package/src/components/Widget.tsx +21 -103
  24. package/src/helpers/filterData.ts +1 -1
  25. package/src/helpers/getFilteredData.ts +39 -0
  26. package/src/helpers/getUpdateConfig.ts +15 -0
  27. package/src/helpers/getVizConfig.ts +31 -0
  28. package/src/helpers/getVizRowColumnLocator.ts +9 -0
  29. package/src/scss/grid.scss +9 -2
  30. package/src/scss/main.scss +5 -0
  31. package/src/store/dashboard.actions.ts +6 -0
  32. package/src/store/dashboard.reducer.ts +33 -8
  33. package/src/types/ConfigRow.ts +12 -3
  34. package/src/types/DataSet.ts +11 -8
  35. package/src/types/SharedFilter.ts +1 -1
  36. package/src/components/EditorWrapper/EditorWrapper.tsx +0 -52
  37. package/src/components/EditorWrapper/editor-wrapper.style.css +0 -13
@@ -0,0 +1,378 @@
1
+ {
2
+ "dashboard": {
3
+ "theme": "theme-blue",
4
+ "sharedFilters": [
5
+ {
6
+ "key": "Dashboard Filter 1",
7
+ "type": "datafilter",
8
+ "columnName": "Sample Categories",
9
+ "showDropdown": true,
10
+ "usedBy": ["0"],
11
+ "tier": 1
12
+ }
13
+ ]
14
+ },
15
+ "rows": [
16
+ {
17
+ "toggle": true,
18
+ "columns": [
19
+ {
20
+ "width": 12,
21
+ "widget": "chart1711646813542"
22
+ },
23
+ {
24
+ "width": 12,
25
+ "widget": "table1711646820983"
26
+ },
27
+ {
28
+ "width": 12
29
+ }
30
+ ],
31
+ "dataDescription": {
32
+ "horizontal": false,
33
+ "series": false
34
+ },
35
+
36
+ "dataKey": "valid-world-data.json",
37
+
38
+ "multiVizColumn": "Country"
39
+ }
40
+ ],
41
+ "visualizations": {
42
+ "chart1711646813542": {
43
+ "type": "chart",
44
+ "debugSvg": false,
45
+ "chartMessage": {
46
+ "noData": "No Data Available"
47
+ },
48
+ "title": "",
49
+ "showTitle": true,
50
+ "showDownloadMediaButton": false,
51
+ "theme": "theme-blue",
52
+ "animate": false,
53
+ "fontSize": "medium",
54
+ "lineDatapointStyle": "hover",
55
+ "lineDatapointColor": "Same as Line",
56
+ "barHasBorder": "false",
57
+ "isLollipopChart": false,
58
+ "lollipopShape": "circle",
59
+ "lollipopColorStyle": "two-tone",
60
+ "visualizationSubType": "regular",
61
+ "barStyle": "",
62
+ "roundingStyle": "standard",
63
+ "tipRounding": "top",
64
+ "isResponsiveTicks": false,
65
+ "general": {
66
+ "showDownloadButton": false
67
+ },
68
+ "padding": {
69
+ "left": 5,
70
+ "right": 5
71
+ },
72
+ "suppressedData": [],
73
+ "preliminaryData": [],
74
+ "yAxis": {
75
+ "hideAxis": false,
76
+ "displayNumbersOnBar": false,
77
+ "hideLabel": false,
78
+ "hideTicks": false,
79
+ "size": 50,
80
+ "gridLines": false,
81
+ "enablePadding": false,
82
+ "min": "",
83
+ "max": "",
84
+ "labelColor": "#333",
85
+ "tickLabelColor": "#333",
86
+ "tickColor": "#333",
87
+ "rightHideAxis": true,
88
+ "rightAxisSize": 0,
89
+ "rightLabel": "",
90
+ "rightLabelOffsetSize": 0,
91
+ "rightAxisLabelColor": "#333",
92
+ "rightAxisTickLabelColor": "#333",
93
+ "rightAxisTickColor": "#333",
94
+ "numTicks": "",
95
+ "axisPadding": 0,
96
+ "scalePadding": 10,
97
+ "tickRotation": 0,
98
+ "anchors": []
99
+ },
100
+ "boxplot": {
101
+ "plots": [],
102
+ "borders": "true",
103
+ "firstQuartilePercentage": 25,
104
+ "thirdQuartilePercentage": 75,
105
+ "boxWidthPercentage": 40,
106
+ "plotOutlierValues": false,
107
+ "plotNonOutlierValues": true,
108
+ "legend": {
109
+ "showHowToReadText": false,
110
+ "howToReadText": ""
111
+ },
112
+ "labels": {
113
+ "q1": "Lower Quartile",
114
+ "q2": "q2",
115
+ "q3": "Upper Quartile",
116
+ "q4": "q4",
117
+ "minimum": "Minimum",
118
+ "maximum": "Maximum",
119
+ "mean": "Mean",
120
+ "median": "Median",
121
+ "sd": "Standard Deviation",
122
+ "iqr": "Interquartile Range",
123
+ "total": "Total",
124
+ "outliers": "Outliers",
125
+ "values": "Values",
126
+ "lowerBounds": "Lower Bounds",
127
+ "upperBounds": "Upper Bounds"
128
+ }
129
+ },
130
+ "topAxis": {
131
+ "hasLine": false
132
+ },
133
+ "isLegendValue": false,
134
+ "barThickness": 0.35,
135
+ "barHeight": 25,
136
+ "barSpace": 15,
137
+ "heights": {
138
+ "vertical": 300,
139
+ "horizontal": 750
140
+ },
141
+ "xAxis": {
142
+ "sortDates": false,
143
+ "anchors": [],
144
+ "type": "categorical",
145
+ "showTargetLabel": true,
146
+ "targetLabel": "Target",
147
+ "hideAxis": false,
148
+ "hideLabel": false,
149
+ "hideTicks": false,
150
+ "size": 75,
151
+ "tickRotation": 0,
152
+ "min": "",
153
+ "max": "",
154
+ "labelColor": "#333",
155
+ "tickLabelColor": "#333",
156
+ "tickColor": "#333",
157
+ "numTicks": "",
158
+ "labelOffset": 65,
159
+ "axisPadding": 0,
160
+ "target": 0,
161
+ "maxTickRotation": 0,
162
+ "dataKey": "Sample Categories",
163
+ "tickWidthMax": 89
164
+ },
165
+ "table": {
166
+ "label": "Data Table",
167
+ "expanded": true,
168
+ "limitHeight": false,
169
+ "height": "",
170
+ "caption": "",
171
+ "showDownloadUrl": false,
172
+ "showDataTableLink": false,
173
+ "indexLabel": "",
174
+ "download": false,
175
+ "showVertical": true,
176
+ "dateDisplayFormat": "",
177
+ "show": false
178
+ },
179
+ "orientation": "vertical",
180
+ "color": "pinkpurple",
181
+ "columns": {},
182
+ "legend": {
183
+ "hide": false,
184
+ "behavior": "isolate",
185
+ "singleRow": true,
186
+ "colorCode": "",
187
+ "reverseLabelOrder": false,
188
+ "description": "",
189
+ "dynamicLegend": false,
190
+ "dynamicLegendDefaultText": "Show All",
191
+ "dynamicLegendItemLimit": 5,
192
+ "dynamicLegendItemLimitMessage": "Dynamic Legend Item Limit Hit.",
193
+ "dynamicLegendChartMessage": "Select Options from the Legend",
194
+ "lineMode": false,
195
+ "verticalSorted": false,
196
+ "highlightOnHover": false,
197
+ "seriesHighlight": []
198
+ },
199
+ "brush": {
200
+ "height": 25,
201
+ "active": false
202
+ },
203
+ "exclusions": {
204
+ "active": false,
205
+ "keys": []
206
+ },
207
+ "palette": "qualitative-bold",
208
+ "isPaletteReversed": false,
209
+ "twoColor": {
210
+ "palette": "monochrome-1",
211
+ "isPaletteReversed": false
212
+ },
213
+ "labels": false,
214
+ "dataFormat": {
215
+ "commas": false,
216
+ "prefix": "",
217
+ "suffix": "",
218
+ "abbreviated": false,
219
+ "bottomSuffix": "",
220
+ "bottomPrefix": "",
221
+ "bottomAbbreviated": false
222
+ },
223
+ "confidenceKeys": {},
224
+ "visual": {
225
+ "border": true,
226
+ "accent": true,
227
+ "background": true,
228
+ "verticalHoverLine": false,
229
+ "horizontalHoverLine": false
230
+ },
231
+ "useLogScale": false,
232
+ "filterBehavior": "Filter Change",
233
+ "highlightedBarValues": [],
234
+ "series": [
235
+ {
236
+ "dataKey": "Data",
237
+ "type": "Bar",
238
+ "axis": "Left",
239
+ "tooltip": true
240
+ }
241
+ ],
242
+ "tooltips": {
243
+ "opacity": 90,
244
+ "singleSeries": false,
245
+ "dateDisplayFormat": ""
246
+ },
247
+ "forestPlot": {
248
+ "startAt": 0,
249
+ "colors": {
250
+ "line": "",
251
+ "shape": ""
252
+ },
253
+ "lineOfNoEffect": {
254
+ "show": true
255
+ },
256
+ "type": "",
257
+ "pooledResult": {
258
+ "diamondHeight": 5,
259
+ "column": ""
260
+ },
261
+ "estimateField": "",
262
+ "estimateRadius": "",
263
+ "shape": "square",
264
+ "rowHeight": 20,
265
+ "description": {
266
+ "show": true,
267
+ "text": "description",
268
+ "location": 0
269
+ },
270
+ "result": {
271
+ "show": true,
272
+ "text": "result",
273
+ "location": 100
274
+ },
275
+ "radius": {
276
+ "min": 2,
277
+ "max": 10,
278
+ "scalingColumn": ""
279
+ },
280
+ "regression": {
281
+ "lower": 0,
282
+ "upper": 0,
283
+ "estimateField": 0
284
+ },
285
+ "leftWidthOffset": 0,
286
+ "rightWidthOffset": 0,
287
+ "showZeroLine": false,
288
+ "leftLabel": "",
289
+ "rightLabel": ""
290
+ },
291
+ "area": {
292
+ "isStacked": false
293
+ },
294
+ "sankey": {
295
+ "title": {
296
+ "defaultColor": "black"
297
+ },
298
+ "iterations": 1,
299
+ "rxValue": 0.9,
300
+ "overallSize": {
301
+ "width": 900,
302
+ "height": 700
303
+ },
304
+ "margin": {
305
+ "margin_y": 25,
306
+ "margin_x": 0
307
+ },
308
+ "nodeSize": {
309
+ "nodeWidth": 26,
310
+ "nodeHeight": 40
311
+ },
312
+ "nodePadding": 55,
313
+ "nodeFontColor": "black",
314
+ "nodeColor": {
315
+ "default": "#ff8500",
316
+ "inactive": "#808080"
317
+ },
318
+ "linkColor": {
319
+ "default": "#ffc900",
320
+ "inactive": "#D3D3D3"
321
+ },
322
+ "opacity": {
323
+ "nodeOpacityDefault": 1,
324
+ "nodeOpacityInactive": 0.1,
325
+ "LinkOpacityDefault": 1,
326
+ "LinkOpacityInactive": 0.1
327
+ },
328
+ "storyNodeFontColor": "#006778",
329
+ "storyNodeText": [],
330
+ "nodeValueStyle": {
331
+ "textBefore": "(",
332
+ "textAfter": ")"
333
+ },
334
+ "data": []
335
+ },
336
+ "openModal": true,
337
+ "uid": "chart1711646813542",
338
+ "visualizationType": "Bar",
339
+ "editing": false,
340
+ "dataKey": "valid-world-data.json",
341
+ "dataDescription": {
342
+ "horizontal": false,
343
+ "series": false
344
+ },
345
+ "version": "4.23",
346
+ "dynamicMarginTop": 0
347
+ },
348
+ "table1711646820983": {
349
+ "newViz": false,
350
+ "openModal": true,
351
+ "uid": "table1711646820983",
352
+ "type": "table",
353
+ "formattedData": {},
354
+ "table": {
355
+ "label": "Data Table",
356
+ "show": true,
357
+ "showDownloadUrl": false,
358
+ "showVertical": true,
359
+ "expanded": true
360
+ },
361
+ "columns": {},
362
+ "dataFormat": {},
363
+ "visualizationType": "table",
364
+ "editing": false
365
+ }
366
+ },
367
+ "table": {
368
+ "label": "Data Table",
369
+ "show": true,
370
+ "showDownloadUrl": false,
371
+ "showVertical": true
372
+ },
373
+ "newViz": true,
374
+ "datasets": {},
375
+ "type": "dashboard",
376
+ "runtime": {},
377
+ "version": "4.23"
378
+ }
@@ -24,7 +24,6 @@
24
24
  ],
25
25
  "visualizations": {
26
26
  "table1707935263149": {
27
- "newViz": true,
28
27
  "openModal": false,
29
28
  "uid": "table1707935263149",
30
29
  "type": "table",
@@ -42,6 +41,8 @@
42
41
  "horizontal": false,
43
42
  "series": false
44
43
  },
44
+ "filters": [],
45
+ "filterBehavior": "Filter Change",
45
46
  "formattedData": [
46
47
  {
47
48
  "Race": "Hispanic or Latino",
@@ -115,7 +116,6 @@
115
116
  "showDownloadUrl": false,
116
117
  "showVertical": true
117
118
  },
118
- "newViz": true,
119
119
  "datasets": {
120
120
  "valid-data-chart.csv": {
121
121
  "data": [
@@ -17,6 +17,8 @@
17
17
  "newViz": true,
18
18
  "openModal": false,
19
19
  "uid": "table1707840146431",
20
+ "filters": [],
21
+ "filterBehavior": "Filter Change",
20
22
  "table": {
21
23
  "label": "Data Table",
22
24
  "show": true,
@@ -0,0 +1,145 @@
1
+ import { useGlobalContext } from '@cdc/core/components/GlobalContext'
2
+ import DataDesigner from '@cdc/core/components/managers/DataDesigner'
3
+ import { useContext, useMemo, useState } from 'react'
4
+ import { DashboardContext, DashboardDispatchContext } from '../DashboardContext'
5
+ import Modal from '@cdc/core/components/ui/Modal'
6
+ import { CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
7
+ import Tooltip from '@cdc/core/components/ui/Tooltip'
8
+ import _ from 'lodash'
9
+ import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
10
+ import DataTransform from '@cdc/core/helpers/DataTransform'
11
+ import { ConfigureData } from '@cdc/core/types/ConfigureData'
12
+ import Icon from '@cdc/core/components/ui/Icon'
13
+ import InputSelect from '@cdc/core/components/inputs/InputSelect'
14
+
15
+ type DataDesignerModalProps = {
16
+ rowIndex: number
17
+ vizKey?: string
18
+ }
19
+
20
+ export const DataDesignerModal: React.FC<DataDesignerModalProps> = ({ vizKey, rowIndex }) => {
21
+ const { config } = useContext(DashboardContext)
22
+ const { overlay } = useGlobalContext()
23
+ const transform = new DataTransform()
24
+ const dispatch = useContext(DashboardDispatchContext)
25
+ const [canContinue, setCanContinue] = useState(false)
26
+ const [useRow, setUseRow] = useState(!vizKey)
27
+ const [multiViz, setMultiViz] = useState(!!config.rows[rowIndex].multiVizColumn)
28
+
29
+ const configureData = useMemo(() => {
30
+ if (vizKey && !useRow) {
31
+ return config.visualizations[vizKey]
32
+ }
33
+ return config.rows[rowIndex]
34
+ }, [config.visualizations, config.rows, vizKey, rowIndex, useRow])
35
+
36
+ const updateConfigureData = (newConfigureData: Partial<ConfigureData>) => {
37
+ if (vizKey && !useRow) {
38
+ dispatch({ type: 'UPDATE_VISUALIZATION', payload: { vizKey, configureData: newConfigureData } })
39
+ } else {
40
+ dispatch({ type: 'UPDATE_ROW', payload: { rowIndex, rowData: newConfigureData } })
41
+ }
42
+ }
43
+
44
+ const changeDataset = ({ target: { value } }) => {
45
+ const newConfigureData = { dataDescription: {}, formattedData: undefined, dataKey: value }
46
+
47
+ updateConfigureData(newConfigureData)
48
+ }
49
+
50
+ const updateDescriptionProp = async (key, value) => {
51
+ const datasetKey = configureData.dataKey
52
+ const { data, dataUrl } = config.datasets[datasetKey]
53
+ let newData = data
54
+ if (!data && dataUrl) {
55
+ newData = await fetchRemoteData(dataUrl)
56
+ newData = transform.autoStandardize(newData)
57
+ }
58
+
59
+ const dataDescription = { ...configureData.dataDescription, [key]: value }
60
+
61
+ const newConfigureData = { data: newData, dataDescription, formattedData: transform.developerStandardize(newData, dataDescription) }
62
+
63
+ updateConfigureData(newConfigureData)
64
+ setCanContinue(true)
65
+ }
66
+
67
+ const setMultiVizColumn = (column: string) => {
68
+ if (column !== '') {
69
+ dispatch({ type: 'UPDATE_ROW', payload: { rowIndex, rowData: { multiVizColumn: column } } })
70
+ setCanContinue(true)
71
+ }
72
+ }
73
+
74
+ return (
75
+ <Modal>
76
+ <Modal.Content>
77
+ <div className='dataset-selector-container'>
78
+ Select a dataset:&nbsp;
79
+ <select className='dataset-selector' value={configureData.dataKey || ''} onChange={changeDataset}>
80
+ <option value=''>Select a dataset</option>
81
+ {config.datasets && Object.keys(config.datasets).map(datasetKey => <option key={datasetKey}>{datasetKey}</option>)}
82
+ </select>
83
+ {vizKey && (
84
+ <CheckBox
85
+ label='Apply To Row'
86
+ value={useRow}
87
+ updateField={(section, subsection, fieldName, value) => {
88
+ setUseRow(value)
89
+ changeDataset({ target: { value: '' } })
90
+ }}
91
+ />
92
+ )}
93
+ </div>
94
+ {configureData.dataKey && (
95
+ <DataDesigner
96
+ {...{
97
+ configureData,
98
+ visualizationKey: vizKey,
99
+ updateDescriptionProp
100
+ }}
101
+ />
102
+ )}
103
+ {useRow && !!configureData.dataKey ? (
104
+ !multiViz ? (
105
+ <CheckBox
106
+ label='Configure Multiple Visualizations'
107
+ value={multiViz}
108
+ tooltip={
109
+ <Tooltip style={{ textTransform: 'none' }}>
110
+ <Tooltip.Target>
111
+ <Icon display='question' style={{ marginLeft: '0.5rem' }} />
112
+ </Tooltip.Target>
113
+ <Tooltip.Content>
114
+ <p>You can select a column where for each unique value in the column the configuration for the row will be repeated in to the data preview.</p>
115
+ </Tooltip.Content>
116
+ </Tooltip>
117
+ }
118
+ updateField={(section, subsection, fieldName, value) => {
119
+ if (canContinue && value === true) setCanContinue(false)
120
+ setMultiViz(value)
121
+ }}
122
+ />
123
+ ) : (
124
+ <InputSelect
125
+ options={Object.keys(config.datasets[configureData.dataKey]?.data[0] || {})}
126
+ value={config.rows[rowIndex].multiVizColumn}
127
+ label='Multi-Visualization Column'
128
+ initial='--Select--'
129
+ fieldName=''
130
+ updateField={(section, subsection, fieldName, value) => setMultiVizColumn(value)}
131
+ required
132
+ />
133
+ )
134
+ ) : (
135
+ <></>
136
+ )}
137
+ {canContinue && (
138
+ <button style={{ margin: '1em', display: 'block' }} className='cove-button' onClick={() => overlay?.actions.toggleOverlay()}>
139
+ Continue
140
+ </button>
141
+ )}
142
+ </Modal.Content>
143
+ </Modal>
144
+ )
145
+ }
@@ -2,6 +2,7 @@ import React, { useContext } from 'react'
2
2
  import Row from './Row'
3
3
 
4
4
  import { DashboardContext, DashboardDispatchContext } from '../DashboardContext'
5
+ import { ConfigRow } from '../types/ConfigRow'
5
6
 
6
7
  const Grid = () => {
7
8
  const { config } = useContext(DashboardContext)
@@ -10,9 +11,10 @@ const Grid = () => {
10
11
  const dispatch = useContext(DashboardDispatchContext)
11
12
  const updateConfig = config => dispatch({ type: 'UPDATE_CONFIG', payload: [config] })
12
13
  const addRow = () => {
14
+ const blankRow: Partial<ConfigRow> = { columns: [{ width: 12 }] }
13
15
  updateConfig({
14
16
  ...config,
15
- rows: [...rows, [{ width: 12 }, { equalHeight: false }, {}, {}]],
17
+ rows: [...rows, blankRow],
16
18
  uuid: Date.now()
17
19
  })
18
20
  }