@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.
- 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 +48574 -46414
- 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 +39095 -39077
- package/examples/private/clade-2.json +430 -0
- package/examples/private/delete.json +32919 -0
- package/examples/private/diabetes.json +546 -196
- package/examples/private/markup-footer/mortality-deaths-footnotes-age.csv +3 -0
- package/examples/private/mpox.json +38128 -0
- package/examples/private/reset.json +32920 -0
- package/examples/test-api-filter-reset.json +132 -0
- package/index.html +2 -2
- package/package.json +9 -10
- package/src/CdcDashboardComponent.tsx +17 -8
- package/src/DashboardContext.tsx +3 -1
- package/src/_stories/Dashboard.stories.tsx +17 -0
- package/src/_stories/_mock/custom-order-new-values.json +116 -0
- package/src/components/DashboardFilters/DashboardFilters.tsx +34 -20
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +29 -12
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +77 -111
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +51 -51
- package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +120 -24
- package/src/components/DashboardFilters/_stories/DashboardFilters.stories.tsx +62 -3
- package/src/components/DataDesignerModal.tsx +12 -5
- package/src/components/Header/Header.tsx +10 -9
- package/src/components/Toggle/Toggle.tsx +48 -48
- package/src/components/VisualizationRow.tsx +4 -3
- package/src/helpers/addValuesToDashboardFilters.ts +29 -4
- package/src/helpers/apiFilterHelpers.ts +26 -2
- package/src/helpers/filterData.ts +52 -7
- package/src/helpers/filterResetHelpers.ts +102 -0
- package/src/helpers/getVizConfig.ts +2 -2
- package/src/helpers/loadAPIFilters.ts +109 -99
- package/src/helpers/tests/filterResetHelpers.test.ts +532 -0
- package/src/index.tsx +1 -0
- package/src/scss/editor-panel.scss +3 -431
- package/src/scss/main.scss +1 -24
- package/src/store/errorMessage/errorMessage.reducer.ts +1 -1
- package/src/types/DashboardFilters.ts +9 -8
- package/examples/private/burden_toolkit_mortality_diabetes_attributable_deaths_data.csv +0 -14041
- package/examples/private/burden_toolkit_mortality_diabetes_attributable_deaths_per_100000_data.csv +0 -14041
- package/examples/private/burden_toolkit_mortality_qaly_data.csv +0 -18721
- package/examples/private/burden_toolkit_mortality_yll_data.csv +0 -18721
- 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,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dashboard": {
|
|
3
|
+
"theme": "theme-blue",
|
|
4
|
+
"sharedFilters": [
|
|
5
|
+
{
|
|
6
|
+
"key": "Category",
|
|
7
|
+
"type": "urlfilter",
|
|
8
|
+
"columnName": "category",
|
|
9
|
+
"apiFilter": {
|
|
10
|
+
"apiEndpoint": "http://localhost:8080/examples/api-test/categories.json",
|
|
11
|
+
"valueSelector": "category",
|
|
12
|
+
"textSelector": "category"
|
|
13
|
+
},
|
|
14
|
+
"queryParameter": "category",
|
|
15
|
+
"resetLabel": "- Select Category -",
|
|
16
|
+
"showDropdown": true,
|
|
17
|
+
"filterStyle": "dropdown",
|
|
18
|
+
"usedBy": ["chart1"]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"key": "Topic",
|
|
22
|
+
"type": "urlfilter",
|
|
23
|
+
"columnName": "topic",
|
|
24
|
+
"apiFilter": {
|
|
25
|
+
"apiEndpoint": "http://localhost:8080/examples/api-test/topics.json",
|
|
26
|
+
"valueSelector": "topic",
|
|
27
|
+
"textSelector": "topic"
|
|
28
|
+
},
|
|
29
|
+
"queryParameter": "topic",
|
|
30
|
+
"resetLabel": "- Select Topic -",
|
|
31
|
+
"showDropdown": true,
|
|
32
|
+
"parents": [
|
|
33
|
+
"Category"
|
|
34
|
+
],
|
|
35
|
+
"filterStyle": "dropdown",
|
|
36
|
+
"usedBy": ["chart1"]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"key": "Year",
|
|
40
|
+
"type": "urlfilter",
|
|
41
|
+
"columnName": "year",
|
|
42
|
+
"apiFilter": {
|
|
43
|
+
"apiEndpoint": "http://localhost:8080/examples/api-test/years.json",
|
|
44
|
+
"valueSelector": "year",
|
|
45
|
+
"textSelector": "year"
|
|
46
|
+
},
|
|
47
|
+
"queryParameter": "year",
|
|
48
|
+
"resetLabel": "- Select -",
|
|
49
|
+
"showDropdown": true,
|
|
50
|
+
"parents": [
|
|
51
|
+
"Category",
|
|
52
|
+
"Topic"
|
|
53
|
+
],
|
|
54
|
+
"filterStyle": "dropdown",
|
|
55
|
+
"usedBy": ["chart1"]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"rows": [
|
|
60
|
+
[
|
|
61
|
+
{
|
|
62
|
+
"width": 12,
|
|
63
|
+
"widget": "filters"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
"width": 12,
|
|
69
|
+
"widget": "header"
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
[
|
|
73
|
+
{
|
|
74
|
+
"width": 12,
|
|
75
|
+
"widget": "chart1"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
],
|
|
79
|
+
"visualizations": {
|
|
80
|
+
"filters": {
|
|
81
|
+
"type": "dashboardFilters",
|
|
82
|
+
"visualizationType": "dashboardFilters",
|
|
83
|
+
"sharedFilterIndexes": [
|
|
84
|
+
0,
|
|
85
|
+
1,
|
|
86
|
+
2
|
|
87
|
+
],
|
|
88
|
+
"filterBehavior": "Apply Button",
|
|
89
|
+
"applyFiltersButtonText": "Apply Filters"
|
|
90
|
+
},
|
|
91
|
+
"header": {
|
|
92
|
+
"type": "markup-include",
|
|
93
|
+
"title": "Test API Filter Reset",
|
|
94
|
+
"contentEditor": {
|
|
95
|
+
"inlineHTML": "<h2>API Filter Reset Test Dashboard</h2><p>This dashboard tests the 'Clear Filters' button functionality with API filters.</p><ul><li><strong>Category</strong>: Has resetLabel = '- Select Category -'</li><li><strong>Topic</strong>: Has resetLabel = '- Select Topic -' (depends on Category)</li><li><strong>Year</strong>: Has defaultValue = '2023' (depends on Category and Topic)</li></ul><h3>Testing Instructions:</h3><ol><li>Select values for all three filters</li><li>Click 'Apply Filters'</li><li>Click 'Clear Filters'</li><li>Expected behavior:<ul><li>Category and Topic should reset to '- Select Category -' and '- Select Topic -'</li><li>Year should reset to '2023' (its defaultValue)</li></ul></li></ol>",
|
|
96
|
+
"useInlineHTML": true
|
|
97
|
+
},
|
|
98
|
+
"theme": "theme-blue"
|
|
99
|
+
},
|
|
100
|
+
"chart1": {
|
|
101
|
+
"type": "chart",
|
|
102
|
+
"title": "Sample Chart",
|
|
103
|
+
"showTitle": true,
|
|
104
|
+
"theme": "theme-blue",
|
|
105
|
+
"visualizationType": "Line",
|
|
106
|
+
"dataKey": "chartData",
|
|
107
|
+
"xAxis": {
|
|
108
|
+
"dataKey": "state",
|
|
109
|
+
"type": "categorical"
|
|
110
|
+
},
|
|
111
|
+
"series": [
|
|
112
|
+
{
|
|
113
|
+
"dataKey": "value",
|
|
114
|
+
"type": "Line"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"general": {
|
|
118
|
+
"showDownloadButton": false
|
|
119
|
+
},
|
|
120
|
+
"table": {
|
|
121
|
+
"showTableButton": false
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"datasets": {
|
|
126
|
+
"chartData": {
|
|
127
|
+
"dataUrl": "http://localhost:8080/examples/api-test/chart-data.json"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"filterBehavior": "Apply Button",
|
|
131
|
+
"type": "dashboard"
|
|
132
|
+
}
|
package/index.html
CHANGED
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
</head>
|
|
23
23
|
|
|
24
24
|
<body>
|
|
25
|
-
<div class="react-container" data-config="/examples/
|
|
25
|
+
<div class="react-container" data-config="/examples/markup-axis-label.json"></div>
|
|
26
26
|
<script src="https://www.cdc.gov/TemplatePackage/contrib/libs/jquery/latest/jquery.min.js?_=91329"></script>
|
|
27
27
|
<script type="module" src="./src/index.tsx"></script>
|
|
28
28
|
</body>
|
|
29
29
|
|
|
30
|
-
</html>
|
|
30
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/dashboard",
|
|
3
|
-
"version": "4.25.
|
|
3
|
+
"version": "4.25.11",
|
|
4
4
|
"description": "React component for combining multiple visualizations into a single dashboard",
|
|
5
5
|
"moduleName": "CdcDashboard",
|
|
6
6
|
"main": "dist/cdcdashboard",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cdc/chart": "^4.25.
|
|
31
|
-
"@cdc/core": "^4.25.
|
|
32
|
-
"@cdc/data-bite": "^4.25.
|
|
33
|
-
"@cdc/filtered-text": "^4.25.
|
|
34
|
-
"@cdc/map": "^4.25.
|
|
35
|
-
"@cdc/markup-include": "^4.25.
|
|
36
|
-
"@cdc/waffle-chart": "^4.25.
|
|
30
|
+
"@cdc/chart": "^4.25.11",
|
|
31
|
+
"@cdc/core": "^4.25.11",
|
|
32
|
+
"@cdc/data-bite": "^4.25.11",
|
|
33
|
+
"@cdc/filtered-text": "^4.25.11",
|
|
34
|
+
"@cdc/map": "^4.25.11",
|
|
35
|
+
"@cdc/markup-include": "^4.25.11",
|
|
36
|
+
"@cdc/waffle-chart": "^4.25.11",
|
|
37
37
|
"js-base64": "^2.5.2",
|
|
38
38
|
"react-accessible-accordion": "^5.0.1",
|
|
39
39
|
"react-dnd": "^14.0.2",
|
|
@@ -45,11 +45,10 @@
|
|
|
45
45
|
"react-dom": "^18.2.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@rollup/plugin-dsv": "^3.0.2",
|
|
49
48
|
"@vitejs/plugin-react": "^4.3.4",
|
|
50
49
|
"vite": "^4.4.11",
|
|
51
50
|
"vite-plugin-css-injected-by-js": "^2.4.0",
|
|
52
51
|
"vite-plugin-svgr": "^2.4.0"
|
|
53
52
|
},
|
|
54
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "5f09a137c22f454111ab5f4cd7fdf1d2d58e31bd"
|
|
55
54
|
}
|
|
@@ -23,7 +23,7 @@ import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
|
23
23
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
24
24
|
|
|
25
25
|
import Grid from './components/Grid'
|
|
26
|
-
import Header from './components/Header
|
|
26
|
+
import Header from './components/Header'
|
|
27
27
|
import DataTable from '@cdc/core/components/DataTable'
|
|
28
28
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
29
29
|
|
|
@@ -32,7 +32,7 @@ import './scss/main.scss'
|
|
|
32
32
|
import VisualizationsPanel from './components/VisualizationsPanel'
|
|
33
33
|
import dashboardReducer from './store/dashboard.reducer'
|
|
34
34
|
import errorMessagesReducer from './store/errorMessage/errorMessage.reducer'
|
|
35
|
-
import { filterData } from './helpers/filterData'
|
|
35
|
+
import { filterData, isFilterAtResetState } from './helpers/filterData'
|
|
36
36
|
import { getVizKeys } from './helpers/getVizKeys'
|
|
37
37
|
import Title from '@cdc/core/components/ui/Title'
|
|
38
38
|
import { type TableConfig } from '@cdc/core/components/DataTable/types/TableConfig'
|
|
@@ -89,10 +89,17 @@ export default function CdcDashboard({
|
|
|
89
89
|
return true
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// Check if any filters are at their reset state (incomplete)
|
|
93
|
+
const sharedFilters = state.config.dashboard?.sharedFilters || []
|
|
94
|
+
const hasResetFilters = sharedFilters.some(isFilterAtResetState)
|
|
95
|
+
if (hasResetFilters) {
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
92
99
|
const vals = reloadURLHelpers.getDatasetKeys(state.config).map(key => state.data[key])
|
|
93
100
|
if (!vals.length) return true
|
|
94
101
|
return vals.some(val => val === undefined)
|
|
95
|
-
}, [state.data, state.config.visualizations, state.filtersApplied])
|
|
102
|
+
}, [state.data, state.config.visualizations, state.config.dashboard?.sharedFilters, state.filtersApplied])
|
|
96
103
|
|
|
97
104
|
const vizRowColumnLocator = getVizRowColumnLocator(state.config.rows)
|
|
98
105
|
|
|
@@ -165,9 +172,13 @@ export default function CdcDashboard({
|
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
if (filter.apiFilter && filter.active) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
// Don't add filter to query params if it's set to its resetLabel
|
|
176
|
+
const isResetLabel = filter.resetLabel && filter.active === filter.resetLabel
|
|
177
|
+
if (!isResetLabel) {
|
|
178
|
+
updatedQSParams[filter.apiFilter.valueSelector] = filter.active
|
|
179
|
+
if (filter.apiFilter.subgroupValueSelector && filter.subGrouping.active) {
|
|
180
|
+
updatedQSParams[filter.apiFilter.subgroupValueSelector] = filter.subGrouping.active
|
|
181
|
+
}
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
}
|
|
@@ -292,8 +303,6 @@ export default function CdcDashboard({
|
|
|
292
303
|
}
|
|
293
304
|
|
|
294
305
|
const setEventData = ({ detail }, data, filteredData) => {
|
|
295
|
-
// eslint-disable-next-line no-console
|
|
296
|
-
console.log('Event: cove_set_data', detail)
|
|
297
306
|
try {
|
|
298
307
|
const newDatasets = Object.keys(detail).reduce((acc, key) => {
|
|
299
308
|
if (data[key] !== undefined) {
|
package/src/DashboardContext.tsx
CHANGED
|
@@ -15,7 +15,9 @@ type ConfigCTX = DashboardState & {
|
|
|
15
15
|
loadAPIFilters: (
|
|
16
16
|
sharedFilters: SharedFilter[],
|
|
17
17
|
dropdowns: APIFilterDropdowns,
|
|
18
|
-
|
|
18
|
+
loadAll?: boolean,
|
|
19
|
+
recursiveLimit?: number,
|
|
20
|
+
isStale?: () => boolean
|
|
19
21
|
) => Promise<SharedFilter[]>
|
|
20
22
|
setAPIFilterDropdowns: (dropdowns: APIFilterDropdowns) => void
|
|
21
23
|
setAPILoading: (loading: boolean) => void
|
|
@@ -28,6 +28,8 @@ import TopSpacing_1 from './_mock/data-bite-dash-test.json'
|
|
|
28
28
|
import TopSpacing_2 from './_mock/data-bite-dash-test_1.json'
|
|
29
29
|
import TopSpacing_3 from './_mock/data-bite-dash-test_1_1.json'
|
|
30
30
|
import TopSpacing_4 from './_mock/data-bite-dash-test_1_1_1.json'
|
|
31
|
+
import CustomOrderNewValues from './_mock/custom-order-new-values.json'
|
|
32
|
+
import APIFilterResetConfig from '../../examples/test-api-filter-reset.json'
|
|
31
33
|
|
|
32
34
|
// Dashboard Filter Updates for Ascending, Descending, and Custom Order
|
|
33
35
|
import DashboardFilterAsc from './_mock/dashboard-filter-asc.json'
|
|
@@ -38,6 +40,7 @@ DashboardFilterCust.dashboard.sharedFilters[0].order = 'cust'
|
|
|
38
40
|
|
|
39
41
|
// On DashboardFilterCust change the sharedFilters[0].values and orderedValues to be in a custom order
|
|
40
42
|
const customOrder = ['American Samoa', 'Alaska', 'Alabama', 'Arizona', 'Arkansas']
|
|
43
|
+
DashboardFilterCust.dashboard.sharedFilters[0].orderedValues = customOrder
|
|
41
44
|
|
|
42
45
|
const meta: Meta<typeof Dashboard> = {
|
|
43
46
|
title: 'Components/Pages/Dashboard',
|
|
@@ -67,6 +70,13 @@ export const Dashboard_Filter_Cust: Story = {
|
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
export const CustomOrder_NewValues_AutoAppend: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
config: CustomOrderNewValues,
|
|
76
|
+
isEditor: false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
export const Example_1: Story = {
|
|
71
81
|
args: {
|
|
72
82
|
config: ExampleConfig_1,
|
|
@@ -472,4 +482,11 @@ export const Top_Spacing_4: Story = {
|
|
|
472
482
|
}
|
|
473
483
|
}
|
|
474
484
|
|
|
485
|
+
export const Clear_Filters_Button: Story = {
|
|
486
|
+
args: {
|
|
487
|
+
config: APIFilterResetConfig as unknown as Config,
|
|
488
|
+
isEditor: false
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
475
492
|
export default meta
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dashboard": {
|
|
3
|
+
"theme": "theme-blue",
|
|
4
|
+
"title": "Custom Order Filter - New Values Auto-Append Demo",
|
|
5
|
+
"sharedFilters": [
|
|
6
|
+
{
|
|
7
|
+
"key": "Location",
|
|
8
|
+
"columnName": "Location",
|
|
9
|
+
"showDropdown": true,
|
|
10
|
+
"type": "datafilter",
|
|
11
|
+
"order": "cust",
|
|
12
|
+
"orderedValues": [
|
|
13
|
+
"California",
|
|
14
|
+
"Texas",
|
|
15
|
+
"Florida"
|
|
16
|
+
],
|
|
17
|
+
"usedBy": [
|
|
18
|
+
"data-bite-demo",
|
|
19
|
+
"chart-demo"
|
|
20
|
+
],
|
|
21
|
+
"tier": 1
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"datasets": {
|
|
26
|
+
"custom-order-demo-data.csv": {
|
|
27
|
+
"dataUrl": "http://localhost:6006/custom-order-demo-data.csv"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"rows": [
|
|
31
|
+
{
|
|
32
|
+
"columns": [
|
|
33
|
+
{
|
|
34
|
+
"width": 12,
|
|
35
|
+
"widget": "legacySharedFilters"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"columns": [
|
|
41
|
+
{
|
|
42
|
+
"width": 6,
|
|
43
|
+
"widget": "data-bite-demo"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"width": 6,
|
|
47
|
+
"widget": "chart-demo"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"visualizations": {
|
|
53
|
+
"data-bite-demo": {
|
|
54
|
+
"type": "data-bite",
|
|
55
|
+
"dataKey": "custom-order-demo-data.csv",
|
|
56
|
+
"dataFunction": "Sum",
|
|
57
|
+
"dataColumn": "Amount",
|
|
58
|
+
"bitePosition": "Left",
|
|
59
|
+
"biteFontSize": 36,
|
|
60
|
+
"fontSize": "large",
|
|
61
|
+
"biteBody": "<h3>Total Amount for Selected Location</h3><p><strong>Custom Order Demo:</strong> The filter has custom order: <em>California, Texas, Florida</em>. But the CSV data includes <strong>New York</strong> and <strong>Illinois</strong> which should auto-append to the end of the dropdown.</p><p>Select different locations from the dropdown above to see the total amount update.</p>",
|
|
62
|
+
"dataFormat": {
|
|
63
|
+
"roundToPlace": 0,
|
|
64
|
+
"commas": true,
|
|
65
|
+
"prefix": "$",
|
|
66
|
+
"suffix": ""
|
|
67
|
+
},
|
|
68
|
+
"biteStyle": "graphic",
|
|
69
|
+
"theme": "theme-blue",
|
|
70
|
+
"shadow": true,
|
|
71
|
+
"uid": "data-bite-demo",
|
|
72
|
+
"visualizationType": "data-bite"
|
|
73
|
+
},
|
|
74
|
+
"chart-demo": {
|
|
75
|
+
"type": "chart",
|
|
76
|
+
"title": "Amount by Year",
|
|
77
|
+
"theme": "theme-blue",
|
|
78
|
+
"fontSize": "medium",
|
|
79
|
+
"height": "250",
|
|
80
|
+
"yAxis": {
|
|
81
|
+
"label": "Amount",
|
|
82
|
+
"gridLines": true
|
|
83
|
+
},
|
|
84
|
+
"xAxis": {
|
|
85
|
+
"dataKey": "Year",
|
|
86
|
+
"label": "Year"
|
|
87
|
+
},
|
|
88
|
+
"table": {
|
|
89
|
+
"show": true,
|
|
90
|
+
"label": "Data Table"
|
|
91
|
+
},
|
|
92
|
+
"legend": {
|
|
93
|
+
"hide": true
|
|
94
|
+
},
|
|
95
|
+
"visualizationType": "Bar",
|
|
96
|
+
"series": [
|
|
97
|
+
{
|
|
98
|
+
"dataKey": "Amount",
|
|
99
|
+
"type": "Bar"
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"dataKey": "custom-order-demo-data.csv",
|
|
103
|
+
"uid": "chart-demo"
|
|
104
|
+
},
|
|
105
|
+
"legacySharedFilters": {
|
|
106
|
+
"type": "dashboardFilters",
|
|
107
|
+
"visualizationType": "dashboardFilters",
|
|
108
|
+
"sharedFilterIndexes": [
|
|
109
|
+
0
|
|
110
|
+
],
|
|
111
|
+
"filterBehavior": "Filter Change",
|
|
112
|
+
"uid": "legacySharedFilters"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"type": "dashboard"
|
|
116
|
+
}
|
|
@@ -18,6 +18,7 @@ type DashboardFilterProps = {
|
|
|
18
18
|
showSubmit: boolean
|
|
19
19
|
applyFilters: MouseEventHandler<HTMLButtonElement>
|
|
20
20
|
applyFiltersButtonText?: string
|
|
21
|
+
handleReset?: MouseEventHandler<HTMLButtonElement>
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
@@ -27,7 +28,8 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
27
28
|
handleOnChange,
|
|
28
29
|
showSubmit,
|
|
29
30
|
applyFilters,
|
|
30
|
-
applyFiltersButtonText
|
|
31
|
+
applyFiltersButtonText,
|
|
32
|
+
handleReset
|
|
31
33
|
}) => {
|
|
32
34
|
const nullVal = (filter: SharedFilter) => {
|
|
33
35
|
const val = filter.queuedActive || filter.active
|
|
@@ -115,8 +117,8 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
const isDisabled = !values.length
|
|
118
|
-
// push reset label only if it does not includes in filter values
|
|
119
|
-
if (filter.resetLabel && !filter.values.includes(filter.resetLabel)) {
|
|
120
|
+
// push reset label only if it does not includes in filter values options
|
|
121
|
+
if (filter.resetLabel && !filter.values.includes(filter.resetLabel) && !_key) {
|
|
120
122
|
values.unshift(
|
|
121
123
|
<option key={`${filter.resetLabel}-option`} value={filter.resetLabel}>
|
|
122
124
|
{filter.resetLabel}
|
|
@@ -145,9 +147,7 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
145
147
|
) : filter.filterStyle === FILTER_STYLE.nestedDropdown ? (
|
|
146
148
|
<NestedDropdown
|
|
147
149
|
activeGroup={(filter.queuedActive?.[0] || filter.active) as string}
|
|
148
|
-
activeSubGroup={
|
|
149
|
-
_key ? filter.queuedActive?.[1] || filter.subGrouping?.active : filter.subGrouping?.active
|
|
150
|
-
}
|
|
150
|
+
activeSubGroup={(filter.queuedActive?.[1] || filter.subGrouping?.active) as string}
|
|
151
151
|
filterIndex={filterIndex}
|
|
152
152
|
options={_key ? getNestedDropdownOptions(apiFilterDropdowns[_key]) : nestedOptions}
|
|
153
153
|
listLabel={label}
|
|
@@ -167,7 +167,14 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
167
167
|
disabled={loading || isDisabled}
|
|
168
168
|
>
|
|
169
169
|
{loading && <option value='Loading...'>Loading...</option>}
|
|
170
|
-
{
|
|
170
|
+
{/* For API filters, show placeholder when no value is selected */}
|
|
171
|
+
{_key && nullVal(filter) && (
|
|
172
|
+
<option key={`reset-label`} value=''>
|
|
173
|
+
{filter.resetLabel || '- Select One -'}
|
|
174
|
+
</option>
|
|
175
|
+
)}
|
|
176
|
+
{/* For non-API filters or when no value is selected, show empty option */}
|
|
177
|
+
{!_key && nullVal(filter) && (
|
|
171
178
|
<option key={`select`} value=''>
|
|
172
179
|
{filter.resetLabel || '- Select -'}
|
|
173
180
|
</option>
|
|
@@ -181,19 +188,26 @@ const DashboardFilters: React.FC<DashboardFilterProps> = ({
|
|
|
181
188
|
)
|
|
182
189
|
})}
|
|
183
190
|
{showSubmit && (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
<>
|
|
192
|
+
<button
|
|
193
|
+
className='btn btn-primary mb-1 me-2'
|
|
194
|
+
onClick={applyFilters}
|
|
195
|
+
disabled={show.some(filterIndex => {
|
|
196
|
+
const emptyFilterValues = [undefined, '', '- Select -']
|
|
197
|
+
return (
|
|
198
|
+
emptyFilterValues.includes(sharedFilters[filterIndex].queuedActive) &&
|
|
199
|
+
emptyFilterValues.includes(sharedFilters[filterIndex].active)
|
|
200
|
+
)
|
|
201
|
+
})}
|
|
202
|
+
>
|
|
203
|
+
{applyFiltersButtonText || 'GO!'}
|
|
204
|
+
</button>
|
|
205
|
+
{handleReset && (
|
|
206
|
+
<button className='btn btn-link mb-1' onClick={handleReset}>
|
|
207
|
+
Clear Filters
|
|
208
|
+
</button>
|
|
209
|
+
)}
|
|
210
|
+
</>
|
|
197
211
|
)}
|
|
198
212
|
</form>
|
|
199
213
|
)
|
|
@@ -43,9 +43,10 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
43
43
|
return config.dashboard.sharedFilters
|
|
44
44
|
?.map<[number, string]>(({ key }, i) => [i, key])
|
|
45
45
|
.filter(([filterIndex]) => !sharedFilterIndexes.includes(filterIndex)) // filter out already added filters
|
|
46
|
-
.map(([filterIndex, filterName]) => (
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
.map(([filterIndex, filterName]) => ({
|
|
47
|
+
value: String(filterIndex),
|
|
48
|
+
label: `${filterIndex} - ${filterName}`
|
|
49
|
+
}))
|
|
49
50
|
}, [config.visualizations, vizConfig.uid])
|
|
50
51
|
|
|
51
52
|
const openControls = useState({})
|
|
@@ -189,6 +190,27 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
189
190
|
}
|
|
190
191
|
/>
|
|
191
192
|
)}
|
|
193
|
+
{vizConfig.filterBehavior === 'Apply Button' && (
|
|
194
|
+
<CheckBox
|
|
195
|
+
label='Show Clear Filters Button'
|
|
196
|
+
value={vizConfig.showClearButton ?? true}
|
|
197
|
+
updateField={(_section, _subsection, _key, value) => {
|
|
198
|
+
updateConfig({ ...vizConfig, showClearButton: value })
|
|
199
|
+
}}
|
|
200
|
+
tooltip={
|
|
201
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
202
|
+
<Tooltip.Target>
|
|
203
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
204
|
+
</Tooltip.Target>
|
|
205
|
+
<Tooltip.Content>
|
|
206
|
+
<p>
|
|
207
|
+
When enabled, displays a "Clear Filters" button that allows users to reset all filter selections.
|
|
208
|
+
</p>
|
|
209
|
+
</Tooltip.Content>
|
|
210
|
+
</Tooltip>
|
|
211
|
+
}
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
192
214
|
</AccordionItemPanel>
|
|
193
215
|
</AccordionItem>
|
|
194
216
|
|
|
@@ -254,8 +276,10 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
254
276
|
</Tooltip.Content>
|
|
255
277
|
</Tooltip>
|
|
256
278
|
</span>
|
|
257
|
-
<
|
|
279
|
+
<Select
|
|
280
|
+
label=''
|
|
258
281
|
value={''}
|
|
282
|
+
options={[{ value: '', label: 'Select' }, ...(existingOptions || [])]}
|
|
259
283
|
onChange={e => {
|
|
260
284
|
updateConfig({
|
|
261
285
|
...vizConfig,
|
|
@@ -263,14 +287,7 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
263
287
|
})
|
|
264
288
|
setCanAddExisting(false)
|
|
265
289
|
}}
|
|
266
|
-
|
|
267
|
-
{[
|
|
268
|
-
<option key='select' value=''>
|
|
269
|
-
Select
|
|
270
|
-
</option>,
|
|
271
|
-
...existingOptions
|
|
272
|
-
]}
|
|
273
|
-
</select>
|
|
290
|
+
/>
|
|
274
291
|
</label>
|
|
275
292
|
) : (
|
|
276
293
|
<button onClick={() => setCanAddExisting(true)} className='btn btn-primary full-width mt-2'>
|