diff --git a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx index 1053222dac..75cb64c99e 100644 --- a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx @@ -58,6 +58,7 @@ class ChartContainer extends React.PureComponent { componentDidUpdate(prevProps) { if ( + this.props.queryResponse && ( prevProps.queryResponse !== this.props.queryResponse || prevProps.height !== this.props.height || diff --git a/superset/assets/javascripts/explorev2/components/Control.jsx b/superset/assets/javascripts/explorev2/components/Control.jsx index ca8ead8609..2c503ff327 100644 --- a/superset/assets/javascripts/explorev2/components/Control.jsx +++ b/superset/assets/javascripts/explorev2/components/Control.jsx @@ -48,8 +48,12 @@ export default class Control extends React.PureComponent { super(props); this.validate = this.validate.bind(this); this.onChange = this.onChange.bind(this); + this.validateAndSetValue(props.value, []); } onChange(value, errors) { + this.validateAndSetValue(value, errors); + } + validateAndSetValue(value, errors) { let validationErrors = this.validate(value); if (errors && errors.length > 0) { validationErrors = validationErrors.concat(errors); diff --git a/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx b/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx index b57b6e6ea5..093f26db4a 100644 --- a/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx @@ -47,7 +47,7 @@ class ExploreViewContainer extends React.Component { } componentDidUpdate() { - if (this.props.triggerQuery) { + if (this.props.triggerQuery && !this.hasErrors()) { this.runQuery(); } } @@ -95,6 +95,10 @@ class ExploreViewContainer extends React.Component { toggleModal() { this.setState({ showModal: !this.state.showModal }); } + hasErrors() { + const ctrls = this.props.controls; + return Object.keys(ctrls).some(k => ctrls[k].validationErrors.length > 0); + } renderErrorMessage() { // Returns an error message as a node if any errors are in the store const errors = []; diff --git a/superset/assets/javascripts/explorev2/components/QueryAndSaveBtns.jsx b/superset/assets/javascripts/explorev2/components/QueryAndSaveBtns.jsx index 812e670f48..023ce98c38 100644 --- a/superset/assets/javascripts/explorev2/components/QueryAndSaveBtns.jsx +++ b/superset/assets/javascripts/explorev2/components/QueryAndSaveBtns.jsx @@ -9,7 +9,7 @@ const propTypes = { onSave: PropTypes.func, onStop: PropTypes.func, loading: PropTypes.bool, - errorMessage: PropTypes.string, + errorMessage: PropTypes.node, }; const defaultProps = { @@ -37,6 +37,7 @@ export default function QueryAndSaveBtns( className="query" onClick={onQuery} bsStyle={qryButtonStyle} + disabled={!!errorMessage} > Query diff --git a/superset/assets/javascripts/explorev2/index.jsx b/superset/assets/javascripts/explorev2/index.jsx index f2757eb5e6..e72b8c3941 100644 --- a/superset/assets/javascripts/explorev2/index.jsx +++ b/superset/assets/javascripts/explorev2/index.jsx @@ -29,7 +29,7 @@ import { exploreReducer } from './reducers/exploreReducer'; // Initial state const bootstrappedState = Object.assign( bootstrapData, { - chartStatus: 'loading', + chartStatus: null, chartUpdateEndTime: null, chartUpdateStartTime: now(), dashboards: [], diff --git a/superset/assets/javascripts/explorev2/stores/visTypes.js b/superset/assets/javascripts/explorev2/stores/visTypes.js index a82665dcb4..e28a4ccdcf 100644 --- a/superset/assets/javascripts/explorev2/stores/visTypes.js +++ b/superset/assets/javascripts/explorev2/stores/visTypes.js @@ -255,10 +255,6 @@ const visTypes = { }, ], controlOverrides: { - metrics: { - default: null, - validators: null, - }, time_grain_sqla: { default: null, }, diff --git a/superset/viz.py b/superset/viz.py index ae440ef949..6538a25e43 100755 --- a/superset/viz.py +++ b/superset/viz.py @@ -112,7 +112,7 @@ class BaseViz(object): """Building a query object""" form_data = self.form_data groupby = form_data.get("groupby") or [] - metrics = form_data.get("metrics") or ['count'] + metrics = form_data.get("metrics") or [] # extra_filters are temporary/contextual filters that are external # to the slice definition. We use those for dynamic interactive