Add line specific error text

pull/10616/head
Andrew Watkins 2018-05-16 11:55:56 -07:00
parent 0a0af981d9
commit 206496c656
5 changed files with 68 additions and 3 deletions

View File

@ -9,6 +9,7 @@ import {
OnChangeScript,
OnSubmitScript,
FlatBody,
Status,
} from 'src/types/ifql'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {HANDLE_VERTICAL, HANDLE_HORIZONTAL} from 'src/shared/constants'
@ -17,6 +18,7 @@ interface Props {
data: string
script: string
body: Body[]
status: Status
suggestions: Suggestion[]
onChangeScript: OnChangeScript
onSubmitScript: OnSubmitScript
@ -63,6 +65,7 @@ class TimeMachine extends PureComponent<Props> {
const {
body,
script,
status,
suggestions,
onChangeScript,
onSubmitScript,
@ -78,6 +81,7 @@ class TimeMachine extends PureComponent<Props> {
menuOptions: [{action: onSubmitScript, text: 'Analyze'}],
render: visibility => (
<TimeMachineEditor
status={status}
script={script}
onChangeScript={onChangeScript}
visibility={visibility}

View File

@ -6,10 +6,16 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
import {OnChangeScript} from 'src/types/ifql'
import {editor} from 'src/ifql/constants'
interface Status {
type: string
text: string
}
interface Props {
script: string
onChangeScript: OnChangeScript
visibility: string
status: Status
onChangeScript: OnChangeScript
}
interface EditorInstance extends IInstance {
@ -19,12 +25,21 @@ interface EditorInstance extends IInstance {
@ErrorHandling
class TimeMachineEditor extends PureComponent<Props> {
private editor: EditorInstance
private prevKey: string
constructor(props) {
super(props)
}
public componentDidUpdate(prevProps) {
if (this.props.status.type === 'error') {
this.makeError()
}
if (this.props.status.type !== 'error') {
this.editor.clearGutter('error-gutter')
}
if (prevProps.visibility === this.props.visibility) {
return
}
@ -45,6 +60,7 @@ class TimeMachineEditor extends PureComponent<Props> {
extraKeys: {'Ctrl-Space': 'autocomplete'},
completeSingle: false,
autoRefresh: true,
gutters: ['error-gutter'],
}
return (
@ -63,6 +79,25 @@ class TimeMachineEditor extends PureComponent<Props> {
)
}
private makeError(): void {
const {status} = this.props
this.editor.clearGutter('error-gutter')
const span = document.createElement('span')
span.className = 'icon stop error-warning'
span.title = status.text
const lineNumber = this.statusLine
this.editor.setGutterMarker(lineNumber - 1, 'error-gutter', span)
this.editor.refresh()
}
private get statusLine(): number {
const {status} = this.props
const numbers = status.text.split(' ')[0]
const [lineNumber] = numbers.split(':')
return Number(lineNumber)
}
private handleMount = (instance: EditorInstance) => {
instance.refresh() // required to for proper line height on mount
this.editor = instance

View File

@ -13,6 +13,11 @@ import {getSuggestions, getAST, getTimeSeries} from 'src/ifql/apis'
import * as argTypes from 'src/ifql/constants/argumentTypes'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Status {
type: string
text: string
}
interface Props {
links: Links
}
@ -27,6 +32,7 @@ interface State {
script: string
data: string
suggestions: Suggestion[]
status: Status
}
export const IFQLContext = React.createContext()
@ -42,6 +48,10 @@ export class IFQLPage extends PureComponent<Props, State> {
suggestions: [],
script: `fil = (r) => r._measurement == "cpu"
tele = from(db: "telegraf") |> filter(fn: fil) |> range(start: -1m) |> sum()`,
status: {
type: 'none',
text: '',
},
}
}
@ -59,7 +69,7 @@ export class IFQLPage extends PureComponent<Props, State> {
}
public render() {
const {suggestions, script, data, body} = this.state
const {suggestions, script, data, body, status} = this.state
return (
<IFQLContext.Provider value={this.handlers}>
@ -84,6 +94,7 @@ export class IFQLPage extends PureComponent<Props, State> {
data={data}
body={body}
script={script}
status={status}
suggestions={suggestions}
onChangeScript={this.handleChangeScript}
onSubmitScript={this.handleSubmitScript}
@ -333,8 +344,13 @@ export class IFQLPage extends PureComponent<Props, State> {
try {
const ast = await getAST({url: links.ast, body: script})
const body = bodyNodes(ast, this.state.suggestions)
this.setState({ast, script, body})
const status = {type: 'success', text: ''}
this.setState({ast, script, body, status})
} catch (error) {
const s = error.data.slice(0, -5) // There is a null newline at the end of these responses
const data = JSON.parse(s)
const status = {type: 'error', text: `${data.message}`}
this.setState({status})
return console.error('Could not parse AST', error)
}
}

View File

@ -19,3 +19,8 @@
width: 100%;
height: 100%;
}
.error-warning {
color: $c-dreamsicle;
cursor: pointer;
}

View File

@ -10,6 +10,11 @@ export type OnGenerateScript = (script: string) => void
export type OnChangeScript = (script: string) => void
export type OnSubmitScript = () => void
export interface Status {
type: string
text: string
}
export interface Handlers {
onAddNode: OnAddNode
onChangeArg: OnChangeArg