@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.
- package/LICENSE +201 -0
- package/dist/cdcdashboard-8NmHlKRI.es.js +15 -0
- package/dist/cdcdashboard-BPoPzKPz.es.js +6 -0
- package/dist/{cdcdashboard-dgT_1dIT.es.js → cdcdashboard-DQ00cQCm.es.js} +1 -20
- package/dist/cdcdashboard-jiQQPkty.es.js +6 -0
- package/dist/cdcdashboard-vr9HZwRt.es.js +6 -0
- package/dist/cdcdashboard.js +80971 -83096
- package/examples/custom/css/respiratory.css +1 -1
- package/examples/data/data-with-metadata.json +18 -0
- package/examples/default.json +492 -132
- package/examples/nested-dropdown.json +6985 -0
- package/examples/private/abc.json +467 -0
- package/examples/private/dash.json +12696 -0
- package/examples/private/inline-markup.json +775 -0
- package/examples/private/npcr.json +1 -0
- package/examples/private/recent-update.json +1456 -0
- package/examples/private/test.json +125407 -0
- package/examples/private/timeline-data.json +4994 -0
- package/examples/private/timeline.json +1708 -0
- package/examples/private/toggle.json +10137 -0
- package/examples/test-api-filter-reset.json +8 -4
- package/examples/tp5-gauges.json +196 -0
- package/examples/tp5-test.json +266 -0
- package/index.html +1 -29
- package/package.json +38 -40
- package/src/CdcDashboard.tsx +2 -1
- package/src/CdcDashboardComponent.tsx +47 -30
- package/src/_stories/Dashboard.DataSetup.stories.tsx +8 -2
- package/src/_stories/Dashboard.Pages.stories.tsx +22 -0
- package/src/_stories/Dashboard.stories.tsx +4501 -80
- package/src/_stories/_mock/dashboard-line-chart-angles.json +1030 -0
- package/src/_stories/_mock/tab-simple-filter.json +153 -0
- package/src/_stories/_mock/tp5-test.json +267 -0
- package/src/components/DashboardFilters/DashboardFilters.tsx +19 -3
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +10 -4
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/APIModal.tsx +1 -1
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +6 -3
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +13 -8
- package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +8 -8
- package/src/components/DashboardFilters/_stories/DashboardFilters.stories.tsx +1 -1
- package/src/components/DashboardFilters/dashboardfilter.styles.css +3 -3
- package/src/components/DataDesignerModal.tsx +2 -2
- package/src/components/Header/Header.tsx +27 -5
- package/src/components/Header/index.scss +1 -1
- package/src/components/MultiConfigTabs/multiconfigtabs.styles.css +6 -6
- package/src/components/Row.tsx +21 -0
- package/src/components/Toggle/toggle-style.css +7 -7
- package/src/components/VisualizationRow.tsx +42 -29
- package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +1 -71
- package/src/components/VisualizationsPanel/visualizations-panel-styles.css +2 -2
- package/src/components/Widget/Widget.tsx +2 -2
- package/src/components/Widget/widget.styles.css +12 -12
- package/src/data/initial-state.js +1 -1
- package/src/helpers/addValuesToDashboardFilters.ts +17 -11
- package/src/helpers/addVisualization.ts +71 -0
- package/src/helpers/apiFilterHelpers.ts +28 -32
- package/src/helpers/formatConfigBeforeSave.ts +1 -1
- package/src/helpers/getVizConfig.ts +13 -3
- package/src/helpers/iconHash.tsx +45 -36
- package/src/helpers/processDataLegacy.ts +19 -14
- package/src/helpers/tests/addValuesToDashboardFilters.test.ts +141 -44
- package/src/helpers/tests/addVisualization.test.ts +52 -0
- package/src/helpers/tests/apiFilterHelpers.test.ts +523 -420
- package/src/helpers/tests/formatConfigBeforeSave.test.ts +81 -1
- package/src/scss/editor-panel.scss +1 -1
- package/src/scss/main.scss +169 -41
- package/src/store/dashboard.reducer.ts +1 -1
- package/src/test/CdcDashboard.test.jsx +2 -2
- package/src/test/CdcDashboardComponent.test.tsx +74 -0
- package/src/types/FilterStyles.ts +2 -1
- package/tests/fixtures/dashboard-config-with-metadata.json +89 -0
- package/vite.config.js +7 -1
- package/dist/cdcdashboard-BnB1QM5d.es.js +0 -361528
- package/dist/cdcdashboard-Ct2SB0vL.es.js +0 -231049
- package/dist/cdcdashboard-D6CG2-Hb.es.js +0 -39377
- 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
|
|
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
|
|
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(
|
|
214
|
-
let data: any[] =
|
|
215
|
-
if (
|
|
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 =
|
|
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 } =
|
|
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,
|
|
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 =
|
|
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, ...
|
|
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
|
|
401
|
-
for (let entry of entries) {
|
|
402
|
-
let newViewport = getViewport(entry.contentRect.width)
|
|
400
|
+
const resizeObserverRef = useRef<ResizeObserver | null>(null)
|
|
403
401
|
|
|
404
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
|
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
|
|
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
|
+
}
|