@cdc/dashboard 4.25.6-2 → 4.25.7

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 (43) hide show
  1. package/dist/cdcdashboard.js +63503 -41005
  2. package/package.json +9 -9
  3. package/src/CdcDashboardComponent.tsx +11 -8
  4. package/src/components/Header/Header.tsx +2 -2
  5. package/src/components/VisualizationRow.tsx +324 -324
  6. package/src/helpers/getVizConfig.ts +1 -0
  7. package/src/helpers/getVizRowColumnLocator.ts +10 -10
  8. package/src/helpers/reloadURLHelpers.ts +124 -124
  9. package/src/store/dashboard.reducer.ts +288 -288
  10. package/src/types/ConfigRow.ts +19 -19
  11. package/src/types/Dashboard.ts +11 -11
  12. package/examples/private/DEV-10120.json +0 -1294
  13. package/examples/private/DEV-10527.json +0 -845
  14. package/examples/private/DEV-10586.json +0 -54319
  15. package/examples/private/DEV-10856.json +0 -54319
  16. package/examples/private/DEV-9199.json +0 -606
  17. package/examples/private/DEV-9644.json +0 -20092
  18. package/examples/private/DEV-9684.json +0 -2135
  19. package/examples/private/DEV-9932.json +0 -95
  20. package/examples/private/DEV-9989.json +0 -229
  21. package/examples/private/art-dashboard.json +0 -18174
  22. package/examples/private/art-scratch.json +0 -2406
  23. package/examples/private/bird-flu-2.json +0 -440
  24. package/examples/private/bird-flu.json +0 -413
  25. package/examples/private/crashing-sidebar.json +0 -975
  26. package/examples/private/d.json +0 -1561
  27. package/examples/private/dashboard-config-ehdi.json +0 -29915
  28. package/examples/private/dashboard-map-filter.json +0 -815
  29. package/examples/private/dashboard-margins.js +0 -15
  30. package/examples/private/dataset.json +0 -1452
  31. package/examples/private/dev-10856-2.json +0 -1348
  32. package/examples/private/ehdi-data.json +0 -29502
  33. package/examples/private/exposure-source-h5-data.csv +0 -26
  34. package/examples/private/fatal-data.csv +0 -3159
  35. package/examples/private/feelings.json +0 -1
  36. package/examples/private/gaza-issue.json +0 -1214
  37. package/examples/private/josh.json +0 -6175
  38. package/examples/private/map-issue.json +0 -628
  39. package/examples/private/markup.json +0 -115
  40. package/examples/private/mpox.json +0 -429
  41. package/examples/private/nhis.json +0 -1792
  42. package/examples/private/testing-pie.json +0 -436
  43. package/examples/private/workforce.json +0 -2041
@@ -1,10 +1,10 @@
1
- import { ConfigRow } from '../types/ConfigRow'
2
-
3
- // returns a dictionary of widget names and their corresponding row and column index
4
- export const getVizRowColumnLocator = (rows: ConfigRow[]): Record<string, { row: number; column: number }> =>
5
- rows.reduce((acc, curr, index) => {
6
- curr.columns?.forEach((column, columnIndex) => {
7
- if (column.widget !== undefined) acc[column.widget] = { row: index, column: columnIndex }
8
- })
9
- return acc
10
- }, {})
1
+ import { ConfigRow } from '../types/ConfigRow'
2
+
3
+ // returns a dictionary of widget names and their corresponding row and column index
4
+ export const getVizRowColumnLocator = (rows: ConfigRow[]): Record<string, { row: number; column: number }> =>
5
+ rows.reduce((acc, curr, index) => {
6
+ curr.columns?.forEach((column, columnIndex) => {
7
+ if (column.widget !== undefined) acc[column.widget] = { row: index, column: columnIndex }
8
+ })
9
+ return acc
10
+ }, {})
@@ -1,124 +1,124 @@
1
- import { gatherQueryParams } from '@cdc/core/helpers/gatherQueryParams'
2
- import { SharedFilter } from '../types/SharedFilter'
3
- import { capitalizeSplitAndJoin } from '@cdc/core/helpers/cove/string'
4
- import { AnyVisualization, Visualization } from '@cdc/core/types/Visualization'
5
- import _ from 'lodash'
6
- import { DashboardConfig } from '../types/DashboardConfig'
7
- import { ConfigRow } from '../types/ConfigRow'
8
- import { getVizRowColumnLocator } from './getVizRowColumnLocator'
9
-
10
- export const isUpdateNeeded = (
11
- filters: SharedFilter[],
12
- currentQueryParams: Record<string, string>,
13
- newQueryParams: Record<string, string>
14
- ): boolean => {
15
- let needsUpdate = false
16
- filters.find(filter => {
17
- if (filter.type === 'urlfilter' && !Array.isArray(filter.active) && filter.filterBy === 'File Name') {
18
- needsUpdate = true
19
- return true
20
- }
21
- })
22
- Object.keys(newQueryParams).forEach(updatedParam => {
23
- if (decodeURIComponent(newQueryParams[updatedParam]) !== currentQueryParams[updatedParam]) {
24
- needsUpdate = true
25
- }
26
- })
27
- return needsUpdate
28
- }
29
-
30
- type GetDatasetKeysParams = Pick<DashboardConfig, 'visualizations' | 'datasets' | 'rows'>
31
- export const getDatasetKeys = ({ visualizations, datasets, rows }: GetDatasetKeysParams): string[] => {
32
- const vizDataKeys = Object.values(visualizations).map(viz => viz.dataKey)
33
- const rowDataKeys = rows.map(row => row.dataKey)
34
- const footnoteDataKeys = Object.values(visualizations)
35
- .map(viz => viz.footnotes?.dataKey)
36
- .filter(Boolean)
37
- // ensure to only load datasets for the specific dashboard tab.
38
- const datasetsUsedByDashboard = _.uniq([...vizDataKeys, ...rowDataKeys, ...footnoteDataKeys])
39
- return Object.keys(datasets).filter(datasetKey => datasetsUsedByDashboard.includes(datasetKey))
40
- }
41
-
42
- export const getDataURL = (updatedQSParams: Record<string, string | string[]>, dataUrl: URL, newFileName: string) => {
43
- const _params = Object.keys(updatedQSParams).flatMap(key => {
44
- const value = updatedQSParams[key]
45
- if (value === undefined) return []
46
- if (typeof value === 'string' && (value as String).match(/undefined/)) return []
47
- if (Array.isArray(value)) return value.map(v => ({ key, value: v }))
48
- return { key, value }
49
- })
50
- const baseURL = dataUrl.origin + dataUrl.pathname
51
- let dataUrlFinal = `${baseURL}${gatherQueryParams(baseURL, _params)}`
52
-
53
- if (newFileName !== '') {
54
- const fileExtension = dataUrl.pathname.split('.').pop()
55
- const pathWithoutFilename = dataUrl.pathname.substring(0, dataUrl.pathname.lastIndexOf('/'))
56
- dataUrlFinal = `${dataUrl.origin}${pathWithoutFilename}/${newFileName}.${fileExtension}${gatherQueryParams(
57
- baseURL,
58
- _params
59
- )}`
60
- }
61
- return dataUrlFinal
62
- }
63
-
64
- export const getNewFileName = (newFileName: string, filter: SharedFilter, datasetKey: string) => {
65
- const replacements = {
66
- 'Remove Spaces': '',
67
- 'Keep Spaces': ' ',
68
- 'Replace With Underscore': '_'
69
- }
70
- let fileName = newFileName
71
- if (filter.datasetKey === datasetKey) {
72
- if (filter.fileName) {
73
- // if a file name is found, ie, state_${query}, use that, ie. state_activeFilter.json
74
- fileName = capitalizeSplitAndJoin.call(
75
- String(filter.fileName),
76
- ' ',
77
- replacements[filter.whitespaceReplacement ?? 'Keep Spaces']
78
- )
79
- } else {
80
- // if no file name is entered use the default active filter. ie. /activeFilter.json
81
- fileName = filter.active as string
82
- }
83
- }
84
-
85
- if (fileName?.includes('${query}')) {
86
- fileName = fileName.replace(
87
- '${query}',
88
- capitalizeSplitAndJoin.call(
89
- String(filter.active),
90
- ' ',
91
- replacements[filter.whitespaceReplacement ?? 'Keep Spaces']
92
- )
93
- )
94
- }
95
-
96
- return fileName
97
- }
98
-
99
- export const getVisualizationsWithFormattedData = (visualizations: Record<string, Visualization>, newData: Object) => {
100
- return Object.keys(visualizations).reduce((acc, vizKey) => {
101
- const dataKey = visualizations[vizKey].dataKey
102
- if (newData[dataKey]) {
103
- acc[vizKey].formattedData = newData[dataKey]
104
- }
105
- return acc
106
- }, _.cloneDeep(visualizations))
107
- }
108
-
109
- export const filterUsedByDataUrl = (
110
- filter: SharedFilter,
111
- datasetKey: string,
112
- visualizations: Record<string, AnyVisualization>,
113
- rows: ConfigRow[]
114
- ) => {
115
- if (!filter.usedBy || !filter.usedBy.length) return true
116
- const vizUsingFilters = filter.usedBy?.map(vizOrRowKey => visualizations[vizOrRowKey] || rows[vizOrRowKey])
117
-
118
- return vizUsingFilters?.some(viz => {
119
- const usedByViz = viz?.dataKey === datasetKey
120
- // datasetKey might be a key to a dynamic footnotes URL
121
- const usedByVizFootnote = viz?.footnotes?.dataKey === datasetKey
122
- return usedByViz || usedByVizFootnote
123
- })
124
- }
1
+ import { gatherQueryParams } from '@cdc/core/helpers/gatherQueryParams'
2
+ import { SharedFilter } from '../types/SharedFilter'
3
+ import { capitalizeSplitAndJoin } from '@cdc/core/helpers/cove/string'
4
+ import { AnyVisualization, Visualization } from '@cdc/core/types/Visualization'
5
+ import _ from 'lodash'
6
+ import { DashboardConfig } from '../types/DashboardConfig'
7
+ import { ConfigRow } from '../types/ConfigRow'
8
+ import { getVizRowColumnLocator } from './getVizRowColumnLocator'
9
+
10
+ export const isUpdateNeeded = (
11
+ filters: SharedFilter[],
12
+ currentQueryParams: Record<string, string>,
13
+ newQueryParams: Record<string, string>
14
+ ): boolean => {
15
+ let needsUpdate = false
16
+ filters.find(filter => {
17
+ if (filter.type === 'urlfilter' && !Array.isArray(filter.active) && filter.filterBy === 'File Name') {
18
+ needsUpdate = true
19
+ return true
20
+ }
21
+ })
22
+ Object.keys(newQueryParams).forEach(updatedParam => {
23
+ if (decodeURIComponent(newQueryParams[updatedParam]) !== currentQueryParams[updatedParam]) {
24
+ needsUpdate = true
25
+ }
26
+ })
27
+ return needsUpdate
28
+ }
29
+
30
+ type GetDatasetKeysParams = Pick<DashboardConfig, 'visualizations' | 'datasets' | 'rows'>
31
+ export const getDatasetKeys = ({ visualizations, datasets, rows }: GetDatasetKeysParams): string[] => {
32
+ const vizDataKeys = Object.values(visualizations).map(viz => viz.dataKey)
33
+ const rowDataKeys = rows.map(row => row.dataKey)
34
+ const footnoteDataKeys = Object.values(visualizations)
35
+ .map(viz => viz.footnotes?.dataKey)
36
+ .filter(Boolean)
37
+ // ensure to only load datasets for the specific dashboard tab.
38
+ const datasetsUsedByDashboard = _.uniq([...vizDataKeys, ...rowDataKeys, ...footnoteDataKeys])
39
+ return Object.keys(datasets).filter(datasetKey => datasetsUsedByDashboard.includes(datasetKey))
40
+ }
41
+
42
+ export const getDataURL = (updatedQSParams: Record<string, string | string[]>, dataUrl: URL, newFileName: string) => {
43
+ const _params = Object.keys(updatedQSParams).flatMap(key => {
44
+ const value = updatedQSParams[key]
45
+ if (value === undefined) return []
46
+ if (typeof value === 'string' && (value as String).match(/undefined/)) return []
47
+ if (Array.isArray(value)) return value.map(v => ({ key, value: v }))
48
+ return { key, value }
49
+ })
50
+ const baseURL = dataUrl.origin + dataUrl.pathname
51
+ let dataUrlFinal = `${baseURL}${gatherQueryParams(baseURL, _params)}`
52
+
53
+ if (newFileName !== '') {
54
+ const fileExtension = dataUrl.pathname.split('.').pop()
55
+ const pathWithoutFilename = dataUrl.pathname.substring(0, dataUrl.pathname.lastIndexOf('/'))
56
+ dataUrlFinal = `${dataUrl.origin}${pathWithoutFilename}/${newFileName}.${fileExtension}${gatherQueryParams(
57
+ baseURL,
58
+ _params
59
+ )}`
60
+ }
61
+ return dataUrlFinal
62
+ }
63
+
64
+ export const getNewFileName = (newFileName: string, filter: SharedFilter, datasetKey: string) => {
65
+ const replacements = {
66
+ 'Remove Spaces': '',
67
+ 'Keep Spaces': ' ',
68
+ 'Replace With Underscore': '_'
69
+ }
70
+ let fileName = newFileName
71
+ if (filter.datasetKey === datasetKey) {
72
+ if (filter.fileName) {
73
+ // if a file name is found, ie, state_${query}, use that, ie. state_activeFilter.json
74
+ fileName = capitalizeSplitAndJoin.call(
75
+ String(filter.fileName),
76
+ ' ',
77
+ replacements[filter.whitespaceReplacement ?? 'Keep Spaces']
78
+ )
79
+ } else {
80
+ // if no file name is entered use the default active filter. ie. /activeFilter.json
81
+ fileName = filter.active as string
82
+ }
83
+ }
84
+
85
+ if (fileName?.includes('${query}')) {
86
+ fileName = fileName.replace(
87
+ '${query}',
88
+ capitalizeSplitAndJoin.call(
89
+ String(filter.active),
90
+ ' ',
91
+ replacements[filter.whitespaceReplacement ?? 'Keep Spaces']
92
+ )
93
+ )
94
+ }
95
+
96
+ return fileName
97
+ }
98
+
99
+ export const getVisualizationsWithFormattedData = (visualizations: Record<string, Visualization>, newData: Object) => {
100
+ return Object.keys(visualizations).reduce((acc, vizKey) => {
101
+ const dataKey = visualizations[vizKey].dataKey
102
+ if (newData[dataKey]) {
103
+ acc[vizKey].formattedData = newData[dataKey]
104
+ }
105
+ return acc
106
+ }, _.cloneDeep(visualizations))
107
+ }
108
+
109
+ export const filterUsedByDataUrl = (
110
+ filter: SharedFilter,
111
+ datasetKey: string,
112
+ visualizations: Record<string, AnyVisualization>,
113
+ rows: ConfigRow[]
114
+ ) => {
115
+ if (!filter.usedBy || !filter.usedBy.length) return true
116
+ const vizUsingFilters = filter.usedBy?.map(vizOrRowKey => visualizations[vizOrRowKey] || rows[vizOrRowKey])
117
+
118
+ return vizUsingFilters?.some(viz => {
119
+ const usedByViz = viz?.dataKey === datasetKey
120
+ // datasetKey might be a key to a dynamic footnotes URL
121
+ const usedByVizFootnote = viz?.footnotes?.dataKey === datasetKey
122
+ return usedByViz || usedByVizFootnote
123
+ })
124
+ }