Skip to content

Commit

Permalink
feat: cleanup plugin error boundary [UX-136] (#856)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzemp authored Jun 24, 2024
1 parent 835b887 commit de252fe
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 16 deletions.
13 changes: 8 additions & 5 deletions adapter/i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"

Expand All @@ -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"

Expand Down
50 changes: 45 additions & 5 deletions adapter/src/components/ErrorBoundary.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => (
<>
<style jsx>{buttonStyles}</style>
<button onClick={onClick}>{children}</button>
<button className={plugin ? 'pluginButton' : null} onClick={onClick}>
{children}
</button>
</>
)

UIButton.propTypes = {
children: PropTypes.node.isRequired,
onClick: PropTypes.func.isRequired,
plugin: PropTypes.bool,
}

const InfoIcon24 = () => (
<svg
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m12 2c5.5228475 0 10 4.4771525 10 10s-4.4771525 10-10 10-10-4.4771525-10-10 4.4771525-10 10-10zm0 2c-4.418278 0-8 3.581722-8 8s3.581722 8 8 8 8-3.581722 8-8-3.581722-8-8-8zm1 7v6h-2v-6zm-1-4c.5522847 0 1 .44771525 1 1s-.4477153 1-1 1-1-.44771525-1-1 .4477153-1 1-1z"
fill="#A0ADBA"
></path>
</svg>
)

const translatedErrorHeading = i18n.t(
'An error occurred in the DHIS2 application.'
)
Expand Down Expand Up @@ -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 +
Expand All @@ -77,10 +101,26 @@ export class ErrorBoundary extends Component {
<>
<style jsx>{styles}</style>
<div className="pluginBoundary">
<span>I am the default plugin boundary</span>
<InfoIcon24 />
<div className="pluginErrorMessage">
{i18n.t(
'There was a problem loading this plugin'
)}
</div>
<div
className="pluginErrorCopy"
onClick={() => {
this.handleCopyErrorDetailsPlugin({
error: this.state.error,
errorInfo: this.state.errorInfo,
})
}}
>
{i18n.t('Copy debug info to clipboard')}
</div>
{onRetry && (
<div className="retry">
<UIButton onClick={onRetry}>
<div className="pluginRetry">
<UIButton onClick={onRetry} plugin>
{i18n.t('Try again')}
</UIButton>
</div>
Expand Down
14 changes: 13 additions & 1 deletion adapter/src/components/styles/Button.style.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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};
}
`
27 changes: 23 additions & 4 deletions adapter/src/components/styles/ErrorBoundary.style.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const bgColor = '#F4F6F8',
secondaryTextColor = '#494949',
errorColor = '#D32F2F',
grey050 = '#FBFCFD',
red200 = '#ffcdd2'
grey100 = '#F8F9FA',
grey600 = '#6C7787'

export default css`
.mask {
Expand Down Expand Up @@ -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;
}
`
46 changes: 45 additions & 1 deletion shell/src/PluginOuterErrorBoundary.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'

const grey100 = '#F8F9FA',
grey600 = '#6C7787'

const InfoIcon24 = () => (
<svg
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m12 2c5.5228475 0 10 4.4771525 10 10s-4.4771525 10-10 10-10-4.4771525-10-10 4.4771525-10 10-10zm0 2c-4.418278 0-8 3.581722-8 8s3.581722 8 8 8 8-3.581722 8-8-3.581722-8-8-8zm1 7v6h-2v-6zm-1-4c.5522847 0 1 .44771525 1 1s-.4477153 1-1 1-1-.44771525-1-1 .4477153-1 1-1z"
fill="#A0ADBA"
></path>
</svg>
)

export class PluginOuterErrorBoundary extends Component {
constructor(props) {
super(props)
Expand All @@ -20,7 +37,34 @@ export class PluginOuterErrorBoundary extends Component {
render() {
const { children } = this.props
if (this.state.error) {
return <p>Plugin outermost error boundary</p>
return (
<>
<div className="pluginBoundary">
<InfoIcon24 />
<div className="pluginErrorMessage">
There was a problem loading this plugin
</div>
</div>
<style jsx>
{`
.pluginBoundary {
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};
}
`}
</style>
</>
)
}

return children
Expand Down

0 comments on commit de252fe

Please sign in to comment.