Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: mark static strings for flash messages on login #1246

Merged
merged 1 commit into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading