@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.
Files changed (151) hide show
  1. package/CONFIG.md +219 -0
  2. package/README.md +60 -20
  3. package/dist/cdcdashboard-CY9IcPSi.es.js +6 -0
  4. package/dist/cdcdashboard-DlpiY3fQ.es.js +4 -0
  5. package/dist/cdcdashboard.js +61559 -58048
  6. package/examples/__data__/data-2.json +6 -0
  7. package/examples/__data__/data.json +6 -0
  8. package/examples/dashboard-conditions-filters-incomplete.json +221 -0
  9. package/examples/dashboard-missing-datasets-multi.json +174 -0
  10. package/examples/dashboard-missing-datasets-single.json +121 -0
  11. package/examples/dashboard-multi-dashboard-version-regression.json +146 -0
  12. package/examples/dashboard-shared-filter-row-delete-cleanup.json +186 -0
  13. package/examples/dashboard-stale-dataset-keys.json +181 -0
  14. package/examples/dashboard-tiered-filter-regression.json +190 -0
  15. package/examples/legend-issue.json +1 -1
  16. package/examples/minimal-example.json +34 -0
  17. package/examples/private/cfa-dashboard.json +651 -0
  18. package/examples/private/data-bite-wrap.json +6936 -0
  19. package/examples/private/dengue.json +4640 -0
  20. package/examples/private/link_to_file.json +16662 -0
  21. package/examples/private/multi-dash-fix.json +16963 -0
  22. package/examples/private/versions.json +41612 -0
  23. package/examples/sankey.json +3 -3
  24. package/examples/test-api-filter-reset.json +4 -4
  25. package/examples/tp5-test.json +86 -4
  26. package/examples/us-map-filter-example.json +1074 -0
  27. package/package.json +9 -9
  28. package/src/CdcDashboard.tsx +6 -2
  29. package/src/CdcDashboardComponent.tsx +179 -88
  30. package/src/DashboardCopyPasteContext.test.tsx +33 -0
  31. package/src/DashboardCopyPasteContext.tsx +48 -0
  32. package/src/_stories/Dashboard.EditorRegression.stories.tsx +72 -0
  33. package/src/_stories/Dashboard.Regression.stories.tsx +196 -0
  34. package/src/_stories/Dashboard.Zoom.stories.tsx +88 -0
  35. package/src/_stories/Dashboard.smoke.stories.tsx +33 -0
  36. package/src/_stories/Dashboard.stories.tsx +337 -2
  37. package/src/_stories/FilteredTextMigrationComparison.stories.tsx +87 -0
  38. package/src/_stories/_mock/dashboard-data-driven-colors.json +171 -0
  39. package/src/_stories/_mock/tp5-test.json +86 -5
  40. package/src/components/Column.test.tsx +176 -0
  41. package/src/components/Column.tsx +214 -13
  42. package/src/components/DashboardConditionModal.test.tsx +420 -0
  43. package/src/components/DashboardConditionModal.tsx +367 -0
  44. package/src/components/DashboardConditionSummary.tsx +59 -0
  45. package/src/components/DashboardEditors.tsx +23 -0
  46. package/src/components/DashboardFilters/DashboardFilters.test.tsx +267 -0
  47. package/src/components/DashboardFilters/DashboardFilters.tsx +193 -172
  48. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.test.tsx +164 -0
  49. package/src/components/DashboardFilters/DashboardFiltersEditor/DashboardFiltersEditor.tsx +46 -6
  50. package/src/components/DashboardFilters/DashboardFiltersEditor/components/APIModal.tsx +5 -3
  51. package/src/components/DashboardFilters/DashboardFiltersEditor/components/DeleteFilterModal.tsx +59 -58
  52. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.test.tsx +304 -0
  53. package/src/components/DashboardFilters/DashboardFiltersEditor/components/FilterEditor.tsx +43 -36
  54. package/src/components/DashboardFilters/DashboardFiltersEditor/components/NestedDropDownDashboard.tsx +2 -2
  55. package/src/components/DashboardFilters/DashboardFiltersWrapper.test.tsx +142 -0
  56. package/src/components/DashboardFilters/DashboardFiltersWrapper.tsx +32 -27
  57. package/src/components/DashboardFilters/dashboardfilter.styles.css +42 -27
  58. package/src/components/DataDesignerModal.tsx +2 -1
  59. package/src/components/ExpandCollapseButtons.tsx +6 -4
  60. package/src/components/Grid.tsx +12 -7
  61. package/src/components/Header/Header.tsx +36 -17
  62. package/src/components/MultiConfigTabs/MultiConfigTabs.tsx +141 -140
  63. package/src/components/Row.test.tsx +228 -0
  64. package/src/components/Row.tsx +104 -28
  65. package/src/components/VisualizationRow.test.tsx +396 -0
  66. package/src/components/VisualizationRow.tsx +177 -51
  67. package/src/components/VisualizationsPanel/VisualizationsPanel.test.tsx +49 -0
  68. package/src/components/VisualizationsPanel/VisualizationsPanel.tsx +14 -13
  69. package/src/components/Widget/Widget.test.tsx +218 -0
  70. package/src/components/Widget/Widget.tsx +123 -20
  71. package/src/components/Widget/widget.styles.css +58 -14
  72. package/src/components/dashboard-condition-modal.css +76 -0
  73. package/src/components/dashboard-condition-summary.css +87 -0
  74. package/src/data/initial-state.js +1 -0
  75. package/src/helpers/addValuesToDashboardFilters.ts +3 -5
  76. package/src/helpers/addVisualization.ts +17 -4
  77. package/src/helpers/cloneDashboardWidget.ts +127 -0
  78. package/src/helpers/dashboardColumnWidgets.ts +99 -0
  79. package/src/helpers/dashboardConditionUi.ts +47 -0
  80. package/src/helpers/dashboardConditions.ts +200 -0
  81. package/src/helpers/dashboardFilterTargets.ts +156 -0
  82. package/src/helpers/filterData.ts +4 -9
  83. package/src/helpers/filterVisibility.ts +20 -0
  84. package/src/helpers/formatConfigBeforeSave.ts +2 -2
  85. package/src/helpers/getFilteredData.ts +18 -5
  86. package/src/helpers/getUpdateConfig.ts +43 -12
  87. package/src/helpers/getVizRowColumnLocator.ts +11 -1
  88. package/src/helpers/iconHash.tsx +9 -3
  89. package/src/helpers/mapDataToConfig.ts +31 -29
  90. package/src/helpers/reloadURLHelpers.ts +25 -5
  91. package/src/helpers/removeDashboardFilter.ts +33 -33
  92. package/src/helpers/tests/addVisualization.test.ts +53 -9
  93. package/src/helpers/tests/cloneDashboardWidget.test.ts +136 -0
  94. package/src/helpers/tests/dashboardColumnWidgets.test.ts +99 -0
  95. package/src/helpers/tests/dashboardConditionUi.test.ts +41 -0
  96. package/src/helpers/tests/dashboardConditions.test.ts +428 -0
  97. package/src/helpers/tests/formatConfigBeforeSave.test.ts +51 -0
  98. package/src/helpers/tests/getFilteredData.test.ts +265 -86
  99. package/src/helpers/tests/getUpdateConfig.test.ts +338 -0
  100. package/src/helpers/tests/reloadURLHelpers.test.ts +394 -238
  101. package/src/index.tsx +6 -3
  102. package/src/scss/grid.scss +281 -22
  103. package/src/scss/main.scss +215 -64
  104. package/src/store/dashboard.actions.ts +17 -4
  105. package/src/store/dashboard.reducer.test.ts +538 -0
  106. package/src/store/dashboard.reducer.ts +136 -22
  107. package/src/test/CdcDashboard.test.jsx +24 -0
  108. package/src/test/CdcDashboard.test.tsx +148 -0
  109. package/src/test/CdcDashboardComponent.test.tsx +935 -2
  110. package/src/types/ConfigRow.ts +15 -0
  111. package/src/types/DashboardFilters.ts +4 -0
  112. package/src/types/SharedFilter.ts +2 -0
  113. package/tests/fixtures/dashboard-config-with-metadata.json +1 -1
  114. package/dist/cdcdashboard-vr9HZwRt.es.js +0 -6
  115. package/examples/DEV-6574.json +0 -2224
  116. package/examples/api-dashboard-data.json +0 -272
  117. package/examples/api-dashboard-years.json +0 -11
  118. package/examples/api-geographies-data.json +0 -11
  119. package/examples/chart-data.json +0 -5409
  120. package/examples/custom/css/respiratory.css +0 -236
  121. package/examples/custom/js/respiratory.js +0 -242
  122. package/examples/default-data.json +0 -368
  123. package/examples/default-filter-control.json +0 -209
  124. package/examples/default-multi-dataset-shared-filter.json +0 -1729
  125. package/examples/default-multi-dataset.json +0 -506
  126. package/examples/ed-visits-county-file.json +0 -402
  127. package/examples/filters/Alabama.json +0 -72
  128. package/examples/filters/Alaska.json +0 -1737
  129. package/examples/filters/Arkansas.json +0 -4713
  130. package/examples/filters/California.json +0 -212
  131. package/examples/filters/Colorado.json +0 -1500
  132. package/examples/filters/Connecticut.json +0 -559
  133. package/examples/filters/Delaware.json +0 -63
  134. package/examples/filters/DistrictofColumbia.json +0 -63
  135. package/examples/filters/Florida.json +0 -4217
  136. package/examples/filters/States.json +0 -146
  137. package/examples/state-level.json +0 -90136
  138. package/examples/state-points.json +0 -10474
  139. package/examples/temp-example-data.json +0 -130
  140. package/examples/test-dashboard-simple.json +0 -503
  141. package/examples/test-example.json +0 -752
  142. package/examples/test-file.json +0 -147
  143. package/examples/test.json +0 -752
  144. package/examples/testing.json +0 -94456
  145. /package/examples/{data → __data__}/data-with-metadata.json +0 -0
  146. /package/examples/{legend-issue-data.json → __data__/legend-issue-data.json} +0 -0
  147. /package/examples/api-test/{categories.json → __data__/categories.json} +0 -0
  148. /package/examples/api-test/{chart-data.json → __data__/chart-data.json} +0 -0
  149. /package/examples/api-test/{topics.json → __data__/topics.json} +0 -0
  150. /package/examples/api-test/{years.json → __data__/years.json} +0 -0
  151. /package/src/_stories/{Dashboard.Pages.stories.tsx → Dashboard.Pages.smoke.stories.tsx} +0 -0
@@ -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
- <button onClick={addNewFilter} className='btn btn-primary full-width'>
355
+ <Button variant='primary' fullWidth onClick={addNewFilter}>
318
356
  Add Filter
319
- </button>
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, e.target.value]
383
+ sharedFilterIndexes: [...vizConfig.sharedFilterIndexes, parsed]
344
384
  })
345
385
  setCanAddExisting(false)
346
386
  }}
347
387
  />
348
388
  </label>
349
389
  ) : (
350
- <button onClick={() => setCanAddExisting(true)} className='btn btn-primary full-width mt-2'>
390
+ <Button variant='primary' fullWidth className='mt-2' onClick={() => setCanAddExisting(true)}>
351
391
  Add Existing Dashboard Filter
352
- </button>
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
- <button
111
- className='btn btn-primary mt-2'
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
- </button>
125
+ </Button>
124
126
  </div>
125
127
  </fieldset>
126
128
  )
@@ -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
- type DeleteFilterProps = {
8
- removeFilterCompletely: (number) => void
9
- removeFilterFromViz: (number) => void
10
- filterIndex: number
11
- }
12
-
13
- const DeleteFilterModal: React.FC<DeleteFilterProps> = ({
14
- removeFilterCompletely,
15
- removeFilterFromViz,
16
- filterIndex
17
- }) => {
18
- const { overlay } = useGlobalContext()
19
- const { config } = useContext(DashboardContext)
20
-
21
- const filterUsedByMany =
22
- Object.values(config.visualizations).filter(viz => {
23
- return (viz as DashboardFilters).sharedFilterIndexes?.map(Number).includes(Number(filterIndex))
24
- }).length > 1
25
-
26
- const message = filterUsedByMany
27
- ? '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.'
28
- : 'Are you sure you want to delete this filter?'
29
- return (
30
- <Modal showClose={true}>
31
- <Modal.Content>
32
- <p>{message}</p>
33
- {filterUsedByMany && (
34
- <button
35
- className='btn btn-warning'
36
- onClick={() => {
37
- removeFilterFromViz(filterIndex)
38
- overlay?.actions.toggleOverlay()
39
- }}
40
- >
41
- Delete from Visualization
42
- </button>
43
- )}
44
- <button
45
- className='btn btn-danger'
46
- onClick={() => {
47
- removeFilterCompletely(filterIndex)
48
- overlay?.actions.toggleOverlay()
49
- }}
50
- >
51
- Delete{filterUsedByMany ? ' Completely' : ''}
52
- </button>
53
- </Modal.Content>
54
- </Modal>
55
- )
56
- }
57
-
58
- export default DeleteFilterModal
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