This is an automated email from the ASF dual-hosted git repository.
beto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 9c8f494 A few improvements to scheduling queries (#7585)
9c8f494 is described below
commit 9c8f494c9dfcc2bf32b5aca13d6fb943fb4e9857
Author: Beto Dealmeida <[email protected]>
AuthorDate: Thu May 23 09:15:04 2019 -0700
A few improvements to scheduling queries (#7585)
* Better message for scheduling queries
* Only allow scheduling after success
* Ask for query name and description
* Use CSS instead of <br />
---
superset/assets/src/SqlLab/actions/sqlLab.js | 11 ++++
.../src/SqlLab/components/ScheduleQueryButton.jsx | 68 +++++++++++++++++++---
.../assets/src/SqlLab/components/SqlEditor.jsx | 12 +++-
.../src/SqlLab/components/TabbedSqlEditors.jsx | 4 ++
superset/config.py | 3 +-
5 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/superset/assets/src/SqlLab/actions/sqlLab.js
b/superset/assets/src/SqlLab/actions/sqlLab.js
index 81c8e8d..9c5a9d0 100644
--- a/superset/assets/src/SqlLab/actions/sqlLab.js
+++ b/superset/assets/src/SqlLab/actions/sqlLab.js
@@ -107,6 +107,17 @@ export function saveQuery(query) {
.catch(() => dispatch(addDangerToast(t('Your query could not be
saved'))));
}
+export function scheduleQuery(query) {
+ return dispatch =>
+ SupersetClient.post({
+ endpoint: '/savedqueryviewapi/api/create',
+ postPayload: query,
+ stringify: false,
+ })
+ .then(() => dispatch(addSuccessToast(t('Your query has been scheduled.
To see details of your query, navigate to Saved Queries'))))
+ .catch(() => dispatch(addDangerToast(t('Your query could not be
scheduled'))));
+}
+
export function startQuery(query) {
Object.assign(query, {
id: query.id ? query.id : shortid.generate(),
diff --git a/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
b/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
index 99ecaa5..d8f82fb 100644
--- a/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
+++ b/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
@@ -20,6 +20,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import Form from 'react-jsonschema-form';
import chrono from 'chrono-node';
+import { Col, FormControl, FormGroup, Row } from 'react-bootstrap';
import { t } from '@superset-ui/translation';
import Button from '../../components/Button';
@@ -76,11 +77,17 @@ const propTypes = {
dbId: PropTypes.number.isRequired,
animation: PropTypes.bool,
onSchedule: PropTypes.func,
+ scheduleQueryWarning: PropTypes.string,
+ disabled: PropTypes.bool,
+ tooltip: PropTypes.string,
};
const defaultProps = {
defaultLabel: t('Undefined'),
animation: true,
onSchedule: () => {},
+ scheduleQueryWarning: null,
+ disabled: false,
+ tooltip: null,
};
class ScheduleQueryButton extends React.PureComponent {
@@ -123,12 +130,53 @@ class ScheduleQueryButton extends React.PureComponent {
}
renderModalBody() {
return (
- <Form
- schema={getJSONSchema()}
- uiSchema={getUISchema()}
- onSubmit={this.onSchedule}
- validate={getValidator()}
- />
+ <FormGroup>
+ <Row style={{ paddingBottom: '10px' }}>
+ <Col md={12}>
+ <label className="control-label" htmlFor="embed-height">
+ {t('Label')}
+ </label>
+ <FormControl
+ type="text"
+ placeholder={t('Label for your query')}
+ value={this.state.label}
+ onChange={this.onLabelChange}
+ />
+ </Col>
+ </Row>
+ <Row style={{ paddingBottom: '10px' }}>
+ <Col md={12}>
+ <label className="control-label" htmlFor="embed-height">
+ {t('Description')}
+ </label>
+ <FormControl
+ componentClass="textarea"
+ placeholder={t('Write a description for your query')}
+ value={this.state.description}
+ onChange={this.onDescriptionChange}
+ />
+ </Col>
+ </Row>
+ <Row>
+ <Col md={12}>
+ <Form
+ schema={getJSONSchema()}
+ uiSchema={getUISchema()}
+ onSubmit={this.onSchedule}
+ validate={getValidator()}
+ />
+ </Col>
+ </Row>
+ {this.props.scheduleQueryWarning && (
+ <Row>
+ <Col md={12}>
+ <small>
+ {this.props.scheduleQueryWarning}
+ </small>
+ </Col>
+ </Row>
+ )}
+ </FormGroup>
);
}
render() {
@@ -139,7 +187,13 @@ class ScheduleQueryButton extends React.PureComponent {
modalTitle={t('Schedule Query')}
modalBody={this.renderModalBody()}
triggerNode={
- <Button bsSize="small" className="toggleSchedule"
onClick={this.toggleSchedule}>
+ <Button
+ bsSize="small"
+ className="toggleSchedule"
+ onClick={this.toggleSchedule}
+ disabled={this.props.disabled}
+ tooltip={this.props.tooltip}
+ >
<i className="fa fa-calendar" /> {t('Schedule Query')}
</Button>
}
diff --git a/superset/assets/src/SqlLab/components/SqlEditor.jsx
b/superset/assets/src/SqlLab/components/SqlEditor.jsx
index 0b25dcf..a4aabb7 100644
--- a/superset/assets/src/SqlLab/components/SqlEditor.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditor.jsx
@@ -67,13 +67,14 @@ const propTypes = {
defaultQueryLimit: PropTypes.number.isRequired,
maxRow: PropTypes.number.isRequired,
saveQueryWarning: PropTypes.string,
+ scheduleQueryWarning: PropTypes.string,
};
const defaultProps = {
database: null,
latestQuery: null,
hideLeftBar: false,
- saveQueryWarning: null,
+ scheduleQueryWarning: null,
};
class SqlEditor extends React.PureComponent {
@@ -334,6 +335,10 @@ class SqlEditor extends React.PureComponent {
</OverlayTrigger>
);
}
+ const successful = this.props.latestQuery && this.props.latestQuery.state
=== 'success';
+ const scheduleToolTip = successful
+ ? t('Schedule the query periodically')
+ : t('You must run the query successfully first');
return (
<div className="sql-toolbar" id="js-sql-toolbar">
<div>
@@ -355,9 +360,12 @@ class SqlEditor extends React.PureComponent {
defaultLabel={qe.title}
sql={qe.sql}
className="m-r-5"
- onSchedule={this.props.actions.saveQuery}
+ onSchedule={this.props.actions.scheduleQuery}
schema={qe.schema}
dbId={qe.dbId}
+ scheduleQueryWarning={this.props.scheduleQueryWarning}
+ tooltip={scheduleToolTip}
+ disabled={!successful}
/>
</span>
}
diff --git a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
index a8516f1..7c32021 100644
--- a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
+++ b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
@@ -41,11 +41,13 @@ const propTypes = {
tables: PropTypes.array.isRequired,
offline: PropTypes.bool,
saveQueryWarning: PropTypes.string,
+ scheduleQueryWarning: PropTypes.string,
};
const defaultProps = {
queryEditors: [],
offline: false,
saveQueryWarning: null,
+ scheduleQueryWarning: null,
};
let queryCount = 1;
@@ -250,6 +252,7 @@ class TabbedSqlEditors extends React.PureComponent {
defaultQueryLimit={this.props.defaultQueryLimit}
maxRow={this.props.maxRow}
saveQueryWarning={this.props.saveQueryWarning}
+ scheduleQueryWarning={this.props.scheduleQueryWarning}
/>
)}
</Tab>
@@ -294,6 +297,7 @@ function mapStateToProps({ sqlLab, common }) {
defaultQueryLimit: common.conf.DEFAULT_SQLLAB_LIMIT,
maxRow: common.conf.SQL_MAX_ROW,
saveQueryWarning: common.conf.SQLLAB_SAVE_WARNING_MESSAGE,
+ scheduleQueryWarning: common.conf.SQLLAB_SCHEDULE_WARNING_MESSAGE,
};
}
function mapDispatchToProps(dispatch) {
diff --git a/superset/config.py b/superset/config.py
index 5f9bd8a..fc287b7 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -357,8 +357,9 @@ DEFAULT_SQLLAB_LIMIT = 1000
# Maximum number of tables/views displayed in the dropdown window in SQL Lab.
MAX_TABLE_NAMES = 3000
-# Adds a warning message on sqllab save query modal.
+# Adds a warning message on sqllab save query and schedule query modals.
SQLLAB_SAVE_WARNING_MESSAGE = None
+SQLLAB_SCHEDULE_WARNING_MESSAGE = None
# If defined, shows this text in an alert-warning box in the navbar
# one example use case may be "STAGING" to make it clear that this is