diff --git a/superset/assets/javascripts/explorev2/components/DisplayQueryButton.jsx b/superset/assets/javascripts/explorev2/components/DisplayQueryButton.jsx index 1912016b4a..3ac6a2eb36 100644 --- a/superset/assets/javascripts/explorev2/components/DisplayQueryButton.jsx +++ b/superset/assets/javascripts/explorev2/components/DisplayQueryButton.jsx @@ -46,11 +46,12 @@ export default class DisplayQueryButton extends React.PureComponent { language: data.language, query: data.query, isLoading: false, + error: null, }); }, error: (data) => { this.setState({ - error: data.error, + error: data.responseJSON ? data.responseJSON.error : 'Error...', isLoading: false, }); }, diff --git a/superset/assets/javascripts/explorev2/components/controls/Filter.jsx b/superset/assets/javascripts/explorev2/components/controls/Filter.jsx index a7dc1f0841..cf29a2b084 100644 --- a/superset/assets/javascripts/explorev2/components/controls/Filter.jsx +++ b/superset/assets/javascripts/explorev2/components/controls/Filter.jsx @@ -8,12 +8,12 @@ const $ = window.$ = require('jquery'); const operatorsArr = [ { val: 'in', type: 'array', useSelect: true, multi: true }, { val: 'not in', type: 'array', useSelect: true, multi: true }, - { val: '==', type: 'string', useSelect: true, multi: false }, - { val: '!=', type: 'string', useSelect: true, multi: false }, - { val: '>=', type: 'string' }, - { val: '<=', type: 'string' }, - { val: '>', type: 'string' }, - { val: '<', type: 'string' }, + { val: '==', type: 'string', useSelect: true, multi: false, havingOnly: true }, + { val: '!=', type: 'string', useSelect: true, multi: false, havingOnly: true }, + { val: '>=', type: 'string', havingOnly: true }, + { val: '<=', type: 'string', havingOnly: true }, + { val: '>', type: 'string', havingOnly: true }, + { val: '<', type: 'string', havingOnly: true }, { val: 'regex', type: 'string', datasourceTypes: ['druid'] }, { val: 'LIKE', type: 'string', datasourceTypes: ['table'] }, ]; @@ -27,12 +27,14 @@ const propTypes = { removeFilter: PropTypes.func, filter: PropTypes.object.isRequired, datasource: PropTypes.object, + having: PropTypes.bool, }; const defaultProps = { changeFilter: () => {}, removeFilter: () => {}, datasource: null, + having: false, }; export default class Filter extends React.Component { @@ -47,7 +49,7 @@ export default class Filter extends React.Component { } fetchFilterValues(col) { const datasource = this.props.datasource; - if (col && this.props.datasource && this.props.datasource.filter_select) { + if (col && this.props.datasource && this.props.datasource.filter_select && !this.props.having) { this.setState({ valuesLoading: true }); $.ajax({ type: 'GET', @@ -90,7 +92,7 @@ export default class Filter extends React.Component { } renderFilterFormControl(filter) { const operator = operators[filter.op]; - if (operator.useSelect) { + if (operator.useSelect && !this.props.having) { return ( !o.datasourceTypes || o.datasourceTypes.indexOf(datasource.type) >= 0) + .filter((o) => { + if (this.props.having) { + return !!o.havingOnly; + } + return (!o.datasourceTypes || o.datasourceTypes.indexOf(datasource.type) >= 0); + }) .map(o => ({ value: o.val, label: o.val })); - const colChoices = datasource ? - datasource.filterable_cols.map(c => ({ value: c[0], label: c[1] })) : - null; + let colChoices; + if (datasource) { + if (this.props.having) { + colChoices = datasource.metrics_combo.map(c => ({ value: c[0], label: c[1] })); + } else { + colChoices = datasource.filterable_cols.map(c => ({ value: c[0], label: c[1] })); + } + } return (