You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2021/07/28 23:30:08 UTC
[superset] branch selfSubscribeReports updated: feat: Create/onsave
Email Report functionality for Dashboard and Chart (#15856)
This is an automated email from the ASF dual-hosted git repository.
elizabeth pushed a commit to branch selfSubscribeReports
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/selfSubscribeReports by this push:
new a6687d3 feat: Create/onsave Email Report functionality for Dashboard and Chart (#15856)
a6687d3 is described below
commit a6687d3a1b0dc54d709fb5a0b64fdebfc0e35b18
Author: Lyndsi Kay Williams <55...@users.noreply.github.com>
AuthorDate: Wed Jul 28 18:28:45 2021 -0500
feat: Create/onsave Email Report functionality for Dashboard and Chart (#15856)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
* feat: toggle the ReportModal Icon based on user permissions (#15780)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* fix: avoid fetching favorite status for anonymous user (#15590)
* avoid fetching favorite status for anonymous user
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* first draft
* added testing props
* cleaned up rebase
* changed name and type
Co-authored-by: Lyndsi Kay Williams <55...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* feat: Begin incorporation of email report modal to Charts (#15793)
* Add email report modal to Charts
* Fix px themes
* feat: fetch UI specific reports (#15785)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* fix: avoid fetching favorite status for anonymous user (#15590)
* avoid fetching favorite status for anonymous user
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* first draft
* created Api call
* added click logic
* made the fetch report into a action/reducer
* abstracted report action
* revision
* added reportState to reducer
* reports conditions
* revisions
* revisions
Co-authored-by: Lyndsi Kay Williams <55...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* fix: Edit physical dataset from the Edit Dataset modal (#15770)
* Remove unnecessary onChange
* Remove confliciting onChange
* Revert unnecessary change
* Enhance and fix tests
* feat: add show columns to Reports model (#15712)
* added logic for creation_method
* revisions
* added index
* Update superset/migrations/versions/3317e9248280_add_creation_method_to_reports_model.py
* filters
* search columns updated
* fix: margin right on warning icon to 8px (#15715)
* changed margin right on warning icon to 8px
* fixed to grid units from pixels
* feat: adding Progress Bar to Benchmark script (#15719)
* rough draft of benchmark script
* revisions
* revisions
* rough draft of benchmark script
* revisions
* Update requirements/development.in
Co-authored-by: Beto Dealmeida <ro...@dealmeida.net>
* Update superset/utils/mock_data.py
Co-authored-by: Beto Dealmeida <ro...@dealmeida.net>
* more revisions
Co-authored-by: Beto Dealmeida <ro...@dealmeida.net>
* fix: migration downgrade references wrong column (#15791)
* fix(dashboard): Add resize handles to right and bottom of component (#15778)
* fix(dashboard): Add resize handles to right and bottom of component
* Fix test
* chore: Add tags to the new viz gallery (#15734)
* chore: add tags to gallery
* fix UT
* fix lint
* redesign tags filter
* chore: change to Highly-used and fix some css
* fix UT
Co-authored-by: stephenLYZ <75...@qq.com>
* chore: bump 0.17.70 (#15795)
* docs: Adding Sunbird to users list (#15794)
* chore: Improves the Select component UI/UX - iteration 4 (#15480)
* Add z-index only on maximize (#15800)
* chore: remove `retry` dependency in favor of `backoff` (#15788)
* chore: remove retry dep in favor of backoff
* Fix lint
* fix: create fk model in benchmark script (#15804)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* fix: avoid fetching favorite status for anonymous user (#15590)
* avoid fetching favorite status for anonymous user
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* Working on onSave functionality
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
* feat: toggle the ReportModal Icon based on user permissions (#15780)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* fix: avoid fetching favorite status for anonymous user (#15590)
* avoid fetching favorite status for anonymous user
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* first draft
* added testing props
* cleaned up rebase
* changed name and type
Co-authored-by: Lyndsi Kay Williams <55...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* feat: fetch UI specific reports (#15785)
* style: Rough draft of email report modal (#15666)
* clears errors when closing out of modal (#15623)
* fix: avoid fetching favorite status for anonymous user (#15590)
* avoid fetching favorite status for anonymous user
* add test + fix types
* fix lint errors
* Building ReportModal component
* Continued ReportModal creation
* Visual details updated
* CronError style
* Very basic testing added
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* first draft
* created Api call
* added click logic
* made the fetch report into a action/reducer
* abstracted report action
* revision
* added reportState to reducer
* reports conditions
* revisions
* revisions
Co-authored-by: Lyndsi Kay Williams <55...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
* Dashboard onSave progress
* More onSave/create progress
* Dashboard POST working!
* Dashboard POST relocated to redux
* POST now also working in Charts
* making linter happy
* linter again
Co-authored-by: AAfghahi <48...@users.noreply.github.com>
Co-authored-by: aspedrosa <as...@ua.pt>
Co-authored-by: Geido <60...@users.noreply.github.com>
Co-authored-by: stellalc7 <st...@gmail.com>
Co-authored-by: Beto Dealmeida <ro...@dealmeida.net>
Co-authored-by: Kamil Gabryjelski <ka...@gmail.com>
Co-authored-by: Yongjie Zhao <yo...@gmail.com>
Co-authored-by: stephenLYZ <75...@qq.com>
Co-authored-by: Kumar <ku...@gmail.com>
Co-authored-by: Michael S. Molina <70...@users.noreply.github.com>
---
.../src/components/ReportModal/index.tsx | 168 ++++++++++++++-------
.../src/components/ReportModal/styles.tsx | 63 ++++++++
.../src/dashboard/components/Header/index.jsx | 1 +
.../src/explore/components/ExploreChartHeader.jsx | 15 ++
.../src/reports/actions/reportState.js | 16 ++
.../src/reports/reducers/reportState.js | 13 +-
6 files changed, 224 insertions(+), 52 deletions(-)
diff --git a/superset-frontend/src/components/ReportModal/index.tsx b/superset-frontend/src/components/ReportModal/index.tsx
index 8fbc50f..9e81778 100644
--- a/superset-frontend/src/components/ReportModal/index.tsx
+++ b/superset-frontend/src/components/ReportModal/index.tsx
@@ -18,28 +18,39 @@
*/
import React, {
useState,
+ // useEffect,
useCallback,
useReducer,
Reducer,
FunctionComponent,
} from 'react';
-import { styled, css, t } from '@superset-ui/core';
+import { t } from '@superset-ui/core';
+// import { useSingleViewResource } from 'src/views/CRUD/hooks';
+
+import { bindActionCreators } from 'redux';
+import { connect, useDispatch } from 'react-redux';
+import { addReport } from 'src/reports/actions/reportState';
import LabeledErrorBoundInput from 'src/components/Form/LabeledErrorBoundInput';
import Icons from 'src/components/Icons';
-import Modal from 'src/components/Modal';
+import withToasts from 'src/messageToasts/enhancers/withToasts';
import { CronPicker, CronError } from 'src/components/CronPicker';
-
-interface ReportProps {
- onHide: () => {};
- show: boolean;
- props: any;
-}
+import {
+ StyledModal,
+ StyledTopSection,
+ StyledBottomSection,
+ StyledIconWrapper,
+ StyledScheduleTitle,
+ StyledCronError,
+ noBottomMargin,
+ StyledFooterButton,
+} from './styles';
interface ReportObject {
active: boolean;
crontab: string;
- dashboard: number;
+ dashboard?: number;
+ chart?: number;
description?: string;
log_retention: number;
name: string;
@@ -50,6 +61,22 @@ interface ReportObject {
validator_config_json: {} | null;
validator_type: string;
working_timeout: number;
+ creation_method: string;
+}
+
+interface ReportProps {
+ addDangerToast: (msg: string) => void;
+ addSuccessToast: (msg: string) => void;
+ addReport: (report?: ReportObject) => {};
+ onHide: () => {};
+ onReportAdd: (report?: ReportObject) => {};
+ show: boolean;
+ userId: number;
+ userEmail: string;
+ dashboardId?: number;
+ chartId?: number;
+ creationMethod: string;
+ props: any;
}
enum ActionType {
@@ -94,47 +121,12 @@ const reportReducer = (
}
};
-const StyledModal = styled(Modal)`
- .ant-modal-body {
- padding: 0;
- }
-`;
-
-const StyledTopSection = styled.div`
- padding: ${({ theme }) => theme.gridUnit * 4}px;
-`;
-
-const StyledBottomSection = styled.div`
- border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
- padding: ${({ theme }) => theme.gridUnit * 4}px;
-`;
-
-const StyledIconWrapper = styled.span`
- span {
- margin-right: ${({ theme }) => theme.gridUnit * 2}px;
- vertical-align: middle;
- }
- .text {
- vertical-align: middle;
- }
-`;
-
-const StyledScheduleTitle = styled.div`
- margin-bottom: ${({ theme }) => theme.gridUnit * 7}px;
-`;
-
-const StyledCronError = styled.p`
- color: ${({ theme }) => theme.colors.error.base};
-`;
-
-const noBottomMargin = css`
- margin-bottom: 0;
-`;
-
const ReportModal: FunctionComponent<ReportProps> = ({
- show = false,
+ // addDangerToast,
+ onReportAdd,
onHide,
- props,
+ show = false,
+ ...props
}) => {
const [currentReport, setCurrentReport] = useReducer<
Reducer<Partial<ReportObject> | null, ReportActionType>
@@ -143,6 +135,59 @@ const ReportModal: FunctionComponent<ReportProps> = ({
setCurrentReport({ type, payload } as ReportActionType);
}, []);
const [error, setError] = useState<CronError>();
+ // ---------- comments on lines 21, 28, 125, 139-159 & 182 are being held for edit functionality
+ // const [hasConnectedReport, setHasConnectedReport] = useState<boolean>(false);
+ // const [isLoading, setLoading] = useState<boolean>(false);
+ const dispatch = useDispatch();
+
+ // Report fetch logic
+ // const {
+ // state: { resource },
+ // } = useSingleViewResource<ReportObject>(
+ // 'report',
+ // t('report'),
+ // addDangerToast,
+ // );
+
+ // useEffect(() => {
+ // if (resource?.dashboard) {
+ // setHasConnectedReport(true);
+ // }
+ // }, [resource?.dashboard]);
+
+ const onClose = () => {
+ // setLoading(false);
+ onHide();
+ };
+
+ const onSave = async () => {
+ // Create new Report
+ const newReportValues: Partial<ReportObject> = {
+ crontab: currentReport?.crontab,
+ dashboard: props.props.dashboardId,
+ chart: props.props.chartId,
+ description: currentReport?.description,
+ name: currentReport?.name || 'Weekly Report',
+ owners: [props.props.userId],
+ recipients: [
+ {
+ recipient_config_json: { target: props.props.userEmail },
+ type: 'Email',
+ },
+ ],
+ type: 'Report',
+ creation_method: props.props.creationMethod,
+ };
+
+ // setLoading(true);
+ await dispatch(addReport(newReportValues as ReportObject));
+
+ if (onReportAdd) {
+ onReportAdd();
+ }
+
+ onClose();
+ };
const wrappedTitle = (
<StyledIconWrapper>
@@ -151,8 +196,26 @@ const ReportModal: FunctionComponent<ReportProps> = ({
</StyledIconWrapper>
);
+ const renderModalFooter = (
+ <>
+ <StyledFooterButton key="back" onClick={onClose}>
+ Cancel
+ </StyledFooterButton>
+ <StyledFooterButton key="submit" buttonStyle="primary" onClick={onSave}>
+ Add
+ </StyledFooterButton>
+ </>
+ );
+
return (
- <StyledModal show={show} onHide={onHide} title={wrappedTitle}>
+ <StyledModal
+ show={show}
+ onHide={onClose}
+ title={wrappedTitle}
+ footer={renderModalFooter}
+ width="432"
+ centered
+ >
<StyledTopSection>
<LabeledErrorBoundInput
id="name"
@@ -196,7 +259,7 @@ const ReportModal: FunctionComponent<ReportProps> = ({
<StyledBottomSection>
<StyledScheduleTitle>
- <h1>Schedule</h1>
+ <h2>Schedule</h2>
<p>Scheduled reports will be sent to your email as a PNG</p>
</StyledScheduleTitle>
@@ -217,4 +280,7 @@ const ReportModal: FunctionComponent<ReportProps> = ({
);
};
-export default ReportModal;
+const mapDispatchToProps = (dispatch: any) =>
+ bindActionCreators({ addReport }, dispatch);
+
+export default connect(null, mapDispatchToProps)(withToasts(ReportModal));
diff --git a/superset-frontend/src/components/ReportModal/styles.tsx b/superset-frontend/src/components/ReportModal/styles.tsx
new file mode 100644
index 0000000..08fe73e
--- /dev/null
+++ b/superset-frontend/src/components/ReportModal/styles.tsx
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { styled, css } from '@superset-ui/core';
+import Modal from 'src/components/Modal';
+import Button from 'src/components/Button';
+
+export const StyledModal = styled(Modal)`
+ .ant-modal-body {
+ padding: 0;
+ }
+`;
+
+export const StyledTopSection = styled.div`
+ padding: ${({ theme }) => theme.gridUnit * 4}px;
+`;
+
+export const StyledBottomSection = styled.div`
+ border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
+ padding: ${({ theme }) => theme.gridUnit * 4}px;
+`;
+
+export const StyledIconWrapper = styled.span`
+ span {
+ margin-right: ${({ theme }) => theme.gridUnit * 2}px;
+ vertical-align: middle;
+ }
+ .text {
+ vertical-align: middle;
+ }
+`;
+
+export const StyledScheduleTitle = styled.div`
+ margin-bottom: ${({ theme }) => theme.gridUnit * 7}px;
+`;
+
+export const StyledCronError = styled.p`
+ color: ${({ theme }) => theme.colors.error.base};
+`;
+
+export const noBottomMargin = css`
+ margin-bottom: 0;
+`;
+
+export const StyledFooterButton = styled(Button)`
+ width: ${({ theme }) => theme.gridUnit * 40}px;
+`;
diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx
index 70ac4db..f2bc8d2 100644
--- a/superset-frontend/src/dashboard/components/Header/index.jsx
+++ b/superset-frontend/src/dashboard/components/Header/index.jsx
@@ -603,6 +603,7 @@ class Header extends React.PureComponent {
userId: user.userId,
userEmail: user.email,
dashboardId: dashboardInfo.id,
+ creationMethod: 'dashboards',
}}
/>
)}
diff --git a/superset-frontend/src/explore/components/ExploreChartHeader.jsx b/superset-frontend/src/explore/components/ExploreChartHeader.jsx
index e33f8e2..aeca9cd 100644
--- a/superset-frontend/src/explore/components/ExploreChartHeader.jsx
+++ b/superset-frontend/src/explore/components/ExploreChartHeader.jsx
@@ -280,10 +280,25 @@ export class ExploreChartHeader extends React.PureComponent {
isRunning={chartStatus === 'loading'}
status={CHART_STATUS_MAP[chartStatus]}
/>
+ <span
+ role="button"
+ title={t('Schedule email report')}
+ tabIndex={0}
+ className="action-button"
+ onClick={this.showReportModal}
+ >
+ <Icons.Calendar />
+ </span>
{this.canAddReports() && this.renderReportModal()}
<ReportModal
show={this.state.showingReportModal}
onHide={this.hideReportModal}
+ props={{
+ userId: this.props.userId,
+ userEmail: this.props.email,
+ chartId: this.props.chart.id,
+ creationMethod: 'charts',
+ }}
/>
<ExploreActionButtons
actions={{
diff --git a/superset-frontend/src/reports/actions/reportState.js b/superset-frontend/src/reports/actions/reportState.js
index 8bed099..f0c5b6a 100644
--- a/superset-frontend/src/reports/actions/reportState.js
+++ b/superset-frontend/src/reports/actions/reportState.js
@@ -70,6 +70,22 @@ export function fetchUISpecificReport(
};
}
+export const ADD_REPORT = 'ADD_REPORT';
+
+export const addReport = report => dispatch => {
+ SupersetClient.post({
+ endpoint: `/api/v1/report/`,
+ jsonPayload: report,
+ })
+ .then(() => {
+ dispatch({ type: ADD_REPORT, report });
+ })
+ .catch(() =>
+ dispatch(
+ addDangerToast(t('An error occurred while creating this report.')),
+ ),
+ );
+};
export const EDIT_REPORT = 'EDIT_REPORT';
export function reportEditor(report) {
diff --git a/superset-frontend/src/reports/reducers/reportState.js b/superset-frontend/src/reports/reducers/reportState.js
index 5946dbd..6493e0e 100644
--- a/superset-frontend/src/reports/reducers/reportState.js
+++ b/superset-frontend/src/reports/reducers/reportState.js
@@ -18,7 +18,12 @@
*/
/* eslint-disable camelcase */
import { alterInArr } from 'src/reduxUtils';
-import { SET_REPORT, EDIT_REPORT, TOGGLE_ACTIVE } from '../actions/reportState';
+import {
+ SET_REPORT,
+ ADD_REPORT,
+ EDIT_REPORT,
+ TOGGLE_ACTIVE,
+} from '../actions/reportState';
export default function reportStateReducer(state = {}, action) {
const actionHandlers = {
@@ -28,6 +33,12 @@ export default function reportStateReducer(state = {}, action) {
report: action.report,
};
},
+ [ADD_REPORT]() {
+ return {
+ ...state,
+ report: action.report,
+ };
+ },
[EDIT_REPORT]() {
return {
...state,