Skip to content

Commit 942c4d8

Browse files
authored
feat: use dynamic window period for zoom re-query (#4876)
1 parent fc0648c commit 942c4d8

File tree

3 files changed

+146
-44
lines changed

3 files changed

+146
-44
lines changed

src/variables/selectors/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {getActiveQuery} from 'src/timeMachine/selectors'
66
import {getRangeVariable} from 'src/variables/utils/getTimeRangeVars'
77
import {getTimeRange, getTimeRangeWithTimezone} from 'src/dashboards/selectors'
88
import {
9-
getWindowPeriodVariableForZoomRequery,
9+
getVariableForZoomRequery,
1010
getWindowPeriodVariableFromVariables,
1111
} from 'src/variables/utils/getWindowVars'
1212
import {
@@ -139,13 +139,14 @@ export const getAllVariables = (
139139

140140
export const getAllVariablesForZoomRequery = (
141141
state: AppState,
142+
domain: number[],
142143
contextID?: string
143144
): Variable[] => {
144145
const vars = getUserVariableNames(state, contextID || currentContext(state))
145-
.concat([TIME_RANGE_START, TIME_RANGE_STOP, WINDOW_PERIOD])
146+
.concat([TIME_RANGE_START, TIME_RANGE_STOP])
146147
.map(variableID => {
147-
if (variableID === WINDOW_PERIOD) {
148-
return getWindowPeriodVariableForZoomRequery()
148+
if (domain?.length) {
149+
return getVariableForZoomRequery(variableID, domain)
149150
}
150151
return getVariable(state, variableID)
151152
})

src/variables/utils/getWindowVars.ts

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import {
99
} from 'src/variables/utils/buildVarsOption'
1010

1111
// Constants
12-
import {WINDOW_PERIOD} from 'src/variables/constants'
12+
import {
13+
TIME_RANGE_START,
14+
TIME_RANGE_STOP,
15+
WINDOW_PERIOD,
16+
} from 'src/variables/constants'
1317

1418
// Types
1519
import {VariableAssignment, Package} from 'src/types/ast'
@@ -18,7 +22,6 @@ import {SELECTABLE_TIME_RANGES} from 'src/shared/constants/timeRanges'
1822

1923
const DESIRED_POINTS_PER_GRAPH = 360
2024
const FALLBACK_WINDOW_PERIOD = 15000
21-
const FINEST_WINDOW_PERIOD_PRECISION = 1000
2225

2326
/*
2427
Compute the `v.windowPeriod` variable assignment for a query.
@@ -193,15 +196,34 @@ export const getWindowPeriodVariableFromVariables = (
193196
return [windowPeriodVariable]
194197
}
195198

196-
export const getWindowPeriodVariableForZoomRequery = (): Variable => ({
197-
orgID: '',
198-
id: WINDOW_PERIOD,
199-
name: WINDOW_PERIOD,
200-
arguments: {
201-
type: 'system',
202-
values: [FINEST_WINDOW_PERIOD_PRECISION],
203-
},
204-
status: RemoteDataState.Done,
205-
labels: [],
206-
selected: [],
207-
})
199+
export const getVariableForZoomRequery = (
200+
variableID: string,
201+
domain: number[]
202+
): Variable => {
203+
const variable: Variable = {
204+
orgID: '',
205+
id: variableID,
206+
name: variableID,
207+
arguments: {
208+
type: 'system',
209+
},
210+
status: RemoteDataState.Done,
211+
labels: [],
212+
selected: [],
213+
}
214+
215+
const startTime = new Date(domain?.[0] ?? '')
216+
const stopTime = new Date(domain?.[1] ?? '')
217+
switch (variableID) {
218+
case TIME_RANGE_START:
219+
variable.arguments.values = [startTime.toISOString()]
220+
return variable
221+
222+
case TIME_RANGE_STOP:
223+
variable.arguments.values = [stopTime.toISOString()]
224+
return variable
225+
226+
default:
227+
return variable
228+
}
229+
}

src/visualization/utils/useVisDomainSettings.ts

Lines changed: 105 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// Libraries
2-
import {useMemo, useState} from 'react'
2+
import {useEffect, useMemo, useState} from 'react'
33
import {useSelector} from 'react-redux'
44
import {NumericColumnData, fromFlux} from '@influxdata/giraffe'
5+
import {isEqual} from 'lodash'
56

67
// API
78
import {runQuery, RunQueryResult} from 'src/shared/apis/query'
@@ -11,11 +12,19 @@ import {useOneWayState} from 'src/shared/utils/useOneWayState'
1112
import {extent} from 'src/shared/utils/vis'
1213
import {getStartTime, getEndTime} from 'src/timeMachine/selectors/index'
1314
import {getOrg} from 'src/organizations/selectors'
14-
import {getAllVariablesForZoomRequery} from 'src/variables/selectors'
15+
import {
16+
// getAllVariables,
17+
getAllVariablesForZoomRequery,
18+
} from 'src/variables/selectors'
1519
import {buildUsedVarsOption} from 'src/variables/utils/buildVarsOption'
1620

21+
import {
22+
getWindowPeriodFromVariables,
23+
getWindowVarsFromVariables,
24+
} from 'src/variables/utils/getWindowVars'
25+
1726
// Types
18-
import {InternalFromFluxResult, TimeRange} from 'src/types'
27+
import {AppState, InternalFromFluxResult, TimeRange} from 'src/types'
1928
/*
2029
This hook helps map the domain setting stored for line graph to the
2130
appropriate settings on a @influxdata/giraffe `Config` object.
@@ -121,6 +130,9 @@ interface ZoomRequeryArgs {
121130
timeRange?: TimeRange
122131
}
123132

133+
const isNotEqual = (firstValue: any, secondValue: any): boolean =>
134+
isEqual(firstValue, secondValue) === false
135+
124136
export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
125137
const {
126138
parsedResult,
@@ -133,10 +145,6 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
133145
timeRange = null,
134146
} = args
135147

136-
const orgId = useSelector(getOrg)?.id
137-
const variables = useSelector(getAllVariablesForZoomRequery)
138-
const extern = buildUsedVarsOption(query, variables)
139-
140148
const initialDomain = useMemo(() => {
141149
if (storedDomain) {
142150
return storedDomain
@@ -148,20 +156,57 @@ export const useZoomRequeryXDomainSettings = (args: ZoomRequeryArgs) => {
148156
const [domain, setDomain] = useState(initialDomain)
149157
const [preZoomDomain, setPreZoomDomain] = useState<Array<number>>(null)
150158

159+
const getAllVariablesWithTimeDomain = (state: AppState) =>
160+
getAllVariablesForZoomRequery(state, timeRange ? domain : [])
161+
const orgId = useSelector(getOrg)?.id
162+
const variables = useSelector(getAllVariablesWithTimeDomain)
163+
164+
const [windowPeriod, setWindowPeriod] = useState<number>(
165+
getWindowPeriodFromVariables(query, variables)
166+
)
167+
168+
/*
169+
* When the user zooms in, re-run the query
170+
* When the user un-zooms, do not re-run but revert back to old data
171+
* Hence re-run the query only when both conditions are met:
172+
* - the window period changes from the domain changing (zooming in)
173+
* - the domain does not equal the original pre-zoom domain (unzooming)
174+
*/
175+
useEffect(() => {
176+
const updatedWindowPeriod = getWindowPeriodFromVariables(query, variables)
177+
if (isNotEqual(windowPeriod, updatedWindowPeriod)) {
178+
setWindowPeriod(getWindowPeriodFromVariables(query, variables))
179+
180+
if (isNotEqual(preZoomDomain, domain)) {
181+
const zoomQueryWindowVariable = getWindowVarsFromVariables(
182+
query,
183+
variables
184+
)
185+
const extern = buildUsedVarsOption(
186+
query,
187+
variables,
188+
zoomQueryWindowVariable
189+
)
190+
runQuery(orgId, query, extern).promise.then(
191+
(result: RunQueryResult) => {
192+
if (result.type === 'SUCCESS') {
193+
const parsed = fromFlux(result.csv)
194+
setResult(parsed)
195+
}
196+
}
197+
)
198+
}
199+
}
200+
}, [domain]) // eslint-disable-line react-hooks/exhaustive-deps
201+
151202
const setZoomDomain = (updatedDomain: number[]) => {
152203
if (!preZoomResult) {
153204
setPreZoomDomain(initialDomain)
154205
setPreZoomResult(parsedResult)
155206
}
156-
157-
runQuery(orgId, query, extern).promise.then((result: RunQueryResult) => {
158-
if (result.type === 'SUCCESS') {
159-
const parsed = fromFlux(result.csv)
160-
setResult(parsed)
161-
setDomain(updatedDomain)
162-
}
163-
})
207+
setDomain(updatedDomain)
164208
}
209+
165210
const resetDomain = () => {
166211
if (preZoomResult) {
167212
setResult(preZoomResult)
@@ -184,9 +229,6 @@ export const useZoomRequeryYDomainSettings = (args: ZoomRequeryArgs) => {
184229
data,
185230
timeRange = null,
186231
} = args
187-
const orgId = useSelector(getOrg)?.id
188-
const variables = useSelector(getAllVariablesForZoomRequery)
189-
const extern = buildUsedVarsOption(query, variables)
190232

191233
const initialDomain = useMemo(() => {
192234
if (
@@ -204,20 +246,57 @@ export const useZoomRequeryYDomainSettings = (args: ZoomRequeryArgs) => {
204246
const [domain, setDomain] = useState(initialDomain)
205247
const [preZoomDomain, setPreZoomDomain] = useState<Array<number>>(null)
206248

249+
const getAllVariablesWithTimeDomain = (state: AppState) =>
250+
getAllVariablesForZoomRequery(state, timeRange ? domain : [])
251+
const orgId = useSelector(getOrg)?.id
252+
const variables = useSelector(getAllVariablesWithTimeDomain)
253+
254+
const [windowPeriod, setWindowPeriod] = useState<number>(
255+
getWindowPeriodFromVariables(query, variables)
256+
)
257+
258+
/*
259+
* When the user zooms in, re-run the query
260+
* When the user un-zooms, do not re-run but revert back to old data
261+
* Hence re-run the query only when both conditions are met:
262+
* - the window period changes from the domain changing (zooming in)
263+
* - the domain does not equal the original pre-zoom domain (unzooming)
264+
*/
265+
useEffect(() => {
266+
const updatedWindowPeriod = getWindowPeriodFromVariables(query, variables)
267+
if (isNotEqual(windowPeriod, updatedWindowPeriod)) {
268+
setWindowPeriod(getWindowPeriodFromVariables(query, variables))
269+
270+
if (isNotEqual(preZoomDomain, domain)) {
271+
const zoomQueryWindowVariable = getWindowVarsFromVariables(
272+
query,
273+
variables
274+
)
275+
const extern = buildUsedVarsOption(
276+
query,
277+
variables,
278+
zoomQueryWindowVariable
279+
)
280+
runQuery(orgId, query, extern).promise.then(
281+
(result: RunQueryResult) => {
282+
if (result.type === 'SUCCESS') {
283+
const parsed = fromFlux(result.csv)
284+
setResult(parsed)
285+
}
286+
}
287+
)
288+
}
289+
}
290+
}, [domain]) // eslint-disable-line react-hooks/exhaustive-deps
291+
207292
const setZoomDomain = (updatedDomain: number[]) => {
208293
if (!preZoomResult) {
209294
setPreZoomDomain(initialDomain)
210295
setPreZoomResult(parsedResult)
211296
}
212-
213-
runQuery(orgId, query, extern).promise.then((result: RunQueryResult) => {
214-
if (result.type === 'SUCCESS') {
215-
const parsed = fromFlux(result.csv)
216-
setResult(parsed)
217-
setDomain(updatedDomain)
218-
}
219-
})
297+
setDomain(updatedDomain)
220298
}
299+
221300
const resetDomain = () => {
222301
if (preZoomResult) {
223302
setResult(preZoomResult)

0 commit comments

Comments
 (0)