You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by cc...@apache.org on 2018/09/11 22:51:20 UTC

[incubator-superset] 03/04: [core] replace dashboard ajax calls with SupersetClient

This is an automated email from the ASF dual-hosted git repository.

ccwilliams pushed a commit to branch chris--ajax-dashboard
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git

commit 503f5bc2244852bf0b5533c7e7a3eb257b984bbc
Author: Chris Williams <ch...@airbnb.com>
AuthorDate: Mon Sep 10 22:05:22 2018 -0700

    [core] replace dashboard ajax calls with SupersetClient
---
 .../assets/src/dashboard/actions/dashboardState.js | 73 +++++++++++++---------
 .../assets/src/dashboard/actions/datasources.js    | 18 +++---
 .../assets/src/dashboard/actions/sliceEntities.js  | 41 ++++++++----
 .../assets/src/dashboard/components/SaveModal.jsx  | 11 +++-
 .../assets/src/dashboard/components/SliceAdder.jsx |  6 +-
 .../dashboard/components/gridComponents/Chart.jsx  |  2 +-
 .../assets/src/dashboard/reducers/sliceEntities.js | 12 ++--
 .../dashboard/stylesheets/builder-sidepane.less    |  7 +++
 superset/assets/src/dashboard/util/propShapes.jsx  |  2 +-
 9 files changed, 108 insertions(+), 64 deletions(-)

diff --git a/superset/assets/src/dashboard/actions/dashboardState.js b/superset/assets/src/dashboard/actions/dashboardState.js
index 17f6d46..e2cb0f3 100644
--- a/superset/assets/src/dashboard/actions/dashboardState.js
+++ b/superset/assets/src/dashboard/actions/dashboardState.js
@@ -1,6 +1,6 @@
 /* eslint camelcase: 0 */
-import $ from 'jquery';
 import { ActionCreators as UndoActionCreators } from 'redux-undo';
+import { SupersetClient } from '@superset-ui/core';
 
 import { addChart, removeChart, refreshChart } from '../../chart/chartAction';
 import { chart as initChart } from '../../chart/chartReducer';
@@ -14,7 +14,6 @@ import {
 } from '../../logger';
 import { SAVE_TYPE_OVERWRITE } from '../util/constants';
 import { t } from '../../locales';
-
 import {
   addSuccessToast,
   addWarningToast,
@@ -57,12 +56,21 @@ export function toggleFaveStar(isStarred) {
 export const FETCH_FAVE_STAR = 'FETCH_FAVE_STAR';
 export function fetchFaveStar(id) {
   return function fetchFaveStarThunk(dispatch) {
-    const url = `${FAVESTAR_BASE_URL}/${id}/count`;
-    return $.get(url).done(data => {
-      if (data.count > 0) {
-        dispatch(toggleFaveStar(true));
-      }
-    });
+    return SupersetClient.get({
+      endpoint: `${FAVESTAR_BASE_URL}/${id}/count`,
+    })
+      .then(({ json }) => {
+        if (json.count > 0) dispatch(toggleFaveStar(true));
+      })
+      .catch(() =>
+        dispatch(
+          addDangerToast(
+            t(
+              'There was an issue fetching the favorite status of this dashboard.',
+            ),
+          ),
+        ),
+      );
   };
 }
 
@@ -70,9 +78,17 @@ export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR';
 export function saveFaveStar(id, isStarred) {
   return function saveFaveStarThunk(dispatch) {
     const urlSuffix = isStarred ? 'unselect' : 'select';
-    const url = `${FAVESTAR_BASE_URL}/${id}/${urlSuffix}/`;
-    $.get(url);
-    dispatch(toggleFaveStar(!isStarred));
+    return SupersetClient.get({
+      endpoint: `${FAVESTAR_BASE_URL}/${id}/${urlSuffix}/`,
+    })
+      .then(() => {
+        dispatch(toggleFaveStar(!isStarred));
+      })
+      .catch(() =>
+        dispatch(
+          addDangerToast(t('There was an issue favoriting this dashboard.')),
+        ),
+      );
   };
 }
 
@@ -111,28 +127,29 @@ export function saveDashboardRequestSuccess() {
 
 export function saveDashboardRequest(data, id, saveType) {
   const path = saveType === SAVE_TYPE_OVERWRITE ? 'save_dash' : 'copy_dash';
-  const url = `/superset/${path}/${id}/`;
+
   return dispatch =>
-    $.ajax({
-      type: 'POST',
-      url,
-      data: {
-        data: JSON.stringify(data),
-      },
-      success: () => {
-        dispatch(saveDashboardRequestSuccess());
-        dispatch(addSuccessToast(t('This dashboard was saved successfully.')));
-      },
-      error: error => {
-        const errorMsg = getAjaxErrorMsg(error);
+    SupersetClient.post({
+      endpoint: `/superset/${path}/${id}/`,
+      postPayload: { data },
+    })
+      .then(response =>
+        Promise.all([
+          Promise.resolve(response),
+          dispatch(saveDashboardRequestSuccess()),
+          dispatch(
+            addSuccessToast(t('This dashboard was saved successfully.')),
+          ),
+        ]),
+      )
+      .catch(error =>
         dispatch(
           addDangerToast(
             `${t('Sorry, there was an error saving this dashboard: ')}
-          ${errorMsg}`,
+          ${getAjaxErrorMsg(error)}`,
           ),
-        );
-      },
-    });
+        ),
+      );
 }
 
 export function fetchCharts(chartList = [], force = false, interval = 0) {
diff --git a/superset/assets/src/dashboard/actions/datasources.js b/superset/assets/src/dashboard/actions/datasources.js
index d97296e..eab9e99 100644
--- a/superset/assets/src/dashboard/actions/datasources.js
+++ b/superset/assets/src/dashboard/actions/datasources.js
@@ -1,4 +1,5 @@
-import $ from 'jquery';
+import { SupersetClient } from '@superset-ui/core';
+import { getAjaxErrorMsg } from '../../modules/utils';
 
 export const SET_DATASOURCE = 'SET_DATASOURCE';
 export function setDatasource(datasource, key) {
@@ -24,13 +25,12 @@ export function fetchDatasourceMetadata(key) {
       return dispatch(setDatasource(datasource, key));
     }
 
-    const url = `/superset/fetch_datasource_metadata?datasourceKey=${key}`;
-    return $.ajax({
-      type: 'GET',
-      url,
-      success: data => dispatch(setDatasource(data, key)),
-      error: error =>
-        dispatch(fetchDatasourceFailed(error.responseJSON.error, key)),
-    });
+    return SupersetClient.get({
+      endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${key}`,
+    })
+      .then(data => dispatch(data, key))
+      .catch(error =>
+        dispatch(fetchDatasourceFailed(getAjaxErrorMsg(error), key)),
+      );
   };
 }
diff --git a/superset/assets/src/dashboard/actions/sliceEntities.js b/superset/assets/src/dashboard/actions/sliceEntities.js
index b635ea0..33e3507 100644
--- a/superset/assets/src/dashboard/actions/sliceEntities.js
+++ b/superset/assets/src/dashboard/actions/sliceEntities.js
@@ -1,11 +1,13 @@
 /* eslint camelcase: 0 */
-import $ from 'jquery';
+import { SupersetClient } from '@superset-ui/core';
 
+import { addDangerToast } from '../../messageToasts/actions';
+import { t } from '../../locales';
 import { getDatasourceParameter } from '../../modules/utils';
 
 export const SET_ALL_SLICES = 'SET_ALL_SLICES';
 export function setAllSlices(slices) {
-  return { type: SET_ALL_SLICES, slices };
+  return { type: SET_ALL_SLICES, payload: { slices } };
 }
 
 export const FETCH_ALL_SLICES_STARTED = 'FETCH_ALL_SLICES_STARTED';
@@ -15,7 +17,7 @@ export function fetchAllSlicesStarted() {
 
 export const FETCH_ALL_SLICES_FAILED = 'FETCH_ALL_SLICES_FAILED';
 export function fetchAllSlicesFailed(error) {
-  return { type: FETCH_ALL_SLICES_FAILED, error };
+  return { type: FETCH_ALL_SLICES_FAILED, payload: { error } };
 }
 
 export function fetchAllSlices(userId) {
@@ -24,13 +26,12 @@ export function fetchAllSlices(userId) {
     if (sliceEntities.lastUpdated === 0) {
       dispatch(fetchAllSlicesStarted());
 
-      const uri = `/sliceaddview/api/read?_flt_0_created_by=${userId}`;
-      return $.ajax({
-        url: uri,
-        type: 'GET',
-        success: response => {
+      return SupersetClient.get({
+        endpoint: `/sliceaddview/api/read?_flt_0_created_by=${userId}`,
+      })
+        .then(({ json }) => {
           const slices = {};
-          response.result.forEach(slice => {
+          json.result.forEach(slice => {
             let form_data = JSON.parse(slice.params);
             let datasource = form_data.datasource;
             if (!datasource) {
@@ -60,10 +61,26 @@ export function fetchAllSlices(userId) {
               };
             }
           });
+
           return dispatch(setAllSlices(slices));
-        },
-        error: error => dispatch(fetchAllSlicesFailed(error)),
-      });
+        })
+        .catch(error =>
+          Promise.all([
+            dispatch(
+              fetchAllSlicesFailed(
+                error.error ||
+                  error.statusText ||
+                  t('Could not fetch all saved charts'),
+              ),
+            ),
+            dispatch(
+              addDangerToast(
+                t('Sorry there was an error fetching saved charts: ') +
+                  error.error || error.statusText,
+              ),
+            ),
+          ]),
+        );
     }
 
     return dispatch(setAllSlices(sliceEntities.slices));
diff --git a/superset/assets/src/dashboard/components/SaveModal.jsx b/superset/assets/src/dashboard/components/SaveModal.jsx
index 8194f46..13863a2 100644
--- a/superset/assets/src/dashboard/components/SaveModal.jsx
+++ b/superset/assets/src/dashboard/components/SaveModal.jsx
@@ -93,9 +93,14 @@ class SaveModal extends React.PureComponent {
         t('You must pick a name for the new dashboard'),
       );
     } else {
-      this.onSave(data, dashboardId, saveType).done(resp => {
-        if (saveType === SAVE_TYPE_NEWDASHBOARD) {
-          window.location = `/superset/dashboard/${resp.id}/`;
+      this.onSave(data, dashboardId, saveType).then(([resp]) => {
+        if (
+          saveType === SAVE_TYPE_NEWDASHBOARD &&
+          resp &&
+          resp.json &&
+          resp.json.id
+        ) {
+          window.location = `/superset/dashboard/${resp.json.id}/`;
         }
       });
       this.modal.close();
diff --git a/superset/assets/src/dashboard/components/SliceAdder.jsx b/superset/assets/src/dashboard/components/SliceAdder.jsx
index 31ad797..608cfc1 100644
--- a/superset/assets/src/dashboard/components/SliceAdder.jsx
+++ b/superset/assets/src/dashboard/components/SliceAdder.jsx
@@ -226,8 +226,6 @@ class SliceAdder extends React.Component {
 
         {this.props.isLoading && <Loading />}
 
-        {this.props.errorMessage && <div>{this.props.errorMessage}</div>}
-
         {!this.props.isLoading &&
           this.state.filteredSlices.length > 0 && (
             <List
@@ -243,6 +241,10 @@ class SliceAdder extends React.Component {
             />
           )}
 
+        {this.props.errorMessage && (
+          <div className="error-message">{this.props.errorMessage}</div>
+        )}
+
         {/* Drag preview is just a single fixed-position element */}
         <AddSliceDragPreview slices={this.state.filteredSlices} />
       </div>
diff --git a/superset/assets/src/dashboard/components/gridComponents/Chart.jsx b/superset/assets/src/dashboard/components/gridComponents/Chart.jsx
index 7e2e6a6..96c92d9 100644
--- a/superset/assets/src/dashboard/components/gridComponents/Chart.jsx
+++ b/superset/assets/src/dashboard/components/gridComponents/Chart.jsx
@@ -233,7 +233,7 @@ class Chart extends React.Component {
             latestQueryFormData={chart.latestQueryFormData}
             lastRendered={chart.lastRendered}
             queryResponse={chart.queryResponse}
-            queryRequest={chart.queryRequest}
+            queryController={chart.queryController}
             triggerQuery={chart.triggerQuery}
           />
         </div>
diff --git a/superset/assets/src/dashboard/reducers/sliceEntities.js b/superset/assets/src/dashboard/reducers/sliceEntities.js
index c5e46c2..a96368a 100644
--- a/superset/assets/src/dashboard/reducers/sliceEntities.js
+++ b/superset/assets/src/dashboard/reducers/sliceEntities.js
@@ -3,6 +3,7 @@ import {
   FETCH_ALL_SLICES_STARTED,
   SET_ALL_SLICES,
 } from '../actions/sliceEntities';
+
 import { t } from '../../locales';
 
 export const initSliceEntities = {
@@ -27,22 +28,17 @@ export default function sliceEntitiesReducer(
       return {
         ...state,
         isLoading: false,
-        slices: { ...state.slices, ...action.slices }, // append more slices
+        slices: { ...state.slices, ...action.payload.slices },
         lastUpdated: new Date().getTime(),
       };
     },
     [FETCH_ALL_SLICES_FAILED]() {
-      const respJSON = action.error.responseJSON;
-      const errorMessage =
-        t('Sorry, there was an error fetching slices: ') +
-        (respJSON && respJSON.message)
-          ? respJSON.message
-          : action.error.responseText;
       return {
         ...state,
         isLoading: false,
-        errorMessage,
         lastUpdated: new Date().getTime(),
+        errorMessage:
+          action.payload.error || t('Could not fetch all saved charts'),
       };
     },
   };
diff --git a/superset/assets/src/dashboard/stylesheets/builder-sidepane.less b/superset/assets/src/dashboard/stylesheets/builder-sidepane.less
index 17c87a8..08355e3 100644
--- a/superset/assets/src/dashboard/stylesheets/builder-sidepane.less
+++ b/superset/assets/src/dashboard/stylesheets/builder-sidepane.less
@@ -127,6 +127,13 @@
   }
 
   .slice-adder-container {
+    position: relative;
+    min-height: 200px; /* for loader positioning */
+
+    .error-message {
+      padding: 16px;
+    }
+
     .controls {
       display: flex;
       padding: 16px;
diff --git a/superset/assets/src/dashboard/util/propShapes.jsx b/superset/assets/src/dashboard/util/propShapes.jsx
index 3c06e14..faedb91 100644
--- a/superset/assets/src/dashboard/util/propShapes.jsx
+++ b/superset/assets/src/dashboard/util/propShapes.jsx
@@ -27,7 +27,7 @@ export const chartPropShape = PropTypes.shape({
   chartUpdateEndTime: PropTypes.number,
   chartUpdateStartTime: PropTypes.number,
   latestQueryFormData: PropTypes.object,
-  queryRequest: PropTypes.object,
+  queryController: PropTypes.shape({ abort: PropTypes.func }),
   queryResponse: PropTypes.object,
   triggerQuery: PropTypes.bool,
   lastRendered: PropTypes.number,