Skip to content

Commit c160b63

Browse files
authored
fix: search measurements for the searchable dropdowns (#4279)
1 parent 2a4308f commit c160b63

File tree

3 files changed

+106
-122
lines changed

3 files changed

+106
-122
lines changed

src/flows/pipes/QueryBuilder/CardList.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import BuilderCard from 'src/timeMachine/components/builderCard/BuilderCard'
3333
import SelectorList from 'src/timeMachine/components/SelectorList'
3434

3535
import {event} from 'src/cloud/utils/reporting'
36+
import ErrorBoundary from 'src/shared/components/ErrorBoundary'
3637

3738
const DEBOUNCE_TIMEOUT = 500
3839
const debounce_array = []
@@ -259,19 +260,21 @@ const Card: FC<Props> = ({idx}) => {
259260
alignItems={AlignItems.Center}
260261
margin={ComponentSize.Small}
261262
>
262-
<SearchableDropdown
263-
searchTerm={keySearches[idx] || ''}
264-
emptyText="No Tags Found"
265-
searchPlaceholder="Search keys..."
266-
selectedOption={card.keys.selected[0]}
267-
onSelect={keySelect}
268-
buttonStatus={toComponentStatus(card.keys.loading)}
269-
onChangeSearchTerm={keySearch}
270-
testID="tag-selector--dropdown"
271-
buttonTestID="tag-selector--dropdown-button"
272-
menuTestID="tag-selector--dropdown-menu"
273-
options={card.keys.results}
274-
/>
263+
<ErrorBoundary>
264+
<SearchableDropdown
265+
searchTerm={keySearches[idx] || ''}
266+
emptyText="No Tags Found"
267+
searchPlaceholder="Search keys..."
268+
selectedOption={card.keys.selected[0]}
269+
onSelect={keySelect}
270+
buttonStatus={toComponentStatus(card.keys.loading)}
271+
onChangeSearchTerm={keySearch}
272+
testID="tag-selector--dropdown"
273+
buttonTestID="tag-selector--dropdown-button"
274+
menuTestID="tag-selector--dropdown-menu"
275+
options={card.keys.results}
276+
/>
277+
</ErrorBoundary>
275278
{!!card?.values?.selected?.length && (
276279
<TagSelectorCount count={card.values.selected.length} />
277280
)}
Lines changed: 74 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Libraries
2-
import React, {Component, ChangeEvent, CSSProperties} from 'react'
2+
import React, {FC, ChangeEvent, CSSProperties, useState} from 'react'
33

44
// Components
55
import {
@@ -11,9 +11,6 @@ import {
1111
ComponentColor,
1212
} from '@influxdata/clockface'
1313

14-
// Decorators
15-
import {ErrorHandling} from 'src/shared/decorators/errors'
16-
1714
interface Props {
1815
testID: string
1916
className?: string
@@ -22,104 +19,45 @@ interface Props {
2219
selectedOption: string
2320
onSelect: (option: string) => void
2421
onChangeSearchTerm?: (value: string) => void
25-
buttonSize: ComponentSize
26-
buttonColor: ComponentColor
2722
buttonStatus: ComponentStatus
2823
buttonTestID: string
29-
menuTheme: DropdownMenuTheme
3024
menuTestID: string
3125
options: (string | number)[]
3226
emptyText: string
3327
style?: CSSProperties
3428
}
3529

36-
@ErrorHandling
37-
export default class SearchableDropdown extends Component<Props> {
38-
public static defaultProps = {
39-
buttonSize: ComponentSize.Small,
40-
buttonColor: ComponentColor.Default,
41-
buttonStatus: ComponentStatus.Default,
42-
menuTheme: DropdownMenuTheme.Onyx,
43-
testID: 'searchable-dropdown',
44-
buttonTestID: 'searchable-dropdown--button',
45-
menuTestID: 'searchable-dropdown--menu',
46-
}
47-
48-
public render() {
49-
const {
50-
searchTerm,
51-
searchPlaceholder,
52-
buttonSize,
53-
buttonColor,
54-
buttonStatus,
55-
buttonTestID,
56-
selectedOption,
57-
testID,
58-
className,
59-
style,
60-
menuTheme,
61-
menuTestID,
62-
} = this.props
30+
const SearchableDropdown: FC<Props> = ({
31+
buttonStatus = ComponentStatus.Default,
32+
testID = 'searchable-dropdown',
33+
buttonTestID = 'searchable-dropdown--button',
34+
menuTestID = 'searchable-dropdown--menu',
35+
searchTerm = '',
36+
searchPlaceholder,
37+
selectedOption,
38+
className,
39+
style,
40+
options,
41+
onChangeSearchTerm,
42+
emptyText,
43+
onSelect,
44+
}) => {
45+
const [isSearchActive, setIsSearchActive] = useState(false)
6346

64-
return (
65-
<Dropdown
66-
testID={testID}
67-
className={className}
68-
style={style}
69-
button={(active, onClick) => (
70-
<Dropdown.Button
71-
active={active}
72-
onClick={onClick}
73-
testID={buttonTestID}
74-
color={buttonColor}
75-
size={buttonSize}
76-
status={buttonStatus}
77-
>
78-
{buttonStatus === ComponentStatus.Loading
79-
? 'Loading...'
80-
: selectedOption}
81-
</Dropdown.Button>
82-
)}
83-
menu={onCollapse => (
84-
<Dropdown.Menu
85-
onCollapse={onCollapse}
86-
theme={menuTheme}
87-
testID={menuTestID}
88-
>
89-
<div className="searchable-dropdown--input-container">
90-
<Input
91-
onChange={this.handleChange}
92-
value={searchTerm}
93-
placeholder={searchPlaceholder}
94-
size={buttonSize}
95-
autoFocus={true}
96-
/>
97-
</div>
98-
{this.filteredMenuOptions}
99-
</Dropdown.Menu>
100-
)}
101-
/>
102-
)
47+
const handleChange = (e: ChangeEvent<HTMLInputElement>): void => {
48+
onChangeSearchTerm(e.target.value)
10349
}
10450

105-
private get filteredMenuOptions(): JSX.Element[] | JSX.Element {
106-
const {
107-
searchTerm,
108-
options,
109-
emptyText,
110-
selectedOption,
111-
onSelect,
112-
} = this.props
113-
114-
const filteredOptions = options.filter(option =>
115-
`${option}`.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase())
116-
)
51+
const filteredOptions = options.filter(option =>
52+
`${option}`.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase())
53+
)
11754

118-
if (!filteredOptions.length) {
119-
return <div className="searchable-dropdown--empty">{emptyText}</div>
120-
}
55+
let body: JSX.Element | JSX.Element[] = (
56+
<div className="searchable-dropdown--empty">{emptyText}</div>
57+
)
12158

122-
return filteredOptions.map(option => (
59+
if (filteredOptions.length) {
60+
body = filteredOptions.map(option => (
12361
<Dropdown.Item
12462
key={option}
12563
value={option}
@@ -132,11 +70,51 @@ export default class SearchableDropdown extends Component<Props> {
13270
))
13371
}
13472

135-
private handleChange = (e: ChangeEvent<HTMLInputElement>): void => {
136-
const {onChangeSearchTerm} = this.props
137-
138-
if (onChangeSearchTerm) {
139-
onChangeSearchTerm(e.target.value)
140-
}
141-
}
73+
return (
74+
<Dropdown
75+
testID={testID}
76+
className={className}
77+
style={style}
78+
button={(active, onClick) => (
79+
<Dropdown.Button
80+
active={active}
81+
onClick={onClick}
82+
testID={buttonTestID}
83+
color={ComponentColor.Default}
84+
size={ComponentSize.Small}
85+
status={buttonStatus}
86+
>
87+
{buttonStatus === ComponentStatus.Loading
88+
? 'Loading...'
89+
: selectedOption}
90+
</Dropdown.Button>
91+
)}
92+
menu={onCollapse => (
93+
<Dropdown.Menu
94+
onCollapse={() => {
95+
if (isSearchActive === false) {
96+
onCollapse()
97+
}
98+
}}
99+
theme={DropdownMenuTheme.Onyx}
100+
testID={menuTestID}
101+
>
102+
<div className="searchable-dropdown--input-container">
103+
<Input
104+
onFocus={() => setIsSearchActive(true)}
105+
onChange={handleChange}
106+
onBlur={() => setIsSearchActive(false)}
107+
value={searchTerm}
108+
placeholder={searchPlaceholder}
109+
size={ComponentSize.Small}
110+
autoFocus={true}
111+
/>
112+
</div>
113+
{body}
114+
</Dropdown.Menu>
115+
)}
116+
/>
117+
)
142118
}
119+
120+
export default SearchableDropdown

src/timeMachine/components/TagSelector.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
RemoteDataState,
5050
} from 'src/types'
5151
import TagSelectorCount from 'src/shared/components/TagSelectorCount'
52+
import ErrorBoundary from 'src/shared/components/ErrorBoundary'
5253

5354
const SEARCH_DEBOUNCE_MS = 500
5455

@@ -139,19 +140,21 @@ class TagSelector extends PureComponent<Props> {
139140
alignItems={AlignItems.Center}
140141
margin={ComponentSize.Small}
141142
>
142-
<SearchableDropdown
143-
searchTerm={keysSearchTerm}
144-
emptyText="No Tags Found"
145-
searchPlaceholder="Search keys..."
146-
selectedOption={selectedKey}
147-
onSelect={this.handleSelectTag}
148-
buttonStatus={toComponentStatus(keysStatus)}
149-
onChangeSearchTerm={this.handleKeysSearch}
150-
testID="tag-selector--dropdown"
151-
buttonTestID="tag-selector--dropdown-button"
152-
menuTestID="tag-selector--dropdown-menu"
153-
options={keys}
154-
/>
143+
<ErrorBoundary>
144+
<SearchableDropdown
145+
searchTerm={keysSearchTerm}
146+
emptyText="No Tags Found"
147+
searchPlaceholder="Search keys..."
148+
buttonStatus={toComponentStatus(keysStatus)}
149+
selectedOption={selectedKey}
150+
onSelect={this.handleSelectTag}
151+
onChangeSearchTerm={this.handleKeysSearch}
152+
testID="tag-selector--dropdown"
153+
buttonTestID="tag-selector--dropdown-button"
154+
menuTestID="tag-selector--dropdown-menu"
155+
options={keys}
156+
/>
157+
</ErrorBoundary>
155158
{this.selectedCounter}
156159
</FlexBox>
157160
)}

0 commit comments

Comments
 (0)