Skip to content

Commit bf86641

Browse files
authored
feat: add multiselect for measurements (#5673)
* feat: add multiselect for measurements * fix: missed some edgecase behaviors * fix: updating styling and text per design review Co-authored-by: drdelambre <drdelambre>
1 parent 418cede commit bf86641

File tree

4 files changed

+102
-9
lines changed

4 files changed

+102
-9
lines changed

src/timeMachine/actions/queryBuilderThunks.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,14 @@ const loadTagSelectorValues =
7878

7979
const state = getState()
8080
const {buckets, tags} = getActiveQuery(state).builderConfig
81-
const tagsSelections = tags.slice(0, index)
81+
const tagsSelections = tags
82+
.slice(0, index)
83+
.filter(
84+
t =>
85+
t.key !== '_measurement' ||
86+
t.values.length !== 1 ||
87+
t.values[0] !== '_all'
88+
)
8289

8390
if (!buckets[0]) {
8491
return
@@ -155,7 +162,14 @@ export const loadTagSelector =
155162
dispatch(setBuilderTagKeysStatus(index, RemoteDataState.Loading))
156163

157164
const state = getState()
158-
const tagsSelections = tags.slice(0, index)
165+
const tagsSelections = tags
166+
.slice(0, index)
167+
.filter(
168+
t =>
169+
t.key !== '_measurement' ||
170+
t.values.length !== 1 ||
171+
t.values[0] !== '_all'
172+
)
159173

160174
const bucket = buckets[0]
161175

@@ -328,7 +342,11 @@ export const selectTagValue =
328342
currentTag.key === '_field'
329343
) {
330344
newValues = [value]
331-
} else if (isFlagEnabled('newQueryBuilder') && index === 0) {
345+
} else if (
346+
isFlagEnabled('newQueryBuilder') &&
347+
index === 0 &&
348+
!isFlagEnabled('measurementMultiselect')
349+
) {
332350
newValues = [value]
333351
} else {
334352
newValues = [...values, value]

src/timeMachine/components/SelectorList.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface Props {
1212
children?: JSX.Element | JSX.Element[]
1313
testID?: string
1414
wrapText?: boolean
15+
disabled?: boolean
1516
}
1617

1718
const SelectorList: FC<Props> = props => {
@@ -23,6 +24,7 @@ const SelectorList: FC<Props> = props => {
2324
children,
2425
testID,
2526
wrapText,
27+
disabled,
2628
} = props
2729

2830
return (
@@ -48,6 +50,7 @@ const SelectorList: FC<Props> = props => {
4850
selected={selected}
4951
size={ComponentSize.ExtraSmall}
5052
wrapText={wrapText}
53+
disabled={disabled}
5154
>
5255
{indicator}
5356
{item}

src/timeMachine/components/TagSelector.tsx

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
FlexBox,
1010
FlexDirection,
1111
Input,
12+
List,
1213
} from '@influxdata/clockface'
1314
import SearchableDropdown from 'src/shared/components/SearchableDropdown'
1415
import WaitingText from 'src/shared/components/WaitingText'
@@ -20,12 +21,16 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
2021

2122
// Actions
2223
import {
23-
removeTagSelector,
24+
addTagSelector,
2425
searchTagKeys,
2526
searchTagValues,
2627
selectTagKey,
2728
selectTagValue,
29+
loadTagSelector,
30+
removeTagSelector,
2831
} from 'src/timeMachine/actions/queryBuilderThunks'
32+
import {setBuilderTagValuesSelection} from 'src/timeMachine/actions/queryBuilder'
33+
2934
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
3035

3136
import {
@@ -91,7 +96,7 @@ class TagSelector extends PureComponent<Props> {
9196
index === 0 &&
9297
(selectedKey === '' || selectedKey === '_measurement') &&
9398
aggregateFunctionType !== 'group' &&
94-
selectedValues.length <= 1
99+
(isFlagEnabled('measurementMultiselect') || selectedValues.length <= 1)
95100
)
96101
}
97102

@@ -202,6 +207,35 @@ class TagSelector extends PureComponent<Props> {
202207
)
203208
}
204209

210+
private toggleSelectAll() {
211+
const {
212+
selectedValues,
213+
onSetBuilderTagValuesSelection,
214+
onAddTagSelector,
215+
onRemoveTagSelector,
216+
index,
217+
isLast,
218+
shouldClearLast,
219+
onLoadTagSelector,
220+
} = this.props
221+
222+
if (selectedValues.length === 1 && selectedValues[0] === '_all') {
223+
onSetBuilderTagValuesSelection(0, [])
224+
225+
if (shouldClearLast) {
226+
onRemoveTagSelector(index + 1)
227+
}
228+
} else {
229+
onSetBuilderTagValuesSelection(0, ['_all'])
230+
231+
if (isLast) {
232+
onAddTagSelector()
233+
} else {
234+
onLoadTagSelector(index + 1)
235+
}
236+
}
237+
}
238+
205239
private get values() {
206240
const {selectedKey, values, valuesStatus, selectedValues} = this.props
207241

@@ -232,13 +266,38 @@ class TagSelector extends PureComponent<Props> {
232266
)
233267
}
234268

269+
// underscore values are not allowed for user data
270+
// so there shouldn't be collisions
271+
const selectedAll =
272+
selectedValues.length === 1 && selectedValues[0] === '_all'
273+
235274
return (
236275
<SelectorList
237-
items={values}
276+
items={values.filter(t => t !== '_all')}
238277
selectedItems={selectedValues}
239278
onSelectItem={this.handleSelectValue}
240-
multiSelect={!this.props.isInCheckOverlay || this.isCompliant}
241-
/>
279+
multiSelect={
280+
!this.props.isInCheckOverlay ||
281+
(this.isCompliant && isFlagEnabled('measurementMultiselect'))
282+
}
283+
disabled={selectedAll}
284+
>
285+
{this.isCompliant && isFlagEnabled('measurementMultiselect') && (
286+
<List.Item
287+
className="selector-list--item select-all"
288+
testID="selector-list --select-all"
289+
key="_all"
290+
value="_all"
291+
onClick={() => this.toggleSelectAll()}
292+
title="Select All"
293+
selected={selectedAll}
294+
size={ComponentSize.ExtraSmall}
295+
>
296+
<List.Indicator type="checkbox" />
297+
All Measurements
298+
</List.Item>
299+
)}
300+
</SelectorList>
242301
)
243302
}
244303

@@ -350,6 +409,9 @@ const mstp = (state: AppState, ownProps: OwnProps) => {
350409
values = [...ADDITIONAL_GROUP_BY_COLUMNS, ...tags.map(tag => tag.key)]
351410
}
352411
const isInCheckOverlay = getIsInCheckOverlay(state)
412+
const isLast = ownProps.index === tags.length - 1
413+
const shouldClearLast =
414+
ownProps.index === tags.length - 2 && !tags[tags.length - 1].values.length
353415

354416
return {
355417
aggregateFunctionType,
@@ -363,6 +425,8 @@ const mstp = (state: AppState, ownProps: OwnProps) => {
363425
valuesSearchTerm,
364426
keysSearchTerm,
365427
isInCheckOverlay,
428+
isLast,
429+
shouldClearLast,
366430
}
367431
}
368432

@@ -375,6 +439,9 @@ const mdtp = {
375439
onSetBuilderAggregateFunctionType: setBuilderAggregateFunctionType,
376440
onSetKeysSearchTerm: setKeysSearchTerm,
377441
onSetValuesSearchTerm: setValuesSearchTerm,
442+
onSetBuilderTagValuesSelection: setBuilderTagValuesSelection,
443+
onAddTagSelector: addTagSelector,
444+
onLoadTagSelector: loadTagSelector,
378445
}
379446

380447
const connector = connect(mstp, mdtp)

src/timeMachine/utils/queryBuilder.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,12 @@ function buildQueryFromConfig(
107107
): string {
108108
const [bucket] = builderConfig.buckets
109109

110-
const tags = Array.from(builderConfig.tags)
110+
const tags = Array.from(builderConfig.tags).filter(
111+
t =>
112+
t.key !== '_measurement' ||
113+
t.values.length !== 1 ||
114+
t.values[0] !== '_all'
115+
)
111116

112117
// todo: (bucky) - check to see if we can combine filter calls
113118
// https://github.com/influxdata/influxdb/issues/16076

0 commit comments

Comments
 (0)