@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.
@@ -19,7 +19,7 @@ import CdcChart from '@cdc/chart'
19
19
  import CdcDataBite from '@cdc/data-bite'
20
20
  import CdcWaffleChart from '@cdc/waffle-chart'
21
21
  import CdcMarkupInclude from '@cdc/markup-include'
22
- import FilteredText from '@cdc/filtered-text';
22
+ import FilteredText from '@cdc/filtered-text'
23
23
 
24
24
  import EditorPanel from './components/EditorPanel'
25
25
  import Grid from './components/Grid'
@@ -61,7 +61,7 @@ const addVisualization = (type, subType) => {
61
61
  newVisualizationConfig.visualizationType = type
62
62
  break
63
63
  case 'filtered-text':
64
- newVisualizationConfig.visualizationType = type
64
+ newVisualizationConfig.visualizationType = type
65
65
  break
66
66
  }
67
67
 
@@ -69,63 +69,60 @@ const addVisualization = (type, subType) => {
69
69
  }
70
70
 
71
71
  const VisualizationsPanel = () => (
72
- <div className="visualizations-panel">
72
+ <div className='visualizations-panel'>
73
73
  <p style={{ fontSize: '14px' }}>Click and drag an item onto the grid to add it to your dashboard.</p>
74
- <span className="subheading-3">Chart</span>
75
- <div className="drag-grid">
76
- <Widget addVisualization={() => addVisualization('chart', 'Bar')} type="Bar"/>
77
- <Widget addVisualization={() => addVisualization('chart', 'Line')} type="Line"/>
78
- <Widget addVisualization={() => addVisualization('chart', 'Pie')} type="Pie"/>
74
+ <span className='subheading-3'>Chart</span>
75
+ <div className='drag-grid'>
76
+ <Widget addVisualization={() => addVisualization('chart', 'Bar')} type='Bar' />
77
+ <Widget addVisualization={() => addVisualization('chart', 'Line')} type='Line' />
78
+ <Widget addVisualization={() => addVisualization('chart', 'Pie')} type='Pie' />
79
79
  </div>
80
- <span className="subheading-3">Map</span>
81
- <div className="drag-grid">
82
- <Widget addVisualization={() => addVisualization('map', 'us')} type="us"/>
83
- <Widget addVisualization={() => addVisualization('map', 'world')} type="world"/>
84
- <Widget addVisualization={() => addVisualization('map', 'single-state')} type="single-state"/>
80
+ <span className='subheading-3'>Map</span>
81
+ <div className='drag-grid'>
82
+ <Widget addVisualization={() => addVisualization('map', 'us')} type='us' />
83
+ <Widget addVisualization={() => addVisualization('map', 'world')} type='world' />
84
+ <Widget addVisualization={() => addVisualization('map', 'single-state')} type='single-state' />
85
85
  </div>
86
- <span className="subheading-3">Misc.</span>
87
- <div className="drag-grid">
88
- <Widget addVisualization={() => addVisualization('data-bite', '')} type="data-bite"/>
89
- <Widget addVisualization={() => addVisualization('waffle-chart', '')} type="waffle-chart"/>
90
- <Widget addVisualization={() => addVisualization('markup-include', '')} type="markup-include"/>
91
- <Widget addVisualization={() => addVisualization('filtered-text', '')} type="filtered-text"/>
86
+ <span className='subheading-3'>Misc.</span>
87
+ <div className='drag-grid'>
88
+ <Widget addVisualization={() => addVisualization('data-bite', '')} type='data-bite' />
89
+ <Widget addVisualization={() => addVisualization('waffle-chart', '')} type='waffle-chart' />
90
+ <Widget addVisualization={() => addVisualization('markup-include', '')} type='markup-include' />
91
+ <Widget addVisualization={() => addVisualization('filtered-text', '')} type='filtered-text' />
92
92
  </div>
93
93
  </div>
94
94
  )
95
95
 
96
- export default function CdcDashboard(
97
- { configUrl = '', config: configObj = undefined, isEditor = false, setConfig: setParentConfig, hostname }
98
- ) {
99
-
96
+ export default function CdcDashboard({ configUrl = '', config: configObj = undefined, isEditor = false, setConfig: setParentConfig, hostname }) {
100
97
  const transform = new DataTransform()
101
98
 
102
- const [ config, setConfig ] = useState(configObj)
99
+ const [config, setConfig] = useState(configObj)
103
100
 
104
- const [ data, setData ] = useState([])
101
+ const [data, setData] = useState([])
105
102
 
106
- const [ filteredData, setFilteredData ] = useState()
103
+ const [filteredData, setFilteredData] = useState()
107
104
 
108
- const [ loading, setLoading ] = useState(true)
105
+ const [loading, setLoading] = useState(true)
109
106
 
110
- const [ preview, setPreview ] = useState(false)
107
+ const [preview, setPreview] = useState(false)
111
108
 
112
- const [ currentViewport, setCurrentViewport ] = useState('lg')
109
+ const [currentViewport, setCurrentViewport] = useState('lg')
113
110
 
114
- const [ coveLoadedHasRan, setCoveLoadedHasRan ] = useState(false)
111
+ const [coveLoadedHasRan, setCoveLoadedHasRan] = useState(false)
115
112
 
116
- const [ container, setContainer ] = useState()
113
+ const [container, setContainer] = useState()
117
114
 
118
- const { title, description } = config ? (config.dashboard || config) : {}
115
+ const { title, description } = config ? config.dashboard || config : {}
119
116
 
120
117
  // Supports JSON or CSV
121
- const fetchRemoteData = async (url) => {
118
+ const fetchRemoteData = async url => {
122
119
  try {
123
120
  const urlObj = new URL(url)
124
121
  const regex = /(?:\.([^.]+))?$/
125
122
 
126
123
  let data = []
127
124
 
128
- const ext = (regex.exec(urlObj.pathname)[1])
125
+ const ext = regex.exec(urlObj.pathname)[1]
129
126
  if ('csv' === ext) {
130
127
  data = await fetch(url)
131
128
  .then(response => response.text())
@@ -140,8 +137,7 @@ export default function CdcDashboard(
140
137
  }
141
138
 
142
139
  if ('json' === ext) {
143
- data = await fetch(url)
144
- .then(response => response.json())
140
+ data = await fetch(url).then(response => response.json())
145
141
  }
146
142
 
147
143
  return data
@@ -156,17 +152,14 @@ export default function CdcDashboard(
156
152
  }
157
153
  }
158
154
 
159
-
160
-
161
- const loadConfig = async (configObj) => {
155
+ const loadConfig = async configObj => {
162
156
  // Set loading flag
163
157
  if (!loading) setLoading(true)
164
158
 
165
- let newState = configObj || await (await fetch(configUrl)).json()
159
+ let newState = configObj || (await (await fetch(configUrl)).json())
166
160
 
167
161
  // If a dataUrl property exists, always pull from that.
168
162
  if (newState.dataUrl) {
169
-
170
163
  if (newState.dataUrl[0] === '/') {
171
164
  newState.dataUrl = 'https://' + hostname + newState.dataUrl
172
165
  }
@@ -198,10 +191,10 @@ export default function CdcDashboard(
198
191
  const filterData = (filters, data) => {
199
192
  let filteredData = []
200
193
 
201
- data.forEach((row) => {
194
+ data.forEach(row => {
202
195
  let add = true
203
196
 
204
- filters.forEach((filter) => {
197
+ filters.forEach(filter => {
205
198
  if (row[filter.columnName] !== filter.active) {
206
199
  add = false
207
200
  }
@@ -217,7 +210,7 @@ export default function CdcDashboard(
217
210
  const generateValuesForFilter = (columnName, data = this.state.data) => {
218
211
  const values = []
219
212
 
220
- data.forEach((row) => {
213
+ data.forEach(row => {
221
214
  const value = row[columnName]
222
215
  if (value && false === values.includes(value)) {
223
216
  values.push(value)
@@ -228,7 +221,7 @@ export default function CdcDashboard(
228
221
  }
229
222
 
230
223
  function isEmpty(obj) {
231
- return Object.keys(obj).length === 0;
224
+ return Object.keys(obj).length === 0
232
225
  }
233
226
 
234
227
  const updateConfig = (newConfig, dataOverride = null) => {
@@ -236,12 +229,12 @@ export default function CdcDashboard(
236
229
  if (newConfig.dashboard.filters) {
237
230
  const filterList = []
238
231
 
239
- newConfig.dashboard.filters.forEach((filter) => {
232
+ newConfig.dashboard.filters.forEach(filter => {
240
233
  filterList.push(filter.columnName)
241
234
  })
242
235
 
243
236
  filterList.forEach((filter, index) => {
244
- const filterValues = generateValuesForFilter(filter, (dataOverride || data))
237
+ const filterValues = generateValuesForFilter(filter, dataOverride || data)
245
238
 
246
239
  if (newConfig.dashboard.filters[index].order === 'asc') {
247
240
  filterValues.sort()
@@ -256,7 +249,7 @@ export default function CdcDashboard(
256
249
  newConfig.dashboard.filters[index].active = filterValues[0]
257
250
  })
258
251
 
259
- setFilteredData(filterData(newConfig.dashboard.filters, (dataOverride || data)))
252
+ setFilteredData(filterData(newConfig.dashboard.filters, dataOverride || data))
260
253
  }
261
254
 
262
255
  //Enforce default values that need to be calculated at runtime
@@ -275,14 +268,14 @@ export default function CdcDashboard(
275
268
  if (setParentConfig && isEditor) {
276
269
  setParentConfig(config)
277
270
  }
278
- }, [ config ])
271
+ }, [config])
279
272
 
280
273
  useEffect(() => {
281
274
  if (config && !coveLoadedHasRan && container) {
282
275
  publish('cove_loaded', { config: config })
283
276
  setCoveLoadedHasRan(true)
284
277
  }
285
- }, [config, container]);
278
+ }, [config, container])
286
279
 
287
280
  const updateChildConfig = (visualizationKey, newConfig) => {
288
281
  let updatedConfig = { ...config }
@@ -302,30 +295,28 @@ export default function CdcDashboard(
302
295
  setFilteredData(filterData(dashboardConfig.filters, data))
303
296
  }
304
297
 
305
- const announceChange = (text) => {
306
-
307
- }
298
+ const announceChange = text => {}
308
299
 
309
300
  return config.dashboard.filters.map((singleFilter, index) => {
310
301
  const values = []
311
302
 
312
303
  singleFilter.values.forEach((filterOption, index) => {
313
- values.push(<option
314
- key={index}
315
- value={filterOption}
316
- >{filterOption}
317
- </option>)
304
+ values.push(
305
+ <option key={index} value={filterOption}>
306
+ {filterOption}
307
+ </option>
308
+ )
318
309
  })
319
310
 
320
311
  return (
321
- <section className="dashboard-filters-section" key={index}>
312
+ <section className='dashboard-filters-section' key={index}>
322
313
  <label htmlFor={`filter-${index}`}>{singleFilter.label}</label>
323
314
  <select
324
315
  id={`filter-${index}`}
325
- className="filter-select"
326
- data-index="0"
316
+ className='filter-select'
317
+ data-index='0'
327
318
  value={singleFilter.active}
328
- onChange={(val) => {
319
+ onChange={val => {
329
320
  changeFilterActive(index, val.target.value)
330
321
  announceChange(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`)
331
322
  }}
@@ -335,7 +326,6 @@ export default function CdcDashboard(
335
326
  </section>
336
327
  )
337
328
  })
338
-
339
329
  }
340
330
 
341
331
  const resizeObserver = new ResizeObserver(entries => {
@@ -354,7 +344,7 @@ export default function CdcDashboard(
354
344
  }, [])
355
345
 
356
346
  // Prevent render if loading
357
- if (loading) return <Loading/>
347
+ if (loading) return <Loading />
358
348
 
359
349
  let body = null
360
350
 
@@ -378,28 +368,58 @@ export default function CdcDashboard(
378
368
  setConfig(newConfig)
379
369
  }
380
370
 
381
- const updateConfig = (newConfig) => updateChildConfig(visualizationKey, newConfig)
371
+ const updateConfig = newConfig => updateChildConfig(visualizationKey, newConfig)
382
372
 
383
373
  switch (visualizationConfig.type) {
384
374
  case 'chart':
385
- body = <><Header back={back} subEditor="Chart"/><CdcChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
375
+ body = (
376
+ <>
377
+ <Header back={back} subEditor='Chart' />
378
+ <CdcChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
379
+ </>
380
+ )
386
381
  break
387
382
  case 'map':
388
- body = <><Header back={back} subEditor="Map"/><CdcMap key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
383
+ body = (
384
+ <>
385
+ <Header back={back} subEditor='Map' />
386
+ <CdcMap key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
387
+ </>
388
+ )
389
389
  break
390
390
  case 'data-bite':
391
391
  visualizationConfig = { ...visualizationConfig, newViz: true }
392
- body = <><Header back={back} subEditor="Data Bite"/><CdcDataBite key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
392
+ body = (
393
+ <>
394
+ <Header back={back} subEditor='Data Bite' />
395
+ <CdcDataBite key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
396
+ </>
397
+ )
393
398
  break
394
399
  case 'waffle-chart':
395
- body = <><Header back={back} subEditor="Waffle Chart"/><CdcWaffleChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
400
+ body = (
401
+ <>
402
+ <Header back={back} subEditor='Waffle Chart' />
403
+ <CdcWaffleChart key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
404
+ </>
405
+ )
396
406
  break
397
407
  case 'markup-include':
398
- body = <><Header back={back} subEditor="Markup Include"/><CdcMarkupInclude key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
408
+ body = (
409
+ <>
410
+ <Header back={back} subEditor='Markup Include' />
411
+ <CdcMarkupInclude key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
412
+ </>
413
+ )
414
+ break
415
+ case 'filtered-text':
416
+ body = (
417
+ <>
418
+ <Header back={back} subEditor='Filtered Text' />
419
+ <FilteredText key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true} />
420
+ </>
421
+ )
399
422
  break
400
- case 'filtered-text':
401
- body = <><Header back={back} subEditor="Filtered Text"/><FilteredText key={visualizationKey} config={visualizationConfig} isEditor={true} setConfig={updateConfig} isDashboard={true}/></>
402
- break
403
423
  }
404
424
  }
405
425
  })
@@ -407,10 +427,10 @@ export default function CdcDashboard(
407
427
  if (!subVisualizationEditing) {
408
428
  body = (
409
429
  <DndProvider backend={HTML5Backend}>
410
- <Header preview={preview} setPreview={setPreview}/>
411
- <div className="layout-container">
412
- <VisualizationsPanel/>
413
- <Grid/>
430
+ <Header preview={preview} setPreview={setPreview} />
431
+ <div className='layout-container'>
432
+ <VisualizationsPanel />
433
+ <Grid />
414
434
  </div>
415
435
  </DndProvider>
416
436
  )
@@ -418,64 +438,120 @@ export default function CdcDashboard(
418
438
  } else {
419
439
  body = (
420
440
  <>
421
- {isEditor && <Header preview={preview} setPreview={setPreview}/>}
422
- {isEditor && <EditorPanel/>}
423
- <div className="cdc-dashboard-inner-container">
441
+ {isEditor && <Header preview={preview} setPreview={setPreview} />}
442
+ {isEditor && <EditorPanel />}
443
+ <div className='cdc-dashboard-inner-container'>
424
444
  {/* Title */}
425
- {title && <div role="heading" className={`dashboard-title ${config.dashboard.theme ?? 'theme-blue'}`}>{title}</div>}
445
+ {title && (
446
+ <div role='heading' className={`dashboard-title ${config.dashboard.theme ?? 'theme-blue'}`}>
447
+ {title}
448
+ </div>
449
+ )}
426
450
 
427
451
  {/* Filters */}
428
- {config.dashboard.filters &&
429
- <div className="cove-dashboard-filters">
452
+ {config.dashboard.filters && (
453
+ <div className='cove-dashboard-filters'>
430
454
  <Filters />
431
455
  </div>
432
- }
456
+ )}
433
457
 
434
458
  {/* Visualizations */}
435
- {config.rows && config.rows.map((row, index) => {
436
- // Empty check
437
- if (row.filter(col => col.widget).length === 0) return null
438
-
439
- return (
440
- <div className="dashboard-row" key={`row__${index}`}>
441
- {row.map((col, index) => {
442
- if (col.width) {
443
- if (!col.widget) return <div className={`dashboard-col dashboard-col-${col.width}`}></div>
444
-
445
- let visualizationConfig = config.visualizations[col.widget]
446
-
447
- visualizationConfig.data = filteredData || data
448
-
449
- return <div className={`dashboard-col dashboard-col-${col.width}`} key={`vis__${index}`}>
450
- {visualizationConfig.type === 'chart' && <CdcChart key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
451
- updateChildConfig(col.widget, newConfig)
452
- }} isDashboard={true}/>}
453
- {visualizationConfig.type === 'map' && <CdcMap key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
454
- updateChildConfig(col.widget, newConfig)
455
- }} isDashboard={true}/>}
456
- {visualizationConfig.type === 'data-bite' && <CdcDataBite key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
457
- updateChildConfig(col.widget, newConfig)
458
- }} isDashboard={true}/>}
459
- {visualizationConfig.type === 'waffle-chart' && <CdcWaffleChart key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
460
- updateChildConfig(col.widget, newConfig)
461
- }} isDashboard={true}/>}
462
- {visualizationConfig.type === 'markup-include' && <CdcMarkupInclude key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
463
- updateChildConfig(col.widget, newConfig)
464
- }} isDashboard={true}/>}
465
- {visualizationConfig.type === 'filtered-text' && <FilteredText key={col.widget} config={visualizationConfig} isEditor={false} setConfig={(newConfig) => {
466
- updateChildConfig(col.widget, newConfig)
467
- }} isDashboard={true}/>}
468
- </div>
469
- }
470
- })}
471
- </div>)
472
- })}
459
+ {config.rows &&
460
+ config.rows.map((row, index) => {
461
+ // Empty check
462
+ if (row.filter(col => col.widget).length === 0) return null
463
+
464
+ return (
465
+ <div className='dashboard-row' key={`row__${index}`}>
466
+ {row.map((col, index) => {
467
+ if (col.width) {
468
+ if (!col.widget) return <div className={`dashboard-col dashboard-col-${col.width}`}></div>
469
+
470
+ let visualizationConfig = config.visualizations[col.widget]
471
+
472
+ visualizationConfig.data = filteredData || data
473
+
474
+ return (
475
+ <div className={`dashboard-col dashboard-col-${col.width}`} key={`vis__${index}`}>
476
+ {visualizationConfig.type === 'chart' && (
477
+ <CdcChart
478
+ key={col.widget}
479
+ config={visualizationConfig}
480
+ isEditor={false}
481
+ setConfig={newConfig => {
482
+ updateChildConfig(col.widget, newConfig)
483
+ }}
484
+ isDashboard={true}
485
+ />
486
+ )}
487
+ {visualizationConfig.type === 'map' && (
488
+ <CdcMap
489
+ key={col.widget}
490
+ config={visualizationConfig}
491
+ isEditor={false}
492
+ setConfig={newConfig => {
493
+ updateChildConfig(col.widget, newConfig)
494
+ }}
495
+ isDashboard={true}
496
+ />
497
+ )}
498
+ {visualizationConfig.type === 'data-bite' && (
499
+ <CdcDataBite
500
+ key={col.widget}
501
+ config={visualizationConfig}
502
+ isEditor={false}
503
+ setConfig={newConfig => {
504
+ updateChildConfig(col.widget, newConfig)
505
+ }}
506
+ isDashboard={true}
507
+ />
508
+ )}
509
+ {visualizationConfig.type === 'waffle-chart' && (
510
+ <CdcWaffleChart
511
+ key={col.widget}
512
+ config={visualizationConfig}
513
+ isEditor={false}
514
+ setConfig={newConfig => {
515
+ updateChildConfig(col.widget, newConfig)
516
+ }}
517
+ isDashboard={true}
518
+ />
519
+ )}
520
+ {visualizationConfig.type === 'markup-include' && (
521
+ <CdcMarkupInclude
522
+ key={col.widget}
523
+ config={visualizationConfig}
524
+ isEditor={false}
525
+ setConfig={newConfig => {
526
+ updateChildConfig(col.widget, newConfig)
527
+ }}
528
+ isDashboard={true}
529
+ />
530
+ )}
531
+ {visualizationConfig.type === 'filtered-text' && (
532
+ <FilteredText
533
+ key={col.widget}
534
+ config={visualizationConfig}
535
+ isEditor={false}
536
+ setConfig={newConfig => {
537
+ updateChildConfig(col.widget, newConfig)
538
+ }}
539
+ isDashboard={true}
540
+ />
541
+ )}
542
+ </div>
543
+ )
544
+ }
545
+ })}
546
+ </div>
547
+ )
548
+ })}
473
549
 
474
550
  {/* Data Table */}
475
- {config.table.show && <DataTable/>}
551
+ {config.table.show && <DataTable />}
476
552
 
477
553
  {/* Description */}
478
- {description && <div className="subtext">{parse(description)}</div>}
554
+ {description && <div className='subtext'>{parse(description)}</div>}
479
555
  </div>
480
556
  </>
481
557
  )