Skip to content

Commit 5dc3884

Browse files
feat: add beta testers
1 parent 8b0a7e0 commit 5dc3884

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

src/enrollments/EnrollmentsPage.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import EnrollmentStatusModal from './components/EnrollmentStatusModal';
88
import UnenrollModal from './components/UnenrollModal';
99
import EnrollLearnersModal from './components/EnrollLearnersModal';
1010
import { Learner } from './types';
11+
import AddBetaTestersModal from './components/AddBetaTestersModal';
1112

1213
const EnrollmentsPage = () => {
1314
const intl = useIntl();
1415
const [isEnrollmentStatusModalOpen, setIsEnrollmentStatusModalOpen] = useState(false);
1516
const [isEnrollLearnersModalOpen, setIsEnrollLearnersModalOpen] = useState(false);
17+
const [isAddBetaTestersModalOpen, setIsAddBetaTestersModalOpen] = useState(false);
1618
const [isUnenrollModalOpen, setIsUnenrollModalOpen] = useState(false);
1719
const [selectedLearner, setSelectedLearner] = useState<Learner | null>(null);
1820

@@ -38,6 +40,10 @@ const EnrollmentsPage = () => {
3840
setIsEnrollLearnersModalOpen(true);
3941
};
4042

43+
const handleAddBetaTesters = () => {
44+
setIsAddBetaTestersModalOpen(true);
45+
};
46+
4147
return (
4248
<div className="my-4.5 mx-4">
4349
<div className="d-flex justify-content-between align-items-center">
@@ -49,14 +55,15 @@ const EnrollmentsPage = () => {
4955
iconAs={MoreVert}
5056
onClick={handleMoreButton}
5157
/>
52-
<Button variant="outline-primary">+ {intl.formatMessage(messages.addBetaTesters)}</Button>
58+
<Button variant="outline-primary" onClick={handleAddBetaTesters}>+ {intl.formatMessage(messages.addBetaTesters)}</Button>
5359
<Button onClick={handleEnrollLearners}>+ {intl.formatMessage(messages.enrollLearners)}</Button>
5460
</ActionRow>
5561
</div>
5662
<EnrollmentsList onUnenroll={handleUnenroll} />
5763
<EnrollmentStatusModal isOpen={isEnrollmentStatusModalOpen} onClose={handleCloseEnrollmentStatusModal} />
5864
<UnenrollModal isOpen={isUnenrollModalOpen} learner={selectedLearner} onClose={handleUnenrollModalClose} />
5965
<EnrollLearnersModal isOpen={isEnrollLearnersModalOpen} onClose={() => setIsEnrollLearnersModalOpen(false)} onSuccess={() => {}} />
66+
<AddBetaTestersModal isOpen={isAddBetaTestersModalOpen} onClose={() => setIsAddBetaTestersModalOpen(false)} onSuccess={() => {}} />
6067
</div>
6168
);
6269
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useParams } from 'react-router-dom';
2+
import { useAddBetaTesters } from '../data/apiHook';
3+
import AddModal from './AddModal';
4+
import { useIntl } from '@openedx/frontend-base';
5+
import messages from '../messages';
6+
7+
export interface AddBetaTestersModalProps {
8+
isOpen: boolean,
9+
onClose: () => void,
10+
onSuccess: () => void,
11+
}
12+
13+
const AddBetaTestersModal = ({ isOpen, onClose, onSuccess }: AddBetaTestersModalProps) => {
14+
const intl = useIntl();
15+
const { courseId = '' } = useParams<{ courseId: string }>();
16+
const { mutate: addBetaTesters } = useAddBetaTesters(courseId);
17+
18+
const handleEnroll = (emailList: string[]) => {
19+
addBetaTesters(emailList, {
20+
onSuccess: () => {
21+
onSuccess();
22+
onClose();
23+
},
24+
onError: (error) => {
25+
console.error(error);
26+
}
27+
});
28+
};
29+
return (
30+
<AddModal
31+
instructions={intl.formatMessage(messages.addBetaTestersInstructions)}
32+
isOpen={isOpen}
33+
title={intl.formatMessage(messages.addBetaTesters)}
34+
onClose={onClose}
35+
onSave={handleEnroll}
36+
/>
37+
);
38+
};
39+
40+
export default AddBetaTestersModal;

src/enrollments/data/api.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,13 @@ export const unenrollLearners = async (
4646
{ data: { users } }
4747
);
4848
};
49+
50+
export const addBetaTesters = async (
51+
courseId: string,
52+
users: string[]
53+
): Promise<void> => {
54+
await getAuthenticatedHttpClient().post(
55+
`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/beta-testers/`,
56+
{ users }
57+
);
58+
};

src/enrollments/data/apiHook.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2-
import { enrollLearners, getEnrollments, getEnrollmentStatus, PaginationParams } from './api';
2+
import { addBetaTesters, enrollLearners, getEnrollments, getEnrollmentStatus, PaginationParams } from './api';
33
import { enrollmentsQueryKeys } from './queryKeys';
44

55
export const useEnrollments = (courseId: string, pagination: PaginationParams) => (
@@ -26,3 +26,13 @@ export const useEnrollLearners = (courseId: string) => {
2626
},
2727
}));
2828
};
29+
30+
export const useAddBetaTesters = (courseId: string) => {
31+
const queryClient = useQueryClient();
32+
return (useMutation({
33+
mutationFn: (users: string[]) => addBetaTesters(courseId, users),
34+
onSuccess: () => {
35+
queryClient.invalidateQueries({ queryKey: enrollmentsQueryKeys.byCourse(courseId) });
36+
},
37+
}));
38+
};

src/enrollments/messages.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ const messages = defineMessages({
126126
defaultMessage: 'Notify Users by Email',
127127
description: 'Label for notify users by email checkbox in enroll learners modal',
128128
},
129+
addBetaTestersInstructions: {
130+
id: 'instruct.enrollments.modals.addBetaTesters.addBetaTestersInstructions',
131+
defaultMessage: 'Enter email addresses and/or usernames separated by new lines or commas. Note: Users must have an activated My Open edX account before they can be enrolled as beta testers.',
132+
description: 'Instructions for adding beta testers to the course',
133+
},
134+
uploadCSV: {
135+
id: 'instruct.enrollments.modals.uploadCSV',
136+
defaultMessage: 'Upload CSV',
137+
description: 'Title for upload CSV tab in add modal',
138+
},
129139
});
130140

131141
export default messages;

0 commit comments

Comments
 (0)