diff --git a/src/courseware/course/sequence/lock-paywall/LockPaywall.jsx b/src/courseware/course/sequence/lock-paywall/LockPaywall.jsx index 37aacd2ad476..f616c25afe28 100644 --- a/src/courseware/course/sequence/lock-paywall/LockPaywall.jsx +++ b/src/courseware/course/sequence/lock-paywall/LockPaywall.jsx @@ -3,7 +3,9 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { Alert, breakpoints, useWindowSize } from '@edx/paragon'; +import { + Alert, Hyperlink, breakpoints, useWindowSize, +} from '@edx/paragon'; import { Locked } from '@edx/paragon/icons'; import SidebarContext from '../../sidebar/SidebarContext'; import messages from './messages'; @@ -24,6 +26,8 @@ function LockPaywall({ const { notificationTrayVisible } = useContext(SidebarContext); const course = useModel('coursewareMeta', courseId); const { + accessExpiration, + marketingUrl, offer, org, verifiedMode, @@ -40,6 +44,9 @@ function LockPaywall({ && !notificationTrayVisible; const shouldWrapTextOnButton = useWindowSize().width > breakpoints.extraSmall.minWidth; + const accessExpirationDate = accessExpiration ? new Date(accessExpiration.expirationDate) : null; + const pastExpirationDeadline = accessExpiration ? new Date(Date.now()) > accessExpirationDate : false; + if (!verifiedMode) { return null; } @@ -59,6 +66,16 @@ function LockPaywall({ }); }; + const logClickPastExpiration = () => { + sendTrackEvent('edx.bi.ecommerce.gated_content.past_expiration.link_clicked', { + ...eventProperties, + linkCategory: 'gated_content', + linkName: 'course_details', + linkType: 'link', + pageName: 'in_course', + }); + }; + return (
@@ -66,12 +83,18 @@ function LockPaywall({

{intl.formatMessage(messages['learn.lockPaywall.title'])}

+ {pastExpirationDeadline ? ( +
+ {intl.formatMessage(messages['learn.lockPaywall.content.pastExpiration'])} + {intl.formatMessage(messages['learn.lockPaywall.courseDetails'])} +
+ ) : ( +
+ {intl.formatMessage(messages['learn.lockPaywall.content'])} +
+ )} -
- {intl.formatMessage(messages['learn.lockPaywall.content'])} -
- -
+
{intl.formatMessage(messages['learn.lockPaywall.example.alt'])}
-
- -
+ {pastExpirationDeadline + ? null + : ( +
+ +
+ )}
); diff --git a/src/courseware/course/sequence/lock-paywall/LockPaywall.scss b/src/courseware/course/sequence/lock-paywall/LockPaywall.scss index 9638c6661a40..7bbee59b2c7c 100644 --- a/src/courseware/course/sequence/lock-paywall/LockPaywall.scss +++ b/src/courseware/course/sequence/lock-paywall/LockPaywall.scss @@ -1,5 +1,6 @@ .alert-content.lock-paywall-container { display: inline-flex; + width: 100%; } .lock-paywall-container svg { diff --git a/src/courseware/course/sequence/lock-paywall/LockPaywall.test.jsx b/src/courseware/course/sequence/lock-paywall/LockPaywall.test.jsx index 5a83fa90bea2..786df96f04e3 100644 --- a/src/courseware/course/sequence/lock-paywall/LockPaywall.test.jsx +++ b/src/courseware/course/sequence/lock-paywall/LockPaywall.test.jsx @@ -80,4 +80,42 @@ describe('Lock Paywall', () => { expect(container).toBeEmptyDOMElement(); }); + + it('displays past expiration message if expiration date has expired', async () => { + const courseMetadata = Factory.build('courseMetadata', { + access_expiration: { + expiration_date: '1995-02-22T05:00:00Z', + }, + marketing_url: 'https://example.com/course-details', + }); + const testStore = await initializeTestStore({ courseMetadata }, false); + render(, { store: testStore }); + expect(screen.getByText('The upgrade deadline for this course passed. To upgrade, enroll in the next available session.')).toBeInTheDocument(); + expect(screen.getByText('View Course Details')) + .toHaveAttribute('href', 'https://example.com/course-details'); + }); + + it('sends analytics event onClick of past expiration course details link', async () => { + sendTrackEvent.mockClear(); + const courseMetadata = Factory.build('courseMetadata', { + access_expiration: { + expiration_date: '1995-02-22T05:00:00Z', + }, + marketing_url: 'https://example.com/course-details', + }); + const testStore = await initializeTestStore({ courseMetadata }, false); + render(, { store: testStore }); + const courseDetailsLink = await screen.getByText('View Course Details'); + fireEvent.click(courseDetailsLink); + + expect(sendTrackEvent).toHaveBeenCalledTimes(1); + expect(sendTrackEvent).toHaveBeenCalledWith('edx.bi.ecommerce.gated_content.past_expiration.link_clicked', { + org_key: 'edX', + courserun_key: mockData.courseId, + linkCategory: 'gated_content', + linkName: 'course_details', + linkType: 'link', + pageName: 'in_course', + }); + }); }); diff --git a/src/courseware/course/sequence/lock-paywall/messages.js b/src/courseware/course/sequence/lock-paywall/messages.js index 964d33a8b413..54f51990b256 100644 --- a/src/courseware/course/sequence/lock-paywall/messages.js +++ b/src/courseware/course/sequence/lock-paywall/messages.js @@ -11,6 +11,16 @@ const messages = defineMessages({ defaultMessage: 'Upgrade to gain access to locked features like this one and get the most out of your course.', description: 'Message shown to indicate that a piece of content is unavailable to audit track users.', }, + 'learn.lockPaywall.content.pastExpiration': { + id: 'learn.lockPaywall.content.pastExpiration', + defaultMessage: 'The upgrade deadline for this course passed. To upgrade, enroll in the next available session. ', + description: 'Message shown to indicate that a piece of content is unavailable to audit track users in a course where the expiration deadline has passed.', + }, + 'learn.lockPaywall.courseDetails': { + id: 'learn.lockPaywall.courseDetails', + defaultMessage: 'View Course Details', + description: 'Link to the course details page for this course with a past expiration date.', + }, 'learn.lockPaywall.example.alt': { id: 'learn.lockPaywall.example.alt', defaultMessage: 'Example Certificate', diff --git a/src/courseware/data/__factories__/courseMetadata.factory.js b/src/courseware/data/__factories__/courseMetadata.factory.js index 90c71e4621e5..272b942ceda9 100644 --- a/src/courseware/data/__factories__/courseMetadata.factory.js +++ b/src/courseware/data/__factories__/courseMetadata.factory.js @@ -6,6 +6,9 @@ Factory.define('courseMetadata') .extend(courseMetadataBase) .option('host', '') .attrs({ + access_expiration: { + expiration_date: '2032-02-22T05:00:00Z', + }, content_type_gating_enabled: false, course_expired_message: null, course_goals: {