More improvements to SQL Lab (#1104)

* Handling timeouts

* Fixing timer on non-utc server

* Allowing async with results

* [bugfix] database is not selected

* Making sure the session is up and running

* Cleaning up query results and query objects

* Picking a groupby and metric field on visualize flow

* Showing local time in query history

* Using pull-left pull-right instead of grid layout for table metdata

Long column name were looking weird and icons were wrapping oddly

* Linting

* Eliminating east buttons under the sql editor

* Sort database dropdown by name

* Linting

* Allowing non-SELECT statements to run

* Adding a db config

* Making sqla checkout check cross-db
This commit is contained in:
Maxime Beauchemin
2016-09-19 15:28:10 -07:00
committed by GitHub
parent 8081080709
commit e8088d5c9a
20 changed files with 377 additions and 158 deletions

View File

@@ -41,7 +41,7 @@ class QueryTable extends React.Component {
if (q.endDttm) {
q.duration = fDuration(q.startDttm, q.endDttm);
}
q.started = moment.utc(q.startDttm).format('HH:mm:ss');
q.started = moment(q.startDttm).format('HH:mm:ss');
const source = (q.ctas) ? q.executedSql : q.sql;
q.sql = (
<SqlShrink sql={source} />

View File

@@ -60,7 +60,7 @@ class ResultSet extends React.Component {
</div>
);
}
if (results && results.data.length > 0) {
if (results && results.data && results.data.length > 0) {
return (
<div>
<VisualizeModal

View File

@@ -9,9 +9,7 @@ import {
InputGroup,
Form,
FormControl,
DropdownButton,
Label,
MenuItem,
OverlayTrigger,
Row,
Tooltip,
@@ -27,7 +25,6 @@ import { connect } from 'react-redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import ButtonWithTooltip from './ButtonWithTooltip';
import SouthPane from './SouthPane';
import Timer from './Timer';
@@ -52,8 +49,8 @@ class SqlEditor extends React.Component {
this.startQuery();
}
}
runQuery() {
this.startQuery();
runQuery(runAsync = false) {
this.startQuery(runAsync);
}
startQuery(runAsync = false, ctas = false) {
const that = this;
@@ -76,10 +73,10 @@ class SqlEditor extends React.Component {
const sqlJsonUrl = '/caravel/sql_json/';
const sqlJsonRequest = {
async: runAsync,
client_id: query.id,
database_id: this.props.queryEditor.dbId,
json: true,
runAsync,
schema: this.props.queryEditor.schema,
select_as_cta: ctas,
sql: this.props.queryEditor.sql,
@@ -149,17 +146,36 @@ class SqlEditor extends React.Component {
}
render() {
let runButtons = (
<ButtonGroup bsSize="small" className="inline m-r-5 pull-left">
let runButtons = [];
if (this.props.database && this.props.database.allow_run_sync) {
runButtons.push(
<Button
bsSize="small"
bsStyle="primary"
style={{ width: '100px' }}
onClick={this.runQuery.bind(this)}
onClick={this.runQuery.bind(this, false)}
disabled={!(this.props.queryEditor.dbId)}
>
<i className="fa fa-table" /> Run Query
</Button>
);
}
if (this.props.database && this.props.database.allow_run_async) {
runButtons.push(
<Button
bsSize="small"
bsStyle="primary"
style={{ width: '100px' }}
onClick={this.runQuery.bind(this, true)}
disabled={!(this.props.queryEditor.dbId)}
>
<i className="fa fa-table" /> Run Async
</Button>
);
}
runButtons = (
<ButtonGroup bsSize="small" className="inline m-r-5 pull-left">
{runButtons}
</ButtonGroup>
);
if (this.props.latestQuery && this.props.latestQuery.state === 'running') {
@@ -176,35 +192,6 @@ class SqlEditor extends React.Component {
</ButtonGroup>
);
}
const rightButtons = (
<ButtonGroup className="inlineblock">
<ButtonWithTooltip
tooltip="Save this query in your workspace"
placement="left"
bsSize="small"
onClick={this.addWorkspaceQuery.bind(this)}
>
<i className="fa fa-save" />&nbsp;
</ButtonWithTooltip>
<DropdownButton
id="ddbtn-export"
pullRight
bsSize="small"
title={<i className="fa fa-file-o" />}
>
<MenuItem
onClick={this.notImplemented}
>
<i className="fa fa-file-text-o" /> export to .csv
</MenuItem>
<MenuItem
onClick={this.notImplemented}
>
<i className="fa fa-file-code-o" /> export to .json
</MenuItem>
</DropdownButton>
</ButtonGroup>
);
let limitWarning = null;
const rowLimit = 1000;
if (this.props.latestQuery && this.props.latestQuery.rows === rowLimit) {
@@ -256,7 +243,6 @@ class SqlEditor extends React.Component {
<div className="pull-right">
{limitWarning}
<Timer query={this.props.latestQuery} />
{rightButtons}
</div>
</div>
);

View File

@@ -77,7 +77,12 @@ class SqlEditorTopToolbar extends React.Component {
}
fetchDatabaseOptions() {
this.setState({ databaseLoading: true });
const url = '/databaseasync/api/read?_flt_0_expose_in_sqllab=1';
const url = (
'/databaseasync/api/read?' +
'_flt_0_expose_in_sqllab=1&' +
'_oc_DatabaseAsync=database_name&' +
'_od_DatabaseAsync=asc'
);
$.get(url, (data) => {
const options = data.result.map((db) => ({ value: db.id, label: db.database_name }));
this.props.actions.setDatabases(data.result);

View File

@@ -63,12 +63,12 @@ class TableElement extends React.Component {
metadata = (
<div>
{this.props.table.columns.map((col) => (
<div className="row">
<div className="col-sm-8">
<div className="m-l-5">{col.name}</div>
<div className="clearfix">
<div className="pull-left m-l-10">
{col.name}
</div>
<div className="col-sm-4">
<div className="pull-right text-muted"><small>{col.type}</small></div>
<div className="pull-right text-muted">
<small> {col.type}</small>
</div>
</div>
))}
@@ -88,11 +88,11 @@ class TableElement extends React.Component {
}
return (
<div>
<div className="row">
<div className="col-sm-9 m-b-10">
<div className="clearfix">
<div className="pull-left">
{buttonToggle}
</div>
<div className="col-sm-3">
<div className="pull-right">
<ButtonGroup className="ws-el-controls pull-right">
<Link
className="fa fa-pencil pull-left m-l-2"

View File

@@ -27,8 +27,8 @@ class Timer extends React.Component {
}
stopwatch() {
if (this.props && this.props.query) {
const since = this.props.query.endDttm || now();
const clockStr = fDuration(this.props.query.startDttm, since);
const endDttm = this.props.query.endDttm || now();
const clockStr = fDuration(this.props.query.startDttm, endDttm);
this.setState({ clockStr });
if (this.props.query.state !== 'running') {
this.stopTimer();