@cdc/dashboard 4.25.8 → 4.25.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.
- package/dist/{cdcdashboard-fce76882.es.js → cdcdashboard-BnB1QM5d.es.js} +6 -13
- package/dist/{cdcdashboard-c55ac1ea.es.js → cdcdashboard-D6CG2-Hb.es.js} +5 -12
- package/dist/{cdcdashboard-31a33da1.es.js → cdcdashboard-MXgURbdZ.es.js} +6 -13
- package/dist/{cdcdashboard-1a1724a1.es.js → cdcdashboard-dgT_1dIT.es.js} +136 -151
- package/dist/cdcdashboard.js +80040 -75976
- package/examples/api-test/categories.json +18 -0
- package/examples/api-test/chart-data.json +602 -0
- package/examples/api-test/topics.json +47 -0
- package/examples/api-test/years.json +22 -0
- package/examples/markup-axis-label.json +4167 -0
- package/examples/private/DEV-10538.json +407 -0
- package/examples/private/DEV-11405.json +39112 -0
- package/examples/private/big-dashboard.json +39112 -0
- package/examples/private/brfs-2.json +1532 -0
- package/examples/private/brfs.json +2128 -2138
- package/examples/private/clade-2.json +430 -0
- package/examples/private/delete.json +32919 -0
- package/examples/private/diabetes.json +5582 -0
- package/examples/private/example-2.json +49796 -0
- package/examples/private/group-legend-test.json +328 -0
- package/examples/private/map.json +1211 -0
- package/examples/private/markup-footer/burden_toolkit_mortality_diabetes_attributable_deaths_data.csv +14041 -0
- package/examples/private/markup-footer/burden_toolkit_mortality_diabetes_attributable_deaths_per_100000_data.csv +14041 -0
- package/examples/private/markup-footer/burden_toolkit_mortality_qaly_data.csv +18721 -0
- package/examples/private/markup-footer/burden_toolkit_mortality_yll_data.csv +18721 -0
- package/examples/private/markup-footer/mortality-deaths-footnotes-age.csv +3 -0
- package/examples/private/markup-variables.json +1451 -0
- package/examples/private/markup.json +5471 -0
- package/examples/private/mpox.json +38128 -0
- package/examples/private/north-dakota.json +1132 -0
- package/examples/private/ophdst.json +38754 -0
- package/examples/private/pedro.json +1 -0
- package/examples/private/pivot.json +683 -0
- package/examples/private/reset.json +32920 -0
- package/examples/private/sewershed.json +435 -0
- package/examples/private/tobacco.json +1938 -0
- package/examples/test-api-filter-reset.json +132 -0
- package/index.html +2 -2
- package/package.json +16 -10
- package/src/CdcDashboard.tsx +1 -3
- package/src/CdcDashboardComponent.tsx +34 -16
- package/src/DashboardContext.tsx +5 -1
- package/src/_stories/Dashboard.API.stories.tsx +62 -0
- package/src/_stories/Dashboard.stories.tsx +492 -472
- package/src/_stories/_mock/api/cessation.json +1 -0
- package/src/_stories/_mock/api/data-explorer.json +1 -0
- package/src/_stories/_mock/api/explore-by-location.json +1 -0
- package/src/_stories/_mock/api/explore-by-topic.json +1 -0
- package/src/_stories/_mock/api/legislation.json +1 -0
- package/src/_stories/_mock/api/oral-health-data.json +1 -0
- package/src/_stories/_mock/custom-order-new-values.json +116 -0
- package/src/components/CollapsibleVisualizationRow.tsx +1 -1
- package/src/components/DashboardFilters/DashboardFilters.tsx +34 -23
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +29 -12
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +81 -112
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +82 -52
- package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +130 -31
- package/src/components/DashboardFilters/_stories/DashboardFilters.stories.tsx +80 -21
- package/src/components/DataDesignerModal.tsx +227 -210
- package/src/components/Header/Header.tsx +13 -12
- package/src/components/Toggle/Toggle.tsx +48 -47
- package/src/components/VisualizationRow.tsx +13 -6
- package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +2 -0
- package/src/components/Widget/Widget.tsx +47 -18
- package/src/helpers/addValuesToDashboardFilters.ts +111 -60
- package/src/helpers/apiFilterHelpers.ts +190 -166
- package/src/helpers/filterData.ts +52 -7
- package/src/helpers/filterResetHelpers.ts +102 -0
- package/src/helpers/formatConfigBeforeSave.ts +137 -0
- package/src/helpers/getVizConfig.ts +36 -18
- package/src/helpers/loadAPIFilters.ts +109 -99
- package/src/helpers/reloadURLHelpers.ts +1 -1
- package/src/helpers/tests/filterResetHelpers.test.ts +532 -0
- package/src/helpers/tests/formatConfigBeforeSave.test.ts +69 -0
- package/src/index.tsx +1 -1
- package/src/scss/editor-panel.scss +3 -431
- package/src/scss/grid.scss +7 -5
- package/src/scss/main.scss +1 -24
- package/src/store/errorMessage/errorMessage.reducer.ts +1 -1
- package/src/types/DashboardFilters.ts +9 -8
- package/src/types/InitialState.ts +12 -12
- package/vite.config.js +1 -1
- package/vitest.config.ts +16 -0
- package/src/coreStyles_dashboard.scss +0 -3
- package/src/helpers/getAutoLoadVisualization.ts +0 -11
- package/src/scss/mixins.scss +0 -47
- package/src/scss/variables.scss +0 -5
- /package/dist/{cdcdashboard-548642e6.es.js → cdcdashboard-Ct2SB0vL.es.js} +0 -0
|
@@ -1,210 +1,227 @@
|
|
|
1
|
-
import { useGlobalContext } from '@cdc/core/components/GlobalContext'
|
|
2
|
-
import DataDesigner from '@cdc/core/components/managers/DataDesigner'
|
|
3
|
-
import { useContext, useMemo, useState } from 'react'
|
|
4
|
-
import { DashboardContext, DashboardDispatchContext } from '../DashboardContext'
|
|
5
|
-
import Modal from '@cdc/core/components/ui/Modal'
|
|
6
|
-
import Loader from '@cdc/core/components/Loader'
|
|
7
|
-
import { CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
|
|
8
|
-
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
9
|
-
import _ from 'lodash'
|
|
10
|
-
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
11
|
-
import DataTransform from '@cdc/core/helpers/DataTransform'
|
|
12
|
-
import { ConfigureData } from '@cdc/core/types/ConfigureData'
|
|
13
|
-
import Icon from '@cdc/core/components/ui/Icon'
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const [
|
|
27
|
-
const [
|
|
28
|
-
const [
|
|
29
|
-
const [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (isUpdatingVisualization) {
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
dispatch({ type: '
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
1
|
+
import { useGlobalContext } from '@cdc/core/components/GlobalContext'
|
|
2
|
+
import DataDesigner from '@cdc/core/components/managers/DataDesigner'
|
|
3
|
+
import { useContext, useMemo, useState } from 'react'
|
|
4
|
+
import { DashboardContext, DashboardDispatchContext } from '../DashboardContext'
|
|
5
|
+
import Modal from '@cdc/core/components/ui/Modal'
|
|
6
|
+
import Loader from '@cdc/core/components/Loader'
|
|
7
|
+
import { CheckBox, Select } from '@cdc/core/components/EditorPanel/Inputs'
|
|
8
|
+
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
9
|
+
import _ from 'lodash'
|
|
10
|
+
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
11
|
+
import DataTransform from '@cdc/core/helpers/DataTransform'
|
|
12
|
+
import { ConfigureData } from '@cdc/core/types/ConfigureData'
|
|
13
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
14
|
+
|
|
15
|
+
type DataDesignerModalProps = {
|
|
16
|
+
rowIndex: number
|
|
17
|
+
vizKey?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const DataDesignerModal: React.FC<DataDesignerModalProps> = ({ vizKey, rowIndex }) => {
|
|
21
|
+
const { config } = useContext(DashboardContext)
|
|
22
|
+
const { overlay } = useGlobalContext()
|
|
23
|
+
const transform = new DataTransform()
|
|
24
|
+
const dispatch = useContext(DashboardDispatchContext)
|
|
25
|
+
const [canContinue, setCanContinue] = useState(false)
|
|
26
|
+
const [useRow, setUseRow] = useState(!vizKey)
|
|
27
|
+
const [multiViz, setMultiViz] = useState(!!config.rows[rowIndex].multiVizColumn)
|
|
28
|
+
const [errorMessage, setErrorMessage] = useState('')
|
|
29
|
+
const [loadingAPIData, setLoadingAPIData] = useState(false)
|
|
30
|
+
|
|
31
|
+
const isUpdatingVisualization = useMemo(() => {
|
|
32
|
+
return !!vizKey && !useRow
|
|
33
|
+
}, [vizKey, useRow])
|
|
34
|
+
|
|
35
|
+
const configureData = useMemo(() => {
|
|
36
|
+
let baseConfig
|
|
37
|
+
if (isUpdatingVisualization) {
|
|
38
|
+
baseConfig = config.visualizations[vizKey]
|
|
39
|
+
} else {
|
|
40
|
+
baseConfig = config.rows[rowIndex]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Directly attach data from datasets
|
|
44
|
+
const data = baseConfig?.dataKey ? config.datasets[baseConfig.dataKey]?.data : undefined
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...baseConfig,
|
|
48
|
+
data
|
|
49
|
+
}
|
|
50
|
+
}, [config.visualizations, config.datasets, config.rows, rowIndex, isUpdatingVisualization])
|
|
51
|
+
|
|
52
|
+
const fetchData = async datasetKey => {
|
|
53
|
+
const { data, dataUrl } = config.datasets[datasetKey]
|
|
54
|
+
if (!dataUrl) return data
|
|
55
|
+
let newData = data
|
|
56
|
+
const noCachedData = dataUrl && !data
|
|
57
|
+
const dataSetChanged = datasetKey !== configureData.dataKey
|
|
58
|
+
setErrorMessage('')
|
|
59
|
+
if (dataSetChanged || noCachedData) {
|
|
60
|
+
setLoadingAPIData(true)
|
|
61
|
+
try {
|
|
62
|
+
newData = await fetchRemoteData(dataUrl)
|
|
63
|
+
newData = transform.autoStandardize(newData)
|
|
64
|
+
} catch (e) {
|
|
65
|
+
setErrorMessage('There was an issue loading the data source. Please check the datasource URL and try again.')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
setLoadingAPIData(false)
|
|
69
|
+
}
|
|
70
|
+
return newData
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const updateConfigureData = (newConfigureData: Partial<ConfigureData>) => {
|
|
74
|
+
if (isUpdatingVisualization) {
|
|
75
|
+
dispatch({ type: 'UPDATE_VISUALIZATION', payload: { vizKey, configureData: newConfigureData } })
|
|
76
|
+
} else {
|
|
77
|
+
dispatch({ type: 'UPDATE_ROW', payload: { rowIndex, rowData: newConfigureData } })
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const removeDatasetsFromVisualizations = () => {
|
|
82
|
+
const columnVisualizations = config.rows[rowIndex].columns.map(column => column.widget).filter(Boolean)
|
|
83
|
+
columnVisualizations.forEach(currentVisualizationKey => {
|
|
84
|
+
dispatch({ type: 'RESET_VISUALIZATION', payload: { vizKey: currentVisualizationKey } })
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const changeDataset = async ({ target: { value } }) => {
|
|
89
|
+
if (!isUpdatingVisualization) removeDatasetsFromVisualizations()
|
|
90
|
+
const newData = value === '' ? {} : await fetchData(value)
|
|
91
|
+
const newConfigureData = {
|
|
92
|
+
dataDescription: {
|
|
93
|
+
horizontal: false
|
|
94
|
+
},
|
|
95
|
+
formattedData: undefined,
|
|
96
|
+
dataKey: value,
|
|
97
|
+
data: newData
|
|
98
|
+
} as ConfigureData
|
|
99
|
+
updateConfigureData(newConfigureData)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const updateDescriptionProp = async (key, value) => {
|
|
103
|
+
const datasetKey = configureData.dataKey
|
|
104
|
+
const newData = configureData.data || (await fetchData(datasetKey))
|
|
105
|
+
|
|
106
|
+
const dataDescription = { ...configureData.dataDescription, [key]: value }
|
|
107
|
+
|
|
108
|
+
const newConfigureData = {
|
|
109
|
+
data: newData,
|
|
110
|
+
dataDescription,
|
|
111
|
+
formattedData: transform.developerStandardize(newData, dataDescription)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
updateConfigureData(newConfigureData)
|
|
115
|
+
setCanContinue(true)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const setMultiVizColumn = (column: string) => {
|
|
119
|
+
if (column !== '') {
|
|
120
|
+
dispatch({ type: 'UPDATE_ROW', payload: { rowIndex, rowData: { multiVizColumn: column } } })
|
|
121
|
+
setCanContinue(true)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const setExpandCollapseAllButtons = (selection: boolean) => {
|
|
126
|
+
dispatch({ type: 'UPDATE_ROW', payload: { rowIndex, rowData: { expandCollapseAllButtons: selection } } })
|
|
127
|
+
setCanContinue(true)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<Modal>
|
|
132
|
+
<Modal.Content>
|
|
133
|
+
{loadingAPIData && <Loader fullScreen />}
|
|
134
|
+
<div className='dataset-selector-container'>
|
|
135
|
+
Select a dataset:
|
|
136
|
+
<select
|
|
137
|
+
className='dataset-selector cove-form-select'
|
|
138
|
+
value={configureData.dataKey || ''}
|
|
139
|
+
onChange={changeDataset}
|
|
140
|
+
>
|
|
141
|
+
<option value=''>Select a dataset</option>
|
|
142
|
+
{config.datasets &&
|
|
143
|
+
Object.keys(config.datasets).map(datasetKey => (
|
|
144
|
+
<option key={datasetKey} value={datasetKey}>
|
|
145
|
+
{datasetKey}
|
|
146
|
+
</option>
|
|
147
|
+
))}
|
|
148
|
+
</select>
|
|
149
|
+
{vizKey && (
|
|
150
|
+
// only shows for visualizations
|
|
151
|
+
<CheckBox
|
|
152
|
+
label='Apply To Row'
|
|
153
|
+
value={useRow}
|
|
154
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
155
|
+
setUseRow(value)
|
|
156
|
+
changeDataset({ target: { value: configureData.dataKey } })
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
)}
|
|
160
|
+
</div>
|
|
161
|
+
{errorMessage && <p className='text-danger'>{errorMessage}</p>}
|
|
162
|
+
{configureData.dataKey && (
|
|
163
|
+
<DataDesigner
|
|
164
|
+
{...{
|
|
165
|
+
configureData,
|
|
166
|
+
visualizationKey: vizKey,
|
|
167
|
+
updateDescriptionProp
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
)}
|
|
171
|
+
{useRow && !!configureData.dataKey ? (
|
|
172
|
+
!multiViz ? (
|
|
173
|
+
<CheckBox
|
|
174
|
+
label='Configure Multiple Visualizations'
|
|
175
|
+
value={multiViz}
|
|
176
|
+
tooltip={
|
|
177
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
178
|
+
<Tooltip.Target>
|
|
179
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
180
|
+
</Tooltip.Target>
|
|
181
|
+
<Tooltip.Content>
|
|
182
|
+
<p>
|
|
183
|
+
You can select a column where for each unique value in the column the configuration for the row
|
|
184
|
+
will be repeated in to the data preview.
|
|
185
|
+
</p>
|
|
186
|
+
</Tooltip.Content>
|
|
187
|
+
</Tooltip>
|
|
188
|
+
}
|
|
189
|
+
updateField={(section, subsection, fieldName, value) => {
|
|
190
|
+
if (canContinue && value === true) setCanContinue(false)
|
|
191
|
+
setMultiViz(value)
|
|
192
|
+
}}
|
|
193
|
+
/>
|
|
194
|
+
) : (
|
|
195
|
+
<>
|
|
196
|
+
<Select
|
|
197
|
+
options={Object.keys(config.datasets[configureData.dataKey]?.data[0] || {})}
|
|
198
|
+
value={config.rows[rowIndex].multiVizColumn}
|
|
199
|
+
label='Multi-Visualization Column'
|
|
200
|
+
initial='--Select--'
|
|
201
|
+
updateField={(section, subsection, fieldName, value) => setMultiVizColumn(value)}
|
|
202
|
+
required
|
|
203
|
+
/>
|
|
204
|
+
<CheckBox
|
|
205
|
+
value={config.rows[rowIndex].expandCollapseAllButtons}
|
|
206
|
+
label=' Add Expand/Collapse All buttons'
|
|
207
|
+
fieldName=''
|
|
208
|
+
updateField={(section, subsection, fieldName, value) => setExpandCollapseAllButtons(value)}
|
|
209
|
+
/>
|
|
210
|
+
</>
|
|
211
|
+
)
|
|
212
|
+
) : (
|
|
213
|
+
<></>
|
|
214
|
+
)}
|
|
215
|
+
{canContinue && (
|
|
216
|
+
<button
|
|
217
|
+
style={{ margin: '1em', display: 'block' }}
|
|
218
|
+
className='cove-button'
|
|
219
|
+
onClick={() => overlay?.actions.toggleOverlay()}
|
|
220
|
+
>
|
|
221
|
+
Continue
|
|
222
|
+
</button>
|
|
223
|
+
)}
|
|
224
|
+
</Modal.Content>
|
|
225
|
+
</Modal>
|
|
226
|
+
)
|
|
227
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { useContext, useRef } from 'react'
|
|
2
|
+
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
3
3
|
import { DashboardContext, DashboardDispatchContext } from '../../DashboardContext'
|
|
4
4
|
|
|
5
5
|
import './index.scss'
|
|
@@ -20,7 +20,7 @@ const Header = (props: HeaderProps) => {
|
|
|
20
20
|
const dispatch = useContext(DashboardDispatchContext)
|
|
21
21
|
const back = () => {
|
|
22
22
|
if (!visualizationKey) return
|
|
23
|
-
const newConfig =
|
|
23
|
+
const newConfig = cloneConfig(config)
|
|
24
24
|
newConfig.visualizations[visualizationKey].editing = false
|
|
25
25
|
dispatch({ type: 'SET_CONFIG', payload: newConfig })
|
|
26
26
|
|
|
@@ -49,28 +49,29 @@ const Header = (props: HeaderProps) => {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const convertStateToConfig = () => {
|
|
52
|
-
const strippedState =
|
|
52
|
+
const strippedState = cloneConfig(config)
|
|
53
53
|
delete strippedState.newViz
|
|
54
54
|
delete strippedState.runtime
|
|
55
55
|
|
|
56
56
|
return strippedState
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
const parsedData = convertStateToConfig()
|
|
59
|
+
const configStringRef = useRef<string>()
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
// Only update parent when config content actually changes (not just reference)
|
|
62
|
+
const configString = JSON.stringify(convertStateToConfig())
|
|
63
|
+
if (configStringRef.current !== configString) {
|
|
64
|
+
configStringRef.current = configString
|
|
64
65
|
|
|
66
|
+
// Emit the data in a regular JS event so it can be consumed by anything.
|
|
67
|
+
const event = new CustomEvent('updateVizConfig', { detail: configString })
|
|
65
68
|
window.dispatchEvent(event)
|
|
66
69
|
|
|
67
70
|
// Pass up to Editor if needed
|
|
68
71
|
if (setParentConfig) {
|
|
69
|
-
setParentConfig(
|
|
72
|
+
setParentConfig(JSON.parse(configString))
|
|
70
73
|
}
|
|
71
|
-
|
|
72
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
-
}, [config])
|
|
74
|
+
}
|
|
74
75
|
|
|
75
76
|
const handleCheck = e => {
|
|
76
77
|
const { checked } = e.currentTarget
|
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
import { ConfigRow } from '../../types/ConfigRow'
|
|
2
|
-
import { AnyVisualization } from '@cdc/core/types/Visualization'
|
|
3
|
-
import { getIcon } from '../../helpers/iconHash'
|
|
4
|
-
import { labelHash } from '@cdc/core/helpers/labelHash'
|
|
5
|
-
import './toggle-style.css'
|
|
6
|
-
import _ from 'lodash'
|
|
7
|
-
|
|
8
|
-
type ToggleProps = {
|
|
9
|
-
active: number
|
|
10
|
-
row: ConfigRow
|
|
11
|
-
visualizations: Record<string, AnyVisualization>
|
|
12
|
-
setToggled: (colIndex: number) => void
|
|
13
|
-
}
|
|
14
|
-
const Toggle: React.FC<ToggleProps> = ({ active, row, visualizations, setToggled, text }) => {
|
|
15
|
-
const selectItem = (colIndex, e = null) => {
|
|
16
|
-
if (e?.key && e.key !== 'Enter') return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
import { ConfigRow } from '../../types/ConfigRow'
|
|
2
|
+
import { AnyVisualization } from '@cdc/core/types/Visualization'
|
|
3
|
+
import { getIcon } from '../../helpers/iconHash'
|
|
4
|
+
import { labelHash } from '@cdc/core/helpers/labelHash'
|
|
5
|
+
import './toggle-style.css'
|
|
6
|
+
import _ from 'lodash'
|
|
7
|
+
|
|
8
|
+
type ToggleProps = {
|
|
9
|
+
active: number
|
|
10
|
+
row: ConfigRow
|
|
11
|
+
visualizations: Record<string, AnyVisualization>
|
|
12
|
+
setToggled: (colIndex: number) => void
|
|
13
|
+
}
|
|
14
|
+
const Toggle: React.FC<ToggleProps> = ({ active, row, visualizations, setToggled, text }) => {
|
|
15
|
+
const selectItem = (colIndex, e = null) => {
|
|
16
|
+
if (e?.key && e.key !== 'Enter' && e.key !== ' ') return
|
|
17
|
+
if (e?.key === ' ') e.preventDefault() // Prevent page scroll
|
|
18
|
+
setToggled(colIndex)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className='toggle-component' role='radiogroup' aria-label='Visualization options'>
|
|
23
|
+
{row.columns.map((col, colIndex) => {
|
|
24
|
+
if (!col.widget) return null
|
|
25
|
+
const type = visualizations[col.widget].type
|
|
26
|
+
// Get the column toggele Text or default to the type
|
|
27
|
+
const text = col.toggleName ? col.toggleName : labelHash[type]
|
|
28
|
+
const selected = colIndex === active
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
role='radio'
|
|
32
|
+
className={selected ? 'selected' : ''}
|
|
33
|
+
key={colIndex}
|
|
34
|
+
onClick={() => selectItem(colIndex)}
|
|
35
|
+
onKeyUp={e => selectItem(colIndex, e)}
|
|
36
|
+
aria-checked={selected}
|
|
37
|
+
tabIndex={0}
|
|
38
|
+
aria-label={`Toggle ${text}`}
|
|
39
|
+
>
|
|
40
|
+
<span aria-hidden='true'>{getIcon(visualizations[col.widget])}</span> <span>{text}</span>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
})}
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default Toggle
|
|
@@ -20,6 +20,7 @@ import CdcChart from '@cdc/chart/src/CdcChartComponent'
|
|
|
20
20
|
import ExpandCollapseButtons from './ExpandCollapseButtons'
|
|
21
21
|
import { ChartConfig } from '@cdc/chart/src/types/ChartConfig'
|
|
22
22
|
import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
|
|
23
|
+
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
23
24
|
|
|
24
25
|
type VisualizationWrapperProps = {
|
|
25
26
|
allExpanded: boolean
|
|
@@ -196,12 +197,15 @@ const VisualizationRow: React.FC<VizRowProps> = ({
|
|
|
196
197
|
href={`#data-table-${dataKey}`}
|
|
197
198
|
className='margin-left-href'
|
|
198
199
|
onClick={() => {
|
|
199
|
-
publishAnalyticsEvent(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
publishAnalyticsEvent({
|
|
201
|
+
vizType: visualizationConfig.type,
|
|
202
|
+
vizSubType: getVizSubType(visualizationConfig),
|
|
203
|
+
eventType: `link_to_data_table_click`,
|
|
204
|
+
eventAction: 'click',
|
|
205
|
+
eventLabel: `${interactionLabel}`,
|
|
206
|
+
vizTitle: getVizTitle(visualizationConfig),
|
|
207
|
+
specifics: `table: #data-table-${dataKey}`
|
|
208
|
+
})
|
|
205
209
|
}}
|
|
206
210
|
>
|
|
207
211
|
{dataKey} (Go to Table)
|
|
@@ -277,6 +281,7 @@ const VisualizationRow: React.FC<VizRowProps> = ({
|
|
|
277
281
|
updateChildConfig(col.widget, newConfig)
|
|
278
282
|
}}
|
|
279
283
|
isDashboard={true}
|
|
284
|
+
interactionLabel={interactionLabel}
|
|
280
285
|
/>
|
|
281
286
|
)}
|
|
282
287
|
{type === 'waffle-chart' && (
|
|
@@ -294,10 +299,12 @@ const VisualizationRow: React.FC<VizRowProps> = ({
|
|
|
294
299
|
<CdcMarkupInclude
|
|
295
300
|
key={col.widget}
|
|
296
301
|
config={visualizationConfig}
|
|
302
|
+
datasets={config.datasets}
|
|
297
303
|
isDashboard={true}
|
|
298
304
|
setConfig={newConfig => {
|
|
299
305
|
updateChildConfig(col.widget, newConfig)
|
|
300
306
|
}}
|
|
307
|
+
interactionLabel={interactionLabel}
|
|
301
308
|
/>
|
|
302
309
|
)}
|
|
303
310
|
{type === 'filtered-text' && (
|