Skip to content

Commit e300499

Browse files
authored
feat: attempt to normalize the bucket language (#4881)
1 parent d2e9129 commit e300499

File tree

2 files changed

+159
-24
lines changed

2 files changed

+159
-24
lines changed

src/dataExplorer/components/BucketSelector.tsx

Lines changed: 147 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,174 @@
1-
import React, {FC, useContext, useState} from 'react'
1+
import React, {FC, Fragment, ChangeEvent, useContext, useState} from 'react'
2+
import {
3+
TechnoSpinner,
4+
ComponentSize,
5+
Dropdown,
6+
DropdownMenuTheme,
7+
IconFont,
8+
Input,
9+
} from '@influxdata/clockface'
210

311
// Components
4-
import {ComponentStatus} from '@influxdata/clockface'
512
import SelectorTitle from 'src/dataExplorer/components/SelectorTitle'
6-
import SearchableDropdown from 'src/shared/components/SearchableDropdown'
713

814
// Contexts
915
import {FluxQueryBuilderContext} from 'src/dataExplorer/context/fluxQueryBuilder'
1016
import {BucketContext} from 'src/shared/contexts/buckets'
1117
import {event} from 'src/cloud/utils/reporting'
1218

19+
// Types
20+
import {RemoteDataState, Bucket} from 'src/types'
21+
1322
const BUCKET_TOOLTIP = `A bucket is a named location where time series data \
1423
is stored. You can think of a bucket like you would a database in SQL systems.`
1524

25+
const REMAP_BUCKET_TYPES = {
26+
user: 'My Data',
27+
system: 'System Data',
28+
sample: 'Sample Data',
29+
}
30+
1631
const BucketSelector: FC = () => {
1732
const {selectedBucket, selectBucket} = useContext(FluxQueryBuilderContext)
18-
const {buckets} = useContext(BucketContext)
33+
const {loading, buckets} = useContext(BucketContext)
34+
const [isSearchActive, setIsSearchActive] = useState(false)
1935
const [searchTerm, setSearchTerm] = useState('')
2036

21-
const handleSelectBucket = (name: string) => {
22-
const bucket = buckets.find(b => b.name === name)
23-
if (!bucket) {
24-
return
25-
}
37+
const _buckets = buckets.filter(b =>
38+
`${b.name}`.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase())
39+
)
40+
41+
const handleSelectBucket = (buck: Bucket) => {
2642
event('bucketSelected', {search: searchTerm.length})
27-
selectBucket(bucket)
43+
selectBucket(buck)
44+
}
45+
46+
const handleChange = (e: ChangeEvent<HTMLInputElement>): void => {
47+
setSearchTerm(e.target.value)
48+
}
49+
50+
let buttonText = 'Loading buckets...'
51+
if (loading === RemoteDataState.Done && !selectedBucket?.name) {
52+
buttonText = 'Select bucket...'
53+
} else if (loading === RemoteDataState.Done && selectedBucket?.name) {
54+
buttonText = selectedBucket.name
2855
}
2956

30-
const handleChangeSearchTerm = (value: string) => {
31-
setSearchTerm(value)
57+
const button = (active, onClick) => (
58+
<Dropdown.Button
59+
onClick={onClick}
60+
active={active}
61+
testID="bucket-selector--dropdown-button"
62+
>
63+
{buttonText}
64+
</Dropdown.Button>
65+
)
66+
67+
if (loading !== RemoteDataState.Done) {
68+
return (
69+
<div>
70+
<SelectorTitle title="Bucket" info={BUCKET_TOOLTIP} />
71+
<Dropdown
72+
button={button}
73+
menu={onCollapse => (
74+
<Dropdown.Menu onCollapse={onCollapse}>
75+
<Dropdown.ItemEmpty>
76+
<TechnoSpinner
77+
strokeWidth={ComponentSize.Small}
78+
diameterPixels={32}
79+
/>
80+
</Dropdown.ItemEmpty>
81+
</Dropdown.Menu>
82+
)}
83+
/>
84+
</div>
85+
)
3286
}
3387

88+
if (!_buckets.length) {
89+
return (
90+
<div>
91+
<SelectorTitle title="Bucket" info={BUCKET_TOOLTIP} />
92+
<Dropdown
93+
button={button}
94+
menu={onCollapse => (
95+
<Dropdown.Menu onCollapse={onCollapse}>
96+
<Dropdown.ItemEmpty>No Buckets Available</Dropdown.ItemEmpty>
97+
</Dropdown.Menu>
98+
)}
99+
/>
100+
</div>
101+
)
102+
}
103+
104+
const body = Object.entries(
105+
_buckets.reduce((acc, curr) => {
106+
if (!acc[curr.type]) {
107+
acc[curr.type] = []
108+
}
109+
110+
acc[curr.type].push(curr)
111+
return acc
112+
}, {}) as Record<string, Bucket[]>
113+
).map(([k, v]) => {
114+
const items = v.map(bucket => (
115+
<Dropdown.Item
116+
key={bucket.name}
117+
value={bucket}
118+
onClick={handleSelectBucket}
119+
selected={bucket.name === selectedBucket?.name}
120+
title={bucket.name}
121+
wrapText={true}
122+
testID={`bucket-selector--dropdown--${bucket.name}`}
123+
>
124+
{bucket.name}
125+
</Dropdown.Item>
126+
))
127+
128+
let name = k
129+
130+
if (REMAP_BUCKET_TYPES.hasOwnProperty(k)) {
131+
name = REMAP_BUCKET_TYPES[k]
132+
}
133+
134+
return (
135+
<Fragment key={name}>
136+
<Dropdown.Divider text={name} />
137+
{items}
138+
</Fragment>
139+
)
140+
})
141+
34142
return (
35143
<div>
36144
<SelectorTitle title="Bucket" info={BUCKET_TOOLTIP} />
37-
<SearchableDropdown
38-
searchTerm={searchTerm}
39-
searchPlaceholder="Search buckets"
40-
selectedOption={selectedBucket?.name || 'Select bucket...'}
41-
onSelect={handleSelectBucket}
42-
onChangeSearchTerm={handleChangeSearchTerm}
43-
options={buckets.map(b => b.name)}
44-
buttonStatus={ComponentStatus.Default}
45-
testID="bucket-selector--dropdown"
46-
buttonTestID="bucket-selector--dropdown-button"
47-
menuTestID="bucket-selector--dropdown-menu"
48-
emptyText="No Buckets Found"
145+
<Dropdown
146+
button={button}
147+
menu={onCollapse => (
148+
<Dropdown.Menu
149+
onCollapse={() => {
150+
if (isSearchActive === false) {
151+
onCollapse()
152+
}
153+
}}
154+
theme={DropdownMenuTheme.Onyx}
155+
testID="searchable-dropdown--menu"
156+
>
157+
<div className="searchable-dropdown--input-container">
158+
<Input
159+
icon={IconFont.Search_New}
160+
onFocus={() => setIsSearchActive(true)}
161+
onChange={handleChange}
162+
onBlur={() => setIsSearchActive(false)}
163+
value={searchTerm}
164+
placeholder="Search buckets"
165+
size={ComponentSize.Small}
166+
autoFocus={true}
167+
/>
168+
</div>
169+
{body}
170+
</Dropdown.Menu>
171+
)}
49172
/>
50173
</div>
51174
)

src/dataExplorer/components/Schema.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010

1111
.schema-browser {
1212
padding-right: $cf-space-xs;
13+
14+
.cf-dropdown-divider {
15+
color: $cf-grey-55;
16+
text-transform: uppercase;
17+
letter-spacing: 0.07em;
18+
border-radius: 1px;
19+
border-bottom: 2px solid $cf-grey-25;
20+
white-space: nowrap;
21+
overflow: hidden;
22+
text-overflow: ellipsis;
23+
font-weight: 600;
24+
}
1325
}
1426

1527
.container-side-bar {

0 commit comments

Comments
 (0)