@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
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import Footnotes from '@cdc/core/types/Footnotes'
|
|
2
|
+
import { AnyVisualization, Visualization } from '@cdc/core/types/Visualization'
|
|
3
|
+
import { DashboardConfig } from '../types/DashboardConfig'
|
|
4
|
+
import { removeDashboardFilter } from './removeDashboardFilter'
|
|
5
|
+
import _ from 'lodash'
|
|
6
|
+
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
7
|
+
|
|
8
|
+
const cleanDashboardFootnotes = (config: DashboardConfig) => {
|
|
9
|
+
if (config.visualizations) {
|
|
10
|
+
Object.keys(config.visualizations).forEach(vizKey => {
|
|
11
|
+
const viz = config.visualizations[vizKey] as any
|
|
12
|
+
if (viz.footnotes) {
|
|
13
|
+
delete viz.footnotes.data
|
|
14
|
+
delete viz.footnotes.formattedData
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const cleanDashboardData = (config: DashboardConfig) => {
|
|
21
|
+
if (config.datasets) {
|
|
22
|
+
Object.keys(config.datasets).forEach(datasetKey => {
|
|
23
|
+
delete config.datasets[datasetKey].formattedData
|
|
24
|
+
if (config.datasets[datasetKey].dataUrl) {
|
|
25
|
+
delete config.datasets[datasetKey].data
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
if (config.visualizations) {
|
|
30
|
+
Object.keys(config.visualizations).forEach(vizKey => {
|
|
31
|
+
config.visualizations[vizKey] = _.omit(config.visualizations[vizKey], [
|
|
32
|
+
'runtime',
|
|
33
|
+
'formattedData',
|
|
34
|
+
'data',
|
|
35
|
+
'editing',
|
|
36
|
+
'originalFormattedData'
|
|
37
|
+
]) as any
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
if (config.rows) {
|
|
41
|
+
config.rows.forEach((row, i) => {
|
|
42
|
+
if (row.dataKey) {
|
|
43
|
+
config.rows[i] = _.omit(row, ['data', 'formattedData'])
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const cleanSharedFilters = (config: DashboardConfig) => {
|
|
50
|
+
if (config.dashboard?.sharedFilters) {
|
|
51
|
+
const recursiveRemoveFilters = (sharedFilters, visualizations: Record<string, AnyVisualization>) => {
|
|
52
|
+
const usedFilters = _.uniq(
|
|
53
|
+
Object.values(visualizations).reduce((acc, viz) => {
|
|
54
|
+
if (viz.type === 'dashboardFilters') {
|
|
55
|
+
acc = acc.concat(viz.sharedFilterIndexes)
|
|
56
|
+
}
|
|
57
|
+
return acc
|
|
58
|
+
}, [])
|
|
59
|
+
)
|
|
60
|
+
for (let index = 0; index < sharedFilters.length; index++) {
|
|
61
|
+
const filter = sharedFilters[index]
|
|
62
|
+
if (!usedFilters.includes(index)) {
|
|
63
|
+
const [newSharedFilters, newVisualizations] = removeDashboardFilter(
|
|
64
|
+
index,
|
|
65
|
+
config.dashboard.sharedFilters,
|
|
66
|
+
config.visualizations
|
|
67
|
+
)
|
|
68
|
+
config.dashboard.sharedFilters = newSharedFilters
|
|
69
|
+
config.visualizations = newVisualizations
|
|
70
|
+
recursiveRemoveFilters(newSharedFilters, newVisualizations)
|
|
71
|
+
break
|
|
72
|
+
} else {
|
|
73
|
+
delete config.dashboard.sharedFilters[index].active
|
|
74
|
+
if (filter.subGrouping) delete config.dashboard.sharedFilters[index].subGrouping.active
|
|
75
|
+
if (filter.type === 'urlfilter') {
|
|
76
|
+
delete config.dashboard.sharedFilters[index].values
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
recursiveRemoveFilters(config.dashboard.sharedFilters, config.visualizations)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const cleanVisualizationFilters = (config: DashboardConfig) => {
|
|
87
|
+
if (config.visualizations) {
|
|
88
|
+
Object.keys(config.visualizations).forEach(vizKey => {
|
|
89
|
+
const viz = config.visualizations[vizKey] as any
|
|
90
|
+
const vizFilters = viz.filters || []
|
|
91
|
+
vizFilters.forEach((_filter, index) => {
|
|
92
|
+
delete viz.filters[index].active
|
|
93
|
+
delete viz.filters[index].values
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const removeRuntimeDataURLs = (config: DashboardConfig) => {
|
|
100
|
+
if (config.datasets) {
|
|
101
|
+
Object.keys(config.datasets).forEach(datasetKey => {
|
|
102
|
+
delete config.datasets[datasetKey].runtimeDataUrl
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const stripConfig = configToStrip => {
|
|
108
|
+
const strippedConfig = cloneConfig(configToStrip)
|
|
109
|
+
if (strippedConfig.type === 'dashboard') {
|
|
110
|
+
if (strippedConfig.multiDashboards) {
|
|
111
|
+
strippedConfig.multiDashboards.forEach((multiDashboard, i) => {
|
|
112
|
+
cleanDashboardData(strippedConfig.multiDashboards[i])
|
|
113
|
+
cleanSharedFilters(strippedConfig.multiDashboards[i])
|
|
114
|
+
cleanDashboardFootnotes(strippedConfig.multiDashboards[i])
|
|
115
|
+
cleanVisualizationFilters(strippedConfig.multiDashboards[i])
|
|
116
|
+
})
|
|
117
|
+
delete strippedConfig.dashboard
|
|
118
|
+
delete strippedConfig.rows
|
|
119
|
+
delete strippedConfig.visualizations
|
|
120
|
+
delete strippedConfig.label
|
|
121
|
+
}
|
|
122
|
+
delete strippedConfig.activeDashboard
|
|
123
|
+
cleanDashboardData(strippedConfig)
|
|
124
|
+
cleanSharedFilters(strippedConfig)
|
|
125
|
+
cleanDashboardFootnotes(strippedConfig)
|
|
126
|
+
cleanVisualizationFilters(strippedConfig)
|
|
127
|
+
removeRuntimeDataURLs(strippedConfig)
|
|
128
|
+
} else {
|
|
129
|
+
delete strippedConfig.runtime
|
|
130
|
+
delete strippedConfig.formattedData
|
|
131
|
+
if (strippedConfig.dataUrl) {
|
|
132
|
+
delete strippedConfig.data
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return strippedConfig
|
|
137
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash'
|
|
2
|
+
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
2
3
|
import { MultiDashboardConfig } from '../types/MultiDashboard'
|
|
3
4
|
import DataTransform from '@cdc/core/helpers/DataTransform'
|
|
4
5
|
import { getApplicableFilters } from './getFilteredData'
|
|
@@ -7,7 +8,7 @@ import { AnyVisualization } from '@cdc/core/types/Visualization'
|
|
|
7
8
|
|
|
8
9
|
const transform = new DataTransform()
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
const getFootnotesVizConfig = (
|
|
11
12
|
visualizationConfig: AnyVisualization,
|
|
12
13
|
rowNumber: number,
|
|
13
14
|
config: MultiDashboardConfig,
|
|
@@ -23,7 +24,7 @@ export const getFootnotesVizConfig = (
|
|
|
23
24
|
const sharedFilters = config.dashboard.sharedFilters
|
|
24
25
|
const matchingFilters = sharedFilters.filter(f => f.usedBy?.includes(visualizationKey))
|
|
25
26
|
|
|
26
|
-
if (matchingFilters.length) {
|
|
27
|
+
if (matchingFilters.length && visualizationConfig.footnotes.data) {
|
|
27
28
|
visualizationConfig.footnotes.data = filterData(matchingFilters, data)
|
|
28
29
|
} else {
|
|
29
30
|
if (visualizationConfig.footnotes.data) {
|
|
@@ -44,7 +45,7 @@ export const getVizConfig = (
|
|
|
44
45
|
multiVizColumn?: string
|
|
45
46
|
): AnyVisualization => {
|
|
46
47
|
if (rowNumber === undefined) return {} as AnyVisualization
|
|
47
|
-
const visualizationConfig =
|
|
48
|
+
const visualizationConfig = cloneConfig(config.visualizations[visualizationKey])
|
|
48
49
|
const rowData = config.rows[rowNumber]
|
|
49
50
|
if (visualizationConfig.footnotes?.dataKey) {
|
|
50
51
|
visualizationConfig.footnotes.data = config.datasets[visualizationConfig.footnotes.dataKey]?.data
|
|
@@ -54,21 +55,36 @@ export const getVizConfig = (
|
|
|
54
55
|
Object.assign(visualizationConfig, _.pick(rowData, ['dataKey', 'dataDescription', 'formattedData', 'data']))
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (subGrouping) {
|
|
67
|
-
acc.push(subGrouping)
|
|
68
|
-
}
|
|
58
|
+
const sharedFilterColumns = config.dashboard.sharedFilters.reduce((acc, filter) => {
|
|
59
|
+
if (!filter.usedBy?.length || filter.usedBy?.includes(visualizationKey)) {
|
|
60
|
+
const apiFilter = filter.apiFilter
|
|
61
|
+
const colName = apiFilter?.textSelector || apiFilter?.valueSelector || filter.columnName
|
|
62
|
+
acc.push(colName)
|
|
63
|
+
const subGrouping =
|
|
64
|
+
apiFilter?.subgroupTextSelector || apiFilter?.subgroupValueSelector || filter.subGrouping?.columnName
|
|
65
|
+
if (subGrouping) {
|
|
66
|
+
acc.push(subGrouping)
|
|
69
67
|
}
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
}
|
|
69
|
+
return acc
|
|
70
|
+
}, [])
|
|
71
|
+
|
|
72
|
+
// Collect active dashboard filters for markup variable processing
|
|
73
|
+
// This allows markup variables to filter even when the viz isn't in usedBy
|
|
74
|
+
const activeDashboardFilters = config.dashboard.sharedFilters
|
|
75
|
+
.filter(filter => filter.active !== undefined && filter.active !== null && filter.active !== '')
|
|
76
|
+
.map(filter => ({
|
|
77
|
+
columnName: filter.columnName,
|
|
78
|
+
active: filter.active,
|
|
79
|
+
values: filter.values || []
|
|
80
|
+
}))
|
|
81
|
+
|
|
82
|
+
if (activeDashboardFilters.length > 0) {
|
|
83
|
+
visualizationConfig.dashboardFilters = activeDashboardFilters
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Download CSV button needs to know to include shared filter columns
|
|
87
|
+
if (visualizationConfig.table && config.dashboard.sharedFilters.length) {
|
|
72
88
|
visualizationConfig.table.sharedFilterColumns = sharedFilterColumns
|
|
73
89
|
}
|
|
74
90
|
|
|
@@ -82,7 +98,9 @@ export const getVizConfig = (
|
|
|
82
98
|
}
|
|
83
99
|
} else {
|
|
84
100
|
const dataKey = visualizationConfig.dataKey || 'backwards-compatibility'
|
|
85
|
-
|
|
101
|
+
// Markup-includes need data even when shared filters exist (for markup variables)
|
|
102
|
+
const shouldClearData = sharedFilterColumns.length && visualizationConfig.type !== 'markup-include'
|
|
103
|
+
visualizationConfig.data = shouldClearData ? [] : data[dataKey] || []
|
|
86
104
|
if (visualizationConfig.formattedData) {
|
|
87
105
|
visualizationConfig.formattedData =
|
|
88
106
|
transform.developerStandardize(visualizationConfig.data, visualizationConfig.dataDescription) ||
|
|
@@ -1,99 +1,109 @@
|
|
|
1
|
-
import _ from 'lodash'
|
|
2
|
-
import { APIFilterDropdowns } from '../components/DashboardFilters'
|
|
3
|
-
import { SharedFilter } from '../types/SharedFilter'
|
|
4
|
-
import * as apiFilterHelpers from './apiFilterHelpers'
|
|
5
|
-
import { APIFilter } from '../types/APIFilter'
|
|
6
|
-
import { getParentParams, notAllParentsSelected } from './apiFilterHelpers'
|
|
7
|
-
|
|
8
|
-
export const loadAPIFiltersFactory = (
|
|
9
|
-
dispatch: Function,
|
|
10
|
-
dispatchErrorMessages: Function,
|
|
11
|
-
setAPIFilterDropdowns: Function,
|
|
12
|
-
autoLoadFilterIndexes: number[]
|
|
13
|
-
) => {
|
|
14
|
-
const loadAPIFilters = (
|
|
15
|
-
sharedFilters: SharedFilter[],
|
|
16
|
-
dropdowns: APIFilterDropdowns,
|
|
17
|
-
loadAll?: boolean,
|
|
18
|
-
recursiveLimit = 50
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { APIFilterDropdowns } from '../components/DashboardFilters'
|
|
3
|
+
import { SharedFilter } from '../types/SharedFilter'
|
|
4
|
+
import * as apiFilterHelpers from './apiFilterHelpers'
|
|
5
|
+
import { APIFilter } from '../types/APIFilter'
|
|
6
|
+
import { getParentParams, notAllParentsSelected } from './apiFilterHelpers'
|
|
7
|
+
|
|
8
|
+
export const loadAPIFiltersFactory = (
|
|
9
|
+
dispatch: Function,
|
|
10
|
+
dispatchErrorMessages: Function,
|
|
11
|
+
setAPIFilterDropdowns: Function,
|
|
12
|
+
autoLoadFilterIndexes: number[]
|
|
13
|
+
) => {
|
|
14
|
+
const loadAPIFilters = (
|
|
15
|
+
sharedFilters: SharedFilter[],
|
|
16
|
+
dropdowns: APIFilterDropdowns,
|
|
17
|
+
loadAll?: boolean,
|
|
18
|
+
recursiveLimit = 50,
|
|
19
|
+
isStale?: () => boolean
|
|
20
|
+
): Promise<SharedFilter[]> => {
|
|
21
|
+
if (!sharedFilters) return
|
|
22
|
+
const allIndexes = sharedFilters.map((_, index) => index)
|
|
23
|
+
const _autoLoadFilterIndexes = loadAll ? allIndexes : autoLoadFilterIndexes
|
|
24
|
+
sharedFilters = sharedFilters.map((filter, index) => {
|
|
25
|
+
// For data filters (no API endpoint), return unchanged to preserve user selections
|
|
26
|
+
if (!filter.apiFilter?.apiEndpoint) {
|
|
27
|
+
return filter
|
|
28
|
+
}
|
|
29
|
+
return apiFilterHelpers.setAutoLoadDefaultValue(
|
|
30
|
+
index,
|
|
31
|
+
dropdowns[filter.apiFilter.apiEndpoint],
|
|
32
|
+
sharedFilters,
|
|
33
|
+
_autoLoadFilterIndexes
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
const sharedAPIFilters = sharedFilters.filter(f => f.apiFilter)
|
|
37
|
+
const filterLookup = new Map(sharedAPIFilters.map(filter => [filter.apiFilter.apiEndpoint, filter.apiFilter]))
|
|
38
|
+
const toFetch = apiFilterHelpers.getToFetch(sharedFilters, dropdowns)
|
|
39
|
+
const loadingDropdowns = Object.values(toFetch).reduce(
|
|
40
|
+
(acc, [dropdownsKey]) => ({ ...acc, [dropdownsKey]: null }),
|
|
41
|
+
{}
|
|
42
|
+
)
|
|
43
|
+
setAPIFilterDropdowns(currentState => {
|
|
44
|
+
return { ...currentState, ...loadingDropdowns }
|
|
45
|
+
})
|
|
46
|
+
const newDropdowns = _.cloneDeep(dropdowns)
|
|
47
|
+
return Promise.all(
|
|
48
|
+
Object.keys(toFetch).map(
|
|
49
|
+
endpoint =>
|
|
50
|
+
new Promise<{ error: boolean }>(resolve => {
|
|
51
|
+
fetch(endpoint)
|
|
52
|
+
.then(resp => resp.json())
|
|
53
|
+
.then(data => {
|
|
54
|
+
if (!Array.isArray(data)) {
|
|
55
|
+
console.error('COVE only supports response data in the shape Array<Object>')
|
|
56
|
+
}
|
|
57
|
+
const [_key, index] = toFetch[endpoint]
|
|
58
|
+
const apiFilter = filterLookup.get(_key) as APIFilter
|
|
59
|
+
const _filterValues = apiFilterHelpers.getFilterValues(data, apiFilter)
|
|
60
|
+
|
|
61
|
+
newDropdowns[_key] = _filterValues
|
|
62
|
+
const newDefaultSelectedFilter = apiFilterHelpers.setAutoLoadDefaultValue(
|
|
63
|
+
index,
|
|
64
|
+
_filterValues,
|
|
65
|
+
sharedFilters,
|
|
66
|
+
_autoLoadFilterIndexes
|
|
67
|
+
)
|
|
68
|
+
sharedFilters[index] = newDefaultSelectedFilter
|
|
69
|
+
})
|
|
70
|
+
.catch(() => {
|
|
71
|
+
dispatchErrorMessages({
|
|
72
|
+
type: 'ADD_ERROR_MESSAGE',
|
|
73
|
+
payload: 'There was a problem returning data. Please try again.'
|
|
74
|
+
})
|
|
75
|
+
resolve({ error: true })
|
|
76
|
+
})
|
|
77
|
+
.finally(() => {
|
|
78
|
+
resolve({ error: false })
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
).then(responses => {
|
|
83
|
+
const hasError = responses.some(({ error }) => error)
|
|
84
|
+
const toLoad = sharedFilters.reduce((acc, curr, index) => {
|
|
85
|
+
// the filter is autoloading and it hasn't finished yet
|
|
86
|
+
if (_autoLoadFilterIndexes.includes(index) && !curr.active) {
|
|
87
|
+
if (notAllParentsSelected(getParentParams(curr, sharedFilters))) {
|
|
88
|
+
return acc
|
|
89
|
+
}
|
|
90
|
+
return [...acc, index]
|
|
91
|
+
}
|
|
92
|
+
return acc
|
|
93
|
+
}, [])
|
|
94
|
+
if (hasError || !toLoad.length || recursiveLimit === 0) {
|
|
95
|
+
// Check if this operation is stale before dispatching
|
|
96
|
+
if (isStale && isStale()) {
|
|
97
|
+
// Operation is stale (filters were cleared), skip dispatch
|
|
98
|
+
return sharedFilters
|
|
99
|
+
}
|
|
100
|
+
setAPIFilterDropdowns(newDropdowns)
|
|
101
|
+
dispatch({ type: 'SET_SHARED_FILTERS', payload: sharedFilters })
|
|
102
|
+
return sharedFilters
|
|
103
|
+
} else {
|
|
104
|
+
return loadAPIFilters(sharedFilters, newDropdowns, loadAll, recursiveLimit - 1, isStale)
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
return loadAPIFilters
|
|
109
|
+
}
|
|
@@ -103,7 +103,7 @@ export const getVisualizationsWithFormattedData = (visualizations: Record<string
|
|
|
103
103
|
acc[vizKey].formattedData = newData[dataKey]
|
|
104
104
|
}
|
|
105
105
|
return acc
|
|
106
|
-
},
|
|
106
|
+
}, visualizations)
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
export const filterUsedByDataUrl = (
|