Files
superset2/superset/assets/javascripts/SqlLab/components/SqlEditor.jsx
Alanna Scott 43dd948476 [sql-lab] performance updates - make ui more responsive (#2469)
* remove network status feature

* only fetch queries if there are started or running queries

* don't use local storage

* remove last network status from actions

* don't remove support for local storage

* address pr comments and linting

* use .some rather than .forEach
2017-03-27 12:46:36 -07:00

221 lines
6.4 KiB
JavaScript

import React from 'react';
import {
Col,
FormGroup,
InputGroup,
Form,
FormControl,
Label,
OverlayTrigger,
Row,
Tooltip,
Collapse,
} from 'react-bootstrap';
import Button from '../../components/Button';
import SouthPane from './SouthPane';
import Timer from '../../components/Timer';
import SqlEditorLeftBar from './SqlEditorLeftBar';
import AceEditorWrapper from './AceEditorWrapper';
import { STATE_BSSTYLE_MAP } from '../constants.js';
import RunQueryActionButton from './RunQueryActionButton';
const propTypes = {
actions: React.PropTypes.object.isRequired,
height: React.PropTypes.string.isRequired,
database: React.PropTypes.object,
latestQuery: React.PropTypes.object,
tables: React.PropTypes.array.isRequired,
editorQueries: React.PropTypes.array.isRequired,
dataPreviewQueries: React.PropTypes.array.isRequired,
queryEditor: React.PropTypes.object.isRequired,
hideLeftBar: React.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: '',
};
}
componentDidMount() {
this.onMount();
}
onMount() {
if (this.state.autorun) {
this.setState({ autorun: false });
this.props.actions.queryEditorSetAutorun(this.props.queryEditor, false);
this.startQuery();
}
}
runQuery(runAsync = false) {
let effectiveRunAsync = runAsync;
if (!this.props.database.allow_run_sync) {
effectiveRunAsync = true;
}
this.startQuery(effectiveRunAsync);
}
startQuery(runAsync = false, ctas = false) {
const qe = this.props.queryEditor;
const query = {
dbId: qe.dbId,
sql: qe.selectedText ? qe.selectedText : qe.sql,
sqlEditorId: qe.id,
tab: qe.title,
schema: qe.schema,
tempTableName: ctas ? this.state.ctas : '',
runAsync,
ctas,
};
this.props.actions.runQuery(query);
this.props.actions.setActiveSouthPaneTab('Results');
}
stopQuery() {
this.props.actions.postStopQuery(this.props.latestQuery);
}
createTableAs() {
this.startQuery(true, true);
}
setQueryEditorSql(sql) {
this.props.actions.queryEditorSetSql(this.props.queryEditor, sql);
}
ctasChanged(event) {
this.setState({ ctas: event.target.value });
}
sqlEditorHeight() {
// quick hack to make the white bg of the tab stretch full height.
const tabNavHeight = 40;
const navBarHeight = 56;
const mysteryVerticalHeight = 50;
return window.innerHeight - tabNavHeight - navBarHeight - mysteryVerticalHeight;
}
render() {
let limitWarning = null;
if (this.props.latestQuery && this.props.latestQuery.limit_reached) {
const tooltip = (
<Tooltip id="tooltip">
It appears that the number of rows in the query results displayed
was limited on the server side to
the {this.props.latestQuery.rows} limit.
</Tooltip>
);
limitWarning = (
<OverlayTrigger placement="left" overlay={tooltip}>
<Label bsStyle="warning" className="m-r-5">LIMIT</Label>
</OverlayTrigger>
);
}
let ctasControls;
if (this.props.database && this.props.database.allow_ctas) {
const ctasToolTip = 'Create table as with query results';
ctasControls = (
<FormGroup>
<InputGroup>
<FormControl
type="text"
bsSize="small"
className="input-sm"
placeholder="new table name"
onChange={this.ctasChanged.bind(this)}
/>
<InputGroup.Button>
<Button
bsSize="small"
disabled={this.state.ctas.length === 0}
onClick={this.createTableAs.bind(this)}
tooltip={ctasToolTip}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
);
}
const editorBottomBar = (
<div className="sql-toolbar clearfix" id="js-sql-toolbar">
<div className="pull-left">
<Form inline>
<RunQueryActionButton
allowAsync={this.props.database && this.props.database.allow_run_async}
dbId={this.props.queryEditor.dbId}
queryState={this.props.latestQuery && this.props.latestQuery.state}
runQuery={this.runQuery.bind(this)}
selectedText={this.props.queryEditor.selectedText}
stopQuery={this.stopQuery.bind(this)}
/>
{ctasControls}
</Form>
</div>
<div className="pull-right">
{limitWarning}
{this.props.latestQuery &&
<Timer
startTime={this.props.latestQuery.startDttm}
endTime={this.props.latestQuery.endDttm}
state={STATE_BSSTYLE_MAP[this.props.latestQuery.state]}
isRunning={this.props.latestQuery.state === 'running'}
/>
}
</div>
</div>
);
return (
<div
className="SqlEditor"
style={{
minHeight: this.sqlEditorHeight(),
height: this.props.height,
}}
>
<Row>
<Collapse
in={!this.props.hideLeftBar}
>
<Col md={3}>
<SqlEditorLeftBar
style={{ height: this.props.height }}
queryEditor={this.props.queryEditor}
tables={this.props.tables}
actions={this.props.actions}
/>
</Col>
</Collapse>
<Col md={this.props.hideLeftBar ? 12 : 9}>
<AceEditorWrapper
actions={this.props.actions}
onBlur={this.setQueryEditorSql.bind(this)}
queryEditor={this.props.queryEditor}
onAltEnter={this.runQuery.bind(this)}
sql={this.props.queryEditor.sql}
tables={this.props.tables}
/>
{editorBottomBar}
<br />
<SouthPane
editorQueries={this.props.editorQueries}
dataPreviewQueries={this.props.dataPreviewQueries}
actions={this.props.actions}
/>
</Col>
</Row>
</div>
);
}
}
SqlEditor.defaultProps = defaultProps;
SqlEditor.propTypes = propTypes;
export default SqlEditor;