import React from 'react';
import PropTypes from 'prop-types';
import throttle from 'lodash.throttle';
import {
Col,
FormGroup,
InputGroup,
Form,
FormControl,
Label,
OverlayTrigger,
Row,
Tooltip,
Collapse,
} from 'react-bootstrap';
import SplitPane from 'react-split-pane';
import Button from '../../components/Button';
import TemplateParamsEditor from './TemplateParamsEditor';
import SouthPane from './SouthPane';
import SaveQuery from './SaveQuery';
import ShareQuery from './ShareQuery';
import Timer from '../../components/Timer';
import Hotkeys from '../../components/Hotkeys';
import SqlEditorLeftBar from './SqlEditorLeftBar';
import AceEditorWrapper from './AceEditorWrapper';
import { STATE_BSSTYLE_MAP } from '../constants';
import RunQueryActionButton from './RunQueryActionButton';
import { t } from '../../locales';
const propTypes = {
actions: PropTypes.object.isRequired,
getHeight: PropTypes.func.isRequired,
database: PropTypes.object,
latestQuery: PropTypes.object,
tables: PropTypes.array.isRequired,
editorQueries: PropTypes.array.isRequired,
dataPreviewQueries: PropTypes.array.isRequired,
queryEditor: PropTypes.object.isRequired,
hideLeftBar: PropTypes.bool,
};
const defaultProps = {
database: null,
latestQuery: null,
hideLeftBar: false,
};
class SqlEditor extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
autorun: props.queryEditor.autorun,
ctas: '',
sql: props.queryEditor.sql,
};
this.onResize = this.onResize.bind(this);
this.throttledResize = throttle(this.onResize, 250);
this.runQuery = this.runQuery.bind(this);
this.stopQuery = this.stopQuery.bind(this);
this.onSqlChanged = this.onSqlChanged.bind(this);
this.setQueryEditorSql = this.setQueryEditorSql.bind(this);
}
componentWillMount() {
if (this.state.autorun) {
this.setState({ autorun: false });
this.props.actions.queryEditorSetAutorun(this.props.queryEditor, false);
this.startQuery();
}
}
componentDidMount() {
this.onResize();
window.addEventListener('resize', this.throttledResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.throttledResize);
}
onResize() {
const height = this.sqlEditorHeight();
const editorPaneHeight = this.props.queryEditor.height || 200;
const splitPaneHandlerHeight = 15;
this.setState({
editorPaneHeight,
southPaneHeight: height - editorPaneHeight - splitPaneHandlerHeight,
height,
});
if (this.refs.ace.clientHeight) {
this.props.actions.persistEditorHeight(this.props.queryEditor, this.refs.ace.clientHeight);
}
}
onSqlChanged(sql) {
this.setState({ sql });
}
getHotkeyConfig() {
return [
{
name: 'runQuery',
key: 'ctrl+r',
descr: 'Run query',
func: this.runQuery,
},
{
name: 'newTab',
key: 'ctrl+t',
descr: 'New tab',
func: () => {
this.props.actions.addQueryEditor({
...this.props.queryEditor,
title: t('Untitled Query'),
sql: '',
});
},
},
{
name: 'stopQuery',
key: 'ctrl+x',
descr: 'Stop query',
func: this.stopQuery,
},
];
}
setQueryEditorSql(sql) {
this.props.actions.queryEditorSetSql(this.props.queryEditor, sql);
}
runQuery() {
this.startQuery(!this.props.database.allow_run_sync);
}
startQuery(runAsync = false, ctas = false) {
const qe = this.props.queryEditor;
const query = {
dbId: qe.dbId,
sql: qe.selectedText ? qe.selectedText : this.state.sql,
sqlEditorId: qe.id,
tab: qe.title,
schema: qe.schema,
tempTableName: ctas ? this.state.ctas : '',
templateParams: qe.templateParams,
runAsync,
ctas,
};
this.props.actions.runQuery(query);
this.props.actions.setActiveSouthPaneTab('Results');
}
stopQuery() {
if (this.props.latestQuery && this.props.latestQuery.state === 'running') {
this.props.actions.postStopQuery(this.props.latestQuery);
}
}
createTableAs() {
this.startQuery(true, true);
}
ctasChanged(event) {
this.setState({ ctas: event.target.value });
}
sqlEditorHeight() {
const horizontalScrollbarHeight = 25;
return parseInt(this.props.getHeight(), 10) - horizontalScrollbarHeight;
}
renderEditorBottomBar(hotkeys) {
let ctasControls;
if (this.props.database && this.props.database.allow_ctas) {
const ctasToolTip = t('Create table as with query results');
ctasControls = (