From 2a326e7398a6bcd7defa1130637f61ffbf1f2265 Mon Sep 17 00:00:00 2001
From: Hamzah Ullah
Date: Wed, 12 Jun 2024 12:09:19 -0400
Subject: [PATCH] feat: Add enroll-by date to the assignment table (#1248)
* feat: Add enroll-by date to the assignment table
* feat: adds internationlization on static text
* chore: center column and cells
* chore: UI feedback to match parity
* chore: Update tests
* chore: cleanup
* chore: add test
* chore: PR feedback
* chore: keep datatable component headers arch in parity
* chore: Hardcode apostrophe and more doublequote fixes
* chore: PR feedback 2
---
.../data/expiryThresholds.js | 16 +--
.../DeleteArchivedHighlightsDialogs.jsx | 6 +-
.../ContentHighlights/DeleteHighlightSet.jsx | 6 +-
.../HighlightStepperTitle.jsx | 8 +-
src/components/NotFoundPage/index.jsx | 6 +-
.../AssignmentEnrollByDateCell.jsx | 62 ++++++++++
.../AssignmentEnrollByDateHeader.jsx | 42 +++++++
.../BudgetAssignmentsTable.jsx | 9 ++
.../BudgetDetailPageOverviewAvailability.jsx | 10 +-
.../BudgetStatusSubtitle.jsx | 8 +-
.../CancelAssignmentModal.jsx | 3 +-
.../RemindAssignmentModal.jsx | 3 +-
.../AssignmentAllocationHelpCollapsibles.jsx | 13 +-
.../AssignmentModalSummaryEmptyState.jsx | 3 +-
.../AssignmentModalSummaryErrorState.jsx | 3 +-
.../data/constants.js | 3 +
.../learner-credit-management/data/utils.js | 5 +
.../MemberEnrollmentsTableColumnHeader.jsx | 6 +-
.../MemberStatusTableColumnHeader.jsx | 6 +-
.../members-tab/tests/MembersTab.test.jsx | 1 -
.../tests/BudgetDetailPage.test.jsx | 111 ++++++++++++++++++
.../learner-credit-management/utils.js | 3 -
.../settings/SettingsAppearanceTab/index.jsx | 6 +-
.../SubscriptionExpirationBanner.jsx | 8 +-
.../expiration/SubscriptionExpiringModal.jsx | 4 +-
src/utils.js | 16 +++
26 files changed, 292 insertions(+), 75 deletions(-)
create mode 100644 src/components/learner-credit-management/AssignmentEnrollByDateCell.jsx
create mode 100644 src/components/learner-credit-management/AssignmentEnrollByDateHeader.jsx
delete mode 100644 src/components/learner-credit-management/utils.js
diff --git a/src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js b/src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js
index b91463fa38..3908c36594 100644
--- a/src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js
+++ b/src/components/BudgetExpiryAlertAndModal/data/expiryThresholds.js
@@ -93,26 +93,26 @@ const expiryThresholds = {
30: ({ intl, date }) => ({
notificationTemplate: {
title: intl.formatMessage({
- id: 'adminPostal.learnerCredit.expiresInThirtyDaysNotification.title',
+ id: 'adminPortal.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: 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.',
+ id: 'adminPortal.learnerCredit.expiresInThirtyDaysNotification.message',
+ defaultMessage: "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.",
description: 'Message for the notification that the Learner Credit plan is expiring in less than 30 days.',
- }, { aposrophe: "'" }),
+ }),
},
modalTemplate: {
title: intl.formatMessage({
- id: 'adminPostal.learnerCredit.expiresInThirtyDaysModal.title',
+ id: 'adminPortal.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',
+ id: 'adminPortal.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 }),
@@ -161,10 +161,10 @@ const expiryThresholds = {
message: parse(sanitizeHTML(
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.
+ defaultMessage: `Your Learner Credit plan expired on {date}. You no longer have access to administrative functions and the remaining balance of your plan'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: "'" }),
+ }, { date }),
)),
},
variant: PLAN_EXPIRY_VARIANTS.expired,
diff --git a/src/components/ContentHighlights/DeleteArchivedHighlightsDialogs.jsx b/src/components/ContentHighlights/DeleteArchivedHighlightsDialogs.jsx
index a1db17a147..f75a2e0705 100644
--- a/src/components/ContentHighlights/DeleteArchivedHighlightsDialogs.jsx
+++ b/src/components/ContentHighlights/DeleteArchivedHighlightsDialogs.jsx
@@ -95,12 +95,8 @@ const DeleteArchivedCoursesDialogs = ({
diff --git a/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx b/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
index 34e4dbbdac..992a62a798 100644
--- a/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
+++ b/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
@@ -36,9 +36,9 @@ const SubscriptionExpirationBanner = ({ isSubscriptionPlanDetails }) => {
{intl.formatMessage({
id: 'admin.portal.subscription.expiration.banner.plan.expired.heading',
- defaultMessage: 'This subscription plan{apostrophe}s end date has passed',
+ defaultMessage: "This subscription plan's end date has passed",
description: 'Heading for expired plan message in subscription expiration banner.',
- }, { apostrophe: "'" })}
+ })}
{intl.formatMessage({
id: 'admin.portal.subscription.expiration.banner.plan.expired.message',
@@ -51,9 +51,9 @@ const SubscriptionExpirationBanner = ({ isSubscriptionPlanDetails }) => {
{intl.formatMessage({
id: 'admin.portal.subscription.expiration.banner.plan.approaching.heading',
- defaultMessage: 'This subscription plan{apostrophe}s end date is approaching',
+ defaultMessage: "This subscription plan's end date is approaching",
description: 'Heading for approaching plan message in subscription expiration banner.',
- }, { apostrophe: "'" })}
+ })}
{intl.formatMessage(
{
diff --git a/src/components/subscriptions/expiration/SubscriptionExpiringModal.jsx b/src/components/subscriptions/expiration/SubscriptionExpiringModal.jsx
index fb82ac4b71..b88399db2a 100644
--- a/src/components/subscriptions/expiration/SubscriptionExpiringModal.jsx
+++ b/src/components/subscriptions/expiration/SubscriptionExpiringModal.jsx
@@ -58,12 +58,10 @@ const SubscriptionExpiringModal = ({
{
intl.formatMessage({
id: 'admin.portal.subscription.expiration.modal.body.p1',
- defaultMessage: `It{apostrophe}s time to renew your subscription contract with edX!
+ defaultMessage: `It's time to renew your subscription contract with edX!
The edX customer support team is here to help.
Get in touch today to minimize access disruptions for your learners.`,
description: 'Body paragraph 1 for the subscription expiring modal in the admin portal.',
- }, {
- apostrophe: "'",
})
}
diff --git a/src/utils.js b/src/utils.js
index 5ed45c0eb5..f4488f4141 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -561,6 +561,21 @@ function isArchivedContent(content) {
return courseRunStatuses.every(status => ARCHIVABLE_STATUSES.includes(status));
}
+/**
+ * Helper function utilizing dayjs's 'isBetween' function to determine
+ * if the date passed is between today and an offset amount of days
+ *
+ * @param date
+ * @param days
+ * @returns {boolean}
+ */
+function isTodayWithinDateThreshold({ date, days }) {
+ const dateToCheck = dayjs(date);
+ const today = dayjs();
+ const offsetDays = dateToCheck.subtract(days, 'days');
+ return today.isBetween(offsetDays, dateToCheck);
+}
+
export {
camelCaseDict,
camelCaseDictArray,
@@ -604,4 +619,5 @@ export {
i18nFormatTimestamp,
i18nFormatPassedTimestamp,
i18nFormatProgressStatus,
+ isTodayWithinDateThreshold,
};