@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
@@ -1,510 +0,0 @@
1
- import { useContext, useEffect, useMemo, useState } from 'react'
2
- import { MultiDashboardConfig } from '../../types/MultiDashboard'
3
- import { SharedFilter } from '../../types/SharedFilter'
4
- import { DashboardDispatchContext } from '../../DashboardContext'
5
- import { useGlobalContext } from '@cdc/core/components/GlobalContext'
6
- import { APIFilter } from '../../types/APIFilter'
7
- import Modal from '@cdc/core/components/ui/Modal'
8
- import { FilterBehavior } from './Header'
9
- import Tooltip from '@cdc/core/components/ui/Tooltip'
10
- import Icon from '@cdc/core/components/ui/Icon'
11
- import Button from '@cdc/core/components/elements/Button'
12
- import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
13
- import DataTransform from '@cdc/core/helpers/DataTransform'
14
- import { getVizRowColumnLocator } from '../../helpers/getVizRowColumnLocator'
15
- import _ from 'lodash'
16
-
17
- type ModalProps = {
18
- config: MultiDashboardConfig
19
- filterState: SharedFilter
20
- index: number
21
- removeFilter: Function
22
- }
23
-
24
- const FilterModal: React.FC<ModalProps> = ({ config, filterState, index, removeFilter }) => {
25
- const { overlay } = useGlobalContext()
26
- const dispatch = useContext(DashboardDispatchContext)
27
- const [filter, setFilter] = useState<SharedFilter>(filterState)
28
- const [columns, setColumns] = useState<string[]>([])
29
- const transform = new DataTransform()
30
-
31
- const vizRowColumnLocator = getVizRowColumnLocator(config.rows)
32
-
33
- const [usedByNameLookup, usedByOptions] = useMemo(() => {
34
- const nameLookup = {}
35
- const vizOptions = Object.keys(config.visualizations)
36
- .filter(vizKey => {
37
- const notAdded = !filter.usedBy || filter.usedBy.indexOf(vizKey) === -1
38
- const usesSharedFilter = config.visualizations[vizKey].usesSharedFilter
39
- const row = vizRowColumnLocator[vizKey].row
40
- const dataConfiguredOnRow = config.rows[row].dataKey
41
- return filter.setBy !== vizKey && notAdded && !usesSharedFilter && !dataConfiguredOnRow
42
- })
43
- .map(vizKey => {
44
- const viz = config.visualizations[vizKey]
45
- const vizName = viz.general?.title || viz.title || vizKey
46
- nameLookup[vizKey] = vizName
47
- return vizKey
48
- })
49
- const rowOptions: number[] = []
50
-
51
- config.rows.forEach((row, rowIndex) => {
52
- if (!!row.multiVizColumn) {
53
- nameLookup[rowIndex] = `Row ${rowIndex + 1}`
54
- rowOptions.push(rowIndex)
55
- }
56
- })
57
-
58
- const rowsNotSelected = rowOptions.filter(row => !filter.usedBy || filter.usedBy.indexOf(row.toString()) === -1)
59
- return [nameLookup, [...vizOptions, ...rowsNotSelected]]
60
- }, [config.visualizations, filter.usedBy, filter.setBy, vizRowColumnLocator])
61
-
62
- useEffect(() => {
63
- const runSetColumns = async () => {
64
- let columns = {}
65
- let dataKeys = Object.keys(config.datasets)
66
-
67
- for (let i = 0; i < dataKeys.length; i++) {
68
- let _dataSet = config.datasets[dataKeys[i]]
69
- if (!_dataSet.data && _dataSet.dataUrl) {
70
- config.datasets[dataKeys[i]].data = await fetchRemoteData(config.datasets[dataKeys[i]].dataUrl)
71
- _dataSet = config.datasets[dataKeys[i]]
72
- if (_dataSet.dataDescription) {
73
- try {
74
- config.datasets[dataKeys[i]].data = transform.autoStandardize(_dataSet.data)
75
- _dataSet = config.datasets[dataKeys[i]]
76
- config.datasets[dataKeys[i]].data = transform.developerStandardize(_dataSet.data, _dataSet.dataDescription)
77
- _dataSet = config.datasets[dataKeys[i]]
78
- } catch (e) {
79
- //Data not able to be standardized, leave as is
80
- }
81
- }
82
- }
83
-
84
- if (_dataSet.data) {
85
- config.datasets[dataKeys[i]].data.forEach(row => {
86
- Object.keys(row).forEach(columnName => (columns[columnName] = true))
87
- })
88
- }
89
- }
90
-
91
- setColumns(Object.keys(columns))
92
- }
93
-
94
- runSetColumns()
95
- }, [config.datasets])
96
-
97
- const saveChanges = () => {
98
- let tempConfig = { ...config.dashboard }
99
- tempConfig.sharedFilters[index] = filter
100
-
101
- dispatch({ type: 'UPDATE_CONFIG', payload: [{ ...config, dashboard: tempConfig }] })
102
- overlay?.actions.toggleOverlay()
103
- }
104
-
105
- const updateFilterProp = (name, value) => {
106
- const newFilter = { ..._.cloneDeep(filter), [name]: value }
107
-
108
- setFilter(newFilter)
109
- }
110
-
111
- const addFilterUsedBy = (filter, value) => {
112
- if (value === '') return
113
- if (!filter.usedBy) filter.usedBy = []
114
- filter.usedBy.push(value)
115
- updateFilterProp('usedBy', filter.usedBy)
116
- }
117
-
118
- const removeFilterUsedBy = (filter, value) => {
119
- let usedByIndex = filter.usedBy.indexOf(value)
120
- if (usedByIndex !== -1) {
121
- filter.usedBy.splice(usedByIndex, 1)
122
- updateFilterProp('usedBy', filter.usedBy)
123
- }
124
- }
125
-
126
- const updateAPIFilter = (key: keyof APIFilter, value: string | boolean) => {
127
- const filterClone = _.cloneDeep(filter)
128
- const _filter = filterClone.apiFilter || { apiEndpoint: '', valueSelector: '', textSelector: '' }
129
- const newAPIFilter: APIFilter = { ..._filter, [key]: value }
130
- setFilter({ ...filterClone, apiFilter: newAPIFilter })
131
- }
132
-
133
- return (
134
- <Modal>
135
- <Modal.Content>
136
- <h2 className='shared-filter-modal__title'>Dashboard Filter Settings</h2>
137
- <fieldset className='shared-filter-modal shared-filter-modal__fieldset' key={filter.columnName + index}>
138
- <label>
139
- <span className='edit-label column-heading'>Filter Type: </span>
140
- <select defaultValue={filter.type || ''} onChange={e => updateFilterProp('type', e.target.value)}>
141
- <option value=''>- Select Option -</option>
142
- <option value='urlfilter'>URL</option>
143
- <option value='datafilter'>Data</option>
144
- </select>
145
- </label>
146
- {filter.type === 'urlfilter' && (
147
- <>
148
- <label>
149
- <span className='edit-label column-heading'>Label: </span>
150
- <input
151
- type='text'
152
- value={filter.key}
153
- onChange={e => {
154
- updateFilterProp('key', e.target.value)
155
- }}
156
- />
157
- </label>
158
- {config.filterBehavior !== FilterBehavior.Apply && (
159
- <>
160
- <label>
161
- <span className='edit-label column-heading'>URL to Filter: </span>
162
- <select defaultValue={filter.datasetKey || ''} onChange={e => updateFilterProp('datasetKey', e.target.value)}>
163
- <option value=''>- Select Option -</option>
164
- {Object.keys(config.datasets).map(datasetKey => {
165
- if (config.datasets[datasetKey].dataUrl) {
166
- return (
167
- <option key={datasetKey} value={datasetKey}>
168
- {config.datasets[datasetKey].dataUrl}
169
- </option>
170
- )
171
- }
172
- return null
173
- })}
174
- </select>
175
- </label>
176
- <label>
177
- <span className='edit-label column-heading'>Filter By: </span>
178
- <select defaultValue={filter.filterBy || ''} onChange={e => updateFilterProp('filterBy', e.target.value)}>
179
- <option value=''>- Select Option -</option>
180
- <option key={'query-string'} value={'Query String'}>
181
- Query String
182
- </option>
183
- <option key={'file-name'} value={'File Name'}>
184
- File Name
185
- </option>
186
- </select>
187
- </label>
188
- {filter.filterBy === 'File Name' && (
189
- <>
190
- <label>
191
- <span className='edit-label column-heading'>
192
- File Name:
193
- <Tooltip style={{ textTransform: 'none' }}>
194
- <Tooltip.Target>
195
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
196
- </Tooltip.Target>
197
- <Tooltip.Content>
198
- <p>{`Add \${query}\ to replace the filename with the active dropdown value.`}</p>
199
- </Tooltip.Content>
200
- </Tooltip>
201
- </span>
202
-
203
- <input type='text' defaultValue={filter.fileName || ''} onChange={e => updateFilterProp('fileName', e.target.value)} />
204
- </label>
205
-
206
- <label>
207
- <span className='edit-label column-heading'>
208
- White Space Replacments
209
- <Tooltip style={{ textTransform: 'none' }}>
210
- <Tooltip.Target>
211
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
212
- </Tooltip.Target>
213
- <Tooltip.Content>
214
- <p>{`Set how whitespace characters will be handled in the file request`}</p>
215
- </Tooltip.Content>
216
- </Tooltip>
217
- </span>
218
- <select defaultValue={filter.whitespaceReplacement || 'Keep Spaces'} onChange={e => updateFilterProp('whitespaceReplacement', e.target.value)}>
219
- <option key={'remove-spaces'} value={'Remove Spaces'}>
220
- Remove Spaces
221
- </option>
222
- <option key={'replace-with-underscore'} value={'Replace With Underscore'}>
223
- Replace With Underscore
224
- </option>
225
- <option key={'keep-spaces'} value={'Keep Spaces'}>
226
- Keep Spaces
227
- </option>
228
- </select>
229
- </label>
230
- </>
231
- )}
232
- </>
233
- )}
234
- {filter.filterBy === 'Query String' && (
235
- <label>
236
- <span className='edit-label column-heading'>Query string parameter</span> <input type='text' defaultValue={filter.queryParameter} onChange={e => updateFilterProp('queryParameter', e.target.value)} />
237
- </label>
238
- )}
239
- <label>
240
- <span className='edit-label column-heading'>Filter API Endpoint: </span>
241
- <input
242
- type='text'
243
- value={filter.apiFilter?.apiEndpoint}
244
- onChange={e => {
245
- updateAPIFilter('apiEndpoint', e.target.value)
246
- }}
247
- />
248
- </label>
249
- <label>
250
- <span className='edit-label column-heading'>
251
- Option Text Selector:
252
- <Tooltip style={{ textTransform: 'none' }}>
253
- <Tooltip.Target>
254
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
255
- </Tooltip.Target>
256
- <Tooltip.Content>
257
- <p>Text to use in the html option element</p>
258
- </Tooltip.Content>
259
- </Tooltip>
260
- </span>
261
- <input
262
- type='text'
263
- value={filter.apiFilter?.textSelector}
264
- onChange={e => {
265
- updateAPIFilter('textSelector', e.target.value)
266
- }}
267
- />
268
- </label>
269
- <label>
270
- <span className='edit-label column-heading'>
271
- Option Value Selector:
272
- <Tooltip style={{ textTransform: 'none' }}>
273
- <Tooltip.Target>
274
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
275
- </Tooltip.Target>
276
- <Tooltip.Content>
277
- <p>Value to use in the html option element</p>
278
- </Tooltip.Content>
279
- </Tooltip>
280
- </span>
281
- <input
282
- type='text'
283
- value={filter.apiFilter?.valueSelector}
284
- onChange={e => {
285
- updateAPIFilter('valueSelector', e.target.value)
286
- }}
287
- />
288
- </label>
289
- <label>
290
- <span className='edit-label column-heading'>Parent Filter: </span>
291
- <select
292
- value={filter.parents || []}
293
- onChange={e => {
294
- updateFilterProp('parents', e.target.value)
295
- }}
296
- >
297
- <option value=''>Select a filter</option>
298
- {config.dashboard.sharedFilters &&
299
- config.dashboard.sharedFilters.map(sharedFilter => {
300
- if (sharedFilter.key !== filter.key && sharedFilter.type !== 'datafilter') {
301
- return <option value={sharedFilter.key}>{sharedFilter.key}</option>
302
- }
303
- })}
304
- </select>
305
- </label>
306
- <label>
307
- <span className='edit-label column-heading'>Auto Load: </span>
308
- <input
309
- type='checkbox'
310
- checked={filter.apiFilter?.autoLoad}
311
- onChange={e => {
312
- updateAPIFilter('autoLoad', !filter.apiFilter?.autoLoad)
313
- }}
314
- />
315
- </label>
316
- <label>
317
- <span className='edit-label column-heading'>Default Value: </span>
318
- <input
319
- type='text'
320
- value={filter.apiFilter?.defaultValue}
321
- onChange={e => {
322
- updateAPIFilter('defaultValue', e.target.value)
323
- }}
324
- />
325
- </label>
326
- <label>
327
- <span className='edit-label column-heading'>Default Value Set By Query String Parameter: </span>
328
- <input
329
- type='text'
330
- value={filter.setByQueryParameter || ''}
331
- onChange={e => {
332
- updateFilterProp('setByQueryParameter', e.target.value)
333
- }}
334
- />
335
- </label>
336
- </>
337
- )}
338
- {filter.type === 'datafilter' && (
339
- <>
340
- <label>
341
- <span className='edit-label column-heading'>Filter: </span>
342
- <select
343
- value={filter.columnName}
344
- onChange={e => {
345
- updateFilterProp('columnName', e.target.value)
346
- }}
347
- >
348
- <option value=''>- Select Option -</option>
349
- {columns.map(dataKey => (
350
- <option value={dataKey} key={`filter-column-select-item-${dataKey}`}>
351
- {dataKey}
352
- </option>
353
- ))}
354
- </select>
355
- </label>
356
- <label>
357
- <span className='edit-label column-heading'>
358
- Pivot:{' '}
359
- <Tooltip style={{ textTransform: 'none' }}>
360
- <Tooltip.Target>
361
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
362
- </Tooltip.Target>
363
- <Tooltip.Content>
364
- <p>The column whos values will be pivoted under the column selected as the Filter.</p>
365
- </Tooltip.Content>
366
- </Tooltip>
367
- </span>
368
- <select
369
- value={filter.pivot}
370
- onChange={e => {
371
- updateFilterProp('pivot', e.target.value)
372
- updateFilterProp('showDropdown', true)
373
- }}
374
- >
375
- <option value=''>- Select Option -</option>
376
- {columns
377
- .filter(col => filter.columnName !== col)
378
- .map(dataKey => (
379
- <option value={dataKey} key={`filter-column-select-item-${dataKey}`}>
380
- {dataKey}
381
- </option>
382
- ))}
383
- </select>
384
- </label>
385
- <label>
386
- <span className='edit-label column-heading'>Label: </span>
387
- <input
388
- type='text'
389
- value={filter.key}
390
- onChange={e => {
391
- updateFilterProp('key', e.target.value)
392
- }}
393
- />
394
- </label>
395
- {!filter.pivot && (
396
- <label>
397
- <span className='edit-label column-heading'>Show Dropdown</span>
398
- <input
399
- type='checkbox'
400
- defaultChecked={filter.showDropdown === true}
401
- onChange={e => {
402
- updateFilterProp('showDropdown', !filter.showDropdown)
403
- }}
404
- />
405
- </label>
406
- )}
407
-
408
- <label>
409
- <span className='edit-label column-heading'>Set By: </span>
410
- <select value={filter.setBy} onChange={e => updateFilterProp('setBy', e.target.value)}>
411
- <option value=''>- Select Option -</option>
412
- {Object.keys(config.visualizations).map(vizKey => (
413
- <option value={vizKey} key={`set-by-select-item-${vizKey}`}>
414
- {config.visualizations[vizKey].general && config.visualizations[vizKey].general.title ? config.visualizations[vizKey].general.title : config.visualizations[vizKey].title || vizKey}
415
- </option>
416
- ))}
417
- </select>
418
- </label>
419
- <label>
420
- <span className='edit-label column-heading'>Used By: </span>
421
- <ul>
422
- {filter.usedBy &&
423
- filter.usedBy.map(opt => (
424
- <li key={`used-by-list-item-${opt}`}>
425
- <span>{usedByNameLookup[opt] || opt}</span>{' '}
426
- <button
427
- onClick={e => {
428
- e.preventDefault()
429
- removeFilterUsedBy(filter, opt)
430
- }}
431
- >
432
- X
433
- </button>
434
- </li>
435
- ))}
436
- </ul>
437
- <select value='' onChange={e => addFilterUsedBy(filter, e.target.value)}>
438
- <option value=''>- Select Option -</option>
439
- {usedByOptions.map(opt => (
440
- <option value={opt} key={`used-by-select-item-${opt}`}>
441
- {usedByNameLookup[opt] || opt}
442
- </option>
443
- ))}
444
- </select>
445
- </label>
446
- <label>
447
- <span className='edit-label column-heading'>Reset Label: </span>
448
- <input
449
- type='text'
450
- value={filter.resetLabel || ''}
451
- onChange={e => {
452
- updateFilterProp('resetLabel', e.target.value)
453
- }}
454
- />
455
- </label>
456
- <label>
457
- <span className='edit-label column-heading'>Parent Filter: </span>
458
- <select
459
- value={filter.parents || []}
460
- onChange={e => {
461
- updateFilterProp('parents', e.target.value)
462
- }}
463
- >
464
- <option value=''>Select a filter</option>
465
- {config.dashboard.sharedFilters &&
466
- config.dashboard.sharedFilters.map(sharedFilter => {
467
- if (sharedFilter.key !== filter.key) {
468
- return <option>{sharedFilter.key}</option>
469
- }
470
- })}
471
- </select>
472
- </label>
473
- <label>
474
- <span className='edit-label column-heading'>Default Value Set By Query String Parameter: </span>
475
- <input
476
- type='text'
477
- value={filter.setByQueryParameter || ''}
478
- onChange={e => {
479
- updateFilterProp('setByQueryParameter', e.target.value)
480
- }}
481
- />
482
- </label>
483
- </>
484
- )}
485
- </fieldset>
486
-
487
- <Button
488
- className='btn--remove warn'
489
- onClick={() => {
490
- removeFilter()
491
- }}
492
- >
493
- Remove Filter
494
- </Button>
495
-
496
- <div className='shared-filter-modal__right-buttons'>
497
- <Button className='btn--cancel muted' style={{ display: 'inline-block', marginRight: '1em' }} onClick={overlay?.actions.toggleOverlay}>
498
- Cancel
499
- </Button>
500
-
501
- <Button type='button' className='btn--submit success' style={{ display: 'inline-block' }} onClick={saveChanges}>
502
- Save
503
- </Button>
504
- </div>
505
- </Modal.Content>
506
- </Modal>
507
- )
508
- }
509
-
510
- export default FilterModal
@@ -1,95 +0,0 @@
1
- import React from 'react'
2
- import type { Visualization } from '@cdc/core/types/Visualization'
3
- import Widget from './Widget'
4
- import AdvancedEditor from '@cdc/core/components/AdvancedEditor'
5
- import { Table } from '@cdc/core/types/Table'
6
-
7
- const addVisualization = (type, subType) => {
8
- const modalWillOpen = type !== 'markup-include'
9
- const newVisualizationConfig: Partial<Visualization> = {
10
- filters: [],
11
- filterBehavior: 'Filter Change',
12
- newViz: type !== 'table',
13
- openModal: modalWillOpen,
14
- uid: type + Date.now(),
15
- type
16
- }
17
-
18
- switch (type) {
19
- case 'chart':
20
- newVisualizationConfig.visualizationType = subType
21
- break
22
- case 'map':
23
- newVisualizationConfig.general = {}
24
- newVisualizationConfig.general.geoType = subType
25
- break
26
- case 'data-bite' || 'waffle-chart' || 'filtered-text':
27
- newVisualizationConfig.visualizationType = type
28
- break
29
- case 'table':
30
- const tableConfig: Table = { label: 'Data Table', show: true, showDownloadUrl: false, showVertical: true, expanded: true, collapsible: true }
31
- newVisualizationConfig.table = tableConfig
32
- newVisualizationConfig.columns = {}
33
- newVisualizationConfig.dataFormat = {}
34
- newVisualizationConfig.visualizationType = type
35
- break
36
- case 'markup-include':
37
- newVisualizationConfig.contentEditor = {
38
- inlineHTML: '<h2>Inline HTML</h2>',
39
- markupVariables: [],
40
- showHeader: true,
41
- srcUrl: '#example',
42
- title: 'Markup Include',
43
- useInlineHTML: true
44
- }
45
- newVisualizationConfig.theme = 'theme-blue'
46
- newVisualizationConfig.visual = {
47
- border: false,
48
- accent: false,
49
- background: false,
50
- hideBackgroundColor: false,
51
- borderColorTheme: false
52
- }
53
- newVisualizationConfig.showEditorPanel = true
54
- newVisualizationConfig.visualizationType = type
55
-
56
- break
57
- default:
58
- newVisualizationConfig.visualizationType = type
59
- break
60
- }
61
-
62
- return newVisualizationConfig
63
- }
64
-
65
- const VisualizationsPanel = ({ loadConfig, config }) => (
66
- <div className='visualizations-panel'>
67
- <p style={{ fontSize: '14px' }}>Click and drag an item onto the grid to add it to your dashboard.</p>
68
- <span className='subheading-3'>Chart</span>
69
- <div className='drag-grid'>
70
- <Widget addVisualization={() => addVisualization('chart', 'Bar')} type='Bar' />
71
- <Widget addVisualization={() => addVisualization('chart', 'Line')} type='Line' />
72
- <Widget addVisualization={() => addVisualization('chart', 'Pie')} type='Pie' />
73
- <Widget addVisualization={() => addVisualization('chart', 'Sankey')} type='Sankey' />
74
- </div>
75
- <span className='subheading-3'>Map</span>
76
- <div className='drag-grid'>
77
- <Widget addVisualization={() => addVisualization('map', 'us')} type='us' />
78
- <Widget addVisualization={() => addVisualization('map', 'world')} type='world' />
79
- <Widget addVisualization={() => addVisualization('map', 'single-state')} type='single-state' />
80
- </div>
81
- <span className='subheading-3'>Misc.</span>
82
- <div className='drag-grid'>
83
- <Widget addVisualization={() => addVisualization('data-bite', '')} type='data-bite' />
84
- <Widget addVisualization={() => addVisualization('waffle-chart', '')} type='waffle-chart' />
85
- <Widget addVisualization={() => addVisualization('markup-include', '')} type='markup-include' />
86
- <Widget addVisualization={() => addVisualization('filtered-text', '')} type='filtered-text' />
87
- <Widget addVisualization={() => addVisualization('filter-dropdowns', '')} type='filter-dropdowns' />
88
- <Widget addVisualization={() => addVisualization('table', '')} type='table' />
89
- </div>
90
- <span className='subheading-3'>Advanced</span>
91
- <AdvancedEditor loadConfig={loadConfig} state={config} convertStateToConfig={() => undefined} />
92
- </div>
93
- )
94
-
95
- export default VisualizationsPanel
@@ -1,5 +0,0 @@
1
- import { APIFilter } from '../types/APIFilter'
2
-
3
- export const getApiFilterKey = ({ apiEndpoint, heirarchyLookup }: APIFilter) => {
4
- return apiEndpoint + (heirarchyLookup || '')
5
- }