From 9ae7c39aac22e1709c9f5e63423e7f2bf3a1fa1d Mon Sep 17 00:00:00 2001 From: Przemek Wiech Date: Fri, 25 Oct 2019 18:54:45 +0200 Subject: [PATCH] Display error when failed to generate pdf or png #3 --- src/app.tsx | 103 +++++++++++++++++++++++++++++++++++---- src/index.css | 8 ++- src/translations/pl.json | 6 ++- 3 files changed, 106 insertions(+), 11 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 3d45076..f39e80a 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -3,24 +3,57 @@ import * as React from 'react'; import {analyticsEvent} from './analytics'; import {Chart, ChartType} from './chart'; import {Details} from './details'; +import {FormattedMessage} from 'react-intl'; import {getSelection, loadFromUrl, loadGedcom} from './load_data'; +import {getSoftware, TopolaData} from './gedcom_util'; import {IndiInfo} from 'topola'; +import {intlShape} from 'react-intl'; import {Intro} from './intro'; -import {Loader, Message, Responsive} from 'semantic-ui-react'; +import {Loader, Message, Portal, Responsive} from 'semantic-ui-react'; import {Redirect, Route, RouteComponentProps, Switch} from 'react-router-dom'; import {TopBar} from './top_bar'; -import {TopolaData, getSoftware} from './gedcom_util'; -/** Shows an error message. */ -export function ErrorMessage(props: {message: string}) { +/** Shows an error message in the middle of the screen. */ +function ErrorMessage(props: {message?: string}) { return ( - Failed to load file + + +

{props.message}

); } +interface ErrorPopupProps { + message?: string; + open: boolean; + onDismiss: () => void; +} + +/** + * Shows a dismissable error message in the bottom left corner of the screen. + */ +function ErrorPopup(props: ErrorPopupProps) { + return ( + + + + + +

{props.message}

+
+
+ ); +} + /** * Message types used in embedded mode. * When the parent is ready to receive messages, it sends PARENT_READY. @@ -65,6 +98,8 @@ interface State { standalone: boolean; /** Type of displayed chart. */ chartType: ChartType; + /** Whether to show the error popup. */ + showErrorPopup: boolean; } export class App extends React.Component { @@ -73,9 +108,15 @@ export class App extends React.Component { embedded: false, standalone: true, chartType: ChartType.Hourglass, + showErrorPopup: false, }; chartRef: Chart | null = null; + /** Make intl appear in this.context. */ + static contextTypes = { + intl: intlShape, + }; + private isNewData( hash: string | undefined, url: string | undefined, @@ -277,14 +318,45 @@ export class App extends React.Component { this.chartRef && this.chartRef.print(); }; - private onDownloadPdf = () => { + private showErrorPopup(message: string) { + this.setState( + Object.assign({}, this.state, { + showErrorPopup: true, + error: message, + }), + ); + } + + private onDownloadPdf = async () => { analyticsEvent('download_pdf'); - this.chartRef && this.chartRef.downloadPdf(); + try { + this.chartRef && (await this.chartRef.downloadPdf()); + } catch (e) { + this.showErrorPopup( + this.context.intl.formatMessage({ + id: 'error.failed_pdf', + defaultMessage: + 'Failed to generate PDF file.' + + ' Please try with a smaller diagram or download an SVG file.', + }), + ); + } }; - private onDownloadPng = () => { + private onDownloadPng = async () => { analyticsEvent('download_png'); - this.chartRef && this.chartRef.downloadPng(); + try { + this.chartRef && (await this.chartRef.downloadPng()); + } catch (e) { + this.showErrorPopup( + this.context.intl.formatMessage({ + id: 'error.failed_png', + defaultMessage: + 'Failed to generate PNG file.' + + ' Please try with a smaller diagram or download an SVG file.', + }), + ); + } }; private onDownloadSvg = () => { @@ -292,10 +364,23 @@ export class App extends React.Component { this.chartRef && this.chartRef.downloadSvg(); }; + onDismissErrorPopup = () => { + this.setState( + Object.assign({}, this.state, { + showErrorPopup: false, + }), + ); + }; + private renderMainArea = () => { if (this.state.data && this.state.selection) { return (
+