Skip to content

Commit

Permalink
feat: implement plugin wrapper (receiver in plugin) (alpha) (#786)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzemp authored Mar 13, 2023
2 parents fb018b9 + d5e17e1 commit d4f1ee2
Show file tree
Hide file tree
Showing 13 changed files with 849 additions and 1,444 deletions.
10 changes: 5 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: 2022-09-22T19:11:17.660Z\n"
"PO-Revision-Date: 2022-09-22T19:11:17.660Z\n"
"POT-Creation-Date: 2023-02-08T14:36:41.461Z\n"
"PO-Revision-Date: 2023-02-08T14:36:41.461Z\n"

msgid "Save your data"
msgstr "Save your data"
Expand Down Expand Up @@ -39,12 +39,12 @@ msgstr "An error occurred in the DHIS2 application."
msgid "Technical details copied to clipboard"
msgstr "Technical details copied to clipboard"

msgid "Something went wrong"
msgstr "Something went wrong"

msgid "Try again"
msgstr "Try again"

msgid "Something went wrong"
msgstr "Something went wrong"

msgid "Hide technical details"
msgstr "Hide technical details"

Expand Down
3 changes: 2 additions & 1 deletion adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
],
"dependencies": {
"@dhis2/pwa": "10.3.1",
"moment": "^2.24.0"
"moment": "^2.24.0",
"post-robot": "^10.0.46"
},
"devDependencies": {
"@dhis2/cli-app-scripts": "10.3.1",
Expand Down
29 changes: 27 additions & 2 deletions adapter/src/components/AppWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,39 @@ import { ErrorBoundary } from './ErrorBoundary.js'
import { LoadingMask } from './LoadingMask.js'
import { styles } from './styles/AppWrapper.style.js'

export const AppWrapper = ({ children, plugin }) => {
const AppWrapper = ({ children, plugin, onPluginError, clearPluginError }) => {
const { loading: localeLoading } = useCurrentUserLocale()
const { loading: latestUserLoading } = useVerifyLatestUser()

if (localeLoading || latestUserLoading) {
return <LoadingMask />
}

if (plugin) {
return (
<div className="app-shell-adapter">
<style jsx>{styles}</style>
<div className="app-shell-app">
<ErrorBoundary
plugin={true}
onPluginError={onPluginError}
onRetry={() => {
clearPluginError()
window.location.reload()
}}
>
{children}
</ErrorBoundary>
</div>
<Alerts />
</div>
)
}

return (
<div className="app-shell-adapter">
<style jsx>{styles}</style>
{!plugin && <ConnectedHeaderBar />}
<ConnectedHeaderBar />
<div className="app-shell-app">
<ErrorBoundary onRetry={() => window.location.reload()}>
{children}
Expand All @@ -32,5 +53,9 @@ export const AppWrapper = ({ children, plugin }) => {

AppWrapper.propTypes = {
children: PropTypes.node,
clearPluginError: PropTypes.func,
plugin: PropTypes.bool,
onPluginError: PropTypes.func,
}

export { AppWrapper }
25 changes: 25 additions & 0 deletions adapter/src/components/ErrorBoundary.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export class ErrorBoundary extends Component {
}

componentDidCatch(error, errorInfo) {
if (this.props.plugin) {
if (this.props.onPluginError) {
console.error(error)
this.props.onPluginError(error)
}
}
this.setState({
error,
errorInfo,
Expand All @@ -58,6 +64,23 @@ export class ErrorBoundary extends Component {
render() {
const { children, fullscreen, onRetry } = this.props
if (this.state.error) {
if (this.props.plugin) {
return (
<>
<style jsx>{styles}</style>
<div className="pluginBoundary">
<span>I am the default plugin boundary</span>
{onRetry && (
<div className="retry">
<UIButton onClick={onRetry}>
{i18n.t('Try again')}
</UIButton>
</div>
)}
</div>
</>
)
}
return (
<div className={cx('mask', { fullscreen })}>
<style jsx>{styles}</style>
Expand Down Expand Up @@ -119,5 +142,7 @@ export class ErrorBoundary extends Component {
ErrorBoundary.propTypes = {
children: PropTypes.node.isRequired,
fullscreen: PropTypes.bool,
plugin: PropTypes.bool,
onPluginError: PropTypes.func,
onRetry: PropTypes.func,
}
9 changes: 9 additions & 0 deletions adapter/src/components/ServerVersionProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export const ServerVersionProvider = ({
url, // url from env vars
apiVersion,
pwaEnabled,
plugin,
parentAlertsAdd,
showAlertsInPlugin,
children,
}) => {
const offlineInterface = useOfflineInterface()
Expand Down Expand Up @@ -160,6 +163,9 @@ export const ServerVersionProvider = ({
pwaEnabled,
}}
offlineInterface={offlineInterface}
plugin={plugin}
parentAlertsAdd={parentAlertsAdd}
showAlertsInPlugin={showAlertsInPlugin}
>
{children}
</Provider>
Expand All @@ -171,6 +177,9 @@ ServerVersionProvider.propTypes = {
appVersion: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
parentAlertsAdd: PropTypes.func,
plugin: PropTypes.bool,
pwaEnabled: PropTypes.bool,
showAlertsInPlugin: PropTypes.bool,
url: PropTypes.string,
}
11 changes: 10 additions & 1 deletion adapter/src/components/styles/ErrorBoundary.style.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const bgColor = '#F4F6F8',
primaryTextColor = '#000000',
secondaryTextColor = '#494949',
errorColor = '#D32F2F',
grey050 = '#FBFCFD'
grey050 = '#FBFCFD',
red200 = '#ffcdd2'

export default css`
.mask {
Expand Down Expand Up @@ -100,4 +101,12 @@ export default css`
color: ${errorColor};
font-family: Menlo, Courier, monospace !important;
}
.pluginBoundary {
background-color: ${red200};
}
.pluginBoundary span {
display: inline-block;
}
`
25 changes: 23 additions & 2 deletions adapter/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ const AppAdapter = ({
apiVersion,
pwaEnabled,
plugin,
parentAlertsAdd,
showAlertsInPlugin,
onPluginError,
clearPluginError,
children,
}) => (
<ErrorBoundary fullscreen onRetry={checkForSWUpdateAndReload}>
<ErrorBoundary
plugin={plugin}
fullscreen
onRetry={checkForSWUpdateAndReload}
>
<OfflineInterfaceProvider>
<PWALoadingBoundary>
<ServerVersionProvider
Expand All @@ -25,8 +33,17 @@ const AppAdapter = ({
url={url}
apiVersion={apiVersion}
pwaEnabled={pwaEnabled}
plugin={plugin}
parentAlertsAdd={parentAlertsAdd}
showAlertsInPlugin={showAlertsInPlugin}
>
<AppWrapper plugin={plugin}>{children}</AppWrapper>
<AppWrapper
plugin={plugin}
onPluginError={onPluginError}
clearPluginError={clearPluginError}
>
{children}
</AppWrapper>
</ServerVersionProvider>
</PWALoadingBoundary>
</OfflineInterfaceProvider>
Expand All @@ -38,9 +55,13 @@ AppAdapter.propTypes = {
appVersion: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
clearPluginError: PropTypes.func,
parentAlertsAdd: PropTypes.func,
plugin: PropTypes.bool,
pwaEnabled: PropTypes.bool,
showAlertsInPlugin: PropTypes.func,
url: PropTypes.string,
onPluginError: PropTypes.func,
}

export default AppAdapter
1 change: 1 addition & 0 deletions cli/config/plugin.webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = ({ env: webpackEnv, config, paths }) => {

const shellEnv = getShellEnv({
plugin: 'true',
requiredProps: config.requiredProps ? config.requiredProps.join() : '',
name: config.title,
...getPWAEnvVars(config),
})
Expand Down
3 changes: 2 additions & 1 deletion shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
"@dhis2/app-runtime": "^3.9.0",
"@dhis2/d2-i18n": "^1.1.1",
"@dhis2/pwa": "10.3.1",
"@dhis2/ui": "^8.6.2",
"@dhis2/ui": "^8.7.7",
"classnames": "^2.2.6",
"moment": "^2.29.1",
"post-robot": "^10.0.46",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
Expand Down
57 changes: 52 additions & 5 deletions shell/src/App.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
import AppAdapter from '@dhis2/app-adapter'
import { Layer, layers, CenteredContent, CircularLoader } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React from 'react'
import { PluginLoader } from './PluginLoader'
import { PluginOuterErrorBoundary } from './PluginOuterErrorBoundary'

const D2App = React.lazy(() =>
import(/*webpackChunkName: 'app'*/ './D2App/app')
) // Automatic bundle splitting!

const parseRequiredProps = (propsEnvVariable) => {
if (!propsEnvVariable || propsEnvVariable === '') {
return []
}
return propsEnvVariable.split(',')
}

const isPlugin = process.env.REACT_APP_DHIS2_APP_PLUGIN === 'true'
const requiredPluginProps = parseRequiredProps(
process.env.REACT_APP_DHIS2_APP_REQUIREDPROPS
)

const appConfig = {
url: process.env.REACT_APP_DHIS2_BASE_URL,
appName: process.env.REACT_APP_DHIS2_APP_NAME || '',
appVersion: process.env.REACT_APP_DHIS2_APP_VERSION || '',
apiVersion: parseInt(process.env.REACT_APP_DHIS2_API_VERSION),
pwaEnabled: process.env.REACT_APP_DHIS2_APP_PWA_ENABLED === 'true',
plugin: process.env.REACT_APP_DHIS2_APP_PLUGIN === 'true',
plugin: isPlugin,
}

const App = () => (
<AppAdapter {...appConfig}>
const pluginConfig = {
...appConfig,
requiredProps: requiredPluginProps,
}

const App = ({ config }) => (
<AppAdapter {...config}>
<React.Suspense
fallback={
<Layer translucent level={layers.alert}>
Expand All @@ -26,9 +46,36 @@ const App = () => (
</Layer>
}
>
<D2App config={appConfig} />
<D2App config={config} />
</React.Suspense>
</AppAdapter>
)

export default App
App.propTypes = {
config: PropTypes.object,
}

const Plugin = ({ config }) => {
return (
<PluginOuterErrorBoundary>
<PluginLoader
config={config}
requiredProps={requiredPluginProps}
D2App={D2App}
/>
</PluginOuterErrorBoundary>
)
}

Plugin.propTypes = {
config: PropTypes.object,
}

const AppOrPlugin = () => {
if (isPlugin) {
return <Plugin config={pluginConfig} />
}
return <App config={appConfig} />
}

export default AppOrPlugin
Loading

0 comments on commit d4f1ee2

Please sign in to comment.