Skip to content

Commit 1d2db3b

Browse files
authored
feat: adds the adaptive zoom view option (#5542)
1 parent a9394db commit 1d2db3b

File tree

4 files changed

+171
-60
lines changed

4 files changed

+171
-60
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Libraries
2+
import React, {CSSProperties, FC} from 'react'
3+
4+
// Components
5+
import {
6+
AlignItems,
7+
ComponentSize,
8+
FlexBox,
9+
FlexDirection,
10+
InfluxColors,
11+
InputLabel,
12+
QuestionMarkTooltip,
13+
SlideToggle,
14+
} from '@influxdata/clockface'
15+
import {SafeBlankLink} from 'src/utils/SafeBlankLink'
16+
17+
// Metrics
18+
import {event} from 'src/cloud/utils/reporting'
19+
20+
interface AdaptiveZoomToggleProps {
21+
adaptiveZoomHide: boolean
22+
update: (obj: any) => void
23+
testID?: string
24+
type: string
25+
}
26+
27+
const getToggleColor = (toggle: boolean): CSSProperties => {
28+
if (toggle) {
29+
return {color: InfluxColors.Grey95}
30+
}
31+
return {color: InfluxColors.Grey65}
32+
}
33+
34+
const adaptiveZoomTooltipStyle = {
35+
maxWidth: '40%',
36+
padding: '2px 18px',
37+
}
38+
39+
const adaptiveZoomTooltip = (
40+
<div>
41+
<p>
42+
When enabled, will re-query on the selected domain upon zooming in on the
43+
graph. Requires window period set to Auto.
44+
</p>
45+
<p>
46+
<SafeBlankLink href="https://docs.influxdata.com/influxdb/cloud/visualize-data/variables/#vwindowperiod">
47+
Learn about window period
48+
</SafeBlankLink>
49+
</p>
50+
</div>
51+
)
52+
53+
export const AdaptiveZoomToggle: FC<AdaptiveZoomToggleProps> = ({
54+
adaptiveZoomHide,
55+
update,
56+
type,
57+
}) => {
58+
const handleSetAdaptiveZoom = () => {
59+
update({
60+
adaptiveZoomHide: !adaptiveZoomHide,
61+
})
62+
event(`visualization.customize.adaptiveZoom.${!adaptiveZoomHide}`, {
63+
type,
64+
})
65+
}
66+
67+
return (
68+
<FlexBox
69+
direction={FlexDirection.Row}
70+
alignItems={AlignItems.Center}
71+
margin={ComponentSize.Medium}
72+
stretchToFitWidth={true}
73+
className="adaptive-zoom-toggle"
74+
testID="adaptive-zoom-toggle"
75+
>
76+
<SlideToggle
77+
active={!adaptiveZoomHide}
78+
size={ComponentSize.ExtraSmall}
79+
onChange={handleSetAdaptiveZoom}
80+
/>
81+
<InputLabel style={getToggleColor(adaptiveZoomHide)}>
82+
Adaptive Zoom
83+
</InputLabel>
84+
<QuestionMarkTooltip
85+
diameter={16}
86+
tooltipContents={adaptiveZoomTooltip}
87+
tooltipStyle={adaptiveZoomTooltipStyle}
88+
/>
89+
</FlexBox>
90+
)
91+
}

src/visualization/types/Graph/options.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ import {
2626
parseYBounds,
2727
} from 'src/shared/utils/vis'
2828
import {generateSeriesToColorHex} from 'src/visualization/utils/colorMappingUtils'
29+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
2930

3031
// Components
32+
import {AdaptiveZoomToggle} from 'src/visualization/components/internal/AdaptiveZoomOption'
3133
import AutoDomainInput from 'src/shared/components/AutoDomainInput'
3234
import ColorSchemeDropdown from 'src/visualization/components/internal/ColorSchemeDropdown'
3335
import HoverLegend from 'src/visualization/components/internal/HoverLegend'
@@ -147,6 +149,20 @@ const GraphViewOptions: FC<Props> = ({properties, results, update}) => {
147149
}
148150
/>
149151
</Form.Element>
152+
{isFlagEnabled('zoomRequery') && (
153+
<AdaptiveZoomToggle
154+
adaptiveZoomHide={properties.adaptiveZoomHide}
155+
type={properties.type}
156+
update={update}
157+
/>
158+
)}
159+
</Grid.Column>
160+
<Grid.Column
161+
widthXS={Columns.Twelve}
162+
widthMD={Columns.Six}
163+
widthLG={Columns.Four}
164+
>
165+
<h5 className="view-options--header">Options</h5>
150166
<Form.Element label="Time Format">
151167
<SelectDropdown
152168
options={FORMAT_OPTIONS.map(option => option.text)}
@@ -156,13 +172,6 @@ const GraphViewOptions: FC<Props> = ({properties, results, update}) => {
156172
}}
157173
/>
158174
</Form.Element>
159-
</Grid.Column>
160-
<Grid.Column
161-
widthXS={Columns.Twelve}
162-
widthMD={Columns.Six}
163-
widthLG={Columns.Four}
164-
>
165-
<h5 className="view-options--header">Options</h5>
166175
{properties.geom && (
167176
<Form.Element label="Interpolation">
168177
<Dropdown

src/visualization/types/Graph/view.tsx

Lines changed: 28 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ import {useLegendOpacity} from 'src/visualization/utils/useLegendOpacity'
4747
import {useStaticLegend} from 'src/visualization/utils/useStaticLegend'
4848
import {useZoomQuery} from 'src/visualization/utils/useZoomQuery'
4949
import {
50-
useVisXDomainSettings,
51-
useVisYDomainSettings,
5250
useZoomRequeryXDomainSettings,
5351
useZoomRequeryYDomainSettings,
5452
} from 'src/visualization/utils/useVisDomainSettings'
@@ -60,11 +58,11 @@ import {
6058
defaultXColumn,
6159
defaultYColumn,
6260
} from 'src/shared/utils/vis'
61+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
6362

6463
// Annotations
6564
import {addAnnotationLayer} from 'src/visualization/utils/annotationUtils'
6665
import {getColorMappingObjects} from 'src/visualization/utils/colorMappingUtils'
67-
import {isFlagEnabled} from '../../../shared/utils/featureFlag'
6866

6967
// Selectors
7068
import {getByID} from 'src/resources/selectors'
@@ -171,55 +169,36 @@ const XYPlot: FC<Props> = ({
171169
properties.position,
172170
])
173171

174-
let useXDomainSettings = ({storedDomain, parsedResult, timeRange}) =>
175-
useVisXDomainSettings(
176-
storedDomain,
177-
parsedResult.table.getColumn(xColumn, 'number'),
178-
timeRange
179-
)
180-
let useYDomainSettings = options => {
181-
const {storedDomain} = options
182-
return useVisYDomainSettings(storedDomain, memoizedYColumnData)
183-
}
184-
185172
const zoomQuery = useZoomQuery(properties)
186-
if (isFlagEnabled('zoomRequery')) {
187-
useXDomainSettings = ({storedDomain, parsedResult, timeRange}) =>
188-
useZoomRequeryXDomainSettings({
189-
data: parsedResult.table.getColumn(xColumn, 'number'),
190-
parsedResult,
191-
preZoomResult,
192-
query: zoomQuery,
193-
setPreZoomResult,
194-
setRequeryStatus,
195-
setResult: setResultState,
196-
storedDomain,
197-
timeRange,
198-
})
199-
useYDomainSettings = ({storedDomain, parsedResult}) =>
200-
useZoomRequeryYDomainSettings({
201-
data: memoizedYColumnData,
202-
parsedResult,
203-
preZoomResult,
204-
query: zoomQuery,
205-
setPreZoomResult,
206-
setRequeryStatus,
207-
setResult: setResultState,
208-
storedDomain,
209-
})
210-
}
211173

212-
const [xDomain, onSetXDomain, onResetXDomain] = useXDomainSettings({
213-
storedDomain: storedXDomain,
214-
parsedResult: resultState,
215-
timeRange,
216-
})
174+
const [xDomain, onSetXDomain, onResetXDomain] = useZoomRequeryXDomainSettings(
175+
{
176+
adaptiveZoomHide: properties.adaptiveZoomHide,
177+
data: resultState.table.getColumn(xColumn, 'number'),
178+
parsedResult: resultState,
179+
preZoomResult,
180+
query: zoomQuery,
181+
setPreZoomResult,
182+
setRequeryStatus,
183+
setResult: setResultState,
184+
storedDomain: storedXDomain,
185+
timeRange,
186+
}
187+
)
217188

218-
const [yDomain, onSetYDomain, onResetYDomain] = useYDomainSettings({
219-
storedDomain: storedYDomain,
220-
parsedResult: resultState,
221-
timeRange,
222-
})
189+
const [yDomain, onSetYDomain, onResetYDomain] = useZoomRequeryYDomainSettings(
190+
{
191+
adaptiveZoomHide: properties.adaptiveZoomHide,
192+
data: memoizedYColumnData,
193+
parsedResult: resultState,
194+
preZoomResult,
195+
query: zoomQuery,
196+
setPreZoomResult,
197+
setRequeryStatus,
198+
setResult: setResultState,
199+
storedDomain: storedYDomain,
200+
}
201+
)
223202

224203
const legendColumns = filterNoisyColumns(
225204
properties.position === 'stacked'

src/visualization/utils/useVisDomainSettings.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
normalizeWindowPeriodForZoomRequery,
2424
normalizeWindowPeriodVariableForZoomRequery,
2525
} from 'src/variables/utils/getWindowVars'
26+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
2627

2728
// Types
2829
import {AppState, InternalFromFluxResult, TimeRange} from 'src/types'
@@ -142,6 +143,7 @@ export const useVisYDomainSettings = (
142143
}
143144

144145
interface ZoomRequeryArgs {
146+
adaptiveZoomHide: boolean
145147
data: NumericColumnData | string[]
146148
parsedResult: InternalFromFluxResult
147149
preZoomResult: InternalFromFluxResult
@@ -158,6 +160,7 @@ const isNotEqual = (firstValue: any, secondValue: any): boolean =>
158160

159161
export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
160162
const {
163+
adaptiveZoomHide,
161164
data,
162165
parsedResult,
163166
preZoomResult,
@@ -185,7 +188,7 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
185188
* - can be changed by the time range dropdown
186189
* - uses one-way state to capture the very first set of values
187190
*/
188-
const [preZoomDomain] = useOneWayState(initialDomain)
191+
const [preZoomDomain, setPreZoomDomain] = useOneWayState(initialDomain)
189192

190193
/*
191194
* domain:
@@ -265,6 +268,20 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
265268
}
266269
}, [preZoomDomain]) // eslint-disable-line react-hooks/exhaustive-deps
267270

271+
// Suppresses adaptive zoom feature; must come after all hooks
272+
if (!isFlagEnabled('zoomRequery') || adaptiveZoomHide) {
273+
const setVisXDomain = (domain: NumericColumnData) => {
274+
setPreZoomDomain(domain)
275+
event('plot.zoom_in.xAxis', {zoomRequery: 'false'})
276+
}
277+
278+
const resetDomain = () => {
279+
setPreZoomDomain(initialDomain)
280+
event('plot.zoom_restore.xAxis', {zoomRequery: 'false'})
281+
}
282+
return [preZoomDomain, setVisXDomain, resetDomain]
283+
}
284+
268285
const setZoomDomain = (updatedDomain: number[]) => {
269286
setRequeryStatus(RemoteDataState.NotStarted)
270287
if (!preZoomResult) {
@@ -274,7 +291,7 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
274291
event('plot.zoom_in.xAxis', {zoomRequery: 'true'}, {orgId})
275292
}
276293

277-
const resetDomain = () => {
294+
const resetZoomDomain = () => {
278295
setRequeryStatus(RemoteDataState.NotStarted)
279296
if (preZoomResult) {
280297
setResult(preZoomResult)
@@ -284,11 +301,12 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
284301
event('plot.zoom_restore.xAxis', {zoomRequery: 'true'}, {orgId})
285302
}
286303

287-
return [domain, setZoomDomain, resetDomain]
304+
return [domain, setZoomDomain, resetZoomDomain]
288305
}
289306

290307
export const useZoomRequeryYDomainSettings = (args: ZoomRequeryArgs) => {
291308
const {
309+
adaptiveZoomHide,
292310
data,
293311
parsedResult,
294312
preZoomResult,
@@ -321,7 +339,7 @@ export const useZoomRequeryYDomainSettings = (args: ZoomRequeryArgs) => {
321339
* - can be changed by the time range dropdown
322340
* - uses one-way state to capture the very first set of values
323341
*/
324-
const [preZoomDomain] = useOneWayState(initialDomain)
342+
const [preZoomDomain, setPreZoomDomain] = useOneWayState(initialDomain)
325343

326344
/*
327345
* domain:
@@ -401,6 +419,20 @@ export const useZoomRequeryYDomainSettings = (args: ZoomRequeryArgs) => {
401419
}
402420
}, [preZoomDomain]) // eslint-disable-line react-hooks/exhaustive-deps
403421

422+
// Suppresses adaptive zoom feature; must come after all hooks
423+
if (!isFlagEnabled('zoomRequery') || adaptiveZoomHide) {
424+
const setVisYDomain = (domain: NumericColumnData | string) => {
425+
setPreZoomDomain(domain)
426+
event('plot.zoom_in.yAxis', {zoomRequery: 'false'})
427+
}
428+
429+
const resetDomain = () => {
430+
setPreZoomDomain(initialDomain)
431+
event('plot.zoom_restore.yAxis', {zoomRequery: 'false'})
432+
}
433+
return [preZoomDomain, setVisYDomain, resetDomain]
434+
}
435+
404436
const setZoomDomain = (updatedDomain: number[]) => {
405437
setRequeryStatus(RemoteDataState.NotStarted)
406438
if (!preZoomResult) {

0 commit comments

Comments
 (0)