From 5392073f3807a20ee6356e7d55ca3ee0b3080720 Mon Sep 17 00:00:00 2001 From: vera-liu Date: Wed, 11 Jan 2017 10:31:30 -0800 Subject: [PATCH] Add a Async Select that fetches options from given endpoint (#1909) * Add a Async Select that fetches options from given endpoint * update it statement --- .../SqlLab/components/DatabaseSelect.jsx | 61 ------------------- .../SqlLab/components/QuerySearch.jsx | 50 +++++++-------- .../SqlLab/components/SqlEditorLeftBar.jsx | 21 +++++-- .../javascripts/components/AsyncSelect.jsx | 59 ++++++++++++++++++ .../AsyncSelect_spec.jsx} | 17 +++--- .../javascripts/sqllab/QuerySearch_spec.jsx | 10 +-- 6 files changed, 112 insertions(+), 106 deletions(-) delete mode 100644 superset/assets/javascripts/SqlLab/components/DatabaseSelect.jsx create mode 100644 superset/assets/javascripts/components/AsyncSelect.jsx rename superset/assets/spec/javascripts/{sqllab/DatabaseSelect_spec.jsx => components/AsyncSelect_spec.jsx} (58%) diff --git a/superset/assets/javascripts/SqlLab/components/DatabaseSelect.jsx b/superset/assets/javascripts/SqlLab/components/DatabaseSelect.jsx deleted file mode 100644 index 49cbba0159b8e..0000000000000 --- a/superset/assets/javascripts/SqlLab/components/DatabaseSelect.jsx +++ /dev/null @@ -1,61 +0,0 @@ -const $ = window.$ = require('jquery'); -import React from 'react'; -import Select from 'react-select'; - -const propTypes = { - onChange: React.PropTypes.func, - actions: React.PropTypes.object, - databaseId: React.PropTypes.number, - valueRenderer: React.PropTypes.func, -}; - -class DatabaseSelect extends React.PureComponent { - constructor(props) { - super(props); - this.state = { - databaseLoading: false, - databaseOptions: [], - }; - } - componentDidMount() { - this.fetchDatabaseOptions(); - } - changeDb(db) { - this.props.onChange(db); - } - fetchDatabaseOptions() { - this.setState({ databaseLoading: true }); - 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.setState({ databaseOptions: options, databaseLoading: false }); - this.props.actions.setDatabases(data.result); - if (data.result.length === 0) { - this.props.actions.addAlert({ - bsStyle: 'danger', - msg: "It seems you don't have access to any database", - }); - } - }); - } - render() { - return ( -
-
-
diff --git a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx index 5c5eacf782918..21d5f2bfceecc 100644 --- a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx +++ b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx @@ -3,7 +3,7 @@ import React from 'react'; import Select from 'react-select'; import { Label, Button } from 'react-bootstrap'; import TableElement from './TableElement'; -import DatabaseSelect from './DatabaseSelect'; +import AsyncSelect from '../../components/AsyncSelect'; const propTypes = { queryEditor: React.PropTypes.object.isRequired, @@ -44,6 +44,17 @@ class SqlEditorLeftBar extends React.PureComponent { this.fetchSchemas(val); } } + dbMutator(data) { + const options = data.result.map((db) => ({ value: db.id, label: db.database_name })); + this.props.actions.setDatabases(data.result); + if (data.result.length === 0) { + this.props.actions.addAlert({ + bsStyle: 'danger', + msg: "It seems you don't have access to any database", + }); + } + return options; + } resetState() { this.props.actions.resetState(); } @@ -103,15 +114,17 @@ class SqlEditorLeftBar extends React.PureComponent {
{networkAlert}
- (
Database: {o.label}
)} + mutator={this.dbMutator.bind(this)} + placeholder="Select a database" />
diff --git a/superset/assets/javascripts/components/AsyncSelect.jsx b/superset/assets/javascripts/components/AsyncSelect.jsx new file mode 100644 index 0000000000000..fbf988c48d7cb --- /dev/null +++ b/superset/assets/javascripts/components/AsyncSelect.jsx @@ -0,0 +1,59 @@ +const $ = window.$ = require('jquery'); +import React from 'react'; +import Select from 'react-select'; + +const propTypes = { + dataEndpoint: React.PropTypes.string.isRequired, + onChange: React.PropTypes.func.isRequired, + mutator: React.PropTypes.func.isRequired, + value: React.PropTypes.number, + valueRenderer: React.PropTypes.func, + placeholder: React.PropTypes.string, +}; + +const defaultProps = { + placeholder: 'Select ...', + valueRenderer: (o) => (
{o.label}
), +}; + +class AsyncSelect extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + isLoading: false, + options: [], + }; + } + componentDidMount() { + this.fetchOptions(); + } + fetchOptions() { + this.setState({ isLoading: true }); + const mutator = this.props.mutator; + $.get(this.props.dataEndpoint, (data) => { + this.setState({ options: mutator ? mutator(data) : data, isLoading: false }); + }); + } + onChange(opt) { + this.props.onChange(opt); + } + render() { + return ( +
+