@cdc/dashboard 4.24.5 → 4.24.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.
- package/dist/cdcdashboard.js +122872 -112065
- package/examples/custom/css/respiratory.css +236 -0
- package/examples/custom/js/respiratory.js +242 -0
- package/examples/default-multi-dataset-shared-filter.json +1729 -0
- package/examples/ed-visits-county-file.json +618 -0
- package/examples/filtered-dash.json +6 -21
- package/index.html +10 -1
- package/package.json +12 -11
- package/src/CdcDashboard.tsx +5 -1
- package/src/CdcDashboardComponent.tsx +165 -306
- package/src/DashboardContext.tsx +9 -1
- package/src/_stories/Dashboard.stories.tsx +38 -34
- package/src/_stories/_mock/api-filter-chart.json +11 -35
- package/src/_stories/_mock/api-filter-map.json +17 -31
- package/src/_stories/_mock/multi-viz.json +2 -3
- package/src/_stories/_mock/pivot-filter.json +14 -12
- package/src/components/CollapsibleVisualizationRow.tsx +44 -0
- package/src/components/Column.tsx +1 -1
- package/src/components/DashboardFilters/DashboardFilters.tsx +80 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +218 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx +48 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +367 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/index.ts +1 -0
- package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +143 -0
- package/src/components/DashboardFilters/index.ts +3 -0
- package/src/components/DataDesignerModal.tsx +9 -9
- package/src/components/ExpandCollapseButtons.tsx +20 -0
- package/src/components/Header/Header.tsx +1 -97
- package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +4 -4
- package/src/components/Row.tsx +52 -19
- package/src/components/Toggle/Toggle.tsx +2 -4
- package/src/components/VisualizationRow.tsx +82 -24
- package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +116 -0
- package/src/components/VisualizationsPanel/index.ts +1 -0
- package/src/components/VisualizationsPanel/visualizations-panel-styles.css +12 -0
- package/src/components/Widget.tsx +26 -90
- package/src/helpers/apiFilterHelpers.ts +51 -0
- package/src/helpers/changeFilterActive.ts +30 -0
- package/src/helpers/filterData.ts +10 -48
- package/src/helpers/generateValuesForFilter.ts +1 -1
- package/src/helpers/getAutoLoadVisualization.ts +11 -0
- package/src/helpers/getFilteredData.ts +4 -2
- package/src/helpers/getVizConfig.ts +23 -2
- package/src/helpers/getVizRowColumnLocator.ts +2 -1
- package/src/helpers/hasDashboardApplyBehavior.ts +5 -0
- package/src/helpers/iconHash.tsx +3 -3
- package/src/helpers/mapDataToConfig.ts +29 -0
- package/src/helpers/processData.ts +2 -3
- package/src/helpers/reloadURLHelpers.ts +68 -0
- package/src/helpers/tests/filterData.test.ts +1 -93
- package/src/scss/editor-panel.scss +1 -1
- package/src/scss/grid.scss +34 -27
- package/src/scss/main.scss +41 -3
- package/src/scss/variables.scss +4 -0
- package/src/store/dashboard.actions.ts +12 -4
- package/src/store/dashboard.reducer.ts +30 -4
- package/src/types/APIFilter.ts +1 -5
- package/src/types/ConfigRow.ts +2 -0
- package/src/types/Dashboard.ts +1 -1
- package/src/types/DashboardConfig.ts +2 -4
- package/src/types/DashboardFilters.ts +7 -0
- package/src/types/InitialState.ts +1 -1
- package/src/types/MultiDashboard.ts +2 -2
- package/src/types/SharedFilter.ts +2 -5
- package/src/types/Tab.ts +1 -1
- package/LICENSE +0 -201
- package/src/components/Filters.tsx +0 -88
- package/src/components/Header/FilterModal.tsx +0 -510
- package/src/components/VisualizationsPanel.tsx +0 -95
- package/src/helpers/getApiFilterKey.ts +0 -5
package/src/DashboardContext.tsx
CHANGED
|
@@ -2,17 +2,22 @@ import { Dispatch, createContext } from 'react'
|
|
|
2
2
|
import { DashboardState } from './store/dashboard.reducer'
|
|
3
3
|
import DashboardActions from './store/dashboard.actions'
|
|
4
4
|
import { Tab } from './types/Tab'
|
|
5
|
+
import { MultiDashboardConfig } from './types/MultiDashboard'
|
|
6
|
+
import { SharedFilter } from './types/SharedFilter'
|
|
7
|
+
import { APIFilterDropdowns } from './components/DashboardFilters'
|
|
5
8
|
|
|
6
9
|
type ConfigCTX = DashboardState & {
|
|
7
10
|
outerContainerRef: (node: any) => void
|
|
8
11
|
setParentConfig: any
|
|
9
12
|
isDebug: boolean
|
|
13
|
+
reloadURLData: (newFilters?: SharedFilter[]) => void
|
|
14
|
+
loadAPIFilters: (sharedFilters: SharedFilter[], dropdowns?: APIFilterDropdowns, recursiveLimit?: number) => Promise<SharedFilter[]>
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
const firstTab: Tab = 'Dashboard Description'
|
|
13
18
|
|
|
14
19
|
export const initialState = {
|
|
15
|
-
data: {},
|
|
20
|
+
data: {} as Record<string, any[]>,
|
|
16
21
|
loading: false,
|
|
17
22
|
filteredData: {},
|
|
18
23
|
preview: false,
|
|
@@ -22,7 +27,10 @@ export const initialState = {
|
|
|
22
27
|
const initialContext: ConfigCTX = {
|
|
23
28
|
outerContainerRef: () => {},
|
|
24
29
|
setParentConfig: () => {},
|
|
30
|
+
reloadURLData: () => {},
|
|
31
|
+
loadAPIFilters: () => Promise.resolve([]),
|
|
25
32
|
isDebug: false,
|
|
33
|
+
config: {} as MultiDashboardConfig,
|
|
26
34
|
...initialState
|
|
27
35
|
}
|
|
28
36
|
|
|
@@ -15,6 +15,9 @@ import { type DashboardConfig as Config } from '../types/DashboardConfig'
|
|
|
15
15
|
import { userEvent, within } from '@storybook/testing-library'
|
|
16
16
|
import ToggleExampleConfig from './_mock/toggle-example.json'
|
|
17
17
|
import _ from 'lodash'
|
|
18
|
+
import { footnotesSymbols } from '@cdc/core/helpers/footnoteSymbols'
|
|
19
|
+
import FootnotesConfig from '@cdc/core/types/Footnotes'
|
|
20
|
+
import { ConfigRow } from '../types/ConfigRow'
|
|
18
21
|
|
|
19
22
|
const meta: Meta<typeof Dashboard> = {
|
|
20
23
|
title: 'Components/Pages/Dashboard',
|
|
@@ -89,8 +92,13 @@ countries.forEach((country, i) => {
|
|
|
89
92
|
})
|
|
90
93
|
})
|
|
91
94
|
|
|
95
|
+
const footnoteData = countries.map((country, i) => {
|
|
96
|
+
return { Country: country, symbol: footnotesSymbols[i][0], text: faker.lorem.sentence() }
|
|
97
|
+
})
|
|
98
|
+
|
|
92
99
|
const multiVizData = {
|
|
93
|
-
'valid-world-data.json': { data }
|
|
100
|
+
'valid-world-data.json': { data },
|
|
101
|
+
'footnote-data.json': { data: footnoteData }
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
export const MultiVisualization: Story = {
|
|
@@ -107,6 +115,16 @@ export const MultiDashboard: Story = {
|
|
|
107
115
|
}
|
|
108
116
|
}
|
|
109
117
|
|
|
118
|
+
const FNrows: ConfigRow[] = [{ ...MultiVizConfig.rows[0], footnotesId: 'footnote123' }]
|
|
119
|
+
const footnoteConfig: Partial<FootnotesConfig> = { dataKey: 'footnote-data.json', dynamicFootnotes: { symbolColumn: 'symbol', textColumn: 'text' }, staticFootnotes: [{ symbol: '**', text: 'This is a static Footnote' }] }
|
|
120
|
+
const FNViz = { ...MultiVizConfig.visualizations, footnote123: footnoteConfig }
|
|
121
|
+
export const Footnotes: Story = {
|
|
122
|
+
args: {
|
|
123
|
+
config: { ...MultiVizConfig, datasets: multiVizData, rows: FNrows, visualizations: FNViz },
|
|
124
|
+
isEditor: false
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
110
128
|
const sleep = ms => {
|
|
111
129
|
return new Promise(r => setTimeout(r, ms))
|
|
112
130
|
}
|
|
@@ -133,35 +151,18 @@ const fetchMock = {
|
|
|
133
151
|
body: [{ IndicatorID: 'indicatorID', Indicator: 'Some Indicator' }]
|
|
134
152
|
}
|
|
135
153
|
},
|
|
136
|
-
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
DataValueTypes: [{ DataValueType: 'Some Data Value Type', DataValueTypeId: 'dataValueTypeId' }],
|
|
146
|
-
StratificationCategories: [{ StratificationCategoryId: 'stratCategoryId', StratificationCategory: 'Some Strat Category' }]
|
|
154
|
+
...['Year', 'DataValueType', 'StratificationCategory', 'Stratification'].map(filter => {
|
|
155
|
+
return {
|
|
156
|
+
matcher: {
|
|
157
|
+
name: 'filters' + filter,
|
|
158
|
+
url: 'path:/api/POC/Filters/' + filter
|
|
159
|
+
},
|
|
160
|
+
response: {
|
|
161
|
+
status: 200,
|
|
162
|
+
body: _.times(5, i => ({ [filter]: `Some ${filter} ${i}` }))
|
|
147
163
|
}
|
|
148
164
|
}
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
matcher: {
|
|
152
|
-
name: 'stratifications',
|
|
153
|
-
url: 'path:/api/POC/stratifications'
|
|
154
|
-
},
|
|
155
|
-
response: {
|
|
156
|
-
status: 200,
|
|
157
|
-
body: [
|
|
158
|
-
{
|
|
159
|
-
StratificationId: 'stratId',
|
|
160
|
-
Stratification: 'Some Strat'
|
|
161
|
-
}
|
|
162
|
-
]
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
+
}),
|
|
165
166
|
{
|
|
166
167
|
matcher: {
|
|
167
168
|
name: 'locations',
|
|
@@ -213,7 +214,8 @@ const fetchMock = {
|
|
|
213
214
|
|
|
214
215
|
export const APIFiltersMap: Story = {
|
|
215
216
|
args: {
|
|
216
|
-
config: APIFiltersMapData as unknown as Config
|
|
217
|
+
config: APIFiltersMapData as unknown as Config,
|
|
218
|
+
isEditor: false
|
|
217
219
|
},
|
|
218
220
|
parameters: {
|
|
219
221
|
fetchMock
|
|
@@ -230,18 +232,19 @@ export const APIFiltersMap: Story = {
|
|
|
230
232
|
const indicatorsFilter = canvas.getByLabelText('Indicator', { selector: 'select' })
|
|
231
233
|
await user.selectOptions(indicatorsFilter, ['indicatorID'])
|
|
232
234
|
const yearsFilter = canvas.getByLabelText('Year', { selector: 'select' })
|
|
233
|
-
await user.selectOptions(yearsFilter, ['
|
|
235
|
+
await user.selectOptions(yearsFilter, ['Some Year 0'])
|
|
234
236
|
const stratCategoryFilter = canvas.getByLabelText('View By', { selector: 'select' })
|
|
235
|
-
await user.selectOptions(stratCategoryFilter, ['
|
|
237
|
+
await user.selectOptions(stratCategoryFilter, ['Some StratificationCategory 0'])
|
|
236
238
|
const stratFilter = canvas.getByLabelText('Stratification', { selector: 'select' })
|
|
237
|
-
await user.selectOptions(stratFilter, ['
|
|
239
|
+
await user.selectOptions(stratFilter, ['Some Stratification 0'])
|
|
238
240
|
await user.click(canvas.getByText('GO!'))
|
|
239
241
|
}
|
|
240
242
|
}
|
|
241
243
|
|
|
242
244
|
export const APIFiltersChart: Story = {
|
|
243
245
|
args: {
|
|
244
|
-
config: APIFiltersChartData as unknown as Config
|
|
246
|
+
config: APIFiltersChartData as unknown as Config,
|
|
247
|
+
isEditor: false
|
|
245
248
|
},
|
|
246
249
|
parameters: {
|
|
247
250
|
fetchMock
|
|
@@ -260,8 +263,9 @@ export const APIFiltersChart: Story = {
|
|
|
260
263
|
const indicatorsFilter = canvas.getByLabelText('Indicator', { selector: 'select' })
|
|
261
264
|
await user.selectOptions(indicatorsFilter, ['indicatorID'])
|
|
262
265
|
await user.click(canvas.getByText('GO!'))
|
|
266
|
+
await sleep(1000)
|
|
263
267
|
const yearFilter = canvas.getByLabelText('Year', { selector: 'select' })
|
|
264
|
-
await user.selectOptions(yearFilter, ['
|
|
268
|
+
await user.selectOptions(yearFilter, ['Some Year 1'])
|
|
265
269
|
}
|
|
266
270
|
}
|
|
267
271
|
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
"sharedFilters": [
|
|
5
5
|
{
|
|
6
6
|
"key": "Location",
|
|
7
|
-
"usedBy": [
|
|
8
|
-
"chart1"
|
|
9
|
-
],
|
|
10
7
|
"type": "urlfilter",
|
|
11
8
|
"apiFilter": {
|
|
12
9
|
"apiEndpoint": "http://test.gov/api/poc/locations",
|
|
@@ -19,9 +16,6 @@
|
|
|
19
16
|
},
|
|
20
17
|
{
|
|
21
18
|
"key": "Category",
|
|
22
|
-
"usedBy": [
|
|
23
|
-
"chart1"
|
|
24
|
-
],
|
|
25
19
|
"type": "urlfilter",
|
|
26
20
|
"apiFilter": {
|
|
27
21
|
"apiEndpoint": "http://test.gov/api/poc/topics",
|
|
@@ -34,9 +28,6 @@
|
|
|
34
28
|
},
|
|
35
29
|
{
|
|
36
30
|
"key": "Indicator",
|
|
37
|
-
"usedBy": [
|
|
38
|
-
"chart1"
|
|
39
|
-
],
|
|
40
31
|
"type": "urlfilter",
|
|
41
32
|
"apiFilter": {
|
|
42
33
|
"apiEndpoint": "http://test.gov/api/poc/indicators",
|
|
@@ -50,15 +41,11 @@
|
|
|
50
41
|
},
|
|
51
42
|
{
|
|
52
43
|
"key": "Year",
|
|
53
|
-
"usedBy": [
|
|
54
|
-
"chart1"
|
|
55
|
-
],
|
|
56
44
|
"type": "urlfilter",
|
|
57
45
|
"apiFilter": {
|
|
58
|
-
"apiEndpoint": "http://test.gov/api/POC/Filters",
|
|
46
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/Year",
|
|
59
47
|
"valueSelector": "Year",
|
|
60
|
-
"textSelector": "Year"
|
|
61
|
-
"heirarchyLookup": "Years"
|
|
48
|
+
"textSelector": "Year"
|
|
62
49
|
},
|
|
63
50
|
"queryParameter": "year",
|
|
64
51
|
"showDropdown": true,
|
|
@@ -66,15 +53,11 @@
|
|
|
66
53
|
},
|
|
67
54
|
{
|
|
68
55
|
"key": "View By",
|
|
69
|
-
"usedBy": [
|
|
70
|
-
"chart1"
|
|
71
|
-
],
|
|
72
56
|
"type": "urlfilter",
|
|
73
57
|
"apiFilter": {
|
|
74
|
-
"apiEndpoint": "http://test.gov/api/POC/Filters",
|
|
75
|
-
"valueSelector": "
|
|
58
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/StratificationCategory",
|
|
59
|
+
"valueSelector": "StratificationCategory",
|
|
76
60
|
"textSelector": "StratificationCategory",
|
|
77
|
-
"heirarchyLookup": "StratificationCategories",
|
|
78
61
|
"defaultValue": "AGE"
|
|
79
62
|
},
|
|
80
63
|
"queryParameter": "stratificationcategoryid",
|
|
@@ -83,16 +66,11 @@
|
|
|
83
66
|
},
|
|
84
67
|
{
|
|
85
68
|
"key": "Data Type",
|
|
86
|
-
"usedBy": [
|
|
87
|
-
"chart1"
|
|
88
|
-
],
|
|
89
69
|
"type": "urlfilter",
|
|
90
70
|
"apiFilter": {
|
|
91
|
-
"apiEndpoint": "http://test.gov/api/POC/Filters",
|
|
92
|
-
"valueSelector": "
|
|
93
|
-
"textSelector": "DataValueType"
|
|
94
|
-
"heirarchyLookup": "DataValueTypes"
|
|
95
|
-
|
|
71
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/DataValueType",
|
|
72
|
+
"valueSelector": "DataValueType",
|
|
73
|
+
"textSelector": "DataValueType"
|
|
96
74
|
},
|
|
97
75
|
"queryParameter": "datavaluetypeid",
|
|
98
76
|
"showDropdown": true,
|
|
@@ -130,7 +108,7 @@
|
|
|
130
108
|
"filters": {
|
|
131
109
|
"type": "filter-dropdowns",
|
|
132
110
|
"visualizationType": "filter-dropdowns",
|
|
133
|
-
"hide": [
|
|
111
|
+
"hide": [3, 4, 5]
|
|
134
112
|
},
|
|
135
113
|
"header": {
|
|
136
114
|
"type": "markup-include",
|
|
@@ -141,7 +119,7 @@
|
|
|
141
119
|
"subfilters": {
|
|
142
120
|
"type": "filter-dropdowns",
|
|
143
121
|
"visualizationType": "filter-dropdowns",
|
|
144
|
-
"hide": [
|
|
122
|
+
"hide": [0, 1, 2],
|
|
145
123
|
"autoLoad": true
|
|
146
124
|
},
|
|
147
125
|
"chart1": {
|
|
@@ -341,9 +319,7 @@
|
|
|
341
319
|
},
|
|
342
320
|
"validated": 4.23,
|
|
343
321
|
"dynamicMarginTop": 0,
|
|
344
|
-
"regions": [
|
|
345
|
-
{}
|
|
346
|
-
]
|
|
322
|
+
"regions": [{}]
|
|
347
323
|
}
|
|
348
324
|
},
|
|
349
325
|
"type": "dashboard",
|
|
@@ -355,4 +331,4 @@
|
|
|
355
331
|
"filterBehavior": "Apply Button",
|
|
356
332
|
"runtime": {},
|
|
357
333
|
"uuid": 1684783370106
|
|
358
|
-
}
|
|
334
|
+
}
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
"sharedFilters": [
|
|
4
4
|
{
|
|
5
5
|
"key": "Category",
|
|
6
|
-
"usedBy": [
|
|
7
|
-
"map1"
|
|
8
|
-
],
|
|
6
|
+
"usedBy": ["map1"],
|
|
9
7
|
"type": "urlfilter",
|
|
10
8
|
"apiFilter": {
|
|
11
9
|
"apiEndpoint": "http://test.gov/api/poc/topics",
|
|
@@ -18,9 +16,7 @@
|
|
|
18
16
|
},
|
|
19
17
|
{
|
|
20
18
|
"key": "Indicator",
|
|
21
|
-
"usedBy": [
|
|
22
|
-
"chart1"
|
|
23
|
-
],
|
|
19
|
+
"usedBy": ["chart1"],
|
|
24
20
|
"type": "urlfilter",
|
|
25
21
|
"apiFilter": {
|
|
26
22
|
"apiEndpoint": "http://test.gov/api/poc/indicators",
|
|
@@ -34,15 +30,12 @@
|
|
|
34
30
|
},
|
|
35
31
|
{
|
|
36
32
|
"key": "Year",
|
|
37
|
-
"usedBy": [
|
|
38
|
-
"map1"
|
|
39
|
-
],
|
|
33
|
+
"usedBy": ["map1"],
|
|
40
34
|
"type": "urlfilter",
|
|
41
35
|
"apiFilter": {
|
|
42
|
-
"apiEndpoint": "http://test.gov/api/POC/Filters",
|
|
36
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/Year",
|
|
43
37
|
"valueSelector": "Year",
|
|
44
|
-
"textSelector": "Year"
|
|
45
|
-
"heirarchyLookup": "Years"
|
|
38
|
+
"textSelector": "Year"
|
|
46
39
|
},
|
|
47
40
|
"queryParameter": "year",
|
|
48
41
|
"resetLabel": "- Select -",
|
|
@@ -51,15 +44,12 @@
|
|
|
51
44
|
},
|
|
52
45
|
{
|
|
53
46
|
"key": "View By",
|
|
54
|
-
"usedBy": [
|
|
55
|
-
"map1"
|
|
56
|
-
],
|
|
47
|
+
"usedBy": ["map1"],
|
|
57
48
|
"type": "urlfilter",
|
|
58
49
|
"apiFilter": {
|
|
59
|
-
"apiEndpoint": "http://test.gov/api/POC/Filters",
|
|
60
|
-
"valueSelector": "
|
|
61
|
-
"textSelector": "StratificationCategory"
|
|
62
|
-
"heirarchyLookup": "StratificationCategories"
|
|
50
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/StratificationCategory",
|
|
51
|
+
"valueSelector": "StratificationCategory",
|
|
52
|
+
"textSelector": "StratificationCategory"
|
|
63
53
|
},
|
|
64
54
|
"resetLabel": "- Select -",
|
|
65
55
|
"queryParameter": "stratificationcategoryid",
|
|
@@ -68,13 +58,11 @@
|
|
|
68
58
|
},
|
|
69
59
|
{
|
|
70
60
|
"key": "Stratification",
|
|
71
|
-
"usedBy": [
|
|
72
|
-
"map1"
|
|
73
|
-
],
|
|
61
|
+
"usedBy": ["map1"],
|
|
74
62
|
"type": "urlfilter",
|
|
75
63
|
"apiFilter": {
|
|
76
|
-
"apiEndpoint": "http://test.gov/api/POC/
|
|
77
|
-
"valueSelector": "
|
|
64
|
+
"apiEndpoint": "http://test.gov/api/POC/Filters/Stratification",
|
|
65
|
+
"valueSelector": "Stratification",
|
|
78
66
|
"textSelector": "Stratification"
|
|
79
67
|
},
|
|
80
68
|
"resetLabel": "- Select -",
|
|
@@ -149,8 +137,8 @@
|
|
|
149
137
|
"suffix": "%",
|
|
150
138
|
"name": "LowConfidenceLimit",
|
|
151
139
|
"tooltip": true
|
|
152
|
-
|
|
153
|
-
|
|
140
|
+
},
|
|
141
|
+
"additionalColumn2": {
|
|
154
142
|
"label": "High Confidence Limit",
|
|
155
143
|
"dataTable": true,
|
|
156
144
|
"tooltips": false,
|
|
@@ -158,7 +146,7 @@
|
|
|
158
146
|
"suffix": "%",
|
|
159
147
|
"name": "HighConfidenceLimit",
|
|
160
148
|
"tooltip": true
|
|
161
|
-
|
|
149
|
+
},
|
|
162
150
|
"navigate": {
|
|
163
151
|
"name": "link",
|
|
164
152
|
"tooltip": false,
|
|
@@ -173,9 +161,7 @@
|
|
|
173
161
|
},
|
|
174
162
|
"legend": {
|
|
175
163
|
"descriptions": {},
|
|
176
|
-
"specialClasses": [
|
|
177
|
-
"NA"
|
|
178
|
-
],
|
|
164
|
+
"specialClasses": ["NA"],
|
|
179
165
|
"unified": false,
|
|
180
166
|
"singleColumn": false,
|
|
181
167
|
"dynamicDescription": false,
|
|
@@ -196,4 +182,4 @@
|
|
|
196
182
|
"filterBehavior": "Apply Button",
|
|
197
183
|
"runtime": {},
|
|
198
184
|
"uuid": 1684783370106
|
|
199
|
-
}
|
|
185
|
+
}
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
},
|
|
165
165
|
"table": {
|
|
166
166
|
"label": "Data Table",
|
|
167
|
-
"expanded":
|
|
167
|
+
"expanded": false,
|
|
168
168
|
"limitHeight": false,
|
|
169
169
|
"height": "",
|
|
170
170
|
"caption": "",
|
|
@@ -366,11 +366,10 @@
|
|
|
366
366
|
},
|
|
367
367
|
"table": {
|
|
368
368
|
"label": "Data Table",
|
|
369
|
-
"show":
|
|
369
|
+
"show": false,
|
|
370
370
|
"showDownloadUrl": false,
|
|
371
371
|
"showVertical": true
|
|
372
372
|
},
|
|
373
|
-
"newViz": true,
|
|
374
373
|
"datasets": {},
|
|
375
374
|
"type": "dashboard",
|
|
376
375
|
"runtime": {},
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dashboard": {
|
|
3
3
|
"theme": "theme-blue",
|
|
4
|
-
"sharedFilters": [
|
|
5
|
-
{
|
|
6
|
-
"key": "Race",
|
|
7
|
-
"type": "datafilter",
|
|
8
|
-
"showDropdown": true,
|
|
9
|
-
"columnName": "Race",
|
|
10
|
-
"pivot": "Age-adjusted rate",
|
|
11
|
-
"usedBy": ["table1707935263149"]
|
|
12
|
-
}
|
|
13
|
-
]
|
|
4
|
+
"sharedFilters": []
|
|
14
5
|
},
|
|
15
6
|
"rows": [
|
|
16
7
|
[
|
|
@@ -32,7 +23,11 @@
|
|
|
32
23
|
"show": true,
|
|
33
24
|
"showDownloadUrl": false,
|
|
34
25
|
"showVertical": true,
|
|
35
|
-
"expanded": true
|
|
26
|
+
"expanded": true,
|
|
27
|
+
"pivot": {
|
|
28
|
+
"columnName": "Race",
|
|
29
|
+
"valueColumn": "Age-adjusted rate"
|
|
30
|
+
}
|
|
36
31
|
},
|
|
37
32
|
"columns": {},
|
|
38
33
|
"dataFormat": {},
|
|
@@ -41,7 +36,14 @@
|
|
|
41
36
|
"horizontal": false,
|
|
42
37
|
"series": false
|
|
43
38
|
},
|
|
44
|
-
"filters": [
|
|
39
|
+
"filters": [
|
|
40
|
+
{
|
|
41
|
+
"filterStyle": "multi-select",
|
|
42
|
+
"label": "Race",
|
|
43
|
+
"columnName": "Race",
|
|
44
|
+
"showDropdown": true
|
|
45
|
+
}
|
|
46
|
+
],
|
|
45
47
|
"filterBehavior": "Filter Change",
|
|
46
48
|
"formattedData": [
|
|
47
49
|
{
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react'
|
|
2
|
+
import Icon from '../../../core/components/ui/Icon'
|
|
3
|
+
|
|
4
|
+
type CollapsableVizRow = {
|
|
5
|
+
allExpanded: boolean
|
|
6
|
+
children: React.ReactNode
|
|
7
|
+
fontSize: string
|
|
8
|
+
groupName: string
|
|
9
|
+
currentViewport: string
|
|
10
|
+
}
|
|
11
|
+
const CollapsibleVisualizationRow: React.FC<CollapsableVizRow> = ({ allExpanded, fontSize, groupName, currentViewport, children }) => {
|
|
12
|
+
const [isExpanded, setIsExpanded] = useState(allExpanded)
|
|
13
|
+
const fontSizes = { small: 16, medium: 18, large: 20 }
|
|
14
|
+
const titleFontSize = ['sm', 'xs', 'xxs'].includes(currentViewport) ? '13px' : `${fontSizes[fontSize]}px`
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
setIsExpanded(allExpanded)
|
|
18
|
+
}, [allExpanded])
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<div
|
|
23
|
+
style={{ fontSize: titleFontSize }}
|
|
24
|
+
role='button'
|
|
25
|
+
className={`multi-visualiation-heading${isExpanded ? '' : ' collapsed'} h4`}
|
|
26
|
+
onClick={() => {
|
|
27
|
+
setIsExpanded(!isExpanded)
|
|
28
|
+
}}
|
|
29
|
+
tabIndex={0}
|
|
30
|
+
onKeyDown={e => {
|
|
31
|
+
if (e.keyCode === 13) {
|
|
32
|
+
setIsExpanded(!isExpanded)
|
|
33
|
+
}
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<Icon display={isExpanded ? 'minus' : 'plus'} base />
|
|
37
|
+
{groupName}
|
|
38
|
+
</div>
|
|
39
|
+
{isExpanded && children}
|
|
40
|
+
</>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default CollapsibleVisualizationRow
|
|
@@ -40,7 +40,7 @@ const Column = ({ data, rowIdx, colIdx }) => {
|
|
|
40
40
|
return (
|
|
41
41
|
<div className={classNames.join(' ')} ref={drop}>
|
|
42
42
|
{widget ? (
|
|
43
|
-
<Widget
|
|
43
|
+
<Widget widgetConfig={{ rowIdx, colIdx, ...widget }} type={widget.visualizationType ?? widget.general?.geoType} />
|
|
44
44
|
) : (
|
|
45
45
|
<p className='builder-column__text'>
|
|
46
46
|
Drag and drop <br /> visualization
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SharedFilter } from '../../types/SharedFilter'
|
|
2
|
+
import { APIFilterDropdowns } from './DashboardFiltersWrapper'
|
|
3
|
+
|
|
4
|
+
type DashboardFilterProps = {
|
|
5
|
+
show: number[]
|
|
6
|
+
filters: SharedFilter[]
|
|
7
|
+
apiFilterDropdowns: APIFilterDropdowns
|
|
8
|
+
handleOnChange: Function
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const DashboardFilters: React.FC<DashboardFilterProps> = ({ show, filters, apiFilterDropdowns, handleOnChange }) => {
|
|
12
|
+
const nullVal = (singleFilter: SharedFilter) => {
|
|
13
|
+
const val = singleFilter.queuedActive || singleFilter.active
|
|
14
|
+
return val === null || val === undefined || val === ''
|
|
15
|
+
}
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
{filters.map((singleFilter, filterIndex) => {
|
|
19
|
+
if ((singleFilter.type !== 'urlfilter' && !singleFilter.showDropdown) || (show && !show.includes(filterIndex))) return <></>
|
|
20
|
+
const values: JSX.Element[] = []
|
|
21
|
+
const multiValues = []
|
|
22
|
+
if (singleFilter.resetLabel) {
|
|
23
|
+
values.push(
|
|
24
|
+
<option key={`${singleFilter.resetLabel}-option`} value={singleFilter.resetLabel}>
|
|
25
|
+
{singleFilter.resetLabel}
|
|
26
|
+
</option>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
const _key = singleFilter.apiFilter?.apiEndpoint
|
|
30
|
+
if (_key && apiFilterDropdowns[_key]) {
|
|
31
|
+
// URL Filter
|
|
32
|
+
apiFilterDropdowns[_key].forEach(({ text, value }, index) => {
|
|
33
|
+
values.push(
|
|
34
|
+
<option key={`${value}-option-${index}`} value={value}>
|
|
35
|
+
{text}
|
|
36
|
+
</option>
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
} else {
|
|
40
|
+
// Data Filter
|
|
41
|
+
singleFilter.values?.forEach((filterOption, index) => {
|
|
42
|
+
const labeledOpt = singleFilter.labels && singleFilter.labels[filterOption]
|
|
43
|
+
values.push(
|
|
44
|
+
<option key={`${singleFilter.key}-option-${index}`} value={filterOption}>
|
|
45
|
+
{labeledOpt || filterOption}
|
|
46
|
+
</option>
|
|
47
|
+
)
|
|
48
|
+
multiValues.push({ value: filterOption, label: labeledOpt || filterOption })
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className='cove-dashboard-filters' key={`${singleFilter.key}-filtersection-${filterIndex}`}>
|
|
54
|
+
<section className='dashboard-filters-section'>
|
|
55
|
+
<label htmlFor={`filter-${filterIndex}`}>{singleFilter.key}</label>
|
|
56
|
+
<select
|
|
57
|
+
id={`filter-${filterIndex}`}
|
|
58
|
+
className='filter-select'
|
|
59
|
+
data-index='0'
|
|
60
|
+
value={singleFilter.queuedActive || singleFilter.active}
|
|
61
|
+
onChange={val => {
|
|
62
|
+
handleOnChange(filterIndex, val.target.value)
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{nullVal(singleFilter) && !singleFilter.resetLabel && (
|
|
66
|
+
<option value='' key='select'>
|
|
67
|
+
{'-Select-'}
|
|
68
|
+
</option>
|
|
69
|
+
)}
|
|
70
|
+
{values}
|
|
71
|
+
</select>
|
|
72
|
+
</section>
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
})}
|
|
76
|
+
</>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default DashboardFilters
|