diff --git a/src/course-home/dates-tab/DatesTab.jsx b/src/course-home/dates-tab/DatesTab.jsx index 65fed3dfdd..c7d3fcbe55 100644 --- a/src/course-home/dates-tab/DatesTab.jsx +++ b/src/course-home/dates-tab/DatesTab.jsx @@ -11,7 +11,7 @@ import { useModel } from '../../generic/model-store'; import SuggestedScheduleHeader from '../suggested-schedule-messaging/SuggestedScheduleHeader'; import ShiftDatesAlert from '../suggested-schedule-messaging/ShiftDatesAlert'; -import UpgradeToCompleteAlert from '../suggested-schedule-messaging/UpgradeToCompleteAlert'; +import { BannerDatesUpgradeSlot } from '../../plugin-slots/BannerDatesUpgradeSlot'; import UpgradeToShiftDatesAlert from '../suggested-schedule-messaging/UpgradeToShiftDatesAlert'; const DatesTab = () => { @@ -51,7 +51,7 @@ const DatesTab = () => { <> - + )} diff --git a/src/course-home/dates-tab/DatesTab.test.jsx b/src/course-home/dates-tab/DatesTab.test.jsx index 17dcd34ad4..d56c4c0d10 100644 --- a/src/course-home/dates-tab/DatesTab.test.jsx +++ b/src/course-home/dates-tab/DatesTab.test.jsx @@ -171,9 +171,9 @@ describe('DatesTab', () => { await waitFor(() => expect(screen.getByText('We’ve built a suggested schedule to help you stay on track. But don’t worry—it’s flexible so you can learn at your own pace.')).toBeInTheDocument()); }); - it('renders UpgradeToCompleteAlert', async () => { + it('does not render UpgradeToCompleteAlert when contentTypeGatingEnabled is false', async () => { datesTabData.datesBannerInfo = { - contentTypeGatingEnabled: true, + contentTypeGatingEnabled: false, missedDeadlines: false, missedGatedContent: false, verifiedUpgradeLink: 'http://localhost:18130/basket/add/?sku=8CF08E5', @@ -182,8 +182,8 @@ describe('DatesTab', () => { axiosMock.onGet(datesUrl).reply(200, datesTabData); render(component); - await waitFor(() => expect(screen.getByText('You are auditing this course, which means that you are unable to participate in graded assignments. To complete graded assignments as part of this course, you can upgrade today.')).toBeInTheDocument()); - expect(screen.getByRole('button', { name: 'Upgrade now' })).toBeInTheDocument(); + expect(screen.queryByText('You are auditing this course, which means that you are unable to participate in graded assignments. To complete graded assignments as part of this course, you can upgrade today.')).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Upgrade now' })).not.toBeInTheDocument(); }); it('renders UpgradeToShiftDatesAlert', async () => { @@ -254,32 +254,6 @@ describe('DatesTab', () => { expect(screen.queryByRole('button', { name: 'Shift due dates' })).not.toBeInTheDocument(); }); - it('sends analytics event onClick of upgrade button in UpgradeToCompleteAlert', async () => { - sendTrackEvent.mockClear(); - datesTabData.datesBannerInfo = { - contentTypeGatingEnabled: true, - missedDeadlines: false, - missedGatedContent: false, - verifiedUpgradeLink: 'http://localhost:18130/basket/add/?sku=8CF08E5', - }; - - axiosMock.onGet(datesUrl).reply(200, datesTabData); - render(component); - - const upgradeButton = await waitFor(() => screen.getByRole('button', { name: 'Upgrade now' })); - fireEvent.click(upgradeButton); - - expect(sendTrackEvent).toHaveBeenCalledTimes(1); - expect(sendTrackEvent).toHaveBeenCalledWith('edx.bi.ecommerce.upsell_links_clicked', { - org_key: 'edX', - courserun_key: courseId, - linkCategory: 'personalized_learner_schedules', - linkName: 'dates_upgrade', - linkType: 'button', - pageName: 'dates_tab', - }); - }); - it('sends analytics event onClick of upgrade button in UpgradeToShiftDatesAlert', async () => { sendTrackEvent.mockClear(); datesTabData.datesBannerInfo = { diff --git a/src/plugin-slots/BannerDatesUpgradeSlot/README.md b/src/plugin-slots/BannerDatesUpgradeSlot/README.md new file mode 100644 index 0000000000..75e553ac59 --- /dev/null +++ b/src/plugin-slots/BannerDatesUpgradeSlot/README.md @@ -0,0 +1,59 @@ +# Banner Dates Upgrade Slot + +### Slot ID: `org.openedx.frontend.learning.banner_dates_upgrade.v1` + +## Description + +This slot is used for rendering upgrade messaging in the dates tab banner area. + +By default, the slot renders `UpgradeToCompleteAlert`. You can disable the default and fully replace it with a custom plugin experience using `keepDefault: false`. + +## Props + +- `courseId` - The course ID (string) +- `logUpgradeLinkClick` - Callback used for upgrade-click analytics + +## Screenshots + +Default banner screenshot: + +![Screenshot of the dates upgrade banner](./images/update_banner_complete_alert.png) + + + +## Example + +The following `env.config.jsx` example replaces the default banner experience with a custom plugin widget: + +```js +import { + DIRECT_PLUGIN, + PLUGIN_OPERATIONS, +} from '@openedx/frontend-plugin-framework'; + +const config = { + pluginSlots: { + 'org.openedx.frontend.learning.banner_dates_upgrade.v1': { + keepDefault: false, + plugins: [ + { + op: PLUGIN_OPERATIONS.Insert, + widget: { + id: 'org.openedx.frontend.learning.custom_banner_dates_upgrade_widget.v1', + type: DIRECT_PLUGIN, + priority: 50, + RenderWidget: (pluginProps) => ( +
+ Replacement Banner + +
+ ), + }, + }, + ], + }, + }, +}; + +export default config; +``` diff --git a/src/plugin-slots/BannerDatesUpgradeSlot/images/update_banner_complete_alert.png b/src/plugin-slots/BannerDatesUpgradeSlot/images/update_banner_complete_alert.png new file mode 100644 index 0000000000..870ecc9132 Binary files /dev/null and b/src/plugin-slots/BannerDatesUpgradeSlot/images/update_banner_complete_alert.png differ diff --git a/src/plugin-slots/BannerDatesUpgradeSlot/index.tsx b/src/plugin-slots/BannerDatesUpgradeSlot/index.tsx new file mode 100644 index 0000000000..43ac9724ef --- /dev/null +++ b/src/plugin-slots/BannerDatesUpgradeSlot/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import { PluginSlot } from '@openedx/frontend-plugin-framework'; +import UpgradeToCompleteAlert from '../../course-home/suggested-schedule-messaging/UpgradeToCompleteAlert'; + +export const BannerDatesUpgradeSlot = ({ + courseId, + logUpgradeLinkClick, +}: BannerDatesUpgradeSlotProps) => ( + + + +); + +interface BannerDatesUpgradeSlotProps { + courseId: string; + logUpgradeLinkClick: () => void; +} diff --git a/src/plugin-slots/README.md b/src/plugin-slots/README.md index 9bd3b3dd3b..4519860652 100644 --- a/src/plugin-slots/README.md +++ b/src/plugin-slots/README.md @@ -2,6 +2,7 @@ * [`org.openedx.frontend.layout.footer.v1`](./FooterSlot/) * [`org.openedx.frontend.layout.header_learning.v1`](./HeaderSlot/) +* [`org.openedx.frontend.learning.banner_dates_upgrade.v1`](./BannerDatesUpgradeSlot/) * [`org.openedx.frontend.learning.content_iframe_loader.v1`](./ContentIFrameLoaderSlot/) * [`org.openedx.frontend.learning.course_breadcrumbs.v1`](./CourseBreadcrumbsSlot/) * [`org.openedx.frontend.learning.course_home_section_outline.v1`](./CourseHomeSectionOutlineSlot/)