Skip to content

Commit fe624e0

Browse files
authored
feat(6482): add smoothing to sql graphs (#6514)
* feat(6482): apply RDP data smoothing viewOption, per field column, in SQL query modifiers for graphing * feat(6482): set default graph properties, based on state of smoothing * chore: provide a shared component for DropdownList selector, and utilize in SqlQueryOptions * feat(6482): refactor ViewResults context to make easier to understand. Set initial view.properties correctly based upon the data expected in childResults. * feat(6482): Remove unsupported graph types.
1 parent d888295 commit fe624e0

File tree

9 files changed

+413
-52
lines changed

9 files changed

+413
-52
lines changed

src/dataExplorer/components/Results.tsx

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
import React, {
2-
FC,
3-
useCallback,
4-
useContext,
5-
useEffect,
6-
useMemo,
7-
useState,
8-
} from 'react'
1+
import React, {FC, useContext, useEffect, useMemo, useState} from 'react'
92
import {
103
Button,
114
ComponentColor,
@@ -206,10 +199,7 @@ const GraphResults: FC = () => {
206199

207200
const WrappedOptions: FC = () => {
208201
const [showOverlay, setShowOverlay] = useState(false)
209-
210-
// use parent `results` so all metadata is present for the viz options
211-
const {result} = useContext(ResultsContext)
212-
const {queryModifers, setResult, setStatus} = useContext(ChildResultsContext)
202+
const {result, queryModifers} = useContext(ChildResultsContext)
213203
const {view, setView, selectViewOptions, viewOptions, selectedViewOptions} =
214204
useContext(ResultsViewContext)
215205
const {resource, query: text, selection} = useContext(PersistanceContext)
@@ -221,18 +211,15 @@ const WrappedOptions: FC = () => {
221211
)
222212
const seeGraphSubquery = () => setShowOverlay(true)
223213

224-
const updateChildResults = useCallback(
225-
update => {
226-
setView({
227-
...view,
228-
properties: {
229-
...view.properties,
230-
...update,
231-
},
232-
})
233-
},
234-
[setStatus, setResult]
235-
)
214+
const updateChildResults = update => {
215+
setView({
216+
...view,
217+
properties: {
218+
...view.properties,
219+
...update,
220+
},
221+
})
222+
}
236223

237224
if (!dataExists) {
238225
return null
@@ -267,6 +254,13 @@ const WrappedOptions: FC = () => {
267254
)
268255
}
269256

257+
const NOT_SUPPORTED_GRAPH_TYPES = [
258+
SUPPORTED_VISUALIZATIONS.check.type,
259+
SUPPORTED_VISUALIZATIONS.gauge.type,
260+
SUPPORTED_VISUALIZATIONS.geo.type,
261+
SUPPORTED_VISUALIZATIONS.mosaic.type,
262+
SUPPORTED_VISUALIZATIONS['single-stat'].type,
263+
]
270264
const GraphHeader: FC = () => {
271265
const {view, setView, viewOptions} = useContext(ResultsViewContext)
272266
const {result} = useContext(ResultsContext)
@@ -310,6 +304,7 @@ const GraphHeader: FC = () => {
310304
<ViewTypeDropdown
311305
viewType={view.properties.type}
312306
onUpdateType={updateType}
307+
filter={NOT_SUPPORTED_GRAPH_TYPES}
313308
/>
314309
<Button
315310
text="Customize"

src/dataExplorer/components/SqlViewOptions.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
@import '@influxdata/clockface/dist/variables.scss';
22

33
.sql-view-options {
4+
padding-bottom: calc($cf-form-xs-height * 0.5);
45
.cf-list {
56
flex: 1 0 !important;
67

78
.selector-list--item {
89
height: $cf-form-xs-height;
910
}
1011
}
12+
.view-options--smoothing-header {
13+
padding-top: calc($cf-form-xs-height * 0.5);
14+
height: $cf-form-lg-height;
15+
justify-content: space-between;
16+
}
1117
.sql-view-options--see-query {
1218
padding-top: $cf-form-xs-height;
1319
display: flex;

src/dataExplorer/components/SqlViewOptions.tsx

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import React, {FC} from 'react'
2-
import {Columns, Grid, Button, ComponentStatus} from '@influxdata/clockface'
2+
import {
3+
Button,
4+
Columns,
5+
ComponentStatus,
6+
FlexBox,
7+
Grid,
8+
SlideToggle,
9+
} from '@influxdata/clockface'
310

4-
import SelectorList from 'src/timeMachine/components/SelectorList'
11+
import {RecursivePartial} from 'src/types'
12+
import {DropdownList as SelectorList} from 'src/shared/components/DropdownList'
513
import SelectorTitle from 'src/dataExplorer/components/SelectorTitle'
614
import {ViewOptions} from 'src/dataExplorer/context/resultsView'
715

816
import './SqlViewOptions.scss'
917

1018
interface SqlViewOptionsT {
11-
selectViewOptions: (_: Partial<ViewOptions>) => void
19+
selectViewOptions: (_: RecursivePartial<ViewOptions>) => void
1220
allViewOptions: ViewOptions
1321
selectedViewOptions: ViewOptions
1422
seeSubquery: () => void
@@ -50,6 +58,28 @@ export const SqlViewOptions: FC<SqlViewOptionsT> = ({
5058
</div>
5159
)
5260

61+
const smoothingTooltipContents = (
62+
<div>
63+
<span>Smoothing used for the graph subquery.</span>
64+
<br />
65+
<br />
66+
<span>
67+
Smoothing applies a{' '}
68+
<a href="https://docs.influxdata.com/flux/v0.x/stdlib/experimental/polyline/rdp/">
69+
RDP algorithm
70+
</a>{' '}
71+
to downsample your data, while maintaining the trends. Smoothing will be
72+
applied to a single column of data, based upon your chosen 'Y column'.
73+
</span>
74+
<br />
75+
<br />
76+
<span>
77+
Goal is to display a graph covering the entire time range, even if your
78+
full returned results are truncated in the table view.
79+
</span>
80+
</div>
81+
)
82+
5383
return (
5484
<div className="view-options sql-view-options">
5585
<Grid>
@@ -71,6 +101,31 @@ export const SqlViewOptions: FC<SqlViewOptionsT> = ({
71101
onSelectItem={tagKey => handleSelectedListItem('groupby', tagKey)}
72102
multiSelect={true}
73103
/>
104+
<FlexBox className="view-options--smoothing-header">
105+
<SelectorTitle
106+
label="Graph smoothing"
107+
tooltipContents={smoothingTooltipContents}
108+
/>
109+
<SlideToggle
110+
active={selectedViewOptions?.smoothing?.applied}
111+
onChange={() =>
112+
selectViewOptions({
113+
smoothing: {
114+
applied: !selectedViewOptions?.smoothing?.applied,
115+
},
116+
})
117+
}
118+
/>
119+
</FlexBox>
120+
<SelectorList
121+
items={allViewOptions?.smoothing?.columns ?? []}
122+
selectedItems={selectedViewOptions?.smoothing?.columns ?? []}
123+
onSelectItem={column =>
124+
selectViewOptions({smoothing: {columns: [column]}})
125+
}
126+
multiSelect={false}
127+
disabled={!selectedViewOptions?.smoothing?.applied}
128+
/>
74129
<div className="sql-view-options--see-query">
75130
<Button
76131
testID="sql-view-options--see-query"

src/dataExplorer/context/fields.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {DEFAULT_LIMIT} from 'src/shared/constants/queryBuilder'
1111

1212
// Contexts
1313
import {QueryContext, QueryScope} from 'src/shared/contexts/query'
14+
import {ResultsViewContext} from 'src/dataExplorer/context/resultsView'
1415

1516
// Utils
1617
import {
@@ -46,6 +47,7 @@ interface Prop {
4647
export const FieldsProvider: FC<Prop> = ({children, scope}) => {
4748
// Contexts
4849
const {query: queryAPI} = useContext(QueryContext)
50+
const {setDefaultViewOptions} = useContext(ResultsViewContext)
4951

5052
// States
5153
const [fields, setFields] = useState<Array<string>>(
@@ -105,6 +107,7 @@ export const FieldsProvider: FC<Prop> = ({children, scope}) => {
105107
)[0]?.data ?? []) as string[]
106108
setFields(values)
107109
setLoading(RemoteDataState.Done)
110+
setDefaultViewOptions({smoothing: {columns: values}})
108111
} catch (e) {
109112
console.error(e.message)
110113
setLoading(RemoteDataState.Error)

src/dataExplorer/context/results/childResults.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ const modifiersToApply = (viewOptions: ViewOptions): SqlQueryModifiers => {
3131
}
3232

3333
// 2. smoothing transformation next
34-
// e.g. to smooth by selected column foo. Rough example.
35-
const shouldSmooth = false
34+
const shouldSmooth =
35+
viewOptions.smoothing?.columns?.length > 0 && viewOptions.smoothing?.applied
3636
if (shouldSmooth) {
3737
prepend.push(`import "experimental/polyline"`)
38-
// append.push(`|> polyline.rdp(valColumn: "foo", timeColumn: "time")`) // TODO
38+
append.push(
39+
`|> polyline.rdp(valColumn: "${viewOptions.smoothing.columns[0]}", timeColumn: "time")`
40+
)
3941
}
4042

4143
return Boolean(prepend.length + append.length)
@@ -136,7 +138,7 @@ export const ChildResultsProvider: FC = ({children}) => {
136138
})
137139
setStatus(RemoteDataState.Error)
138140
})
139-
}, [resultFromParent, viewOptions, setStatus, setResult])
141+
}, [resultFromParent, setStatus, setResult, viewOptions])
140142

141143
return (
142144
<ChildResultsContext.Provider

0 commit comments

Comments
 (0)