Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ jobs:
npm run build
npm pack
mv openedx-frontend-base* openedx-frontend-base.tgz
cd test-project
cd test-site
npm i ../openedx-frontend-base.tgz
npm ci
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Test Project
run: npm run test-project
- name: Build Test Site
run: npm run test-site:build
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ scss
node_modules
npm-debug.log
docs/api
/openedx-frontend-base-1.0.0.tgz
/*.tgz
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ If a consumer chooses not to use ``initialize`` and instead the ``configureAuth`

configureAuth({
loggingService: getLoggingService(),
config: getConfig(),
config: getSiteConfig(),
options: {
middleware: [axiosCaseConverter, (client) => axiosRetry(client, { retries: 3 })]
}
Expand Down
8 changes: 4 additions & 4 deletions docs/decisions/0008-stylesheet-import-in-site-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ As a best practice, a project should have a top-level SCSS file as a peer to the

## Implementation

The `project.scss` file should import the stylesheet from the shell:
The `site.scss` file should import the stylesheet from the shell:

```diff
+ @import '@openedx/frontend-base/shell/app.scss';
Expand All @@ -29,11 +29,11 @@ The `project.scss` file should import the stylesheet from the shell:
The site.config file should then import the top-level SCSS file:

```diff
+ import './project.scss';
+ import './site.scss';

const config = {
const siteConfig = {
// config document
}

export default config;
export default siteConfig;
```
2 changes: 1 addition & 1 deletion docs/decisions/0009-slot-naming-and-lifecycle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Where:

For example:

* org.openedx.frontend.slot.devProject.foobar (unsupported slot, as version is empty)
* org.openedx.frontend.slot.devSite.foobar (unsupported slot, as version is empty)
* org.openedx.frontend.slot.footer.main.unstable (unstable slot)
* org.openedx.frontend.slot.learning.navigationSidebar.v2 (this slot is on version 2)

Expand Down
2 changes: 1 addition & 1 deletion docs/how_tos/automatic-case-conversion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Or, if you choose to use ``configureAuth`` instead::

configureAuth({
loggingService: getLoggingService(),
config: getConfig(),
config: getSiteConfig(),
options: {
middleware: [axiosCaseConverter, (client) => axiosRetry(client, { retries: 3 })]
}
Expand Down
2 changes: 1 addition & 1 deletion docs/how_tos/i18n.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Load up your translation files

configureI18n({
messages,
config: getConfig(), // environment and languagePreferenceCookieName are required
config: getSiteConfig(), // environment and languagePreferenceCookieName are required
loggingService: getLoggingService(), // An object with logError and logInfo methods
});

Expand Down
94 changes: 50 additions & 44 deletions docs/how_tos/migrate-frontend-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,8 @@ With the exception of any custom scripts, replace the `scripts` section of your

```
"scripts": {
"build": "PORT=YOUR_PORT openedx build",
"build:legacy": "openedx build:legacy", // TODO: Does this target exist?
"build": "openedx build",
"dev": "PORT=YOUR_PORT openedx dev",
"dev:legacy": "PORT=YOUR_PORT openedx dev:legacy",
"i18n_extract": "openedx formatjs extract",
"lint": "openedx lint .",
"lint:fix": "openedx lint --fix .",
Expand Down Expand Up @@ -182,7 +180,7 @@ Create an `app.d.ts` file in the root of your MFE with the following contents:
/// <reference types="@openedx/frontend-base" />

declare module 'site.config' {
export default ProjectSiteConfig;
export default SiteConfig;
}

declare module '*.svg' {
Expand Down Expand Up @@ -210,7 +208,6 @@ Create a `tsconfig.json` file and add the following contents to it:
"babel.config.js",
"eslint.config.js",
"jest.config.js",
"test.site.config.tsx",
"site.config.*.tsx",
],
}
Expand Down Expand Up @@ -306,13 +303,13 @@ module.exports = config;
Merge site.config into config in setupTest.js
=============================================

frontend-platform used environment variables to seed the configuration object, meaning it had default values at the time code is loaded based on `process.env` variables. frontend-base has a hard-coded, minimal configuration object that _must_ be augmented by a valid site config file at initialization time. This means that any tests that rely on configuration (e.g., via `getConfig()`) must first initialize the configuration object. This can be done for tests by adding these lines to `setupTest.js`:
frontend-platform used environment variables to seed the configuration object, meaning it had default values at the time code is loaded based on `process.env` variables. frontend-base has a hard-coded, minimal configuration object that _must_ be augmented by a valid site config file at initialization time. This means that any tests that rely on configuration (e.g., via `getSiteConfig()`) must first initialize the configuration object. This can be done for tests by adding these lines to `setupTest.js`:

```
import siteConfig from 'site.config';
import { mergeConfig } from '@openedx/frontend-base';
import { mergeSiteConfig } from '@openedx/frontend-base';

mergeConfig(siteConfig);
mergeSiteConfig(siteConfig);

```

Expand Down Expand Up @@ -388,7 +385,7 @@ Description fields are now required on all i18n messages in the repository. Thi
SVGR "ReactComponent" imports have been removed
===============================================

We have removed the `@svgr/webpack` loader because it was incompatible with more modern tooling (it requires Babel). As a result, the ability to import SVG files into JS as the `ReactComponent` export no longer works. We know of a total of 5 places where this is happening today in Open edX MFEs - frontend-app-learning and frontend-app-profile use it. Please replace that export with the default URL export and set the URL as the source of an `<img>` tag, rather than using `ReactComponent`. You can see an example of normal SVG imports in `test-project/src/ExamplePage.tsx`.
We have removed the `@svgr/webpack` loader because it was incompatible with more modern tooling (it requires Babel). As a result, the ability to import SVG files into JS as the `ReactComponent` export no longer works. We know of a total of 5 places where this is happening today in Open edX MFEs - frontend-app-learning and frontend-app-profile use it. Please replace that export with the default URL export and set the URL as the source of an `<img>` tag, rather than using `ReactComponent`. You can see an example of normal SVG imports in `test-site/src/ExamplePage.tsx`.


Import createConfig and getBaseConfig from @openedx/frontend-base/config
Expand All @@ -414,7 +411,7 @@ Replace all imports from @edx/frontend-platform with @openedx/frontend-base
- import { logInfo } from '@edx/frontend-platform/logging';
- import { FormattedMessage } from '@edx/frontend-platform/i18n';
+ import {
+ getConfig,
+ getSiteConfig,
+ logInfo,
+ FormattedMessage
+ } from '@openedx/frontend-base';
Expand Down Expand Up @@ -490,7 +487,7 @@ Required config

The required configuration at the time of this writing is:

- appId: string
- siteId: string
- siteName: string
- baseUrl: string
- lmsBaseUrl: string
Expand Down Expand Up @@ -521,6 +518,7 @@ Note that the .env files and env.config.js files also include a number of URLs f
```
// Creating a route role with for 'example' in an App
const app: App = {
...
routes: [{
path: '/example',
id: 'example.page',
Expand All @@ -538,17 +536,16 @@ const examplePageUrl = getUrlForRouteRole('example');
App-specific config values
--------------------------

App-specific configuration can be expressed by adding a `custom` section to SiteConfig which allows arbitrary config variables.
App-specific configuration can be expressed by adding an `config` section to the app, allowing arbitrary variables:

```
const config: ProjectSiteConfig = {
// ... Other config

custom: {
const app: App = {
...
config: {
appId: 'myapp',
myCustomVariableName: 'my custom variable value',
}
}
},
};
```

These variables can be used in code with the `getAppConfig` function:
Expand All @@ -557,49 +554,58 @@ These variables can be used in code with the `getAppConfig` function:
getAppConfig('myapp').myCustomVariableName
```

If you have fully converted your app over to the new module architecture, you can add custom variables to the `config` object in your `App` definition and they will be available via `getAppConfig`.
Or via `useAppConfig()` (with no need to specify the appId), if `AppProvider` is wrapping your app.


Replace the .env.test file with configuration in test.site.config.tsx file
Replace the .env.test file with configuration in site.config.test.tsx file
==========================================================================

We're moving away from .env files because they're not expressive enough (only string types!) to configure an Open edX frontend. Instead, the test suite has been configured to expect a `test.site.config.tsx` file. If you're initializing an application in your tests, `frontend-base` will pick up this configuration and make it available to `getConfig()`, etc. If you need to manually access the variables, you can import `site.config` in your test files:

Note that test.site.config.tsx has a different naming scheme than `site.config.*.tsx` because it's intended to be checked in, and `site.config.*.tsx` is git-ignored.
We're moving away from .env files because they're not expressive enough (only string types!) to configure an Open edX frontend. Instead, the test suite has been configured to expect a `site.config.test.tsx` file. If you're initializing an application in your tests, `frontend-base` will pick up this configuration and make it available to `getSiteConfig()`, etc. If you need to manually access the variables, you can import `site.config` in your test files:

```diff
+ import config from 'site.config';
+ import siteConfig from 'site.config';
```

The Jest configuration has been set up to find `site.config` in a `test.site.config.tsx` file.
The Jest configuration has been set up to find `site.config` in a `site.config.test.tsx` file.

Once you've verified your test suite still works, you should delete the `.env.test` file.

A sample `test.site.config.tsx` file:
A sample `site.config.test.tsx` file:

```
import { ProjectSiteConfig } from '@openedx/frontend-base';
import { SiteConfig } from '@openedx/frontend-base';

const config: ProjectSiteConfig = {
apps: [],
accessTokenCookieName: 'edx-jwt-cookie-header-payload',
const siteConfig: SiteConfig = {
siteId: 'test',
siteName: 'localhost',
baseUrl: 'http://localhost:8080',
csrfTokenApiPath: '/csrf/api/v1/token',
languagePreferenceCookieName: 'openedx-language-preference',
lmsBaseUrl: 'http://localhost:18000',
loginUrl: 'http://localhost:18000/login',
logoutUrl: 'http://localhost:18000/logout',
environment: 'dev',
apps: [{
appId: 'test-app',
routes: [{
path: '/app1',
element: (
<div>Test App 1</div>
),
handle: {
role: 'test-app-1'
}
}]
}],
accessTokenCookieName: 'edx-jwt-cookie-header-payload',
csrfTokenApiPath: '/csrf/api/v1/token',
languagePreferenceCookieName: 'openedx-language-preference',
refreshAccessTokenApiPath: '/login_refresh',
segmentKey: '',
siteName: 'localhost',
userInfoCookieName: 'edx-user-info',
appId: 'authn',
environment: 'dev',
ignoredErrorRegex: null,
publicPath: '/',
};

export default config;
export default siteConfig;
```


Expand Down Expand Up @@ -629,12 +635,12 @@ Remove core-js and regenerator-runtime
We don't need these libraries anymore, remove them from the package.json dependencies and remove any imports of them in the code.


Create a project.scss file
==========================
Create a site.scss file
=======================

This is required if you intend to run builds from the app itself.

Create a new `project.scss` file at the top of your application. It's responsible for:
Create a new `site.scss` file at the top of your application. It's responsible for:

1. Importing the shell's stylesheet, which includes Paragon's core stylesheet.
2. Importing your brand stylesheet.
Expand All @@ -643,16 +649,16 @@ Create a new `project.scss` file at the top of your application. It's responsib
You must then import this new stylesheet into your `site.config` file:

```diff
+ import './project.scss';
+ import './site.scss';

const config: ProjectSiteConfig = {
const siteConfig: SiteConfig = {
// config document
}

export default config;
export default siteConfig;
```

This file will be ignored via `.gitignore`, as it is part of your 'project', not the module library.
This file will be ignored via `.gitignore`, as it is part of your 'site', not the module library.


Document module-specific configuration needs
Expand Down Expand Up @@ -731,7 +737,7 @@ Refactor plugin-slots

First, rename `src/plugin-slots`, if it exists, to `src/slots`. Modify imports and documentation across the codebase accordingly.

Next, the frontend-base equivalent to `<PluginSlot />` is `<Slot />`, and has a different API. This includes a change in the slot ID, according to the [new slot naming ADR](../decisions/0009-slot-naming-and-lifecycle.rst) in this repository. Rename them accordingly. You can refer to the `src/shell/dev-project` in this repository for examples.
Next, the frontend-base equivalent to `<PluginSlot />` is `<Slot />`, and has a different API. This includes a change in the slot ID, according to the [new slot naming ADR](../decisions/0009-slot-naming-and-lifecycle.rst) in this repository. Rename them accordingly. You can refer to the `src/shell/dev-site` in this repository for examples.


Find your module boundaries
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = tseslint.config(
{
ignores: [
'tools/*',
'test-project/*',
'test-site/*',
'config/*',
'docs/*',
],
Expand Down
2 changes: 1 addition & 1 deletion frontend-base.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
declare module 'site.config' {
export default ProjectSiteConfig;
export default SiteConfig;
}

declare module '*.svg' {
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
"dev:shell": "npm run build && node ./tools/dist/cli/openedx.js dev:shell",
"docs": "jsdoc -c jsdoc.json",
"docs:watch": "nodemon -w runtime -w docs/template -w README.md -e js,jsx,ts,tsx --exec npm run docs",
"lint": "eslint .; npm run lint:tools; npm --prefix ./test-project run lint",
"lint": "eslint .; npm run lint:tools; npm --prefix ./test-site run lint",
"lint:tools": "cd ./tools && eslint . && cd ..",
"test": "jest",
"test-project": "npm --prefix ./test-project i; npm --prefix ./test-project run build",
"test-project:refresh": "npm run build && npm pack && cd test-project && npm i --audit=false --fund=false ../openedx-frontend-base-1.0.0.tgz && cd ../"
"test-site:build": "npm --prefix ./test-site i; npm --prefix ./test-site run build",
"test-site:refresh": "npm run build && npm pack && cd test-site && npm i --audit=false --fund=false ../openedx-frontend-base-1.0.0.tgz && cd ../"
},
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions runtime/analytics/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
*
* ```
* import {
* getConfig,
* getSiteConfig,
* getAuthenticatedHttpClient,
* getLoggingService,
* configureAnalytics,
* SegmentAnalyticsService
* } from '@openedx/frontend-base';
*
* configureAnalytics(SegmentAnalyticsService, {
* config: getConfig(),
* config: getSiteConfig(),
* loggingService: getLoggingService(),
* httpClient: getAuthenticatedHttpClient(),
* });
Expand Down
4 changes: 2 additions & 2 deletions runtime/auth/AxiosJwtAuthService.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Cookies from 'universal-cookie';
import { getConfig } from '../config';
import { getSiteConfig } from '../config';
import AxiosJwtAuthService from './AxiosJwtAuthService';

const mockLoggingService = {
Expand All @@ -12,7 +12,7 @@ const mockLoggingService = {
};

const authOptions = {
config: getConfig(),
config: getSiteConfig(),
loggingService: mockLoggingService,
};

Expand Down
Loading
Loading