@cdc/dashboard 4.26.3 → 4.26.5
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/CONFIG.md +219 -0
- package/README.md +60 -20
- package/dist/cdcdashboard-CY9IcPSi.es.js +6 -0
- package/dist/cdcdashboard-DlpiY3fQ.es.js +4 -0
- package/dist/cdcdashboard.js +61559 -58048
- package/examples/__data__/data-2.json +6 -0
- package/examples/__data__/data.json +6 -0
- package/examples/dashboard-conditions-filters-incomplete.json +221 -0
- package/examples/dashboard-missing-datasets-multi.json +174 -0
- package/examples/dashboard-missing-datasets-single.json +121 -0
- package/examples/dashboard-multi-dashboard-version-regression.json +146 -0
- package/examples/dashboard-shared-filter-row-delete-cleanup.json +186 -0
- package/examples/dashboard-stale-dataset-keys.json +181 -0
- package/examples/dashboard-tiered-filter-regression.json +190 -0
- package/examples/legend-issue.json +1 -1
- package/examples/minimal-example.json +34 -0
- package/examples/private/cfa-dashboard.json +651 -0
- package/examples/private/data-bite-wrap.json +6936 -0
- package/examples/private/dengue.json +4640 -0
- package/examples/private/link_to_file.json +16662 -0
- package/examples/private/multi-dash-fix.json +16963 -0
- package/examples/private/versions.json +41612 -0
- package/examples/sankey.json +3 -3
- package/examples/test-api-filter-reset.json +4 -4
- package/examples/tp5-test.json +86 -4
- package/examples/us-map-filter-example.json +1074 -0
- package/package.json +9 -9
- package/src/CdcDashboard.tsx +6 -2
- package/src/CdcDashboardComponent.tsx +179 -88
- package/src/DashboardCopyPasteContext.test.tsx +33 -0
- package/src/DashboardCopyPasteContext.tsx +48 -0
- package/src/_stories/Dashboard.EditorRegression.stories.tsx +72 -0
- package/src/_stories/Dashboard.Regression.stories.tsx +196 -0
- package/src/_stories/Dashboard.Zoom.stories.tsx +88 -0
- package/src/_stories/Dashboard.smoke.stories.tsx +33 -0
- package/src/_stories/Dashboard.stories.tsx +337 -2
- package/src/_stories/FilteredTextMigrationComparison.stories.tsx +87 -0
- package/src/_stories/_mock/dashboard-data-driven-colors.json +171 -0
- package/src/_stories/_mock/tp5-test.json +86 -5
- package/src/components/Column.test.tsx +176 -0
- package/src/components/Column.tsx +214 -13
- package/src/components/DashboardConditionModal.test.tsx +420 -0
- package/src/components/DashboardConditionModal.tsx +367 -0
- package/src/components/DashboardConditionSummary.tsx +59 -0
- package/src/components/DashboardEditors.tsx +23 -0
- package/src/components/DashboardFilters/DashboardFilters.test.tsx +267 -0
- package/src/components/DashboardFilters/DashboardFilters.tsx +193 -172
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.test.tsx +164 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +46 -6
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/APIModal.tsx +5 -3
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx +59 -58
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.test.tsx +304 -0
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +43 -36
- package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +2 -2
- package/src/components/DashboardFilters/DashboardFiltersWrapper.test.tsx +142 -0
- package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +32 -27
- package/src/components/DashboardFilters/dashboardfilter.styles.css +42 -27
- package/src/components/DataDesignerModal.tsx +2 -1
- package/src/components/ExpandCollapseButtons.tsx +6 -4
- package/src/components/Grid.tsx +12 -7
- package/src/components/Header/Header.tsx +36 -17
- package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +141 -140
- package/src/components/Row.test.tsx +228 -0
- package/src/components/Row.tsx +104 -28
- package/src/components/VisualizationRow.test.tsx +396 -0
- package/src/components/VisualizationRow.tsx +177 -51
- package/src/components/VisualizationsPanel/VisualizationsPanel.test.tsx +49 -0
- package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +14 -13
- package/src/components/Widget/Widget.test.tsx +218 -0
- package/src/components/Widget/Widget.tsx +123 -20
- package/src/components/Widget/widget.styles.css +58 -14
- package/src/components/dashboard-condition-modal.css +76 -0
- package/src/components/dashboard-condition-summary.css +87 -0
- package/src/data/initial-state.js +1 -0
- package/src/helpers/addValuesToDashboardFilters.ts +3 -5
- package/src/helpers/addVisualization.ts +17 -4
- package/src/helpers/cloneDashboardWidget.ts +127 -0
- package/src/helpers/dashboardColumnWidgets.ts +99 -0
- package/src/helpers/dashboardConditionUi.ts +47 -0
- package/src/helpers/dashboardConditions.ts +200 -0
- package/src/helpers/dashboardFilterTargets.ts +156 -0
- package/src/helpers/filterData.ts +4 -9
- package/src/helpers/filterVisibility.ts +20 -0
- package/src/helpers/formatConfigBeforeSave.ts +2 -2
- package/src/helpers/getFilteredData.ts +18 -5
- package/src/helpers/getUpdateConfig.ts +43 -12
- package/src/helpers/getVizRowColumnLocator.ts +11 -1
- package/src/helpers/iconHash.tsx +9 -3
- package/src/helpers/mapDataToConfig.ts +31 -29
- package/src/helpers/reloadURLHelpers.ts +25 -5
- package/src/helpers/removeDashboardFilter.ts +33 -33
- package/src/helpers/tests/addVisualization.test.ts +53 -9
- package/src/helpers/tests/cloneDashboardWidget.test.ts +136 -0
- package/src/helpers/tests/dashboardColumnWidgets.test.ts +99 -0
- package/src/helpers/tests/dashboardConditionUi.test.ts +41 -0
- package/src/helpers/tests/dashboardConditions.test.ts +428 -0
- package/src/helpers/tests/formatConfigBeforeSave.test.ts +51 -0
- package/src/helpers/tests/getFilteredData.test.ts +265 -86
- package/src/helpers/tests/getUpdateConfig.test.ts +338 -0
- package/src/helpers/tests/reloadURLHelpers.test.ts +394 -238
- package/src/index.tsx +6 -3
- package/src/scss/grid.scss +281 -22
- package/src/scss/main.scss +215 -64
- package/src/store/dashboard.actions.ts +17 -4
- package/src/store/dashboard.reducer.test.ts +538 -0
- package/src/store/dashboard.reducer.ts +136 -22
- package/src/test/CdcDashboard.test.jsx +24 -0
- package/src/test/CdcDashboard.test.tsx +148 -0
- package/src/test/CdcDashboardComponent.test.tsx +935 -2
- package/src/types/ConfigRow.ts +15 -0
- package/src/types/DashboardFilters.ts +4 -0
- package/src/types/SharedFilter.ts +2 -0
- package/tests/fixtures/dashboard-config-with-metadata.json +1 -1
- package/dist/cdcdashboard-vr9HZwRt.es.js +0 -6
- package/examples/DEV-6574.json +0 -2224
- package/examples/api-dashboard-data.json +0 -272
- package/examples/api-dashboard-years.json +0 -11
- package/examples/api-geographies-data.json +0 -11
- package/examples/chart-data.json +0 -5409
- package/examples/custom/css/respiratory.css +0 -236
- package/examples/custom/js/respiratory.js +0 -242
- package/examples/default-data.json +0 -368
- package/examples/default-filter-control.json +0 -209
- package/examples/default-multi-dataset-shared-filter.json +0 -1729
- package/examples/default-multi-dataset.json +0 -506
- package/examples/ed-visits-county-file.json +0 -402
- package/examples/filters/Alabama.json +0 -72
- package/examples/filters/Alaska.json +0 -1737
- package/examples/filters/Arkansas.json +0 -4713
- package/examples/filters/California.json +0 -212
- package/examples/filters/Colorado.json +0 -1500
- package/examples/filters/Connecticut.json +0 -559
- package/examples/filters/Delaware.json +0 -63
- package/examples/filters/DistrictofColumbia.json +0 -63
- package/examples/filters/Florida.json +0 -4217
- package/examples/filters/States.json +0 -146
- package/examples/state-level.json +0 -90136
- package/examples/state-points.json +0 -10474
- package/examples/temp-example-data.json +0 -130
- package/examples/test-dashboard-simple.json +0 -503
- package/examples/test-example.json +0 -752
- package/examples/test-file.json +0 -147
- package/examples/test.json +0 -752
- package/examples/testing.json +0 -94456
- /package/examples/{data → __data__}/data-with-metadata.json +0 -0
- /package/examples/{legend-issue-data.json → __data__/legend-issue-data.json} +0 -0
- /package/examples/api-test/{categories.json → __data__/categories.json} +0 -0
- /package/examples/api-test/{chart-data.json → __data__/chart-data.json} +0 -0
- /package/examples/api-test/{topics.json → __data__/topics.json} +0 -0
- /package/examples/api-test/{years.json → __data__/years.json} +0 -0
- /package/src/_stories/{Dashboard.Pages.stories.tsx → Dashboard.Pages.smoke.stories.tsx} +0 -0
package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.test.tsx
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
4
|
+
import { DashboardContext, DashboardDispatchContext, initialState } from '../../../DashboardContext'
|
|
5
|
+
import { GlobalContext } from '@cdc/core/components/GlobalContext'
|
|
6
|
+
import DashboardFiltersEditor from './DashboardFiltersEditor'
|
|
7
|
+
|
|
8
|
+
vi.mock('@cdc/core/components/ui/Icon', () => ({
|
|
9
|
+
default: props => <span data-testid='mock-icon' {...props} />
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
vi.mock('@hello-pangea/dnd', () => ({
|
|
13
|
+
DragDropContext: ({ children }) => <div>{children}</div>,
|
|
14
|
+
Droppable: ({ children }) => <div>{children({ droppableProps: {}, innerRef: vi.fn(), placeholder: null })}</div>,
|
|
15
|
+
Draggable: ({ children }) => (
|
|
16
|
+
<div>
|
|
17
|
+
{children(
|
|
18
|
+
{
|
|
19
|
+
draggableProps: { style: {} },
|
|
20
|
+
dragHandleProps: {},
|
|
21
|
+
innerRef: vi.fn()
|
|
22
|
+
},
|
|
23
|
+
{ isDragging: false }
|
|
24
|
+
)}
|
|
25
|
+
</div>
|
|
26
|
+
)
|
|
27
|
+
}))
|
|
28
|
+
|
|
29
|
+
const renderEditor = (visual = { grayBackground: false }, sharedFilters = [], sharedFilterIndexes = []) => {
|
|
30
|
+
const updateConfig = vi.fn()
|
|
31
|
+
const dispatch = vi.fn()
|
|
32
|
+
const vizConfig = {
|
|
33
|
+
uid: 'dashboardFilters1',
|
|
34
|
+
type: 'dashboardFilters',
|
|
35
|
+
visualizationType: 'dashboardFilters',
|
|
36
|
+
filterBehavior: 'Filter Change',
|
|
37
|
+
filterIntro: '',
|
|
38
|
+
sharedFilterIndexes,
|
|
39
|
+
visual
|
|
40
|
+
} as any
|
|
41
|
+
|
|
42
|
+
const rendered = render(
|
|
43
|
+
<GlobalContext.Provider
|
|
44
|
+
value={{
|
|
45
|
+
overlay: {
|
|
46
|
+
object: null,
|
|
47
|
+
show: false,
|
|
48
|
+
disableBgClose: false,
|
|
49
|
+
actions: {
|
|
50
|
+
openOverlay: vi.fn(),
|
|
51
|
+
toggleOverlay: vi.fn()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<DashboardContext.Provider
|
|
57
|
+
value={{
|
|
58
|
+
...initialState,
|
|
59
|
+
config: {
|
|
60
|
+
type: 'dashboard',
|
|
61
|
+
dashboard: { sharedFilters },
|
|
62
|
+
datasets: {},
|
|
63
|
+
rows: [],
|
|
64
|
+
visualizations: {
|
|
65
|
+
dashboardFilters1: vizConfig
|
|
66
|
+
}
|
|
67
|
+
} as any,
|
|
68
|
+
data: {},
|
|
69
|
+
outerContainerRef: vi.fn(),
|
|
70
|
+
setParentConfig: vi.fn(),
|
|
71
|
+
isDebug: false,
|
|
72
|
+
isEditor: true,
|
|
73
|
+
reloadURLData: vi.fn(),
|
|
74
|
+
loadAPIFilters: vi.fn(),
|
|
75
|
+
setAPIFilterDropdowns: vi.fn(),
|
|
76
|
+
setAPILoading: vi.fn()
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<DashboardDispatchContext.Provider value={dispatch}>
|
|
80
|
+
<DashboardFiltersEditor updateConfig={updateConfig} vizConfig={vizConfig} />
|
|
81
|
+
</DashboardDispatchContext.Provider>
|
|
82
|
+
</DashboardContext.Provider>
|
|
83
|
+
</GlobalContext.Provider>
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return { ...rendered, dispatch, updateConfig, vizConfig }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
describe('DashboardFiltersEditor', () => {
|
|
90
|
+
it('renders a Visual accordion with a Gray Background option', () => {
|
|
91
|
+
renderEditor()
|
|
92
|
+
|
|
93
|
+
expect(screen.getByText('Visual')).toBeInTheDocument()
|
|
94
|
+
expect(screen.getAllByLabelText('Use Gray Background Style')[0]).not.toBeChecked()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('updates visual.grayBackground when Gray Background is toggled', () => {
|
|
98
|
+
const { updateConfig, vizConfig } = renderEditor()
|
|
99
|
+
|
|
100
|
+
fireEvent.click(screen.getAllByLabelText('Use Gray Background Style')[0])
|
|
101
|
+
|
|
102
|
+
expect(updateConfig).toHaveBeenCalledWith({
|
|
103
|
+
...vizConfig,
|
|
104
|
+
visual: {
|
|
105
|
+
grayBackground: true
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('updates filterIntro from the General panel', async () => {
|
|
111
|
+
const { updateConfig, vizConfig } = renderEditor()
|
|
112
|
+
|
|
113
|
+
fireEvent.change(screen.getByLabelText('Filter intro text'), {
|
|
114
|
+
target: { value: 'Choose filters before viewing results.' }
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await waitFor(() => {
|
|
118
|
+
expect(updateConfig).toHaveBeenCalledWith({
|
|
119
|
+
...vizConfig,
|
|
120
|
+
filterIntro: 'Choose filters before viewing results.'
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it.each([
|
|
126
|
+
['combobox', 'tab-simple', 'Show'],
|
|
127
|
+
['tab-simple', 'combobox', 'Show'],
|
|
128
|
+
['dropdown', 'multi-select', ['Show']]
|
|
129
|
+
])('applies the configured default when switching a data filter from %s to %s', (initialStyle, nextStyle, active) => {
|
|
130
|
+
const sharedFilter = {
|
|
131
|
+
key: 'Status',
|
|
132
|
+
type: 'datafilter',
|
|
133
|
+
filterStyle: initialStyle,
|
|
134
|
+
showDropdown: true,
|
|
135
|
+
values: ['Show', 'Hide'],
|
|
136
|
+
orderedValues: ['Show', 'Hide'],
|
|
137
|
+
columnName: 'status',
|
|
138
|
+
defaultValue: 'Show',
|
|
139
|
+
active: '',
|
|
140
|
+
order: 'cust'
|
|
141
|
+
}
|
|
142
|
+
const { container, dispatch } = renderEditor({ grayBackground: false }, [sharedFilter], [0])
|
|
143
|
+
|
|
144
|
+
fireEvent.click(container.querySelector('.editor-field-item__header button') as HTMLButtonElement)
|
|
145
|
+
fireEvent.change(screen.getAllByLabelText('Filter Style')[0], { target: { value: nextStyle } })
|
|
146
|
+
|
|
147
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
148
|
+
type: 'SET_SHARED_FILTERS',
|
|
149
|
+
payload: [
|
|
150
|
+
{
|
|
151
|
+
...sharedFilter,
|
|
152
|
+
active,
|
|
153
|
+
apiFilter: {
|
|
154
|
+
apiEndpoint: '',
|
|
155
|
+
subgroupValueSelector: '',
|
|
156
|
+
textSelector: '',
|
|
157
|
+
valueSelector: ''
|
|
158
|
+
},
|
|
159
|
+
filterStyle: nextStyle
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
})
|
|
@@ -22,6 +22,7 @@ import { FILTER_STYLE } from '../../../types/FilterStyles'
|
|
|
22
22
|
import { handleSorting } from '@cdc/core/components/Filters'
|
|
23
23
|
import { removeDashboardFilter } from '../../../helpers/removeDashboardFilter'
|
|
24
24
|
import { DragDropContext, Droppable, Draggable, DropResult } from '@hello-pangea/dnd'
|
|
25
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
25
26
|
|
|
26
27
|
type DashboardFitlersEditorProps = {
|
|
27
28
|
vizConfig: DashboardFilters
|
|
@@ -54,6 +55,11 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
54
55
|
const [canAddExisting, setCanAddExisting] = useState(false)
|
|
55
56
|
const [isNestedDragHovered, setIsNestedDragHovered] = useState(false)
|
|
56
57
|
|
|
58
|
+
const getActiveValueForFilterStyle = (filter: SharedFilter, filterStyle: string) => {
|
|
59
|
+
const defaultValue = filter.defaultValue || filter.values?.[0] || ''
|
|
60
|
+
return filterStyle === FILTER_STYLE.multiSelect ? (defaultValue ? [defaultValue] : []) : defaultValue
|
|
61
|
+
}
|
|
62
|
+
|
|
57
63
|
const updateFilterProp = (prop: string, index: number, value) => {
|
|
58
64
|
const newSharedFilters = cloneDeep(sharedFilters)
|
|
59
65
|
const {
|
|
@@ -80,7 +86,7 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
80
86
|
} else if (prop === 'filterStyle') {
|
|
81
87
|
newSharedFilters[index] = {
|
|
82
88
|
...newSharedFilters[index],
|
|
83
|
-
active:
|
|
89
|
+
active: getActiveValueForFilterStyle(newSharedFilters[index], value),
|
|
84
90
|
apiFilter: {
|
|
85
91
|
apiEndpoint: '',
|
|
86
92
|
subgroupValueSelector: '',
|
|
@@ -187,6 +193,15 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
187
193
|
</Tooltip>
|
|
188
194
|
}
|
|
189
195
|
/>
|
|
196
|
+
<TextField
|
|
197
|
+
type='textarea'
|
|
198
|
+
className='filter-editor__compact-textarea'
|
|
199
|
+
label='Filter intro text'
|
|
200
|
+
value={vizConfig.filterIntro || ''}
|
|
201
|
+
updateField={(_section, _subsection, _key, value) => {
|
|
202
|
+
updateConfig({ ...vizConfig, filterIntro: value })
|
|
203
|
+
}}
|
|
204
|
+
/>
|
|
190
205
|
{vizConfig.filterBehavior === 'Apply Button' && (
|
|
191
206
|
<TextField
|
|
192
207
|
label='Apply Filter Button Text'
|
|
@@ -243,6 +258,29 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
243
258
|
</AccordionItemPanel>
|
|
244
259
|
</AccordionItem>
|
|
245
260
|
|
|
261
|
+
<AccordionItem>
|
|
262
|
+
<AccordionItemHeading>
|
|
263
|
+
<AccordionItemButton>Visual</AccordionItemButton>
|
|
264
|
+
</AccordionItemHeading>
|
|
265
|
+
<AccordionItemPanel>
|
|
266
|
+
<CheckBox
|
|
267
|
+
label='Use Gray Background Style'
|
|
268
|
+
section='visual'
|
|
269
|
+
fieldName='grayBackground'
|
|
270
|
+
value={vizConfig.visual?.grayBackground ?? false}
|
|
271
|
+
updateField={(_section, _subsection, _key, value) => {
|
|
272
|
+
updateConfig({
|
|
273
|
+
...vizConfig,
|
|
274
|
+
visual: {
|
|
275
|
+
...vizConfig.visual,
|
|
276
|
+
grayBackground: value
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
}}
|
|
280
|
+
/>
|
|
281
|
+
</AccordionItemPanel>
|
|
282
|
+
</AccordionItem>
|
|
283
|
+
|
|
246
284
|
<AccordionItem>
|
|
247
285
|
<AccordionItemHeading>
|
|
248
286
|
<AccordionItemButton>Filters</AccordionItemButton>
|
|
@@ -314,9 +352,9 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
314
352
|
)}
|
|
315
353
|
</Droppable>
|
|
316
354
|
</DragDropContext>
|
|
317
|
-
<
|
|
355
|
+
<Button variant='primary' fullWidth onClick={addNewFilter}>
|
|
318
356
|
Add Filter
|
|
319
|
-
</
|
|
357
|
+
</Button>
|
|
320
358
|
{canAddExisting ? (
|
|
321
359
|
<label>
|
|
322
360
|
<span className='edit-label column-heading'>
|
|
@@ -338,18 +376,20 @@ const DashboardFiltersEditor: React.FC<DashboardFitlersEditorProps> = ({ vizConf
|
|
|
338
376
|
value={''}
|
|
339
377
|
options={[{ value: '', label: 'Select' }, ...(existingOptions || [])]}
|
|
340
378
|
onChange={e => {
|
|
379
|
+
const parsed = Number(e.target.value)
|
|
380
|
+
if (!e.target.value || isNaN(parsed)) return
|
|
341
381
|
updateConfig({
|
|
342
382
|
...vizConfig,
|
|
343
|
-
sharedFilterIndexes: [...vizConfig.sharedFilterIndexes,
|
|
383
|
+
sharedFilterIndexes: [...vizConfig.sharedFilterIndexes, parsed]
|
|
344
384
|
})
|
|
345
385
|
setCanAddExisting(false)
|
|
346
386
|
}}
|
|
347
387
|
/>
|
|
348
388
|
</label>
|
|
349
389
|
) : (
|
|
350
|
-
<
|
|
390
|
+
<Button variant='primary' fullWidth className='mt-2' onClick={() => setCanAddExisting(true)}>
|
|
351
391
|
Add Existing Dashboard Filter
|
|
352
|
-
</
|
|
392
|
+
</Button>
|
|
353
393
|
)}
|
|
354
394
|
</AccordionItemPanel>
|
|
355
395
|
</AccordionItem>
|
|
@@ -2,6 +2,7 @@ import { useState } from 'react'
|
|
|
2
2
|
import { SharedFilter } from '../../../../types/SharedFilter'
|
|
3
3
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
4
4
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
5
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
5
6
|
|
|
6
7
|
type APIModalProps = {
|
|
7
8
|
filter: SharedFilter
|
|
@@ -107,8 +108,9 @@ const APIModal: React.FC<APIModalProps> = ({ filter, isNestedDropdown, updateAPI
|
|
|
107
108
|
)}
|
|
108
109
|
</div>
|
|
109
110
|
<div className='d-flex justify-content-end mt-2'>
|
|
110
|
-
<
|
|
111
|
-
|
|
111
|
+
<Button
|
|
112
|
+
variant='primary'
|
|
113
|
+
className='mt-2'
|
|
112
114
|
onClick={() =>
|
|
113
115
|
updateAPIFilter(
|
|
114
116
|
APIEndpoint,
|
|
@@ -120,7 +122,7 @@ const APIModal: React.FC<APIModalProps> = ({ filter, isNestedDropdown, updateAPI
|
|
|
120
122
|
}
|
|
121
123
|
>
|
|
122
124
|
Save
|
|
123
|
-
</
|
|
125
|
+
</Button>
|
|
124
126
|
</div>
|
|
125
127
|
</fieldset>
|
|
126
128
|
)
|
package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx
CHANGED
|
@@ -1,58 +1,59 @@
|
|
|
1
|
-
import { useGlobalContext } from '@cdc/core/components/GlobalContext'
|
|
2
|
-
import Modal from '@cdc/core/components/ui/Modal'
|
|
3
|
-
import { DashboardContext } from '../../../../DashboardContext'
|
|
4
|
-
import { useContext } from 'react'
|
|
5
|
-
import { DashboardFilters } from '../../../../types/DashboardFilters'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
58
|
-
|
|
1
|
+
import { useGlobalContext } from '@cdc/core/components/GlobalContext'
|
|
2
|
+
import Modal from '@cdc/core/components/ui/Modal'
|
|
3
|
+
import { DashboardContext } from '../../../../DashboardContext'
|
|
4
|
+
import { useContext } from 'react'
|
|
5
|
+
import { DashboardFilters } from '../../../../types/DashboardFilters'
|
|
6
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
7
|
+
|
|
8
|
+
type DeleteFilterProps = {
|
|
9
|
+
removeFilterCompletely: (number) => void
|
|
10
|
+
removeFilterFromViz: (number) => void
|
|
11
|
+
filterIndex: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const DeleteFilterModal: React.FC<DeleteFilterProps> = ({
|
|
15
|
+
removeFilterCompletely,
|
|
16
|
+
removeFilterFromViz,
|
|
17
|
+
filterIndex
|
|
18
|
+
}) => {
|
|
19
|
+
const { overlay } = useGlobalContext()
|
|
20
|
+
const { config } = useContext(DashboardContext)
|
|
21
|
+
|
|
22
|
+
const filterUsedByMany =
|
|
23
|
+
Object.values(config.visualizations).filter(viz => {
|
|
24
|
+
return (viz as DashboardFilters).sharedFilterIndexes?.map(Number).includes(Number(filterIndex))
|
|
25
|
+
}).length > 1
|
|
26
|
+
|
|
27
|
+
const message = filterUsedByMany
|
|
28
|
+
? 'This filter is used by multiple visualizations. You can either delete the filter from this visualization only or you can delete the filter completely, which will also remove it from other visualizations.'
|
|
29
|
+
: 'Are you sure you want to delete this filter?'
|
|
30
|
+
return (
|
|
31
|
+
<Modal showClose={true}>
|
|
32
|
+
<Modal.Content>
|
|
33
|
+
<p>{message}</p>
|
|
34
|
+
{filterUsedByMany && (
|
|
35
|
+
<Button
|
|
36
|
+
variant='warning'
|
|
37
|
+
onClick={() => {
|
|
38
|
+
removeFilterFromViz(filterIndex)
|
|
39
|
+
overlay?.actions.toggleOverlay()
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
42
|
+
Delete from Visualization
|
|
43
|
+
</Button>
|
|
44
|
+
)}
|
|
45
|
+
<Button
|
|
46
|
+
variant='danger'
|
|
47
|
+
onClick={() => {
|
|
48
|
+
removeFilterCompletely(filterIndex)
|
|
49
|
+
overlay?.actions.toggleOverlay()
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
Delete{filterUsedByMany ? ' Completely' : ''}
|
|
53
|
+
</Button>
|
|
54
|
+
</Modal.Content>
|
|
55
|
+
</Modal>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default DeleteFilterModal
|