From 72b9489a270bf1280f35b0371b035b472acd69dc Mon Sep 17 00:00:00 2001
From: Tom Robinson <tlrobinson@gmail.com>
Date: Fri, 13 Jul 2018 15:43:56 -0700
Subject: [PATCH] Use redux action to save xray dashboard, make sure it
 invalidates dashboard listings

---
 .../dashboard/containers/AutomaticDashboardApp.jsx | 14 ++++++++++----
 frontend/src/metabase/entities/dashboards.js       | 12 ++++++++++++
 frontend/src/metabase/lib/entities.js              |  7 ++++++-
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/frontend/src/metabase/dashboard/containers/AutomaticDashboardApp.jsx b/frontend/src/metabase/dashboard/containers/AutomaticDashboardApp.jsx
index a642330254a..c24fa7ed910 100644
--- a/frontend/src/metabase/dashboard/containers/AutomaticDashboardApp.jsx
+++ b/frontend/src/metabase/dashboard/containers/AutomaticDashboardApp.jsx
@@ -22,7 +22,7 @@ import Parameters from "metabase/parameters/components/Parameters";
 import { getMetadata } from "metabase/selectors/metadata";
 import { getUserIsAdmin } from "metabase/selectors/user";
 
-import { DashboardApi } from "metabase/services";
+import Dashboards from "metabase/entities/dashboards";
 import * as Urls from "metabase/lib/urls";
 import MetabaseAnalytics from "metabase/lib/analytics";
 
@@ -41,7 +41,11 @@ const mapStateToProps = (state, props) => ({
   dashboardId: getDashboardId(state, props),
 });
 
-@connect(mapStateToProps)
+const mapDispatchToProps = {
+  saveDashboard: Dashboards.actions.save,
+};
+
+@connect(mapStateToProps, mapDispatchToProps)
 @DashboardData
 @withToast
 @title(({ dashboard }) => dashboard && dashboard.name)
@@ -58,9 +62,11 @@ class AutomaticDashboardApp extends React.Component {
   }
 
   save = async () => {
-    const { dashboard, triggerToast } = this.props;
+    const { dashboard, triggerToast, saveDashboard } = this.props;
     // remove the transient id before trying to save
-    const newDashboard = await DashboardApi.save(dissoc(dashboard, "id"));
+    const { payload: newDashboard } = await saveDashboard(
+      dissoc(dashboard, "id"),
+    );
     triggerToast(
       <div className="flex align-center">
         <Icon
diff --git a/frontend/src/metabase/entities/dashboards.js b/frontend/src/metabase/entities/dashboards.js
index 8183e18011c..857e42b9cf6 100644
--- a/frontend/src/metabase/entities/dashboards.js
+++ b/frontend/src/metabase/entities/dashboards.js
@@ -18,6 +18,7 @@ const Dashboards = createEntity({
   api: {
     favorite: POST("/api/dashboard/:id/favorite"),
     unfavorite: DELETE("/api/dashboard/:id/favorite"),
+    save: POST("/api/dashboard/save"),
   },
 
   objectActions: {
@@ -56,6 +57,17 @@ const Dashboards = createEntity({
     },
   },
 
+  actions: {
+    save: dashboard => async dispatch => {
+      const savedDashboard = await Dashboards.api.save(dashboard);
+      dispatch({ type: Dashboards.actionTypes.INVALIDATE_LISTS_ACTION });
+      return {
+        type: "metabase/entities/dashboards/SAVE_DASHBOARD",
+        payload: savedDashboard,
+      };
+    },
+  },
+
   reducer: (state = {}, { type, payload, error }) => {
     if (type === FAVORITE_ACTION && !error) {
       return assocIn(state, [payload, "favorite"], true);
diff --git a/frontend/src/metabase/lib/entities.js b/frontend/src/metabase/lib/entities.js
index 125da1e7014..7ab0779cc60 100644
--- a/frontend/src/metabase/lib/entities.js
+++ b/frontend/src/metabase/lib/entities.js
@@ -175,6 +175,9 @@ export function createEntity(def: EntityDefinition): Entity {
   const UPDATE_ACTION = `metabase/entities/${entity.name}/UPDATE`;
   const DELETE_ACTION = `metabase/entities/${entity.name}/DELETE`;
   const FETCH_LIST_ACTION = `metabase/entities/${entity.name}/FETCH_LIST`;
+  const INVALIDATE_LISTS_ACTION = `metabase/entities/${
+    entity.name
+  }/INVALIDATE_LISTS_ACTION`;
 
   entity.actionTypes = {
     CREATE: CREATE_ACTION,
@@ -182,6 +185,7 @@ export function createEntity(def: EntityDefinition): Entity {
     UPDATE: UPDATE_ACTION,
     DELETE: DELETE_ACTION,
     FETCH_LIST: FETCH_LIST_ACTION,
+    INVALIDATE_LISTS_ACTION: INVALIDATE_LISTS_ACTION,
     ...(entity.actionTypes || {}),
   };
 
@@ -470,7 +474,8 @@ export function createEntity(def: EntityDefinition): Entity {
     entity.actionShouldInvalidateLists = action =>
       action.type === CREATE_ACTION ||
       action.type === DELETE_ACTION ||
-      action.type === UPDATE_ACTION;
+      action.type === UPDATE_ACTION ||
+      action.type === INVALIDATE_LISTS_ACTION;
   }
 
   entity.requestsReducer = (state, action) => {
-- 
GitLab