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: same titles for sent email groups #207

Open
wants to merge 4 commits into
base: open-release/redwood.master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -219,7 +220,7 @@ function BulkEmailForm(props) {
<p>{intl.formatMessage(messages.bulkEmailTaskAlertRecipients, { subject: editor.emailSubject })}</p>
<ul className="list-unstyled">
{editor.emailRecipients.map((group) => (
<li key={group}>{group}</li>
<li key={group}>{getDisplayTextFromRecipient(intl, group)}</li>
))}
</ul>
{!isScheduled && (
Expand All @@ -246,7 +247,7 @@ function BulkEmailForm(props) {
<p>{intl.formatMessage(messages.bulkEmailTaskAlertEditingTo)}</p>
<ul className="list-unstyled">
{editor.emailRecipients.map((group) => (
<li key={group}>{group}</li>
<li key={group}>{getDisplayTextFromRecipient(intl, group)}</li>
))}
</ul>
<p>{intl.formatMessage(messages.bulkEmailTaskAlertEditingWarning)}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
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,
selectedGroups,
additionalCohorts,
courseModes,
} = props;
const intl = useIntl();
const hasCourseModes = courseModes && courseModes.length > 1;
return (
<Form.Group>
Expand All @@ -39,22 +34,14 @@ export default function BulkEmailRecipient(props) {
value={selectedGroups}
>
<Form.Checkbox key="myself" value="myself" className="mt-2.5 col col-lg-4 col-sm-6 col-12">
<FormattedMessage
id="bulk.email.form.recipients.myself"
defaultMessage="Myself"
description="A selectable choice from a list of potential email recipients"
/>
{getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.SELF)}
</Form.Checkbox>
<Form.Checkbox
key="staff"
value="staff"
className="col col-lg-4 col-sm-6 col-12"
>
<FormattedMessage
id="bulk.email.form.recipients.staff"
defaultMessage="Staff/Administrators"
description="A selectable choice from a list of potential email recipients"
/>
{getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.STAFF)}
</Form.Checkbox>
{
// additional modes
Expand All @@ -63,7 +50,7 @@ export default function BulkEmailRecipient(props) {
<Form.Checkbox
key={`track:${courseMode.slug}`}
value={`track:${courseMode.slug}`}
disabled={selectedGroups.find((group) => 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"
>
<FormattedMessage
Expand All @@ -81,7 +68,7 @@ export default function BulkEmailRecipient(props) {
<Form.Checkbox
key={cohort}
value={`cohort:${cohort}`}
disabled={selectedGroups.find((group) => 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"
>
<FormattedMessage
Expand All @@ -97,11 +84,7 @@ export default function BulkEmailRecipient(props) {
value="learners"
className="col col-lg-4 col-sm-6 col-12"
>
<FormattedMessage
id="bulk.email.form.recipients.learners"
defaultMessage="All Learners"
description="A selectable choice from a list of potential email recipients"
/>
{getDisplayTextFromRecipient(intl, DEFAULT_RECIPIENTS_GROUPS.ALL_LEARNERS)}
</Form.Checkbox>
</Form.CheckboxSet>
{!props.isValid && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function ViewEmailModal({
<p className="pl-2">{messageContent.created}</p>
</div>
<div className="d-flex flex-row">
<p>{intl.formatMessage(messages.modalMessageSentTo)}</p>
<p className="flex-shrink-0">{intl.formatMessage(messages.modalMessageSentTo)}</p>
<p className="pl-2">{messageContent.sent_to}</p>
</div>
<hr className="py-2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -29,6 +30,7 @@ function flattenScheduledEmailsArray(emails) {
taskDueUTC: email.taskDue,
...email.courseEmail,
targets: email.courseEmail.targets.join(', '),
targetsText: email.courseEmail.targets.map((mess) => getDisplayTextFromRecipient(intl, mess)).join(', '),
}));
}

Expand All @@ -44,8 +46,8 @@ function BulkEmailScheduledEmailsTable({ intl }) {
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));
Expand Down Expand Up @@ -154,7 +156,7 @@ function BulkEmailScheduledEmailsTable({ intl }) {
},
{
Header: intl.formatMessage(messages.bulkEmailScheduledEmailsTableSendTo),
accessor: 'targets',
accessor: 'targetsText',
},
{
Header: intl.formatMessage(messages.bulkEmailScheduledEmailsTableSubject),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
8 changes: 8 additions & 0 deletions src/components/bulk-email-tool/constants.js
Original file line number Diff line number Diff line change
@@ -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',
};
21 changes: 21 additions & 0 deletions src/components/bulk-email-tool/messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineMessages } from '@edx/frontend-platform/i18n';

const messages = defineMessages({
bulkEmailRecipientsMyselfLabel: {
id: 'bulk.email.recipients.myself.label',
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;
22 changes: 22 additions & 0 deletions src/components/bulk-email-tool/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { DEFAULT_RECIPIENTS_GROUPS } from './constants';
import messages from './messages';

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.
*/
// eslint-disable-next-line import/prefer-default-export
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.
);
Loading