@cdc/core 4.24.7 → 4.24.9
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/assets/icon-gear-multi.svg +23 -0
- package/components/Alert/components/Alert.styles.css +15 -0
- package/components/Alert/components/Alert.tsx +39 -0
- package/components/Alert/index.tsx +3 -0
- package/components/DataTable/DataTable.tsx +106 -30
- package/components/DataTable/helpers/chartCellMatrix.tsx +3 -3
- package/components/DataTable/helpers/getChartCellValue.ts +1 -1
- package/components/DataTable/helpers/getDataSeriesColumns.ts +2 -2
- package/components/DataTable/helpers/mapCellMatrix.tsx +3 -3
- package/components/DataTable/types/TableConfig.ts +1 -1
- package/components/EditorPanel/Inputs.tsx +13 -4
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +268 -0
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +161 -82
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +31 -45
- package/components/Filters.tsx +223 -180
- package/components/Layout/components/Responsive.tsx +14 -4
- package/components/Layout/components/Sidebar/components/Sidebar.tsx +14 -5
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +15 -16
- package/components/Layout/components/Visualization/index.tsx +7 -1
- package/components/Layout/components/Visualization/visualizations.scss +32 -26
- package/components/Layout/styles/editor.scss +0 -8
- package/components/Legend/Legend.Gradient.tsx +133 -0
- package/components/LegendShape.tsx +28 -0
- package/components/MultiSelect/MultiSelect.tsx +6 -3
- package/components/NestedDropdown/NestedDropdown.tsx +47 -52
- package/components/NestedDropdown/nesteddropdown.styles.css +19 -25
- package/components/Table/Table.tsx +8 -5
- package/components/Table/components/Cell.tsx +2 -2
- package/components/Table/components/Row.tsx +25 -7
- package/components/_stories/Layout.Debug.stories.tsx +91 -0
- package/components/_stories/_mocks/bar-chart-suppressed.json +474 -0
- package/components/_stories/styles.scss +13 -1
- package/components/createBarElement.jsx +4 -4
- package/components/ui/Icon.tsx +21 -14
- package/components/ui/Title/Title.scss +0 -8
- package/helpers/DataTransform.ts +2 -2
- package/helpers/addValuesToFilters.ts +95 -16
- package/helpers/cove/accessibility.ts +16 -4
- package/helpers/coveUpdateWorker.ts +24 -10
- package/helpers/filterVizData.ts +23 -4
- package/helpers/formatConfigBeforeSave.ts +7 -2
- package/helpers/getGradientLegendWidth.ts +15 -0
- package/helpers/getTextWidth.ts +18 -0
- package/helpers/scaling.ts +7 -0
- package/helpers/tests/addValuesToFilters.test.ts +55 -0
- package/helpers/tests/filterVizData.test.ts +31 -0
- package/helpers/tests/invertValue.test.ts +35 -0
- package/helpers/updatePaletteNames.ts +19 -0
- package/helpers/{useDataVizClasses.js → useDataVizClasses.ts} +3 -2
- package/helpers/ver/4.24.5.ts +3 -3
- package/helpers/ver/4.24.7.ts +34 -3
- package/helpers/ver/4.24.9.ts +63 -0
- package/helpers/ver/tests/4.24.9.test.ts +22 -0
- package/helpers/ver/versionNeedsUpdate.ts +9 -0
- package/package.json +3 -3
- package/styles/_button-section.scss +1 -1
- package/styles/_global.scss +6 -2
- package/styles/filters.scss +4 -0
- package/types/Axis.ts +3 -0
- package/types/Dimensions.ts +1 -0
- package/types/General.ts +1 -1
- package/types/VizFilter.ts +24 -3
- package/components/LegendCircle.jsx +0 -17
- package/helpers/updatePaletteNames.js +0 -16
- /package/components/{Waiting.jsx → Waiting.tsx} +0 -0
- /package/helpers/ver/{4.23.4.ts → 4.24.4.ts} +0 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { SubGrouping, VizFilter, OrderBy } from '../../../types/VizFilter'
|
|
3
|
+
import { filterOrderOptions, handleSorting } from '../../Filters'
|
|
4
|
+
import FilterOrder from './components/FilterOrder'
|
|
5
|
+
import { Visualization } from '../../../types/Visualization'
|
|
6
|
+
|
|
7
|
+
type NestedDropdownEditorProps = {
|
|
8
|
+
config: Visualization
|
|
9
|
+
dataColumns: string[]
|
|
10
|
+
filterIndex: number
|
|
11
|
+
handleNameChange: Function
|
|
12
|
+
rawData: Object[]
|
|
13
|
+
updateField: Function
|
|
14
|
+
updateFilterStyle: Function
|
|
15
|
+
handleGroupingCustomOrder: (index1: number, index2: number) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const NestedDropdownEditor: React.FC<NestedDropdownEditorProps> = ({
|
|
19
|
+
config,
|
|
20
|
+
dataColumns,
|
|
21
|
+
handleGroupingCustomOrder,
|
|
22
|
+
handleNameChange: handleGroupColumnNameChange,
|
|
23
|
+
filterIndex,
|
|
24
|
+
rawData,
|
|
25
|
+
updateField
|
|
26
|
+
}) => {
|
|
27
|
+
const filter = config.filters[filterIndex]
|
|
28
|
+
const subGrouping = filter?.subGrouping
|
|
29
|
+
const listOfUsedColumnNames: string[] = []
|
|
30
|
+
|
|
31
|
+
config.filters.forEach((filter: VizFilter, index) => {
|
|
32
|
+
if (filterIndex === index) return
|
|
33
|
+
listOfUsedColumnNames.push(filter.columnName)
|
|
34
|
+
if (subGrouping?.columnName) listOfUsedColumnNames.push(subGrouping.columnName)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const updateGroupingFilterProp = (prop, value) => {
|
|
38
|
+
updateField('filters', filterIndex, prop, value)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const handleGroupingOrderBy = (order: OrderBy) => {
|
|
42
|
+
const groupSortObject = {
|
|
43
|
+
values: _.cloneDeep(filter.values),
|
|
44
|
+
order
|
|
45
|
+
}
|
|
46
|
+
const newOrderedValues = handleSorting(groupSortObject).values
|
|
47
|
+
|
|
48
|
+
const newAllFilters = _.cloneDeep(config.filters)
|
|
49
|
+
newAllFilters[filterIndex] = { ...filter, values: newOrderedValues, order }
|
|
50
|
+
if (order === 'cust') {
|
|
51
|
+
newAllFilters[filterIndex].orderedValues = newOrderedValues
|
|
52
|
+
} else {
|
|
53
|
+
delete newAllFilters[filterIndex].orderedValues
|
|
54
|
+
}
|
|
55
|
+
updateField(null, null, 'filters', newAllFilters)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const updateSubGroupingFilterProperty = (newSubGrouping: SubGrouping) => {
|
|
59
|
+
updateField('filters', filterIndex, 'subGrouping', newSubGrouping)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const handleSubGroupColumnNameChange = value => {
|
|
63
|
+
const filterGroups = filter.orderedValues?.length ? filter.orderedValues : filter.values
|
|
64
|
+
|
|
65
|
+
const valuesLookup = filterGroups.reduce((acc, groupName) => {
|
|
66
|
+
const values: string[] = _.uniq(
|
|
67
|
+
rawData
|
|
68
|
+
.map(d => {
|
|
69
|
+
return d[filter.columnName] === groupName ? d[value] : ''
|
|
70
|
+
})
|
|
71
|
+
.filter(value => value !== '')
|
|
72
|
+
).sort()
|
|
73
|
+
|
|
74
|
+
acc[groupName] = {
|
|
75
|
+
values // add temp values when column changes
|
|
76
|
+
}
|
|
77
|
+
return acc
|
|
78
|
+
}, {})
|
|
79
|
+
const newSubGrouping: SubGrouping = {
|
|
80
|
+
...subGrouping,
|
|
81
|
+
columnName: value,
|
|
82
|
+
valuesLookup
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
updateSubGroupingFilterProperty(newSubGrouping)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const handleSubGroupingOrderBy = (order: OrderBy) => {
|
|
89
|
+
const newValuesLookup = Object.keys(subGrouping.valuesLookup).reduce((acc, groupName) => {
|
|
90
|
+
const subGroup = subGrouping.valuesLookup[groupName]
|
|
91
|
+
|
|
92
|
+
const { values } = handleSorting({ values: subGroup.values, order })
|
|
93
|
+
acc[groupName] = {
|
|
94
|
+
values
|
|
95
|
+
}
|
|
96
|
+
if (order === 'cust') {
|
|
97
|
+
acc[groupName].orderedValues = values
|
|
98
|
+
} else {
|
|
99
|
+
delete acc[groupName].orderedValues
|
|
100
|
+
}
|
|
101
|
+
return acc
|
|
102
|
+
}, {})
|
|
103
|
+
const newSortedSubGrouping = { ...subGrouping, order, valuesLookup: newValuesLookup }
|
|
104
|
+
updateSubGroupingFilterProperty(newSortedSubGrouping)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const handleSubGroupingCustomOrder = (
|
|
108
|
+
currentIndex,
|
|
109
|
+
newIndex,
|
|
110
|
+
subGroupingFitlerOrder: string[],
|
|
111
|
+
groupName: string
|
|
112
|
+
) => {
|
|
113
|
+
const updatedGroupOrderedValues = _.cloneDeep(subGroupingFitlerOrder)
|
|
114
|
+
const [movedItem] = updatedGroupOrderedValues.splice(currentIndex, 1)
|
|
115
|
+
updatedGroupOrderedValues.splice(newIndex, 0, movedItem)
|
|
116
|
+
const newSubGrouping = _.cloneDeep(subGrouping)
|
|
117
|
+
newSubGrouping.valuesLookup[groupName].values = updatedGroupOrderedValues
|
|
118
|
+
newSubGrouping.valuesLookup[groupName].orderedValues = updatedGroupOrderedValues
|
|
119
|
+
updateSubGroupingFilterProperty({ ...newSubGrouping, order: 'cust' })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const columnNameOptions = dataColumns.filter(columnName => !listOfUsedColumnNames.includes(columnName))
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<div className='nesteddropdown-editor'>
|
|
126
|
+
<label>
|
|
127
|
+
<span className='edit-label column-heading mt-2'>Label</span>
|
|
128
|
+
<input
|
|
129
|
+
type='text'
|
|
130
|
+
value={filter.label}
|
|
131
|
+
onChange={e => {
|
|
132
|
+
updateGroupingFilterProp('label', e.target.value)
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
</label>
|
|
136
|
+
|
|
137
|
+
<label>
|
|
138
|
+
<div className='edit-label column-heading mt-2'>
|
|
139
|
+
Filter Grouping
|
|
140
|
+
<span></span>
|
|
141
|
+
</div>
|
|
142
|
+
<select value={filter.columnName} onChange={e => handleGroupColumnNameChange(e.target.value)}>
|
|
143
|
+
<option value=''>- Select Option -</option>
|
|
144
|
+
{columnNameOptions.map((option, index) => (
|
|
145
|
+
<option value={option} key={index}>
|
|
146
|
+
{option}
|
|
147
|
+
</option>
|
|
148
|
+
))}
|
|
149
|
+
</select>
|
|
150
|
+
</label>
|
|
151
|
+
<label>
|
|
152
|
+
<div className='edit-label column-heading mt-2'>
|
|
153
|
+
Filter SubGrouping
|
|
154
|
+
<span></span>
|
|
155
|
+
</div>
|
|
156
|
+
<select
|
|
157
|
+
value={subGrouping?.columnName ?? ''}
|
|
158
|
+
onChange={e => {
|
|
159
|
+
handleSubGroupColumnNameChange(e.target.value)
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
<option value=''>- Select Option -</option>
|
|
163
|
+
{columnNameOptions.map((option, index) => {
|
|
164
|
+
if (option !== filter.columnName) {
|
|
165
|
+
return (
|
|
166
|
+
<option value={option} key={index}>
|
|
167
|
+
{option}
|
|
168
|
+
</option>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
})}
|
|
172
|
+
</select>
|
|
173
|
+
</label>
|
|
174
|
+
|
|
175
|
+
<label>
|
|
176
|
+
<input
|
|
177
|
+
type='checkbox'
|
|
178
|
+
checked={!!filter.setByQueryParameter}
|
|
179
|
+
aria-label='Create query parameters'
|
|
180
|
+
onChange={e => {
|
|
181
|
+
updateGroupingFilterProp('setByQueryParameter', filter.columnName)
|
|
182
|
+
updateSubGroupingFilterProperty({ ...subGrouping, setByQueryParameter: subGrouping.columnName })
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
<span> Create query parameters</span>
|
|
186
|
+
{!!filter.setByQueryParameter && (
|
|
187
|
+
<>
|
|
188
|
+
<span className='edit-label column-heading mt-2'>
|
|
189
|
+
Grouping: Default Value Set By Query String Parameter
|
|
190
|
+
</span>
|
|
191
|
+
<input
|
|
192
|
+
type='text'
|
|
193
|
+
value={filter.setByQueryParameter}
|
|
194
|
+
onChange={e => {
|
|
195
|
+
updateGroupingFilterProp('setByQueryParameter', e.target.value)
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
<span className='edit-label column-heading mt-2'>
|
|
199
|
+
SubGrouping: Default Value Set By Query String Parameter
|
|
200
|
+
</span>
|
|
201
|
+
<input
|
|
202
|
+
type='text'
|
|
203
|
+
value={subGrouping.setByQueryParameter}
|
|
204
|
+
onChange={e => {
|
|
205
|
+
const setByQueryParameter = e.target.value
|
|
206
|
+
updateSubGroupingFilterProperty({ ...subGrouping, setByQueryParameter })
|
|
207
|
+
}}
|
|
208
|
+
/>
|
|
209
|
+
</>
|
|
210
|
+
)}
|
|
211
|
+
</label>
|
|
212
|
+
|
|
213
|
+
<label className='mt-2'>
|
|
214
|
+
<div className='edit-label column-heading float-right'>{filter.columnName} </div>
|
|
215
|
+
<span className={'edit-filterOrder column-heading '}>Group Order</span>
|
|
216
|
+
<select value={filter.order} onChange={e => handleGroupingOrderBy(e.target.value as OrderBy)}>
|
|
217
|
+
{filterOrderOptions.map((option, index) => {
|
|
218
|
+
return (
|
|
219
|
+
<option value={option.value} key={`filter-${option.label}-${index}`}>
|
|
220
|
+
{option.label}
|
|
221
|
+
</option>
|
|
222
|
+
)
|
|
223
|
+
})}
|
|
224
|
+
</select>
|
|
225
|
+
{filter.order === 'cust' && (
|
|
226
|
+
<FilterOrder orderedValues={filter.orderedValues} handleFilterOrder={handleGroupingCustomOrder} />
|
|
227
|
+
)}
|
|
228
|
+
</label>
|
|
229
|
+
|
|
230
|
+
{subGrouping?.columnName && (
|
|
231
|
+
<label className='mt-2'>
|
|
232
|
+
<span className={'edit-filterOrder column-heading'}>SubGrouping Order</span>
|
|
233
|
+
<div className='edit-label column-heading float-right'>{subGrouping.columnName} </div>
|
|
234
|
+
<select
|
|
235
|
+
value={subGrouping.order ? subGrouping.order : 'asc'}
|
|
236
|
+
onChange={e => handleSubGroupingOrderBy(e.target.value as OrderBy)}
|
|
237
|
+
>
|
|
238
|
+
{filterOrderOptions.map((option, index) => {
|
|
239
|
+
return (
|
|
240
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
241
|
+
{option.label}
|
|
242
|
+
</option>
|
|
243
|
+
)
|
|
244
|
+
})}
|
|
245
|
+
</select>
|
|
246
|
+
{subGrouping?.order === 'cust' &&
|
|
247
|
+
filter.values.map((groupName, i) => {
|
|
248
|
+
const orderedSubGroupValues = subGrouping.valuesLookup[groupName].orderedValues
|
|
249
|
+
return (
|
|
250
|
+
<div key={`group-subgroup-values-${groupName}-${i}`}>
|
|
251
|
+
<span className='font-weight-bold'>{groupName}</span>
|
|
252
|
+
<FilterOrder
|
|
253
|
+
key={`subgroup-values-${groupName}-${i}`}
|
|
254
|
+
orderedValues={orderedSubGroupValues}
|
|
255
|
+
handleFilterOrder={(sourceIndex, destinationIndex) => {
|
|
256
|
+
handleSubGroupingCustomOrder(sourceIndex, destinationIndex, orderedSubGroupValues, groupName)
|
|
257
|
+
}}
|
|
258
|
+
/>
|
|
259
|
+
</div>
|
|
260
|
+
)
|
|
261
|
+
})}
|
|
262
|
+
</label>
|
|
263
|
+
)}
|
|
264
|
+
</div>
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export default NestedDropdownEditor
|
|
@@ -4,12 +4,14 @@ import Icon from '../../ui/Icon'
|
|
|
4
4
|
import { Visualization } from '../../../types/Visualization'
|
|
5
5
|
import { UpdateFieldFunc } from '../../../types/UpdateFieldFunc'
|
|
6
6
|
import _ from 'lodash'
|
|
7
|
-
import { MultiSelectFilter, VizFilter } from '../../../types/VizFilter'
|
|
8
|
-
import { filterStyleOptions, handleSorting } from '../../Filters'
|
|
7
|
+
import { MultiSelectFilter, VizFilter, VizFilterStyle } from '../../../types/VizFilter'
|
|
8
|
+
import { filterStyleOptions, handleSorting, filterOrderOptions } from '../../Filters'
|
|
9
9
|
import FieldSetWrapper from '../FieldSetWrapper'
|
|
10
10
|
|
|
11
11
|
import FilterOrder from './components/FilterOrder'
|
|
12
12
|
import { useMemo, useState } from 'react'
|
|
13
|
+
import MultiSelect from '../../MultiSelect'
|
|
14
|
+
import NestedDropdownEditor from './NestedDropdownEditor'
|
|
13
15
|
|
|
14
16
|
type VizFilterProps = {
|
|
15
17
|
config: Visualization
|
|
@@ -31,19 +33,22 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
31
33
|
updateField(null, null, 'filters', filters)
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
const updateFilterProp = (prop,
|
|
35
|
-
updateField('filters',
|
|
36
|
+
const updateFilterProp = (prop, filterIndex, value) => {
|
|
37
|
+
updateField('filters', filterIndex, prop, value)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const updateFilterStyle = (index,
|
|
40
|
+
const updateFilterStyle = (index, style: VizFilterStyle) => {
|
|
39
41
|
const filters = _.cloneDeep(config.filters)
|
|
40
|
-
const currentFilter = filters[index]
|
|
41
|
-
currentFilter.filterStyle =
|
|
42
|
-
if (
|
|
42
|
+
const currentFilter = { ...filters[index], orderedValues: filters[index].values }
|
|
43
|
+
currentFilter.filterStyle = style
|
|
44
|
+
if (style === 'multi-select') {
|
|
43
45
|
currentFilter.active = Array.isArray(currentFilter.active) ? currentFilter.active : [currentFilter.active]
|
|
44
46
|
} else if (Array.isArray(currentFilter.active)) {
|
|
45
47
|
currentFilter.active = currentFilter.active[0]
|
|
46
48
|
}
|
|
49
|
+
if (style === 'nested-dropdown') {
|
|
50
|
+
currentFilter.showDropdown = true
|
|
51
|
+
}
|
|
47
52
|
filters[index] = currentFilter
|
|
48
53
|
updateField(null, null, 'filters', filters)
|
|
49
54
|
}
|
|
@@ -62,14 +67,16 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
62
67
|
|
|
63
68
|
const addNewFilter = () => {
|
|
64
69
|
const filters = config.filters ? [...config.filters] : []
|
|
65
|
-
const newVizFilter: VizFilter = { values: [], filterStyle: 'dropdown' } as VizFilter
|
|
70
|
+
const newVizFilter: VizFilter = { values: [], filterStyle: 'dropdown', id: Date.now() } as VizFilter
|
|
66
71
|
filters.push(newVizFilter)
|
|
67
72
|
updateField(null, null, 'filters', filters)
|
|
68
73
|
}
|
|
69
74
|
|
|
70
|
-
const handleFilterOrder = (idx1, idx2, filterIndex
|
|
75
|
+
const handleFilterOrder = (idx1, idx2, filterIndex) => {
|
|
76
|
+
const filter = config.filters[filterIndex]
|
|
71
77
|
// Create a shallow copy of the filter values array & update position of the values
|
|
72
|
-
const updatedValues = [...filter.values]
|
|
78
|
+
const updatedValues = [...(filter.orderedValues || filter.values)]
|
|
79
|
+
|
|
73
80
|
const [movedItem] = updatedValues.splice(idx1, 1)
|
|
74
81
|
updatedValues.splice(idx2, 0, movedItem)
|
|
75
82
|
|
|
@@ -80,14 +87,20 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
80
87
|
filterItem.values = updatedValues
|
|
81
88
|
filterItem.orderedValues = updatedValues
|
|
82
89
|
filterItem.active = updatedValues[0]
|
|
90
|
+
|
|
83
91
|
filterItem.order = 'cust'
|
|
84
92
|
|
|
85
93
|
// Update the filters
|
|
86
94
|
filtersCopy[filterIndex] = filterItem
|
|
87
|
-
|
|
88
95
|
updateField(null, null, 'filters', filtersCopy)
|
|
89
96
|
}
|
|
90
97
|
|
|
98
|
+
const getParentFilterOptions = (index: number): { label: string; value: number }[] => {
|
|
99
|
+
return config.filters
|
|
100
|
+
.filter((f, i) => i !== index)
|
|
101
|
+
.map(({ label, columnName, id }) => ({ label: label || columnName, value: id }))
|
|
102
|
+
}
|
|
103
|
+
|
|
91
104
|
return (
|
|
92
105
|
<>
|
|
93
106
|
{config.filters && (
|
|
@@ -104,7 +117,10 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
104
117
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
105
118
|
</Tooltip.Target>
|
|
106
119
|
<Tooltip.Content>
|
|
107
|
-
<p>
|
|
120
|
+
<p>
|
|
121
|
+
The Apply Button option changes the visualization when the user clicks "apply". The Filter Change
|
|
122
|
+
option immediately changes the visualization when the selection is changed.
|
|
123
|
+
</p>
|
|
108
124
|
</Tooltip.Content>
|
|
109
125
|
</Tooltip>
|
|
110
126
|
}
|
|
@@ -113,46 +129,24 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
113
129
|
<ul className='filters-list'>
|
|
114
130
|
{/* Whether filters should apply onChange or Apply Button */}
|
|
115
131
|
|
|
116
|
-
{config.filters.map((filter,
|
|
132
|
+
{config.filters.map((filter, filterIndex) => {
|
|
117
133
|
if (filter.type === 'url') return <></>
|
|
118
|
-
|
|
119
134
|
return (
|
|
120
|
-
<FieldSetWrapper
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
>
|
|
129
|
-
<option value=''>- Select Option -</option>
|
|
130
|
-
{dataColumns.map((dataKey, index) => (
|
|
131
|
-
<option value={dataKey} key={index}>
|
|
132
|
-
{dataKey}
|
|
133
|
-
</option>
|
|
134
|
-
))}
|
|
135
|
-
</select>
|
|
136
|
-
</label>
|
|
137
|
-
|
|
138
|
-
<label>
|
|
139
|
-
<span className='edit-showDropdown column-heading'>Show Filter Input</span>
|
|
140
|
-
<input
|
|
141
|
-
type='checkbox'
|
|
142
|
-
checked={filter.showDropdown === undefined ? true : filter.showDropdown}
|
|
143
|
-
onChange={e => {
|
|
144
|
-
updateFilterProp('showDropdown', index, e.target.checked)
|
|
145
|
-
}}
|
|
146
|
-
/>
|
|
147
|
-
</label>
|
|
148
|
-
|
|
135
|
+
<FieldSetWrapper
|
|
136
|
+
key={filter.columnName}
|
|
137
|
+
fieldName={filter.columnName}
|
|
138
|
+
fieldKey={filterIndex}
|
|
139
|
+
fieldType='Filter'
|
|
140
|
+
controls={openControls}
|
|
141
|
+
deleteField={() => removeFilter(filterIndex)}
|
|
142
|
+
>
|
|
149
143
|
<label>
|
|
150
144
|
<span className='edit-label column-heading'>Filter Style</span>
|
|
151
145
|
|
|
152
146
|
<select
|
|
153
147
|
value={filter.filterStyle}
|
|
154
148
|
onChange={e => {
|
|
155
|
-
updateFilterStyle(
|
|
149
|
+
updateFilterStyle(filterIndex, e.target.value)
|
|
156
150
|
}}
|
|
157
151
|
>
|
|
158
152
|
{filterStyleOptions.map((item, index) => {
|
|
@@ -165,51 +159,136 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
165
159
|
</select>
|
|
166
160
|
</label>
|
|
167
161
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
162
|
+
{filter.filterStyle !== 'nested-dropdown' ? (
|
|
163
|
+
<>
|
|
164
|
+
<label>
|
|
165
|
+
<span className='edit-label column-heading'>Filter</span>
|
|
166
|
+
<select
|
|
167
|
+
value={filter.columnName}
|
|
168
|
+
onChange={e => {
|
|
169
|
+
handleNameChange(filterIndex, e.target.value)
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<option value=''>- Select Option -</option>
|
|
173
|
+
{dataColumns.map((dataKey, filterIndex) => (
|
|
174
|
+
<option value={dataKey} key={filterIndex}>
|
|
175
|
+
{dataKey}
|
|
176
|
+
</option>
|
|
177
|
+
))}
|
|
178
|
+
</select>
|
|
179
|
+
</label>
|
|
180
|
+
|
|
181
|
+
<label>
|
|
182
|
+
<span className='edit-showDropdown column-heading'>Show Filter Input</span>
|
|
183
|
+
<input
|
|
184
|
+
type='checkbox'
|
|
185
|
+
checked={filter.showDropdown === undefined ? true : filter.showDropdown}
|
|
186
|
+
onChange={e => {
|
|
187
|
+
updateFilterProp('showDropdown', filterIndex, e.target.checked)
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
</label>
|
|
191
|
+
|
|
192
|
+
<label>
|
|
193
|
+
<span className='edit-label column-heading'>Label</span>
|
|
194
|
+
<input
|
|
195
|
+
type='text'
|
|
196
|
+
value={filter.label}
|
|
197
|
+
onChange={e => {
|
|
198
|
+
updateFilterProp('label', filterIndex, e.target.value)
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
</label>
|
|
202
|
+
|
|
203
|
+
{filter.filterStyle === 'multi-select' && (
|
|
204
|
+
<TextField
|
|
205
|
+
label='Select Limit'
|
|
206
|
+
value={(filter as MultiSelectFilter).selectLimit}
|
|
207
|
+
updateField={updateField}
|
|
208
|
+
section='filters'
|
|
209
|
+
subsection={filterIndex}
|
|
210
|
+
fieldName='selectLimit'
|
|
211
|
+
type='number'
|
|
212
|
+
tooltip={
|
|
213
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
214
|
+
<Tooltip.Target>
|
|
215
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
216
|
+
</Tooltip.Target>
|
|
217
|
+
<Tooltip.Content>
|
|
218
|
+
<p>The maximum number of items that can be selected.</p>
|
|
219
|
+
</Tooltip.Content>
|
|
220
|
+
</Tooltip>
|
|
221
|
+
}
|
|
222
|
+
/>
|
|
223
|
+
)}
|
|
178
224
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
225
|
+
<label>
|
|
226
|
+
<span className='edit-label column-heading'>Default Value Set By Query String Parameter</span>
|
|
227
|
+
<input
|
|
228
|
+
type='text'
|
|
229
|
+
value={filter.setByQueryParameter}
|
|
230
|
+
onChange={e => {
|
|
231
|
+
updateFilterProp('setByQueryParameter', filterIndex, e.target.value)
|
|
232
|
+
}}
|
|
233
|
+
/>
|
|
234
|
+
</label>
|
|
235
|
+
|
|
236
|
+
<label>
|
|
237
|
+
<span className='edit-filterOrder column-heading'>Filter Order</span>
|
|
238
|
+
<select
|
|
239
|
+
value={filter.order ? filter.order : 'asc'}
|
|
240
|
+
onChange={e => updateFilterProp('order', filterIndex, e.target.value)}
|
|
241
|
+
>
|
|
242
|
+
{filterOrderOptions.map((option, index) => {
|
|
243
|
+
return (
|
|
244
|
+
<option value={option.value} key={`filter-${index}`}>
|
|
245
|
+
{option.label}
|
|
246
|
+
</option>
|
|
247
|
+
)
|
|
248
|
+
})}
|
|
249
|
+
</select>
|
|
250
|
+
{filter.order === 'cust' && (
|
|
251
|
+
<FilterOrder
|
|
252
|
+
orderedValues={filter.orderedValues || filter.values}
|
|
253
|
+
handleFilterOrder={(index1, index2) => handleFilterOrder(index1, index2, filterIndex)}
|
|
254
|
+
/>
|
|
255
|
+
)}
|
|
256
|
+
</label>
|
|
257
|
+
</>
|
|
258
|
+
) : (
|
|
259
|
+
<NestedDropdownEditor
|
|
260
|
+
config={config}
|
|
261
|
+
dataColumns={dataColumns}
|
|
262
|
+
filterIndex={filterIndex}
|
|
263
|
+
rawData={rawData}
|
|
264
|
+
handleGroupingCustomOrder={(index1, index2) => handleFilterOrder(index1, index2, filterIndex)}
|
|
265
|
+
handleNameChange={value => handleNameChange(filterIndex, value)}
|
|
183
266
|
updateField={updateField}
|
|
184
|
-
|
|
185
|
-
subsection={index}
|
|
186
|
-
fieldName='selectLimit'
|
|
187
|
-
type='number'
|
|
188
|
-
tooltip={
|
|
189
|
-
<Tooltip style={{ textTransform: 'none' }}>
|
|
190
|
-
<Tooltip.Target>
|
|
191
|
-
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
192
|
-
</Tooltip.Target>
|
|
193
|
-
<Tooltip.Content>
|
|
194
|
-
<p>The maximum number of items that can be selected.</p>
|
|
195
|
-
</Tooltip.Content>
|
|
196
|
-
</Tooltip>
|
|
197
|
-
}
|
|
267
|
+
updateFilterStyle={updateFilterStyle}
|
|
198
268
|
/>
|
|
199
269
|
)}
|
|
200
|
-
|
|
201
270
|
<label>
|
|
202
|
-
<span className='edit-label column-heading'>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
271
|
+
<span className='edit-label column-heading'>
|
|
272
|
+
Filter Parents{' '}
|
|
273
|
+
<Tooltip style={{ textTransform: 'none' }}>
|
|
274
|
+
<Tooltip.Target>
|
|
275
|
+
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
276
|
+
</Tooltip.Target>
|
|
277
|
+
<Tooltip.Content>
|
|
278
|
+
<p>
|
|
279
|
+
A selected parent's value will be used to filter the available options of this child filter.
|
|
280
|
+
</p>
|
|
281
|
+
</Tooltip.Content>
|
|
282
|
+
</Tooltip>
|
|
283
|
+
</span>
|
|
284
|
+
<MultiSelect
|
|
285
|
+
fieldName='parents'
|
|
286
|
+
updateField={(_section, _subsection, _fieldname, value) => {
|
|
287
|
+
updateFilterProp('parents', filterIndex, value)
|
|
208
288
|
}}
|
|
289
|
+
options={getParentFilterOptions(filterIndex)}
|
|
209
290
|
/>
|
|
210
291
|
</label>
|
|
211
|
-
|
|
212
|
-
<FilterOrder filterIndex={index} filter={filter} updateFilterProp={updateFilterProp} handleFilterOrder={handleFilterOrder} />
|
|
213
292
|
</FieldSetWrapper>
|
|
214
293
|
)
|
|
215
294
|
})}
|