diff --git a/adapter/i18n/en.pot b/adapter/i18n/en.pot index da6efefa..7cd6b8da 100644 --- a/adapter/i18n/en.pot +++ b/adapter/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2024-04-24T13:58:13.591Z\n" -"PO-Revision-Date: 2024-04-24T13:58:13.591Z\n" +"POT-Creation-Date: 2024-06-21T08:27:55.991Z\n" +"PO-Revision-Date: 2024-06-21T08:27:55.991Z\n" msgid "Save your data" msgstr "Save your data" @@ -39,6 +39,12 @@ msgstr "An error occurred in the DHIS2 application." msgid "Technical details copied to clipboard" msgstr "Technical details copied to clipboard" +msgid "There was a problem loading this plugin" +msgstr "There was a problem loading this plugin" + +msgid "Copy debug info to clipboard" +msgstr "Copy debug info to clipboard" + msgid "Try again" msgstr "Try again" @@ -48,9 +54,6 @@ msgstr "Something went wrong" msgid "Redirect to safe login mode" msgstr "Redirect to safe login mode" -msgid "Redirect to safe login mode" -msgstr "Redirect to safe login mode" - msgid "Hide technical details" msgstr "Hide technical details" diff --git a/adapter/src/components/ErrorBoundary.js b/adapter/src/components/ErrorBoundary.js index 6365848d..e8049e84 100644 --- a/adapter/src/components/ErrorBoundary.js +++ b/adapter/src/components/ErrorBoundary.js @@ -8,18 +8,35 @@ import styles from './styles/ErrorBoundary.style.js' // In order to avoid using @dhis2/ui components in the error boundary - as anything // that breaks within it will not be caught properly - we define a component // with the same styles as Button -const UIButton = ({ children, onClick }) => ( +const UIButton = ({ children, onClick, plugin }) => ( <> - + ) UIButton.propTypes = { children: PropTypes.node.isRequired, onClick: PropTypes.func.isRequired, + plugin: PropTypes.bool, } +const InfoIcon24 = () => ( + + + +) + const translatedErrorHeading = i18n.t( 'An error occurred in the DHIS2 application.' ) @@ -61,6 +78,13 @@ export class ErrorBoundary extends Component { }) } + handleCopyErrorDetailsPlugin = ({ error, errorInfo }) => { + const errorDetails = `${error}\n${error?.stack}\n${errorInfo?.componentStack}` + navigator.clipboard.writeText(errorDetails).then(() => { + alert(i18n.t('Technical details copied to clipboard')) + }) + } + handleSafeLoginRedirect = () => { window.location.href = this.props.baseURL + @@ -77,10 +101,26 @@ export class ErrorBoundary extends Component { <>
- I am the default plugin boundary + +
+ {i18n.t( + 'There was a problem loading this plugin' + )} +
+
{ + this.handleCopyErrorDetailsPlugin({ + error: this.state.error, + errorInfo: this.state.errorInfo, + }) + }} + > + {i18n.t('Copy debug info to clipboard')} +
{onRetry && ( -
- +
+ {i18n.t('Try again')}
diff --git a/adapter/src/components/styles/Button.style.js b/adapter/src/components/styles/Button.style.js index b251dce3..b096d000 100644 --- a/adapter/src/components/styles/Button.style.js +++ b/adapter/src/components/styles/Button.style.js @@ -7,7 +7,8 @@ import css from 'styled-jsx/css' const grey900 = '#21934', grey500 = '#a0adba', grey200 = '#f3f5f7', - primary600 = '#147cd7' + primary600 = '#147cd7', + grey600 = '#6C7787' export default css` button { @@ -87,4 +88,15 @@ export default css` button:focus::after { border-color: ${primary600}; } + + .pluginButton { + /*small*/ + height: 28px; + padding: 0 6px; + font-size: 14px; + line-height: 16px; + + /*text color for plugin error*/ + color: ${grey600}; + } ` diff --git a/adapter/src/components/styles/ErrorBoundary.style.js b/adapter/src/components/styles/ErrorBoundary.style.js index cceaa76c..3ab75c0b 100644 --- a/adapter/src/components/styles/ErrorBoundary.style.js +++ b/adapter/src/components/styles/ErrorBoundary.style.js @@ -6,7 +6,8 @@ const bgColor = '#F4F6F8', secondaryTextColor = '#494949', errorColor = '#D32F2F', grey050 = '#FBFCFD', - red200 = '#ffcdd2' + grey100 = '#F8F9FA', + grey600 = '#6C7787' export default css` .mask { @@ -103,10 +104,28 @@ export default css` } .pluginBoundary { - background-color: ${red200}; + background-color: ${grey100}; + height: 100vh; + width: 100vw; + display: flex; + flex-direction: column; + align-items: center; + padding-block-start: 16px; + } + + .pluginErrorMessage { + margin-block-start: 8px; + color: ${grey600}; + } + + .pluginErrorCopy { + margin-block-start: 8px; + color: ${grey600}; + text-decoration: underline; + font-size: 14px; } - .pluginBoundary span { - display: inline-block; + .pluginRetry { + margin-block-start: 16px; } ` diff --git a/shell/src/PluginOuterErrorBoundary.js b/shell/src/PluginOuterErrorBoundary.js index 38f7092a..697490cb 100644 --- a/shell/src/PluginOuterErrorBoundary.js +++ b/shell/src/PluginOuterErrorBoundary.js @@ -1,6 +1,23 @@ import PropTypes from 'prop-types' import React, { Component } from 'react' +const grey100 = '#F8F9FA', + grey600 = '#6C7787' + +const InfoIcon24 = () => ( + + + +) + export class PluginOuterErrorBoundary extends Component { constructor(props) { super(props) @@ -20,7 +37,34 @@ export class PluginOuterErrorBoundary extends Component { render() { const { children } = this.props if (this.state.error) { - return

Plugin outermost error boundary

+ return ( + <> +
+ +
+ There was a problem loading this plugin +
+
+ + + ) } return children