Merge pull request #3696 from influxdata/flux/deletion
Introduce ability to delete entire queriespull/10616/head
commit
4a166b9706
|
@ -10,6 +10,7 @@
|
|||
|
||||
1. [#3474](https://github.com/influxdata/chronograf/pull/3474): Sort task table on Manage Alert page alphabetically
|
||||
1. [#3590](https://github.com/influxdata/chronograf/pull/3590): Redesign icons in side navigation
|
||||
1. [#3696](https://github.com/influxdata/chronograf/pull/3696): Add ability to delete entire queries in Flux Editor
|
||||
1. [#3671](https://github.com/influxdata/chronograf/pull/3671): Remove Snip functionality in hover legend
|
||||
1. [#3659](https://github.com/influxdata/chronograf/pull/3659): Upgrade Data Explorer query text field with syntax highlighting and partial multi-line support
|
||||
1. [#3663](https://github.com/influxdata/chronograf/pull/3663): Truncate message preview in Alert Rules table
|
||||
|
|
|
@ -3,12 +3,13 @@ import _ from 'lodash'
|
|||
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
import ExpressionNode from 'src/flux/components/ExpressionNode'
|
||||
import VariableName from 'src/flux/components/VariableName'
|
||||
import VariableNode from 'src/flux/components/VariableNode'
|
||||
import FuncSelector from 'src/flux/components/FuncSelector'
|
||||
import BodyDelete from 'src/flux/components/BodyDelete'
|
||||
import {funcNames} from 'src/flux/constants'
|
||||
|
||||
import {Service} from 'src/types'
|
||||
import {FlatBody, Suggestion} from 'src/types/flux'
|
||||
import {Body, Suggestion} from 'src/types/flux'
|
||||
|
||||
interface Props {
|
||||
service: Service
|
||||
|
@ -16,21 +17,25 @@ interface Props {
|
|||
suggestions: Suggestion[]
|
||||
onAppendFrom: () => void
|
||||
onAppendJoin: () => void
|
||||
}
|
||||
|
||||
interface Body extends FlatBody {
|
||||
id: string
|
||||
onDeleteBody: (bodyID: string) => void
|
||||
}
|
||||
|
||||
class BodyBuilder extends PureComponent<Props> {
|
||||
public render() {
|
||||
const bodybuilder = this.props.body.map((b, i) => {
|
||||
const {body, onDeleteBody} = this.props
|
||||
|
||||
const bodybuilder = body.map((b, i) => {
|
||||
if (b.declarations.length) {
|
||||
return b.declarations.map(d => {
|
||||
if (d.funcs) {
|
||||
return (
|
||||
<div className="declaration" key={i}>
|
||||
<VariableName name={d.name} assignedToQuery={true} />
|
||||
<div className="func-node--wrapper">
|
||||
<VariableNode name={d.name} assignedToQuery={true} />
|
||||
<div className="func-node--menu">
|
||||
<BodyDelete bodyID={b.id} onDeleteBody={onDeleteBody} />
|
||||
</div>
|
||||
</div>
|
||||
<ExpressionNode
|
||||
bodyID={b.id}
|
||||
declarationID={d.id}
|
||||
|
@ -38,6 +43,7 @@ class BodyBuilder extends PureComponent<Props> {
|
|||
funcs={d.funcs}
|
||||
declarationsFromBody={this.declarationsFromBody}
|
||||
isLastBody={this.isLastBody(i)}
|
||||
onDeleteBody={onDeleteBody}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -45,7 +51,16 @@ class BodyBuilder extends PureComponent<Props> {
|
|||
|
||||
return (
|
||||
<div className="declaration" key={i}>
|
||||
<VariableName name={b.source} assignedToQuery={false} />
|
||||
<div className="func-node--wrapper">
|
||||
<VariableNode name={b.source} assignedToQuery={false} />
|
||||
<div className="func-node--menu">
|
||||
<BodyDelete
|
||||
bodyID={b.id}
|
||||
type="variable"
|
||||
onDeleteBody={onDeleteBody}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
@ -59,6 +74,7 @@ class BodyBuilder extends PureComponent<Props> {
|
|||
funcNames={this.funcNames}
|
||||
declarationsFromBody={this.declarationsFromBody}
|
||||
isLastBody={this.isLastBody(i)}
|
||||
onDeleteBody={onDeleteBody}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import ConfirmButton from 'src/shared/components/ConfirmButton'
|
||||
|
||||
type BodyType = 'variable' | 'query'
|
||||
|
||||
interface Props {
|
||||
bodyID: string
|
||||
type?: BodyType
|
||||
onDeleteBody: (bodyID: string) => void
|
||||
}
|
||||
|
||||
class BodyDelete extends PureComponent<Props> {
|
||||
public static defaultProps: Partial<Props> = {
|
||||
type: 'query',
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {type} = this.props
|
||||
|
||||
if (type === 'variable') {
|
||||
return (
|
||||
<button
|
||||
className="btn btn-sm btn-square btn-danger"
|
||||
title="Delete Variable"
|
||||
onClick={this.handleDelete}
|
||||
>
|
||||
<span className="icon remove" />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfirmButton
|
||||
icon="trash"
|
||||
type="btn-danger"
|
||||
confirmText="Delete Query"
|
||||
square={true}
|
||||
confirmAction={this.handleDelete}
|
||||
position="right"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private handleDelete = (): void => {
|
||||
this.props.onDeleteBody(this.props.bodyID)
|
||||
}
|
||||
}
|
||||
|
||||
export default BodyDelete
|
|
@ -15,6 +15,7 @@ interface Props {
|
|||
declarationID?: string
|
||||
declarationsFromBody: string[]
|
||||
isLastBody: boolean
|
||||
onDeleteBody: (bodyID: string) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -42,6 +43,7 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
funcNames,
|
||||
funcs,
|
||||
declarationsFromBody,
|
||||
onDeleteBody,
|
||||
} = this.props
|
||||
|
||||
const {nonYieldableIndexesToggled} = this.state
|
||||
|
@ -106,6 +108,7 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
onGenerateScript={onGenerateScript}
|
||||
declarationsFromBody={declarationsFromBody}
|
||||
onToggleYieldWithLast={this.handleToggleYieldWithLast}
|
||||
onDeleteBody={onDeleteBody}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -152,6 +155,7 @@ class ExpressionNode extends PureComponent<Props, State> {
|
|||
onGenerateScript={onGenerateScript}
|
||||
declarationsFromBody={declarationsFromBody}
|
||||
onToggleYieldWithLast={this.handleToggleYieldWithLast}
|
||||
onDeleteBody={onDeleteBody}
|
||||
/>
|
||||
<YieldFuncNode
|
||||
index={i}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, {PureComponent, MouseEvent} from 'react'
|
|||
import classnames from 'classnames'
|
||||
import _ from 'lodash'
|
||||
|
||||
import BodyDelete from 'src/flux/components/BodyDelete'
|
||||
import FuncArgs from 'src/flux/components/FuncArgs'
|
||||
import FuncArgsPreview from 'src/flux/components/FuncArgsPreview'
|
||||
import {
|
||||
|
@ -28,6 +29,7 @@ interface Props {
|
|||
declarationsFromBody: string[]
|
||||
isYielding: boolean
|
||||
isYieldable: boolean
|
||||
onDeleteBody: (bodyID: string) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -53,14 +55,16 @@ export default class FuncNode extends PureComponent<Props, State> {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={this.nodeClassName}
|
||||
onClick={this.handleToggleEdit}
|
||||
title="Edit function arguments"
|
||||
>
|
||||
<div className="func-node--connector" />
|
||||
<div className="func-node--name">{func.name}</div>
|
||||
<FuncArgsPreview func={func} />
|
||||
<div className="func-node--wrapper">
|
||||
<div
|
||||
className={this.nodeClassName}
|
||||
onClick={this.handleToggleEdit}
|
||||
title="Edit function arguments"
|
||||
>
|
||||
<div className="func-node--connector" />
|
||||
<div className="func-node--name">{func.name}</div>
|
||||
<FuncArgsPreview func={func} />
|
||||
</div>
|
||||
{this.funcMenu}
|
||||
</div>
|
||||
{this.funcArgs}
|
||||
|
@ -103,13 +107,7 @@ export default class FuncNode extends PureComponent<Props, State> {
|
|||
return (
|
||||
<div className="func-node--menu">
|
||||
{this.yieldToggleButton}
|
||||
<button
|
||||
className="btn btn-sm btn-square btn-danger"
|
||||
onClick={this.handleDelete}
|
||||
title="Delete this Function"
|
||||
>
|
||||
<span className="icon trash" />
|
||||
</button>
|
||||
{this.deleteButton}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -140,6 +138,24 @@ export default class FuncNode extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get deleteButton(): JSX.Element {
|
||||
const {func, bodyID, onDeleteBody} = this.props
|
||||
|
||||
if (func.name === 'from') {
|
||||
return <BodyDelete onDeleteBody={onDeleteBody} bodyID={bodyID} />
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className="btn btn-sm btn-square btn-danger"
|
||||
onClick={this.handleDelete}
|
||||
title="Delete this Function"
|
||||
>
|
||||
<span className="icon remove" />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
private get nodeClassName(): string {
|
||||
const {isYielding} = this.props
|
||||
const {editing} = this.state
|
||||
|
@ -147,14 +163,14 @@ export default class FuncNode extends PureComponent<Props, State> {
|
|||
return classnames('func-node', {active: isYielding || editing})
|
||||
}
|
||||
|
||||
private handleDelete = (e: MouseEvent<HTMLElement>): void => {
|
||||
e.stopPropagation()
|
||||
private handleDelete = (): void => {
|
||||
const {func, bodyID, declarationID} = this.props
|
||||
|
||||
this.props.onDelete({funcID: func.id, bodyID, declarationID})
|
||||
}
|
||||
|
||||
private handleToggleEdit = (): void => {
|
||||
private handleToggleEdit = (e: MouseEvent<HTMLElement>): void => {
|
||||
e.stopPropagation()
|
||||
this.setState({editing: !this.state.editing})
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
Suggestion,
|
||||
OnChangeScript,
|
||||
OnSubmitScript,
|
||||
OnDeleteBody,
|
||||
FlatBody,
|
||||
ScriptStatus,
|
||||
} from 'src/types/flux'
|
||||
|
@ -22,6 +23,7 @@ interface Props {
|
|||
status: ScriptStatus
|
||||
suggestions: Suggestion[]
|
||||
onChangeScript: OnChangeScript
|
||||
onDeleteBody: OnDeleteBody
|
||||
onSubmitScript: OnSubmitScript
|
||||
onAppendFrom: () => void
|
||||
onAppendJoin: () => void
|
||||
|
@ -63,7 +65,14 @@ class TimeMachine extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
private get builder() {
|
||||
const {body, service, suggestions, onAppendFrom, onAppendJoin} = this.props
|
||||
const {
|
||||
body,
|
||||
service,
|
||||
suggestions,
|
||||
onAppendFrom,
|
||||
onDeleteBody,
|
||||
onAppendJoin,
|
||||
} = this.props
|
||||
|
||||
return {
|
||||
name: 'Build',
|
||||
|
@ -75,6 +84,7 @@ class TimeMachine extends PureComponent<Props> {
|
|||
body={body}
|
||||
service={service}
|
||||
suggestions={suggestions}
|
||||
onDeleteBody={onDeleteBody}
|
||||
onAppendFrom={onAppendFrom}
|
||||
onAppendJoin={onAppendJoin}
|
||||
/>
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
export const emptyAST = {
|
||||
type: 'Program',
|
||||
location: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 1,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 1,
|
||||
},
|
||||
source: '',
|
||||
},
|
||||
body: [],
|
||||
}
|
||||
|
||||
export const ast = {
|
||||
type: 'File',
|
||||
start: 0,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {ast} from 'src/flux/constants/ast'
|
||||
import {ast, emptyAST} from 'src/flux/constants/ast'
|
||||
import * as editor from 'src/flux/constants/editor'
|
||||
import * as argTypes from 'src/flux/constants/argumentTypes'
|
||||
import * as funcNames from 'src/flux/constants/funcNames'
|
||||
|
@ -10,6 +10,7 @@ const MAX_RESPONSE_BYTES = 1e7 // 10 MB
|
|||
|
||||
export {
|
||||
ast,
|
||||
emptyAST,
|
||||
funcNames,
|
||||
argTypes,
|
||||
editor,
|
||||
|
|
|
@ -15,7 +15,7 @@ import {UpdateScript} from 'src/flux/actions'
|
|||
|
||||
import {bodyNodes} from 'src/flux/helpers'
|
||||
import {getSuggestions, getAST, getTimeSeries} from 'src/flux/apis'
|
||||
import {builder, argTypes} from 'src/flux/constants'
|
||||
import {builder, argTypes, emptyAST} from 'src/flux/constants'
|
||||
|
||||
import {Source, Service, Notification, FluxTable} from 'src/types'
|
||||
import {
|
||||
|
@ -114,6 +114,7 @@ export class FluxPage extends PureComponent<Props, State> {
|
|||
onAppendJoin={this.handleAppendJoin}
|
||||
onChangeScript={this.handleChangeScript}
|
||||
onSubmitScript={this.handleSubmitScript}
|
||||
onDeleteBody={this.handleDeleteBody}
|
||||
/>
|
||||
</div>
|
||||
</KeyboardShortcuts>
|
||||
|
@ -331,6 +332,13 @@ export class FluxPage extends PureComponent<Props, State> {
|
|||
this.getASTResponse(script)
|
||||
}
|
||||
|
||||
private handleDeleteBody = (bodyID: string): void => {
|
||||
const newBody = this.state.body.filter(b => b.id !== bodyID)
|
||||
const script = this.getBodyToScript(newBody)
|
||||
|
||||
this.getASTResponse(script)
|
||||
}
|
||||
|
||||
private handleScriptUpToYield = (
|
||||
bodyID: string,
|
||||
declarationID: string,
|
||||
|
@ -601,7 +609,8 @@ export class FluxPage extends PureComponent<Props, State> {
|
|||
const {links} = this.props
|
||||
|
||||
if (!script) {
|
||||
return
|
||||
this.props.updateScript(script)
|
||||
return this.setState({ast: emptyAST, body: []})
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
type Position = 'top' | 'bottom' | 'left' | 'right'
|
||||
|
||||
interface Props {
|
||||
text?: string
|
||||
confirmText?: string
|
||||
|
@ -12,6 +15,7 @@ interface Props {
|
|||
icon?: string
|
||||
disabled?: boolean
|
||||
customClass?: string
|
||||
position?: Position
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -47,10 +51,11 @@ class ConfirmButton extends PureComponent<Props, State> {
|
|||
className={this.className}
|
||||
onClick={this.handleButtonClick}
|
||||
ref={r => (this.buttonDiv = r)}
|
||||
title={confirmText}
|
||||
>
|
||||
{icon && <span className={`icon ${icon}`} />}
|
||||
{text && text}
|
||||
<div className={`confirm-button--tooltip ${this.calculatedPosition}`}>
|
||||
<div className={this.tooltipClassName}>
|
||||
<div
|
||||
className="confirm-button--confirmation"
|
||||
onClick={this.handleConfirmClick}
|
||||
|
@ -64,18 +69,6 @@ class ConfirmButton extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get className() {
|
||||
const {type, size, square, disabled, customClass} = this.props
|
||||
const {expanded} = this.state
|
||||
|
||||
const customClassString = customClass ? ` ${customClass}` : ''
|
||||
const squareString = square ? ' btn-square' : ''
|
||||
const expandedString = expanded ? ' active' : ''
|
||||
const disabledString = disabled ? ' disabled' : ''
|
||||
|
||||
return `confirm-button btn ${type} ${size}${customClassString}${squareString}${expandedString}${disabledString}`
|
||||
}
|
||||
|
||||
private handleButtonClick = () => {
|
||||
if (this.props.disabled) {
|
||||
return
|
||||
|
@ -92,9 +85,27 @@ class ConfirmButton extends PureComponent<Props, State> {
|
|||
this.setState({expanded: false})
|
||||
}
|
||||
|
||||
private get calculatedPosition() {
|
||||
private get className(): string {
|
||||
const {type, size, square, disabled, customClass} = this.props
|
||||
const {expanded} = this.state
|
||||
|
||||
return classnames(`confirm-button btn ${type} ${size}`, {
|
||||
[customClass]: customClass,
|
||||
'btn-square': square,
|
||||
active: expanded,
|
||||
disabled,
|
||||
})
|
||||
}
|
||||
|
||||
private get tooltipClassName(): string {
|
||||
const {position} = this.props
|
||||
|
||||
if (position) {
|
||||
return `confirm-button--tooltip ${position}`
|
||||
}
|
||||
|
||||
if (!this.buttonDiv || !this.tooltipDiv) {
|
||||
return ''
|
||||
return 'confirm-button--tooltip bottom'
|
||||
}
|
||||
|
||||
const windowWidth = window.innerWidth
|
||||
|
@ -104,10 +115,10 @@ class ConfirmButton extends PureComponent<Props, State> {
|
|||
const rightGap = windowWidth - buttonRect.right
|
||||
|
||||
if (tooltipRect.width / 2 > rightGap) {
|
||||
return 'left'
|
||||
return 'confirm-button--tooltip left'
|
||||
}
|
||||
|
||||
return 'bottom'
|
||||
return 'confirm-button--tooltip bottom'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,18 +11,26 @@
|
|||
position: absolute;
|
||||
z-index: 1;
|
||||
|
||||
|
||||
&.top {
|
||||
bottom: calc(100% + 4px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
&.bottom {
|
||||
top: calc(100% + 4px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&.left {
|
||||
top: 50%;
|
||||
right: calc(100% + 4px);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
&.right {
|
||||
top: 50%;
|
||||
left: calc(100% + 4px);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.confirm-button--confirmation {
|
||||
|
@ -43,11 +51,7 @@
|
|||
&:after {
|
||||
content: '';
|
||||
border: 8px solid transparent;
|
||||
border-bottom-color: $c-curacao;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
transition: border-color 0.25s ease;
|
||||
z-index: 100;
|
||||
}
|
||||
|
@ -56,28 +60,35 @@
|
|||
background-color: $c-dreamsicle;
|
||||
cursor: pointer;
|
||||
}
|
||||
&:hover:after {
|
||||
border-bottom-color: $c-dreamsicle;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-button--tooltip.bottom .confirm-button--confirmation:after {
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
border-bottom-color: $c-curacao;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.confirm-button--tooltip.bottom .confirm-button--confirmation:hover:after {
|
||||
border-bottom-color: $c-dreamsicle;
|
||||
}
|
||||
.confirm-button--tooltip.left .confirm-button--confirmation:after {
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
border-left-color: $c-curacao;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.confirm-button--tooltip.left .confirm-button--confirmation:hover:after {
|
||||
border-left-color: $c-dreamsicle;
|
||||
.top &:after {
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-top-color: $c-curacao;
|
||||
}
|
||||
.top &:hover:after {border-top-color: $c-dreamsicle;}
|
||||
.bottom &:after {
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
border-bottom-color: $c-curacao;
|
||||
}
|
||||
.bottom &:hover:after {border-bottom-color: $c-dreamsicle;}
|
||||
.left &:after {
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
transform: translateY(-50%);
|
||||
border-left-color: $c-curacao;
|
||||
}
|
||||
.left &:hover:after {border-left-color: $c-dreamsicle;}
|
||||
.right &:after {
|
||||
top: 50%;
|
||||
right: 100%;
|
||||
transform: translateY(-50%);
|
||||
border-right-color: $c-curacao;
|
||||
}
|
||||
.right &:hover:after {border-right-color: $c-dreamsicle;}
|
||||
}
|
||||
|
||||
.confirm-button.active {
|
||||
|
|
|
@ -144,6 +144,8 @@ $flux-invalid-hover: $c-dreamsicle;
|
|||
|
||||
&:hover,
|
||||
&.active {
|
||||
cursor: pointer !important;
|
||||
|
||||
.func-node--preview {
|
||||
color: $g20-white;
|
||||
}
|
||||
|
@ -196,7 +198,7 @@ $flux-invalid-hover: $c-dreamsicle;
|
|||
}
|
||||
|
||||
// When a query exists unassigned to a variable
|
||||
.func-node:first-child {
|
||||
.func-node--wrapper:first-child .func-node {
|
||||
margin-left: 0;
|
||||
padding-left: $flux-node-gap;
|
||||
.func-node--connector {
|
||||
|
@ -248,24 +250,26 @@ $flux-invalid-hover: $c-dreamsicle;
|
|||
}
|
||||
}
|
||||
|
||||
.func-node--wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.func-node--menu {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translate(100%, -50%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease;
|
||||
|
||||
> button.btn {
|
||||
> button.btn,
|
||||
> .confirm-button {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.func-node:hover .func-node--menu,
|
||||
.func-node.editing .func-node--menu,
|
||||
.func-node.active .func-node--menu {
|
||||
.func-node--wrapper:hover .func-node--menu,
|
||||
.func-node.editing + .func-node--menu,
|
||||
.func-node.active + .func-node--menu {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ export type ScriptUpToYield = (
|
|||
yieldNodeIndex: number,
|
||||
isYieldable: boolean
|
||||
) => string
|
||||
export type OnDeleteBody = (bodyID: string) => void
|
||||
|
||||
export interface ScriptStatus {
|
||||
type: string
|
||||
|
@ -105,6 +106,9 @@ export interface FlatBody {
|
|||
funcs?: Func[]
|
||||
declarations?: FlatDeclaration[]
|
||||
}
|
||||
export interface Body extends FlatBody {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface Func {
|
||||
type: string
|
||||
|
|
|
@ -15,6 +15,7 @@ const setup = () => {
|
|||
onValidate: () => {},
|
||||
onAppendFrom: () => {},
|
||||
onAppendJoin: () => {},
|
||||
onDeleteBody: () => {},
|
||||
status: {type: '', text: ''},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue