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 {Service, FluxTable} from 'src/types'
|
||||
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'
|
||||
|
||||
export const getSuggestions = async (url: string) => {
|
||||
|
@ -56,6 +59,9 @@ export const getTimeSeries = async (
|
|||
service.links.proxy
|
||||
}?path=/v1/query${mark}orgName=defaulorgname${and}q=${garbage}`
|
||||
|
||||
let responseBody: string
|
||||
let responseByteLength: number
|
||||
|
||||
try {
|
||||
// We are using the `fetch` API here since the `AJAX` utility lacks support
|
||||
// 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 {body, byteLength} = await decodeFluxRespWithLimit(resp)
|
||||
|
||||
return {
|
||||
tables: parseResponse(body),
|
||||
didTruncate: byteLength >= MAX_RESPONSE_BYTES,
|
||||
}
|
||||
responseBody = body
|
||||
responseByteLength = byteLength
|
||||
} catch (error) {
|
||||
console.error('Problem fetching data', error)
|
||||
|
||||
throw _.get(error, 'headers.x-influx-error', false) ||
|
||||
_.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) => {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, {PureComponent, Fragment} from 'react'
|
||||
import _ from 'lodash'
|
||||
|
||||
import {FluxContext} from 'src/flux/containers/FluxPage'
|
||||
import FuncSelector from 'src/flux/components/FuncSelector'
|
||||
import FuncNode from 'src/flux/components/FuncNode'
|
||||
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 {
|
||||
funcNames: any[]
|
||||
|
@ -22,7 +22,6 @@ interface State {
|
|||
nonYieldableIndexesToggled: {
|
||||
[x: number]: boolean
|
||||
}
|
||||
isImplicitYieldToggled: boolean
|
||||
}
|
||||
|
||||
// an Expression is a group of one or more functions
|
||||
|
@ -32,7 +31,6 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
|
||||
this.state = {
|
||||
nonYieldableIndexesToggled: {},
|
||||
isImplicitYieldToggled: this.isImplicitYieldToggled,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,13 +57,17 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
service,
|
||||
data,
|
||||
scriptUpToYield,
|
||||
}) => {
|
||||
}: Context) => {
|
||||
let isAfterRange = false
|
||||
let isAfterFilter = false
|
||||
|
||||
return (
|
||||
<>
|
||||
{funcs.map((func, i) => {
|
||||
if (func.name === 'yield') {
|
||||
return null
|
||||
}
|
||||
|
||||
if (func.name === 'range') {
|
||||
isAfterRange = true
|
||||
}
|
||||
|
@ -74,22 +76,7 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
isAfterFilter = true
|
||||
}
|
||||
|
||||
if (func.name === 'yield') {
|
||||
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 isYieldable = isAfterFilter && isAfterRange
|
||||
|
||||
const funcNode = (
|
||||
<FuncNode
|
||||
|
@ -102,8 +89,9 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
onChangeArg={onChangeArg}
|
||||
onDelete={onDeleteFuncNode}
|
||||
onToggleYield={onToggleYield}
|
||||
isYieldable={isAfterFilter && isAfterRange}
|
||||
isYielding={this.isBeforeFuncYield(i)}
|
||||
isYieldable={isYieldable}
|
||||
isYielding={this.isBeforeYielding(i)}
|
||||
isYieldedInScript={this.isYieldNodeIndex(i + 1)}
|
||||
declarationID={declarationID}
|
||||
onGenerateScript={onGenerateScript}
|
||||
declarationsFromBody={declarationsFromBody}
|
||||
|
@ -112,12 +100,15 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
/>
|
||||
)
|
||||
|
||||
if (nonYieldableIndexesToggled[i]) {
|
||||
const script = scriptUpToYield(
|
||||
if (
|
||||
nonYieldableIndexesToggled[i] ||
|
||||
this.isYieldNodeIndex(i + 1)
|
||||
) {
|
||||
const script: string = scriptUpToYield(
|
||||
bodyID,
|
||||
declarationID,
|
||||
i,
|
||||
false
|
||||
isYieldable
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -134,43 +125,9 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
/>
|
||||
</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
|
||||
bodyID={bodyID}
|
||||
|
@ -185,45 +142,26 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private isBeforeFuncYield(funcIndex: number): boolean {
|
||||
const {funcs, isLastBody} = this.props
|
||||
const {isImplicitYieldToggled} = this.state
|
||||
private isBeforeYielding(funcIndex: number): boolean {
|
||||
const {nonYieldableIndexesToggled} = this.state
|
||||
const beforeToggledLastYield = !!nonYieldableIndexesToggled[funcIndex]
|
||||
|
||||
if (
|
||||
funcIndex === funcs.length - 1 &&
|
||||
isLastBody &&
|
||||
isImplicitYieldToggled
|
||||
) {
|
||||
if (beforeToggledLastYield) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (funcIndex === funcs.length - 1) {
|
||||
return false
|
||||
}
|
||||
|
||||
const nextFunc = funcs[funcIndex + 1]
|
||||
|
||||
if (nextFunc.name === 'yield') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return this.isYieldNodeIndex(funcIndex + 1)
|
||||
}
|
||||
|
||||
private get isImplicitYieldToggled(): boolean {
|
||||
const {isLastBody} = this.props
|
||||
|
||||
return isLastBody && this.isLastFuncYield
|
||||
}
|
||||
|
||||
private get isLastFuncYield(): boolean {
|
||||
private isYieldNodeIndex(funcIndex: number): boolean {
|
||||
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()
|
||||
private handleToggleYieldWithLast = (funcNodeIndex: number) => {
|
||||
private handleToggleYieldWithLast = (funcNodeIndex: number): void => {
|
||||
this.setState(({nonYieldableIndexesToggled}) => {
|
||||
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
|
||||
|
|
|
@ -8,7 +8,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
|
|||
import FromDatabaseDropdown from 'src/flux/components/FromDatabaseDropdown'
|
||||
|
||||
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'
|
||||
|
||||
interface Props {
|
||||
|
@ -22,7 +22,7 @@ interface Props {
|
|||
bodyID: string
|
||||
declarationID: string
|
||||
onChangeArg: OnChangeArg
|
||||
onGenerateScript: () => void
|
||||
onGenerateScript: OnGenerateScript
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {PureComponent, ChangeEvent, KeyboardEvent} from 'react'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {OnChangeArg} from 'src/types/flux'
|
||||
import {OnChangeArg, OnGenerateScript} from 'src/types/flux'
|
||||
|
||||
interface Props {
|
||||
funcID: string
|
||||
|
@ -10,7 +10,7 @@ interface Props {
|
|||
bodyID: string
|
||||
declarationID: string
|
||||
onChangeArg: OnChangeArg
|
||||
onGenerateScript: () => void
|
||||
onGenerateScript: OnGenerateScript
|
||||
autoFocus?: boolean
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, {PureComponent, ReactElement, MouseEvent} from 'react'
|
|||
import FuncArg from 'src/flux/components/FuncArg'
|
||||
import {OnChangeArg} from 'src/types/flux'
|
||||
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 JoinArgs from 'src/flux/components/JoinArgs'
|
||||
import FilterArgs from 'src/flux/components/FilterArgs'
|
||||
|
@ -15,7 +15,7 @@ interface Props {
|
|||
bodyID: string
|
||||
onChangeArg: OnChangeArg
|
||||
declarationID: string
|
||||
onGenerateScript: () => void
|
||||
onGenerateScript: OnGenerateScript
|
||||
declarationsFromBody: string[]
|
||||
onStopPropagation: (e: MouseEvent<HTMLElement>) => void
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import BodyDelete from 'src/flux/components/BodyDelete'
|
|||
import FuncArgs from 'src/flux/components/FuncArgs'
|
||||
import FuncArgsPreview from 'src/flux/components/FuncArgsPreview'
|
||||
import {
|
||||
OnGenerateScript,
|
||||
OnDeleteFuncNode,
|
||||
OnChangeArg,
|
||||
OnToggleYield,
|
||||
|
@ -24,12 +25,13 @@ interface Props {
|
|||
onDelete: OnDeleteFuncNode
|
||||
onToggleYield: OnToggleYield
|
||||
onChangeArg: OnChangeArg
|
||||
onGenerateScript: () => void
|
||||
onGenerateScript: OnGenerateScript
|
||||
onToggleYieldWithLast: (funcNodeIndex: number) => void
|
||||
declarationsFromBody: string[]
|
||||
isYielding: boolean
|
||||
isYieldable: boolean
|
||||
onDeleteBody: (bodyID: string) => void
|
||||
isYieldedInScript: boolean
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -182,11 +184,12 @@ export default class FuncNode extends PureComponent<Props, State> {
|
|||
index,
|
||||
bodyID,
|
||||
declarationID,
|
||||
isYieldable,
|
||||
onToggleYieldWithLast,
|
||||
isYieldable,
|
||||
isYieldedInScript,
|
||||
} = this.props
|
||||
|
||||
if (isYieldable) {
|
||||
if (isYieldedInScript || isYieldable) {
|
||||
onToggleYield(bodyID, declarationID, index)
|
||||
} else {
|
||||
onToggleYieldWithLast(index)
|
||||
|
|
|
@ -344,7 +344,7 @@ export class FluxPage extends PureComponent<Props, State> {
|
|||
declarationID: string,
|
||||
funcNodeIndex: number,
|
||||
isYieldable: boolean
|
||||
) => {
|
||||
): string => {
|
||||
const {body: bodies} = this.state
|
||||
|
||||
const bodyIndex = bodies.findIndex(b => b.id === bodyID)
|
||||
|
|
|
@ -4,6 +4,19 @@ import uuid from 'uuid'
|
|||
|
||||
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[] => {
|
||||
const trimmedReponse = response.trim()
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ export type OnToggleYield = (
|
|||
declarationID: string,
|
||||
funcNodeIndex: number
|
||||
) => void
|
||||
export type OnGenerateScript = (script: string) => void
|
||||
export type OnGenerateScript = () => void
|
||||
export type OnChangeScript = (script: string) => void
|
||||
export type OnSubmitScript = () => void
|
||||
export type ScriptUpToYield = (
|
||||
|
|
Loading…
Reference in New Issue