@cdc/dashboard 4.24.5 → 4.24.9

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 (87) hide show
  1. package/dist/cdcdashboard.js +144406 -127510
  2. package/examples/custom/css/respiratory.css +236 -0
  3. package/examples/custom/js/respiratory.js +242 -0
  4. package/examples/default-multi-dataset-shared-filter.json +1729 -0
  5. package/examples/ed-visits-county-file.json +618 -0
  6. package/examples/filtered-dash.json +6 -21
  7. package/examples/single-state-dashboard-filters.json +421 -0
  8. package/examples/state-level.json +90136 -0
  9. package/examples/state-points.json +10474 -0
  10. package/examples/test-file.json +147 -0
  11. package/examples/testing.json +94456 -0
  12. package/index.html +25 -4
  13. package/package.json +12 -11
  14. package/src/CdcDashboard.tsx +5 -1
  15. package/src/CdcDashboardComponent.tsx +250 -327
  16. package/src/DashboardContext.tsx +15 -1
  17. package/src/_stories/Dashboard.stories.tsx +158 -40
  18. package/src/_stories/_mock/api-filter-chart.json +11 -35
  19. package/src/_stories/_mock/api-filter-map.json +17 -31
  20. package/src/_stories/_mock/bump-chart.json +3554 -0
  21. package/src/_stories/_mock/methodology.json +412 -0
  22. package/src/_stories/_mock/methodologyAPI.ts +90 -0
  23. package/src/_stories/_mock/multi-viz.json +3 -4
  24. package/src/_stories/_mock/pivot-filter.json +14 -12
  25. package/src/_stories/_mock/single-state-dashboard-filters.json +390 -0
  26. package/src/components/CollapsibleVisualizationRow.tsx +44 -0
  27. package/src/components/Column.tsx +1 -1
  28. package/src/components/DashboardFilters/DashboardFilters.tsx +102 -0
  29. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +218 -0
  30. package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx +48 -0
  31. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +477 -0
  32. package/src/components/DashboardFilters/DashboardFiltersEditor/index.ts +1 -0
  33. package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +191 -0
  34. package/src/components/DashboardFilters/index.ts +3 -0
  35. package/src/components/DataDesignerModal.tsx +9 -9
  36. package/src/components/ExpandCollapseButtons.tsx +20 -0
  37. package/src/components/Header/Header.tsx +1 -102
  38. package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +24 -12
  39. package/src/components/Row.tsx +52 -19
  40. package/src/components/Toggle/Toggle.tsx +2 -4
  41. package/src/components/VisualizationRow.tsx +169 -30
  42. package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +116 -0
  43. package/src/components/VisualizationsPanel/index.ts +1 -0
  44. package/src/components/VisualizationsPanel/visualizations-panel-styles.css +12 -0
  45. package/src/components/Widget.tsx +27 -90
  46. package/src/helpers/FilterBehavior.ts +4 -0
  47. package/src/helpers/addValuesToDashboardFilters.ts +49 -0
  48. package/src/helpers/apiFilterHelpers.ts +102 -0
  49. package/src/helpers/changeFilterActive.ts +39 -0
  50. package/src/helpers/filterData.ts +10 -48
  51. package/src/helpers/generateValuesForFilter.ts +1 -1
  52. package/src/helpers/getAutoLoadVisualization.ts +11 -0
  53. package/src/helpers/getFilteredData.ts +7 -5
  54. package/src/helpers/getVizConfig.ts +23 -2
  55. package/src/helpers/getVizRowColumnLocator.ts +2 -1
  56. package/src/helpers/hasDashboardApplyBehavior.ts +5 -0
  57. package/src/helpers/iconHash.tsx +5 -3
  58. package/src/helpers/loadAPIFilters.ts +74 -0
  59. package/src/helpers/mapDataToConfig.ts +29 -0
  60. package/src/helpers/processData.ts +2 -3
  61. package/src/helpers/reloadURLHelpers.ts +78 -0
  62. package/src/helpers/tests/addValuesToDashboardFilters.test.ts +44 -0
  63. package/src/helpers/tests/apiFilterHelpers.test.ts +156 -0
  64. package/src/helpers/tests/filterData.test.ts +1 -93
  65. package/src/helpers/tests/getFilteredData.test.ts +86 -0
  66. package/src/helpers/tests/loadAPIFiltersWrapper.test.ts +176 -0
  67. package/src/helpers/tests/reloadURLHelpers.test.ts +195 -0
  68. package/src/scss/editor-panel.scss +1 -1
  69. package/src/scss/grid.scss +34 -27
  70. package/src/scss/main.scss +41 -3
  71. package/src/scss/variables.scss +4 -0
  72. package/src/store/dashboard.actions.ts +12 -4
  73. package/src/store/dashboard.reducer.ts +30 -4
  74. package/src/types/APIFilter.ts +1 -5
  75. package/src/types/ConfigRow.ts +2 -0
  76. package/src/types/Dashboard.ts +1 -1
  77. package/src/types/DashboardConfig.ts +2 -4
  78. package/src/types/DashboardFilters.ts +7 -0
  79. package/src/types/InitialState.ts +1 -1
  80. package/src/types/MultiDashboard.ts +2 -2
  81. package/src/types/SharedFilter.ts +4 -6
  82. package/src/types/Tab.ts +1 -1
  83. package/LICENSE +0 -201
  84. package/src/components/Filters.tsx +0 -88
  85. package/src/components/Header/FilterModal.tsx +0 -510
  86. package/src/components/VisualizationsPanel.tsx +0 -95
  87. package/src/helpers/getApiFilterKey.ts +0 -5
@@ -0,0 +1,390 @@
1
+ {
2
+ "dashboard": {
3
+ "theme": "theme-blue",
4
+ "sharedFilters": [
5
+ {
6
+ "key": "New Dashboard Filter 1",
7
+ "showDropdown": true,
8
+ "values": [
9
+ "Florida",
10
+ "California"
11
+ ],
12
+ "type": "datafilter",
13
+ "columnName": "State",
14
+ "tier": 1,
15
+ "usedBy": [
16
+ "map1721943918271"
17
+ ]
18
+ }
19
+ ]
20
+ },
21
+ "rows": [
22
+ {
23
+ "columns": [
24
+ {
25
+ "width": 12,
26
+ "widget": "dashboardFilters1721943964161"
27
+ }
28
+ ],
29
+ "uuid": 1721943975299
30
+ },
31
+ {
32
+ "uuid": 1721943975299,
33
+ "columns": [
34
+ {
35
+ "width": 12,
36
+ "widget": "map1721943918271"
37
+ },
38
+ {},
39
+ {}
40
+ ]
41
+ }
42
+ ],
43
+ "visualizations": {
44
+ "map1721943918271": {
45
+ "annotations": [],
46
+ "general": {
47
+ "geoType": "single-state",
48
+ "annotationDropdownText": "Annotations",
49
+ "geoBorderColor": "darkGray",
50
+ "headerColor": "theme-blue",
51
+ "title": "",
52
+ "showTitle": true,
53
+ "showSidebar": true,
54
+ "showDownloadButton": true,
55
+ "showDownloadMediaButton": false,
56
+ "displayAsHex": false,
57
+ "displayStateLabels": false,
58
+ "territoriesLabel": "Territories",
59
+ "territoriesAlwaysShow": false,
60
+ "language": "en",
61
+ "geoLabelOverride": "",
62
+ "hasRegions": false,
63
+ "fullBorder": false,
64
+ "type": "data",
65
+ "convertFipsCodes": true,
66
+ "palette": {
67
+ "isReversed": false
68
+ },
69
+ "allowMapZoom": true,
70
+ "hideGeoColumnInTooltip": false,
71
+ "hidePrimaryColumnInTooltip": false,
72
+ "expandDataTable": false,
73
+ "filterControlsStatePicked": "State",
74
+ "statePicked": {
75
+ "fipsCode": "01",
76
+ "stateName": "Alabama"
77
+ }
78
+ },
79
+ "type": "map",
80
+ "color": "pinkpurple",
81
+ "columns": {
82
+ "geo": {
83
+ "name": "FIPS Codes",
84
+ "label": "Location",
85
+ "tooltip": false,
86
+ "dataTable": true
87
+ },
88
+ "primary": {
89
+ "dataTable": true,
90
+ "tooltip": true,
91
+ "prefix": "",
92
+ "suffix": "",
93
+ "name": "Insured Rate",
94
+ "label": "",
95
+ "roundToPlace": 0
96
+ },
97
+ "navigate": {
98
+ "name": ""
99
+ },
100
+ "latitude": {
101
+ "name": "Latitude"
102
+ },
103
+ "longitude": {
104
+ "name": "Longitude"
105
+ }
106
+ },
107
+ "legend": {
108
+ "descriptions": {},
109
+ "specialClasses": [],
110
+ "unified": false,
111
+ "singleColumn": false,
112
+ "singleRow": false,
113
+ "verticalSorted": false,
114
+ "showSpecialClassesLast": false,
115
+ "dynamicDescription": false,
116
+ "type": "equalnumber",
117
+ "numberOfItems": 3,
118
+ "position": "side",
119
+ "title": "Legend"
120
+ },
121
+ "filters": [],
122
+ "table": {
123
+ "wrapColumns": false,
124
+ "label": "Data Table",
125
+ "expanded": false,
126
+ "limitHeight": false,
127
+ "height": "",
128
+ "caption": "",
129
+ "showDownloadUrl": false,
130
+ "showDataTableLink": true,
131
+ "showFullGeoNameInCSV": false,
132
+ "forceDisplay": true,
133
+ "download": true,
134
+ "indexLabel": ""
135
+ },
136
+ "tooltips": {
137
+ "appearanceType": "hover",
138
+ "linkLabel": "Learn More",
139
+ "capitalizeLabels": true,
140
+ "opacity": 90
141
+ },
142
+ "visual": {
143
+ "minBubbleSize": 1,
144
+ "maxBubbleSize": 20,
145
+ "extraBubbleBorder": false,
146
+ "cityStyle": "circle",
147
+ "cityStyleLabel": "",
148
+ "showBubbleZeros": false,
149
+ "additionalCityStyles": [],
150
+ "geoCodeCircleSize": "2"
151
+ },
152
+ "mapPosition": {
153
+ "coordinates": [
154
+ 0,
155
+ 30
156
+ ],
157
+ "zoom": 1
158
+ },
159
+ "map": {
160
+ "layers": [],
161
+ "patterns": []
162
+ },
163
+ "hexMap": {
164
+ "type": "",
165
+ "shapeGroups": [
166
+ {
167
+ "legendTitle": "",
168
+ "legendDescription": "",
169
+ "items": [
170
+ {
171
+ "key": "",
172
+ "shape": "Arrow Up",
173
+ "column": "",
174
+ "operator": "=",
175
+ "value": ""
176
+ }
177
+ ]
178
+ }
179
+ ]
180
+ },
181
+ "filterBehavior": "Filter Change",
182
+ "openModal": true,
183
+ "uid": "map1721943918271",
184
+ "dataDescription": {
185
+ "horizontal": false,
186
+ "series": false
187
+ },
188
+ "dataKey": "test-single-county-file.json",
189
+ "editing": false,
190
+ "originalFormattedData": [
191
+ {
192
+ "Insured Rate": 8,
193
+ "Coverage Status": "Insured",
194
+ "FIPS Codes": "12057",
195
+ "Year (Good filter option)": "2010",
196
+ "link": "",
197
+ "Latitude": "",
198
+ "Longitude": "",
199
+ "State": "Florida"
200
+ },
201
+ {
202
+ "Insured Rate": 25,
203
+ "Coverage Status": "Insured",
204
+ "FIPS Codes": "55005",
205
+ "Year (Good filter option)": "2010",
206
+ "link": "",
207
+ "Latitude": "",
208
+ "Longitude": "",
209
+ "State": "California"
210
+ },
211
+ {
212
+ "Insured Rate": 25,
213
+ "Coverage Status": "Insured",
214
+ "FIPS Codes": "12103",
215
+ "Year (Good filter option)": "2010",
216
+ "link": "",
217
+ "Latitude": "",
218
+ "Longitude": "",
219
+ "State": "Florida"
220
+ },
221
+ {
222
+ "Insured Rate": 25,
223
+ "Coverage Status": "Insured",
224
+ "FIPS Codes": "32005",
225
+ "Year (Good filter option)": "2010",
226
+ "link": "",
227
+ "Latitude": "",
228
+ "Longitude": "",
229
+ "State": "California"
230
+ },
231
+ {
232
+ "Insured Rate": 18,
233
+ "Coverage Status": "Insured",
234
+ "FIPS Codes": "06075",
235
+ "Year (Good filter option)": "2010",
236
+ "link": "",
237
+ "Latitude": "",
238
+ "Longitude": "",
239
+ "State": "California"
240
+ },
241
+ {
242
+ "Insured Rate": 3,
243
+ "Coverage Status": "Insured",
244
+ "FIPS Codes": "06027",
245
+ "Year (Good filter option)": "2010",
246
+ "link": "",
247
+ "Latitude": "",
248
+ "Longitude": "",
249
+ "State": "California"
250
+ },
251
+ {
252
+ "Insured Rate": 25,
253
+ "Coverage Status": "Insured",
254
+ "FIPS Codes": "06029",
255
+ "Year (Good filter option)": "2010",
256
+ "link": "",
257
+ "Latitude": "",
258
+ "Longitude": "",
259
+ "State": "California"
260
+ },
261
+ {
262
+ "Insured Rate": 60,
263
+ "Coverage Status": "Insured",
264
+ "FIPS Codes": "Yosemite",
265
+ "Year (Good filter option)": "2010",
266
+ "link": "",
267
+ "Latitude": "37.865101",
268
+ "Longitude": "-119.538330",
269
+ "State": "California"
270
+ }
271
+ ],
272
+ "version": "4.24.9"
273
+ },
274
+ "dashboardFilters1721943964161": {
275
+ "filters": [],
276
+ "filterBehavior": "Filter Change",
277
+ "newViz": true,
278
+ "openModal": true,
279
+ "uid": "dashboardFilters1721943964161",
280
+ "type": "dashboardFilters",
281
+ "sharedFilterIndexes": [
282
+ 0
283
+ ],
284
+ "visualizationType": "dashboardFilters",
285
+ "editing": false
286
+ }
287
+ },
288
+ "table": {
289
+ "label": "Data Table",
290
+ "show": true,
291
+ "showDownloadUrl": false,
292
+ "showVertical": true
293
+ },
294
+ "newViz": true,
295
+ "datasets": {
296
+ "test-single-county-file.json": {
297
+ "data": [
298
+ {
299
+ "Insured Rate": 8,
300
+ "Coverage Status": "Insured",
301
+ "FIPS Codes": "12057",
302
+ "Year (Good filter option)": "2010",
303
+ "link": "",
304
+ "Latitude": "",
305
+ "Longitude": "",
306
+ "State": "Florida"
307
+ },
308
+ {
309
+ "Insured Rate": 25,
310
+ "Coverage Status": "Insured",
311
+ "FIPS Codes": "55005",
312
+ "Year (Good filter option)": "2010",
313
+ "link": "",
314
+ "Latitude": "",
315
+ "Longitude": "",
316
+ "State": "California"
317
+ },
318
+ {
319
+ "Insured Rate": 25,
320
+ "Coverage Status": "Insured",
321
+ "FIPS Codes": "12103",
322
+ "Year (Good filter option)": "2010",
323
+ "link": "",
324
+ "Latitude": "",
325
+ "Longitude": "",
326
+ "State": "Florida"
327
+ },
328
+ {
329
+ "Insured Rate": 25,
330
+ "Coverage Status": "Insured",
331
+ "FIPS Codes": "32005",
332
+ "Year (Good filter option)": "2010",
333
+ "link": "",
334
+ "Latitude": "",
335
+ "Longitude": "",
336
+ "State": "California"
337
+ },
338
+ {
339
+ "Insured Rate": 18,
340
+ "Coverage Status": "Insured",
341
+ "FIPS Codes": "06075",
342
+ "Year (Good filter option)": "2010",
343
+ "link": "",
344
+ "Latitude": "",
345
+ "Longitude": "",
346
+ "State": "California"
347
+ },
348
+ {
349
+ "Insured Rate": 3,
350
+ "Coverage Status": "Insured",
351
+ "FIPS Codes": "06027",
352
+ "Year (Good filter option)": "2010",
353
+ "link": "",
354
+ "Latitude": "",
355
+ "Longitude": "",
356
+ "State": "California"
357
+ },
358
+ {
359
+ "Insured Rate": 25,
360
+ "Coverage Status": "Insured",
361
+ "FIPS Codes": "06029",
362
+ "Year (Good filter option)": "2010",
363
+ "link": "",
364
+ "Latitude": "",
365
+ "Longitude": "",
366
+ "State": "California"
367
+ },
368
+ {
369
+ "Insured Rate": 60,
370
+ "Coverage Status": "Insured",
371
+ "FIPS Codes": "Yosemite",
372
+ "Year (Good filter option)": "2010",
373
+ "link": "",
374
+ "Latitude": "37.865101",
375
+ "Longitude": "-119.538330",
376
+ "State": "California"
377
+ }
378
+ ],
379
+ "dataFileSize": 1764,
380
+ "dataFileName": "test-single-county-file.json",
381
+ "dataFileSourceType": "file",
382
+ "dataFileFormat": "JSON",
383
+ "preview": true
384
+ }
385
+ },
386
+ "type": "dashboard",
387
+ "runtime": {},
388
+ "version": "4.24.9",
389
+ "uuid": 1721943961122
390
+ }
@@ -0,0 +1,44 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import Icon from '../../../core/components/ui/Icon'
3
+
4
+ type CollapsableVizRow = {
5
+ allExpanded: boolean
6
+ children: React.ReactNode
7
+ fontSize: string
8
+ groupName: string
9
+ currentViewport: string
10
+ }
11
+ const CollapsibleVisualizationRow: React.FC<CollapsableVizRow> = ({ allExpanded, fontSize, groupName, currentViewport, children }) => {
12
+ const [isExpanded, setIsExpanded] = useState(allExpanded)
13
+ const fontSizes = { small: 16, medium: 18, large: 20 }
14
+ const titleFontSize = ['sm', 'xs', 'xxs'].includes(currentViewport) ? '13px' : `${fontSizes[fontSize]}px`
15
+
16
+ useEffect(() => {
17
+ setIsExpanded(allExpanded)
18
+ }, [allExpanded])
19
+
20
+ return (
21
+ <>
22
+ <div
23
+ style={{ fontSize: titleFontSize }}
24
+ role='button'
25
+ className={`multi-visualiation-heading${isExpanded ? '' : ' collapsed'} h4`}
26
+ onClick={() => {
27
+ setIsExpanded(!isExpanded)
28
+ }}
29
+ tabIndex={0}
30
+ onKeyDown={e => {
31
+ if (e.keyCode === 13) {
32
+ setIsExpanded(!isExpanded)
33
+ }
34
+ }}
35
+ >
36
+ <Icon display={isExpanded ? 'minus' : 'plus'} base />
37
+ {groupName}
38
+ </div>
39
+ {isExpanded && children}
40
+ </>
41
+ )
42
+ }
43
+
44
+ export default CollapsibleVisualizationRow
@@ -40,7 +40,7 @@ const Column = ({ data, rowIdx, colIdx }) => {
40
40
  return (
41
41
  <div className={classNames.join(' ')} ref={drop}>
42
42
  {widget ? (
43
- <Widget data={{ rowIdx, colIdx, ...widget }} type={widget.visualizationType ?? widget.general?.geoType} />
43
+ <Widget widgetConfig={{ rowIdx, colIdx, ...widget }} type={widget.visualizationType ?? widget.general?.geoType} />
44
44
  ) : (
45
45
  <p className='builder-column__text'>
46
46
  Drag and drop <br /> visualization
@@ -0,0 +1,102 @@
1
+ import MultiSelect from '@cdc/core/components/MultiSelect'
2
+ import { SharedFilter } from '../../types/SharedFilter'
3
+ import { APIFilterDropdowns } from './DashboardFiltersWrapper'
4
+
5
+ type DashboardFilterProps = {
6
+ show: number[]
7
+ filters: SharedFilter[]
8
+ apiFilterDropdowns: APIFilterDropdowns
9
+ handleOnChange: Function
10
+ }
11
+
12
+ const DashboardFilters: React.FC<DashboardFilterProps> = ({
13
+ show,
14
+ filters: sharedFilters,
15
+ apiFilterDropdowns,
16
+ handleOnChange
17
+ }) => {
18
+ const nullVal = (filter: SharedFilter) => {
19
+ const val = filter.queuedActive || filter.active
20
+ return val === null || val === undefined || val === ''
21
+ }
22
+
23
+ const updateField = (_section, _subsection, fieldName, value) => {
24
+ handleOnChange(fieldName, value)
25
+ }
26
+
27
+ return (
28
+ <>
29
+ {sharedFilters.map((filter, filterIndex) => {
30
+ if (filter.showDropdown === false || (show && !show.includes(filterIndex))) return <></>
31
+ const values: JSX.Element[] = []
32
+ const multiValues = []
33
+ if (filter.resetLabel) {
34
+ values.push(
35
+ <option key={`${filter.resetLabel}-option`} value={filter.resetLabel}>
36
+ {filter.resetLabel}
37
+ </option>
38
+ )
39
+ }
40
+ const _key = filter.apiFilter?.apiEndpoint
41
+ if (_key && apiFilterDropdowns[_key]) {
42
+ // URL Filter
43
+ apiFilterDropdowns[_key].forEach(({ text, value }, index) => {
44
+ values.push(
45
+ <option key={`${value}-option-${index}`} value={value}>
46
+ {text}
47
+ </option>
48
+ )
49
+ multiValues.push({ value, label: text })
50
+ })
51
+ } else {
52
+ // Data Filter
53
+ filter.values?.forEach((filterOption, index) => {
54
+ const labeledOpt = filter.labels && filter.labels[filterOption]
55
+ values.push(
56
+ <option key={`${filter.key}-option-${index}`} value={filterOption}>
57
+ {labeledOpt || filterOption}
58
+ </option>
59
+ )
60
+ multiValues.push({ value: filterOption, label: labeledOpt || filterOption })
61
+ })
62
+ }
63
+
64
+ return filter.multiSelect ? (
65
+ <MultiSelect
66
+ key={`${filter.key}-filtersection-${filterIndex}`}
67
+ label={filter.key}
68
+ options={multiValues}
69
+ fieldName={filterIndex}
70
+ updateField={updateField}
71
+ selected={filter.active as string[]}
72
+ limit={filter.selectLimit || 5}
73
+ />
74
+ ) : (
75
+ <div className='cove-dashboard-filters' key={`${filter.key}-filtersection-${filterIndex}`}>
76
+ <section className='dashboard-filters-section'>
77
+ <label htmlFor={`filter-${filterIndex}`}>{filter.key}</label>
78
+ <select
79
+ id={`filter-${filterIndex}`}
80
+ className='filter-select'
81
+ data-index='0'
82
+ value={filter.queuedActive || filter.active}
83
+ onChange={val => {
84
+ handleOnChange(filterIndex, val.target.value)
85
+ }}
86
+ >
87
+ {nullVal(filter) && !filter.resetLabel && (
88
+ <option value='' key='select'>
89
+ {'-Select-'}
90
+ </option>
91
+ )}
92
+ {values}
93
+ </select>
94
+ </section>
95
+ </div>
96
+ )
97
+ })}
98
+ </>
99
+ )
100
+ }
101
+
102
+ export default DashboardFilters