Skip to content

Commit

Permalink
Merge pull request #1246 from openedx/eahmadjaved/ENT-8748
Browse files Browse the repository at this point in the history
feat: mark static strings for flash messages on login
  • Loading branch information
jajjibhai008 authored Jun 5, 2024
2 parents 85e2cdf + edd4e31 commit 5eae978
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 64 deletions.
150 changes: 121 additions & 29 deletions src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,168 @@ import parse from 'html-react-parser';
import { PLAN_EXPIRY_VARIANTS } from './constants';

const expiryThresholds = {
120: ({ date }) => ({
120: ({ intl, date }) => ({
notificationTemplate: {
title: 'Your Learner Credit plan expires soon',
title: intl.formatMessage({
id: 'adminPortal.leaernerCredit.expiryNotification.title',
defaultMessage: 'Your Learner Credit plan expires soon',
description: 'Title for the notification that the Learner Credit plan is expiring soon.',
}),
variant: 'info',
message: `Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`,
message: intl.formatMessage({
id: 'adminPortal.leaernerCredit.expiryNotification.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the notification that the Learner Credit plan is expiring soon.',
}, { date }),
dismissible: true,
},
modalTemplate: {
title: 'Your plan expires soon',
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
title: intl.formatMessage({
id: 'adminPortal.leaernerCredit.expiryModal.title',
defaultMessage: 'Your plan expires soon',
description: 'Title for the modal that the Learner Credit plan is expiring soon.',
}),
message: parse(sanitizeHTML(intl.formatMessage({
id: 'adminPortal.leaernerCredit.expiryModal.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the modal that the Learner Credit plan is expiring soon.',
}, { date }))),
},
variant: PLAN_EXPIRY_VARIANTS.expiring,
}),
90: ({ date }) => ({
90: ({ intl, date }) => ({
notificationTemplate: {
title: 'Reminder: Your Learner Credit plan expires soon',
title: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiryReminderNotification.title',
defaultMessage: 'Reminder: Your Learner Credit plan expires soon',
description: 'Title for the notification that the Learner Credit plan is expiring soon.',
}),
variant: 'info',
message: `Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`,
message: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiryReminderNotification.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the notification that the Learner Credit plan is expiring soon.',
}, { date }),
dismissible: true,
},
modalTemplate: {
title: 'Reminder: Your plan expires soon',
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
title: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiryReminderModal.title',
defaultMessage: 'Reminder: Your plan expires soon',
description: 'Title for the modal that the Learner Credit plan is expiring soon.',
}),
message: parse(sanitizeHTML(intl.formatMessage({
id: 'adminPortal.learnerCredit.expiryReminderModal.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the modal that the Learner Credit plan is expiring soon.',
}, { date }))),
},
variant: PLAN_EXPIRY_VARIANTS.expiring,
}),
60: ({ date }) => ({
60: ({ intl, date }) => ({
notificationTemplate: {
title: `Your Learner Credit plan expires ${date}`,
title: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiresNotification.title',
defaultMessage: 'Your Learner Credit plan expires {date}',
description: 'Title for the notification that the Learner Credit plan is expiring.',
}, { date }),
variant: 'warning',
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.',
message: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiresNotification.message',
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.',
description: 'Message for the notification that the Learner Credit plan is expiring.',
}),
dismissible: true,
},
modalTemplate: {
title: `Your Learner Credit plan expires ${date}`,
message: parse(sanitizeHTML(`Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.`)),
title: intl.formatMessage({
id: 'adminPortal.learnerCredit.expiresModal.title',
defaultMessage: 'Your Learner Credit plan expires {date}',
description: 'Title for the modal that the Learner Credit plan is expiring.',
}, { date }),
message: parse(sanitizeHTML(intl.formatMessage({
id: 'adminPortal.learnerCredit.expiresModal.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the modal that the Learner Credit plan is expiring.',
}, { date }))),
},
variant: PLAN_EXPIRY_VARIANTS.expiring,
}),
30: ({ date }) => ({
30: ({ intl, date }) => ({
notificationTemplate: {
title: 'Your Learner Credit plan expires in less than 30 days',
title: intl.formatMessage({
id: 'adminPostal.learnerCredit.expiresInThirtyDaysNotification.title',
defaultMessage: 'Your Learner Credit plan expires in less than 30 days',
description: 'Title for the notification that the Learner Credit plan is expiring in less than 30 days.',
}),
variant: 'danger',
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.',
message: intl.formatMessage({
id: 'adminPostal.learnerCredit.expiresInThirtyDaysNotification.message',
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.',
description: 'Message for the notification that the Learner Credit plan is expiring in less than 30 days.',
}, { aposrophe: "'" }),
},
modalTemplate: {
title: 'Your Learner Credit plan expires in less than 30 days',
message: parse(sanitizeHTML(`<p>Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.</p>`)),
title: intl.formatMessage({
id: 'adminPostal.learnerCredit.expiresInThirtyDaysModal.title',
defaultMessage: 'Your Learner Credit plan expires in less than 30 days',
description: 'Title for the modal that the Learner Credit plan is expiring in less than 30 days.',
}),
message: parse(sanitizeHTML(
intl.formatMessage({
id: 'adminPostal.learnerCredit.expiresInThirtyDaysModal.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the modal that the Learner Credit plan is expiring in less than 30 days.',
}, { date }),
)),
},
variant: PLAN_EXPIRY_VARIANTS.expiring,
}),
10: ({ date, days, hours }) => ({
10: ({
intl, date, days, hours,
}) => ({
notificationTemplate: {
title: `Reminder: Your Learner Credit plan expires ${date}`,
title: intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysNotification.title',
defaultMessage: 'Reminder: Your Learner Credit plan expires {date}',
description: 'Title for the notification that the Learner Credit plan is expiring.',
}, { date }),
variant: 'danger',
message: parse(sanitizeHTML(`Your Learner Credit plan expires in <strong>${days} days and ${hours} hours</strong>. Contact support today to renew your plan.`)),
message: parse(sanitizeHTML(intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysNotification.message',
defaultMessage: 'Your Learner Credit plan expires in <strong>{days} days and {hours} hours</strong>. Contact support today to renew your plan.',
description: 'Message for the notification that the Learner Credit plan is expiring.',
}, { days, hours, strong: (str) => `<strong>${str}</strong>` }))),
},
modalTemplate: {
title: `Reminder: Your Learner Credit plan expires ${date}`,
message: parse(sanitizeHTML(`<p>Your Learner Credit plan expires ${date}. Contact support today to renew your plan and keep people learning.</p>`)),
title: intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysModal.title',
defaultMessage: 'Reminder: Your Learner Credit plan expires {date}',
description: 'Title for the modal that the Learner Credit plan is expiring.',
}, { date }),
message: parse(sanitizeHTML(intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiresInTenDaysModal.message',
defaultMessage: 'Your Learner Credit plan expires {date}. Contact support today to renew your plan and keep people learning.',
description: 'Message for the modal that the Learner Credit plan is expiring.',
}, { date }))),
},
variant: PLAN_EXPIRY_VARIANTS.expiring,
}),
0: ({ date }) => ({
0: ({ intl, date }) => ({
notificationTemplate: null,
modalTemplate: {
title: 'Your Learner Credit plan has expired',
title: intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiredModal.title',
defaultMessage: 'Your Learner Credit plan has expired',
description: 'Title for the modal that the Learner Credit plan has expired.',
}),
message: parse(sanitizeHTML(
`<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>`
+ '<p>Please contact your representative if you have any questions or concerns.</p>',
intl.formatMessage({
id: 'adminPortal.learnerCreditPlan.expiredModal.message',
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.
Please contact your representative if you have any questions or concerns.`,
description: 'Message for the modal that the Learner Credit plan has expired.',
}, { date, apostrophe: "'" }),
)),
},
variant: PLAN_EXPIRY_VARIANTS.expired,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useEffect } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
getEnterpriseBudgetExpiringAlertCookieName,
getEnterpriseBudgetExpiringModalCookieName,
Expand All @@ -7,6 +8,7 @@ import {
} from '../utils';

const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, alertClose) => {
const intl = useIntl();
const [notification, setNotification] = useState(null);
const [expirationThreshold, setExpirationThreshold] = useState(null);
const [modal, setModal] = useState(null);
Expand Down Expand Up @@ -41,7 +43,7 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
budgetsToConsiderForExpirationMessaging[0],
);

const { thresholdKey, threshold } = getExpirationMetadata(earliestExpiryBudget.end);
const { thresholdKey, threshold } = getExpirationMetadata(intl, earliestExpiryBudget.end);

if (thresholdKey !== null) {
const { notificationTemplate, modalTemplate } = threshold;
Expand Down Expand Up @@ -74,7 +76,7 @@ const useExpiry = (enterpriseId, budgets, modalOpen, modalClose, alertOpen, aler
if (!isAlertDismissed) {
alertOpen();
}
}, [budgets, enterpriseId, modalOpen, alertOpen]);
}, [budgets, enterpriseId, modalOpen, alertOpen, intl]);

const dismissModal = () => {
const seenCurrentExpirationModalCookieName = getEnterpriseBudgetExpiringModalCookieName({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { renderHook } from '@testing-library/react-hooks';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; // Assuming this is the path to your expiryThresholds file
import { createIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import useExpiry from './useExpiry';
import expiryThresholds from '../expiryThresholds';
import { formatDate } from '../../../learner-credit-management/data';
Expand All @@ -20,44 +21,57 @@ const offsetDays = {
10: dayjs().add(10, 'day'),
1: dayjs().subtract(1, 'day'),
};
const intl = createIntl({
locale: 'en',
messages: {},
});

describe('useExpiry', () => {
beforeEach(() => {
jest.clearAllMocks();
});

const wrapper = ({ children }) => (
<IntlProvider locale="en">
{children}
</IntlProvider>
);
it.each([
{
endDate: offsetDays['120'],
expected: expiryThresholds[120]({
intl,
date: formatDate(offsetDays['120'].toString()),
}),
isNonExpiredBudget: true,
},
{
endDate: offsetDays['90'],
expected: expiryThresholds[90]({
intl,
date: formatDate(offsetDays['90'].toString()),
}),
isNonExpiredBudget: true,
},
{
endDate: offsetDays['60'],
expected: expiryThresholds[60]({
intl,
date: formatDate(offsetDays['60'].toString()),
}),
isNonExpiredBudget: true,
},
{
endDate: offsetDays['30'],
expected: expiryThresholds[30]({
intl,
date: formatDate(offsetDays['30'].toString()),
}),
isNonExpiredBudget: true,
},
{
endDate: offsetDays['10'],
expected: expiryThresholds[10]({
intl,
date: formatDate(offsetDays['10'].toString()),
days: dayjs.duration(offsetDays['10'].diff(dayjs())).days(),
hours: dayjs.duration(offsetDays['10'].diff(dayjs())).hours(),
Expand All @@ -67,14 +81,14 @@ describe('useExpiry', () => {
{
endDate: offsetDays['1'],
expected: expiryThresholds[0]({
intl,
date: formatDate(offsetDays['1'].toString()),
}),
isNonExpiredBudget: false,
},
])('displays correct notification and modal when plan is expiring in %s days', ({ endDate, expected, isNonExpiredBudget }) => {
const budgets = [{ end: endDate }]; // Mock data with an expiring budget

const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose));
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose), { wrapper });

expect(result.current.notification).toEqual(expected.notificationTemplate);
expect(result.current.modal).toEqual(expected.modalTemplate);
Expand All @@ -86,8 +100,7 @@ describe('useExpiry', () => {
const expiredBudget = { end: dayjs().subtract(1, 'day') };
const nonExpiredBudget = { end: dayjs().add(200, 'day') };
const budgets = [expiredBudget, nonExpiredBudget];

const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose));
const { result } = renderHook(() => useExpiry('enterpriseId', budgets, modalOpen, modalClose, alertOpen, alertClose), { wrapper });

expect(result.current.notification).toEqual(null);
expect(result.current.modal).toEqual(null);
Expand Down
7 changes: 4 additions & 3 deletions src/components/BudgetExpiryAlertAndModal/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const getExpiredAndNonExpiredBudgets = (budgets) => {
};
};

export const getExpirationMetadata = (endDateStr) => {
export const getExpirationMetadata = (intl, endDateStr) => {
const endDate = dayjs(endDateStr);
const today = dayjs();
const durationDiff = dayjs.duration(endDate.diff(today));
Expand All @@ -40,6 +40,7 @@ export const getExpirationMetadata = (endDateStr) => {
return {
thresholdKey,
threshold: ExpiryThresholds[thresholdKey]({
intl,
date: endDate.format('MMM D, YYYY'),
days: durationDiff.days(),
hours: durationDiff.hours(),
Expand All @@ -48,8 +49,8 @@ export const getExpirationMetadata = (endDateStr) => {
};
};

export const isPlanApproachingExpiry = (endDateStr) => {
const { thresholdKey, threshold } = getExpirationMetadata(endDateStr);
export const isPlanApproachingExpiry = (intl, endDateStr) => {
const { thresholdKey, threshold } = getExpirationMetadata(intl, endDateStr);

if (!thresholdKey) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Card, Skeleton } from '@openedx/paragon';

import { FormattedMessage } from '@edx/frontend-platform/i18n';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
useBudgetDetailHeaderData,
useBudgetId,
Expand All @@ -19,6 +19,7 @@ const BudgetOverviewContent = ({
enterpriseUUID,
enterpriseFeatures,
}) => {
const intl = useIntl();
const { subsidyAccessPolicyId, enterpriseOfferId } = useBudgetId();
const budgetType = (enterpriseOfferId !== null) ? BUDGET_TYPES.ecommerce : BUDGET_TYPES.policy;

Expand All @@ -43,6 +44,7 @@ const BudgetOverviewContent = ({
date,
isAssignable,
} = useBudgetDetailHeaderData({
intl,
subsidyAccessPolicy,
subsidySummary,
budgetId: policyOrOfferId,
Expand Down
Loading

0 comments on commit 5eae978

Please sign in to comment.