WIP Update delete for FuncNodes

pull/10616/head
Andrew Watkins 2018-04-18 16:00:55 -07:00
parent d784af0018
commit cff1fbaa97
10 changed files with 124 additions and 66 deletions

View File

@ -3,12 +3,13 @@ import React, {PureComponent} from 'react'
import {getDatabases} from 'src/ifql/apis'
import Dropdown from 'src/shared/components/Dropdown'
import {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import {OnChangeArg} from 'src/types/ifql'
interface Props {
funcID: string
argKey: string
value: string
expressionID: string
onChangeArg: OnChangeArg
}
@ -55,8 +56,14 @@ class From extends PureComponent<Props, State> {
}
private handleChooseDatabase = (item: DropdownItem): void => {
const {argKey, funcID, onChangeArg} = this.props
onChangeArg({funcID, key: argKey, value: item.text, generate: true})
const {argKey, funcID, onChangeArg, expressionID} = this.props
onChangeArg({
funcID,
key: argKey,
value: item.text,
expressionID,
generate: true,
})
}
private get items(): DropdownItem[] {

View File

@ -1,11 +1,12 @@
import React, {PureComponent} from 'react'
import FuncArgInput, {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import FuncArgInput from 'src/ifql/components/FuncArgInput'
import FuncArgBool from 'src/ifql/components/FuncArgBool'
import {ErrorHandling} from 'src/shared/decorators/errors'
import From from 'src/ifql/components/From'
import {funcNames, argTypes} from 'src/ifql/constants'
import {OnChangeArg} from 'src/types/ifql'
interface Props {
funcName: string
@ -13,6 +14,7 @@ interface Props {
argKey: string
value: string | boolean
type: string
expressionID: string
onChangeArg: OnChangeArg
onGenerateScript: () => void
}
@ -25,17 +27,19 @@ class FuncArg extends PureComponent<Props> {
value,
type,
funcName,
onChangeArg,
funcID,
onChangeArg,
expressionID,
onGenerateScript,
} = this.props
if (funcName === funcNames.FROM) {
return (
<From
value={`${value}`}
argKey={argKey}
funcID={funcID}
value={this.value}
expressionID={expressionID}
onChangeArg={onChangeArg}
/>
)
@ -53,9 +57,10 @@ class FuncArg extends PureComponent<Props> {
return (
<FuncArgInput
type={type}
value={`${value}`}
value={this.value}
argKey={argKey}
funcID={funcID}
expressionID={expressionID}
onChangeArg={onChangeArg}
onGenerateScript={onGenerateScript}
/>
@ -69,6 +74,7 @@ class FuncArg extends PureComponent<Props> {
argKey={argKey}
funcID={funcID}
onChangeArg={onChangeArg}
expressionID={expressionID}
onGenerateScript={onGenerateScript}
/>
)
@ -99,6 +105,10 @@ class FuncArg extends PureComponent<Props> {
}
}
private get value(): string {
return `${this.props.value}`
}
private get boolValue(): boolean {
return this.props.value === true
}

View File

@ -1,12 +1,13 @@
import React, {PureComponent} from 'react'
import SlideToggle from 'src/shared/components/SlideToggle'
import {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import {OnChangeArg} from 'src/types/ifql'
interface Props {
argKey: string
value: boolean
funcID: string
expressionID: string
onChangeArg: OnChangeArg
onGenerateScript: () => void
}
@ -22,8 +23,8 @@ class FuncArgBool extends PureComponent<Props> {
}
private handleToggle = (value: boolean): void => {
const {argKey, funcID, onChangeArg} = this.props
onChangeArg({funcID, key: argKey, value, generate: true})
const {argKey, funcID, expressionID, onChangeArg} = this.props
onChangeArg({funcID, key: argKey, value, generate: true, expressionID})
}
}

View File

@ -1,20 +1,13 @@
import React, {PureComponent, ChangeEvent, KeyboardEvent} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
export type OnChangeArg = (inputArg: InputArg) => void
export interface InputArg {
funcID: string
key: string
value: string | boolean
generate?: boolean
}
import {OnChangeArg} from 'src/types/ifql'
interface Props {
funcID: string
argKey: string
value: string
type: string
expressionID: string
onChangeArg: OnChangeArg
onGenerateScript: () => void
}
@ -51,9 +44,14 @@ class FuncArgInput extends PureComponent<Props> {
}
private handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const {funcID, argKey} = this.props
const {funcID, argKey, expressionID} = this.props
this.props.onChangeArg({funcID, key: argKey, value: e.target.value})
this.props.onChangeArg({
funcID,
key: argKey,
value: e.target.value,
expressionID,
})
}
}

View File

@ -1,6 +1,6 @@
import React, {PureComponent} from 'react'
import FuncArg from 'src/ifql/components/FuncArg'
import {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import {OnChangeArg} from 'src/types/ifql'
import {ErrorHandling} from 'src/shared/decorators/errors'
type Value = string | boolean
@ -20,6 +20,7 @@ export interface Func {
interface Props {
func: Func
expressionID: string
onChangeArg: OnChangeArg
onGenerateScript: () => void
}
@ -27,20 +28,21 @@ interface Props {
@ErrorHandling
export default class FuncArgs extends PureComponent<Props> {
public render() {
const {func, onChangeArg, onGenerateScript} = this.props
const {expressionID, func, onChangeArg, onGenerateScript} = this.props
return (
<div className="func-args">
{func.args.map(({key, value, type}) => {
return (
<FuncArg
funcID={func.id}
funcName={func.name}
key={key}
type={type}
argKey={key}
value={value}
funcID={func.id}
funcName={func.name}
onChangeArg={onChangeArg}
expressionID={expressionID}
onGenerateScript={onGenerateScript}
/>
)

View File

@ -1,12 +1,13 @@
import React, {PureComponent, MouseEvent} from 'react'
import FuncArgs from 'src/ifql/components/FuncArgs'
import {Func} from 'src/ifql/components/FuncArgs'
import {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import {OnChangeArg} from 'src/types/ifql'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
func: Func
onDelete: (id: string) => void
expressionID: string
onDelete: (funcID: string, expressionID: string) => void
onChangeArg: OnChangeArg
onGenerateScript: () => void
}
@ -25,7 +26,7 @@ export default class FuncNode extends PureComponent<Props, State> {
}
public render() {
const {func, onChangeArg, onGenerateScript} = this.props
const {expressionID, func, onChangeArg, onGenerateScript} = this.props
const {isOpen} = this.state
return (
@ -37,6 +38,7 @@ export default class FuncNode extends PureComponent<Props, State> {
<FuncArgs
func={func}
onChangeArg={onChangeArg}
expressionID={expressionID}
onGenerateScript={onGenerateScript}
/>
)}
@ -48,7 +50,7 @@ export default class FuncNode extends PureComponent<Props, State> {
}
private handleDelete = (): void => {
this.props.onDelete(this.props.func.id)
this.props.onDelete(this.props.func.id, this.props.expressionID)
}
private handleClick = (e: MouseEvent<HTMLElement>): void => {

View File

@ -4,7 +4,7 @@ import FuncNode from 'src/ifql/components/FuncNode'
import TimeMachineEditor from 'src/ifql/components/TimeMachineEditor'
import {Func} from 'src/ifql/components/FuncArgs'
import {OnChangeArg} from 'src/ifql/components/FuncArgInput'
import {OnChangeArg, OnDeleteFuncNode} from 'src/types/ifql'
import {ErrorHandling} from 'src/shared/decorators/errors'
export interface Suggestion {
@ -23,11 +23,11 @@ interface Props {
script: string
suggestions: Suggestion[]
expressions: Expression[]
onSubmitScript: () => void
onAddNode: (name: string) => void
onChangeScript: (script: string) => void
onSubmitScript: () => void
onDeleteFuncNode: (id: string) => void
onChangeArg: OnChangeArg
onDeleteFuncNode: OnDeleteFuncNode
onGenerateScript: () => void
}
@ -53,13 +53,15 @@ class TimeMachine extends PureComponent<Props> {
onSubmitScript={onSubmitScript}
/>
<div className="expression-container">
{expressions.map(({funcs, id}) => {
{expressions.map(({funcs, id}, i) => {
return (
<div key={id} className="func-nodes-container">
<h2>Expression {i}</h2>
{funcs.map(func => (
<FuncNode
key={func.id}
func={func}
expressionID={id}
onChangeArg={onChangeArg}
onDelete={onDeleteFuncNode}
onGenerateScript={onGenerateScript}

View File

@ -8,7 +8,7 @@ import TimeMachine, {Suggestion} from 'src/ifql/components/TimeMachine'
import KeyboardShortcuts from 'src/shared/components/KeyboardShortcuts'
import Walker from 'src/ifql/ast/walker'
import {Func} from 'src/ifql/components/FuncArgs'
import {InputArg} from 'src/ifql/components/FuncArgInput'
import {InputArg} from 'src/types/ifql'
import {getSuggestions, getAST} from 'src/ifql/apis'
import * as argTypes from 'src/ifql/constants/argumentTypes'
@ -34,6 +34,7 @@ interface State {
interface Expression {
id: string
funcs: Func[]
source: string
}
@ErrorHandling
@ -100,40 +101,55 @@ export class IFQLPage extends PureComponent<Props, State> {
}
private handleGenerateScript = (): void => {
this.getASTResponse(this.funcsToScript)
this.getASTResponse(this.expressionsToScript)
}
private handleChangeArg = ({
funcID,
key,
value,
generate,
funcID,
expressionID,
}: InputArg): void => {
const funcs = this.state.funcs.map(f => {
if (f.id !== funcID) {
return f
const expressions = this.state.expressions.map(expression => {
if (expression.id === expressionID) {
return expression
}
const args = f.args.map(a => {
if (a.key === key) {
return {...a, value}
const funcs = expression.funcs.map(f => {
if (f.id !== funcID) {
return f
}
return a
const args = f.args.map(a => {
if (a.key === key) {
return {...a, value}
}
return a
})
return {...f, args}
})
return {...f, args}
return {...expression, funcs}
})
this.setState({funcs}, () => {
this.setState({expressions}, () => {
if (generate) {
this.handleGenerateScript()
}
})
}
private get funcsToScript(): string {
return this.state.funcs
private get expressionsToScript(): string {
return this.state.expressions.reduce((acc, expression) => {
return acc + this.funcsToScript(expression.funcs)
}, '')
}
private funcsToScript(funcs): string {
return funcs
.map(func => `${func.name}(${this.argsToScript(func.args)})`)
.join('\n\t|> ')
}
@ -166,21 +182,32 @@ export class IFQLPage extends PureComponent<Props, State> {
}
private handleDeleteFuncNode = (
expressionID: string,
funcID: string
funcID: string,
expressionID: string
): void => {
const expression = this.state.expressions.find(
({id}) => id === expressionID
)
const script = this.state.expressions
.map((expression, i) => {
if (expression.id !== expressionID) {
return expression.source
}
const funcs = expression.funcs.filter(f => f.id !== funcID)
const script = funcs.reduce((acc, f, i) => {
if (i === 0) {
return `${f.source}`
}
const funcs = expression.funcs.filter(f => f.id !== funcID)
const source = funcs.reduce((acc, f, i) => {
if (i === 0) {
return `${f.source}`
}
return `${acc}\n\t${f.source}`
}, '')
return `${acc}\n\t${f.source}`
}, '')
const isLast = i === this.state.expressions.length - 1
if (isLast) {
return `${source}`
}
return `${source}\n\n`
})
.join('')
this.getASTResponse(script)
}
@ -192,13 +219,12 @@ export class IFQLPage extends PureComponent<Props, State> {
const walker = new Walker(ast)
const expressions = walker.expressions.map(expression => {
const funcs = this.functions(expression.funcs, suggestions)
const expressions = walker.expressions.map(({funcs, source}) => {
const id = uuid.v4()
return {
id: uuid.v4(),
funcs,
source: expression.source,
id,
funcs: this.functions(funcs, suggestions),
source,
}
})

10
ui/src/types/ifql.ts Normal file
View File

@ -0,0 +1,10 @@
// function definitions
export type OnDeleteFuncNode = (funcID: string, expressionID: string) => void
export type OnChangeArg = (inputArg: InputArg) => void
export interface InputArg {
funcID: string
expressionID: string
key: string
value: string | boolean
generate?: boolean
}

View File

@ -36,7 +36,7 @@ module.exports = {
},
watch: true,
cache: true,
devtool: 'inline-eval-cheap-source-map',
devtool: 'source-map',
entry: {
app: path.resolve(__dirname, '..', 'src', 'index.tsx'),
},