You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2023/04/06 19:00:57 UTC

[superset] branch master updated: fix: Disables email reports for unsaved charts (#23588)

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

michaelsmolina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 290920c4fb fix: Disables email reports for unsaved charts (#23588)
290920c4fb is described below

commit 290920c4fb1fec85bf6f95e23f3c91b2681cfcbe
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Thu Apr 6 16:00:47 2023 -0300

    fix: Disables email reports for unsaved charts (#23588)
---
 .../ReportModal/HeaderReportDropdown/index.tsx     | 67 +++++++++++++---------
 .../src/components/ReportModal/index.tsx           |  8 ++-
 superset-frontend/src/reports/actions/reports.js   |  4 +-
 superset-frontend/src/reports/reducers/reports.js  | 19 +++++-
 superset-frontend/src/views/CRUD/hooks.ts          |  2 +-
 5 files changed, 69 insertions(+), 31 deletions(-)

diff --git a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx
index 6d141f941c..b2e47cc53c 100644
--- a/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx
+++ b/superset-frontend/src/components/ReportModal/HeaderReportDropdown/index.tsx
@@ -18,6 +18,7 @@
  */
 import React, { useState, useEffect } from 'react';
 import { useSelector, useDispatch } from 'react-redux';
+import { isEmpty } from 'lodash';
 import {
   t,
   SupersetTheme,
@@ -103,6 +104,9 @@ export interface HeaderReportProps {
   showReportSubMenu?: boolean;
 }
 
+// Same instance to be used in useEffects
+const EMPTY_OBJECT = {};
+
 export default function HeaderReportDropDown({
   dashboardId,
   chart,
@@ -116,7 +120,10 @@ export default function HeaderReportDropDown({
     const resourceType = dashboardId
       ? CreationMethod.DASHBOARDS
       : CreationMethod.CHARTS;
-    return reportSelector(state, resourceType, dashboardId || chart?.id);
+    return (
+      reportSelector(state, resourceType, dashboardId || chart?.id) ||
+      EMPTY_OBJECT
+    );
   });
 
   const isReportActive: boolean = report?.active || false;
@@ -133,6 +140,12 @@ export default function HeaderReportDropDown({
       // this is in the case that there is an anonymous user.
       return false;
     }
+
+    // Cannot add reports if the resource is not saved
+    if (!(dashboardId || chart?.id)) {
+      return false;
+    }
+
     const roles = Object.keys(user.roles || []);
     const permissions = roles.map(key =>
       user.roles[key].filter(
@@ -200,7 +213,21 @@ export default function HeaderReportDropDown({
   };
 
   const textMenu = () =>
-    report ? (
+    isEmpty(report) ? (
+      <Menu selectable={false} css={onMenuHover}>
+        <Menu.Item onClick={handleShowMenu}>
+          {DropdownItemExtension ? (
+            <StyledDropdownItemWithIcon>
+              <div>{t('Set up an email report')}</div>
+              <DropdownItemExtension />
+            </StyledDropdownItemWithIcon>
+          ) : (
+            t('Set up an email report')
+          )}
+        </Menu.Item>
+        <Menu.Divider />
+      </Menu>
+    ) : (
       isDropdownVisible && (
         <Menu selectable={false} css={{ border: 'none' }}>
           <Menu.Item
@@ -220,20 +247,6 @@ export default function HeaderReportDropDown({
           </Menu.Item>
         </Menu>
       )
-    ) : (
-      <Menu selectable={false} css={onMenuHover}>
-        <Menu.Item onClick={handleShowMenu}>
-          {DropdownItemExtension ? (
-            <StyledDropdownItemWithIcon>
-              <div>{t('Set up an email report')}</div>
-              <DropdownItemExtension />
-            </StyledDropdownItemWithIcon>
-          ) : (
-            t('Set up an email report')
-          )}
-        </Menu.Item>
-        <Menu.Divider />
-      </Menu>
     );
   const menu = () => (
     <Menu selectable={false} css={{ width: '200px' }}>
@@ -260,7 +273,17 @@ export default function HeaderReportDropDown({
   );
 
   const iconMenu = () =>
-    report ? (
+    isEmpty(report) ? (
+      <span
+        role="button"
+        title={t('Schedule email report')}
+        tabIndex={0}
+        className="action-button action-schedule-report"
+        onClick={() => setShowModal(true)}
+      >
+        <Icons.Calendar />
+      </span>
+    ) : (
       <>
         <NoAnimationDropdown
           overlay={menu()}
@@ -278,16 +301,6 @@ export default function HeaderReportDropDown({
           </span>
         </NoAnimationDropdown>
       </>
-    ) : (
-      <span
-        role="button"
-        title={t('Schedule email report')}
-        tabIndex={0}
-        className="action-button action-schedule-report"
-        onClick={() => setShowModal(true)}
-      >
-        <Icons.Calendar />
-      </span>
     );
 
   return (
diff --git a/superset-frontend/src/components/ReportModal/index.tsx b/superset-frontend/src/components/ReportModal/index.tsx
index 9f9596e2ff..345d8b8224 100644
--- a/superset-frontend/src/components/ReportModal/index.tsx
+++ b/superset-frontend/src/components/ReportModal/index.tsx
@@ -93,6 +93,9 @@ type ReportObjectState = Partial<ReportObject> & {
   isSubmitting?: boolean;
 };
 
+// Same instance to be used in useEffects
+const EMPTY_OBJECT = {};
+
 function ReportModal({
   onHide,
   show = false,
@@ -147,7 +150,10 @@ function ReportModal({
     const resourceType = dashboardId
       ? CreationMethod.DASHBOARDS
       : CreationMethod.CHARTS;
-    return reportSelector(state, resourceType, dashboardId || chart?.id);
+    return (
+      reportSelector(state, resourceType, dashboardId || chart?.id) ||
+      EMPTY_OBJECT
+    );
   });
   const isEditMode = report && Object.keys(report).length;
 
diff --git a/superset-frontend/src/reports/actions/reports.js b/superset-frontend/src/reports/actions/reports.js
index 96a435ec5d..45edc90129 100644
--- a/superset-frontend/src/reports/actions/reports.js
+++ b/superset-frontend/src/reports/actions/reports.js
@@ -143,6 +143,8 @@ export function toggleActive(report, isActive) {
   };
 }
 
+export const DELETE_REPORT = 'DELETE_REPORT';
+
 export function deleteActiveReport(report) {
   return function deleteActiveReportThunk(dispatch) {
     return SupersetClient.delete({
@@ -152,7 +154,7 @@ export function deleteActiveReport(report) {
         dispatch(addDangerToast(t('Your report could not be deleted')));
       })
       .finally(() => {
-        dispatch(structureFetchAction);
+        dispatch({ type: DELETE_REPORT, report });
         dispatch(addSuccessToast(t('Deleted: %s', report.name)));
       });
   };
diff --git a/superset-frontend/src/reports/reducers/reports.js b/superset-frontend/src/reports/reducers/reports.js
index 1896250f5c..823660b645 100644
--- a/superset-frontend/src/reports/reducers/reports.js
+++ b/superset-frontend/src/reports/reducers/reports.js
@@ -18,7 +18,13 @@
  */
 /* eslint-disable camelcase */
 // eslint-disable-next-line import/no-extraneous-dependencies
-import { SET_REPORT, ADD_REPORT, EDIT_REPORT } from '../actions/reports';
+import { omit } from 'lodash';
+import {
+  SET_REPORT,
+  ADD_REPORT,
+  EDIT_REPORT,
+  DELETE_REPORT,
+} from '../actions/reports';
 
 export default function reportsReducer(state = {}, action) {
   const actionHandlers = {
@@ -78,6 +84,17 @@ export default function reportsReducer(state = {}, action) {
         },
       };
     },
+
+    [DELETE_REPORT]() {
+      const { report } = action;
+      const reportTypeId = report.dashboard || report.chart;
+      return {
+        ...state,
+        [report.creation_method]: {
+          ...omit(state[report.creation_method], reportTypeId),
+        },
+      };
+    },
   };
 
   if (action.type in actionHandlers) {
diff --git a/superset-frontend/src/views/CRUD/hooks.ts b/superset-frontend/src/views/CRUD/hooks.ts
index dfcf23e190..91af5817b4 100644
--- a/superset-frontend/src/views/CRUD/hooks.ts
+++ b/superset-frontend/src/views/CRUD/hooks.ts
@@ -867,5 +867,5 @@ export const reportSelector = (
   if (resourceId) {
     return state.reports[resourceType]?.[resourceId];
   }
-  return {};
+  return null;
 };