diff --git a/superset/assets/javascripts/SqlLab/components/RunQueryActionButton.jsx b/superset/assets/javascripts/SqlLab/components/RunQueryActionButton.jsx
new file mode 100644
index 0000000000000..d117318460b59
--- /dev/null
+++ b/superset/assets/javascripts/SqlLab/components/RunQueryActionButton.jsx
@@ -0,0 +1,71 @@
+import React, { PropTypes } from 'react';
+import Button from '../../components/Button';
+
+const propTypes = {
+ allowAsync: PropTypes.bool.isRequired,
+ dbId: PropTypes.number.isRequired,
+ queryState: PropTypes.string.isRequired,
+ runQuery: PropTypes.func.isRequired,
+ selectedText: PropTypes.string,
+ stopQuery: PropTypes.func.isRequired,
+};
+
+export default function RunQueryActionButton(props) {
+ const runBtnText = props.selectedText ? 'Run Selected Query' : 'Run Query';
+ const btnStyle = props.selectedText ? 'warning' : 'primary';
+ const shouldShowStopBtn = ['running', 'pending'].indexOf(props.queryState) > -1;
+ const asyncToolTip = 'Run query asynchronously';
+
+ const commonBtnProps = {
+ bsSize: 'small',
+ bsStyle: btnStyle,
+ disabled: !(props.dbId),
+ };
+
+ const syncBtn = (
+
+ );
+
+ const asyncBtn = (
+
+ );
+
+ const stopBtn = (
+
+ );
+
+ let button;
+ if (shouldShowStopBtn) {
+ button = stopBtn;
+ } else if (props.allowAsync) {
+ button = asyncBtn;
+ } else {
+ button = syncBtn;
+ }
+
+ return (
+
+ {button}
+
+ );
+}
+
+RunQueryActionButton.propTypes = propTypes;
diff --git a/superset/assets/javascripts/SqlLab/components/SqlEditor.jsx b/superset/assets/javascripts/SqlLab/components/SqlEditor.jsx
index 6daba5857e7ed..aacb21681257f 100644
--- a/superset/assets/javascripts/SqlLab/components/SqlEditor.jsx
+++ b/superset/assets/javascripts/SqlLab/components/SqlEditor.jsx
@@ -1,7 +1,5 @@
import React from 'react';
import {
- Button as BootstrapButton,
- ButtonGroup,
Col,
FormGroup,
InputGroup,
@@ -21,6 +19,7 @@ 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,
@@ -104,64 +103,6 @@ class SqlEditor extends React.PureComponent {
}
render() {
- let runButtons = [];
- let runText = 'Run Query';
- let btnStyle = 'primary';
- if (this.props.queryEditor.selectedText) {
- runText = 'Run Selection';
- btnStyle = 'warning';
- }
- if (this.props.database && this.props.database.allow_run_sync) {
- runButtons.push(
-
- {runText}
-
- );
- }
- if (this.props.database && this.props.database.allow_run_async) {
- const asyncToolTip = 'Run query asynchronously';
- runButtons.push(
-
- );
- }
- runButtons = (
-
- {runButtons}
-
- );
- if (
- this.props.latestQuery &&
- ['running', 'pending'].indexOf(this.props.latestQuery.state) > -1) {
- runButtons = (
-
-
- Stop
-
-
- );
- }
let limitWarning = null;
if (this.props.latestQuery && this.props.latestQuery.limit_reached) {
const tooltip = (
@@ -208,7 +149,14 @@ class SqlEditor extends React.PureComponent {
diff --git a/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js b/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js
new file mode 100644
index 0000000000000..509caa969eca9
--- /dev/null
+++ b/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { expect } from 'chai';
+import { describe, it, beforeEach } from 'mocha';
+import { shallow } from 'enzyme';
+
+import RunQueryActionButton
+ from '../../../../javascripts/SqlLab/components/RunQueryActionButton';
+import Button from '../../../../javascripts/components/Button';
+
+describe('RunQueryActionButton', () => {
+ let wrapper;
+ const defaultProps = {
+ allowAsync: false,
+ dbId: 1,
+ queryState: 'pending',
+ runQuery: () => {}, // eslint-disable-line
+ selectedText: null,
+ stopQuery: () => {}, // eslint-disable-line
+ };
+
+ beforeEach(() => {
+ wrapper = shallow(
);
+ });
+
+ it('is a valid react element', () => {
+ expect(
+ React.isValidElement(
)
+ ).to.equal(true);
+ });
+
+ it('renders a single Button', () => {
+ expect(wrapper.find(Button)).to.have.lengthOf(1);
+ });
+});