mirror of
https://github.com/apache/superset.git
synced 2024-09-18 19:49:37 -04:00
fix: Disables email reports for unsaved charts (#23588)
This commit is contained in:
parent
83df609782
commit
290920c4fb
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import {
|
import {
|
||||||
t,
|
t,
|
||||||
SupersetTheme,
|
SupersetTheme,
|
||||||
@ -103,6 +104,9 @@ export interface HeaderReportProps {
|
|||||||
showReportSubMenu?: boolean;
|
showReportSubMenu?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same instance to be used in useEffects
|
||||||
|
const EMPTY_OBJECT = {};
|
||||||
|
|
||||||
export default function HeaderReportDropDown({
|
export default function HeaderReportDropDown({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
chart,
|
chart,
|
||||||
@ -116,7 +120,10 @@ export default function HeaderReportDropDown({
|
|||||||
const resourceType = dashboardId
|
const resourceType = dashboardId
|
||||||
? CreationMethod.DASHBOARDS
|
? CreationMethod.DASHBOARDS
|
||||||
: CreationMethod.CHARTS;
|
: CreationMethod.CHARTS;
|
||||||
return reportSelector(state, resourceType, dashboardId || chart?.id);
|
return (
|
||||||
|
reportSelector(state, resourceType, dashboardId || chart?.id) ||
|
||||||
|
EMPTY_OBJECT
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const isReportActive: boolean = report?.active || false;
|
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.
|
// this is in the case that there is an anonymous user.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cannot add reports if the resource is not saved
|
||||||
|
if (!(dashboardId || chart?.id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const roles = Object.keys(user.roles || []);
|
const roles = Object.keys(user.roles || []);
|
||||||
const permissions = roles.map(key =>
|
const permissions = roles.map(key =>
|
||||||
user.roles[key].filter(
|
user.roles[key].filter(
|
||||||
@ -200,7 +213,21 @@ export default function HeaderReportDropDown({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const textMenu = () =>
|
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 && (
|
isDropdownVisible && (
|
||||||
<Menu selectable={false} css={{ border: 'none' }}>
|
<Menu selectable={false} css={{ border: 'none' }}>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
@ -220,20 +247,6 @@ export default function HeaderReportDropDown({
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu>
|
</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 = () => (
|
const menu = () => (
|
||||||
<Menu selectable={false} css={{ width: '200px' }}>
|
<Menu selectable={false} css={{ width: '200px' }}>
|
||||||
@ -260,7 +273,17 @@ export default function HeaderReportDropDown({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const iconMenu = () =>
|
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
|
<NoAnimationDropdown
|
||||||
overlay={menu()}
|
overlay={menu()}
|
||||||
@ -278,16 +301,6 @@ export default function HeaderReportDropDown({
|
|||||||
</span>
|
</span>
|
||||||
</NoAnimationDropdown>
|
</NoAnimationDropdown>
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<span
|
|
||||||
role="button"
|
|
||||||
title={t('Schedule email report')}
|
|
||||||
tabIndex={0}
|
|
||||||
className="action-button action-schedule-report"
|
|
||||||
onClick={() => setShowModal(true)}
|
|
||||||
>
|
|
||||||
<Icons.Calendar />
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -93,6 +93,9 @@ type ReportObjectState = Partial<ReportObject> & {
|
|||||||
isSubmitting?: boolean;
|
isSubmitting?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Same instance to be used in useEffects
|
||||||
|
const EMPTY_OBJECT = {};
|
||||||
|
|
||||||
function ReportModal({
|
function ReportModal({
|
||||||
onHide,
|
onHide,
|
||||||
show = false,
|
show = false,
|
||||||
@ -147,7 +150,10 @@ function ReportModal({
|
|||||||
const resourceType = dashboardId
|
const resourceType = dashboardId
|
||||||
? CreationMethod.DASHBOARDS
|
? CreationMethod.DASHBOARDS
|
||||||
: CreationMethod.CHARTS;
|
: 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;
|
const isEditMode = report && Object.keys(report).length;
|
||||||
|
|
||||||
|
@ -143,6 +143,8 @@ export function toggleActive(report, isActive) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DELETE_REPORT = 'DELETE_REPORT';
|
||||||
|
|
||||||
export function deleteActiveReport(report) {
|
export function deleteActiveReport(report) {
|
||||||
return function deleteActiveReportThunk(dispatch) {
|
return function deleteActiveReportThunk(dispatch) {
|
||||||
return SupersetClient.delete({
|
return SupersetClient.delete({
|
||||||
@ -152,7 +154,7 @@ export function deleteActiveReport(report) {
|
|||||||
dispatch(addDangerToast(t('Your report could not be deleted')));
|
dispatch(addDangerToast(t('Your report could not be deleted')));
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
dispatch(structureFetchAction);
|
dispatch({ type: DELETE_REPORT, report });
|
||||||
dispatch(addSuccessToast(t('Deleted: %s', report.name)));
|
dispatch(addSuccessToast(t('Deleted: %s', report.name)));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// 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) {
|
export default function reportsReducer(state = {}, action) {
|
||||||
const actionHandlers = {
|
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) {
|
if (action.type in actionHandlers) {
|
||||||
|
@ -867,5 +867,5 @@ export const reportSelector = (
|
|||||||
if (resourceId) {
|
if (resourceId) {
|
||||||
return state.reports[resourceType]?.[resourceId];
|
return state.reports[resourceType]?.[resourceId];
|
||||||
}
|
}
|
||||||
return {};
|
return null;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user