[SQL Lab] Adding DB options for SQL LAb (#1054)

* [SQL Lab] Adding DB options for SQL LAb

each db can be exposed or not in SQL Lab
CTAS is an option
target_schema placeholder (not hooked yet, but would force the CTAS to
target a specific schema)

* Addressing comments
This commit is contained in:
Maxime Beauchemin
2016-09-01 14:21:46 -07:00
committed by GitHub
parent 1667d15f31
commit 4b77710016
16 changed files with 170 additions and 66 deletions

View File

@@ -15,7 +15,7 @@ class QueryAutoRefresh extends React.Component {
}
startTimer() {
if (!(this.timer)) {
this.timer = setInterval(this.stopwatch.bind(this), 5000);
this.timer = setInterval(this.stopwatch.bind(this), 1000);
}
}
stopTimer() {

View File

@@ -19,16 +19,18 @@ const SouthPane = function (props) {
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
}
return (
<Tabs bsStyle="tabs">
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>
</Tab>
<Tab title="Query History" eventKey={2}>
<QueryHistory />
</Tab>
</Tabs>
<div className="SouthPane">
<Tabs bsStyle="tabs">
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>
</Tab>
<Tab title="Query History" eventKey={2}>
<QueryHistory />
</Tab>
</Tabs>
</div>
);
};

View File

@@ -207,31 +207,37 @@ class SqlEditor extends React.Component {
</OverlayTrigger>
);
}
let ctasControls;
if (this.props.database && this.props.database.allow_ctas) {
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)}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
);
}
const editorBottomBar = (
<div className="sql-toolbar clearfix">
<div className="pull-left">
<Form inline>
{runButtons}
<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)}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
{ctasControls}
</Form>
</div>
<div className="pull-right">
@@ -276,9 +282,10 @@ class SqlEditor extends React.Component {
}
SqlEditor.propTypes = {
queryEditor: React.PropTypes.object,
actions: React.PropTypes.object,
database: React.PropTypes.object,
latestQuery: React.PropTypes.object,
queryEditor: React.PropTypes.object,
};
SqlEditor.defaultProps = {

View File

@@ -6,6 +6,7 @@ import { connect } from 'react-redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import Select from 'react-select';
import { Button } from 'react-bootstrap';
import TableElement from './TableElement';
@@ -26,6 +27,9 @@ class SqlEditorTopToolbar extends React.Component {
this.fetchSchemas();
this.fetchTables();
}
resetState() {
this.props.actions.resetState();
}
fetchTables(dbId, schema) {
const actualDbId = dbId || this.props.queryEditor.dbId;
if (actualDbId) {
@@ -73,11 +77,17 @@ class SqlEditorTopToolbar extends React.Component {
}
fetchDatabaseOptions() {
this.setState({ databaseLoading: true });
const url = '/databaseasync/api/read';
const url = '/databaseasync/api/read?_flt_0_expose_in_sqllab=1';
$.get(url, (data) => {
const options = data.result.map((db) => ({ value: db.id, label: db.database_name }));
this.props.actions.setDatabases(data.result);
this.setState({ databaseOptions: options });
this.setState({ databaseLoading: false });
// Auto select if only one option
if (options.length === 1) {
this.changeDb(options[0]);
}
});
}
closePopover(ref) {
@@ -112,7 +122,7 @@ class SqlEditorTopToolbar extends React.Component {
<div>
<Select
name="select-db"
placeholder="[Database]"
placeholder={`Select a database (${this.state.databaseOptions.length})`}
options={this.state.databaseOptions}
value={this.props.queryEditor.dbId}
isLoading={this.state.databaseLoading}
@@ -123,7 +133,7 @@ class SqlEditorTopToolbar extends React.Component {
<div className="m-t-5">
<Select
name="select-schema"
placeholder="[Schema]"
placeholder={`Select a schema (${this.state.schemaOptions.length})`}
options={this.state.schemaOptions}
value={this.props.queryEditor.schema}
isLoading={this.state.schemaLoading}
@@ -136,7 +146,7 @@ class SqlEditorTopToolbar extends React.Component {
name="select-table"
ref="selectTable"
isLoading={this.state.tableLoading}
placeholder="Add a table"
placeholder={`Add a table (${this.state.tableOptions.length})`}
autosize={false}
value={this.state.tableName}
onChange={this.changeTable.bind(this)}
@@ -149,6 +159,9 @@ class SqlEditorTopToolbar extends React.Component {
<TableElement table={table} queryEditor={this.props.queryEditor} />
))}
</div>
<Button bsSize="small" bsStyle="danger" onClick={this.resetState.bind(this)}>
<i className="fa fa-bomb" /> Reset State
</Button>
</div>
);
}

View File

@@ -48,6 +48,8 @@ class QueryEditors extends React.Component {
render() {
const editors = this.props.queryEditors.map((qe, i) => {
let latestQuery = this.props.queries[qe.latestQueryId];
const database = this.props.databases[qe.dbId];
const state = (latestQuery) ? latestQuery.state : '';
const tabTitle = (
<div>
@@ -76,6 +78,7 @@ class QueryEditors extends React.Component {
<SqlEditor
queryEditor={qe}
latestQuery={latestQuery}
database={database}
/>
</div>
</div>
@@ -95,6 +98,7 @@ class QueryEditors extends React.Component {
}
QueryEditors.propTypes = {
actions: React.PropTypes.object,
databases: React.PropTypes.object,
queries: React.PropTypes.object,
queryEditors: React.PropTypes.array,
tabHistory: React.PropTypes.array,
@@ -106,6 +110,7 @@ QueryEditors.defaultProps = {
function mapStateToProps(state) {
return {
databases: state.databases,
queryEditors: state.queryEditors,
queries: state.queries,
tabHistory: state.tabHistory,

View File

@@ -49,7 +49,7 @@ class TableElement extends React.Component {
{this.props.table.columns.map((col) => (
<div className="clearfix">
<span className="pull-left m-l-5">{col.name}</span>
<span className="pull-right">{col.type}</span>
<span className="pull-right text-muted">{col.type}</span>
</div>
))}
<hr />