diff --git a/package-lock.json b/package-lock.json
index b76c0cc8..7cc71979 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2695,20 +2695,20 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
- "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/wasi-threads": "1.1.0",
+ "@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
- "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2716,9 +2716,9 @@
}
},
"node_modules/@emnapi/wasi-threads": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
- "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -3392,6 +3392,9 @@
"cpu": [
"arm"
],
+ "libc": [
+ "glibc"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3408,6 +3411,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3424,6 +3430,9 @@
"cpu": [
"ppc64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3440,6 +3449,9 @@
"cpu": [
"s390x"
],
+ "libc": [
+ "glibc"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3456,6 +3468,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3472,6 +3487,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3488,6 +3506,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -3504,6 +3525,9 @@
"cpu": [
"arm"
],
+ "libc": [
+ "glibc"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3526,6 +3550,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3548,6 +3575,9 @@
"cpu": [
"ppc64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3570,6 +3600,9 @@
"cpu": [
"s390x"
],
+ "libc": [
+ "glibc"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3592,6 +3625,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3614,6 +3650,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -3636,6 +3675,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -5370,6 +5412,9 @@
"cpu": [
"arm"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -5390,6 +5435,9 @@
"cpu": [
"arm"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -5410,6 +5458,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -5430,6 +5481,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -5450,6 +5504,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -5470,6 +5527,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7026,6 +7086,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7039,6 +7102,9 @@
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7052,6 +7118,9 @@
"cpu": [
"ppc64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7065,6 +7134,9 @@
"cpu": [
"riscv64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7078,6 +7150,9 @@
"cpu": [
"riscv64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7091,6 +7166,9 @@
"cpu": [
"s390x"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7104,6 +7182,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -7117,6 +7198,9 @@
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
diff --git a/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx b/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx
index 26191c62..9389edb4 100644
--- a/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx
+++ b/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx
@@ -28,6 +28,7 @@ import {
} from './data/actions';
import { editScheduledEmailThunk, postBulkEmailThunk } from './data/thunks';
import { getScheduledBulkEmailThunk } from '../bulk-email-task-manager/bulk-email-scheduled-emails-table/data/thunks';
+import { getDisplayTextFromRecipient } from '../utils';
import './bulkEmailForm.scss';
@@ -219,7 +220,7 @@ function BulkEmailForm(props) {
{intl.formatMessage(messages.bulkEmailTaskAlertRecipients, { subject: editor.emailSubject })}
{editor.emailRecipients.map((group) => (
- - {group}
+ - {getDisplayTextFromRecipient(intl, group)}
))}
{!isScheduled && (
@@ -246,7 +247,7 @@ function BulkEmailForm(props) {
{intl.formatMessage(messages.bulkEmailTaskAlertEditingTo)}
{editor.emailRecipients.map((group) => (
- - {group}
+ - {getDisplayTextFromRecipient(intl, group)}
))}
{intl.formatMessage(messages.bulkEmailTaskAlertEditingWarning)}
diff --git a/src/components/bulk-email-tool/bulk-email-form/bulk-email-recipient/BulkEmailRecipient.jsx b/src/components/bulk-email-tool/bulk-email-form/bulk-email-recipient/BulkEmailRecipient.jsx
index d60b316b..98ca9b67 100644
--- a/src/components/bulk-email-tool/bulk-email-form/bulk-email-recipient/BulkEmailRecipient.jsx
+++ b/src/components/bulk-email-tool/bulk-email-form/bulk-email-recipient/BulkEmailRecipient.jsx
@@ -1,18 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Form } from '@openedx/paragon';
-import { FormattedMessage } from '@edx/frontend-platform/i18n';
+import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
+import { getDisplayTextFromRecipient } from '../../utils';
+import { DEFAULT_RECIPIENTS_GROUPS } from '../../constants';
import './bulkEmailRecepient.scss';
-const DEFAULT_GROUPS = {
- SELF: 'myself',
- STAFF: 'staff',
- ALL_LEARNERS: 'learners',
- VERIFIED: 'track:verified',
- AUDIT: 'track:audit',
-};
-
export default function BulkEmailRecipient(props) {
const {
handleCheckboxes,
@@ -20,6 +14,7 @@ export default function BulkEmailRecipient(props) {
additionalCohorts,
courseModes,
} = props;
+ const intl = useIntl();
const hasCourseModes = courseModes && courseModes.length > 1;
return (
@@ -39,22 +34,14 @@ export default function BulkEmailRecipient(props) {
value={selectedGroups}
>
-
+ {getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.SELF)}
-
+ {getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.STAFF)}
{
// additional modes
@@ -63,7 +50,7 @@ export default function BulkEmailRecipient(props) {
group === DEFAULT_GROUPS.ALL_LEARNERS)}
+ disabled={selectedGroups.find((group) => group === DEFAULT_RECIPIENTS_GROUPS.ALL_LEARNERS)}
className="col col-lg-4 col-sm-6 col-12"
>
group === DEFAULT_GROUPS.ALL_LEARNERS)}
+ disabled={selectedGroups.find((group) => group === DEFAULT_RECIPIENTS_GROUPS.ALL_LEARNERS)}
className="col col-lg-4 col-sm-6 col-12"
>
-
+ {getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.ALL_LEARNERS)}
{!props.isValid && (
diff --git a/src/components/bulk-email-tool/bulk-email-form/test/BulkEmailForm.test.jsx b/src/components/bulk-email-tool/bulk-email-form/test/BulkEmailForm.test.jsx
index b11d9edc..afacbccd 100644
--- a/src/components/bulk-email-tool/bulk-email-form/test/BulkEmailForm.test.jsx
+++ b/src/components/bulk-email-tool/bulk-email-form/test/BulkEmailForm.test.jsx
@@ -99,9 +99,9 @@ describe('bulk-email-form', () => {
fireEvent.click(await screen.findByRole('button', { name: /continue/i }));
expect(await screen.findByText('An error occured while attempting to send the email.')).toBeInTheDocument();
});
- test('Checking "All Learners" disables each learner group', async () => {
+ test('Checking "All learners" disables each learner group', async () => {
render(renderBulkEmailForm());
- fireEvent.click(screen.getByRole('checkbox', { name: 'All Learners' }));
+ fireEvent.click(screen.getByRole('checkbox', { name: 'All learners' }));
const verifiedLearners = screen.getByRole('checkbox', { name: 'Learners in the Verified Certificate Track' });
const auditLearners = screen.getByRole('checkbox', { name: 'Learners in the Audit Track' });
const { cohorts } = cohortFactory.build();
diff --git a/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/BulkEmailScheduledEmailsTable.jsx b/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/BulkEmailScheduledEmailsTable.jsx
index a7bdd685..4f6d5128 100644
--- a/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/BulkEmailScheduledEmailsTable.jsx
+++ b/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/BulkEmailScheduledEmailsTable.jsx
@@ -19,8 +19,9 @@ import ViewEmailModal from '../ViewEmailModal';
import { copyToEditor } from '../../bulk-email-form/data/actions';
import TaskAlertModal from '../../task-alert-modal';
import { formatDate, formatTime } from '../../../../utils/formatDateAndTime';
+import { getDisplayTextFromRecipient } from '../../utils';
-function flattenScheduledEmailsArray(emails) {
+function flattenScheduledEmailsArray(intl, emails) {
return emails.map((email) => ({
schedulingId: email.id,
emailId: email.courseEmail.id,
@@ -29,6 +30,7 @@ function flattenScheduledEmailsArray(emails) {
taskDueUTC: email.taskDue,
...email.courseEmail,
targets: email.courseEmail.targets.join(', '),
+ targetsText: email.courseEmail.targets.map((recipient) => getDisplayTextFromRecipient(intl, recipient)).join(', '),
}));
}
@@ -45,8 +47,8 @@ function BulkEmailScheduledEmailsTable() {
const [currentTask, setCurrentTask] = useState({});
useEffect(() => {
- setTableData(flattenScheduledEmailsArray(scheduledEmailsTable.results));
- }, [scheduledEmailsTable.results]);
+ setTableData(flattenScheduledEmailsArray(intl, scheduledEmailsTable.results));
+ }, [intl, scheduledEmailsTable.results]);
const fetchTableData = useCallback((args) => {
dispatch(getScheduledBulkEmailThunk(courseId, args.pageIndex + 1));
@@ -63,7 +65,7 @@ function BulkEmailScheduledEmailsTable() {
email: {
html_message: row.original.htmlMessage,
},
- sent_to: row.original.targets,
+ sent_to: row.original.targetsText,
},
});
};
@@ -155,7 +157,7 @@ function BulkEmailScheduledEmailsTable() {
},
{
Header: intl.formatMessage(messages.bulkEmailScheduledEmailsTableSendTo),
- accessor: 'targets',
+ accessor: 'targetsText',
},
{
Header: intl.formatMessage(messages.bulkEmailScheduledEmailsTableSubject),
diff --git a/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/test/BulkEmailScheduledEmailsTable.test.jsx b/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/test/BulkEmailScheduledEmailsTable.test.jsx
index 3495bef2..e540f727 100644
--- a/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/test/BulkEmailScheduledEmailsTable.test.jsx
+++ b/src/components/bulk-email-tool/bulk-email-task-manager/bulk-email-scheduled-emails-table/test/BulkEmailScheduledEmailsTable.test.jsx
@@ -42,7 +42,7 @@ describe('BulkEmailScheduledEmailsTable', () => {
.onGet(`${getConfig().LMS_BASE_URL}/api/instructor_task/v1/schedules/test-id/bulk_email/?page=1`)
.reply(200, scheduledEmailsFactory.build(1));
render(renderBulkEmailScheduledEmailsTable());
- expect(await screen.findByText('learners')).toBeTruthy();
+ expect(await screen.findByText('All learners')).toBeTruthy();
expect(await screen.findByText('subject')).toBeTruthy();
expect(await screen.findByText('edx')).toBeTruthy();
expect(await screen.findByLabelText('View')).toBeTruthy();
diff --git a/src/components/bulk-email-tool/constants.js b/src/components/bulk-email-tool/constants.js
new file mode 100644
index 00000000..9cd9e4f5
--- /dev/null
+++ b/src/components/bulk-email-tool/constants.js
@@ -0,0 +1,8 @@
+// eslint-disable-next-line import/prefer-default-export
+export const DEFAULT_RECIPIENTS_GROUPS = {
+ SELF: 'myself',
+ STAFF: 'staff',
+ ALL_LEARNERS: 'learners',
+ VERIFIED: 'track:verified',
+ AUDIT: 'track:audit',
+};
diff --git a/src/components/bulk-email-tool/messages.js b/src/components/bulk-email-tool/messages.js
new file mode 100644
index 00000000..2d6cadb7
--- /dev/null
+++ b/src/components/bulk-email-tool/messages.js
@@ -0,0 +1,21 @@
+import { defineMessages } from '@edx/frontend-platform/i18n';
+
+const messages = defineMessages({
+ bulkEmailRecipientsMyselfLabel: {
+ id: 'bulk.email.form.recipients.myself',
+ defaultMessage: 'Myself',
+ description: 'Label for selecting the option to send a bulk email to oneself.',
+ },
+ bulkEmailRecipientsStaffLabel: {
+ id: 'bulk.email.recipients.staff.label',
+ defaultMessage: 'Staff and instructors',
+ description: 'Label for selecting the option to send a bulk email to all staff and instructors.',
+ },
+ bulkEmailRecipientsLearnersLabel: {
+ id: 'bulk.email.recipients.learners.label',
+ defaultMessage: 'All learners',
+ description: 'Label for selecting the option to send a bulk email to all learners.',
+ },
+});
+
+export default messages;
diff --git a/src/components/bulk-email-tool/utils.js b/src/components/bulk-email-tool/utils.js
new file mode 100644
index 00000000..4d4764cb
--- /dev/null
+++ b/src/components/bulk-email-tool/utils.js
@@ -0,0 +1,21 @@
+import { DEFAULT_RECIPIENTS_GROUPS } from './constants';
+import messages from './messages';
+
+export const RECIPIENTS_DISPLAY_NAMES = {
+ [DEFAULT_RECIPIENTS_GROUPS.SELF]: messages.bulkEmailRecipientsMyselfLabel,
+ [DEFAULT_RECIPIENTS_GROUPS.STAFF]: messages.bulkEmailRecipientsStaffLabel,
+ [DEFAULT_RECIPIENTS_GROUPS.ALL_LEARNERS]: messages.bulkEmailRecipientsLearnersLabel,
+};
+
+/**
+ * Retrieves the display text for a given recipient.
+ *
+ * @param {Object} intl - The internationalization object, provided by React Intl.
+ * @param {string} recipient - The recipient key used to look up the corresponding display name.
+ * @returns {string} - The formatted display name for the recipient,
+ * or the original recipient key if no display name is found.
+ */
+export const getDisplayTextFromRecipient = (intl, recipient) => {
+ const msg = RECIPIENTS_DISPLAY_NAMES[recipient];
+ return msg ? intl.formatMessage(msg) : recipient; // Fall back to the recipient key if no display name is found.
+};