Skip to content

Commit 4542069

Browse files
committed
feat: add ability to dynamically load theme overrides
1 parent de22bf4 commit 4542069

File tree

4 files changed

+28
-4
lines changed

4 files changed

+28
-4
lines changed

.env.development

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
2727
IGNORED_ERROR_REGEX=
2828
MFE_CONFIG_API_URL=
2929
APP_ID=
30-
SUPPORT_URL=https://support.edx.org
30+
SUPPORT_URL=https://support.edx.org
31+
THEME_OVERRIDE_URL=

.env.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ IGNORED_ERROR_REGEX=
2828
MFE_CONFIG_API_URL=
2929
APP_ID=
3030
SUPPORT_URL=https://support.edx.org
31+
THEME_OVERRIDE_URL=

src/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ let config = {
7272
MFE_CONFIG_API_URL: process.env.MFE_CONFIG_API_URL,
7373
APP_ID: process.env.APP_ID,
7474
SUPPORT_URL: process.env.SUPPORT_URL,
75+
THEME_OVERRIDE_URL: process.env.THEME_OVERRIDE_URL,
7576
};
7677

7778
/**
@@ -203,4 +204,5 @@ export function ensureConfig(keys, requester = 'unspecified application code') {
203204
* @property {string} MFE_CONFIG_API_URL
204205
* @property {string} APP_ID
205206
* @property {string} SUPPORT_URL
207+
* @property {string} THEME_OVERRIDE_URL
206208
*/

src/react/AppProvider.jsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useMemo } from 'react';
1+
import React, { useState, useMemo, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import { Router } from 'react-router-dom';
44

@@ -48,6 +48,7 @@ export default function AppProvider({ store, children }) {
4848
const [config, setConfig] = useState(getConfig());
4949
const [authenticatedUser, setAuthenticatedUser] = useState(getAuthenticatedUser());
5050
const [locale, setLocale] = useState(getLocale());
51+
const [themeLoaded, setThemeLoaded] = useState(false);
5152

5253
useAppEvent(AUTHENTICATED_USER_CHANGED, () => {
5354
setAuthenticatedUser(getAuthenticatedUser());
@@ -61,8 +62,28 @@ export default function AppProvider({ store, children }) {
6162
setLocale(getLocale());
6263
});
6364

65+
useEffect(() => {
66+
if (config.THEME_OVERRIDE_URL) {
67+
const themeLink = document.createElement('link');
68+
themeLink.href = config.THEME_OVERRIDE_URL;
69+
themeLink.rel = 'stylesheet';
70+
themeLink.type = 'text/css';
71+
themeLink.onload = () => setThemeLoaded(true);
72+
themeLink.onerror = () => setThemeLoaded(true);
73+
74+
document.head.appendChild(themeLink);
75+
76+
return () => document.head.removeChild(themeLink);
77+
}
78+
setThemeLoaded(true);
79+
}, [config.THEME_OVERRIDE_URL]);
80+
6481
const appContextValue = useMemo(() => ({ authenticatedUser, config, locale }), [authenticatedUser, config, locale]);
6582

83+
if (!themeLoaded) {
84+
return null;
85+
}
86+
6687
return (
6788
<IntlProvider locale={locale} messages={getMessages()}>
6889
<ErrorBoundary>
@@ -81,8 +102,7 @@ export default function AppProvider({ store, children }) {
81102
}
82103

83104
AppProvider.propTypes = {
84-
// eslint-disable-next-line react/forbid-prop-types
85-
store: PropTypes.object,
105+
store: PropTypes.shape({}),
86106
children: PropTypes.node.isRequired,
87107
};
88108

0 commit comments

Comments
 (0)