feat: plugin slot for marketing banner on Schedule & Details page (#2748)

* feat: add Page Banner Slot for Schedule and Details Page

* fix: js to ts

* fix: remove js

* fix: lint issues

* fix: issues

* fix: lint issues

* fix: issues

* fix: issue

* fix: issue
This commit is contained in:
Muhammad Anas
2026-01-09 23:21:12 +00:00
committed by GitHub
parent 5641daf68d
commit 6464f37e2a
4 changed files with 93 additions and 5 deletions

View File

@@ -0,0 +1,52 @@
# Page Banner Slot
### Slot ID: `org.openedx.frontend.authoring.page_banner.v1`
### Slot ID Aliases
* `page_banner_slot`
## Description
This slot wraps the Paragon `PageBanner` component to allow plugins to replace, modify, or hide the banner shown on pages like Schedule & Details. By default, it renders the standard `PageBanner` with the provided props and children.
## Example
The following `env.config.jsx` example replaces the default banner message with a custom message.
![Screenshot of Custom Page Banner](./screenshot_custom_banner_msg.png)
```jsx
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
'org.openedx.frontend.authoring.page_banner.v1': {
plugins: [
{
// Hide the default banner contents
op: PLUGIN_OPERATIONS.Hide,
widgetId: 'default_contents',
},
{
// Insert a custom banner contents
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_page_banner_contents',
type: DIRECT_PLUGIN,
RenderWidget: () => (
<>
<h4 className="text-black">Custom Banner Title</h4>
<span className="text text-gray-700 text-left">
This message was injected via the PageBanner plugin slot.
</span>
</>
),
},
},
],
},
},
};
export default config;
```

View File

@@ -0,0 +1,37 @@
import React, { ReactNode } from 'react';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { PageBanner } from '@openedx/paragon';
export interface PageBannerSlotProps {
show: boolean;
onDismiss: () => void;
children: ReactNode;
}
const PageBannerSlot: React.FC<PageBannerSlotProps> = ({
show,
onDismiss,
children,
}) => (
<PluginSlot
id="org.openedx.frontend.authoring.page_banner.v1"
idAliases={['page_banner_slot']}
pluginProps={{
show, onDismiss,
}}
>
<div className="align-items-start">
<PageBanner
show={show}
dismissible
onDismiss={onDismiss}
variant="light"
dismissAltText="Close"
>
{children}
</PageBanner>
</div>
</PluginSlot>
);
export default PageBannerSlot;

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -2,8 +2,9 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
import {
PageBanner, Button, Card, MailtoLink, Hyperlink,
Button, Card, MailtoLink, Hyperlink,
} from '@openedx/paragon';
import PageBannerSlot from '@src/plugin-slots/PageBannerSlot';
import { Email as EmailIcon } from '@openedx/paragon/icons';
import SectionSubHeader from '../../generic/section-sub-header';
@@ -78,17 +79,15 @@ const BasicSection = ({
);
const renderPageBanner = () => (
<PageBanner
<PageBannerSlot
show={showPageBanner}
dismissible
onDismiss={() => setShowPageBanner(false)}
className="align-items-start"
>
<h4 className="text-black">{intl.formatMessage(messages.basicBannerTitle, { platformName })}</h4>
<span className="text text-gray-700 text-left">
{intl.formatMessage(messages.basicBannerText)}
</span>
</PageBanner>
</PageBannerSlot>
);
const renderCoursePromotion = () => (