Skip to content

Commit

Permalink
Merge branch 'aperture/PluginPOCFeature' into jwesson/merge-master-in…
Browse files Browse the repository at this point in the history
…to-POC
  • Loading branch information
jsnwesson authored Nov 8, 2023
2 parents c6c5521 + cd28310 commit 03a0552
Show file tree
Hide file tree
Showing 21 changed files with 903 additions and 63 deletions.
134 changes: 75 additions & 59 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"prop-types": "15.8.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-error-boundary": "^4.0.11",
"react-helmet": "6.1.0",
"react-redux": "7.2.9",
"react-router": "6.16.0",
Expand Down
93 changes: 93 additions & 0 deletions plugins/Plugin.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
'use client';

import React, {
useEffect, useMemo, useState,
} from 'react';
import PropTypes from 'prop-types';
import { ErrorBoundary } from 'react-error-boundary';
import { logError } from '@edx/frontend-platform/logging';
import {
dispatchMountedEvent, dispatchReadyEvent, dispatchUnmountedEvent, useHostEvent,
} from './data/hooks';
import { PLUGIN_RESIZE } from './data/constants';

// see example-plugin-app/src/PluginOne.jsx for example of customizing errorFallback
function errorFallbackDefault() {
return (
<div>
<h2>
Oops! An error occurred. Please refresh the screen to try again.
</h2>
</div>
);
}

// eslint-disable-next-line react/function-component-definition
export default function Plugin({
children, className, style, ready, errorFallbackProp,
}) {
const [dimensions, setDimensions] = useState({
width: null,
height: null,
});

const finalStyle = useMemo(() => ({
...dimensions,
...style,
}), [dimensions, style]);

const errorFallback = errorFallbackProp || errorFallbackDefault;

// Error logging function
// Need to confirm: When an error is caught here, the logging will be sent to the child MFE's logging service
const logErrorToService = (error, info) => {
logError(error, { stack: info.componentStack });
};

useHostEvent(PLUGIN_RESIZE, ({ payload }) => {
setDimensions({
width: payload.width,
height: payload.height,
});
});

useEffect(() => {
dispatchMountedEvent();

return () => {
dispatchUnmountedEvent();
};
}, []);

useEffect(() => {
if (ready) {
dispatchReadyEvent();
}
}, [ready]);

return (
<div className={className} style={finalStyle}>
<ErrorBoundary
FallbackComponent={errorFallback}
onError={logErrorToService}
>
{children}
</ErrorBoundary>
</div>
);
}

Plugin.propTypes = {
children: PropTypes.node.isRequired,
className: PropTypes.string,
errorFallbackProp: PropTypes.func,
ready: PropTypes.bool,
style: PropTypes.object, // eslint-disable-line
};

Plugin.defaultProps = {
className: null,
errorFallbackProp: null,
style: {},
ready: true,
};
42 changes: 42 additions & 0 deletions plugins/PluginContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client';

import React from 'react';

// eslint-disable-next-line import/no-extraneous-dependencies
import PluginContainerIframe from './PluginContainerIframe';

import {
IFRAME_PLUGIN,
} from './data/constants';
import { pluginConfigShape } from './data/shapes';

// eslint-disable-next-line react/function-component-definition
export default function PluginContainer({ config, ...props }) {
if (config === null) {
return null;
}

// this will allow for future plugin types to be inserted in the PluginErrorBoundary
let renderer = null;
switch (config.type) {
case IFRAME_PLUGIN:
renderer = (
<PluginContainerIframe config={config} {...props} />
);
break;
// istanbul ignore next: default isn't meaningful, just satisfying linter
default:
}

return (
renderer
);
}

PluginContainer.propTypes = {
config: pluginConfigShape,
};

PluginContainer.defaultProps = {
config: null,
};
Loading

0 comments on commit 03a0552

Please sign in to comment.