diff --git a/src/components/bulk-email-tool/BulkEmailTool.jsx b/src/components/bulk-email-tool/BulkEmailTool.jsx index 015e1d0..f8a54a2 100644 --- a/src/components/bulk-email-tool/BulkEmailTool.jsx +++ b/src/components/bulk-email-tool/BulkEmailTool.jsx @@ -6,7 +6,7 @@ import { Spinner } from '@edx/paragon'; import { ErrorPage } from '@edx/frontend-platform/react'; import BulkEmailTaskManager from './bulk-email-task-manager/BulkEmailTaskManager'; import Navigationtabs from '../navigation-tabs/NavigationTabs'; -import { getCourseHomeCourseMetadata } from './data/api'; +import { getCohorts, getCourseHomeCourseMetadata } from './data/api'; import useMobileResponsive from '../../utils/useMobileResponsive'; import BulkEmailForm from './bulk-email-form'; @@ -18,20 +18,25 @@ export default function BulkEmailTool() { useEffect(() => { async function fetchTabData() { - let data; + let metadataResponse; + let cohortsResponse; try { - data = await getCourseHomeCourseMetadata(courseId); + metadataResponse = await getCourseHomeCourseMetadata(courseId); + cohortsResponse = await getCohorts(courseId); } catch (e) { setCourseMetadata({ isStaff: false, tabs: [], + cohorts: [], }); return; } - const { tabs, is_staff: isStaff } = data; + const { tabs, is_staff: isStaff } = metadataResponse; + const { cohorts } = cohortsResponse; setCourseMetadata({ isStaff, tabs: [...tabs], + cohorts: cohorts.map(({ name }) => name), }); } fetchTabData(); @@ -43,7 +48,7 @@ export default function BulkEmailTool() {
- +
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 dd19344..c2af641 100644 --- a/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx +++ b/src/components/bulk-email-tool/bulk-email-form/BulkEmailForm.jsx @@ -20,7 +20,7 @@ export const FORM_SUBMIT_STATES = { }; export default function BulkEmailForm(props) { - const { courseId } = props; + const { courseId, cohorts } = props; const [subject, setSubject] = useState(''); const [emailFormStatus, setEmailFormStatus] = useState(FORM_SUBMIT_STATES.DEFAULT); const [emailFormValidation, setEmailFormValidation] = useState({ @@ -126,6 +126,7 @@ export default function BulkEmailForm(props) { @@ -220,6 +221,11 @@ export default function BulkEmailForm(props) { ); } +BulkEmailForm.defaultProps = { + cohorts: [], +}; + BulkEmailForm.propTypes = { courseId: PropTypes.string.isRequired, + cohorts: PropTypes.arrayOf(PropTypes.string), }; diff --git a/src/components/bulk-email-tool/bulk-email-form/BulkEmailRecipient.jsx b/src/components/bulk-email-tool/bulk-email-form/BulkEmailRecipient.jsx index 3fb3c04..5a486ac 100644 --- a/src/components/bulk-email-tool/bulk-email-form/BulkEmailRecipient.jsx +++ b/src/components/bulk-email-tool/bulk-email-form/BulkEmailRecipient.jsx @@ -12,7 +12,7 @@ const DEFAULT_GROUPS = { }; export default function BulkEmailRecipient(props) { - const { handleCheckboxes, selectedGroups } = props; + const { handleCheckboxes, selectedGroups, additionalCohorts } = props; return ( @@ -22,8 +22,13 @@ export default function BulkEmailRecipient(props) { description="A label before the list of potential recipients" /> - - + + + { + // additional cohorts + additionalCohorts + && additionalCohorts.map((cohort) => ( + group === (DEFAULT_GROUPS.AUDIT || DEFAULT_GROUPS.VERIFIED))} + > + + + )) + } {!props.isValid && ( @@ -86,10 +108,12 @@ export default function BulkEmailRecipient(props) { BulkEmailRecipient.defaultProps = { isValid: true, + additionalCohorts: [], }; BulkEmailRecipient.propTypes = { selectedGroups: PropTypes.arrayOf(PropTypes.string).isRequired, handleCheckboxes: PropTypes.func.isRequired, isValid: PropTypes.bool, + additionalCohorts: PropTypes.arrayOf(PropTypes.string), }; diff --git a/src/components/bulk-email-tool/data/__factories__/cohort.factory.js b/src/components/bulk-email-tool/data/__factories__/cohort.factory.js new file mode 100644 index 0000000..ab51d27 --- /dev/null +++ b/src/components/bulk-email-tool/data/__factories__/cohort.factory.js @@ -0,0 +1,9 @@ +import { Factory } from 'rosie'; // eslint-disable-line import/no-extraneous-dependencies + +export default Factory.define('cohort') + .sequence('id', (i) => i) + .sequence('name', i => `test cohort ${i}`) + .attrs({ + assignment_type: 'test', + user_count: 1, + }); diff --git a/src/components/bulk-email-tool/data/api.js b/src/components/bulk-email-tool/data/api.js index 5a3eeb8..70d39ce 100644 --- a/src/components/bulk-email-tool/data/api.js +++ b/src/components/bulk-email-tool/data/api.js @@ -14,3 +14,9 @@ export async function getCourseHomeCourseMetadata(courseId) { const { data } = await getAuthenticatedHttpClient().get(courseHomeMetadataUrl); return data; } + +export async function getCohorts(courseId) { + const url = `${getConfig().LMS_BASE_URL}/courses/${courseId}/cohorts/`; + const { data } = await getAuthenticatedHttpClient().get(url); + return data; +} diff --git a/src/components/bulk-email-tool/test/BulkEmailTool.test.jsx b/src/components/bulk-email-tool/test/BulkEmailTool.test.jsx index 5ff2d15..ee02cf0 100644 --- a/src/components/bulk-email-tool/test/BulkEmailTool.test.jsx +++ b/src/components/bulk-email-tool/test/BulkEmailTool.test.jsx @@ -3,10 +3,11 @@ */ import React from 'react'; import { Factory } from 'rosie'; -import { render, screen } from '../../../setupTest'; +import { render, screen, cleanup } from '../../../setupTest'; import BulkEmailTool from '../BulkEmailTool'; -import { getCourseHomeCourseMetadata } from '../data/api'; +import { getCourseHomeCourseMetadata, getCohorts } from '../data/api'; import '../data/__factories__/courseMetadata.factory'; +import '../data/__factories__/cohort.factory'; jest.mock('../text-editor/TextEditor'); jest.mock('../bulk-email-task-manager/api', () => ({ @@ -16,6 +17,7 @@ jest.mock('../bulk-email-task-manager/api', () => ({ jest.mock('../data/api', () => ({ __esModule: true, getCourseHomeCourseMetadata: jest.fn(() => {}), + getCohorts: jest.fn(() => {}), })); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -25,15 +27,21 @@ jest.mock('react-router-dom', () => ({ })); describe('BulkEmailTool', () => { + beforeEach(() => jest.resetModules()); + afterEach(cleanup); test('BulkEmailTool renders properly when given course metadata', async () => { const courseMetadata = Factory.build('courseMetadata'); + const cohorts = { cohorts: [Factory.build('cohort'), Factory.build('cohort')] }; getCourseHomeCourseMetadata.mockImplementation(() => courseMetadata); + getCohorts.mockImplementation(() => cohorts); render(); expect(await screen.findByText('Course')).toBeTruthy(); }); test('BulkEmailTool renders error page on no staff user', async () => { const courseMetadata = Factory.build('courseMetadata', { is_staff: false }); + const cohorts = { cohorts: [Factory.build('cohort'), Factory.build('cohort')] }; getCourseHomeCourseMetadata.mockImplementation(() => courseMetadata); + getCohorts.mockImplementation(() => cohorts); render(); expect( await screen.findByText('An unexpected error occurred. Please click the button below to refresh the page.'),