@cdc/core 4.24.10 → 4.24.12-2
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/components/AdvancedEditor/AdvancedEditor.tsx +17 -13
- package/components/Alert/components/Alert.tsx +39 -8
- package/components/DataTable/DataTable.tsx +31 -10
- package/components/DataTable/DataTableStandAlone.tsx +3 -3
- package/components/DataTable/components/ExpandCollapse.tsx +1 -1
- package/components/DataTable/components/SortIcon/sort-icon.css +15 -0
- package/components/DataTable/data-table.css +4 -22
- package/components/DataTable/helpers/boxplotCellMatrix.tsx +19 -14
- package/components/DataTable/helpers/getChartCellValue.ts +25 -7
- package/components/EditorPanel/ColumnsEditor.tsx +81 -36
- package/components/EditorPanel/DataTableEditor.tsx +62 -56
- package/components/EditorPanel/FieldSetWrapper.tsx +2 -2
- package/components/EditorPanel/Inputs.tsx +26 -16
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +55 -56
- package/components/Filters/Filters.tsx +42 -38
- package/components/Filters/helpers/handleSorting.ts +5 -0
- package/components/Footnotes/FootnotesStandAlone.tsx +17 -4
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +0 -4
- package/components/Layout/components/Visualization/visualizations.scss +1 -1
- package/components/Legend/Legend.Gradient.tsx +50 -35
- package/components/Loader/Loader.tsx +10 -5
- package/components/MultiSelect/MultiSelect.tsx +56 -33
- package/components/MultiSelect/multiselect.styles.css +20 -7
- package/components/NestedDropdown/NestedDropdown.tsx +55 -32
- package/components/NestedDropdown/nesteddropdown.styles.css +26 -13
- package/components/Table/Table.tsx +102 -34
- package/components/Table/components/Row.tsx +1 -1
- package/components/_stories/DataTable.stories.tsx +14 -0
- package/components/_stories/Filters.stories.tsx +57 -0
- package/components/_stories/_mocks/DataTable/no-data.json +108 -0
- package/components/inputs/{InputToggle.jsx → InputToggle.tsx} +35 -29
- package/components/ui/Icon.tsx +19 -6
- package/dist/cove-main.css +26 -57
- package/dist/cove-main.css.map +1 -1
- package/helpers/DataTransform.ts +2 -1
- package/helpers/addValuesToFilters.ts +22 -8
- package/helpers/cove/{number.js → number.ts} +25 -11
- package/helpers/coveUpdateWorker.ts +1 -1
- package/helpers/fetchRemoteData.js +32 -37
- package/helpers/filterVizData.ts +2 -2
- package/helpers/formatConfigBeforeSave.ts +16 -0
- package/helpers/gatherQueryParams.ts +2 -3
- package/helpers/queryStringUtils.ts +16 -1
- package/helpers/tests/addValuesToFilters.test.ts +6 -1
- package/helpers/useDataVizClasses.ts +44 -21
- package/helpers/ver/4.24.10.ts +12 -0
- package/helpers/ver/versionNeedsUpdate.ts +2 -0
- package/helpers/viewports.ts +8 -7
- package/package.json +2 -2
- package/styles/_button-section.scss +1 -1
- package/styles/_global-variables.scss +9 -4
- package/styles/_global.scss +21 -22
- package/styles/_reset.scss +0 -12
- package/styles/filters.scss +0 -22
- package/styles/v2/base/_reset.scss +0 -7
- package/styles/v2/components/editor.scss +0 -4
- package/styles/v2/components/icon.scss +1 -1
- package/types/Axis.ts +2 -0
- package/types/BoxPlot.ts +5 -3
- package/types/Color.ts +1 -1
- package/types/Legend.ts +1 -2
- package/types/MarkupInclude.ts +1 -0
- package/types/Runtime.ts +3 -1
- package/types/Series.ts +8 -1
- package/types/Table.ts +1 -1
- package/types/Version.ts +1 -0
- package/types/Visualization.ts +7 -8
- package/types/VizFilter.ts +2 -1
- package/components/ui/Select.jsx +0 -30
- package/helpers/getGradientLegendWidth.ts +0 -15
|
@@ -83,7 +83,7 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
83
83
|
</Tooltip>
|
|
84
84
|
}
|
|
85
85
|
/>
|
|
86
|
-
{config.type !== 'table'
|
|
86
|
+
{config.type !== 'table' ? (
|
|
87
87
|
<CheckBox
|
|
88
88
|
value={config.table.show}
|
|
89
89
|
fieldName='show'
|
|
@@ -108,6 +108,15 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
108
108
|
</Tooltip>
|
|
109
109
|
}
|
|
110
110
|
/>
|
|
111
|
+
) : (
|
|
112
|
+
<CheckBox
|
|
113
|
+
value={config.general?.showDownloadButton}
|
|
114
|
+
fieldName='showDownloadButton'
|
|
115
|
+
label='Show Download CSV link'
|
|
116
|
+
section='general'
|
|
117
|
+
updateField={updateField}
|
|
118
|
+
className='column-heading'
|
|
119
|
+
/>
|
|
111
120
|
)}
|
|
112
121
|
|
|
113
122
|
{config.visualizationType !== 'Box Plot' && config.type !== 'table' && (
|
|
@@ -196,15 +205,18 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
196
205
|
/>
|
|
197
206
|
)}
|
|
198
207
|
{config?.visualizationType !== 'Sankey' && (
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
<label>
|
|
209
|
+
<span className='edit-label column-heading mt-1'>Exclude Columns </span>
|
|
210
|
+
<MultiSelect
|
|
211
|
+
key={excludedColumns.join('') + 'excluded'}
|
|
212
|
+
options={dataColumns.map(c => ({ label: c, value: c }))}
|
|
213
|
+
selected={excludedColumns}
|
|
214
|
+
label={'Exclude Columns'}
|
|
215
|
+
fieldName='dataTable'
|
|
216
|
+
section='columns'
|
|
217
|
+
updateField={excludeColumns}
|
|
218
|
+
/>
|
|
219
|
+
</label>
|
|
208
220
|
)}
|
|
209
221
|
<CheckBox
|
|
210
222
|
value={config.table.collapsible}
|
|
@@ -249,15 +261,14 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
249
261
|
updateField={updateField}
|
|
250
262
|
/>
|
|
251
263
|
)}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
)}
|
|
264
|
+
|
|
265
|
+
<CheckBox
|
|
266
|
+
value={config.table.showDownloadLinkBelow}
|
|
267
|
+
fieldName='showDownloadLinkBelow'
|
|
268
|
+
label='Show Download Link Below Table'
|
|
269
|
+
section='table'
|
|
270
|
+
updateField={updateField}
|
|
271
|
+
/>
|
|
261
272
|
<label>
|
|
262
273
|
<span className='edit-label column-heading'>Table Cell Min Width</span>
|
|
263
274
|
<input
|
|
@@ -267,9 +278,17 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
267
278
|
/>
|
|
268
279
|
</label>
|
|
269
280
|
{config?.visualizationType !== 'Sankey' && (
|
|
270
|
-
<
|
|
271
|
-
|
|
272
|
-
|
|
281
|
+
<Select
|
|
282
|
+
value={config.table.groupBy}
|
|
283
|
+
fieldName={'groupBy'}
|
|
284
|
+
section='table'
|
|
285
|
+
label='Group By'
|
|
286
|
+
updateField={(_section, _subSection, _fieldName, value) => changeGroupBy(value)}
|
|
287
|
+
initial={PLACEHOLDER}
|
|
288
|
+
options={groupPivotColumns.filter(
|
|
289
|
+
col => col !== config.table.pivot?.columnName && !(config.table.pivot?.valueColumns || []).includes(col)
|
|
290
|
+
)}
|
|
291
|
+
tooltip={
|
|
273
292
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
274
293
|
<Tooltip.Target>
|
|
275
294
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
@@ -281,27 +300,11 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
281
300
|
</p>
|
|
282
301
|
</Tooltip.Content>
|
|
283
302
|
</Tooltip>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
<select
|
|
287
|
-
value={config.table.groupBy}
|
|
288
|
-
onChange={event => {
|
|
289
|
-
changeGroupBy(event.target.value)
|
|
290
|
-
}}
|
|
291
|
-
>
|
|
292
|
-
{[
|
|
293
|
-
PLACEHOLDER,
|
|
294
|
-
...groupPivotColumns.filter(
|
|
295
|
-
col => col !== config.table.pivot?.columnName && col !== config.table.pivot?.valueColumn
|
|
296
|
-
)
|
|
297
|
-
].map(option => (
|
|
298
|
-
<option key={option}>{option}</option>
|
|
299
|
-
))}
|
|
300
|
-
</select>
|
|
301
|
-
</label>
|
|
303
|
+
}
|
|
304
|
+
/>
|
|
302
305
|
)}
|
|
303
306
|
<Select
|
|
304
|
-
label='Pivot Column
|
|
307
|
+
label='Pivot Column'
|
|
305
308
|
tooltip={
|
|
306
309
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
307
310
|
<Tooltip.Target>
|
|
@@ -314,7 +317,7 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
314
317
|
}
|
|
315
318
|
value={config.table.pivot?.columnName}
|
|
316
319
|
options={groupPivotColumns.filter(
|
|
317
|
-
col => col !== config.table.groupBy &&
|
|
320
|
+
col => col !== config.table.groupBy && !(config.table.pivot?.valueColumns || []).includes(col)
|
|
318
321
|
)}
|
|
319
322
|
initial='-Select-'
|
|
320
323
|
section='table'
|
|
@@ -323,18 +326,9 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
323
326
|
updateField={updateField}
|
|
324
327
|
/>
|
|
325
328
|
{config.table.pivot?.columnName && (
|
|
326
|
-
<
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
.filter(col => col !== config.table.pivot?.columnName && col !== config.table.groupBy)
|
|
330
|
-
.map(c => ({ label: c, value: c }))}
|
|
331
|
-
selected={config.table.pivot?.valueColumns}
|
|
332
|
-
label='Pivot Value Column(s) '
|
|
333
|
-
section='table'
|
|
334
|
-
subsection='pivot'
|
|
335
|
-
fieldName='valueColumns'
|
|
336
|
-
updateField={updateField}
|
|
337
|
-
tooltip={
|
|
329
|
+
<label>
|
|
330
|
+
<span className='edit-label column-heading mt-1'>
|
|
331
|
+
Pivot Value Column(s)
|
|
338
332
|
<Tooltip style={{ textTransform: 'none' }}>
|
|
339
333
|
<Tooltip.Target>
|
|
340
334
|
<Icon display='question' style={{ marginLeft: '0.5rem' }} />
|
|
@@ -343,8 +337,20 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
343
337
|
<p>The column(s) whos values will be pivoted under the column selected as the Filter.</p>
|
|
344
338
|
</Tooltip.Content>
|
|
345
339
|
</Tooltip>
|
|
346
|
-
|
|
347
|
-
|
|
340
|
+
</span>
|
|
341
|
+
<MultiSelect
|
|
342
|
+
key={config.table.pivot?.columnName}
|
|
343
|
+
options={groupPivotColumns
|
|
344
|
+
.filter(col => col !== config.table.pivot?.columnName && col !== config.table.groupBy)
|
|
345
|
+
.map(c => ({ label: c, value: c }))}
|
|
346
|
+
selected={config.table.pivot?.valueColumns}
|
|
347
|
+
label='Pivot Value Column(s) '
|
|
348
|
+
section='table'
|
|
349
|
+
subsection='pivot'
|
|
350
|
+
fieldName='valueColumns'
|
|
351
|
+
updateField={updateField}
|
|
352
|
+
/>
|
|
353
|
+
</label>
|
|
348
354
|
)}
|
|
349
355
|
</>
|
|
350
356
|
)
|
|
@@ -21,7 +21,7 @@ const FieldSet: React.FC<FieldSetProps> = ({ fieldName, fieldKey, fieldType, con
|
|
|
21
21
|
if (!show)
|
|
22
22
|
return (
|
|
23
23
|
<div className='mb-1'>
|
|
24
|
-
<button onClick={() => setShow(fieldKey, true)}>
|
|
24
|
+
<button className='btn btn-light' onClick={() => setShow(fieldKey, true)}>
|
|
25
25
|
<Icon display='caretDown' />
|
|
26
26
|
</button>
|
|
27
27
|
<span> {fieldName ? `${fieldName}` : 'New ' + fieldType}</span>
|
|
@@ -30,7 +30,7 @@ const FieldSet: React.FC<FieldSetProps> = ({ fieldName, fieldKey, fieldType, con
|
|
|
30
30
|
return (
|
|
31
31
|
<fieldset className='edit-block mb-1' key={fieldKey}>
|
|
32
32
|
<div className='d-flex justify-content-between'>
|
|
33
|
-
<button onClick={() => setShow(fieldKey, false)}>
|
|
33
|
+
<button className='btn btn-light' onClick={() => setShow(fieldKey, false)}>
|
|
34
34
|
<Icon display='caretUp' />
|
|
35
35
|
</button>
|
|
36
36
|
<button
|
|
@@ -31,16 +31,6 @@ export type CheckboxProps = {
|
|
|
31
31
|
} & Input &
|
|
32
32
|
Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value'>
|
|
33
33
|
|
|
34
|
-
export type SelectProps = {
|
|
35
|
-
value?: string
|
|
36
|
-
options?: string[]
|
|
37
|
-
required?: boolean
|
|
38
|
-
initial?: string
|
|
39
|
-
|
|
40
|
-
// all other props
|
|
41
|
-
[x: string]: any
|
|
42
|
-
} & Input
|
|
43
|
-
|
|
44
34
|
const TextField = memo((props: TextFieldProps) => {
|
|
45
35
|
const {
|
|
46
36
|
display = true,
|
|
@@ -141,6 +131,16 @@ const CheckBox = memo((props: CheckboxProps) => {
|
|
|
141
131
|
)
|
|
142
132
|
})
|
|
143
133
|
|
|
134
|
+
export type SelectProps = {
|
|
135
|
+
value?: string
|
|
136
|
+
options?: string[] | { label: string; value: string }[]
|
|
137
|
+
required?: boolean
|
|
138
|
+
initial?: string
|
|
139
|
+
|
|
140
|
+
// all other props
|
|
141
|
+
[x: string]: any
|
|
142
|
+
} & Input
|
|
143
|
+
|
|
144
144
|
const Select = memo((props: SelectProps) => {
|
|
145
145
|
const {
|
|
146
146
|
display = true,
|
|
@@ -156,11 +156,21 @@ const Select = memo((props: SelectProps) => {
|
|
|
156
156
|
initial: initialValue,
|
|
157
157
|
...attributes
|
|
158
158
|
} = props
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
159
|
+
const optionsJsx = options.map((option, index) => {
|
|
160
|
+
if (typeof option === 'string') {
|
|
161
|
+
return (
|
|
162
|
+
<option value={option} key={index}>
|
|
163
|
+
{option}
|
|
164
|
+
</option>
|
|
165
|
+
)
|
|
166
|
+
} else {
|
|
167
|
+
return (
|
|
168
|
+
<option value={option.value} key={index}>
|
|
169
|
+
{option.label}
|
|
170
|
+
</option>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
164
174
|
|
|
165
175
|
if (initialValue) {
|
|
166
176
|
optionsJsx.unshift(
|
|
@@ -180,7 +190,7 @@ const Select = memo((props: SelectProps) => {
|
|
|
180
190
|
{tooltip}
|
|
181
191
|
</span>
|
|
182
192
|
<select
|
|
183
|
-
className={required && !value ? 'warning' : ''}
|
|
193
|
+
className={`cove-form-select ${required && !value ? 'warning' : ''}`}
|
|
184
194
|
name={fieldName}
|
|
185
195
|
value={value}
|
|
186
196
|
onChange={event => {
|
|
@@ -67,7 +67,12 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
67
67
|
|
|
68
68
|
const addNewFilter = () => {
|
|
69
69
|
const filters = config.filters ? [...config.filters] : []
|
|
70
|
-
const newVizFilter: VizFilter = {
|
|
70
|
+
const newVizFilter: VizFilter = {
|
|
71
|
+
values: [],
|
|
72
|
+
filterStyle: 'dropdown',
|
|
73
|
+
id: Date.now(),
|
|
74
|
+
showDropdown: true
|
|
75
|
+
} as VizFilter
|
|
71
76
|
filters.push(newVizFilter)
|
|
72
77
|
updateField(null, null, 'filters', filters)
|
|
73
78
|
}
|
|
@@ -125,6 +130,13 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
125
130
|
</Tooltip>
|
|
126
131
|
}
|
|
127
132
|
/>
|
|
133
|
+
<TextField
|
|
134
|
+
type='textarea'
|
|
135
|
+
label='Filter intro text'
|
|
136
|
+
value={config.filterIntro}
|
|
137
|
+
updateField={updateField}
|
|
138
|
+
fieldName='filterIntro'
|
|
139
|
+
/>
|
|
128
140
|
<br />
|
|
129
141
|
<ul className='filters-list'>
|
|
130
142
|
{/* Whether filters should apply onChange or Apply Button */}
|
|
@@ -140,43 +152,24 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
140
152
|
controls={openControls}
|
|
141
153
|
deleteField={() => removeFilter(filterIndex)}
|
|
142
154
|
>
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}}
|
|
151
|
-
>
|
|
152
|
-
{filterStyleOptions.map((item, index) => {
|
|
153
|
-
return (
|
|
154
|
-
<option key={`filter-style-${index}`} value={item}>
|
|
155
|
-
{item}
|
|
156
|
-
</option>
|
|
157
|
-
)
|
|
158
|
-
})}
|
|
159
|
-
</select>
|
|
160
|
-
</label>
|
|
155
|
+
<Select
|
|
156
|
+
value={filter.filterStyle}
|
|
157
|
+
fieldName='filterStyle'
|
|
158
|
+
label='Filter Style'
|
|
159
|
+
updateField={(_section, _subsection, _field, value) => updateFilterStyle(filterIndex, value)}
|
|
160
|
+
options={filterStyleOptions}
|
|
161
|
+
/>
|
|
161
162
|
|
|
162
163
|
{filter.filterStyle !== 'nested-dropdown' ? (
|
|
163
164
|
<>
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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>
|
|
165
|
+
<Select
|
|
166
|
+
value={filter.columnName}
|
|
167
|
+
fieldName='columnName'
|
|
168
|
+
label='Filter'
|
|
169
|
+
updateField={(_section, _subsection, _field, value) => handleNameChange(filterIndex, value)}
|
|
170
|
+
options={dataColumns}
|
|
171
|
+
initial='- Select Option -'
|
|
172
|
+
/>
|
|
180
173
|
|
|
181
174
|
<label>
|
|
182
175
|
<span className='edit-showDropdown column-heading'>Show Filter Input</span>
|
|
@@ -233,27 +226,32 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
233
226
|
/>
|
|
234
227
|
</label>
|
|
235
228
|
|
|
236
|
-
<
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
229
|
+
<Select
|
|
230
|
+
value={filter.order || 'asc'}
|
|
231
|
+
fieldName='order'
|
|
232
|
+
label='Filter Order'
|
|
233
|
+
updateField={(_section, _subSection, _field, value) =>
|
|
234
|
+
updateFilterProp('order', filterIndex, value)
|
|
235
|
+
}
|
|
236
|
+
options={filterOrderOptions}
|
|
237
|
+
/>
|
|
238
|
+
{filter.order === 'cust' && (
|
|
239
|
+
<FilterOrder
|
|
240
|
+
orderedValues={filter.orderedValues || filter.values}
|
|
241
|
+
handleFilterOrder={(index1, index2) => handleFilterOrder(index1, index2, filterIndex)}
|
|
242
|
+
/>
|
|
243
|
+
)}
|
|
244
|
+
{filter.order === 'column' && (
|
|
245
|
+
<Select
|
|
246
|
+
value={filter.orderColumn}
|
|
247
|
+
fieldName='orderColumn'
|
|
248
|
+
label='Order Column'
|
|
249
|
+
updateField={(_section, _subSection, _field, value) =>
|
|
250
|
+
updateFilterProp('orderColumn', filterIndex, value)
|
|
251
|
+
}
|
|
252
|
+
options={dataColumns}
|
|
253
|
+
/>
|
|
254
|
+
)}
|
|
257
255
|
</>
|
|
258
256
|
) : (
|
|
259
257
|
<NestedDropdownEditor
|
|
@@ -287,6 +285,7 @@ const VizFilterEditor: React.FC<VizFilterProps> = ({ config, updateField, rawDat
|
|
|
287
285
|
updateFilterProp('parents', filterIndex, value)
|
|
288
286
|
}}
|
|
289
287
|
options={getParentFilterOptions(filterIndex)}
|
|
288
|
+
selected={config.filters[filterIndex].parents}
|
|
290
289
|
/>
|
|
291
290
|
</label>
|
|
292
291
|
</FieldSetWrapper>
|
|
@@ -41,18 +41,25 @@ export const filterOrderOptions: { label: string; value: OrderBy }[] = [
|
|
|
41
41
|
{
|
|
42
42
|
label: 'Custom',
|
|
43
43
|
value: 'cust'
|
|
44
|
-
}
|
|
44
|
+
},
|
|
45
|
+
{ label: 'Order By Data Column', value: 'column' }
|
|
45
46
|
]
|
|
46
47
|
|
|
47
|
-
const hasStandardFilterBehavior = ['chart', 'table']
|
|
48
|
-
|
|
49
48
|
export const useFilters = props => {
|
|
50
49
|
const [showApplyButton, setShowApplyButton] = useState(false)
|
|
51
50
|
|
|
52
51
|
// Desconstructing: notice, adding more descriptive visualizationConfig name over config
|
|
53
52
|
// visualizationConfig feels more robust for all vis types so that its not confused with config/state/etc.
|
|
54
|
-
const {
|
|
55
|
-
|
|
53
|
+
const {
|
|
54
|
+
config: visualizationConfig,
|
|
55
|
+
setConfig,
|
|
56
|
+
filteredData,
|
|
57
|
+
setFilteredData,
|
|
58
|
+
excludedData,
|
|
59
|
+
getUniqueValues,
|
|
60
|
+
standaloneMap
|
|
61
|
+
} = props
|
|
62
|
+
const { data } = visualizationConfig
|
|
56
63
|
|
|
57
64
|
/**
|
|
58
65
|
* Re-orders a filter based on two indices and updates the runtime filters array and filters state
|
|
@@ -72,9 +79,7 @@ export const useFilters = props => {
|
|
|
72
79
|
const [movedItem] = updatedValues.splice(idx1, 1)
|
|
73
80
|
updatedValues.splice(idx2, 0, movedItem)
|
|
74
81
|
|
|
75
|
-
const filtersCopy =
|
|
76
|
-
? [...visualizationConfig.filters]
|
|
77
|
-
: [...filteredData]
|
|
82
|
+
const filtersCopy = !standaloneMap ? [...visualizationConfig.filters] : [...filteredData]
|
|
78
83
|
const filterItem = { ...filtersCopy[filterIndex] }
|
|
79
84
|
|
|
80
85
|
// Overwrite filterItem.values since thats what we map through in the editor panel
|
|
@@ -86,7 +91,7 @@ export const useFilters = props => {
|
|
|
86
91
|
// Update the filters
|
|
87
92
|
filtersCopy[filterIndex] = filterItem
|
|
88
93
|
|
|
89
|
-
if (
|
|
94
|
+
if (standaloneMap) {
|
|
90
95
|
setFilteredData(filtersCopy)
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -94,7 +99,7 @@ export const useFilters = props => {
|
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
const changeFilterActive = (index, value) => {
|
|
97
|
-
let newFilters =
|
|
102
|
+
let newFilters = standaloneMap ? [...filteredData] : [...visualizationConfig.filters]
|
|
98
103
|
|
|
99
104
|
if (visualizationConfig.filterBehavior === 'Apply Button') {
|
|
100
105
|
newFilters[index].queuedActive = value
|
|
@@ -120,7 +125,7 @@ export const useFilters = props => {
|
|
|
120
125
|
queryParams[newFilter?.subGrouping?.setByQueryParameter] = newFilter.subGrouping.active
|
|
121
126
|
updateQueryString(queryParams)
|
|
122
127
|
}
|
|
123
|
-
setFilteredData(newFilters
|
|
128
|
+
setFilteredData(newFilters)
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
if (!visualizationConfig.dynamicSeries) {
|
|
@@ -132,15 +137,12 @@ export const useFilters = props => {
|
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
// Used for setting active filter, fromHash breaks the filteredData functionality.
|
|
135
|
-
if (
|
|
140
|
+
if (standaloneMap && visualizationConfig.filterBehavior === 'Filter Change') {
|
|
136
141
|
setFilteredData(newFilters)
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
// If we're on a chart and not using the apply button
|
|
140
|
-
if (
|
|
141
|
-
hasStandardFilterBehavior.includes(visualizationConfig.type) &&
|
|
142
|
-
visualizationConfig.filterBehavior === 'Filter Change'
|
|
143
|
-
) {
|
|
145
|
+
if (!standaloneMap && visualizationConfig.filterBehavior === 'Filter Change') {
|
|
144
146
|
const newFilteredData = filterVizData(newFilters, excludedData)
|
|
145
147
|
setFilteredData(newFilteredData)
|
|
146
148
|
|
|
@@ -204,11 +206,9 @@ export const useFilters = props => {
|
|
|
204
206
|
|
|
205
207
|
setConfig({ ...visualizationConfig, filters: newFilters })
|
|
206
208
|
|
|
207
|
-
if (
|
|
209
|
+
if (standaloneMap) {
|
|
208
210
|
setFilteredData(newFilters, excludedData)
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (hasStandardFilterBehavior.includes(visualizationConfig.type)) {
|
|
211
|
+
} else {
|
|
212
212
|
setFilteredData(filterVizData(newFilters, excludedData))
|
|
213
213
|
}
|
|
214
214
|
|
|
@@ -240,7 +240,7 @@ export const useFilters = props => {
|
|
|
240
240
|
|
|
241
241
|
setConfig({ ...visualizationConfig, filters: newFilters })
|
|
242
242
|
|
|
243
|
-
if (
|
|
243
|
+
if (standaloneMap) {
|
|
244
244
|
setFilteredData(newFilters, excludedData)
|
|
245
245
|
} else {
|
|
246
246
|
setFilteredData(filterVizData(newFilters, excludedData))
|
|
@@ -249,9 +249,7 @@ export const useFilters = props => {
|
|
|
249
249
|
|
|
250
250
|
const filterConstants = {
|
|
251
251
|
buttonText: 'Apply Filters',
|
|
252
|
-
resetText: 'Reset All'
|
|
253
|
-
introText: `Make a selection from the filters to change the visualization information.`,
|
|
254
|
-
applyText: 'Select the apply button to update the visualization information.'
|
|
252
|
+
resetText: 'Reset All'
|
|
255
253
|
}
|
|
256
254
|
|
|
257
255
|
// prettier-ignore
|
|
@@ -276,13 +274,12 @@ type FilterProps = {
|
|
|
276
274
|
setFilteredData: Function
|
|
277
275
|
// updating function for setting fitlerBehavior
|
|
278
276
|
setConfig: Function
|
|
279
|
-
|
|
280
|
-
exclusions: any[]
|
|
277
|
+
standaloneMap?: boolean
|
|
281
278
|
}
|
|
282
279
|
|
|
283
280
|
const Filters = (props: FilterProps) => {
|
|
284
|
-
const { config: visualizationConfig, filteredData, dimensions } = props
|
|
285
|
-
const { filters,
|
|
281
|
+
const { config: visualizationConfig, filteredData, dimensions, standaloneMap } = props
|
|
282
|
+
const { filters, general, theme, filterBehavior } = visualizationConfig
|
|
286
283
|
const [mobileFilterStyle, setMobileFilterStyle] = useState(false)
|
|
287
284
|
const [selectedFilter, setSelectedFilter] = useState<EventTarget>(null)
|
|
288
285
|
const id = useId()
|
|
@@ -351,7 +348,7 @@ const Filters = (props: FilterProps) => {
|
|
|
351
348
|
id={`filter-${outerIndex}`}
|
|
352
349
|
name={label}
|
|
353
350
|
aria-label={`Filter by ${label}`}
|
|
354
|
-
className='
|
|
351
|
+
className='cove-form-select'
|
|
355
352
|
data-index='0'
|
|
356
353
|
value={active}
|
|
357
354
|
onChange={e => {
|
|
@@ -365,7 +362,7 @@ const Filters = (props: FilterProps) => {
|
|
|
365
362
|
|
|
366
363
|
const vizFiltersWithValues = useMemo(() => {
|
|
367
364
|
// Here charts is using config.filters where maps is using a runtime value
|
|
368
|
-
let vizfilters =
|
|
365
|
+
let vizfilters = standaloneMap ? filteredData : filters
|
|
369
366
|
if (!vizfilters) return []
|
|
370
367
|
if (vizfilters.fromHash) delete vizfilters.fromHash // support for Maps config
|
|
371
368
|
return addValuesToFilters(vizfilters as VizFilter[], visualizationConfig.data)
|
|
@@ -439,6 +436,7 @@ const Filters = (props: FilterProps) => {
|
|
|
439
436
|
|
|
440
437
|
const classList = [
|
|
441
438
|
'single-filters',
|
|
439
|
+
'form-group mr-3',
|
|
442
440
|
mobileFilterStyle ? 'single-filters--dropdown' : `single-filters--${filterStyle}`
|
|
443
441
|
]
|
|
444
442
|
const mobileExempt = ['nested-dropdown', 'multi-select'].includes(filterStyle)
|
|
@@ -446,7 +444,11 @@ const Filters = (props: FilterProps) => {
|
|
|
446
444
|
return (
|
|
447
445
|
<div className={classList.join(' ')} key={outerIndex}>
|
|
448
446
|
<>
|
|
449
|
-
{label &&
|
|
447
|
+
{label && (
|
|
448
|
+
<label className='font-weight-bold mt-1 mb-0' htmlFor={`filter-${outerIndex}`}>
|
|
449
|
+
{label}
|
|
450
|
+
</label>
|
|
451
|
+
)}
|
|
450
452
|
{filterStyle === 'tab' && !mobileFilterStyle && Tabs}
|
|
451
453
|
{filterStyle === 'pill' && !mobileFilterStyle && Pills}
|
|
452
454
|
{filterStyle === 'tab bar' && !mobileFilterStyle && <TabBar filter={singleFilter} index={outerIndex} />}
|
|
@@ -463,6 +465,7 @@ const Filters = (props: FilterProps) => {
|
|
|
463
465
|
<NestedDropdown
|
|
464
466
|
activeGroup={(singleFilter.active as string) || (singleFilter.queuedActive || [])[0]}
|
|
465
467
|
activeSubGroup={(singleFilter.subGrouping?.active as string) || (singleFilter.queuedActive || [])[1]}
|
|
468
|
+
filterIndex={outerIndex}
|
|
466
469
|
options={getNestedOptions(singleFilter)}
|
|
467
470
|
listLabel={label}
|
|
468
471
|
handleSelectedItems={value => changeFilterActive(outerIndex, value)}
|
|
@@ -488,7 +491,7 @@ const Filters = (props: FilterProps) => {
|
|
|
488
491
|
const getClasses = () => {
|
|
489
492
|
const { visualizationType, legend } = visualizationConfig || {}
|
|
490
493
|
const baseClass = 'filters-section'
|
|
491
|
-
const conditionalClass =
|
|
494
|
+
const conditionalClass = standaloneMap ? general.headerColor : visualizationType === 'Spark Line' ? null : theme
|
|
492
495
|
const legendClass = legend && !legend.hide && legend.position === 'top' ? 'mb-0' : null
|
|
493
496
|
|
|
494
497
|
return [baseClass, conditionalClass, legendClass].filter(Boolean)
|
|
@@ -496,18 +499,19 @@ const Filters = (props: FilterProps) => {
|
|
|
496
499
|
|
|
497
500
|
return (
|
|
498
501
|
<section className={getClasses().join(' ')}>
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
<div className='filters-section__wrapper'>
|
|
502
|
+
{visualizationConfig.filterIntro && (
|
|
503
|
+
<p className='filters-section__intro-text'>{visualizationConfig.filterIntro}</p>
|
|
504
|
+
)}
|
|
505
|
+
<div className='d-flex flex-wrap w-100 filters-section__wrapper'>
|
|
504
506
|
{' '}
|
|
505
507
|
<>
|
|
506
508
|
<Style />
|
|
507
509
|
{filterBehavior === 'Apply Button' ? (
|
|
508
510
|
<div className='filters-section__buttons'>
|
|
509
511
|
<Button
|
|
510
|
-
onClick={
|
|
512
|
+
onClick={e => {
|
|
513
|
+
handleApplyButton(filters)
|
|
514
|
+
}}
|
|
511
515
|
disabled={!showApplyButton}
|
|
512
516
|
className={[general?.headerColor ? general.headerColor : theme, 'apply'].join(' ')}
|
|
513
517
|
>
|
|
@@ -7,6 +7,11 @@ export const handleSorting = singleFilter => {
|
|
|
7
7
|
return singleFilter
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
if (singleFilter.order === 'column') {
|
|
11
|
+
// sorting is done in the generateValuesForFilter function
|
|
12
|
+
return singleFilter
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
const sort = (a, b) => {
|
|
11
16
|
const asc = singleFilter.order !== 'desc'
|
|
12
17
|
return String(asc ? a : b).localeCompare(String(asc ? b : a), 'en', { numeric: true })
|