Skip to content

Commit 0664dc3

Browse files
authored
feat: decouple notifications panel using widget registry mechanism (#1885)
Removes the tightly coupled upgrade/upsell ("notifications") panel from the Learning MFE core and replaces it with a pluggable widget registry system. The right sidebar now supports dynamically-registered external widgets, making it easy to add, remove, or replace sidebar panels without forking the MFE.
1 parent a5d9d62 commit 0664dc3

File tree

115 files changed

+15443
-10872
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+15443
-10872
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 10. Extract Upgrade Widget from Core MFE
2+
3+
## Context
4+
5+
The Learning MFE shipped with a built-in upgrade sidebar widget internally named "Notifications". This caused several problems:
6+
7+
1. **Confusing naming**: The "Notifications" label implied platform notification functionality, conflicting with the actual notification tray used elsewhere in the platform.
8+
2. **Core/commercial coupling**: The upgrade widget is a commercial feature specific to paid instances, not part of the Open edX core offering. Yet it was enabled by default for all deployments.
9+
3. **Empty panel problem**: In courses without a paid track, the upgrade panel was empty but still visible, degrading the learner experience.
10+
4. **Tight coupling**: The widget was directly imported and wired into the sidebar, making it difficult to customize or disable without forking the MFE.
11+
12+
## Decision
13+
14+
### 1. Rename "notifications" terminology to "upgrade"
15+
16+
All internal code references to "notification" that specifically relate to the upgrade panel are renamed to "upgrade":
17+
18+
- `WIDGETS.NOTIFICATIONS``WIDGETS.UPGRADE`
19+
- `notificationStatus` context property → `upgradeWidgetStatus`
20+
- `onNotificationSeen``onUpgradeWidgetSeen`
21+
- `NotificationTray` component → `UpgradePanel`
22+
- `NotificationTrigger` component → `UpgradeTrigger`
23+
- `NotificationIcon` component → `UpgradeIcon`
24+
- localStorage keys: `notificationStatus.${courseId}``upgradeWidget.${courseId}`
25+
- i18n message keys (`notification.*`)
26+
27+
28+
### 2. Widget moved to `src/widgets/upgrade/`
29+
30+
Rather than publishing a separate npm package, the widget is kept as a subdirectory of the MFE. This avoids monorepo publishing overhead while maintaining a clean separation from the sidebar framework.
31+
32+
Instances that need the upgrade panel register it via `env.config.jsx`:
33+
34+
```js
35+
import upgradeWidget from './src/widgets/upgrade/src/index';
36+
37+
export const SIDEBAR_WIDGETS = [upgradeWidget];
38+
```

example.env.config.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import UnitTranslationPlugin from '@edx/unit-translation-selector-plugin';
2+
import { upgradeWidgetConfig } from './src/widgets/upgrade/src/index';
23
import { PLUGIN_OPERATIONS, DIRECT_PLUGIN } from '@openedx/frontend-plugin-framework';
34

45
// Load environment variables from .env file
56
const config = {
67
...process.env,
8+
SIDEBAR_WIDGETS: [upgradeWidgetConfig],
9+
710
pluginSlots: {
811
unit_title_plugin: {
912
plugins: [

jest.config.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,16 @@ const config = createConfig('jest', {
2424

2525
// delete config.testURL;
2626

27-
config.reporters = [...(config.reporters || []), ["jest-console-group-reporter", {
28-
// change this setting if need to see less details for each test
29-
// reportType: "summary" | "details",
30-
// enable: true | false,
31-
afterEachTest: {
32-
enable: true,
33-
filePaths: false,
34-
reportType: "details",
35-
},
36-
afterAllTests: {
37-
reportType: "summary",
38-
enable: true,
39-
filePaths: true,
40-
},
41-
}]];
27+
// NOTE: jest-console-group-reporter@1.1.1 uses @jest/reporters@^30 internally
28+
// (via its peer dep resolution) but this project runs Jest 29, whose globalConfig
29+
// uses testPathPattern (string) not testPathPatterns (object). When any worker
30+
// exits uncleanly the reporter's SummaryReporter.onRunComplete crashes with
31+
// "Cannot read properties of undefined (reading 'isSet')", causing a non-zero
32+
// exit code even when all tests pass. Disabled until the package is updated for
33+
// Jest 29/30 compatibility.
34+
// config.reporters = [...(config.reporters || []), ["jest-console-group-reporter", {
35+
// afterEachTest: { enable: true, filePaths: false, reportType: "details" },
36+
// afterAllTests: { reportType: "summary", enable: true, filePaths: true },
37+
// }]];
4238

4339
module.exports = config;

0 commit comments

Comments
 (0)