Skip to content

Commit 5eae978

Browse files
authored
Merge pull request #1246 from openedx/eahmadjaved/ENT-8748
feat: mark static strings for flash messages on login
2 parents 85e2cdf + edd4e31 commit 5eae978

File tree

12 files changed

+204
-64
lines changed

12 files changed

+204
-64
lines changed

src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js

Lines changed: 121 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,168 @@ import parse from 'html-react-parser';
33
import { PLAN_EXPIRY_VARIANTS } from './constants';
44

55
const expiryThresholds = {
6-
120: ({ date }) => ({
6+
120: ({ intl, date }) => ({
77
notificationTemplate: {
8-
title: 'Your Learner Credit plan expires soon',
8+
title: intl.formatMessage({
9+
id: 'adminPortal.leaernerCredit.expiryNotification.title',
10+
defaultMessage: 'Your Learner Credit plan expires soon',
11+
description: 'Title for the notification that the Learner Credit plan is expiring soon.',
12+
}),
913
variant: 'info',
10-
message: `Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`,
14+
message: intl.formatMessage({
15+
id: 'adminPortal.leaernerCredit.expiryNotification.message',
16+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
17+
description: 'Message for the notification that the Learner Credit plan is expiring soon.',
18+
}, { date }),
1119
dismissible: true,
1220
},
1321
modalTemplate: {
14-
title: 'Your plan expires soon',
15-
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
22+
title: intl.formatMessage({
23+
id: 'adminPortal.leaernerCredit.expiryModal.title',
24+
defaultMessage: 'Your plan expires soon',
25+
description: 'Title for the modal that the Learner Credit plan is expiring soon.',
26+
}),
27+
message: parse(sanitizeHTML(intl.formatMessage({
28+
id: 'adminPortal.leaernerCredit.expiryModal.message',
29+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
30+
description: 'Message for the modal that the Learner Credit plan is expiring soon.',
31+
}, { date }))),
1632
},
1733
variant: PLAN_EXPIRY_VARIANTS.expiring,
1834
}),
19-
90: ({ date }) => ({
35+
90: ({ intl, date }) => ({
2036
notificationTemplate: {
21-
title: 'Reminder: Your Learner Credit plan expires soon',
37+
title: intl.formatMessage({
38+
id: 'adminPortal.learnerCredit.expiryReminderNotification.title',
39+
defaultMessage: 'Reminder: Your Learner Credit plan expires soon',
40+
description: 'Title for the notification that the Learner Credit plan is expiring soon.',
41+
}),
2242
variant: 'info',
23-
message: `Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`,
43+
message: intl.formatMessage({
44+
id: 'adminPortal.learnerCredit.expiryReminderNotification.message',
45+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
46+
description: 'Message for the notification that the Learner Credit plan is expiring soon.',
47+
}, { date }),
2448
dismissible: true,
2549
},
2650
modalTemplate: {
27-
title: 'Reminder: Your plan expires soon',
28-
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
51+
title: intl.formatMessage({
52+
id: 'adminPortal.learnerCredit.expiryReminderModal.title',
53+
defaultMessage: 'Reminder: Your plan expires soon',
54+
description: 'Title for the modal that the Learner Credit plan is expiring soon.',
55+
}),
56+
message: parse(sanitizeHTML(intl.formatMessage({
57+
id: 'adminPortal.learnerCredit.expiryReminderModal.message',
58+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
59+
description: 'Message for the modal that the Learner Credit plan is expiring soon.',
60+
}, { date }))),
2961
},
3062
variant: PLAN_EXPIRY_VARIANTS.expiring,
3163
}),
32-
60: ({ date }) => ({
64+
60: ({ intl, date }) => ({
3365
notificationTemplate: {
34-
title: `Your Learner Credit plan expires ${date}`,
66+
title: intl.formatMessage({
67+
id: 'adminPortal.learnerCredit.expiresNotification.title',
68+
defaultMessage: 'Your Learner Credit plan expires {date}',
69+
description: 'Title for the notification that the Learner Credit plan is expiring.',
70+
}, { date }),
3571
variant: 'warning',
36-
message: 'When your Learner Credit plan expires, you will no longer have access to administrative functions and the remaining balance of your budget(s) will be unusable. Contact support today to renew your plan.',
72+
message: intl.formatMessage({
73+
id: 'adminPortal.learnerCredit.expiresNotification.message',
74+
defaultMessage: 'When your Learner Credit plan expires, you will no longer have access to administrative functions and the remaining balance of your budget(s) will be unusable. Contact support today to renew your plan.',
75+
description: 'Message for the notification that the Learner Credit plan is expiring.',
76+
}),
3777
dismissible: true,
3878
},
3979
modalTemplate: {
40-
title: `Your Learner Credit plan expires ${date}`,
41-
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
80+
title: intl.formatMessage({
81+
id: 'adminPortal.learnerCredit.expiresModal.title',
82+
defaultMessage: 'Your Learner Credit plan expires {date}',
83+
description: 'Title for the modal that the Learner Credit plan is expiring.',
84+
}, { date }),
85+
message: parse(sanitizeHTML(intl.formatMessage({
86+
id: 'adminPortal.learnerCredit.expiresModal.message',
87+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
88+
description: 'Message for the modal that the Learner Credit plan is expiring.',
89+
}, { date }))),
4290
},
4391
variant: PLAN_EXPIRY_VARIANTS.expiring,
4492
}),
45-
30: ({ date }) => ({
93+
30: ({ intl, date }) => ({
4694
notificationTemplate: {
47-
title: 'Your Learner Credit plan expires in less than 30 days',
95+
title: intl.formatMessage({
96+
id: 'adminPostal.learnerCredit.expiresInThirtyDaysNotification.title',
97+
defaultMessage: 'Your Learner Credit plan expires in less than 30 days',
98+
description: 'Title for the notification that the Learner Credit plan is expiring in less than 30 days.',
99+
}),
48100
variant: 'danger',
49-
message: 'When your plan expires you will lose access to administrative functions and the remaining balance of your plan’s budget(s) will be unusable. Contact support today to renew your plan.',
101+
message: intl.formatMessage({
102+
id: 'adminPostal.learnerCredit.expiresInThirtyDaysNotification.message',
103+
defaultMessage: 'When your plan expires you will lose access to administrative functions and the remaining balance of your plan{apostrophe}s budget(s) will be unusable. Contact support today to renew your plan.',
104+
description: 'Message for the notification that the Learner Credit plan is expiring in less than 30 days.',
105+
}, { aposrophe: "'" }),
50106
},
51107
modalTemplate: {
52-
title: 'Your Learner Credit plan expires in less than 30 days',
53-
message: parse(sanitizeHTML(`<p>Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.</p>`)),
108+
title: intl.formatMessage({
109+
id: 'adminPostal.learnerCredit.expiresInThirtyDaysModal.title',
110+
defaultMessage: 'Your Learner Credit plan expires in less than 30 days',
111+
description: 'Title for the modal that the Learner Credit plan is expiring in less than 30 days.',
112+
}),
113+
message: parse(sanitizeHTML(
114+
intl.formatMessage({
115+
id: 'adminPostal.learnerCredit.expiresInThirtyDaysModal.message',
116+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
117+
description: 'Message for the modal that the Learner Credit plan is expiring in less than 30 days.',
118+
}, { date }),
119+
)),
54120
},
55121
variant: PLAN_EXPIRY_VARIANTS.expiring,
56122
}),
57-
10: ({ date, days, hours }) => ({
123+
10: ({
124+
intl, date, days, hours,
125+
}) => ({
58126
notificationTemplate: {
59-
title: `Reminder: Your Learner Credit plan expires ${date}`,
127+
title: intl.formatMessage({
128+
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysNotification.title',
129+
defaultMessage: 'Reminder: Your Learner Credit plan expires {date}',
130+
description: 'Title for the notification that the Learner Credit plan is expiring.',
131+
}, { date }),
60132
variant: 'danger',
61-
message: parse(sanitizeHTML(`Your Learner Credit plan expires in <strong>${days} days and ${hours} hours</strong>. Contact support today to renew your plan.`)),
133+
message: parse(sanitizeHTML(intl.formatMessage({
134+
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysNotification.message',
135+
defaultMessage: 'Your Learner Credit plan expires in <strong>{days} days and {hours} hours</strong>. Contact support today to renew your plan.',
136+
description: 'Message for the notification that the Learner Credit plan is expiring.',
137+
}, { days, hours, strong: (str) => `<strong>${str}</strong>` }))),
62138
},
63139
modalTemplate: {
64-
title: `Reminder: Your Learner Credit plan expires ${date}`,
65-
message: parse(sanitizeHTML(`<p>Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.</p>`)),
140+
title: intl.formatMessage({
141+
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysModal.title',
142+
defaultMessage: 'Reminder: Your Learner Credit plan expires {date}',
143+
description: 'Title for the modal that the Learner Credit plan is expiring.',
144+
}, { date }),
145+
message: parse(sanitizeHTML(intl.formatMessage({
146+
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysModal.message',
147+
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
148+
description: 'Message for the modal that the Learner Credit plan is expiring.',
149+
}, { date }))),
66150
},
67151
variant: PLAN_EXPIRY_VARIANTS.expiring,
68152
}),
69-
0: ({ date }) => ({
153+
0: ({ intl, date }) => ({
70154
notificationTemplate: null,
71155
modalTemplate: {
72-
title: 'Your Learner Credit plan has expired',
156+
title: intl.formatMessage({
157+
id: 'adminPortal.learnerCreditPlan.expiredModal.title',
158+
defaultMessage: 'Your Learner Credit plan has expired',
159+
description: 'Title for the modal that the Learner Credit plan has expired.',
160+
}),
73161
message: parse(sanitizeHTML(
74-
`<p>Your Learner Credit Plan expired on ${date}. You are no longer have access to administrative functions and the remaining balance of your plan's budget(s) are no longer available to spend</p>`
75-
+ '<p>Please contact your representative if you have any questions or concerns.</p>',
162+
intl.formatMessage({
163+
id: 'adminPortal.learnerCreditPlan.expiredModal.message',
164+
defaultMessage: `Your Learner Credit plan expired on {date}. You no longer have access to administrative functions and the remaining balance of your plan{apostrophe}s budget(s) are no longer available to spend.
165+
Please contact your representative if you have any questions or concerns.`,
166+
description: 'Message for the modal that the Learner Credit plan has expired.',
167+
}, { date, apostrophe: "'" }),
76168
)),
77169
},
78170
variant: PLAN_EXPIRY_VARIANTS.expired,

src/components/BudgetExpiryAlertAndModal/data/hooks/useExpiry.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useState, useEffect } from 'react';
2+
import { useIntl } from '@edx/frontend-platform/i18n';
23
import {
34
getEnterpriseBudgetExpiringAlertCookieName,
45
getEnterpriseBudgetExpiringModalCookieName,
@@ -7,6 +8,7 @@ import {
78
} from '../utils';
89

910
const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, alertClose) => {
11+
const intl = useIntl();
1012
const [notification, setNotification] = useState(null);
1113
const [expirationThreshold, setExpirationThreshold] = useState(null);
1214
const [modal, setModal] = useState(null);
@@ -41,7 +43,7 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
4143
budgetsToConsiderForExpirationMessaging[0],
4244
);
4345

44-
const { thresholdKey, threshold } = getExpirationMetadata(earliestExpiryBudget.end);
46+
const { thresholdKey, threshold } = getExpirationMetadata(intl, earliestExpiryBudget.end);
4547

4648
if (thresholdKey !== null) {
4749
const { notificationTemplate, modalTemplate } = threshold;
@@ -74,7 +76,7 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
7476
if (!isAlertDismissed) {
7577
alertOpen();
7678
}
77-
}, [budgets, enterpriseId, modalOpen, alertOpen]);
79+
}, [budgets, enterpriseId, modalOpen, alertOpen, intl]);
7880

7981
const dismissModal = () => {
8082
const seenCurrentExpirationModalCookieName = getEnterpriseBudgetExpiringModalCookieName({

src/components/BudgetExpiryAlertAndModal/data/hooks/useExpiry.test.jsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { renderHook } from '@testing-library/react-hooks';
22
import dayjs from 'dayjs';
33
import duration from 'dayjs/plugin/duration'; // Assuming this is the path to your expiryThresholds file
4+
import { createIntl, IntlProvider } from '@edx/frontend-platform/i18n';
45
import useExpiry from './useExpiry';
56
import expiryThresholds from '../expiryThresholds';
67
import { formatDate } from '../../../learner-credit-management/data';
@@ -20,44 +21,57 @@ const offsetDays = {
2021
10: dayjs().add(10, 'day'),
2122
1: dayjs().subtract(1, 'day'),
2223
};
24+
const intl = createIntl({
25+
locale: 'en',
26+
messages: {},
27+
});
2328

2429
describe('useExpiry', () => {
2530
beforeEach(() => {
2631
jest.clearAllMocks();
2732
});
28-
33+
const wrapper = ({ children }) => (
34+
<IntlProvider locale="en">
35+
{children}
36+
</IntlProvider>
37+
);
2938
it.each([
3039
{
3140
endDate: offsetDays['120'],
3241
expected: expiryThresholds[120]({
42+
intl,
3343
date: formatDate(offsetDays['120'].toString()),
3444
}),
3545
isNonExpiredBudget: true,
3646
},
3747
{
3848
endDate: offsetDays['90'],
3949
expected: expiryThresholds[90]({
50+
intl,
4051
date: formatDate(offsetDays['90'].toString()),
4152
}),
4253
isNonExpiredBudget: true,
4354
},
4455
{
4556
endDate: offsetDays['60'],
4657
expected: expiryThresholds[60]({
58+
intl,
4759
date: formatDate(offsetDays['60'].toString()),
4860
}),
4961
isNonExpiredBudget: true,
5062
},
5163
{
5264
endDate: offsetDays['30'],
5365
expected: expiryThresholds[30]({
66+
intl,
5467
date: formatDate(offsetDays['30'].toString()),
5568
}),
5669
isNonExpiredBudget: true,
5770
},
5871
{
5972
endDate: offsetDays['10'],
6073
expected: expiryThresholds[10]({
74+
intl,
6175
date: formatDate(offsetDays['10'].toString()),
6276
days: dayjs.duration(offsetDays['10'].diff(dayjs())).days(),
6377
hours: dayjs.duration(offsetDays['10'].diff(dayjs())).hours(),
@@ -67,14 +81,14 @@ describe('useExpiry', () => {
6781
{
6882
endDate: offsetDays['1'],
6983
expected: expiryThresholds[0]({
84+
intl,
7085
date: formatDate(offsetDays['1'].toString()),
7186
}),
7287
isNonExpiredBudget: false,
7388
},
7489
])('displays correct notification and modal when plan is expiring in %s days', ({ endDate, expected, isNonExpiredBudget }) => {
7590
const budgets = [{ end: endDate }]; // Mock data with an expiring budget
76-
77-
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose));
91+
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose), { wrapper });
7892

7993
expect(result.current.notification).toEqual(expected.notificationTemplate);
8094
expect(result.current.modal).toEqual(expected.modalTemplate);
@@ -86,8 +100,7 @@ describe('useExpiry', () => {
86100
const expiredBudget = { end: dayjs().subtract(1, 'day') };
87101
const nonExpiredBudget = { end: dayjs().add(200, 'day') };
88102
const budgets = [expiredBudget, nonExpiredBudget];
89-
90-
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose));
103+
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose), { wrapper });
91104

92105
expect(result.current.notification).toEqual(null);
93106
expect(result.current.modal).toEqual(null);

src/components/BudgetExpiryAlertAndModal/data/utils.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const getExpiredAndNonExpiredBudgets = (budgets) => {
2222
};
2323
};
2424

25-
export const getExpirationMetadata = (endDateStr) => {
25+
export const getExpirationMetadata = (intl, endDateStr) => {
2626
const endDate = dayjs(endDateStr);
2727
const today = dayjs();
2828
const durationDiff = dayjs.duration(endDate.diff(today));
@@ -40,6 +40,7 @@ export const getExpirationMetadata = (endDateStr) => {
4040
return {
4141
thresholdKey,
4242
threshold: ExpiryThresholds[thresholdKey]({
43+
intl,
4344
date: endDate.format('MMM D, YYYY'),
4445
days: durationDiff.days(),
4546
hours: durationDiff.hours(),
@@ -48,8 +49,8 @@ export const getExpirationMetadata = (endDateStr) => {
4849
};
4950
};
5051

51-
export const isPlanApproachingExpiry = (endDateStr) => {
52-
const { thresholdKey, threshold } = getExpirationMetadata(endDateStr);
52+
export const isPlanApproachingExpiry = (intl, endDateStr) => {
53+
const { thresholdKey, threshold } = getExpirationMetadata(intl, endDateStr);
5354

5455
if (!thresholdKey) {
5556
return false;

src/components/learner-credit-management/BudgetOverviewContent.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
33
import PropTypes from 'prop-types';
44
import { Card, Skeleton } from '@openedx/paragon';
55

6-
import { FormattedMessage } from '@edx/frontend-platform/i18n';
6+
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
77
import {
88
useBudgetDetailHeaderData,
99
useBudgetId,
@@ -19,6 +19,7 @@ const BudgetOverviewContent = ({
1919
enterpriseUUID,
2020
enterpriseFeatures,
2121
}) => {
22+
const intl = useIntl();
2223
const { subsidyAccessPolicyId, enterpriseOfferId } = useBudgetId();
2324
const budgetType = (enterpriseOfferId !== null) ? BUDGET_TYPES.ecommerce : BUDGET_TYPES.policy;
2425

@@ -43,6 +44,7 @@ const BudgetOverviewContent = ({
4344
date,
4445
isAssignable,
4546
} = useBudgetDetailHeaderData({
47+
intl,
4648
subsidyAccessPolicy,
4749
subsidySummary,
4850
budgetId: policyOrOfferId,

0 commit comments

Comments
 (0)