From a8480f54922775992a28edd7878b1cfa7690264e Mon Sep 17 00:00:00 2001 From: vera-liu Date: Fri, 18 Nov 2016 11:17:06 -0800 Subject: [PATCH] Added Alert for ControlPanel and ChartContainer (#1626) * Added Alert for ControlPanel and ChartContainer Done: - Add alert for Control Panel when fetch_datasource_metadata failes - Add alert for Chart Container when update_explore query fails * Changed color to warning-yellow * Solve linter issue * Fixed indent and delete error_redirect --- .../explorev2/actions/exploreActions.js | 36 ++++++++++++------- .../explorev2/components/ChartContainer.jsx | 17 ++++++++- .../components/ControlPanelsContainer.jsx | 17 ++++++++- .../components/ExploreViewContainer.jsx | 4 +++ .../explorev2/reducers/exploreReducer.js | 15 ++++++-- superset/views.py | 12 ++++--- 6 files changed, 79 insertions(+), 22 deletions(-) diff --git a/superset/assets/javascripts/explorev2/actions/exploreActions.js b/superset/assets/javascripts/explorev2/actions/exploreActions.js index 427c6bb70d..8d0728fbba 100644 --- a/superset/assets/javascripts/explorev2/actions/exploreActions.js +++ b/superset/assets/javascripts/explorev2/actions/exploreActions.js @@ -24,8 +24,8 @@ export function fetchSucceeded() { } export const FETCH_FAILED = 'FETCH_FAILED'; -export function fetchFailed() { - return { type: FETCH_FAILED }; +export function fetchFailed(error) { + return { type: FETCH_FAILED, error }; } export function fetchFieldOptions(datasourceId, datasourceType) { @@ -35,18 +35,19 @@ export function fetchFieldOptions(datasourceId, datasourceType) { if (datasourceId) { const params = [`datasource_id=${datasourceId}`, `datasource_type=${datasourceType}`]; const url = '/superset/fetch_datasource_metadata?' + params.join('&'); - - $.get(url, (data, status) => { - if (status === 'success') { - // populate options for select type fields + $.ajax({ + type: 'GET', + url, + success: (data) => { dispatch(setFieldOptions(data.field_options)); dispatch(fetchSucceeded()); - } else if (status === 'error') { - dispatch(fetchFailed()); - } + }, + error(error) { + dispatch(fetchFailed(error.responseJSON.error)); + }, }); } else { - // in what case don't we have a datasource id? + dispatch(fetchFailed('Please select a datasource')); } }; } @@ -119,8 +120,8 @@ export function chartUpdateStarted() { } export const CHART_UPDATE_FAILED = 'CHART_UPDATE_FAILED '; -export function chartUpdateFailed() { - return { type: CHART_UPDATE_FAILED }; +export function chartUpdateFailed(error) { + return { type: CHART_UPDATE_FAILED, error }; } export function updateExplore(datasource_type, datasource_id, form_data) { @@ -139,9 +140,18 @@ export function updateExplore(datasource_type, datasource_id, form_data) { dispatch(updateChart(JSON.parse(data))); }, error(error) { - dispatch(chartUpdateFailed(error)); + dispatch(chartUpdateFailed(error.responseJSON.error)); }, }); }; } +export const REMOVE_CONTROL_PANEL_ALERT = 'REMOVE_CONTROL_PANEL_ALERT'; +export function removeControlPanelAlert() { + return { type: REMOVE_CONTROL_PANEL_ALERT }; +} + +export const REMOVE_CHART_ALERT = 'REMOVE_CHART_ALERT'; +export function removeChartAlert() { + return { type: REMOVE_CHART_ALERT }; +} diff --git a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx index 23cb2b62dc..3ede6dbaaf 100644 --- a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx @@ -1,7 +1,7 @@ import $ from 'jquery'; import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; -import { Panel } from 'react-bootstrap'; +import { Panel, Alert } from 'react-bootstrap'; import visMap from '../../../visualizations/main'; import { d3format } from '../../modules/utils'; import ExploreActionButtons from '../../explore/components/ExploreActionButtons'; @@ -24,6 +24,7 @@ const propTypes = { data: PropTypes.any, isChartLoading: PropTypes.bool, isStarred: PropTypes.bool.isRequired, + alert: PropTypes.string, }; class ChartContainer extends React.Component { @@ -139,6 +140,9 @@ class ChartContainer extends React.Component { }; } + removeAlert() { + this.props.actions.removeChartAlert(); + } renderVis() { visMap[this.props.viz_type](this.state.mockSlice).render(); @@ -183,6 +187,16 @@ class ChartContainer extends React.Component { } > + {this.props.alert && + + {this.props.alert} + + + } {!this.props.isChartLoading &&
+ {this.props.alert && + + {this.props.alert} + + + } {!this.props.isDatasourceMetaLoading &&
@@ -91,6 +105,7 @@ ControlPanelsContainer.propTypes = propTypes; function mapStateToProps(state) { return { + alert: state.controlPanelAlert, isDatasourceMetaLoading: state.isDatasourceMetaLoading, fields: state.fields, datasource_type: state.datasource_type, diff --git a/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx b/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx index b133f12b14..2b3442fd94 100644 --- a/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ExploreViewContainer.jsx @@ -41,6 +41,9 @@ class ExploreViewContainer extends React.Component { const params = $.param(data, true); this.updateUrl(params); + // remove alerts when query + this.props.actions.removeControlPanelAlert(); + this.props.actions.removeChartAlert(); } getHeight() { @@ -85,6 +88,7 @@ class ExploreViewContainer extends React.Component {
diff --git a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js index e12d3172fa..1316c0bca2 100644 --- a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js +++ b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js @@ -18,9 +18,15 @@ export const exploreReducer = function (state, action) { [actions.FETCH_FAILED]() { // todo(alanna) handle failure/error state - return Object.assign({}, state, { isDatasourceMetaLoading: false }); + return Object.assign({}, state, + { + isDatasourceMetaLoading: false, + controlPanelAlert: action.error, + }); + }, + [actions.REMOVE_CONTROL_PANEL_ALERT]() { + return Object.assign({}, state, { controlPanelAlert: null }); }, - [actions.SET_FIELD_OPTIONS]() { const newState = Object.assign({}, state); const optionsByFieldName = action.options; @@ -88,7 +94,10 @@ export const exploreReducer = function (state, action) { return Object.assign({}, state, { isChartLoading: true }); }, [actions.CHART_UPDATE_FAILED]() { - return Object.assign({}, state, { isChartLoading: false }); + return Object.assign({}, state, { isChartLoading: false, chartAlert: action.error }); + }, + [actions.REMOVE_CHART_ALERT]() { + return Object.assign({}, state, { chartAlert: null }); }, }; if (action.type in actionHandlers) { diff --git a/superset/views.py b/superset/views.py index 475a6ca90e..9abd2ac7ea 100755 --- a/superset/views.py +++ b/superset/views.py @@ -1294,16 +1294,20 @@ class Superset(BaseSupersetView): def update_explore(self, datasource_type, datasource_id): """Send back new viz on POST request for updating update explore view""" form_data = json.loads(request.form.get('data')) - error_redirect = '/slicemodelview/list/' try: viz_obj = self.get_viz( datasource_type=datasource_type, datasource_id=datasource_id, args=form_data) except Exception as e: - flash('{}'.format(e), "alert") - return redirect(error_redirect) - return viz_obj.get_json() + logging.exception(e) + return json_error_response('{}'.format(e)) + try: + viz_json = viz_obj.get_json() + except Exception as e: + logging.exception(e) + return json_error_response(utils.error_msg_from_exception(e)) + return viz_json @has_access_api @expose("/explore_json///")