I attended the fantastic frontend plugin workshop at the Open edX conference today. I had an env.config.jsx that looked like this at the end of the session:
import React from 'react';
import { Button } from '@openedx/paragon'
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
unit_contents_slot: {
keepDefault: true,
plugins: [
{
// Display the unit ID *above* the content
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'before_unit_content',
priority: 10, // 10 will come before the unit content, which has priority 50
type: DIRECT_PLUGIN,
RenderWidget: (props) => (
<div style={{backgroundColor: 'cornflowerblue', color: 'white', padding: '8px 2px'}}>
<small>This unit is <code style={{color: 'white'}}>{props.unitId}</code></small>
</div>
),
},
},
{ // Blur the content until the user confirms they are ready to learn
op: PLUGIN_OPERATIONS.Wrap,
widgetId: 'default_contents', // Wrap the contents
wrapper: ({ component }) => {
const [isBlurred, setBlur] = React.useState(true);
if (isBlurred) {
return (
<div style={{position: 'relative'}}>
<div style={{filter: 'blur(5px)', pointerEvents: 'none'}}>
{ component }
</div>
<div style={{
position: 'absolute', backgroundColor: 'white', left: '10%',
width: '80%', top: '200px', padding: '30px', border: '1px solid darkgrey',
}}>
<p>Are you sure you want to learn this now?</p>
<Button onClick={() => setBlur(false)}>Yes</Button>
</div>
</div>
);
} else {
return <>{ component }</>;
}
},
},
],
},
},
}
export default config;
and I found myself wondering: why do we need a list of operations at all? Assuming that there is only env.config.jsx file, couldnât the plugins
list just be replaced with a single component function, wrapping the slot defaults? ie:
import React from 'react';
import { Button } from '@openedx/paragon'
const config = {
pluginSlots: {
unit_contents_slot: (DefaultComponent, props, children) => {
const beforeContent = (
<div style={{backgroundColor: 'cornflowerblue', color: 'white', padding: '8px 2px'}}>
<small>This unit is <code style={{color: 'white'}}>{props.unitId}</code></small>
</div>
);
const [isBlurred, setBlur] = React.useState(true);
if (isBlurred) {
return (
<>
{beforeContent}
<div style={{position: 'relative'}}>
<div style={{filter: 'blur(5px)', pointerEvents: 'none'}}>
<DefaultComponent {...props}> {children} </DefaultComponent>
</div>
<div style={{
position: 'absolute', backgroundColor: 'white', left: '10%',
width: '80%', top: '200px', padding: '30px', border: '1px solid darkgrey',
}}>
<p>Are you sure you want to learn this now?</p>
<Button onClick={() => setBlur(false)}>Yes</Button>
</div>
</div>
</>
);
} else {
return (
<>
{beforeContent}
<DefaultComponent {...props}>
{children}
<DefaultComponent/>
</>
)
}
}
}
};