@cdc/dashboard 4.26.1 → 4.26.3

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 (76) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcdashboard-8NmHlKRI.es.js +15 -0
  3. package/dist/cdcdashboard-BPoPzKPz.es.js +6 -0
  4. package/dist/{cdcdashboard-dgT_1dIT.es.js → cdcdashboard-DQ00cQCm.es.js} +1 -20
  5. package/dist/cdcdashboard-jiQQPkty.es.js +6 -0
  6. package/dist/cdcdashboard-vr9HZwRt.es.js +6 -0
  7. package/dist/cdcdashboard.js +80971 -83096
  8. package/examples/custom/css/respiratory.css +1 -1
  9. package/examples/data/data-with-metadata.json +18 -0
  10. package/examples/default.json +492 -132
  11. package/examples/nested-dropdown.json +6985 -0
  12. package/examples/private/abc.json +467 -0
  13. package/examples/private/dash.json +12696 -0
  14. package/examples/private/inline-markup.json +775 -0
  15. package/examples/private/npcr.json +1 -0
  16. package/examples/private/recent-update.json +1456 -0
  17. package/examples/private/test.json +125407 -0
  18. package/examples/private/timeline-data.json +4994 -0
  19. package/examples/private/timeline.json +1708 -0
  20. package/examples/private/toggle.json +10137 -0
  21. package/examples/test-api-filter-reset.json +8 -4
  22. package/examples/tp5-gauges.json +196 -0
  23. package/examples/tp5-test.json +266 -0
  24. package/index.html +1 -29
  25. package/package.json +38 -40
  26. package/src/CdcDashboard.tsx +2 -1
  27. package/src/CdcDashboardComponent.tsx +47 -30
  28. package/src/_stories/Dashboard.DataSetup.stories.tsx +8 -2
  29. package/src/_stories/Dashboard.Pages.stories.tsx +22 -0
  30. package/src/_stories/Dashboard.stories.tsx +4501 -80
  31. package/src/_stories/_mock/dashboard-line-chart-angles.json +1030 -0
  32. package/src/_stories/_mock/tab-simple-filter.json +153 -0
  33. package/src/_stories/_mock/tp5-test.json +267 -0
  34. package/src/components/DashboardFilters/DashboardFilters.tsx +19 -3
  35. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +10 -4
  36. package/src/components/DashboardFilters/DashboardFiltersEditor/components/APIModal.tsx +1 -1
  37. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +6 -3
  38. package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +13 -8
  39. package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +8 -8
  40. package/src/components/DashboardFilters/_stories/DashboardFilters.stories.tsx +1 -1
  41. package/src/components/DashboardFilters/dashboardfilter.styles.css +3 -3
  42. package/src/components/DataDesignerModal.tsx +2 -2
  43. package/src/components/Header/Header.tsx +27 -5
  44. package/src/components/Header/index.scss +1 -1
  45. package/src/components/MultiConfigTabs/multiconfigtabs.styles.css +6 -6
  46. package/src/components/Row.tsx +21 -0
  47. package/src/components/Toggle/toggle-style.css +7 -7
  48. package/src/components/VisualizationRow.tsx +42 -29
  49. package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +1 -71
  50. package/src/components/VisualizationsPanel/visualizations-panel-styles.css +2 -2
  51. package/src/components/Widget/Widget.tsx +2 -2
  52. package/src/components/Widget/widget.styles.css +12 -12
  53. package/src/data/initial-state.js +1 -1
  54. package/src/helpers/addValuesToDashboardFilters.ts +17 -11
  55. package/src/helpers/addVisualization.ts +71 -0
  56. package/src/helpers/apiFilterHelpers.ts +28 -32
  57. package/src/helpers/formatConfigBeforeSave.ts +1 -1
  58. package/src/helpers/getVizConfig.ts +13 -3
  59. package/src/helpers/iconHash.tsx +45 -36
  60. package/src/helpers/processDataLegacy.ts +19 -14
  61. package/src/helpers/tests/addValuesToDashboardFilters.test.ts +141 -44
  62. package/src/helpers/tests/addVisualization.test.ts +52 -0
  63. package/src/helpers/tests/apiFilterHelpers.test.ts +523 -420
  64. package/src/helpers/tests/formatConfigBeforeSave.test.ts +81 -1
  65. package/src/scss/editor-panel.scss +1 -1
  66. package/src/scss/main.scss +169 -41
  67. package/src/store/dashboard.reducer.ts +1 -1
  68. package/src/test/CdcDashboard.test.jsx +2 -2
  69. package/src/test/CdcDashboardComponent.test.tsx +74 -0
  70. package/src/types/FilterStyles.ts +2 -1
  71. package/tests/fixtures/dashboard-config-with-metadata.json +89 -0
  72. package/vite.config.js +7 -1
  73. package/dist/cdcdashboard-BnB1QM5d.es.js +0 -361528
  74. package/dist/cdcdashboard-Ct2SB0vL.es.js +0 -231049
  75. package/dist/cdcdashboard-D6CG2-Hb.es.js +0 -39377
  76. package/dist/cdcdashboard-MXgURbdZ.es.js +0 -39194
@@ -1,7 +1,4 @@
1
- import React, { useState, useEffect, useCallback, useMemo, useReducer, useContext } from 'react'
2
-
3
- // IE11
4
- // import 'core-js/stable'
1
+ import React, { useState, useEffect, useCallback, useMemo, useReducer, useContext, useRef } from 'react'
5
2
  import 'whatwg-fetch'
6
3
  import ResizeObserver from 'resize-observer-polyfill'
7
4
 
@@ -42,7 +39,9 @@ import { type SharedFilter } from './types/SharedFilter'
42
39
  import { type WCMSProps } from '@cdc/core/types/WCMSProps'
43
40
  import { type InitialState } from './types/InitialState'
44
41
  import MultiTabs from './components/MultiConfigTabs'
45
- import _ from 'lodash'
42
+ import cloneDeep from 'lodash/cloneDeep'
43
+ import pick from 'lodash/pick'
44
+ import pickBy from 'lodash/pickBy'
46
45
  import EditorContext from '@cdc/core/contexts/EditorContext'
47
46
  import { APIFilterDropdowns } from './components/DashboardFilters'
48
47
  import { ViewPort } from '@cdc/core/types/ViewPort'
@@ -50,7 +49,7 @@ import VisualizationRow from './components/VisualizationRow'
50
49
  import { getVizConfig } from './helpers/getVizConfig'
51
50
  import { getFilteredData } from './helpers/getFilteredData'
52
51
  import { getVizRowColumnLocator } from './helpers/getVizRowColumnLocator'
53
- import Layout from '@cdc/core/components/Layout'
52
+ import { Responsive, VisualizationContainer } from '@cdc/core/components/Layout'
54
53
  import * as reloadURLHelpers from './helpers/reloadURLHelpers'
55
54
  import { addValuesToDashboardFilters } from './helpers/addValuesToDashboardFilters'
56
55
  import { DashboardFilters } from './types/DashboardFilters'
@@ -210,9 +209,9 @@ export default function CdcDashboard({
210
209
 
211
210
  setAPILoading(true)
212
211
  await fetchRemoteData(dataUrlFinal)
213
- .then(responseData => {
214
- let data: any[] = responseData
215
- if (responseData && dataset.dataDescription) {
212
+ .then(({ data: fetchedData, dataMetadata }) => {
213
+ let data: any[] = fetchedData
214
+ if (data && dataset.dataDescription) {
216
215
  try {
217
216
  data = transform.autoStandardize(data)
218
217
  data = transform.developerStandardize(data, dataset.dataDescription)
@@ -222,6 +221,7 @@ export default function CdcDashboard({
222
221
  }
223
222
  }
224
223
  newDatasets[datasetKey].data = data
224
+ newDatasets[datasetKey].dataMetadata = dataMetadata
225
225
  newDatasets[datasetKey].runtimeDataUrl = dataUrlFinal
226
226
  newData[datasetKey] = data
227
227
  })
@@ -239,7 +239,7 @@ export default function CdcDashboard({
239
239
  }
240
240
  }
241
241
 
242
- const datasetsWithFiles = _.pickBy(newDatasets, dataset => !dataset.dataUrl)
242
+ const datasetsWithFiles = pickBy(newDatasets, dataset => !dataset.dataUrl)
243
243
 
244
244
  if (dataWasFetched || Object.keys(datasetsWithFiles).length) {
245
245
  const dataFiles = Object.keys(datasetsWithFiles).reduce((acc, key) => {
@@ -294,7 +294,7 @@ export default function CdcDashboard({
294
294
  }
295
295
 
296
296
  const setSharedFilter = (key, datum) => {
297
- const { config: newConfig, filteredData } = _.cloneDeep(state)
297
+ const { config: newConfig, filteredData } = cloneDeep(state)
298
298
 
299
299
  for (let i = 0; i < newConfig.dashboard.sharedFilters.length; i++) {
300
300
  const filter = newConfig.dashboard.sharedFilters[i]
@@ -322,7 +322,7 @@ export default function CdcDashboard({
322
322
  return acc
323
323
  }, {})
324
324
  const newConfig = { ...state, data: { ...data, ...newDatasets } }
325
- const newFilteredData = getFilteredData(newConfig, _.cloneDeep(filteredData))
325
+ const newFilteredData = getFilteredData(newConfig, cloneDeep(filteredData))
326
326
  dispatch({ type: 'SET_FILTERED_DATA', payload: newFilteredData })
327
327
  dispatch({ type: 'SET_DATA', payload: { ...data, ...newDatasets } })
328
328
  } catch (e) {
@@ -378,14 +378,14 @@ export default function CdcDashboard({
378
378
 
379
379
  const updateChildConfig = (visualizationKey, newConfig) => {
380
380
  const config = cloneConfig(state.config)
381
- const updatedConfig = _.pick(config, ['visualizations', 'multiDashboards'])
381
+ const updatedConfig = pick(config, ['visualizations', 'multiDashboards'])
382
382
  updatedConfig.visualizations[visualizationKey] = newConfig
383
383
  updatedConfig.visualizations[visualizationKey].formattedData = config.visualizations[visualizationKey].formattedData
384
384
  if (config.multiDashboards) {
385
385
  const activeDashboard = config.activeDashboard
386
386
  const multiDashboards = [...config.multiDashboards]
387
387
  const label = multiDashboards[activeDashboard].label
388
- const toSave = { label, visualizations: updatedConfig.visualizations, ..._.pick(config, ['dashboard', 'rows']) }
388
+ const toSave = { label, visualizations: updatedConfig.visualizations, ...pick(config, ['dashboard', 'rows']) }
389
389
  multiDashboards[activeDashboard] = toSave
390
390
  updatedConfig.multiDashboards = multiDashboards
391
391
  }
@@ -397,17 +397,31 @@ export default function CdcDashboard({
397
397
  }
398
398
  }
399
399
 
400
- const resizeObserver = new ResizeObserver(entries => {
401
- for (let entry of entries) {
402
- let newViewport = getViewport(entry.contentRect.width)
400
+ const resizeObserverRef = useRef<ResizeObserver | null>(null)
403
401
 
404
- setCurrentViewport(newViewport)
402
+ const outerContainerRef = useCallback(node => {
403
+ if (resizeObserverRef.current) {
404
+ resizeObserverRef.current.disconnect()
405
+ resizeObserverRef.current = null
405
406
  }
406
- })
407
407
 
408
- const outerContainerRef = useCallback(node => {
409
408
  if (node !== null) {
410
- resizeObserver.observe(node)
409
+ resizeObserverRef.current = new ResizeObserver(entries => {
410
+ for (let entry of entries) {
411
+ const newViewport = getViewport(entry.contentRect.width)
412
+ setCurrentViewport(newViewport)
413
+ }
414
+ })
415
+ resizeObserverRef.current.observe(node)
416
+ }
417
+ }, [])
418
+
419
+ useEffect(() => {
420
+ return () => {
421
+ if (resizeObserverRef.current) {
422
+ resizeObserverRef.current.disconnect()
423
+ resizeObserverRef.current = null
424
+ }
411
425
  }
412
426
  }, [])
413
427
 
@@ -500,7 +514,7 @@ export default function CdcDashboard({
500
514
  autoDismiss={true}
501
515
  />
502
516
  ))}
503
- <Layout.Responsive isEditor={isEditor}>
517
+ <Responsive isEditor={isEditor}>
504
518
  <div className={`cdc-dashboard-inner-container${isEditor ? ' is-editor' : ''}`}>
505
519
  <Title
506
520
  title={title}
@@ -643,16 +657,11 @@ export default function CdcDashboard({
643
657
  })
644
658
  .filter(Boolean)}
645
659
  </div>
646
- </Layout.Responsive>
660
+ </Responsive>
647
661
  </>
648
662
  )
649
663
  }
650
664
 
651
- const dashboardContainerClasses = ['cdc-open-viz-module', 'type-dashboard', `${currentViewport}`]
652
- if (isEditor) {
653
- dashboardContainerClasses.push('isDashboardEditor')
654
- }
655
-
656
665
  return (
657
666
  <GlobalContextProvider>
658
667
  <DashboardContext.Provider
@@ -669,9 +678,17 @@ export default function CdcDashboard({
669
678
  }}
670
679
  >
671
680
  <DashboardDispatchContext.Provider value={dispatch}>
672
- <div className={dashboardContainerClasses.join(' ')} ref={outerContainerRef} data-download-id={imageId}>
681
+ <VisualizationContainer
682
+ className={isEditor ? 'is-dashboard-editor' : undefined}
683
+ config={state.config}
684
+ currentViewport={currentViewport}
685
+ imageId={imageId}
686
+ isEditor={false}
687
+ ref={outerContainerRef}
688
+ renderResponsive={false}
689
+ >
673
690
  {body}
674
- </div>
691
+ </VisualizationContainer>
675
692
  <OverlayFrame />
676
693
  </DashboardDispatchContext.Provider>
677
694
  </DashboardContext.Provider>
@@ -151,14 +151,20 @@ export const MultiVizConfigurationWorkflow: Story = {
151
151
  // ========================================================================
152
152
  await sleep(500)
153
153
 
154
- const dataSourceSelect = canvas.getByRole('combobox')
154
+ const comboboxes = canvas.getAllByRole('combobox')
155
+ const dataSourceSelect = comboboxes[comboboxes.length - 1]
155
156
  await user.selectOptions(dataSourceSelect, 'Demo')
156
157
  await sleep(500)
157
158
 
158
159
  // ========================================================================
159
160
  // STEP 11: Click "Vertical Values for map" button
160
161
  // ========================================================================
161
- await sleep(500)
162
+ await waitFor(
163
+ () => {
164
+ expect(canvas.getByRole('button', { name: /vertical values for map/i })).toBeTruthy()
165
+ },
166
+ { timeout: 5000 }
167
+ )
162
168
 
163
169
  const verticalValuesButton = canvas.getByRole('button', { name: /vertical values for map/i })
164
170
  await user.click(verticalValuesButton)
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { assertVisualizationRendered } from '@cdc/core/helpers/testing'
3
+ import Dashboard from '../CdcDashboard'
4
+
5
+ const meta: Meta<typeof Dashboard> = {
6
+ title: 'Pages/NWSS',
7
+ component: Dashboard
8
+ }
9
+
10
+ export default meta
11
+ type Story = StoryObj<typeof Dashboard>
12
+
13
+ export const FluA_Top_Modules: Story = {
14
+ name: 'FluA Top Modules',
15
+ args: {
16
+ configUrl: 'https://www.cdc.gov/nwss/rv/modules/flua/flua-top-modules.json',
17
+ isEditor: false
18
+ },
19
+ play: async ({ canvasElement }) => {
20
+ await assertVisualizationRendered(canvasElement)
21
+ }
22
+ }