@cdc/dashboard 4.22.10 → 4.22.11

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.
@@ -25,7 +25,7 @@ import CdcChart from '@cdc/chart'
25
25
  import CdcDataBite from '@cdc/data-bite'
26
26
  import CdcWaffleChart from '@cdc/waffle-chart'
27
27
  import CdcMarkupInclude from '@cdc/markup-include'
28
- import CdcFilteredText from '@cdc/filtered-text';
28
+ import CdcFilteredText from '@cdc/filtered-text'
29
29
 
30
30
  import Grid from './components/Grid'
31
31
  import Header from './components/Header'
@@ -37,13 +37,13 @@ import './scss/main.scss'
37
37
  import '@cdc/core/styles/v2/main.scss'
38
38
 
39
39
  const addVisualization = (type, subType) => {
40
- let modalWillOpen = type === "markup-include" ? false : true;
40
+ let modalWillOpen = type === 'markup-include' ? false : true
41
41
  let newVisualizationConfig = {
42
42
  newViz: true,
43
43
  openModal: modalWillOpen,
44
44
  uid: type + Date.now(),
45
- type,
46
- };
45
+ type
46
+ }
47
47
 
48
48
  switch (type) {
49
49
  case 'chart':
@@ -74,44 +74,44 @@ const addVisualization = (type, subType) => {
74
74
  }
75
75
 
76
76
  const VisualizationsPanel = () => (
77
- <div className="visualizations-panel">
77
+ <div className='visualizations-panel'>
78
78
  <p style={{ fontSize: '14px' }}>Click and drag an item onto the grid to add it to your dashboard.</p>
79
- <span className="subheading-3">Chart</span>
80
- <div className="drag-grid">
81
- <Widget addVisualization={() => addVisualization('chart', 'Bar')} type="Bar"/>
82
- <Widget addVisualization={() => addVisualization('chart', 'Line')} type="Line"/>
83
- <Widget addVisualization={() => addVisualization('chart', 'Pie')} type="Pie"/>
79
+ <span className='subheading-3'>Chart</span>
80
+ <div className='drag-grid'>
81
+ <Widget addVisualization={() => addVisualization('chart', 'Bar')} type='Bar' />
82
+ <Widget addVisualization={() => addVisualization('chart', 'Line')} type='Line' />
83
+ <Widget addVisualization={() => addVisualization('chart', 'Pie')} type='Pie' />
84
84
  </div>
85
- <span className="subheading-3">Map</span>
86
- <div className="drag-grid">
87
- <Widget addVisualization={() => addVisualization('map', 'us')} type="us"/>
88
- <Widget addVisualization={() => addVisualization('map', 'world')} type="world"/>
89
- <Widget addVisualization={() => addVisualization('map', 'single-state')} type="single-state"/>
85
+ <span className='subheading-3'>Map</span>
86
+ <div className='drag-grid'>
87
+ <Widget addVisualization={() => addVisualization('map', 'us')} type='us' />
88
+ <Widget addVisualization={() => addVisualization('map', 'world')} type='world' />
89
+ <Widget addVisualization={() => addVisualization('map', 'single-state')} type='single-state' />
90
90
  </div>
91
- <span className="subheading-3">Misc.</span>
92
- <div className="drag-grid">
93
- <Widget addVisualization={() => addVisualization('data-bite', '')} type="data-bite"/>
94
- <Widget addVisualization={() => addVisualization('waffle-chart', '')} type="waffle-chart"/>
95
- <Widget addVisualization={() => addVisualization('markup-include', '')} type="markup-include"/>
96
- <Widget addVisualization={() => addVisualization('filtered-text', '')} type="filtered-text"/>
91
+ <span className='subheading-3'>Misc.</span>
92
+ <div className='drag-grid'>
93
+ <Widget addVisualization={() => addVisualization('data-bite', '')} type='data-bite' />
94
+ <Widget addVisualization={() => addVisualization('waffle-chart', '')} type='waffle-chart' />
95
+ <Widget addVisualization={() => addVisualization('markup-include', '')} type='markup-include' />
96
+ <Widget addVisualization={() => addVisualization('filtered-text', '')} type='filtered-text' />
97
97
  </div>
98
98
  </div>
99
99
  )
100
100
 
101
101
  export default function CdcDashboard({ configUrl = '', config: configObj = undefined, isEditor = false, setConfig: setParentConfig }) {
102
- const [ config, setConfig ] = useState(configObj ?? {})
103
- const [ data, setData ] = useState([])
104
- const [ filteredData, setFilteredData ] = useState()
105
- const [ loading, setLoading ] = useState(true)
106
- const [ preview, setPreview ] = useState(false)
107
- const [ tabSelected, setTabSelected ] = useState(0);
108
- const [ currentViewport, setCurrentViewport ] = useState('lg')
102
+ const [config, setConfig] = useState(configObj ?? {})
103
+ const [data, setData] = useState([])
104
+ const [filteredData, setFilteredData] = useState()
105
+ const [loading, setLoading] = useState(true)
106
+ const [preview, setPreview] = useState(false)
107
+ const [tabSelected, setTabSelected] = useState(0)
108
+ const [currentViewport, setCurrentViewport] = useState('lg')
109
109
 
110
110
  const { title, description } = config.dashboard || config
111
111
 
112
112
  const transform = new DataTransform()
113
113
 
114
- const processData = async (config) => {
114
+ const processData = async config => {
115
115
  let dataset = config.formattedData || config.data
116
116
 
117
117
  if (config.dataUrl) {
@@ -131,44 +131,46 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
131
131
  }
132
132
 
133
133
  const loadConfig = async () => {
134
- let response = configObj || await (await fetch(configUrl)).json()
134
+ let response = configObj || (await (await fetch(configUrl)).json())
135
135
  let newConfig = { ...defaults, ...response }
136
136
  let datasets = {}
137
137
 
138
138
  if (response.datasets) {
139
- await Promise.all(Object.keys(response.datasets).map(async (key) => {
140
- datasets[key] = await processData(response.datasets[key])
141
- }))
139
+ await Promise.all(
140
+ Object.keys(response.datasets).map(async key => {
141
+ datasets[key] = await processData(response.datasets[key])
142
+ })
143
+ )
142
144
  } else {
143
145
  let dataKey = newConfig.dataFileName || 'backwards-compatibility'
144
146
  datasets[dataKey] = await processData(response)
145
147
 
146
- let datasetsFull = {};
148
+ let datasetsFull = {}
147
149
  datasetsFull[dataKey] = {
148
150
  data: datasets[dataKey],
149
151
  dataDescription: newConfig.dataDescription
150
152
  }
151
- newConfig.datasets = datasetsFull;
152
-
153
+ newConfig.datasets = datasetsFull
154
+
153
155
  Object.keys(newConfig.visualizations).forEach(vizKey => {
154
156
  newConfig.visualizations[vizKey].dataKey = dataKey
155
157
  newConfig.visualizations[vizKey].dataDescription = newConfig.dataDescription
156
158
  newConfig.visualizations[vizKey].formattedData = newConfig.formattedData
157
159
  })
158
-
160
+
159
161
  delete newConfig.data
160
162
  delete newConfig.dataUrl
161
163
  delete newConfig.dataFileName
162
164
  delete newConfig.dataFileSourceType
163
165
  delete newConfig.dataDescription
164
166
  delete newConfig.formattedData
165
-
167
+
166
168
  if (newConfig.dashboard && newConfig.dashboard.filters) {
167
169
  newConfig.dashboard.sharedFilters = newConfig.dashboard.sharedFilters || []
168
170
  newConfig.dashboard.filters.forEach(filter => {
169
171
  newConfig.dashboard.sharedFilters.push({ ...filter, key: filter.label, showDropdown: true, usedBy: Object.keys(newConfig.visualizations) })
170
172
  })
171
-
173
+
172
174
  delete newConfig.dashboard.filters
173
175
  }
174
176
  }
@@ -182,11 +184,11 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
182
184
  const filterData = (filters, data) => {
183
185
  let filteredData = []
184
186
 
185
- if(data){
186
- data.forEach((row) => {
187
+ if (data) {
188
+ data.forEach(row => {
187
189
  let add = true
188
190
 
189
- filters.forEach((filter) => {
191
+ filters.forEach(filter => {
190
192
  if (row[filter.columnName] !== filter.active) {
191
193
  add = false
192
194
  }
@@ -211,11 +213,11 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
211
213
  }
212
214
 
213
215
  Object.keys(newConfig.visualizations).forEach(visualizationKey => {
214
- let applicableFilters = newConfig.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.usedBy && sharedFilter.usedBy.indexOf(visualizationKey) !== -1);
215
-
216
+ let applicableFilters = newConfig.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.usedBy && sharedFilter.usedBy.indexOf(visualizationKey) !== -1)
217
+
216
218
  if (applicableFilters.length > 0) {
217
219
  const visualization = newConfig.visualizations[visualizationKey]
218
-
220
+
219
221
  newFilteredData[visualizationKey] = filterData(applicableFilters, visualization.formattedData || data[visualization.dataKey])
220
222
  }
221
223
  })
@@ -229,7 +231,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
229
231
  const values = []
230
232
 
231
233
  Object.keys(data).forEach(key => {
232
- data[key].forEach((row) => {
234
+ data[key].forEach(row => {
233
235
  const value = row[columnName]
234
236
  if (value && false === values.includes(value)) {
235
237
  values.push(value)
@@ -248,7 +250,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
248
250
  newConfig.dashboard.sharedFilters.forEach((filter, i) => {
249
251
  for (let j = 0; j < visualizationKeys.length; j++) {
250
252
  if (visualizationKeys[j] === filter.setBy) {
251
- const filterValues = generateValuesForFilter(filter.columnName, (dataOverride || data))
253
+ const filterValues = generateValuesForFilter(filter.columnName, dataOverride || data)
252
254
 
253
255
  if (newConfig.dashboard.sharedFilters[i].order === 'asc') {
254
256
  filterValues.sort()
@@ -258,23 +260,23 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
258
260
  }
259
261
 
260
262
  newConfig.dashboard.sharedFilters[i].values = filterValues
261
- if(filterValues.length > 0){
262
- newConfig.dashboard.sharedFilters[i].active = newConfig.dashboard.sharedFilters[i].active || newConfig.dashboard.sharedFilters[i].values[0];
263
+ if (filterValues.length > 0) {
264
+ newConfig.dashboard.sharedFilters[i].active = newConfig.dashboard.sharedFilters[i].active || newConfig.dashboard.sharedFilters[i].values[0]
263
265
  }
264
266
  break
265
267
  }
266
268
  }
267
269
 
268
270
  if ((!newConfig.dashboard.sharedFilters[i].values || newConfig.dashboard.sharedFilters[i].values.length === 0) && newConfig.dashboard.sharedFilters[i].showDropdown) {
269
- newConfig.dashboard.sharedFilters[i].values = generateValuesForFilter(filter.columnName, (dataOverride || data))
270
- if(newConfig.dashboard.sharedFilters[i].values.length > 0){
271
- newConfig.dashboard.sharedFilters[i].active = newConfig.dashboard.sharedFilters[i].active || newConfig.dashboard.sharedFilters[i].values[0];
271
+ newConfig.dashboard.sharedFilters[i].values = generateValuesForFilter(filter.columnName, dataOverride || data)
272
+ if (newConfig.dashboard.sharedFilters[i].values.length > 0) {
273
+ newConfig.dashboard.sharedFilters[i].active = newConfig.dashboard.sharedFilters[i].active || newConfig.dashboard.sharedFilters[i].values[0]
272
274
  }
273
275
  }
274
276
  })
275
277
 
276
278
  visualizationKeys.forEach(visualizationKey => {
277
- let applicableFilters = newConfig.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.usedBy && sharedFilter.usedBy.indexOf(visualizationKey) !== -1);
279
+ let applicableFilters = newConfig.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.usedBy && sharedFilter.usedBy.indexOf(visualizationKey) !== -1)
278
280
 
279
281
  if (applicableFilters.length > 0) {
280
282
  newFilteredData[visualizationKey] = filterData(applicableFilters, newConfig.visualizations[visualizationKey].formattedData || newConfig.visualizations[visualizationKey].data || (dataOverride || data)[newConfig.visualizations[visualizationKey].dataKey])
@@ -299,7 +301,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
299
301
  if (setParentConfig && isEditor) {
300
302
  setParentConfig(config)
301
303
  }
302
- }, [ config ])
304
+ }, [config])
303
305
 
304
306
  const updateChildConfig = (visualizationKey, newConfig) => {
305
307
  let updatedConfig = { ...config }
@@ -321,7 +323,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
321
323
  let newFilteredData = {}
322
324
  Object.keys(config.visualizations).forEach(key => {
323
325
  let applicableFilters = dashboardConfig.sharedFilters.filter(sharedFilter => sharedFilter.usedBy && sharedFilter.usedBy.indexOf(key) !== -1)
324
- if(applicableFilters.length > 0){
326
+ if (applicableFilters.length > 0) {
325
327
  newFilteredData[key] = filterData(applicableFilters, config.visualizations[key].formattedData || data[config.visualizations[key].dataKey])
326
328
  }
327
329
  })
@@ -329,7 +331,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
329
331
  setFilteredData(newFilteredData)
330
332
  }
331
333
 
332
- const announceChange = (text) => {}
334
+ const announceChange = text => {}
333
335
 
334
336
  return config.dashboard.sharedFilters.map((singleFilter, index) => {
335
337
  if (!singleFilter.showDropdown) return
@@ -337,22 +339,22 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
337
339
  const values = []
338
340
 
339
341
  singleFilter.values.forEach((filterOption, index) => {
340
- values.push(<option
341
- key={`${singleFilter.key}-option-${index}`}
342
- value={filterOption}
343
- >{filterOption}
344
- </option>)
342
+ values.push(
343
+ <option key={`${singleFilter.key}-option-${index}`} value={filterOption}>
344
+ {filterOption}
345
+ </option>
346
+ )
345
347
  })
346
348
 
347
349
  return (
348
- <section className="dashboard-filters-section" key={`${singleFilter.key}-filtersection-${index}`}>
350
+ <section className='dashboard-filters-section' key={`${singleFilter.key}-filtersection-${index}`}>
349
351
  <label htmlFor={`filter-${index}`}>{singleFilter.key}</label>
350
352
  <select
351
353
  id={`filter-${index}`}
352
- className="filter-select"
353
- data-index="0"
354
+ className='filter-select'
355
+ data-index='0'
354
356
  value={singleFilter.active}
355
- onChange={(val) => {
357
+ onChange={val => {
356
358
  changeFilterActive(index, val.target.value)
357
359
  announceChange(`Filter ${singleFilter.key} value has been changed to ${val.target.value}, please reference the data table to see updated values.`)
358
360
  }}
@@ -379,7 +381,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
379
381
  }, [])
380
382
 
381
383
  // Prevent render if loading
382
- if (loading) return <Loading/>
384
+ if (loading) return <Loading />
383
385
 
384
386
  let body = null
385
387
 
@@ -394,7 +396,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
394
396
 
395
397
  visualizationConfig.data = filteredData && filteredData[visualizationKey] ? filteredData[visualizationKey] : data[dataKey]
396
398
  if (visualizationConfig.formattedData) {
397
- visualizationConfig.originalFormattedData = visualizationConfig.formattedData;
399
+ visualizationConfig.originalFormattedData = visualizationConfig.formattedData
398
400
  visualizationConfig.formattedData = visualizationConfig.data
399
401
  }
400
402
 
@@ -412,82 +414,61 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
412
414
  setConfig(newConfig)
413
415
  }
414
416
 
415
- const updateConfig = (newConfig) => {
416
- let dataCorrectedConfig = visualizationConfig.originalFormattedData ? {...newConfig, formattedData: visualizationConfig.originalFormattedData} : newConfig;
417
+ const updateConfig = newConfig => {
418
+ let dataCorrectedConfig = visualizationConfig.originalFormattedData ? { ...newConfig, formattedData: visualizationConfig.originalFormattedData } : newConfig
417
419
  updateChildConfig(visualizationKey, dataCorrectedConfig)
418
420
  }
419
421
 
420
422
  switch (visualizationConfig.type) {
421
423
  case 'chart':
422
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Chart"/>
423
- <CdcChart
424
- key={visualizationKey}
425
- config={visualizationConfig}
426
- isEditor={true}
427
- setConfig={updateConfig}
428
- setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
429
- isDashboard={true}
430
- />
431
- </>
424
+ body = (
425
+ <>
426
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Chart' />
427
+ <CdcChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} setSharedFilter={setsSharedFilter ? setSharedFilter : undefined} isDashboard={true} />
428
+ </>
429
+ )
432
430
  break
433
431
  case 'map':
434
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Map"/>
435
- <CdcMap
436
- key={visualizationKey}
437
- config={visualizationConfig}
438
- isEditor={true}
439
- setConfig={updateConfig}
440
- setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
441
- setSharedFilterValue={setSharedFilterValue}
442
- isDashboard={true}
443
- />
444
- </>
432
+ body = (
433
+ <>
434
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Map' />
435
+ <CdcMap key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} setSharedFilter={setsSharedFilter ? setSharedFilter : undefined} setSharedFilterValue={setSharedFilterValue} isDashboard={true} />
436
+ </>
437
+ )
445
438
  break
446
439
  case 'data-bite':
447
440
  visualizationConfig = { ...visualizationConfig, newViz: true }
448
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Data Bite"/>
449
- <CdcDataBite
450
- key={visualizationKey}
451
- config={visualizationConfig}
452
- isEditor={true}
453
- setConfig={updateConfig}
454
- isDashboard={true}
455
- />
456
- </>
441
+ body = (
442
+ <>
443
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Data Bite' />
444
+ <CdcDataBite key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
445
+ </>
446
+ )
457
447
  break
458
448
  case 'waffle-chart':
459
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Waffle Chart"/>
460
- <CdcWaffleChart
461
- key={visualizationKey}
462
- config={visualizationConfig}
463
- isEditor={true}
464
- setConfig={updateConfig}
465
- isDashboard={true}
466
- />
467
- </>
449
+ body = (
450
+ <>
451
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Waffle Chart' />
452
+ <CdcWaffleChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
453
+ </>
454
+ )
468
455
  break
469
456
  case 'markup-include':
470
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Markup Include"/>
471
- <CdcMarkupInclude
472
- key={visualizationKey}
473
- config={visualizationConfig}
474
- isEditor={true}
475
- setConfig={updateConfig}
476
- isDashboard={true}
477
- />
478
- </>
457
+ body = (
458
+ <>
459
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Markup Include' />
460
+ <CdcMarkupInclude key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
461
+ </>
462
+ )
479
463
  break
480
- case 'filtered-text':
481
- body = <><Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor="Filtered Text"/>
482
- <CdcFilteredText
483
- key={visualizationKey}
484
- config={visualizationConfig}
485
- isEditor={true}
486
- setConfig={updateConfig}
487
- isDashboard={true}
488
- />
464
+ case 'filtered-text':
465
+ body = (
466
+ <>
467
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} back={back} subEditor='Filtered Text' />
468
+ <CdcFilteredText key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
489
469
  </>
490
- break
470
+ )
471
+ break
491
472
  default:
492
473
  body = <></>
493
474
  break
@@ -498,10 +479,10 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
498
479
  if (!subVisualizationEditing) {
499
480
  body = (
500
481
  <DndProvider backend={HTML5Backend}>
501
- <Header tabSelected={tabSelected} setTabSelected={setTabSelected} preview={preview} setPreview={setPreview}/>
502
- <div className="layout-container">
503
- <VisualizationsPanel/>
504
- <Grid/>
482
+ <Header tabSelected={tabSelected} setTabSelected={setTabSelected} preview={preview} setPreview={setPreview} />
483
+ <div className='layout-container'>
484
+ <VisualizationsPanel />
485
+ <Grid />
505
486
  </div>
506
487
  </DndProvider>
507
488
  )
@@ -509,164 +490,177 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
509
490
  } else {
510
491
  body = (
511
492
  <>
512
-
513
- {isEditor && <Header tabSelected={tabSelected} setTabSelected={setTabSelected} preview={preview} setPreview={setPreview}/>}
493
+ {isEditor && <Header tabSelected={tabSelected} setTabSelected={setTabSelected} preview={preview} setPreview={setPreview} />}
514
494
  <div className={`cdc-dashboard-inner-container${isEditor ? ' is-editor' : ''}`}>
515
495
  {/* Title */}
516
- {title &&
517
- <div role="heading" aria-level="3" className={`dashboard-title ${config.dashboard.theme ?? 'theme-blue'}`}>{title}</div>}
496
+ {title && (
497
+ <div role='heading' aria-level='3' className={`dashboard-title ${config.dashboard.theme ?? 'theme-blue'}`}>
498
+ {title}
499
+ </div>
500
+ )}
518
501
  {/* Description */}
519
- {description && <div className="subtext">{parse(description)}</div>}
502
+ {description && <div className='subtext'>{parse(description)}</div>}
520
503
  {/* Filters */}
521
- {config.dashboard.sharedFilters && <div className="cove-dashboard-filters"> <Filters/></div>}
504
+ {config.dashboard.sharedFilters && (
505
+ <div className='cove-dashboard-filters'>
506
+ {' '}
507
+ <Filters />
508
+ </div>
509
+ )}
522
510
 
523
511
  {/* Visualizations */}
524
- {config.rows && config.rows.filter(row => row.filter(col => col.widget).length !== 0).map((row, index) => {
525
-
526
- return (
527
-
528
- <div className={`dashboard-row ${row.equalHeight ? 'equal-height' : ''}`} key={`row__${index}`}>
529
- {row.map((col, colIndex) => {
530
- if (col.width) {
531
- if (!col.widget) return <div key={`row__${index}__col__${colIndex}`} className={`dashboard-col dashboard-col-${col.width}`}></div>
512
+ {config.rows &&
513
+ config.rows
514
+ .filter(row => row.filter(col => col.widget).length !== 0)
515
+ .map((row, index) => {
516
+ return (
517
+ <div className={`dashboard-row ${row.equalHeight ? 'equal-height' : ''}`} key={`row__${index}`}>
518
+ {row.map((col, colIndex) => {
519
+ if (col.width) {
520
+ if (!col.widget) return <div key={`row__${index}__col__${colIndex}`} className={`dashboard-col dashboard-col-${col.width}`}></div>
521
+
522
+ let visualizationConfig = { ...config.visualizations[col.widget] }
523
+
524
+ const dataKey = visualizationConfig.dataKey || 'backwards-compatibility'
525
+
526
+ visualizationConfig.data = filteredData && filteredData[col.widget] ? filteredData[col.widget] : data[dataKey]
527
+ if (visualizationConfig.formattedData) {
528
+ visualizationConfig.formattedData = visualizationConfig.data
529
+ }
530
+
531
+ const setsSharedFilter = config.dashboard.sharedFilters && config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget).length > 0
532
+ const setSharedFilterValue = setsSharedFilter ? config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget)[0].active : undefined
533
+ const tableLink = <a href={`#data-table-${visualizationConfig.dataKey}`}>{visualizationConfig.dataKey} (Go to Table)</a>
534
+
535
+ return (
536
+ <React.Fragment key={`vis__${index}__${colIndex}`}>
537
+ <div className={`dashboard-col dashboard-col-${col.width}`}>
538
+ {visualizationConfig.type === 'chart' && (
539
+ <CdcChart
540
+ key={col.widget}
541
+ config={visualizationConfig}
542
+ isEditor={false}
543
+ setConfig={newConfig => {
544
+ updateChildConfig(col.widget, newConfig)
545
+ }}
546
+ setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
547
+ isDashboard={true}
548
+ link={config.table && config.table.show && config.datasets ? tableLink : undefined}
549
+ />
550
+ )}
551
+ {visualizationConfig.type === 'map' && (
552
+ <CdcMap
553
+ key={col.widget}
554
+ config={visualizationConfig}
555
+ isEditor={false}
556
+ setConfig={newConfig => {
557
+ updateChildConfig(col.widget, newConfig)
558
+ }}
559
+ setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
560
+ setSharedFilterValue={setSharedFilterValue}
561
+ isDashboard={true}
562
+ link={config.table && config.table.show && config.datasets ? tableLink : undefined}
563
+ />
564
+ )}
565
+ {visualizationConfig.type === 'data-bite' && (
566
+ <CdcDataBite
567
+ key={col.widget}
568
+ config={visualizationConfig}
569
+ isEditor={false}
570
+ setConfig={newConfig => {
571
+ updateChildConfig(col.widget, newConfig)
572
+ }}
573
+ isDashboard={true}
574
+ />
575
+ )}
576
+ {visualizationConfig.type === 'waffle-chart' && (
577
+ <CdcWaffleChart
578
+ key={col.widget}
579
+ config={visualizationConfig}
580
+ isEditor={false}
581
+ setConfig={newConfig => {
582
+ updateChildConfig(col.widget, newConfig)
583
+ }}
584
+ isDashboard={true}
585
+ link={config.table && config.table.show && config.datasets ? tableLink : undefined}
586
+ />
587
+ )}
588
+ {visualizationConfig.type === 'markup-include' && (
589
+ <CdcMarkupInclude
590
+ key={col.widget}
591
+ config={visualizationConfig}
592
+ isEditor={false}
593
+ setConfig={newConfig => {
594
+ updateChildConfig(col.widget, newConfig)
595
+ }}
596
+ isDashboard={true}
597
+ />
598
+ )}
599
+ {visualizationConfig.type === 'filtered-text' && (
600
+ <CdcFilteredText
601
+ key={col.widget}
602
+ config={visualizationConfig}
603
+ isEditor={false}
604
+ setConfig={newConfig => {
605
+ updateChildConfig(col.widget, newConfig)
606
+ }}
607
+ isDashboard={true}
608
+ />
609
+ )}
610
+ </div>
611
+ </React.Fragment>
612
+ )
613
+ }
614
+ return <React.Fragment key={`vis__${index}__${colIndex}`}></React.Fragment>
615
+ })}
616
+ </div>
617
+ )
618
+ })}
532
619
 
533
- let visualizationConfig = { ...config.visualizations[col.widget] }
534
-
535
- const dataKey = visualizationConfig.dataKey || 'backwards-compatibility'
536
-
537
- visualizationConfig.data = filteredData && filteredData[col.widget] ? filteredData[col.widget] : data[dataKey]
538
- if (visualizationConfig.formattedData) {
539
- visualizationConfig.formattedData = visualizationConfig.data
620
+ {/* Data Table */}
621
+ {config.table && config.table.show && config.data && <DataTable data={config.data} config={config} />}
622
+ {config.table &&
623
+ config.table.show &&
624
+ config.datasets &&
625
+ Object.keys(config.datasets).map(datasetKey => {
626
+ //For each dataset, find any shared filters that apply to all visualizations using the dataset
627
+ //Apply these filters to the table
628
+ let filteredTableData
629
+ if (config.dashboard.sharedFilters && config.dashboard.sharedFilters.length > 0) {
630
+ //Gets list of visuailzations using the dataset
631
+ let vizKeysUsingDataset = []
632
+ Object.keys(config.visualizations).forEach(visualizationKey => {
633
+ if (config.visualizations[visualizationKey].dataKey === datasetKey) {
634
+ vizKeysUsingDataset.push(visualizationKey)
635
+ }
636
+ })
637
+
638
+ //Checks shared filters against list to see if all visualizations are represented
639
+ let applicableFilters = []
640
+ config.dashboard.sharedFilters.forEach(sharedFilter => {
641
+ let allMatch = true
642
+ vizKeysUsingDataset.forEach(visualizationKey => {
643
+ if (sharedFilter.usedBy.indexOf(visualizationKey) === -1) {
644
+ allMatch = false
540
645
  }
541
-
542
- const setsSharedFilter = config.dashboard.sharedFilters && config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget).length > 0
543
- const setSharedFilterValue = setsSharedFilter ? config.dashboard.sharedFilters.filter(sharedFilter => sharedFilter.setBy === col.widget)[0].active : undefined
544
- const tableLink = <a href={`#data-table-${visualizationConfig.dataKey}`}>{visualizationConfig.dataKey} (Go to Table)</a>;
545
-
546
- return (
547
- <React.Fragment key={`vis__${index}__${colIndex}`}>
548
- <div className={`dashboard-col dashboard-col-${col.width}`}>
549
- {visualizationConfig.type === 'chart' && (
550
- <CdcChart
551
- key={col.widget}
552
- config={visualizationConfig}
553
- isEditor={false}
554
- setConfig={(newConfig) => {
555
- updateChildConfig(col.widget, newConfig)
556
- }}
557
- setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
558
- isDashboard={true}
559
- link = { config.table && config.table.show && config.datasets ? tableLink : undefined }
560
- />
561
- )}
562
- {visualizationConfig.type === 'map' && (
563
- <CdcMap
564
- key={col.widget}
565
- config={visualizationConfig}
566
- isEditor={false}
567
- setConfig={(newConfig) => {
568
- updateChildConfig(col.widget, newConfig)
569
- }}
570
- setSharedFilter={setsSharedFilter ? setSharedFilter : undefined}
571
- setSharedFilterValue={setSharedFilterValue}
572
- isDashboard={true}
573
- link = { config.table && config.table.show && config.datasets ? tableLink : undefined }
574
- />
575
- )}
576
- {visualizationConfig.type === 'data-bite' && (
577
- <CdcDataBite
578
- key={col.widget}
579
- config={visualizationConfig}
580
- isEditor={false}
581
- setConfig={(newConfig) => {
582
- updateChildConfig(col.widget, newConfig)
583
- }}
584
- isDashboard={true}
585
- />
586
- )}
587
- {visualizationConfig.type === 'waffle-chart' && (
588
- <CdcWaffleChart
589
- key={col.widget}
590
- config={visualizationConfig}
591
- isEditor={false}
592
- setConfig={(newConfig) => {
593
- updateChildConfig(col.widget, newConfig)
594
- }}
595
- isDashboard={true}
596
- link = { config.table && config.table.show && config.datasets ? tableLink : undefined }
597
- />
598
- )}
599
- {visualizationConfig.type === 'markup-include' && (
600
- <CdcMarkupInclude
601
- key={col.widget}
602
- config={visualizationConfig}
603
- isEditor={false}
604
- setConfig={(newConfig) => {
605
- updateChildConfig(col.widget, newConfig)
606
- }}
607
- isDashboard={true}
608
- />
609
- )}
610
- {visualizationConfig.type === 'filtered-text' && (
611
- <CdcFilteredText
612
- key={col.widget}
613
- config={visualizationConfig}
614
- isEditor={false}
615
- setConfig={(newConfig) => {
616
- updateChildConfig(col.widget, newConfig)
617
- }}
618
- isDashboard={true}
619
- />
620
- )}
621
- </div>
622
- </React.Fragment>
623
- )
646
+ })
647
+ if (allMatch) {
648
+ applicableFilters.push(sharedFilter)
624
649
  }
625
- return <React.Fragment key={`vis__${index}__${colIndex}`}></React.Fragment>
626
- })}
627
- </div>)
628
- })}
650
+ })
629
651
 
630
- {/* Data Table */}
631
- {config.table && config.table.show && config.data && <DataTable data={config.data} config={config}/>}
632
- {config.table && config.table.show && config.datasets && Object.keys(config.datasets).map(datasetKey => {
633
-
634
- //For each dataset, find any shared filters that apply to all visualizations using the dataset
635
- //Apply these filters to the table
636
- let filteredTableData;
637
- if(config.dashboard.sharedFilters && config.dashboard.sharedFilters.length > 0){
638
- //Gets list of visuailzations using the dataset
639
- let vizKeysUsingDataset = [];
640
- Object.keys(config.visualizations).forEach(visualizationKey => {
641
- if(config.visualizations[visualizationKey].dataKey === datasetKey){
642
- vizKeysUsingDataset.push(visualizationKey);
652
+ //Applys any applicable filters
653
+ if (applicableFilters.length > 0) {
654
+ filteredTableData = filterData(applicableFilters, config.datasets[datasetKey].data)
643
655
  }
644
- });
645
-
646
- //Checks shared filters against list to see if all visualizations are represented
647
- let applicableFilters = [];
648
- config.dashboard.sharedFilters.forEach(sharedFilter => {
649
- let allMatch = true;
650
- vizKeysUsingDataset.forEach(visualizationKey => {
651
- if(sharedFilter.usedBy.indexOf(visualizationKey) === -1){
652
- allMatch = false;
653
- }
654
- });
655
- if(allMatch){
656
- applicableFilters.push(sharedFilter);
657
- }
658
- });
659
-
660
- //Applys any applicable filters
661
- if(applicableFilters.length > 0){
662
- filteredTableData = filterData(applicableFilters, config.datasets[datasetKey].data)
663
656
  }
664
- }
665
657
 
666
- return (<div className="multi-table-container" id={`data-table-${datasetKey}`} key={`data-table-${datasetKey}`}>
667
- <DataTable data={filteredTableData || config.datasets[datasetKey].data} datasetKey={datasetKey} config={config}></DataTable>
668
- </div>)
669
- })}
658
+ return (
659
+ <div className='multi-table-container' id={`data-table-${datasetKey}`} key={`data-table-${datasetKey}`}>
660
+ <DataTable data={filteredTableData || config.datasets[datasetKey].data} datasetKey={datasetKey} config={config}></DataTable>
661
+ </div>
662
+ )
663
+ })}
670
664
  </div>
671
665
  </>
672
666
  )
@@ -690,7 +684,7 @@ export default function CdcDashboard({ configUrl = '', config: configObj = undef
690
684
  <div className={`cdc-open-viz-module type-dashboard ${currentViewport}`} ref={outerContainerRef}>
691
685
  {body}
692
686
  </div>
693
- <OverlayFrame/>
687
+ <OverlayFrame />
694
688
  </ConfigContext.Provider>
695
689
  </GlobalContextProvider>
696
690
  )