mirror of
https://github.com/apache/superset.git
synced 2026-04-21 09:04:38 +00:00
[sqllab] optimizing React (#1438)
* [sqllab] optimizing React * Addressing comments and making npm run dev faster
This commit is contained in:
committed by
GitHub
parent
64d196442f
commit
b24206387b
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import AceEditor from 'react-ace';
|
||||
import 'brace/mode/sql';
|
||||
import 'brace/theme/github';
|
||||
import 'brace/ext/language_tools';
|
||||
|
||||
const propTypes = {
|
||||
sql: React.PropTypes.string.isRequired,
|
||||
onBlur: React.PropTypes.func,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
onBlur: () => {},
|
||||
};
|
||||
|
||||
class AceEditorWrapper extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sql: props.sql,
|
||||
};
|
||||
}
|
||||
textChange(text) {
|
||||
this.setState({ sql: text });
|
||||
}
|
||||
onBlur() {
|
||||
this.props.onBlur(this.state.sql);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<AceEditor
|
||||
mode="sql"
|
||||
theme="github"
|
||||
onBlur={this.onBlur.bind(this)}
|
||||
minLines={8}
|
||||
maxLines={30}
|
||||
onChange={this.textChange.bind(this)}
|
||||
height="200px"
|
||||
width="100%"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
enableBasicAutocompletion
|
||||
value={this.state.sql}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
AceEditorWrapper.defaultProps = defaultProps;
|
||||
AceEditorWrapper.propTypes = propTypes;
|
||||
|
||||
export default AceEditorWrapper;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
|
||||
class Alerts extends React.Component {
|
||||
class Alerts extends React.PureComponent {
|
||||
removeAlert(alert) {
|
||||
this.props.actions.removeAlert(alert);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import DataPreviewModal from './DataPreviewModal';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
class App extends React.Component {
|
||||
class App extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -10,7 +10,7 @@ const defaultProps = {
|
||||
queryEditor: null,
|
||||
};
|
||||
|
||||
export default class CopyQueryTabUrl extends React.Component {
|
||||
export default class CopyQueryTabUrl extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -13,7 +13,7 @@ const propTypes = {
|
||||
dataPreviewQueryId: React.PropTypes.string,
|
||||
};
|
||||
|
||||
class DataPreviewModal extends React.Component {
|
||||
class DataPreviewModal extends React.PureComponent {
|
||||
hide() {
|
||||
this.props.actions.hideDataPreview();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ const $ = window.$ = require('jquery');
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
|
||||
class DatabaseSelect extends React.Component {
|
||||
class DatabaseSelect extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -20,7 +20,7 @@ const defaultProps = {
|
||||
};
|
||||
|
||||
|
||||
class Link extends React.Component {
|
||||
class Link extends React.PureComponent {
|
||||
render() {
|
||||
let tooltip = (
|
||||
<Tooltip id="tooltip">
|
||||
|
||||
@@ -7,7 +7,7 @@ const $ = require('jquery');
|
||||
const QUERY_UPDATE_FREQ = 1000;
|
||||
const QUERY_UPDATE_BUFFER_MS = 5000;
|
||||
|
||||
class QueryAutoRefresh extends React.Component {
|
||||
class QueryAutoRefresh extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
this.startTimer();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const propTypes = {
|
||||
actions: React.PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
class QuerySearch extends React.Component {
|
||||
class QuerySearch extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -27,7 +27,7 @@ const defaultProps = {
|
||||
};
|
||||
|
||||
|
||||
class QueryTable extends React.Component {
|
||||
class QueryTable extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const uri = window.location.toString();
|
||||
|
||||
@@ -25,7 +25,7 @@ const defaultProps = {
|
||||
};
|
||||
|
||||
|
||||
class ResultSet extends React.Component {
|
||||
class ResultSet extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Alert, Tab, Tabs } from 'react-bootstrap';
|
||||
import QueryHistory from './QueryHistory';
|
||||
import ResultSet from './ResultSet';
|
||||
import { areArraysShallowEqual } from '../../reduxUtils';
|
||||
import React from 'react';
|
||||
|
||||
import shortid from 'shortid';
|
||||
@@ -10,32 +11,40 @@ const propTypes = {
|
||||
actions: React.PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
const SouthPane = function (props) {
|
||||
let latestQuery;
|
||||
if (props.queries.length > 0) {
|
||||
latestQuery = props.queries[props.queries.length - 1];
|
||||
class SouthPane extends React.PureComponent {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !areArraysShallowEqual(this.props.queries, nextProps.queries);
|
||||
}
|
||||
let results;
|
||||
if (latestQuery) {
|
||||
results = <ResultSet showControls search query={latestQuery} actions={props.actions} />;
|
||||
} else {
|
||||
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
|
||||
render() {
|
||||
let latestQuery;
|
||||
const props = this.props;
|
||||
if (props.queries.length > 0) {
|
||||
latestQuery = props.queries[props.queries.length - 1];
|
||||
}
|
||||
let results;
|
||||
if (latestQuery) {
|
||||
results = (
|
||||
<ResultSet showControls search query={latestQuery} actions={props.actions} />
|
||||
);
|
||||
} else {
|
||||
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
|
||||
}
|
||||
return (
|
||||
<div className="SouthPane">
|
||||
<Tabs bsStyle="tabs" id={shortid.generate()}>
|
||||
<Tab title="Results" eventKey={1}>
|
||||
<div style={{ overflow: 'auto' }}>
|
||||
{results}
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab title="Query History" eventKey={2}>
|
||||
<QueryHistory queries={props.queries} actions={props.actions} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="SouthPane">
|
||||
<Tabs bsStyle="tabs" id={shortid.generate()}>
|
||||
<Tab title="Results" eventKey={1}>
|
||||
<div style={{ overflow: 'auto' }}>
|
||||
{results}
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab title="Query History" eventKey={2}>
|
||||
<QueryHistory queries={props.queries} actions={props.actions} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
SouthPane.propTypes = propTypes;
|
||||
|
||||
export default SouthPane;
|
||||
|
||||
@@ -13,16 +13,11 @@ import {
|
||||
Tooltip,
|
||||
} from 'react-bootstrap';
|
||||
|
||||
import AceEditor from 'react-ace';
|
||||
import 'brace/mode/sql';
|
||||
import 'brace/theme/github';
|
||||
import 'brace/ext/language_tools';
|
||||
|
||||
import shortid from 'shortid';
|
||||
import SouthPane from './SouthPane';
|
||||
import Timer from './Timer';
|
||||
|
||||
import SqlEditorLeftBar from './SqlEditorLeftBar';
|
||||
import AceEditorWrapper from './AceEditorWrapper';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object.isRequired,
|
||||
@@ -41,12 +36,11 @@ const defaultProps = {
|
||||
};
|
||||
|
||||
|
||||
class SqlEditor extends React.Component {
|
||||
class SqlEditor extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
autorun: props.queryEditor.autorun,
|
||||
sql: props.queryEditor.sql,
|
||||
ctas: '',
|
||||
};
|
||||
}
|
||||
@@ -82,16 +76,12 @@ class SqlEditor extends React.Component {
|
||||
createTableAs() {
|
||||
this.startQuery(true, true);
|
||||
}
|
||||
textChange(text) {
|
||||
this.setState({ sql: text });
|
||||
this.props.actions.queryEditorSetSql(this.props.queryEditor, text);
|
||||
setQueryEditorSql(sql) {
|
||||
this.props.actions.queryEditorSetSql(this.props.queryEditor, sql);
|
||||
}
|
||||
ctasChange() {}
|
||||
visualize() {}
|
||||
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;
|
||||
@@ -110,7 +100,7 @@ class SqlEditor extends React.Component {
|
||||
style={{ width: '100px' }}
|
||||
onClick={this.runQuery.bind(this, false)}
|
||||
disabled={!(this.props.queryEditor.dbId)}
|
||||
key={shortid.generate()}
|
||||
key="run-btn"
|
||||
>
|
||||
<i className="fa fa-table" /> Run Query
|
||||
</Button>
|
||||
@@ -124,7 +114,7 @@ class SqlEditor extends React.Component {
|
||||
style={{ width: '100px' }}
|
||||
onClick={this.runQuery.bind(this, true)}
|
||||
disabled={!(this.props.queryEditor.dbId)}
|
||||
key={shortid.generate()}
|
||||
key="run-async-btn"
|
||||
>
|
||||
<i className="fa fa-table" /> Run Async
|
||||
</Button>
|
||||
@@ -217,18 +207,9 @@ class SqlEditor extends React.Component {
|
||||
/>
|
||||
</Col>
|
||||
<Col md={9}>
|
||||
<AceEditor
|
||||
mode="sql"
|
||||
name={this.props.queryEditor.id}
|
||||
theme="github"
|
||||
minLines={7}
|
||||
maxLines={30}
|
||||
onChange={this.textChange.bind(this)}
|
||||
height="200px"
|
||||
width="100%"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
enableBasicAutocompletion
|
||||
value={this.props.queryEditor.sql}
|
||||
<AceEditorWrapper
|
||||
sql={this.props.queryEditor.sql}
|
||||
onBlur={this.setQueryEditorSql.bind(this)}
|
||||
/>
|
||||
{editorBottomBar}
|
||||
<br />
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
import React from 'react';
|
||||
|
||||
import Select from 'react-select';
|
||||
import { Label, Button } from 'react-bootstrap';
|
||||
import TableElement from './TableElement';
|
||||
@@ -19,7 +18,7 @@ const defaultProps = {
|
||||
actions: {},
|
||||
};
|
||||
|
||||
class SqlEditorLeftBar extends React.Component {
|
||||
class SqlEditorLeftBar extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -27,6 +26,7 @@ class SqlEditorLeftBar extends React.Component {
|
||||
schemaOptions: [],
|
||||
tableLoading: false,
|
||||
tableOptions: [],
|
||||
networkOn: true,
|
||||
};
|
||||
}
|
||||
componentWillMount() {
|
||||
@@ -92,8 +92,8 @@ class SqlEditorLeftBar extends React.Component {
|
||||
this.setState({ tableLoading: true });
|
||||
$.get(url, (data) => {
|
||||
this.props.actions.mergeTable(Object.assign(data, {
|
||||
dbId: this.props.queryEditor.dbId,
|
||||
queryEditorId: this.props.queryEditor.id,
|
||||
dbId: qe.dbId,
|
||||
queryEditorId: qe.id,
|
||||
schema: qe.schema,
|
||||
expanded: true,
|
||||
}));
|
||||
@@ -163,7 +163,6 @@ class SqlEditorLeftBar extends React.Component {
|
||||
isLoading={this.state.tableLoading}
|
||||
placeholder={`Add a table (${this.state.tableOptions.length})`}
|
||||
autosize={false}
|
||||
value={this.state.tableName}
|
||||
onChange={this.changeTable.bind(this)}
|
||||
options={this.state.tableOptions}
|
||||
/>
|
||||
@@ -173,7 +172,6 @@ class SqlEditorLeftBar extends React.Component {
|
||||
{this.props.tables.map((table) => (
|
||||
<TableElement
|
||||
table={table}
|
||||
queryEditor={this.props.queryEditor}
|
||||
key={table.id}
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
|
||||
@@ -23,7 +23,7 @@ const defaultProps = {
|
||||
|
||||
let queryCount = 1;
|
||||
|
||||
class TabbedSqlEditors extends React.Component {
|
||||
class TabbedSqlEditors extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const uri = window.location.toString();
|
||||
|
||||
@@ -9,7 +9,6 @@ import ModalTrigger from '../../components/ModalTrigger';
|
||||
|
||||
const propTypes = {
|
||||
table: React.PropTypes.object,
|
||||
queryEditor: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
};
|
||||
|
||||
@@ -18,7 +17,7 @@ const defaultProps = {
|
||||
actions: {},
|
||||
};
|
||||
|
||||
class TableElement extends React.Component {
|
||||
class TableElement extends React.PureComponent {
|
||||
|
||||
popSelectStar() {
|
||||
const qe = {
|
||||
@@ -46,7 +45,7 @@ class TableElement extends React.Component {
|
||||
}
|
||||
dataPreviewModal() {
|
||||
const query = {
|
||||
dbId: this.props.queryEditor.dbId,
|
||||
dbId: this.props.table.dbId,
|
||||
sql: this.props.table.selectStar,
|
||||
tableName: this.props.table.name,
|
||||
sqlEditorId: null,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { now, fDuration } from '../../modules/dates';
|
||||
|
||||
import { STATE_BSSTYLE_MAP } from '../common.js';
|
||||
|
||||
class Timer extends React.Component {
|
||||
class Timer extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
@@ -23,7 +23,7 @@ const defaultProps = {
|
||||
onHide: () => {},
|
||||
};
|
||||
|
||||
class VisualizeModal extends React.Component {
|
||||
class VisualizeModal extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const uniqueId = shortid.generate();
|
||||
|
||||
Reference in New Issue
Block a user