Skip to content

Commit 3b24d1d

Browse files
authored
feat(4708/4709): flux browser panel in QX flux query builder (#4780)
Add the FluxBrowser panel to the QX FluxEditor, within a SidePane (to be used by other future menus too), and using the EditorProvider for injection. Introduced a new shared MinimalInjectionOption, to be used with FilterList, in order to match the new design for an injection option.
1 parent 72a4a9b commit 3b24d1d

File tree

18 files changed

+285
-38
lines changed

18 files changed

+285
-38
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@import '@influxdata/clockface/dist/variables.scss';
2+
3+
.qx-builder-flux-browser {
4+
.flux-toolbar {
5+
display: flex;
6+
flex-direction: column;
7+
align-items: stretch;
8+
height: 100%;
9+
position: absolute;
10+
width: 100%;
11+
.flux-toolbar--search {
12+
padding: 0px;
13+
display: flex;
14+
align-items: center;
15+
justify-content: flex-start;
16+
width: 100%;
17+
}
18+
.flux-toolbar--list {
19+
overflow-y: scroll;
20+
height: 100%;
21+
}
22+
}
23+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React, {FC, useCallback, useContext, useEffect, useMemo} from 'react'
2+
import {useDispatch, useSelector} from 'react-redux'
3+
4+
// Components
5+
import SelectorTitle from 'src/dataExplorer/components/SelectorTitle'
6+
import FilterList from 'src/shared/components/FilterList/FilterList'
7+
import FluxDocsTooltipContent from 'src/shared/components/functions/perFunction/FluxDocsTooltipContent'
8+
import Fn from 'src/shared/components/FilterList/MinimalistInjectOption'
9+
10+
// State
11+
import {getFluxPackages} from 'src/shared/actions/fluxDocs'
12+
import {getAllFluxFunctions} from 'src/shared/selectors/app'
13+
import {EditorContext} from 'src/shared/contexts/editor'
14+
15+
// Types
16+
import {FluxFunction} from 'src/types/shared'
17+
18+
// Utils
19+
import {event} from 'src/cloud/utils/reporting'
20+
import {getFluxExample} from 'src/shared/utils/fluxExample'
21+
import {sortFuncs} from 'src/shared/components/functions/utils'
22+
import './FluxBrowser.scss'
23+
24+
const TOOLTIP = `The flux standard library contains several packages, \
25+
functions, and variables which may be useful when constructing your flux query.`
26+
27+
const FluxBrowser: FC = () => {
28+
const {editor, injectFunction} = useContext(EditorContext)
29+
30+
const dispatch = useDispatch()
31+
const fluxFunctions = useSelector(getAllFluxFunctions)
32+
33+
useEffect(() => {
34+
if (fluxFunctions.length === 0) {
35+
dispatch(getFluxPackages())
36+
}
37+
}, [])
38+
39+
const handleSelectItem = useCallback(
40+
(func: FluxFunction) => {
41+
injectFunction(getFluxExample(func), _ => null)
42+
event('flux.function.injected', {name: `${func.package}.${func.name}`})
43+
},
44+
[injectFunction, editor]
45+
)
46+
47+
const render = useCallback(
48+
fn => (
49+
<Fn
50+
onClick={handleSelectItem}
51+
extractor={fn =>
52+
`${(fn as FluxFunction).package}.${(fn as FluxFunction).name}`
53+
}
54+
key={`${fn.name}_${fn.desc}`}
55+
option={fn}
56+
testID={fn.name}
57+
ToolTipContent={FluxDocsTooltipContent}
58+
/>
59+
),
60+
[handleSelectItem, editor]
61+
)
62+
63+
return useMemo(
64+
() => (
65+
<div className="qx-builder-flux-browser">
66+
<SelectorTitle title="Flux library" info={TOOLTIP} />
67+
<FilterList
68+
placeholder="Search for package or function..."
69+
emptyMessage="No results matched your search"
70+
extractor={fn =>
71+
`${(fn as FluxFunction).name} ${(fn as FluxFunction).package}`
72+
}
73+
items={fluxFunctions.sort(sortFuncs)}
74+
renderItem={render}
75+
/>
76+
</div>
77+
),
78+
[editor, render, fluxFunctions, injectFunction]
79+
)
80+
}
81+
82+
export default FluxBrowser

src/dataExplorer/components/FluxQueryBuilder.tsx

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,48 @@ import React, {FC, useState} from 'react'
33
// Components
44
import {DraggableResizer, Orientation} from '@influxdata/clockface'
55
import {QueryProvider} from 'src/shared/contexts/query'
6+
import {EditorProvider} from 'src/shared/contexts/editor'
67
import {ResultsProvider} from 'src/dataExplorer/components/ResultsContext'
78
import ResultsPane from 'src/dataExplorer/components/ResultsPane'
9+
import SidePane from 'src/dataExplorer/components/SidePane'
810
import Schema from 'src/dataExplorer/components/Schema'
911

1012
// Styles
1113
import './FluxQueryBuilder.scss'
1214

13-
const INITIAL_VERT_RESIZER_HANDLE = 0.24
15+
const INITIAL_LEFT_VERT_RESIZER_HANDLE = 0.2
16+
const INITIAL_RIGHT_VERT_RESIZER_HANDLE = 0.8
1417

1518
const FluxQueryBuilder: FC = () => {
1619
const [vertDragPosition, setVertDragPosition] = useState([
17-
INITIAL_VERT_RESIZER_HANDLE,
20+
INITIAL_LEFT_VERT_RESIZER_HANDLE,
21+
INITIAL_RIGHT_VERT_RESIZER_HANDLE,
1822
])
1923

2024
return (
2125
<QueryProvider>
22-
<DraggableResizer
23-
handleOrientation={Orientation.Vertical}
24-
handlePositions={vertDragPosition}
25-
onChangePositions={setVertDragPosition}
26-
>
27-
<DraggableResizer.Panel>
28-
<Schema />
29-
</DraggableResizer.Panel>
30-
<DraggableResizer.Panel className="new-data-explorer-rightside">
31-
<ResultsProvider>
32-
<ResultsPane />
33-
</ResultsProvider>
34-
</DraggableResizer.Panel>
35-
</DraggableResizer>
26+
<EditorProvider>
27+
<DraggableResizer
28+
handleOrientation={Orientation.Vertical}
29+
handlePositions={vertDragPosition}
30+
onChangePositions={setVertDragPosition}
31+
>
32+
<DraggableResizer.Panel>
33+
<Schema />
34+
</DraggableResizer.Panel>
35+
<DraggableResizer.Panel
36+
testID="flux-query-builder-middle-panel"
37+
className="new-data-explorer-rightside"
38+
>
39+
<ResultsProvider>
40+
<ResultsPane />
41+
</ResultsProvider>
42+
</DraggableResizer.Panel>
43+
<DraggableResizer.Panel>
44+
<SidePane />
45+
</DraggableResizer.Panel>
46+
</DraggableResizer>
47+
</EditorProvider>
3648
</QueryProvider>
3749
)
3850
}

src/dataExplorer/components/ResultsPane.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {createLocalStorageStateHook} from 'use-local-storage-state'
1818
import TimeRangeDropdown from 'src/shared/components/TimeRangeDropdown'
1919
import Results from 'src/dataExplorer/components/Results'
2020
import {ResultsContext} from 'src/dataExplorer/components/ResultsContext'
21+
import {EditorContext} from 'src/shared/contexts/editor'
2122
import {TimeRange} from 'src/types'
2223
import {SubmitQueryButton} from 'src/timeMachine/components/SubmitQueryButton'
2324
import {downloadTextFile} from 'src/shared/utils/download'
@@ -52,6 +53,8 @@ const ResultsPane: FC = () => {
5253
const [text, setText] = useLocalStorageState()
5354
const [timeRange, setTimeRange] = useState<TimeRange>(DEFAULT_TIME_RANGE)
5455

56+
const {setEditor} = useContext(EditorContext)
57+
5558
const download = () => {
5659
event('CSV Download Initiated')
5760
basic(text).promise.then(response => {
@@ -139,6 +142,7 @@ const ResultsPane: FC = () => {
139142
variables={variables}
140143
script={text}
141144
onChangeScript={setText}
145+
setEditorInstance={setEditor}
142146
/>
143147
</Suspense>
144148
</div>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import '@influxdata/clockface/dist/variables.scss';
2+
3+
.container-right-side-bar {
4+
margin-left: $cf-space-s;
5+
width: inherit;
6+
overflow-x: hidden;
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React, {FC} from 'react'
2+
3+
// Components
4+
import FluxBrowser from 'src/dataExplorer/components/FluxBrowser'
5+
6+
// Utils
7+
import './SidePane.scss'
8+
9+
const SidePane: FC = () => {
10+
return (
11+
<div className="container-right-side-bar">
12+
<FluxBrowser />
13+
</div>
14+
)
15+
}
16+
17+
export default SidePane

src/flows/pipes/RawFluxEditor/SecretsList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
IconFont,
1111
JustifyContent,
1212
} from '@influxdata/clockface'
13-
import FilterList from 'src/flows/shared/FilterList/FilterList'
14-
import InjectSecretOption from 'src/flows/shared/FilterList/InjectionOption'
13+
import FilterList from 'src/shared/components/FilterList/FilterList'
14+
import InjectSecretOption from 'src/shared/components/FilterList/InjectionOption'
1515
import {showOverlay, dismissOverlay} from 'src/overlays/actions/overlays'
1616

1717
// Actions & Selectors

src/flows/pipes/RawFluxEditor/view.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import {VariablesContext} from 'src/flows/context/variables'
2828

2929
// Components
3030
import SecretsList from 'src/flows/pipes/RawFluxEditor/SecretsList'
31-
import Functions from 'src/flows/pipes/RawFluxEditor/FunctionsList/GroupedFunctionsList'
32-
import DynamicFunctions from 'src/flows/pipes/RawFluxEditor/FunctionsList/DynamicFunctionsList'
31+
import Functions from 'src/shared/components/functions/FunctionsList/GroupedFunctionsList'
32+
import DynamicFunctions from 'src/shared/components/functions/FunctionsList/DynamicFunctionsList'
3333

3434
// Styles
3535
import 'src/flows/pipes/RawFluxEditor/style.scss'

src/flows/shared/FilterList/FilterList.tsx renamed to src/shared/components/FilterList/FilterList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const FilterList: FC<Props> = ({
5454
</>
5555
)
5656
}
57-
}, [search, items])
57+
}, [search, items, renderItem])
5858

5959
return useMemo(
6060
() => (

0 commit comments

Comments
 (0)