@cdc/dashboard 4.25.10 → 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.
Files changed (56) hide show
  1. package/dist/{cdcdashboard-fce76882.es.js → cdcdashboard-BnB1QM5d.es.js} +6 -13
  2. package/dist/{cdcdashboard-c55ac1ea.es.js → cdcdashboard-D6CG2-Hb.es.js} +5 -12
  3. package/dist/{cdcdashboard-31a33da1.es.js → cdcdashboard-MXgURbdZ.es.js} +6 -13
  4. package/dist/{cdcdashboard-1a1724a1.es.js → cdcdashboard-dgT_1dIT.es.js} +136 -151
  5. package/dist/cdcdashboard.js +48574 -46414
  6. package/examples/api-test/categories.json +18 -0
  7. package/examples/api-test/chart-data.json +602 -0
  8. package/examples/api-test/topics.json +47 -0
  9. package/examples/api-test/years.json +22 -0
  10. package/examples/markup-axis-label.json +4167 -0
  11. package/examples/private/DEV-10538.json +407 -0
  12. package/examples/private/DEV-11405.json +39112 -0
  13. package/examples/private/big-dashboard.json +39095 -39077
  14. package/examples/private/clade-2.json +430 -0
  15. package/examples/private/delete.json +32919 -0
  16. package/examples/private/diabetes.json +546 -196
  17. package/examples/private/markup-footer/mortality-deaths-footnotes-age.csv +3 -0
  18. package/examples/private/mpox.json +38128 -0
  19. package/examples/private/reset.json +32920 -0
  20. package/examples/test-api-filter-reset.json +132 -0
  21. package/index.html +2 -2
  22. package/package.json +9 -10
  23. package/src/CdcDashboardComponent.tsx +17 -8
  24. package/src/DashboardContext.tsx +3 -1
  25. package/src/_stories/Dashboard.stories.tsx +17 -0
  26. package/src/_stories/_mock/custom-order-new-values.json +116 -0
  27. package/src/components/DashboardFilters/DashboardFilters.tsx +34 -20
  28. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +29 -12
  29. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +77 -111
  30. package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +51 -51
  31. package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +120 -24
  32. package/src/components/DashboardFilters/_stories/DashboardFilters.stories.tsx +62 -3
  33. package/src/components/DataDesignerModal.tsx +12 -5
  34. package/src/components/Header/Header.tsx +10 -9
  35. package/src/components/Toggle/Toggle.tsx +48 -48
  36. package/src/components/VisualizationRow.tsx +4 -3
  37. package/src/helpers/addValuesToDashboardFilters.ts +29 -4
  38. package/src/helpers/apiFilterHelpers.ts +26 -2
  39. package/src/helpers/filterData.ts +52 -7
  40. package/src/helpers/filterResetHelpers.ts +102 -0
  41. package/src/helpers/getVizConfig.ts +2 -2
  42. package/src/helpers/loadAPIFilters.ts +109 -99
  43. package/src/helpers/tests/filterResetHelpers.test.ts +532 -0
  44. package/src/index.tsx +1 -0
  45. package/src/scss/editor-panel.scss +3 -431
  46. package/src/scss/main.scss +1 -24
  47. package/src/store/errorMessage/errorMessage.reducer.ts +1 -1
  48. package/src/types/DashboardFilters.ts +9 -8
  49. package/examples/private/burden_toolkit_mortality_diabetes_attributable_deaths_data.csv +0 -14041
  50. package/examples/private/burden_toolkit_mortality_diabetes_attributable_deaths_per_100000_data.csv +0 -14041
  51. package/examples/private/burden_toolkit_mortality_qaly_data.csv +0 -18721
  52. package/examples/private/burden_toolkit_mortality_yll_data.csv +0 -18721
  53. package/src/helpers/getAutoLoadVisualization.ts +0 -11
  54. package/src/scss/mixins.scss +0 -47
  55. package/src/scss/variables.scss +0 -5
  56. /package/dist/{cdcdashboard-548642e6.es.js → cdcdashboard-Ct2SB0vL.es.js} +0 -0
@@ -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
- ): Promise<SharedFilter[]> => {
20
- if (!sharedFilters) return
21
- const allIndexes = sharedFilters.map((_, index) => index)
22
- const _autoLoadFilterIndexes = loadAll ? allIndexes : autoLoadFilterIndexes
23
- sharedFilters = sharedFilters.map((filter, index) =>
24
- apiFilterHelpers.setAutoLoadDefaultValue(
25
- index,
26
- dropdowns[filter.apiFilter?.apiEndpoint],
27
- sharedFilters,
28
- _autoLoadFilterIndexes
29
- )
30
- )
31
- const sharedAPIFilters = sharedFilters.filter(f => f.apiFilter)
32
- const filterLookup = new Map(sharedAPIFilters.map(filter => [filter.apiFilter.apiEndpoint, filter.apiFilter]))
33
- const toFetch = apiFilterHelpers.getToFetch(sharedFilters, dropdowns)
34
- const loadingDropdowns = Object.values(toFetch).reduce(
35
- (acc, [dropdownsKey]) => ({ ...acc, [dropdownsKey]: null }),
36
- {}
37
- )
38
- setAPIFilterDropdowns(currentState => {
39
- return { ...currentState, ...loadingDropdowns }
40
- })
41
- const newDropdowns = _.cloneDeep(dropdowns)
42
- return Promise.all(
43
- Object.keys(toFetch).map(
44
- endpoint =>
45
- new Promise<{ error: boolean }>(resolve => {
46
- fetch(endpoint)
47
- .then(resp => resp.json())
48
- .then(data => {
49
- if (!Array.isArray(data)) {
50
- console.error('COVE only supports response data in the shape Array<Object>')
51
- }
52
- const [_key, index] = toFetch[endpoint]
53
- const apiFilter = filterLookup.get(_key) as APIFilter
54
- const _filterValues = apiFilterHelpers.getFilterValues(data, apiFilter)
55
-
56
- newDropdowns[_key] = _filterValues
57
- const newDefaultSelectedFilter = apiFilterHelpers.setAutoLoadDefaultValue(
58
- index,
59
- _filterValues,
60
- sharedFilters,
61
- _autoLoadFilterIndexes
62
- )
63
- sharedFilters[index] = newDefaultSelectedFilter
64
- })
65
- .catch(() => {
66
- dispatchErrorMessages({
67
- type: 'ADD_ERROR_MESSAGE',
68
- payload: 'There was a problem returning data. Please try again.'
69
- })
70
- resolve({ error: true })
71
- })
72
- .finally(() => {
73
- resolve({ error: false })
74
- })
75
- })
76
- )
77
- ).then(responses => {
78
- const hasError = responses.some(({ error }) => error)
79
- const toLoad = sharedFilters.reduce((acc, curr, index) => {
80
- // the filter is autoloading and it hasn't finished yet
81
- if (_autoLoadFilterIndexes.includes(index) && !curr.active) {
82
- if (notAllParentsSelected(getParentParams(curr, sharedFilters))) {
83
- return acc
84
- }
85
- return [...acc, index]
86
- }
87
- return acc
88
- }, [])
89
- if (hasError || !toLoad.length || recursiveLimit === 0) {
90
- setAPIFilterDropdowns(newDropdowns)
91
- dispatch({ type: 'SET_SHARED_FILTERS', payload: sharedFilters })
92
- return sharedFilters
93
- } else {
94
- return loadAPIFilters(sharedFilters, newDropdowns, loadAll, recursiveLimit - 1)
95
- }
96
- })
97
- }
98
- return loadAPIFilters
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
+ }