@edx/frontend-plugin-advertisements 2.25.0 → 2.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/__factories__/extraOffer.factory.js +2 -2
- package/dist/data/__factories__/extraOffer.factory.js.map +1 -1
- package/dist/data/lms_api.js +17 -0
- package/dist/data/lms_api.js.map +1 -1
- package/dist/paywall/LockPaywall.js +26 -3
- package/dist/paywall/LockPaywall.js.map +1 -1
- package/dist/paywall/SubscriptionPaywall.js +99 -0
- package/dist/paywall/SubscriptionPaywall.js.map +1 -0
- package/dist/subscription-upsell/SubscriptionUpgradeCard.js +42 -21
- package/dist/subscription-upsell/SubscriptionUpgradeCard.js.map +1 -1
- package/dist/subscription-upsell/SubscriptionUpsell.js +37 -12
- package/dist/subscription-upsell/SubscriptionUpsell.js.map +1 -1
- package/dist/subscription-upsell/reloadWhenUpgraded.js +71 -0
- package/dist/subscription-upsell/reloadWhenUpgraded.js.map +1 -0
- package/dist/subscription-upsell/useSubscriptionOffer.js +30 -7
- package/dist/subscription-upsell/useSubscriptionOffer.js.map +1 -1
- package/dist/upgrade-notification/UpgradeNotification.js +52 -4
- package/dist/upgrade-notification/UpgradeNotification.js.map +1 -1
- package/dist/upgrade-to-complete-alert/UpgradeToCompleteAlert.js +30 -3
- package/dist/upgrade-to-complete-alert/UpgradeToCompleteAlert.js.map +1 -1
- package/dist/upgrade-to-complete-alert/track.js +4 -2
- package/dist/upgrade-to-complete-alert/track.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,8 +10,10 @@ var _i18n = require("@edx/frontend-platform/i18n");
|
|
|
10
10
|
var _logging = require("@edx/frontend-platform/logging");
|
|
11
11
|
var _paragon = require("@openedx/paragon");
|
|
12
12
|
var _lms_api = require("../data/lms_api");
|
|
13
|
+
var _messages = _interopRequireDefault(require("../upgrade-notification/messages"));
|
|
14
|
+
var _reloadWhenUpgraded = _interopRequireDefault(require("./reloadWhenUpgraded"));
|
|
13
15
|
var _useSubscriptionOffer = _interopRequireDefault(require("./useSubscriptionOffer"));
|
|
14
|
-
var
|
|
16
|
+
var _messages2 = _interopRequireDefault(require("./messages"));
|
|
15
17
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
16
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
19
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
@@ -61,6 +63,13 @@ const SubscriptionUpsell = _ref => {
|
|
|
61
63
|
const setUpgradeFor = (id, state) => setUpgrades(prev => _objectSpread(_objectSpread({}, prev), {}, {
|
|
62
64
|
[id]: state
|
|
63
65
|
}));
|
|
66
|
+
// Cancels the reload poll when this component unmounts or shows another course.
|
|
67
|
+
const pollSignal = (0, _react.useRef)(null);
|
|
68
|
+
(0, _react.useEffect)(() => {
|
|
69
|
+
const controller = new AbortController();
|
|
70
|
+
pollSignal.current = controller.signal;
|
|
71
|
+
return () => controller.abort();
|
|
72
|
+
}, [courseId]);
|
|
64
73
|
if (!offer) {
|
|
65
74
|
return null;
|
|
66
75
|
}
|
|
@@ -71,6 +80,9 @@ const SubscriptionUpsell = _ref => {
|
|
|
71
80
|
} = offer;
|
|
72
81
|
const handleUpgrade = async () => {
|
|
73
82
|
const requestedCourseId = courseId;
|
|
83
|
+
const signal = pollSignal.current;
|
|
84
|
+
// Read before the request, so moving to another unit while it is pending also rules out the reload.
|
|
85
|
+
const startPath = global.location.pathname;
|
|
74
86
|
if (inFlight.current.has(requestedCourseId)) {
|
|
75
87
|
return;
|
|
76
88
|
}
|
|
@@ -99,7 +111,10 @@ const SubscriptionUpsell = _ref => {
|
|
|
99
111
|
safeCall(onUpgradeEvent, 'failed', error);
|
|
100
112
|
} else {
|
|
101
113
|
safeCall(onUpgradeEvent, 'succeeded');
|
|
102
|
-
safeCall(onUpgraded,
|
|
114
|
+
safeCall(onUpgraded || (() => (0, _reloadWhenUpgraded.default)(requestedCourseId, {
|
|
115
|
+
signal,
|
|
116
|
+
startPath
|
|
117
|
+
})), result);
|
|
103
118
|
}
|
|
104
119
|
};
|
|
105
120
|
if (offer.canUpgradeInPlace) {
|
|
@@ -108,7 +123,7 @@ const SubscriptionUpsell = _ref => {
|
|
|
108
123
|
className: className,
|
|
109
124
|
role: "status",
|
|
110
125
|
"data-testid": "subscription-upgrade-pending",
|
|
111
|
-
children: formatMessage(
|
|
126
|
+
children: formatMessage(_messages2.default.upgradePending)
|
|
112
127
|
});
|
|
113
128
|
}
|
|
114
129
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
@@ -116,34 +131,34 @@ const SubscriptionUpsell = _ref => {
|
|
|
116
131
|
children: [upgradeState === UPGRADE_STATE.NOT_ACTIVE && /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
|
|
117
132
|
role: "alert",
|
|
118
133
|
"data-testid": "subscription-upgrade-not-active",
|
|
119
|
-
children: [formatMessage(
|
|
134
|
+
children: [formatMessage(_messages2.default.upgradeNotActive), offer.subscribeUrl && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
120
135
|
children: [' ', /*#__PURE__*/(0, _jsxRuntime.jsx)(_paragon.Hyperlink, {
|
|
121
136
|
destination: offer.subscribeUrl,
|
|
122
|
-
children: formatMessage(
|
|
137
|
+
children: formatMessage(_messages2.default.reactivateSubscription)
|
|
123
138
|
})]
|
|
124
139
|
})]
|
|
125
140
|
}), upgradeState === UPGRADE_STATE.FAILED && /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
|
|
126
141
|
role: "alert",
|
|
127
142
|
"data-testid": "subscription-upgrade-failed",
|
|
128
|
-
children: formatMessage(
|
|
143
|
+
children: formatMessage(_messages2.default.upgradeFailed)
|
|
129
144
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_paragon.Button, {
|
|
130
145
|
variant: "brand",
|
|
131
146
|
block: true,
|
|
132
147
|
onClick: handleUpgrade,
|
|
133
148
|
disabled: upgradeState === UPGRADE_STATE.LOADING,
|
|
134
149
|
"data-testid": "subscription-upgrade-now-button",
|
|
135
|
-
children: formatMessage(upgradeState === UPGRADE_STATE.LOADING ?
|
|
150
|
+
children: formatMessage(upgradeState === UPGRADE_STATE.LOADING ? _messages2.default.upgrading : _messages2.default.upgradeNow)
|
|
136
151
|
})]
|
|
137
152
|
});
|
|
138
153
|
}
|
|
139
|
-
if (!
|
|
154
|
+
if (!offer.hasUpsell) {
|
|
140
155
|
return null;
|
|
141
156
|
}
|
|
142
157
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
143
158
|
className: className,
|
|
144
159
|
children: [offer.showNotIncluded && /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
|
|
145
160
|
"data-testid": "subscription-not-included",
|
|
146
|
-
children: formatMessage(
|
|
161
|
+
children: formatMessage(_messages2.default.notIncluded)
|
|
147
162
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
148
163
|
className: "d-flex",
|
|
149
164
|
children: [canPurchase && /*#__PURE__*/(0, _jsxRuntime.jsx)(_paragon.Button, {
|
|
@@ -152,9 +167,9 @@ const SubscriptionUpsell = _ref => {
|
|
|
152
167
|
variant: offer.canSubscribe ? 'outline-primary' : 'brand',
|
|
153
168
|
onClick: onPurchaseClick,
|
|
154
169
|
"data-testid": "subscription-purchase-button",
|
|
155
|
-
children: coursePrice ? formatMessage(
|
|
170
|
+
children: coursePrice ? formatMessage(_messages2.default.purchase, {
|
|
156
171
|
price: coursePrice
|
|
157
|
-
}) : formatMessage(
|
|
172
|
+
}) : formatMessage(_messages2.default.purchaseNoPrice)
|
|
158
173
|
}), offer.canSubscribe && /*#__PURE__*/(0, _jsxRuntime.jsx)(_paragon.Button, {
|
|
159
174
|
as: "a",
|
|
160
175
|
href: offer.subscribeUrl,
|
|
@@ -162,8 +177,17 @@ const SubscriptionUpsell = _ref => {
|
|
|
162
177
|
className: "ml-2",
|
|
163
178
|
onClick: onSubscribeClick,
|
|
164
179
|
"data-testid": "subscription-subscribe-button",
|
|
165
|
-
children: formatMessage(
|
|
180
|
+
children: formatMessage(_messages2.default.subscribe)
|
|
166
181
|
})]
|
|
182
|
+
}), canPurchase && offer.purchaseCode && /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
|
|
183
|
+
className: "mt-2 mb-0",
|
|
184
|
+
"data-testid": "subscription-purchase-code",
|
|
185
|
+
children: formatMessage(_messages.default.discountCodeMessage, {
|
|
186
|
+
code: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
187
|
+
className: "font-weight-bold",
|
|
188
|
+
children: offer.purchaseCode
|
|
189
|
+
})
|
|
190
|
+
})
|
|
167
191
|
})]
|
|
168
192
|
});
|
|
169
193
|
};
|
|
@@ -172,6 +196,7 @@ SubscriptionUpsell.propTypes = {
|
|
|
172
196
|
onSubscribeClick: _propTypes.default.func,
|
|
173
197
|
onPurchaseClick: _propTypes.default.func,
|
|
174
198
|
onUpgradeEvent: _propTypes.default.func,
|
|
199
|
+
// Called after an accepted upgrade. Without it, the page reloads once the LMS has upgraded the enrollment.
|
|
175
200
|
onUpgraded: _propTypes.default.func,
|
|
176
201
|
className: _propTypes.default.string
|
|
177
202
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionUpsell.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_i18n","_logging","_paragon","_lms_api","_useSubscriptionOffer","_messages","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","_toPropertyKey","value","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","UPGRADE_STATE","exports","IDLE","LOADING","PENDING","NOT_ACTIVE","FAILED","safeCall","fn","_len","args","Array","_key","Promise","resolve","catch","logError","error","SubscriptionUpsell","_ref","courseId","onSubscribeClick","onPurchaseClick","onUpgradeEvent","onUpgraded","className","formatMessage","useIntl","offer","useSubscriptionOffer","upgrades","setUpgrades","useState","inFlight","useRef","Set","upgradeState","setUpgradeFor","id","state","prev","purchaseUrl","canPurchase","coursePrice","handleUpgrade","requestedCourseId","current","add","nextState","result","upgradeEnrollmentWithSubscription","success","SubscriptionUpgradeError","code","status","delete","canUpgradeInPlace","jsx","role","children","messages","upgradePending","jsxs","upgradeNotActive","subscribeUrl","Fragment","Hyperlink","destination","reactivateSubscription","upgradeFailed","Button","variant","block","onClick","disabled","upgrading","upgradeNow","canSubscribe","showNotIncluded","notIncluded","as","href","purchase","price","purchaseNoPrice","subscribe","propTypes","PropTypes","string","isRequired","func","defaultProps","undefined","_default"],"sources":["../../src/subscription-upsell/SubscriptionUpsell.jsx"],"sourcesContent":["/* eslint import/no-unresolved: 0 */\nimport React, { useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { useIntl } from '@edx/frontend-platform/i18n';\nimport { logError } from '@edx/frontend-platform/logging';\nimport { Button, Hyperlink } from '@openedx/paragon';\n\nimport { SubscriptionUpgradeError, upgradeEnrollmentWithSubscription } from '../data/lms_api';\nimport useSubscriptionOffer from './useSubscriptionOffer';\nimport messages from './messages';\n\nexport const UPGRADE_STATE = {\n IDLE: 'idle',\n LOADING: 'loading',\n PENDING: 'pending',\n NOT_ACTIVE: 'not_active',\n FAILED: 'failed',\n};\n\n// Host callbacks (analytics, refresh) must never change the outcome of the upgrade request.\nconst safeCall = (fn, ...args) => {\n try {\n Promise.resolve(fn?.(...args)).catch(logError);\n } catch (error) {\n logError(error);\n }\n};\n\n/** Subscribe and Purchase, Purchase only, Upgrade now for subscribers, or the \"not included\" note. */\nconst SubscriptionUpsell = ({\n courseId,\n onSubscribeClick,\n onPurchaseClick,\n onUpgradeEvent,\n onUpgraded,\n className,\n}) => {\n const { formatMessage } = useIntl();\n const offer = useSubscriptionOffer(courseId);\n // Per course, so a course change reads as idle and a late response cannot touch another course.\n const [upgrades, setUpgrades] = useState({});\n const inFlight = useRef(new Set());\n const upgradeState = upgrades[courseId] || UPGRADE_STATE.IDLE;\n const setUpgradeFor = (id, state) => setUpgrades((prev) => ({ ...prev, [id]: state }));\n\n if (!offer) {\n return null;\n }\n\n const { purchaseUrl, canPurchase, coursePrice } = offer;\n\n const handleUpgrade = async () => {\n const requestedCourseId = courseId;\n if (inFlight.current.has(requestedCourseId)) {\n return;\n }\n inFlight.current.add(requestedCourseId);\n setUpgradeFor(requestedCourseId, UPGRADE_STATE.LOADING);\n safeCall(onUpgradeEvent, 'started');\n let nextState;\n let result;\n let error;\n try {\n result = await upgradeEnrollmentWithSubscription(requestedCourseId);\n if (result?.success !== true) {\n throw new SubscriptionUpgradeError('Upgrade was not accepted', { code: result?.code, status: result?.status });\n }\n nextState = UPGRADE_STATE.PENDING;\n } catch (e) {\n error = e;\n nextState = e.code === 'SUBSCRIPTION_NOT_ACTIVE' ? UPGRADE_STATE.NOT_ACTIVE : UPGRADE_STATE.FAILED;\n }\n inFlight.current.delete(requestedCourseId);\n setUpgradeFor(requestedCourseId, nextState);\n if (error) {\n safeCall(onUpgradeEvent, 'failed', error);\n } else {\n safeCall(onUpgradeEvent, 'succeeded');\n safeCall(onUpgraded, result);\n }\n };\n\n if (offer.canUpgradeInPlace) {\n if (upgradeState === UPGRADE_STATE.PENDING) {\n return <p className={className} role=\"status\" data-testid=\"subscription-upgrade-pending\">{formatMessage(messages.upgradePending)}</p>;\n }\n return (\n <div className={className}>\n {upgradeState === UPGRADE_STATE.NOT_ACTIVE && (\n <p role=\"alert\" data-testid=\"subscription-upgrade-not-active\">\n {formatMessage(messages.upgradeNotActive)}\n {offer.subscribeUrl && (\n <>\n {' '}\n <Hyperlink destination={offer.subscribeUrl}>{formatMessage(messages.reactivateSubscription)}</Hyperlink>\n </>\n )}\n </p>\n )}\n {upgradeState === UPGRADE_STATE.FAILED && (\n <p role=\"alert\" data-testid=\"subscription-upgrade-failed\">{formatMessage(messages.upgradeFailed)}</p>\n )}\n <Button\n variant=\"brand\"\n block\n onClick={handleUpgrade}\n disabled={upgradeState === UPGRADE_STATE.LOADING}\n data-testid=\"subscription-upgrade-now-button\"\n >\n {formatMessage(upgradeState === UPGRADE_STATE.LOADING ? messages.upgrading : messages.upgradeNow)}\n </Button>\n </div>\n );\n }\n\n if (!canPurchase && !offer.canSubscribe && !offer.showNotIncluded) {\n return null;\n }\n\n return (\n <div className={className}>\n {offer.showNotIncluded && (\n <p data-testid=\"subscription-not-included\">{formatMessage(messages.notIncluded)}</p>\n )}\n <div className=\"d-flex\">\n {canPurchase && (\n <Button\n as=\"a\"\n href={purchaseUrl}\n variant={offer.canSubscribe ? 'outline-primary' : 'brand'}\n onClick={onPurchaseClick}\n data-testid=\"subscription-purchase-button\"\n >\n {coursePrice\n ? formatMessage(messages.purchase, { price: coursePrice })\n : formatMessage(messages.purchaseNoPrice)}\n </Button>\n )}\n {offer.canSubscribe && (\n <Button\n as=\"a\"\n href={offer.subscribeUrl}\n variant=\"brand\"\n className=\"ml-2\"\n onClick={onSubscribeClick}\n data-testid=\"subscription-subscribe-button\"\n >\n {formatMessage(messages.subscribe)}\n </Button>\n )}\n </div>\n </div>\n );\n};\n\nSubscriptionUpsell.propTypes = {\n courseId: PropTypes.string.isRequired,\n onSubscribeClick: PropTypes.func,\n onPurchaseClick: PropTypes.func,\n onUpgradeEvent: PropTypes.func,\n onUpgraded: PropTypes.func,\n className: PropTypes.string,\n};\n\nSubscriptionUpsell.defaultProps = {\n onSubscribeClick: undefined,\n onPurchaseClick: undefined,\n onUpgradeEvent: undefined,\n onUpgraded: undefined,\n className: undefined,\n};\n\nexport default SubscriptionUpsell;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"SubscriptionUpsell.js","names":["_react","_interopRequireWildcard","require","_propTypes","_interopRequireDefault","_i18n","_logging","_paragon","_lms_api","_messages","_reloadWhenUpgraded","_useSubscriptionOffer","_messages2","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","_toPropertyKey","value","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","UPGRADE_STATE","exports","IDLE","LOADING","PENDING","NOT_ACTIVE","FAILED","safeCall","fn","_len","args","Array","_key","Promise","resolve","catch","logError","error","SubscriptionUpsell","_ref","courseId","onSubscribeClick","onPurchaseClick","onUpgradeEvent","onUpgraded","className","formatMessage","useIntl","offer","useSubscriptionOffer","upgrades","setUpgrades","useState","inFlight","useRef","Set","upgradeState","setUpgradeFor","id","state","prev","pollSignal","useEffect","controller","AbortController","current","signal","abort","purchaseUrl","canPurchase","coursePrice","handleUpgrade","requestedCourseId","startPath","global","location","pathname","add","nextState","result","upgradeEnrollmentWithSubscription","success","SubscriptionUpgradeError","code","status","delete","reloadWhenUpgraded","canUpgradeInPlace","jsx","role","children","messages","upgradePending","jsxs","upgradeNotActive","subscribeUrl","Fragment","Hyperlink","destination","reactivateSubscription","upgradeFailed","Button","variant","block","onClick","disabled","upgrading","upgradeNow","hasUpsell","showNotIncluded","notIncluded","as","href","canSubscribe","purchase","price","purchaseNoPrice","subscribe","purchaseCode","upgradeNotificationMessages","discountCodeMessage","propTypes","PropTypes","string","isRequired","func","defaultProps","undefined","_default"],"sources":["../../src/subscription-upsell/SubscriptionUpsell.jsx"],"sourcesContent":["/* eslint import/no-unresolved: 0 */\nimport React, { useEffect, useRef, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { useIntl } from '@edx/frontend-platform/i18n';\nimport { logError } from '@edx/frontend-platform/logging';\nimport { Button, Hyperlink } from '@openedx/paragon';\n\nimport { SubscriptionUpgradeError, upgradeEnrollmentWithSubscription } from '../data/lms_api';\nimport upgradeNotificationMessages from '../upgrade-notification/messages';\nimport reloadWhenUpgraded from './reloadWhenUpgraded';\nimport useSubscriptionOffer from './useSubscriptionOffer';\nimport messages from './messages';\n\nexport const UPGRADE_STATE = {\n IDLE: 'idle',\n LOADING: 'loading',\n PENDING: 'pending',\n NOT_ACTIVE: 'not_active',\n FAILED: 'failed',\n};\n\n// Host callbacks (analytics, refresh) must never change the outcome of the upgrade request.\nconst safeCall = (fn, ...args) => {\n try {\n Promise.resolve(fn?.(...args)).catch(logError);\n } catch (error) {\n logError(error);\n }\n};\n\n/** Subscribe and Purchase, Purchase only, Upgrade now for subscribers, or the \"not included\" note. */\nconst SubscriptionUpsell = ({\n courseId,\n onSubscribeClick,\n onPurchaseClick,\n onUpgradeEvent,\n onUpgraded,\n className,\n}) => {\n const { formatMessage } = useIntl();\n const offer = useSubscriptionOffer(courseId);\n // Per course, so a course change reads as idle and a late response cannot touch another course.\n const [upgrades, setUpgrades] = useState({});\n const inFlight = useRef(new Set());\n const upgradeState = upgrades[courseId] || UPGRADE_STATE.IDLE;\n const setUpgradeFor = (id, state) => setUpgrades((prev) => ({ ...prev, [id]: state }));\n // Cancels the reload poll when this component unmounts or shows another course.\n const pollSignal = useRef(null);\n useEffect(() => {\n const controller = new AbortController();\n pollSignal.current = controller.signal;\n return () => controller.abort();\n }, [courseId]);\n\n if (!offer) {\n return null;\n }\n\n const { purchaseUrl, canPurchase, coursePrice } = offer;\n\n const handleUpgrade = async () => {\n const requestedCourseId = courseId;\n const signal = pollSignal.current;\n // Read before the request, so moving to another unit while it is pending also rules out the reload.\n const startPath = global.location.pathname;\n if (inFlight.current.has(requestedCourseId)) {\n return;\n }\n inFlight.current.add(requestedCourseId);\n setUpgradeFor(requestedCourseId, UPGRADE_STATE.LOADING);\n safeCall(onUpgradeEvent, 'started');\n let nextState;\n let result;\n let error;\n try {\n result = await upgradeEnrollmentWithSubscription(requestedCourseId);\n if (result?.success !== true) {\n throw new SubscriptionUpgradeError('Upgrade was not accepted', { code: result?.code, status: result?.status });\n }\n nextState = UPGRADE_STATE.PENDING;\n } catch (e) {\n error = e;\n nextState = e.code === 'SUBSCRIPTION_NOT_ACTIVE' ? UPGRADE_STATE.NOT_ACTIVE : UPGRADE_STATE.FAILED;\n }\n inFlight.current.delete(requestedCourseId);\n setUpgradeFor(requestedCourseId, nextState);\n if (error) {\n safeCall(onUpgradeEvent, 'failed', error);\n } else {\n safeCall(onUpgradeEvent, 'succeeded');\n safeCall(onUpgraded || (() => reloadWhenUpgraded(requestedCourseId, { signal, startPath })), result);\n }\n };\n\n if (offer.canUpgradeInPlace) {\n if (upgradeState === UPGRADE_STATE.PENDING) {\n return <p className={className} role=\"status\" data-testid=\"subscription-upgrade-pending\">{formatMessage(messages.upgradePending)}</p>;\n }\n return (\n <div className={className}>\n {upgradeState === UPGRADE_STATE.NOT_ACTIVE && (\n <p role=\"alert\" data-testid=\"subscription-upgrade-not-active\">\n {formatMessage(messages.upgradeNotActive)}\n {offer.subscribeUrl && (\n <>\n {' '}\n <Hyperlink destination={offer.subscribeUrl}>{formatMessage(messages.reactivateSubscription)}</Hyperlink>\n </>\n )}\n </p>\n )}\n {upgradeState === UPGRADE_STATE.FAILED && (\n <p role=\"alert\" data-testid=\"subscription-upgrade-failed\">{formatMessage(messages.upgradeFailed)}</p>\n )}\n <Button\n variant=\"brand\"\n block\n onClick={handleUpgrade}\n disabled={upgradeState === UPGRADE_STATE.LOADING}\n data-testid=\"subscription-upgrade-now-button\"\n >\n {formatMessage(upgradeState === UPGRADE_STATE.LOADING ? messages.upgrading : messages.upgradeNow)}\n </Button>\n </div>\n );\n }\n\n if (!offer.hasUpsell) {\n return null;\n }\n\n return (\n <div className={className}>\n {offer.showNotIncluded && (\n <p data-testid=\"subscription-not-included\">{formatMessage(messages.notIncluded)}</p>\n )}\n <div className=\"d-flex\">\n {canPurchase && (\n <Button\n as=\"a\"\n href={purchaseUrl}\n variant={offer.canSubscribe ? 'outline-primary' : 'brand'}\n onClick={onPurchaseClick}\n data-testid=\"subscription-purchase-button\"\n >\n {coursePrice\n ? formatMessage(messages.purchase, { price: coursePrice })\n : formatMessage(messages.purchaseNoPrice)}\n </Button>\n )}\n {offer.canSubscribe && (\n <Button\n as=\"a\"\n href={offer.subscribeUrl}\n variant=\"brand\"\n className=\"ml-2\"\n onClick={onSubscribeClick}\n data-testid=\"subscription-subscribe-button\"\n >\n {formatMessage(messages.subscribe)}\n </Button>\n )}\n </div>\n {canPurchase && offer.purchaseCode && (\n <p className=\"mt-2 mb-0\" data-testid=\"subscription-purchase-code\">\n {formatMessage(upgradeNotificationMessages.discountCodeMessage, {\n code: <span className=\"font-weight-bold\">{offer.purchaseCode}</span>,\n })}\n </p>\n )}\n </div>\n );\n};\n\nSubscriptionUpsell.propTypes = {\n courseId: PropTypes.string.isRequired,\n onSubscribeClick: PropTypes.func,\n onPurchaseClick: PropTypes.func,\n onUpgradeEvent: PropTypes.func,\n // Called after an accepted upgrade. Without it, the page reloads once the LMS has upgraded the enrollment.\n onUpgraded: PropTypes.func,\n className: PropTypes.string,\n};\n\nSubscriptionUpsell.defaultProps = {\n onSubscribeClick: undefined,\n onPurchaseClick: undefined,\n onUpgradeEvent: undefined,\n onUpgraded: undefined,\n className: undefined,\n};\n\nexport default SubscriptionUpsell;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.POLL_INTERVAL_MS = exports.MAX_POLLS = void 0;
|
|
7
|
+
var _lms_api = require("../data/lms_api");
|
|
8
|
+
const POLL_INTERVAL_MS = exports.POLL_INTERVAL_MS = 3000;
|
|
9
|
+
const MAX_POLLS = exports.MAX_POLLS = 10;
|
|
10
|
+
const wait = ms => new Promise(resolve => {
|
|
11
|
+
setTimeout(resolve, ms);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// One poll per course, however many placements on the page started one: the enrollment API allows
|
|
15
|
+
// 40 requests a minute per learner, and a poll makes 20.
|
|
16
|
+
const activePolls = new Map();
|
|
17
|
+
const pollAndReload = async (courseId, callers) => {
|
|
18
|
+
// Stop once no caller still wants it: each cancels (unmount, course change) or the learner has left
|
|
19
|
+
// the page it started from, so a reload never throws away what they are doing there. The next page
|
|
20
|
+
// load shows the upgrade.
|
|
21
|
+
const isStillWanted = () => callers.some(_ref => {
|
|
22
|
+
let {
|
|
23
|
+
signal,
|
|
24
|
+
startPath
|
|
25
|
+
} = _ref;
|
|
26
|
+
return !signal?.aborted && global.location.pathname === startPath;
|
|
27
|
+
});
|
|
28
|
+
for (let poll = 0; poll < MAX_POLLS; poll += 1) {
|
|
29
|
+
await wait(POLL_INTERVAL_MS); // eslint-disable-line no-await-in-loop
|
|
30
|
+
if (!isStillWanted()) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const mode = await (0, _lms_api.fetchEnrollmentMode)(courseId); // eslint-disable-line no-await-in-loop
|
|
34
|
+
if (mode === 'verified') {
|
|
35
|
+
if (!isStillWanted()) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
global.location.reload();
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Upgrade now answers PENDING and the LMS upgrades the enrollment later, so a reload right away would
|
|
47
|
+
* still show the audit page. This polls the enrollment and reloads once it is verified. After MAX_POLLS
|
|
48
|
+
* it gives up and the pending message stays. Resolves true when it reloaded. startPath is the page the
|
|
49
|
+
* learner clicked on, read before the upgrade request; it defaults to the current page.
|
|
50
|
+
*/
|
|
51
|
+
const reloadWhenUpgraded = function (courseId) {
|
|
52
|
+
let {
|
|
53
|
+
signal,
|
|
54
|
+
startPath = global.location.pathname
|
|
55
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
56
|
+
if (!activePolls.has(courseId)) {
|
|
57
|
+
const callers = [];
|
|
58
|
+
activePolls.set(courseId, {
|
|
59
|
+
callers,
|
|
60
|
+
done: pollAndReload(courseId, callers).finally(() => activePolls.delete(courseId))
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const poll = activePolls.get(courseId);
|
|
64
|
+
poll.callers.push({
|
|
65
|
+
signal,
|
|
66
|
+
startPath
|
|
67
|
+
});
|
|
68
|
+
return poll.done;
|
|
69
|
+
};
|
|
70
|
+
var _default = exports.default = reloadWhenUpgraded;
|
|
71
|
+
//# sourceMappingURL=reloadWhenUpgraded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reloadWhenUpgraded.js","names":["_lms_api","require","POLL_INTERVAL_MS","exports","MAX_POLLS","wait","ms","Promise","resolve","setTimeout","activePolls","Map","pollAndReload","courseId","callers","isStillWanted","some","_ref","signal","startPath","aborted","global","location","pathname","poll","mode","fetchEnrollmentMode","reload","reloadWhenUpgraded","arguments","length","undefined","has","set","done","finally","delete","get","push","_default","default"],"sources":["../../src/subscription-upsell/reloadWhenUpgraded.js"],"sourcesContent":["import { fetchEnrollmentMode } from '../data/lms_api';\n\nexport const POLL_INTERVAL_MS = 3000;\nexport const MAX_POLLS = 10;\n\nconst wait = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); });\n\n// One poll per course, however many placements on the page started one: the enrollment API allows\n// 40 requests a minute per learner, and a poll makes 20.\nconst activePolls = new Map();\n\nconst pollAndReload = async (courseId, callers) => {\n // Stop once no caller still wants it: each cancels (unmount, course change) or the learner has left\n // the page it started from, so a reload never throws away what they are doing there. The next page\n // load shows the upgrade.\n const isStillWanted = () => callers.some(\n ({ signal, startPath }) => !signal?.aborted && global.location.pathname === startPath,\n );\n\n for (let poll = 0; poll < MAX_POLLS; poll += 1) {\n await wait(POLL_INTERVAL_MS); // eslint-disable-line no-await-in-loop\n if (!isStillWanted()) {\n return false;\n }\n const mode = await fetchEnrollmentMode(courseId); // eslint-disable-line no-await-in-loop\n if (mode === 'verified') {\n if (!isStillWanted()) {\n return false;\n }\n global.location.reload();\n return true;\n }\n }\n return false;\n};\n\n/**\n * Upgrade now answers PENDING and the LMS upgrades the enrollment later, so a reload right away would\n * still show the audit page. This polls the enrollment and reloads once it is verified. After MAX_POLLS\n * it gives up and the pending message stays. Resolves true when it reloaded. startPath is the page the\n * learner clicked on, read before the upgrade request; it defaults to the current page.\n */\nconst reloadWhenUpgraded = (courseId, { signal, startPath = global.location.pathname } = {}) => {\n if (!activePolls.has(courseId)) {\n const callers = [];\n activePolls.set(courseId, {\n callers,\n done: pollAndReload(courseId, callers).finally(() => activePolls.delete(courseId)),\n });\n }\n const poll = activePolls.get(courseId);\n poll.callers.push({ signal, startPath });\n return poll.done;\n};\n\nexport default reloadWhenUpgraded;\n"],"mappings":";;;;;;AAAA,IAAAA,QAAA,GAAAC,OAAA;AAEO,MAAMC,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG,IAAI;AAC7B,MAAME,SAAS,GAAAD,OAAA,CAAAC,SAAA,GAAG,EAAE;AAE3B,MAAMC,IAAI,GAAIC,EAAE,IAAK,IAAIC,OAAO,CAAEC,OAAO,IAAK;EAAEC,UAAU,CAACD,OAAO,EAAEF,EAAE,CAAC;AAAE,CAAC,CAAC;;AAE3E;AACA;AACA,MAAMI,WAAW,GAAG,IAAIC,GAAG,CAAC,CAAC;AAE7B,MAAMC,aAAa,GAAG,MAAAA,CAAOC,QAAQ,EAAEC,OAAO,KAAK;EACjD;EACA;EACA;EACA,MAAMC,aAAa,GAAGA,CAAA,KAAMD,OAAO,CAACE,IAAI,CACtCC,IAAA;IAAA,IAAC;MAAEC,MAAM;MAAEC;IAAU,CAAC,GAAAF,IAAA;IAAA,OAAK,CAACC,MAAM,EAAEE,OAAO,IAAIC,MAAM,CAACC,QAAQ,CAACC,QAAQ,KAAKJ,SAAS;EAAA,CACvF,CAAC;EAED,KAAK,IAAIK,IAAI,GAAG,CAAC,EAAEA,IAAI,GAAGpB,SAAS,EAAEoB,IAAI,IAAI,CAAC,EAAE;IAC9C,MAAMnB,IAAI,CAACH,gBAAgB,CAAC,CAAC,CAAC;IAC9B,IAAI,CAACa,aAAa,CAAC,CAAC,EAAE;MACpB,OAAO,KAAK;IACd;IACA,MAAMU,IAAI,GAAG,MAAM,IAAAC,4BAAmB,EAACb,QAAQ,CAAC,CAAC,CAAC;IAClD,IAAIY,IAAI,KAAK,UAAU,EAAE;MACvB,IAAI,CAACV,aAAa,CAAC,CAAC,EAAE;QACpB,OAAO,KAAK;MACd;MACAM,MAAM,CAACC,QAAQ,CAACK,MAAM,CAAC,CAAC;MACxB,OAAO,IAAI;IACb;EACF;EACA,OAAO,KAAK;AACd,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,kBAAkB,GAAG,SAAAA,CAACf,QAAQ,EAA4D;EAAA,IAA1D;IAAEK,MAAM;IAAEC,SAAS,GAAGE,MAAM,CAACC,QAAQ,CAACC;EAAS,CAAC,GAAAM,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EACzF,IAAI,CAACnB,WAAW,CAACsB,GAAG,CAACnB,QAAQ,CAAC,EAAE;IAC9B,MAAMC,OAAO,GAAG,EAAE;IAClBJ,WAAW,CAACuB,GAAG,CAACpB,QAAQ,EAAE;MACxBC,OAAO;MACPoB,IAAI,EAAEtB,aAAa,CAACC,QAAQ,EAAEC,OAAO,CAAC,CAACqB,OAAO,CAAC,MAAMzB,WAAW,CAAC0B,MAAM,CAACvB,QAAQ,CAAC;IACnF,CAAC,CAAC;EACJ;EACA,MAAMW,IAAI,GAAGd,WAAW,CAAC2B,GAAG,CAACxB,QAAQ,CAAC;EACtCW,IAAI,CAACV,OAAO,CAACwB,IAAI,CAAC;IAAEpB,MAAM;IAAEC;EAAU,CAAC,CAAC;EACxC,OAAOK,IAAI,CAACU,IAAI;AAClB,CAAC;AAAC,IAAAK,QAAA,GAAApC,OAAA,CAAAqC,OAAA,GAEaZ,kBAAkB","ignoreList":[]}
|
|
@@ -44,7 +44,9 @@ const formatCoursePrice = verifiedMode => verifiedMode?.price === undefined || v
|
|
|
44
44
|
/**
|
|
45
45
|
* The offer for a course from courseHomeMeta.extraOffer, with the flags and labels the components
|
|
46
46
|
* need, or null when the LMS sent no block (callers keep today's UI). The backend decides whether
|
|
47
|
-
* Subscribe is offered: subscribeUrl is null when not. Purchase uses the
|
|
47
|
+
* Subscribe is offered: subscribeUrl is null when not. Purchase uses the first-purchase discount
|
|
48
|
+
* (the `offer` on the outline or courseware model, as the existing upgrade button does) when there
|
|
49
|
+
* is one, else the course's verifiedMode link and price.
|
|
48
50
|
*/
|
|
49
51
|
exports.formatCoursePrice = formatCoursePrice;
|
|
50
52
|
const useSubscriptionOffer = courseId => {
|
|
@@ -53,23 +55,44 @@ const useSubscriptionOffer = courseId => {
|
|
|
53
55
|
extraOffer,
|
|
54
56
|
verifiedMode
|
|
55
57
|
} = (0, _modelStore.useModel)('courseHomeMeta', courseId) || {};
|
|
58
|
+
const outline = (0, _modelStore.useModel)('outline', courseId) || {};
|
|
59
|
+
const courseware = (0, _modelStore.useModel)('coursewareMeta', courseId) || {};
|
|
60
|
+
// Both models stay in the store across pages, so the one not fetched for this page may be stale.
|
|
61
|
+
// shortcut: an expired discount is dropped; a live one is the same per learner in both, so order is moot.
|
|
62
|
+
// Expiry is judged on server time: each model carries the server/browser clock offset.
|
|
63
|
+
const isLive = _ref => {
|
|
64
|
+
let {
|
|
65
|
+
offer,
|
|
66
|
+
timeOffsetMillis = 0
|
|
67
|
+
} = _ref;
|
|
68
|
+
return !!offer && (!offer.expirationDate || new Date(offer.expirationDate) > new Date(Date.now() + timeOffsetMillis));
|
|
69
|
+
};
|
|
70
|
+
const purchaseOffer = ([outline, courseware].find(isLive) || {}).offer || null;
|
|
56
71
|
if (!extraOffer) {
|
|
57
72
|
return null;
|
|
58
73
|
}
|
|
59
74
|
const inCatalog = extraOffer.inCatalog !== false;
|
|
60
75
|
const isSubscriber = extraOffer.isSubscriber === true;
|
|
61
|
-
const purchaseUrl = verifiedMode?.upgradeUrl || null;
|
|
76
|
+
const purchaseUrl = purchaseOffer?.upgradeUrl || verifiedMode?.upgradeUrl || null;
|
|
62
77
|
const price = formatOfferPrice(intl, extraOffer.price);
|
|
78
|
+
const canPurchase = !!purchaseUrl;
|
|
79
|
+
const canSubscribe = inCatalog && !isSubscriber && !!extraOffer.subscribeUrl;
|
|
80
|
+
const canUpgradeInPlace = inCatalog && isSubscriber;
|
|
81
|
+
const showNotIncluded = !inCatalog && isSubscriber;
|
|
63
82
|
return _objectSpread(_objectSpread({}, extraOffer), {}, {
|
|
64
83
|
inCatalog,
|
|
65
84
|
isSubscriber,
|
|
66
85
|
purchaseUrl,
|
|
67
86
|
hasTrial: extraOffer.freeTrialEligible === true,
|
|
68
|
-
canPurchase
|
|
69
|
-
canSubscribe
|
|
70
|
-
canUpgradeInPlace
|
|
71
|
-
showNotIncluded
|
|
72
|
-
|
|
87
|
+
canPurchase,
|
|
88
|
+
canSubscribe,
|
|
89
|
+
canUpgradeInPlace,
|
|
90
|
+
showNotIncluded,
|
|
91
|
+
// Something for SubscriptionUpsell to show: a button or the "not included" note. Without it, e.g.
|
|
92
|
+
// unknown status and no purchase link, the placements keep today's UI.
|
|
93
|
+
hasUpsell: canPurchase || canSubscribe || canUpgradeInPlace || showNotIncluded,
|
|
94
|
+
coursePrice: purchaseOffer ? purchaseOffer.discountedPrice : formatCoursePrice(verifiedMode),
|
|
95
|
+
purchaseCode: purchaseOffer?.code || null,
|
|
73
96
|
subscribePrice: price && intl.formatMessage(_messages.default.pricePerInterval, {
|
|
74
97
|
price,
|
|
75
98
|
interval: extraOffer.price.billingPeriod || 'month'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSubscriptionOffer.js","names":["_i18n","require","_modelStore","_messages","_interopRequireDefault","e","__esModule","default","ownKeys","r","t","Object","keys","getOwnPropertySymbols","o","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","defineProperty","_toPropertyKey","value","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","SUBSCRIPTION_STATUS","exports","NOT_SUBSCRIBED","TRIAL_ACTIVE","ACTIVE","CANCEL_PENDING","CANCELLED","UNKNOWN","formatOfferPrice","intl","price","amount","undefined","formatNumber","style","currency","isInteger","minimumFractionDigits","formatCoursePrice","verifiedMode","currencySymbol","useSubscriptionOffer","courseId","useIntl","extraOffer","useModel","
|
|
1
|
+
{"version":3,"file":"useSubscriptionOffer.js","names":["_i18n","require","_modelStore","_messages","_interopRequireDefault","e","__esModule","default","ownKeys","r","t","Object","keys","getOwnPropertySymbols","o","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","defineProperty","_toPropertyKey","value","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","SUBSCRIPTION_STATUS","exports","NOT_SUBSCRIBED","TRIAL_ACTIVE","ACTIVE","CANCEL_PENDING","CANCELLED","UNKNOWN","formatOfferPrice","intl","price","amount","undefined","formatNumber","style","currency","isInteger","minimumFractionDigits","formatCoursePrice","verifiedMode","currencySymbol","useSubscriptionOffer","courseId","useIntl","extraOffer","useModel","outline","courseware","isLive","_ref","offer","timeOffsetMillis","expirationDate","Date","now","purchaseOffer","find","inCatalog","isSubscriber","purchaseUrl","upgradeUrl","canPurchase","canSubscribe","subscribeUrl","canUpgradeInPlace","showNotIncluded","hasTrial","freeTrialEligible","hasUpsell","coursePrice","discountedPrice","purchaseCode","code","subscribePrice","formatMessage","messages","pricePerInterval","interval","billingPeriod","_default"],"sources":["../../src/subscription-upsell/useSubscriptionOffer.js"],"sourcesContent":["/* eslint import/no-unresolved: 0 */\nimport { useIntl } from '@edx/frontend-platform/i18n';\nimport { useModel } from '@src/generic/model-store';\n\nimport messages from './messages';\n\n// Viax statuses, as the LMS extra_offer block reports them.\nexport const SUBSCRIPTION_STATUS = {\n NOT_SUBSCRIBED: 'NOT_SUBSCRIBED',\n TRIAL_ACTIVE: 'TRIAL_ACTIVE',\n ACTIVE: 'ACTIVE',\n CANCEL_PENDING: 'CANCEL_PENDING',\n CANCELLED: 'CANCELLED',\n UNKNOWN: 'UNKNOWN',\n};\n\n/** \"$39\" from { amount: \"39.00\", currency: \"USD\" }, or null without a price. */\nexport const formatOfferPrice = (intl, price) => {\n if (price?.amount === undefined || price?.amount === null) {\n return null;\n }\n const amount = Number(price.amount);\n return intl.formatNumber(amount, {\n style: 'currency',\n currency: price.currency || 'USD',\n // Whole amounts show as \"$39\"; otherwise the currency's own precision applies.\n ...(Number.isInteger(amount) ? { minimumFractionDigits: 0 } : {}),\n });\n};\n\n/** \"$149\" from verifiedMode, as the existing upgrade button shows it, or null. */\nexport const formatCoursePrice = (verifiedMode) => (\n verifiedMode?.price === undefined || verifiedMode?.price === null\n ? null\n : `${verifiedMode.currencySymbol || ''}${verifiedMode.price}`\n);\n\n/**\n * The offer for a course from courseHomeMeta.extraOffer, with the flags and labels the components\n * need, or null when the LMS sent no block (callers keep today's UI). The backend decides whether\n * Subscribe is offered: subscribeUrl is null when not. Purchase uses the first-purchase discount\n * (the `offer` on the outline or courseware model, as the existing upgrade button does) when there\n * is one, else the course's verifiedMode link and price.\n */\nconst useSubscriptionOffer = (courseId) => {\n const intl = useIntl();\n const { extraOffer, verifiedMode } = useModel('courseHomeMeta', courseId) || {};\n const outline = useModel('outline', courseId) || {};\n const courseware = useModel('coursewareMeta', courseId) || {};\n // Both models stay in the store across pages, so the one not fetched for this page may be stale.\n // shortcut: an expired discount is dropped; a live one is the same per learner in both, so order is moot.\n // Expiry is judged on server time: each model carries the server/browser clock offset.\n const isLive = ({ offer, timeOffsetMillis = 0 }) => !!offer && (\n !offer.expirationDate || new Date(offer.expirationDate) > new Date(Date.now() + timeOffsetMillis)\n );\n const purchaseOffer = ([outline, courseware].find(isLive) || {}).offer || null;\n if (!extraOffer) {\n return null;\n }\n const inCatalog = extraOffer.inCatalog !== false;\n const isSubscriber = extraOffer.isSubscriber === true;\n const purchaseUrl = purchaseOffer?.upgradeUrl || verifiedMode?.upgradeUrl || null;\n const price = formatOfferPrice(intl, extraOffer.price);\n const canPurchase = !!purchaseUrl;\n const canSubscribe = inCatalog && !isSubscriber && !!extraOffer.subscribeUrl;\n const canUpgradeInPlace = inCatalog && isSubscriber;\n const showNotIncluded = !inCatalog && isSubscriber;\n return {\n ...extraOffer,\n inCatalog,\n isSubscriber,\n purchaseUrl,\n hasTrial: extraOffer.freeTrialEligible === true,\n canPurchase,\n canSubscribe,\n canUpgradeInPlace,\n showNotIncluded,\n // Something for SubscriptionUpsell to show: a button or the \"not included\" note. Without it, e.g.\n // unknown status and no purchase link, the placements keep today's UI.\n hasUpsell: canPurchase || canSubscribe || canUpgradeInPlace || showNotIncluded,\n coursePrice: purchaseOffer ? purchaseOffer.discountedPrice : formatCoursePrice(verifiedMode),\n purchaseCode: purchaseOffer?.code || null,\n subscribePrice: price && intl.formatMessage(messages.pricePerInterval, {\n price,\n interval: extraOffer.price.billingPeriod || 'month',\n }),\n };\n};\n\nexport default useSubscriptionOffer;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -14,6 +14,7 @@ var _icons = require("@openedx/paragon/icons");
|
|
|
14
14
|
var _upgradeButton = require("@src/generic/upgrade-button");
|
|
15
15
|
var _modelStore = require("@src/generic/model-store");
|
|
16
16
|
var _data = require("../data");
|
|
17
|
+
var _subscriptionUpsell = require("../subscription-upsell");
|
|
17
18
|
var _certificatePreview = _interopRequireDefault(require("./certificate-preview"));
|
|
18
19
|
var _generic = require("../generic");
|
|
19
20
|
var _utils = _interopRequireDefault(require("./utils"));
|
|
@@ -26,7 +27,9 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
26
27
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
27
28
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
28
29
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
29
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint import/no-unresolved: 0 */
|
|
30
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint import/no-unresolved: 0 */ // Placements that show the subscription card: course home and the courseware sidebar
|
|
31
|
+
// (tray and widget). The Progress page keeps the current card.
|
|
32
|
+
const SUBSCRIPTION_CARD_PLACEMENTS = ['outline', 'notification_tray', 'notification_widget'];
|
|
30
33
|
const UpgradeNotification = _ref => {
|
|
31
34
|
let {
|
|
32
35
|
id,
|
|
@@ -57,23 +60,31 @@ const UpgradeNotification = _ref => {
|
|
|
57
60
|
const {
|
|
58
61
|
conversion
|
|
59
62
|
} = (0, _cohesion.useCohesion)(courseId);
|
|
63
|
+
const subscriptionOffer = (0, _subscriptionUpsell.useSubscriptionOffer)(courseId);
|
|
60
64
|
const dateNow = Date.now();
|
|
61
65
|
const timezoneFormatArgs = userTimezone ? {
|
|
62
66
|
timeZone: userTimezone
|
|
63
67
|
} : {};
|
|
64
68
|
const correctedTime = new Date(dateNow + timeOffsetMillis);
|
|
65
69
|
const accessExpirationDate = accessExpiration ? new Date(accessExpiration.upgradeDeadline) : null;
|
|
66
|
-
|
|
70
|
+
// Server time, so this agrees with the countdown and the FBE branches below.
|
|
71
|
+
const pastExpirationDeadline = accessExpiration ? correctedTime > accessExpirationDate : false;
|
|
67
72
|
const shouldDisplayBorder = pluginLocationId.includes('outline');
|
|
73
|
+
const isSubscriptionCardPlacement = SUBSCRIPTION_CARD_PLACEMENTS.some(placement => pluginLocationId.includes(placement));
|
|
74
|
+
// Without an offer or anything in it to show, past the upgrade deadline, and on the Progress page,
|
|
75
|
+
// today's card renders.
|
|
76
|
+
const showSubscriptionCard = isSubscriptionCardPlacement && !pastExpirationDeadline && !!subscriptionOffer?.hasUpsell;
|
|
68
77
|
const upsellPageName = (0, _utils.default)({
|
|
69
78
|
id: pluginLocationId
|
|
70
79
|
});
|
|
71
80
|
const setupgradeNotificationCurrentState = setNotificationCurrentState;
|
|
72
81
|
const isFBE = !!accessExpiration && !!datesBannerInfo?.contentTypeGatingEnabled;
|
|
73
|
-
const eventProperties = {
|
|
82
|
+
const eventProperties = _objectSpread({
|
|
74
83
|
org_key: org,
|
|
75
84
|
courserun_key: courseId
|
|
76
|
-
}
|
|
85
|
+
}, showSubscriptionCard && {
|
|
86
|
+
variant: 'subscription'
|
|
87
|
+
});
|
|
77
88
|
const promotionEventProperties = _objectSpread({
|
|
78
89
|
creative: 'sidebarupsell',
|
|
79
90
|
name: 'In-Course Verification Prompt',
|
|
@@ -110,6 +121,43 @@ const UpgradeNotification = _ref => {
|
|
|
110
121
|
pageName: upsellPageName
|
|
111
122
|
}));
|
|
112
123
|
};
|
|
124
|
+
const logSubscribeClick = () => {
|
|
125
|
+
(0, _analytics.sendTrackEvent)('edx.bi.ecommerce.upsell_links_clicked', _objectSpread(_objectSpread({}, eventProperties), {}, {
|
|
126
|
+
linkCategory: 'subscription',
|
|
127
|
+
linkName: `${upsellPageName}_subscribe`,
|
|
128
|
+
linkType: 'button',
|
|
129
|
+
pageName: upsellPageName
|
|
130
|
+
}));
|
|
131
|
+
conversion('Subscribe Clicked'); // on the click, before checkout
|
|
132
|
+
};
|
|
133
|
+
if (showSubscriptionCard) {
|
|
134
|
+
// the card handles every offer state itself
|
|
135
|
+
let banner;
|
|
136
|
+
if (isFBE) {
|
|
137
|
+
// content-gated learners keep the access expiration warning and its sidebar dot stages
|
|
138
|
+
const hoursToAccessExpiration = Math.floor((accessExpirationDate - correctedTime) / 1000 / 60 / 60);
|
|
139
|
+
banner = hoursToAccessExpiration < 7 * 24 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_generic.ExpirationCountdown, {
|
|
140
|
+
courseId: courseId,
|
|
141
|
+
hoursToExpiration: hoursToAccessExpiration,
|
|
142
|
+
setupgradeNotificationCurrentState: setupgradeNotificationCurrentState,
|
|
143
|
+
type: "access"
|
|
144
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_generic.AccessExpirationDateBanner, {
|
|
145
|
+
courseId: courseId,
|
|
146
|
+
accessExpirationDate: accessExpirationDate,
|
|
147
|
+
timezoneFormatArgs: timezoneFormatArgs,
|
|
148
|
+
setupgradeNotificationCurrentState: setupgradeNotificationCurrentState
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_subscriptionUpsell.SubscriptionUpgradeCard, {
|
|
152
|
+
courseId: courseId,
|
|
153
|
+
withBorder: shouldDisplayBorder,
|
|
154
|
+
banner: banner,
|
|
155
|
+
onSubscribeClick: logSubscribeClick,
|
|
156
|
+
onPurchaseClick: logUpgradeClick,
|
|
157
|
+
onUpgradeEvent: stage => stage === 'succeeded' && logUpgradeClick(),
|
|
158
|
+
onClose: toggleSidebar
|
|
159
|
+
});
|
|
160
|
+
}
|
|
113
161
|
|
|
114
162
|
/*
|
|
115
163
|
There are 5 parts that change in the upgrade card:
|