-
-
-
{
- logEvent('edx.ui.lms.sequence.next_selected', 'top');
- handleNext();
- }}
- onNavigate={(destinationUnitId) => {
- logEvent('edx.ui.lms.sequence.tab_selected', 'top', destinationUnitId);
- handleNavigate(destinationUnitId);
- }}
- previousSequenceHandler={() => {
- logEvent('edx.ui.lms.sequence.previous_selected', 'top');
- handlePrevious();
- }}
- goToCourseExitPage={() => goToCourseExitPage()}
- />
-
-
+
+
+
- {unitHasLoaded && (
- {
- logEvent('edx.ui.lms.sequence.previous_selected', 'bottom');
- handlePrevious();
- }}
- onClickNext={() => {
- logEvent('edx.ui.lms.sequence.next_selected', 'bottom');
+ className="mb-4"
+ /* This line should be reverted after REV1512 experiment */
+ toggleREV1512Flyover={toggleREV1512Flyover}
+ /* This line should be reverted after REV1512 experiment */
+ REV1512FlyoverEnabled={REV1512FlyoverEnabled}
+ /* should be reverted after REV1512 experiment */
+ isREV1512FlyoverVisible={isREV1512FlyoverVisible}
+ nextSequenceHandler={() => {
+ logEvent('edx.ui.lms.sequence.next_selected', 'top');
handleNext();
}}
+ onNavigate={(destinationUnitId) => {
+ logEvent('edx.ui.lms.sequence.tab_selected', 'top', destinationUnitId);
+ handleNavigate(destinationUnitId);
+ }}
+ previousSequenceHandler={() => {
+ logEvent('edx.ui.lms.sequence.previous_selected', 'top');
+ handlePrevious();
+ }}
goToCourseExitPage={() => goToCourseExitPage()}
/>
- )}
-
-
- {/* This block of code should be reverted post REV1512 experiment */}
- {REV1512FlyoverEnabled && isREV1512FlyoverVisible() && (
- isMobile
- ?
- :
- )}
-
+
+
+ {unitHasLoaded && (
+ {
+ logEvent('edx.ui.lms.sequence.previous_selected', 'bottom');
+ handlePrevious();
+ }}
+ onClickNext={() => {
+ logEvent('edx.ui.lms.sequence.next_selected', 'bottom');
+ handleNext();
+ }}
+ goToCourseExitPage={() => goToCourseExitPage()}
+ />
+ )}
+
+
+
+
+
+ {/* This block of code should be reverted post REV1512 experiment */}
+ {REV1512FlyoverEnabled && isREV1512FlyoverVisible() && (
+ isMobile
+ ?
+ :
+ )}
+
+
);
@@ -380,6 +396,7 @@ function Sequence({
Sequence.propTypes = {
unitId: PropTypes.string,
sequenceId: PropTypes.string,
+ sectionId: PropTypes.string,
courseId: PropTypes.string.isRequired,
unitNavigationHandler: PropTypes.func.isRequired,
nextSequenceHandler: PropTypes.func.isRequired,
@@ -392,6 +409,7 @@ Sequence.propTypes = {
Sequence.defaultProps = {
sequenceId: null,
+ sectionId: null,
unitId: null,
};
diff --git a/src/index.jsx b/src/index.jsx
index 9dc01be5..a457b2a2 100755
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -4,6 +4,7 @@ import 'regenerator-runtime/runtime';
import {
APP_INIT_ERROR, APP_READY, subscribe, initialize,
mergeConfig,
+ getConfig,
} from '@edx/frontend-platform';
import { AppProvider, ErrorPage, PageRoute } from '@edx/frontend-platform/react';
import React from 'react';
@@ -28,6 +29,8 @@ import { fetchDatesTab, fetchOutlineTab, fetchProgressTab } from './course-home/
import { fetchCourse } from './courseware/data';
import initializeStore from './store';
import PluginTestPage from './plugin-test/PluginTestPage';
+import { COMPONENT } from './plugin-test/PluginComponent';
+import { loadDynamicScript, loadScriptComponent } from './plugin-test/utils';
subscribe(APP_READY, () => {
ReactDOM.render(
@@ -70,6 +73,13 @@ subscribe(APP_READY, () => {
,
document.getElementById('root'),
);
+
+ getConfig().plugins.scripts.forEach((plugin) => {
+ loadDynamicScript(plugin.url).then(() => {
+ const pluginFunction = loadScriptComponent(plugin.scope, plugin.module);
+ pluginFunction();
+ });
+ });
});
subscribe(APP_INIT_ERROR, (error) => {
@@ -92,6 +102,43 @@ initialize({
SUPPORT_URL_VERIFIED_CERTIFICATE: process.env.SUPPORT_URL_VERIFIED_CERTIFICATE || null,
TWITTER_HASHTAG: process.env.TWITTER_HASHTAG || null,
TWITTER_URL: process.env.TWITTER_URL || null,
+ plugins: {
+ scripts: [
+ // {
+ // url: 'http://localhost:7331/remoteEntry.js',
+ // scope: 'plugin',
+ // module: './Pomodoro',
+ // type: SCRIPT,
+ // },
+ ],
+ slots: {
+ header: [
+ {
+ url: 'http://localhost:7331/remoteEntry.js',
+ scope: 'plugin',
+ module: './Banner',
+ type: COMPONENT,
+ },
+ ],
+ coursewareSidebar: [
+ {
+ url: 'http://localhost:7331/remoteEntry.js',
+ scope: 'plugin',
+ module: './Discussions',
+ type: COMPONENT,
+ },
+ {
+ url: 'http://localhost:7331/remoteEntry.js',
+ scope: 'plugin',
+ module: './Calendly',
+ type: COMPONENT,
+ props: {
+ username: 'djoy',
+ },
+ },
+ ],
+ },
+ },
}, 'LearnerAppConfig');
},
},
diff --git a/src/index.scss b/src/index.scss
index 1b5902a4..cd2adb61 100755
--- a/src/index.scss
+++ b/src/index.scss
@@ -95,8 +95,6 @@
}
.sequence-container {
- display: flex;
- flex-direction: column;
flex-grow: 1;
margin-bottom: 4rem;
@@ -111,6 +109,7 @@
}
.sequence {
+ width: 100%;
@media (min-width: map-get($grid-breakpoints, 'sm')) {
border: solid 1px #EAEAEA;
border-radius: 4px;
@@ -302,9 +301,9 @@
.unit-iframe-wrapper {
margin: 0 -20px 2rem;
- @media (min-width: 830px) {
- margin: 0 -40px 2rem;
- }
+ // @media (min-width: 830px) {
+ // margin: 0 -20px 2rem;
+ // }
}
#unit-iframe {
diff --git a/src/plugin-test/Plugin.jsx b/src/plugin-test/PluginComponent.jsx
similarity index 77%
rename from src/plugin-test/Plugin.jsx
rename to src/plugin-test/PluginComponent.jsx
index c1141f88..ac64e781 100644
--- a/src/plugin-test/Plugin.jsx
+++ b/src/plugin-test/PluginComponent.jsx
@@ -5,6 +5,7 @@ import PageLoading from '../generic/PageLoading';
import messages from './messages';
import { loadDynamicScript, loadScriptComponent } from './utils';
+import PluginErrorBoundary from './PluginErrorBoundary';
// These are intended to represent three different plugin types. They're not fully used yet.
// Different plugins of different types would have different loading functionality.
@@ -16,6 +17,7 @@ export const LTI = 'lti'; // loads LTI iframe at the URL, rather than loading a
const useDynamicScript = (url) => {
const [ready, setReady] = React.useState(false);
const [failed, setFailed] = React.useState(false);
+ // eslint-disable-next-line no-unused-vars
const [element, setElement] = React.useState(null);
React.useEffect(() => {
if (!url) {
@@ -34,7 +36,9 @@ const useDynamicScript = (url) => {
});
return () => {
- document.head.removeChild(element);
+ // TODO: How to do reference checking on this script to only remove it when the last
+ // component using it has unmounted?
+ // document.head.removeChild(element);
};
}, [url]);
@@ -44,7 +48,7 @@ const useDynamicScript = (url) => {
};
};
-function Plugin({ plugin, intl }) {
+function PluginComponent({ plugin, intl, ...props }) {
const url = plugin ? plugin.url : null;
const { ready, failed } = useDynamicScript(url);
@@ -64,7 +68,7 @@ function Plugin({ plugin, intl }) {
return null;
}
- const PluginComponent = React.lazy(
+ const Component = React.lazy(
loadScriptComponent(plugin.scope, plugin.module),
);
@@ -76,23 +80,26 @@ function Plugin({ plugin, intl }) {
/>
)}
>
- Plugin failed to load.
;
+ }
+
+ return this.props.children;
+ }
+}
+
+PluginErrorBoundary.propTypes = {
+ children: PropTypes.node,
+};
+
+PluginErrorBoundary.defaultProps = {
+ children: null,
+};
diff --git a/src/plugin-test/PluginTestPage.jsx b/src/plugin-test/PluginTestPage.jsx
index 614afc00..46f19b78 100644
--- a/src/plugin-test/PluginTestPage.jsx
+++ b/src/plugin-test/PluginTestPage.jsx
@@ -1,30 +1,9 @@
import React from 'react';
-import { Button } from '@edx/paragon';
-
-import Plugin, { SCRIPT, COMPONENT } from './Plugin';
+import { getConfig } from '@edx/frontend-platform';
+import PluginComponent from './PluginComponent';
function PluginTestPage() {
- const [plugin, setPlugin] = React.useState(undefined);
-
- function setPluginOne() {
- setPlugin({
- url: 'http://localhost:7331/remoteEntry.js',
- scope: 'plugin',
- module: './PluginOne',
- type: SCRIPT,
- });
- }
-
- function setPluginTwo() {
- setPlugin({
- url: 'http://localhost:7331/remoteEntry.js',
- scope: 'plugin',
- module: './PluginTwo',
- type: COMPONENT,
- });
- }
-
return (
Dynamic Plugin Host
@@ -34,10 +13,15 @@ function PluginTestPage() {
remotes and
exposes. It will no load
components that have been loaded already.
-
-
+ {/*
+
*/}
-
+ {getConfig().plugins.slots.testPage.map((plugin) => (
+
+ ))}
);
diff --git a/src/tab-page/LoadedTabPage.jsx b/src/tab-page/LoadedTabPage.jsx
index b7cb9288..5f5f062c 100644
--- a/src/tab-page/LoadedTabPage.jsx
+++ b/src/tab-page/LoadedTabPage.jsx
@@ -10,6 +10,7 @@ import { AlertList } from '../generic/user-messages';
import InstructorToolbar from '../instructor-toolbar';
import useEnrollmentAlert from '../alerts/enrollment-alert';
import useLogistrationAlert from '../alerts/logistration-alert';
+import PluginComponent from '../plugin-test/PluginComponent';
function LoadedTabPage({
activeTabSlug,
@@ -38,6 +39,12 @@ function LoadedTabPage({