Compare commits
1 Commits
dependabot
...
kshitij/th
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40ab53d793 |
1
.env
1
.env
@@ -20,3 +20,4 @@ REFRESH_ACCESS_TOKEN_ENDPOINT=''
|
|||||||
SEGMENT_KEY=''
|
SEGMENT_KEY=''
|
||||||
SITE_NAME=''
|
SITE_NAME=''
|
||||||
USER_INFO_COOKIE_NAME=''
|
USER_INFO_COOKIE_NAME=''
|
||||||
|
THEME_LOADER_URL=''
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ REFRESH_ACCESS_TOKEN_ENDPOINT='http://localhost:18000/login_refresh'
|
|||||||
SEGMENT_KEY=''
|
SEGMENT_KEY=''
|
||||||
SITE_NAME=localhost
|
SITE_NAME=localhost
|
||||||
USER_INFO_COOKIE_NAME='edx-user-info'
|
USER_INFO_COOKIE_NAME='edx-user-info'
|
||||||
|
THEME_LOADER_URL='https://xitij2000.github.io/frontend-theme-prototype/themes.js'
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
|
|
||||||
import { PostActionsBar } from '../../components';
|
import { PostActionsBar } from '../../components';
|
||||||
import { ALL_ROUTES, DiscussionProvider, Routes } from '../../data/constants';
|
import { ALL_ROUTES, DiscussionProvider, Routes } from '../../data/constants';
|
||||||
|
import { useTheme } from '../../theme-hooks';
|
||||||
import { DiscussionContext } from '../common/context';
|
import { DiscussionContext } from '../common/context';
|
||||||
import {
|
import {
|
||||||
useCourseDiscussionData, useIsOnDesktop, useRedirectToThread, useSidebarVisible,
|
useCourseDiscussionData, useIsOnDesktop, useRedirectToThread, useSidebarVisible,
|
||||||
@@ -21,6 +22,7 @@ import DiscussionSidebar from './DiscussionSidebar';
|
|||||||
|
|
||||||
export default function DiscussionsHome() {
|
export default function DiscussionsHome() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
const ready = useTheme('red_theme');
|
||||||
const postEditorVisible = useSelector(
|
const postEditorVisible = useSelector(
|
||||||
(state) => state.threads.postEditorVisible,
|
(state) => state.threads.postEditorVisible,
|
||||||
);
|
);
|
||||||
@@ -59,6 +61,9 @@ export default function DiscussionsHome() {
|
|||||||
postMessageToParent('discussions.navigate', { path });
|
postMessageToParent('discussions.navigate', { path });
|
||||||
}
|
}
|
||||||
}, [path]);
|
}, [path]);
|
||||||
|
if (!ready) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DiscussionContext.Provider value={{
|
<DiscussionContext.Provider value={{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import appMessages from './i18n';
|
|||||||
import store from './store';
|
import store from './store';
|
||||||
|
|
||||||
import './assets/favicon.ico';
|
import './assets/favicon.ico';
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
subscribe(APP_READY, () => {
|
subscribe(APP_READY, () => {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
@@ -38,6 +37,7 @@ initialize({
|
|||||||
config() {
|
config() {
|
||||||
mergeConfig({
|
mergeConfig({
|
||||||
POST_MARK_AS_READ_DELAY: process.env.POST_MARK_AS_READ_DELAY || 2000,
|
POST_MARK_AS_READ_DELAY: process.env.POST_MARK_AS_READ_DELAY || 2000,
|
||||||
|
THEME_LOADER_URL: process.env.THEME_LOADER_URL || 'http://localhost:8111/themes.js',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
94
src/theme-hooks.js
Normal file
94
src/theme-hooks.js
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { getConfig } from '@edx/frontend-platform';
|
||||||
|
|
||||||
|
export async function loadComponent(scope, module) {
|
||||||
|
// Initializes the share scope. This fills it with known provided modules from this build and all remotes
|
||||||
|
// Webpack module federation allows sharing common dependencies, like `react`, `react-dom` etc
|
||||||
|
// between modules so that they are no loaded multiple times. The following line will initialise
|
||||||
|
// the system for sharing common modules.
|
||||||
|
// Since there are no shared module here, you can safely comment out the next three lines and this
|
||||||
|
// will still work.
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
await __webpack_init_sharing__('default');
|
||||||
|
const container = window[scope];
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
await container.init(__webpack_share_scopes__.default);
|
||||||
|
const factory = await window[scope].get(module);
|
||||||
|
return factory();
|
||||||
|
} // The hook loads the supplied theme, and if the current theme changes it will
|
||||||
|
// Given a script URL this hook will add the script to the body. When the url
|
||||||
|
// changes it will unload the previous script.
|
||||||
|
// For theming, if we know where the script will come from in advance we can just
|
||||||
|
// include it in the HTML and not load it at runtime. However, that would
|
||||||
|
// require supplying that as a build-time value. Keeping this dynamic allows us
|
||||||
|
// to use it
|
||||||
|
function useDynamicScript(url) {
|
||||||
|
const [ready, setReady] = useState(false);
|
||||||
|
const [failed, setFailed] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!url) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = document.createElement('script');
|
||||||
|
|
||||||
|
element.src = url;
|
||||||
|
element.type = 'text/javascript';
|
||||||
|
element.async = true;
|
||||||
|
|
||||||
|
setReady(false);
|
||||||
|
setFailed(false);
|
||||||
|
|
||||||
|
element.onload = () => {
|
||||||
|
console.log(`Dynamic Script Loaded: ${url}`);
|
||||||
|
setReady(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.onerror = () => {
|
||||||
|
console.error(`Dynamic Script Error: ${url}`);
|
||||||
|
setReady(false);
|
||||||
|
setFailed(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(element);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
console.log(`Dynamic Script Removed: ${url}`);
|
||||||
|
document.head.removeChild(element);
|
||||||
|
};
|
||||||
|
}, [url]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ready,
|
||||||
|
failed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// unload the previous theme and load the new one.
|
||||||
|
export function useTheme(theme) {
|
||||||
|
const { ready } = useDynamicScript(getConfig().THEME_LOADER_URL);
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ready) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
let styles = null;
|
||||||
|
(async () => {
|
||||||
|
const themeComponent = await loadComponent(theme, './theme');
|
||||||
|
styles = themeComponent.styles;
|
||||||
|
|
||||||
|
themeComponent.styles.use();
|
||||||
|
setLoaded(true);
|
||||||
|
})();
|
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
return () => {
|
||||||
|
if (styles) {
|
||||||
|
styles.unuse();
|
||||||
|
}
|
||||||
|
setLoaded(false);
|
||||||
|
};
|
||||||
|
}, [ready]);
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user