Merge pull request #3730 from influxdata/fix/script-yield-before-range-filter
Fix unable to toggle yieldspull/10616/head
commit
10af172b32
|
@ -3,7 +3,10 @@ import _ from 'lodash'
|
||||||
import AJAX from 'src/utils/ajax'
|
import AJAX from 'src/utils/ajax'
|
||||||
import {Service, FluxTable} from 'src/types'
|
import {Service, FluxTable} from 'src/types'
|
||||||
import {updateService} from 'src/shared/apis'
|
import {updateService} from 'src/shared/apis'
|
||||||
import {parseResponse} from 'src/shared/parsing/flux/response'
|
import {
|
||||||
|
parseResponse,
|
||||||
|
parseResponseError,
|
||||||
|
} from 'src/shared/parsing/flux/response'
|
||||||
import {MAX_RESPONSE_BYTES} from 'src/flux/constants'
|
import {MAX_RESPONSE_BYTES} from 'src/flux/constants'
|
||||||
|
|
||||||
export const getSuggestions = async (url: string) => {
|
export const getSuggestions = async (url: string) => {
|
||||||
|
@ -56,6 +59,9 @@ export const getTimeSeries = async (
|
||||||
service.links.proxy
|
service.links.proxy
|
||||||
}?path=/v1/query${mark}orgName=defaulorgname${and}q=${garbage}`
|
}?path=/v1/query${mark}orgName=defaulorgname${and}q=${garbage}`
|
||||||
|
|
||||||
|
let responseBody: string
|
||||||
|
let responseByteLength: number
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// We are using the `fetch` API here since the `AJAX` utility lacks support
|
// We are using the `fetch` API here since the `AJAX` utility lacks support
|
||||||
// for limiting response size. The `AJAX` utility depends on
|
// for limiting response size. The `AJAX` utility depends on
|
||||||
|
@ -66,16 +72,28 @@ export const getTimeSeries = async (
|
||||||
const resp = await fetch(url, {method: 'POST'})
|
const resp = await fetch(url, {method: 'POST'})
|
||||||
const {body, byteLength} = await decodeFluxRespWithLimit(resp)
|
const {body, byteLength} = await decodeFluxRespWithLimit(resp)
|
||||||
|
|
||||||
return {
|
responseBody = body
|
||||||
tables: parseResponse(body),
|
responseByteLength = byteLength
|
||||||
didTruncate: byteLength >= MAX_RESPONSE_BYTES,
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Problem fetching data', error)
|
console.error('Problem fetching data', error)
|
||||||
|
|
||||||
throw _.get(error, 'headers.x-influx-error', false) ||
|
throw _.get(error, 'headers.x-influx-error', false) ||
|
||||||
_.get(error, 'data.message', 'unknown error 🤷')
|
_.get(error, 'data.message', 'unknown error 🤷')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
tables: parseResponse(responseBody),
|
||||||
|
didTruncate: responseByteLength >= MAX_RESPONSE_BYTES,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Could not parse response body', error)
|
||||||
|
|
||||||
|
return {
|
||||||
|
tables: parseResponseError(responseBody),
|
||||||
|
didTruncate: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateScript = async (service: Service, script: string) => {
|
export const updateScript = async (service: Service, script: string) => {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React, {PureComponent, Fragment} from 'react'
|
import React, {PureComponent, Fragment} from 'react'
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
import {FluxContext} from 'src/flux/containers/FluxPage'
|
import {FluxContext} from 'src/flux/containers/FluxPage'
|
||||||
import FuncSelector from 'src/flux/components/FuncSelector'
|
import FuncSelector from 'src/flux/components/FuncSelector'
|
||||||
import FuncNode from 'src/flux/components/FuncNode'
|
import FuncNode from 'src/flux/components/FuncNode'
|
||||||
import YieldFuncNode from 'src/flux/components/YieldFuncNode'
|
import YieldFuncNode from 'src/flux/components/YieldFuncNode'
|
||||||
|
import {getDeep} from 'src/utils/wrappers'
|
||||||
|
|
||||||
import {Func} from 'src/types/flux'
|
import {Func, Context} from 'src/types/flux'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
funcNames: any[]
|
funcNames: any[]
|
||||||
|
@ -22,7 +22,6 @@ interface State {
|
||||||
nonYieldableIndexesToggled: {
|
nonYieldableIndexesToggled: {
|
||||||
[x: number]: boolean
|
[x: number]: boolean
|
||||||
}
|
}
|
||||||
isImplicitYieldToggled: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// an Expression is a group of one or more functions
|
// an Expression is a group of one or more functions
|
||||||
|
@ -32,7 +31,6 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
nonYieldableIndexesToggled: {},
|
nonYieldableIndexesToggled: {},
|
||||||
isImplicitYieldToggled: this.isImplicitYieldToggled,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,13 +57,17 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
service,
|
service,
|
||||||
data,
|
data,
|
||||||
scriptUpToYield,
|
scriptUpToYield,
|
||||||
}) => {
|
}: Context) => {
|
||||||
let isAfterRange = false
|
let isAfterRange = false
|
||||||
let isAfterFilter = false
|
let isAfterFilter = false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{funcs.map((func, i) => {
|
{funcs.map((func, i) => {
|
||||||
|
if (func.name === 'yield') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (func.name === 'range') {
|
if (func.name === 'range') {
|
||||||
isAfterRange = true
|
isAfterRange = true
|
||||||
}
|
}
|
||||||
|
@ -74,22 +76,7 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
isAfterFilter = true
|
isAfterFilter = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func.name === 'yield') {
|
const isYieldable = isAfterFilter && isAfterRange
|
||||||
const script = scriptUpToYield(bodyID, declarationID, i, true)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<YieldFuncNode
|
|
||||||
index={i}
|
|
||||||
key={i}
|
|
||||||
func={func}
|
|
||||||
data={data}
|
|
||||||
script={script}
|
|
||||||
bodyID={bodyID}
|
|
||||||
service={service}
|
|
||||||
declarationID={declarationID}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const funcNode = (
|
const funcNode = (
|
||||||
<FuncNode
|
<FuncNode
|
||||||
|
@ -102,8 +89,9 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
onChangeArg={onChangeArg}
|
onChangeArg={onChangeArg}
|
||||||
onDelete={onDeleteFuncNode}
|
onDelete={onDeleteFuncNode}
|
||||||
onToggleYield={onToggleYield}
|
onToggleYield={onToggleYield}
|
||||||
isYieldable={isAfterFilter && isAfterRange}
|
isYieldable={isYieldable}
|
||||||
isYielding={this.isBeforeFuncYield(i)}
|
isYielding={this.isBeforeYielding(i)}
|
||||||
|
isYieldedInScript={this.isYieldNodeIndex(i + 1)}
|
||||||
declarationID={declarationID}
|
declarationID={declarationID}
|
||||||
onGenerateScript={onGenerateScript}
|
onGenerateScript={onGenerateScript}
|
||||||
declarationsFromBody={declarationsFromBody}
|
declarationsFromBody={declarationsFromBody}
|
||||||
|
@ -112,12 +100,15 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (nonYieldableIndexesToggled[i]) {
|
if (
|
||||||
const script = scriptUpToYield(
|
nonYieldableIndexesToggled[i] ||
|
||||||
|
this.isYieldNodeIndex(i + 1)
|
||||||
|
) {
|
||||||
|
const script: string = scriptUpToYield(
|
||||||
bodyID,
|
bodyID,
|
||||||
declarationID,
|
declarationID,
|
||||||
i,
|
i,
|
||||||
false
|
isYieldable
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -134,43 +125,9 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
} else if (this.isEndOfScript(i)) {
|
|
||||||
const script = scriptUpToYield(bodyID, declarationID, i, true)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment key={`${i}-notInScript`}>
|
|
||||||
<FuncNode
|
|
||||||
key={i}
|
|
||||||
index={i}
|
|
||||||
func={func}
|
|
||||||
funcs={funcs}
|
|
||||||
bodyID={bodyID}
|
|
||||||
service={service}
|
|
||||||
onChangeArg={onChangeArg}
|
|
||||||
onDelete={onDeleteFuncNode}
|
|
||||||
onToggleYield={this.handleHideImplicitYield}
|
|
||||||
isYieldable={isAfterFilter && isAfterRange}
|
|
||||||
isYielding={this.isBeforeFuncYield(i)}
|
|
||||||
declarationID={declarationID}
|
|
||||||
onGenerateScript={onGenerateScript}
|
|
||||||
declarationsFromBody={declarationsFromBody}
|
|
||||||
onToggleYieldWithLast={this.handleToggleYieldWithLast}
|
|
||||||
onDeleteBody={onDeleteBody}
|
|
||||||
/>
|
|
||||||
<YieldFuncNode
|
|
||||||
index={i}
|
|
||||||
func={func}
|
|
||||||
data={data}
|
|
||||||
script={script}
|
|
||||||
bodyID={bodyID}
|
|
||||||
service={service}
|
|
||||||
declarationID={declarationID}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return funcNode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return funcNode
|
||||||
})}
|
})}
|
||||||
<FuncSelector
|
<FuncSelector
|
||||||
bodyID={bodyID}
|
bodyID={bodyID}
|
||||||
|
@ -185,45 +142,26 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private isBeforeFuncYield(funcIndex: number): boolean {
|
private isBeforeYielding(funcIndex: number): boolean {
|
||||||
const {funcs, isLastBody} = this.props
|
const {nonYieldableIndexesToggled} = this.state
|
||||||
const {isImplicitYieldToggled} = this.state
|
const beforeToggledLastYield = !!nonYieldableIndexesToggled[funcIndex]
|
||||||
|
|
||||||
if (
|
if (beforeToggledLastYield) {
|
||||||
funcIndex === funcs.length - 1 &&
|
|
||||||
isLastBody &&
|
|
||||||
isImplicitYieldToggled
|
|
||||||
) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funcIndex === funcs.length - 1) {
|
return this.isYieldNodeIndex(funcIndex + 1)
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextFunc = funcs[funcIndex + 1]
|
|
||||||
|
|
||||||
if (nextFunc.name === 'yield') {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private get isImplicitYieldToggled(): boolean {
|
private isYieldNodeIndex(funcIndex: number): boolean {
|
||||||
const {isLastBody} = this.props
|
|
||||||
|
|
||||||
return isLastBody && this.isLastFuncYield
|
|
||||||
}
|
|
||||||
|
|
||||||
private get isLastFuncYield(): boolean {
|
|
||||||
const {funcs} = this.props
|
const {funcs} = this.props
|
||||||
|
const funcName = getDeep<string>(funcs, `${funcIndex}.name`, '')
|
||||||
|
|
||||||
return _.get(funcs, `${funcs.length - 1}.name`) !== 'yield'
|
return funcName === 'yield'
|
||||||
}
|
}
|
||||||
|
|
||||||
// if funcNode is not yieldable, add last before yield()
|
// if funcNode is not yieldable, add last before yield()
|
||||||
private handleToggleYieldWithLast = (funcNodeIndex: number) => {
|
private handleToggleYieldWithLast = (funcNodeIndex: number): void => {
|
||||||
this.setState(({nonYieldableIndexesToggled}) => {
|
this.setState(({nonYieldableIndexesToggled}) => {
|
||||||
const isFuncYieldToggled = !!nonYieldableIndexesToggled[funcNodeIndex]
|
const isFuncYieldToggled = !!nonYieldableIndexesToggled[funcNodeIndex]
|
||||||
|
|
||||||
|
@ -235,20 +173,6 @@ class ExpressionNode extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleHideImplicitYield = () => {
|
|
||||||
this.setState(() => ({
|
|
||||||
isImplicitYieldToggled: false,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
private isEndOfScript(index: number): boolean {
|
|
||||||
const {isLastBody, funcs} = this.props
|
|
||||||
const {isImplicitYieldToggled} = this.state
|
|
||||||
const isLastScriptFunc = isLastBody && index === funcs.length - 1
|
|
||||||
|
|
||||||
return isLastScriptFunc && isImplicitYieldToggled
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ExpressionNode
|
export default ExpressionNode
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
import FromDatabaseDropdown from 'src/flux/components/FromDatabaseDropdown'
|
import FromDatabaseDropdown from 'src/flux/components/FromDatabaseDropdown'
|
||||||
|
|
||||||
import {funcNames, argTypes} from 'src/flux/constants'
|
import {funcNames, argTypes} from 'src/flux/constants'
|
||||||
import {OnChangeArg, Arg} from 'src/types/flux'
|
import {OnChangeArg, Arg, OnGenerateScript} from 'src/types/flux'
|
||||||
import {Service} from 'src/types'
|
import {Service} from 'src/types'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -22,7 +22,7 @@ interface Props {
|
||||||
bodyID: string
|
bodyID: string
|
||||||
declarationID: string
|
declarationID: string
|
||||||
onChangeArg: OnChangeArg
|
onChangeArg: OnChangeArg
|
||||||
onGenerateScript: () => void
|
onGenerateScript: OnGenerateScript
|
||||||
}
|
}
|
||||||
|
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, {PureComponent, ChangeEvent, KeyboardEvent} from 'react'
|
import React, {PureComponent, ChangeEvent, KeyboardEvent} from 'react'
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
import {OnChangeArg} from 'src/types/flux'
|
import {OnChangeArg, OnGenerateScript} from 'src/types/flux'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
funcID: string
|
funcID: string
|
||||||
|
@ -10,7 +10,7 @@ interface Props {
|
||||||
bodyID: string
|
bodyID: string
|
||||||
declarationID: string
|
declarationID: string
|
||||||
onChangeArg: OnChangeArg
|
onChangeArg: OnChangeArg
|
||||||
onGenerateScript: () => void
|
onGenerateScript: OnGenerateScript
|
||||||
autoFocus?: boolean
|
autoFocus?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, {PureComponent, ReactElement, MouseEvent} from 'react'
|
||||||
import FuncArg from 'src/flux/components/FuncArg'
|
import FuncArg from 'src/flux/components/FuncArg'
|
||||||
import {OnChangeArg} from 'src/types/flux'
|
import {OnChangeArg} from 'src/types/flux'
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
import {Func} from 'src/types/flux'
|
import {Func, OnGenerateScript} from 'src/types/flux'
|
||||||
import {funcNames} from 'src/flux/constants'
|
import {funcNames} from 'src/flux/constants'
|
||||||
import JoinArgs from 'src/flux/components/JoinArgs'
|
import JoinArgs from 'src/flux/components/JoinArgs'
|
||||||
import FilterArgs from 'src/flux/components/FilterArgs'
|
import FilterArgs from 'src/flux/components/FilterArgs'
|
||||||
|
@ -15,7 +15,7 @@ interface Props {
|
||||||
bodyID: string
|
bodyID: string
|
||||||
onChangeArg: OnChangeArg
|
onChangeArg: OnChangeArg
|
||||||
declarationID: string
|
declarationID: string
|
||||||
onGenerateScript: () => void
|
onGenerateScript: OnGenerateScript
|
||||||
declarationsFromBody: string[]
|
declarationsFromBody: string[]
|
||||||
onStopPropagation: (e: MouseEvent<HTMLElement>) => void
|
onStopPropagation: (e: MouseEvent<HTMLElement>) => void
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import BodyDelete from 'src/flux/components/BodyDelete'
|
||||||
import FuncArgs from 'src/flux/components/FuncArgs'
|
import FuncArgs from 'src/flux/components/FuncArgs'
|
||||||
import FuncArgsPreview from 'src/flux/components/FuncArgsPreview'
|
import FuncArgsPreview from 'src/flux/components/FuncArgsPreview'
|
||||||
import {
|
import {
|
||||||
|
OnGenerateScript,
|
||||||
OnDeleteFuncNode,
|
OnDeleteFuncNode,
|
||||||
OnChangeArg,
|
OnChangeArg,
|
||||||
OnToggleYield,
|
OnToggleYield,
|
||||||
|
@ -24,12 +25,13 @@ interface Props {
|
||||||
onDelete: OnDeleteFuncNode
|
onDelete: OnDeleteFuncNode
|
||||||
onToggleYield: OnToggleYield
|
onToggleYield: OnToggleYield
|
||||||
onChangeArg: OnChangeArg
|
onChangeArg: OnChangeArg
|
||||||
onGenerateScript: () => void
|
onGenerateScript: OnGenerateScript
|
||||||
onToggleYieldWithLast: (funcNodeIndex: number) => void
|
onToggleYieldWithLast: (funcNodeIndex: number) => void
|
||||||
declarationsFromBody: string[]
|
declarationsFromBody: string[]
|
||||||
isYielding: boolean
|
isYielding: boolean
|
||||||
isYieldable: boolean
|
isYieldable: boolean
|
||||||
onDeleteBody: (bodyID: string) => void
|
onDeleteBody: (bodyID: string) => void
|
||||||
|
isYieldedInScript: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -182,11 +184,12 @@ export default class FuncNode extends PureComponent<Props, State> {
|
||||||
index,
|
index,
|
||||||
bodyID,
|
bodyID,
|
||||||
declarationID,
|
declarationID,
|
||||||
isYieldable,
|
|
||||||
onToggleYieldWithLast,
|
onToggleYieldWithLast,
|
||||||
|
isYieldable,
|
||||||
|
isYieldedInScript,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (isYieldable) {
|
if (isYieldedInScript || isYieldable) {
|
||||||
onToggleYield(bodyID, declarationID, index)
|
onToggleYield(bodyID, declarationID, index)
|
||||||
} else {
|
} else {
|
||||||
onToggleYieldWithLast(index)
|
onToggleYieldWithLast(index)
|
||||||
|
|
|
@ -344,7 +344,7 @@ export class FluxPage extends PureComponent<Props, State> {
|
||||||
declarationID: string,
|
declarationID: string,
|
||||||
funcNodeIndex: number,
|
funcNodeIndex: number,
|
||||||
isYieldable: boolean
|
isYieldable: boolean
|
||||||
) => {
|
): string => {
|
||||||
const {body: bodies} = this.state
|
const {body: bodies} = this.state
|
||||||
|
|
||||||
const bodyIndex = bodies.findIndex(b => b.id === bodyID)
|
const bodyIndex = bodies.findIndex(b => b.id === bodyID)
|
||||||
|
|
|
@ -4,6 +4,19 @@ import uuid from 'uuid'
|
||||||
|
|
||||||
import {FluxTable} from 'src/types'
|
import {FluxTable} from 'src/types'
|
||||||
|
|
||||||
|
export const parseResponseError = (response: string): FluxTable[] => {
|
||||||
|
const data = Papa.parse(response.trim()).data as string[][]
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: uuid.v4(),
|
||||||
|
name: 'Error',
|
||||||
|
partitionKey: {},
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
export const parseResponse = (response: string): FluxTable[] => {
|
export const parseResponse = (response: string): FluxTable[] => {
|
||||||
const trimmedReponse = response.trim()
|
const trimmedReponse = response.trim()
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export type OnToggleYield = (
|
||||||
declarationID: string,
|
declarationID: string,
|
||||||
funcNodeIndex: number
|
funcNodeIndex: number
|
||||||
) => void
|
) => void
|
||||||
export type OnGenerateScript = (script: string) => void
|
export type OnGenerateScript = () => void
|
||||||
export type OnChangeScript = (script: string) => void
|
export type OnChangeScript = (script: string) => void
|
||||||
export type OnSubmitScript = () => void
|
export type OnSubmitScript = () => void
|
||||||
export type ScriptUpToYield = (
|
export type ScriptUpToYield = (
|
||||||
|
|
Loading…
Reference in New Issue