@cdc/dashboard 4.24.2 → 4.24.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 (38) hide show
  1. package/dist/cdcdashboard.js +98192 -85200
  2. package/examples/sankey.json +5218 -0
  3. package/index.html +3 -2
  4. package/package.json +11 -10
  5. package/src/CdcDashboard.tsx +124 -124
  6. package/src/CdcDashboardComponent.tsx +173 -186
  7. package/src/DashboardContext.tsx +4 -1
  8. package/src/_stories/Dashboard.stories.tsx +27 -5
  9. package/src/_stories/_mock/pivot-filter.json +163 -0
  10. package/src/_stories/_mock/standalone-table.json +122 -0
  11. package/src/_stories/_mock/toggle-example.json +4035 -0
  12. package/src/components/EditorWrapper/EditorWrapper.tsx +52 -0
  13. package/src/components/EditorWrapper/editor-wrapper.style.css +13 -0
  14. package/src/components/Filters.tsx +88 -0
  15. package/src/components/Header/FilterModal.tsx +480 -0
  16. package/src/components/Header/Header.tsx +25 -465
  17. package/src/components/Row.tsx +28 -17
  18. package/src/components/Toggle/Toggle.tsx +37 -0
  19. package/src/components/Toggle/index.tsx +1 -0
  20. package/src/components/Toggle/toggle-style.css +34 -0
  21. package/src/components/VisualizationsPanel.tsx +13 -3
  22. package/src/components/Widget.tsx +14 -30
  23. package/src/helpers/filterData.ts +72 -49
  24. package/src/helpers/generateValuesForFilter.ts +2 -12
  25. package/src/helpers/getApiFilterKey.ts +5 -0
  26. package/src/helpers/getUpdateConfig.ts +24 -22
  27. package/src/helpers/iconHash.tsx +34 -0
  28. package/src/helpers/tests/filterData.test.ts +149 -0
  29. package/src/images/icon-toggle.svg +1 -0
  30. package/src/scss/grid.scss +1 -1
  31. package/src/scss/main.scss +6 -0
  32. package/src/store/dashboard.actions.ts +19 -2
  33. package/src/store/dashboard.reducer.ts +9 -1
  34. package/src/types/ConfigRow.ts +2 -0
  35. package/src/types/DataSet.ts +7 -7
  36. package/src/types/InitialState.ts +2 -1
  37. package/src/types/SharedFilter.ts +5 -2
  38. package/src/types/Tab.ts +1 -0
package/index.html CHANGED
@@ -21,11 +21,12 @@
21
21
  </head>
22
22
 
23
23
  <body>
24
- <div class="react-container" data-config="/examples/private/test.json"></div>
24
+ <!-- <div class="react-container" data-config="/examples/private/test.json"></div> -->
25
25
  <!-- <div class="react-container" data-config="/examples/dashboard-gallery.json"></div> -->
26
26
  <!-- <div class="react-container" data-config="/examples/filtered-dash.json"></div> -->
27
27
  <!-- <div class="react-container" data-config="/examples/all-components.json"></div> -->
28
- <div class="react-container" data-config="/examples/dash.json"></div>
28
+ <!-- <div class="react-container" data-config="/examples/sankey.json"></div> -->
29
+ <div class="react-container" data-config="/examples/DEV-6574.json"></div>
29
30
  <!-- <div class="react-container" data-config="/examples/default-multi-dataset-2.json"></div> -->
30
31
  <!-- <div class="react-container" data-config="/examples/default-multi-dataset.json"></div> -->
31
32
  <!-- <div class="react-container" data-config="/examples/default-filter-control.json"></div> -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/dashboard",
3
- "version": "4.24.2",
3
+ "version": "4.24.3",
4
4
  "description": "React component for combining multiple visualizations into a single dashboard",
5
5
  "moduleName": "CdcDashboard",
6
6
  "main": "dist/cdcdashboard",
@@ -12,7 +12,8 @@
12
12
  "graph": "nx graph",
13
13
  "prepublishOnly": "lerna run --scope @cdc/dashboard build",
14
14
  "test": "vitest watch --reporter verbose",
15
- "test:ui": "vitest --ui"
15
+ "test:ui": "vitest --ui",
16
+ "coverage": "vitest run --coverage"
16
17
  },
17
18
  "repository": {
18
19
  "type": "git",
@@ -25,13 +26,13 @@
25
26
  },
26
27
  "license": "Apache-2.0",
27
28
  "dependencies": {
28
- "@cdc/chart": "^4.24.2",
29
- "@cdc/core": "^4.24.2",
30
- "@cdc/data-bite": "^4.24.2",
31
- "@cdc/filtered-text": "^4.24.2",
32
- "@cdc/map": "^4.24.2",
33
- "@cdc/markup-include": "^4.24.2",
34
- "@cdc/waffle-chart": "^4.24.2",
29
+ "@cdc/chart": "^4.24.3",
30
+ "@cdc/core": "^4.24.3",
31
+ "@cdc/data-bite": "^4.24.3",
32
+ "@cdc/filtered-text": "^4.24.3",
33
+ "@cdc/map": "^4.24.3",
34
+ "@cdc/markup-include": "^4.24.3",
35
+ "@cdc/waffle-chart": "^4.24.3",
35
36
  "html-react-parser": "^3.0.8",
36
37
  "js-base64": "^2.5.2",
37
38
  "papaparse": "^5.3.0",
@@ -47,5 +48,5 @@
47
48
  "react": "^18.2.0",
48
49
  "react-dom": "^18.2.0"
49
50
  },
50
- "gitHead": "edde49c96dee146de5e3a4537880b1bcf4dbee08"
51
+ "gitHead": "9c7ef7ca74f2d2a1e04d923b133fe0fc557a62bf"
51
52
  }
@@ -1,124 +1,124 @@
1
- import { useEffect, useState } from 'react'
2
- import CdcDashboard from './CdcDashboardComponent'
3
- import { MultiDashboardConfig } from './types/MultiDashboard'
4
- import Loading from '@cdc/core/components/Loading'
5
- import defaults from './data/initial-state'
6
- import { processData } from './helpers/processData'
7
- import { getVizKeys } from './helpers/getVizKeys'
8
- import { processDataLegacy } from './helpers/processDataLegacy'
9
- import { WCMSProps } from '@cdc/core/types/WCMSProps'
10
- import { initialState } from './DashboardContext'
11
- import { getUpdateConfig } from './helpers/getUpdateConfig'
12
- import { InitialState } from './types/InitialState'
13
- import { DashboardConfig } from './types/DashboardConfig'
14
- import _ from 'lodash'
15
-
16
- type MultiDashboardProps = Omit<WCMSProps, 'configUrl'> & {
17
- configUrl?: string
18
- config?: MultiDashboardConfig
19
- }
20
-
21
- const MultiDashboardWrapper: React.FC<MultiDashboardProps> = ({ configUrl, config: editorConfig, isEditor, isDebug }) => {
22
- const [initial, setInitial] = useState<InitialState>(undefined)
23
- console.log('multi dashboard wrapper')
24
-
25
- const getSelectedConfig = (config: MultiDashboardConfig, selectedConfig?: string): number | null => {
26
- if (!config.multiDashboards) return null
27
- // TODO: if query parameter select based on query parameter
28
- if (selectedConfig) {
29
- const foundConfig = Object.values(config.multiDashboards).findIndex(({ label }) => {
30
- return label === selectedConfig
31
- })
32
- if (foundConfig > -1) return foundConfig
33
- }
34
- // else select the first available
35
- return 0
36
- }
37
-
38
- const formatInitialState = (newConfig: MultiDashboardConfig | DashboardConfig, datasets: Record<string, Object[]>) => {
39
- const [config, filteredData] = getUpdateConfig(initialState)(newConfig, datasets)
40
- return { ...initialState, config, filteredData, data: datasets }
41
- }
42
-
43
- const loadConfig = async (selectedConfig?: string) => {
44
- const _config: MultiDashboardConfig = editorConfig || (await (await fetch(configUrl)).json())
45
- const selected = getSelectedConfig(_config, selectedConfig)
46
-
47
- const { newConfig, datasets } = selected !== null ? await loadMultiDashboard(_config, selected) : await loadSingleDashboard(_config)
48
- setInitial(formatInitialState(newConfig, datasets))
49
- }
50
-
51
- useEffect(() => {
52
- loadConfig()
53
- }, [])
54
-
55
- const loadData = async (initialConfig: DashboardConfig | MultiDashboardConfig) => {
56
- let newConfig = { ...initialConfig }
57
- let datasets: Record<string, Object[]> = {}
58
- await Promise.all(
59
- Object.keys(initialConfig.datasets).map(async key => {
60
- datasets[key] = await processData(initialConfig.datasets[key], initialConfig.filterBehavior)
61
- })
62
- )
63
-
64
- getVizKeys(newConfig).forEach(vizKey => {
65
- newConfig.visualizations[vizKey].formattedData = datasets[newConfig.visualizations[vizKey].dataKey]
66
- })
67
-
68
- Object.keys(datasets).forEach(key => {
69
- newConfig.datasets[key].data = datasets[key]
70
- })
71
- return { newConfig, datasets }
72
- }
73
-
74
- const loadSingleDashboard = async config => {
75
- let newConfig = { ...defaults, ...config } as DashboardConfig
76
-
77
- if (config.datasets) {
78
- return await loadData(newConfig)
79
- } else {
80
- const dataKey = newConfig.dataFileName || 'backwards-compatibility'
81
- const data = await processDataLegacy(config)
82
-
83
- const datasetsFull = {}
84
- datasetsFull[dataKey] = {
85
- data,
86
- dataDescription: newConfig.dataDescription
87
- }
88
- newConfig.datasets = datasetsFull
89
-
90
- getVizKeys(newConfig).forEach(vizKey => {
91
- const newData = { dataKey, ..._.pick(newConfig, 'dataDescription', 'formattedData') }
92
- newConfig.visualizations[vizKey] = { ...newConfig.visualizations[vizKey], ...newData }
93
- })
94
-
95
- const blankFields = { data: [], dataUrl: '', dataFileName: '', dataFileSourceType: '', dataDescription: [], formattedData: [] }
96
- newConfig = { ...newConfig, ...blankFields }
97
-
98
- if (newConfig.dashboard.filters) {
99
- const dashboard = { ...newConfig.dashboard }
100
- // replace filters with sharedFilters
101
- if (!dashboard.sharedFilters) dashboard.sharedFilters = []
102
- const filters = dashboard.filters.map(filter => {
103
- return { ...filter, key: filter.label, showDropdown: true, usedBy: getVizKeys(newConfig) }
104
- })
105
- dashboard.sharedFilters = [...dashboard.sharedFilters, ...filters]
106
- newConfig.dashboard = { ...dashboard, filters: undefined }
107
- }
108
-
109
- const datasets: Record<string, Object[]> = { [dataKey]: data }
110
- return { newConfig, datasets }
111
- }
112
- }
113
-
114
- const loadMultiDashboard = async (multiConfig: MultiDashboardConfig, selectedConfig: number) => {
115
- const selectedDashboard = multiConfig.multiDashboards[selectedConfig]
116
- let newConfig = { ...defaults, ...multiConfig, ...selectedDashboard, multiDashboards: multiConfig.multiDashboards, activeDashboard: selectedConfig } as MultiDashboardConfig
117
- return await loadData(newConfig)
118
- }
119
-
120
- if (!initial) return <Loading />
121
- return <CdcDashboard isEditor={isEditor} isDebug={isDebug} initialState={initial} />
122
- }
123
-
124
- export default MultiDashboardWrapper
1
+ import { useEffect, useState } from 'react'
2
+ import CdcDashboard from './CdcDashboardComponent'
3
+ import { MultiDashboardConfig } from './types/MultiDashboard'
4
+ import Loading from '@cdc/core/components/Loading'
5
+ import defaults from './data/initial-state'
6
+ import { processData } from './helpers/processData'
7
+ import { getVizKeys } from './helpers/getVizKeys'
8
+ import { processDataLegacy } from './helpers/processDataLegacy'
9
+ import { WCMSProps } from '@cdc/core/types/WCMSProps'
10
+ import { initialState } from './DashboardContext'
11
+ import { getUpdateConfig } from './helpers/getUpdateConfig'
12
+ import { InitialState } from './types/InitialState'
13
+ import { DashboardConfig } from './types/DashboardConfig'
14
+ import _ from 'lodash'
15
+
16
+ type MultiDashboardProps = Omit<WCMSProps, 'configUrl'> & {
17
+ configUrl?: string
18
+ config?: MultiDashboardConfig
19
+ }
20
+
21
+ const MultiDashboardWrapper: React.FC<MultiDashboardProps> = ({ configUrl, config: editorConfig, isEditor, isDebug }) => {
22
+ const [initial, setInitial] = useState<InitialState>(undefined)
23
+
24
+ const getSelectedConfig = (config: MultiDashboardConfig, selectedConfig?: string): number | null => {
25
+ if (!config.multiDashboards) return null
26
+ // TODO: if query parameter select based on query parameter
27
+ if (selectedConfig) {
28
+ const foundConfig = Object.values(config.multiDashboards).findIndex(({ label }) => {
29
+ return label === selectedConfig
30
+ })
31
+ if (foundConfig > -1) return foundConfig
32
+ }
33
+ // else select the first available
34
+ return 0
35
+ }
36
+
37
+ const formatInitialState = (newConfig: MultiDashboardConfig | DashboardConfig, datasets: Record<string, Object[]>) => {
38
+ const [config, filteredData] = getUpdateConfig(initialState)(newConfig, datasets)
39
+ return { ...initialState, config, filteredData, data: datasets }
40
+ }
41
+
42
+ const loadConfig = async (selectedConfig?: string) => {
43
+ const _config: MultiDashboardConfig = editorConfig || (await (await fetch(configUrl)).json())
44
+ const selected = getSelectedConfig(_config, selectedConfig)
45
+
46
+ const { newConfig, datasets } = selected !== null ? await loadMultiDashboard(_config, selected) : await loadSingleDashboard(_config)
47
+ setInitial(formatInitialState(newConfig, datasets))
48
+ }
49
+
50
+ useEffect(() => {
51
+ loadConfig()
52
+ }, [])
53
+
54
+ const loadData = async (initialConfig: DashboardConfig | MultiDashboardConfig) => {
55
+ let newConfig = { ...initialConfig }
56
+ let datasets: Record<string, Object[]> = {}
57
+ await Promise.all(
58
+ Object.keys(initialConfig.datasets).map(async key => {
59
+ const data = await processData(initialConfig.datasets[key], initialConfig.filterBehavior)
60
+ datasets[key] = data || []
61
+ })
62
+ )
63
+
64
+ getVizKeys(newConfig).forEach(vizKey => {
65
+ newConfig.visualizations[vizKey].formattedData = datasets[newConfig.visualizations[vizKey].dataKey]
66
+ })
67
+
68
+ Object.keys(datasets).forEach(key => {
69
+ newConfig.datasets[key].data = datasets[key]
70
+ })
71
+ return { newConfig, datasets }
72
+ }
73
+
74
+ const loadSingleDashboard = async config => {
75
+ let newConfig = { ...defaults, ...config } as DashboardConfig
76
+
77
+ if (config.datasets) {
78
+ return await loadData(newConfig)
79
+ } else {
80
+ const dataKey = newConfig.dataFileName || 'backwards-compatibility'
81
+ const data = await processDataLegacy(config)
82
+
83
+ const datasetsFull = {}
84
+ datasetsFull[dataKey] = {
85
+ data,
86
+ dataDescription: newConfig.dataDescription
87
+ }
88
+ newConfig.datasets = datasetsFull
89
+
90
+ getVizKeys(newConfig).forEach(vizKey => {
91
+ const newData = { dataKey, ..._.pick(newConfig, 'dataDescription', 'formattedData') }
92
+ newConfig.visualizations[vizKey] = { ...newConfig.visualizations[vizKey], ...newData }
93
+ })
94
+
95
+ const blankFields = { data: [], dataUrl: '', dataFileName: '', dataFileSourceType: '', dataDescription: [], formattedData: [] }
96
+ newConfig = { ...newConfig, ...blankFields }
97
+
98
+ if (newConfig.dashboard.filters) {
99
+ const dashboard = { ...newConfig.dashboard }
100
+ // replace filters with sharedFilters
101
+ if (!dashboard.sharedFilters) dashboard.sharedFilters = []
102
+ const filters = dashboard.filters.map(filter => {
103
+ return { ...filter, key: filter.label, showDropdown: true, usedBy: getVizKeys(newConfig) }
104
+ })
105
+ dashboard.sharedFilters = [...dashboard.sharedFilters, ...filters]
106
+ newConfig.dashboard = { ...dashboard, filters: undefined }
107
+ }
108
+
109
+ const datasets: Record<string, Object[]> = { [dataKey]: data }
110
+ return { newConfig, datasets }
111
+ }
112
+ }
113
+
114
+ const loadMultiDashboard = async (multiConfig: MultiDashboardConfig, selectedConfig: number) => {
115
+ const selectedDashboard = multiConfig.multiDashboards[selectedConfig]
116
+ let newConfig = { ...defaults, ...multiConfig, ...selectedDashboard, multiDashboards: multiConfig.multiDashboards, activeDashboard: selectedConfig } as MultiDashboardConfig
117
+ return await loadData(newConfig)
118
+ }
119
+
120
+ if (!initial) return <Loading />
121
+ return <CdcDashboard isEditor={isEditor} isDebug={isDebug} initialState={initial} />
122
+ }
123
+
124
+ export default MultiDashboardWrapper