Replace textarea in DE query editor with code mirror editor
parent
cef2e98f94
commit
d94898b8fc
|
@ -1,10 +1,14 @@
|
|||
import React, {PureComponent, KeyboardEvent} from 'react'
|
||||
import React, {PureComponent} from 'react'
|
||||
|
||||
import {Controlled as ReactCodeMirror, IInstance} from 'react-codemirror2'
|
||||
import {EditorChange} from 'codemirror'
|
||||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
import classnames from 'classnames'
|
||||
import {QUERY_TEMPLATES, QueryTemplate} from 'src/data_explorer/constants'
|
||||
import QueryStatus from 'src/shared/components/QueryStatus'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {QueryConfig} from 'src/types'
|
||||
import 'src/external/codemirror'
|
||||
|
||||
interface Props {
|
||||
query: string
|
||||
|
@ -14,19 +18,17 @@ interface Props {
|
|||
|
||||
interface State {
|
||||
value: string
|
||||
focused: boolean
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class QueryEditor extends PureComponent<Props, State> {
|
||||
private editor: React.RefObject<HTMLTextAreaElement>
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
value: this.props.query,
|
||||
focused: false,
|
||||
}
|
||||
|
||||
this.editor = React.createRef<HTMLTextAreaElement>()
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
|
@ -41,21 +43,34 @@ class QueryEditor extends PureComponent<Props, State> {
|
|||
} = this.props
|
||||
const {value} = this.state
|
||||
|
||||
const options = {
|
||||
tabIndex: 1,
|
||||
mode: 'influxQL',
|
||||
readonly: false,
|
||||
lineNumbers: false,
|
||||
autoRefresh: true,
|
||||
theme: 'influxql',
|
||||
completeSingle: false,
|
||||
lineWrapping: true,
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="query-editor">
|
||||
<textarea
|
||||
className="query-editor--field"
|
||||
ref={this.editor}
|
||||
value={value}
|
||||
autoComplete="off"
|
||||
spellCheck={false}
|
||||
onBlur={this.handleUpdate}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
data-test="query-editor-field"
|
||||
placeholder="Enter a query or select database, measurement, and field below and have us build one for you..."
|
||||
/>
|
||||
<div className="varmoji">
|
||||
<div className={this.queryCodeClassName}>
|
||||
<ReactCodeMirror
|
||||
autoFocus={true}
|
||||
autoCursor={true}
|
||||
value={value}
|
||||
options={options}
|
||||
onBeforeChange={this.updateCode}
|
||||
onChange={this.handleChange}
|
||||
onTouchStart={this.onTouchStart}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.handleFocus}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
/>
|
||||
</div>
|
||||
<div className={this.varmojiClassName}>
|
||||
<div className="varmoji-container">
|
||||
<div className="varmoji-front">
|
||||
<QueryStatus status={status}>
|
||||
|
@ -66,6 +81,12 @@ class QueryEditor extends PureComponent<Props, State> {
|
|||
className="dropdown-140 query-editor--templates"
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
<button
|
||||
className="btn btn-xs btn-primary query-editor--submit"
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
Submit Query
|
||||
</button>
|
||||
</QueryStatus>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -74,32 +95,54 @@ class QueryEditor extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>): void => {
|
||||
const {value} = this.state
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault()
|
||||
this.setState({value})
|
||||
}
|
||||
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
this.handleUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
private handleChange = (): void => {
|
||||
const value = this.editor.current.value
|
||||
this.setState({value})
|
||||
}
|
||||
|
||||
private handleUpdate = (): void => {
|
||||
private handleSubmit = (): void => {
|
||||
this.props.onUpdate(this.state.value)
|
||||
}
|
||||
|
||||
private get queryCodeClassName(): string {
|
||||
const {focused} = this.state
|
||||
|
||||
return classnames('query-editor--code', {focus: focused})
|
||||
}
|
||||
|
||||
private get varmojiClassName(): string {
|
||||
const {focused} = this.state
|
||||
|
||||
return classnames('varmoji', {focus: focused})
|
||||
}
|
||||
|
||||
private onTouchStart = () => {}
|
||||
|
||||
private handleChange = (): void => {}
|
||||
|
||||
private handleBlur = (): void => {
|
||||
this.setState({focused: false})
|
||||
this.handleSubmit()
|
||||
}
|
||||
|
||||
private handleFocus = (): void => {
|
||||
this.setState({focused: true})
|
||||
}
|
||||
|
||||
private handleChooseMetaQuery = (template: QueryTemplate): void => {
|
||||
this.setState({value: template.query})
|
||||
}
|
||||
|
||||
private handleKeyUp = (__, e: KeyboardEvent) => {
|
||||
const {ctrlKey, metaKey, key} = e
|
||||
|
||||
if (key === 'Enter' && (ctrlKey || metaKey)) {
|
||||
this.handleSubmit()
|
||||
}
|
||||
}
|
||||
|
||||
private updateCode = (
|
||||
_: IInstance,
|
||||
__: EditorChange,
|
||||
value: string
|
||||
): void => {
|
||||
this.setState({value})
|
||||
}
|
||||
}
|
||||
|
||||
export default QueryEditor
|
||||
|
|
|
@ -13,40 +13,15 @@
|
|||
position: relative;
|
||||
z-index: 3; /* Minimum amount to obcure the toggle flip within Query Builder. Will fix later */
|
||||
}
|
||||
.query-editor--field {
|
||||
font-family: $code-font;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
font-weight: 600;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
@include custom-scrollbar($query-editor--field-bg, $query-editor--field-text);
|
||||
display: block;
|
||||
resize: none;
|
||||
width: 100%;
|
||||
height: $query-editor--field-height;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease,
|
||||
border-color 0.25s ease;
|
||||
.query-editor--code {
|
||||
background-color: $query-editor--field-bg;
|
||||
border: 2px solid $query-editor--bg;
|
||||
border-bottom: 0;
|
||||
background-color: $query-editor--field-bg;
|
||||
color: $query-editor--field-text;
|
||||
padding: 12px 10px 0 10px;
|
||||
border-radius: $radius $radius 0 0;
|
||||
margin: 0;
|
||||
padding: 6px 8px;
|
||||
transition: border-color 0.25s ease;
|
||||
|
||||
&:hover,
|
||||
&:hover + .query-editor--status {
|
||||
border-color: $query-editor--bg;
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
color: $query-editor--field-text !important;
|
||||
border-color: $c-pool;
|
||||
}
|
||||
&:focus + .varmoji {
|
||||
&.focus {
|
||||
border-color: $c-pool;
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +71,9 @@
|
|||
max-width: $query-editor--templates-menu-width;
|
||||
}
|
||||
}
|
||||
button.btn.query-editor--submit {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -113,6 +91,10 @@
|
|||
height: $query-editor--status-height;
|
||||
width: 100%;
|
||||
perspective: 1000px;
|
||||
|
||||
&.focus {
|
||||
border-color: $c-pool;
|
||||
}
|
||||
}
|
||||
.varmoji-container {
|
||||
transition: transform 0.6s ease;
|
||||
|
|
Loading…
Reference in New Issue