@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.2 → 1.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/dist/Main.d.ts +1 -1
  2. package/dist/Main.js +4 -13
  3. package/dist/Main.js.map +1 -1
  4. package/dist/app.js +2 -11
  5. package/dist/app.js.map +1 -1
  6. package/dist/certificates/CertificatesPage.d.ts +1 -0
  7. package/dist/certificates/CertificatesPage.js +162 -2
  8. package/dist/certificates/CertificatesPage.js.map +1 -1
  9. package/dist/certificates/CertificatesPage.scss +81 -0
  10. package/dist/certificates/components/CertificateTable.d.ts +14 -0
  11. package/dist/certificates/components/CertificateTable.js +85 -0
  12. package/dist/certificates/components/CertificateTable.js.map +1 -0
  13. package/dist/certificates/components/CertificatesPageHeader.d.ts +7 -0
  14. package/dist/certificates/components/CertificatesPageHeader.js +11 -0
  15. package/dist/certificates/components/CertificatesPageHeader.js.map +1 -0
  16. package/dist/certificates/components/CertificatesToolbar.d.ts +10 -0
  17. package/dist/certificates/components/CertificatesToolbar.js +12 -0
  18. package/dist/certificates/components/CertificatesToolbar.js.map +1 -0
  19. package/dist/certificates/components/DisableCertificatesModal.d.ts +9 -0
  20. package/dist/certificates/components/DisableCertificatesModal.js +16 -0
  21. package/dist/certificates/components/DisableCertificatesModal.js.map +1 -0
  22. package/dist/certificates/components/FilterDropdown.d.ts +8 -0
  23. package/dist/certificates/components/FilterDropdown.js +50 -0
  24. package/dist/certificates/components/FilterDropdown.js.map +1 -0
  25. package/dist/certificates/components/GenerationHistoryTable.d.ts +11 -0
  26. package/dist/certificates/components/GenerationHistoryTable.js +40 -0
  27. package/dist/certificates/components/GenerationHistoryTable.js.map +1 -0
  28. package/dist/certificates/components/GrantExceptionsModal.d.ts +8 -0
  29. package/dist/certificates/components/GrantExceptionsModal.js +10 -0
  30. package/dist/certificates/components/GrantExceptionsModal.js.map +1 -0
  31. package/dist/certificates/components/InvalidateCertificateModal.d.ts +8 -0
  32. package/dist/certificates/components/InvalidateCertificateModal.js +10 -0
  33. package/dist/certificates/components/InvalidateCertificateModal.js.map +1 -0
  34. package/dist/certificates/components/IssuedCertificatesTab.d.ts +18 -0
  35. package/dist/certificates/components/IssuedCertificatesTab.js +6 -0
  36. package/dist/certificates/components/IssuedCertificatesTab.js.map +1 -0
  37. package/dist/certificates/components/LearnerActionModal.d.ts +16 -0
  38. package/dist/certificates/components/LearnerActionModal.js +22 -0
  39. package/dist/certificates/components/LearnerActionModal.js.map +1 -0
  40. package/dist/certificates/components/RemoveInvalidationModal.d.ts +9 -0
  41. package/dist/certificates/components/RemoveInvalidationModal.js +10 -0
  42. package/dist/certificates/components/RemoveInvalidationModal.js.map +1 -0
  43. package/dist/certificates/constants.d.ts +15 -0
  44. package/dist/certificates/constants.js +16 -0
  45. package/dist/certificates/constants.js.map +1 -0
  46. package/dist/certificates/data/api.d.ts +9 -0
  47. package/dist/certificates/data/api.js +63 -0
  48. package/dist/certificates/data/api.js.map +1 -0
  49. package/dist/certificates/data/apiHook.d.ts +30 -0
  50. package/dist/certificates/data/apiHook.js +90 -0
  51. package/dist/certificates/data/apiHook.js.map +1 -0
  52. package/dist/certificates/data/dummyData.d.ts +2 -0
  53. package/dist/certificates/data/dummyData.js +234 -0
  54. package/dist/certificates/data/dummyData.js.map +1 -0
  55. package/dist/certificates/data/queryKeys.d.ts +8 -0
  56. package/dist/certificates/data/queryKeys.js +8 -0
  57. package/dist/certificates/data/queryKeys.js.map +1 -0
  58. package/dist/certificates/messages.d.ts +313 -0
  59. package/dist/certificates/messages.js +315 -0
  60. package/dist/certificates/messages.js.map +1 -0
  61. package/dist/certificates/types.d.ts +61 -0
  62. package/dist/certificates/types.js +26 -0
  63. package/dist/certificates/types.js.map +1 -0
  64. package/dist/certificates/utils/errorHandling.d.ts +10 -0
  65. package/dist/certificates/utils/errorHandling.js +3 -0
  66. package/dist/certificates/utils/errorHandling.js.map +1 -0
  67. package/dist/certificates/utils/filterUtils.d.ts +4 -0
  68. package/dist/certificates/utils/filterUtils.js +31 -0
  69. package/dist/certificates/utils/filterUtils.js.map +1 -0
  70. package/dist/certificates/utils/index.d.ts +2 -0
  71. package/dist/certificates/utils/index.js +2 -0
  72. package/dist/certificates/utils/index.js.map +1 -0
  73. package/dist/cohorts/data/queryKeys.d.ts +4 -4
  74. package/dist/components/ActionCard.d.ts +2 -2
  75. package/dist/components/ActionCard.js +1 -1
  76. package/dist/components/ActionCard.js.map +1 -1
  77. package/dist/components/PendingTasks.d.ts +3 -1
  78. package/dist/components/PendingTasks.js +3 -2
  79. package/dist/components/PendingTasks.js.map +1 -1
  80. package/dist/components/SpecifyLearnerField.d.ts +4 -1
  81. package/dist/components/SpecifyLearnerField.js +24 -10
  82. package/dist/components/SpecifyLearnerField.js.map +1 -1
  83. package/dist/components/SpecifyProblemField.d.ts +13 -0
  84. package/dist/components/SpecifyProblemField.js +46 -0
  85. package/dist/components/SpecifyProblemField.js.map +1 -0
  86. package/dist/components/UsernameFilter.d.ts +7 -0
  87. package/dist/components/UsernameFilter.js +19 -0
  88. package/dist/components/UsernameFilter.js.map +1 -0
  89. package/dist/components/messages.d.ts +30 -0
  90. package/dist/components/messages.js +30 -0
  91. package/dist/components/messages.js.map +1 -1
  92. package/dist/constants.d.ts +2 -1
  93. package/dist/constants.js +2 -1
  94. package/dist/constants.js.map +1 -1
  95. package/dist/courseInfo/types.d.ts +2 -0
  96. package/dist/courseInfo/types.js.map +1 -1
  97. package/dist/courseTeam/CourseTeamPage.js +20 -2
  98. package/dist/courseTeam/CourseTeamPage.js.map +1 -1
  99. package/dist/courseTeam/components/AddTeamMemberModal.d.ts +6 -0
  100. package/dist/courseTeam/components/AddTeamMemberModal.js +60 -0
  101. package/dist/courseTeam/components/AddTeamMemberModal.js.map +1 -0
  102. package/dist/courseTeam/components/EditTeamMemberModal.d.ts +8 -0
  103. package/dist/courseTeam/components/EditTeamMemberModal.js +90 -0
  104. package/dist/courseTeam/components/EditTeamMemberModal.js.map +1 -0
  105. package/dist/courseTeam/components/MembersContent.d.ts +6 -0
  106. package/dist/courseTeam/components/MembersContent.js +48 -0
  107. package/dist/courseTeam/components/MembersContent.js.map +1 -0
  108. package/dist/courseTeam/components/RoleFilter.d.ts +7 -0
  109. package/dist/courseTeam/components/RoleFilter.js +22 -0
  110. package/dist/courseTeam/components/RoleFilter.js.map +1 -0
  111. package/dist/courseTeam/components/RolesContent.d.ts +3 -0
  112. package/dist/courseTeam/components/RolesContent.js +25 -0
  113. package/dist/courseTeam/components/RolesContent.js.map +1 -0
  114. package/dist/courseTeam/data/api.d.ts +6 -0
  115. package/dist/courseTeam/data/api.js +38 -0
  116. package/dist/courseTeam/data/api.js.map +1 -0
  117. package/dist/courseTeam/data/apiHook.d.ts +11 -0
  118. package/dist/courseTeam/data/apiHook.js +32 -0
  119. package/dist/courseTeam/data/apiHook.js.map +1 -0
  120. package/dist/courseTeam/data/queryKeys.d.ts +7 -0
  121. package/dist/courseTeam/data/queryKeys.js +14 -0
  122. package/dist/courseTeam/data/queryKeys.js.map +1 -0
  123. package/dist/courseTeam/messages.d.ts +243 -0
  124. package/dist/courseTeam/messages.js +245 -0
  125. package/dist/courseTeam/messages.js.map +1 -0
  126. package/dist/courseTeam/types.d.ts +22 -0
  127. package/dist/courseTeam/types.js +3 -0
  128. package/dist/courseTeam/types.js.map +1 -0
  129. package/dist/data/api.d.ts +2 -1
  130. package/dist/data/api.js +9 -3
  131. package/dist/data/api.js.map +1 -1
  132. package/dist/data/apiHook.d.ts +1 -0
  133. package/dist/data/apiHook.js +10 -2
  134. package/dist/data/apiHook.js.map +1 -1
  135. package/dist/data/queryKeys.d.ts +10 -6
  136. package/dist/data/queryKeys.js +4 -0
  137. package/dist/data/queryKeys.js.map +1 -1
  138. package/dist/dataDownloads/data/queryKeys.d.ts +3 -3
  139. package/dist/dateExtensions/components/AddExtensionModal.d.ts +1 -1
  140. package/dist/dateExtensions/components/AddExtensionModal.js +5 -6
  141. package/dist/dateExtensions/components/AddExtensionModal.js.map +1 -1
  142. package/dist/dateExtensions/components/DateExtensionsList.js +2 -13
  143. package/dist/dateExtensions/components/DateExtensionsList.js.map +1 -1
  144. package/dist/dateExtensions/data/apiHook.d.ts +2 -2
  145. package/dist/dateExtensions/data/apiHook.js +4 -4
  146. package/dist/dateExtensions/data/apiHook.js.map +1 -1
  147. package/dist/dateExtensions/data/queryKeys.d.ts +5 -5
  148. package/dist/dateExtensions/messages.d.ts +0 -5
  149. package/dist/dateExtensions/messages.js +1 -6
  150. package/dist/dateExtensions/messages.js.map +1 -1
  151. package/dist/enrollments/EnrollmentsPage.js +41 -7
  152. package/dist/enrollments/EnrollmentsPage.js.map +1 -1
  153. package/dist/enrollments/components/AddBetaTestersModal.d.ts +6 -0
  154. package/dist/enrollments/components/AddBetaTestersModal.js +61 -0
  155. package/dist/enrollments/components/AddBetaTestersModal.js.map +1 -0
  156. package/dist/enrollments/components/EnrollLearnersModal.d.ts +6 -0
  157. package/dist/enrollments/components/EnrollLearnersModal.js +53 -0
  158. package/dist/enrollments/components/EnrollLearnersModal.js.map +1 -0
  159. package/dist/enrollments/components/EnrollmentStatusModal.js +3 -3
  160. package/dist/enrollments/components/EnrollmentStatusModal.js.map +1 -1
  161. package/dist/enrollments/components/EnrollmentsList.d.ts +3 -2
  162. package/dist/enrollments/components/EnrollmentsList.js +13 -14
  163. package/dist/enrollments/components/EnrollmentsList.js.map +1 -1
  164. package/dist/enrollments/components/UnenrollModal.d.ts +1 -1
  165. package/dist/enrollments/components/UnenrollModal.js +29 -3
  166. package/dist/enrollments/components/UnenrollModal.js.map +1 -1
  167. package/dist/enrollments/components/UpdateBetaTesterModal.d.ts +8 -0
  168. package/dist/enrollments/components/UpdateBetaTesterModal.js +52 -0
  169. package/dist/enrollments/components/UpdateBetaTesterModal.js.map +1 -0
  170. package/dist/enrollments/data/api.d.ts +3 -1
  171. package/dist/enrollments/data/api.js +11 -1
  172. package/dist/enrollments/data/api.js.map +1 -1
  173. package/dist/enrollments/data/apiHook.d.ts +5 -3
  174. package/dist/enrollments/data/apiHook.js +21 -3
  175. package/dist/enrollments/data/apiHook.js.map +1 -1
  176. package/dist/enrollments/data/queryKeys.d.ts +5 -5
  177. package/dist/enrollments/data/queryKeys.js.map +1 -1
  178. package/dist/enrollments/messages.d.ts +121 -1
  179. package/dist/enrollments/messages.js +126 -6
  180. package/dist/enrollments/messages.js.map +1 -1
  181. package/dist/enrollments/types.d.ts +24 -0
  182. package/dist/enrollments/types.js.map +1 -1
  183. package/dist/grading/GradingPage.js +15 -2
  184. package/dist/grading/GradingPage.js.map +1 -1
  185. package/dist/grading/components/GradingActionRow.d.ts +2 -0
  186. package/dist/grading/components/GradingActionRow.js +28 -0
  187. package/dist/grading/components/GradingActionRow.js.map +1 -0
  188. package/dist/grading/components/GradingConfigurationModal.d.ts +6 -0
  189. package/dist/grading/components/GradingConfigurationModal.js +14 -0
  190. package/dist/grading/components/GradingConfigurationModal.js.map +1 -0
  191. package/dist/grading/components/GradingLearnerContent.d.ts +7 -0
  192. package/dist/grading/components/GradingLearnerContent.js +114 -0
  193. package/dist/grading/components/GradingLearnerContent.js.map +1 -0
  194. package/dist/grading/data/api.d.ts +6 -0
  195. package/dist/grading/data/api.js +59 -0
  196. package/dist/grading/data/api.js.map +1 -0
  197. package/dist/grading/data/apiHook.d.ts +6 -0
  198. package/dist/grading/data/apiHook.js +29 -0
  199. package/dist/grading/data/apiHook.js.map +1 -0
  200. package/dist/grading/data/queryKeys.d.ts +9 -0
  201. package/dist/grading/data/queryKeys.js +8 -0
  202. package/dist/grading/data/queryKeys.js.map +1 -0
  203. package/dist/grading/messages.d.ts +173 -0
  204. package/dist/grading/messages.js +175 -0
  205. package/dist/grading/messages.js.map +1 -0
  206. package/dist/grading/types.d.ts +11 -0
  207. package/dist/grading/types.js +2 -0
  208. package/dist/grading/types.js.map +1 -0
  209. package/dist/hooks/useDebouncedFilter.d.ts +1 -0
  210. package/dist/hooks/useDebouncedFilter.js +5 -0
  211. package/dist/hooks/useDebouncedFilter.js.map +1 -1
  212. package/dist/index.d.ts +2 -3
  213. package/dist/index.js +2 -3
  214. package/dist/index.js.map +1 -1
  215. package/dist/instructorNav/InstructorNav.js +1 -1
  216. package/dist/instructorNav/InstructorNav.js.map +1 -1
  217. package/dist/provides.d.ts +4 -0
  218. package/dist/provides.js +7 -0
  219. package/dist/provides.js.map +1 -0
  220. package/dist/routes.d.ts +1 -1
  221. package/dist/routes.js +5 -4
  222. package/dist/routes.js.map +1 -1
  223. package/dist/specialExams/SpecialExamsPage.js +10 -2
  224. package/dist/specialExams/SpecialExamsPage.js.map +1 -1
  225. package/dist/specialExams/components/Allowances.d.ts +2 -0
  226. package/dist/specialExams/components/Allowances.js +6 -0
  227. package/dist/specialExams/components/Allowances.js.map +1 -0
  228. package/dist/specialExams/components/AttemptsList.d.ts +3 -0
  229. package/dist/specialExams/components/AttemptsList.js +44 -0
  230. package/dist/specialExams/components/AttemptsList.js.map +1 -0
  231. package/dist/specialExams/data/api.d.ts +3 -0
  232. package/dist/specialExams/data/api.js +23 -0
  233. package/dist/specialExams/data/api.js.map +1 -0
  234. package/dist/specialExams/data/apiHook.d.ts +2 -0
  235. package/dist/specialExams/data/apiHook.js +9 -0
  236. package/dist/specialExams/data/apiHook.js.map +1 -0
  237. package/dist/specialExams/data/queryKeys.d.ts +5 -0
  238. package/dist/specialExams/data/queryKeys.js +6 -0
  239. package/dist/specialExams/data/queryKeys.js.map +1 -0
  240. package/dist/specialExams/messages.d.ts +58 -0
  241. package/dist/specialExams/messages.js +60 -0
  242. package/dist/specialExams/messages.js.map +1 -0
  243. package/dist/specialExams/types.d.ts +13 -0
  244. package/dist/specialExams/types.js +2 -0
  245. package/dist/specialExams/types.js.map +1 -0
  246. package/dist/style.scss +16 -0
  247. package/dist/testUtils.js +1 -1
  248. package/dist/testUtils.js.map +1 -1
  249. package/dist/types/index.d.ts +1 -0
  250. package/dist/types/index.js.map +1 -1
  251. package/dist/utils/formatters.d.ts +5 -0
  252. package/dist/utils/formatters.js +10 -0
  253. package/dist/utils/formatters.js.map +1 -1
  254. package/package.json +2 -5
  255. package/dist/app.scss +0 -10
  256. package/dist/providers/QueryProvider.d.ts +0 -6
  257. package/dist/providers/QueryProvider.js +0 -16
  258. package/dist/providers/QueryProvider.js.map +0 -1
  259. package/dist/providers.d.ts +0 -3
  260. package/dist/providers.js +0 -8
  261. package/dist/providers.js.map +0 -1
@@ -0,0 +1,53 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useParams } from 'react-router-dom';
4
+ import { isAxiosError } from 'axios';
5
+ import { useIntl } from '@openedx/frontend-base';
6
+ import { Button, FormControl, ModalDialog, Form } from '@openedx/paragon';
7
+ import { useUpdateEnrollments } from '../../enrollments/data/apiHook';
8
+ import messages from '../../enrollments/messages';
9
+ import { useAlert } from '../../providers/AlertProvider';
10
+ const EnrollLearnersModal = ({ isOpen, onClose }) => {
11
+ const intl = useIntl();
12
+ const { courseId = '' } = useParams();
13
+ const [emails, setEmails] = useState('');
14
+ const [autoEnroll, setAutoEnroll] = useState(true);
15
+ const [emailStudents, setEmailStudents] = useState(true);
16
+ const { mutate: enrollLearners } = useUpdateEnrollments(courseId);
17
+ const { showModal, addAlert } = useAlert();
18
+ const handleSave = () => {
19
+ const identifier = emails.split(',').map(email => email.trim()).filter(email => email);
20
+ enrollLearners({ identifier, action: 'enroll', autoEnroll, emailStudents }, {
21
+ onSuccess: (data) => {
22
+ var _a;
23
+ const failedUsernames = ((_a = data.results) === null || _a === void 0 ? void 0 : _a.filter(user => user.invalidIdentifier).map(user => user.identifier)) || [];
24
+ if (failedUsernames.length > 0) {
25
+ addAlert({
26
+ type: 'danger',
27
+ message: intl.formatMessage(messages.failedEnrollLearners),
28
+ extraContent: (failedUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.unknownLearner, { learner })] }, learner))))
29
+ });
30
+ }
31
+ setEmails('');
32
+ setAutoEnroll(true);
33
+ setEmailStudents(true);
34
+ onClose();
35
+ },
36
+ onError: (error) => {
37
+ var _a;
38
+ const notFound = isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404;
39
+ const errorMessage = notFound
40
+ ? intl.formatMessage(messages.enrollLearnerNotFoundError)
41
+ : intl.formatMessage(messages.enrollLearnerError);
42
+ showModal({
43
+ message: errorMessage,
44
+ variant: 'danger',
45
+ confirmText: intl.formatMessage(messages.closeButton),
46
+ });
47
+ }
48
+ });
49
+ };
50
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, isOverflowVisible: false, title: intl.formatMessage(messages.enrollLearners), children: [_jsx(ModalDialog.Header, { className: "border-light-700 border-bottom", children: _jsx("h3", { className: "text-primary-500", children: intl.formatMessage(messages.enrollLearners) }) }), _jsx("div", { className: "position-relative overflow-auto", children: _jsxs(ModalDialog.Body, { className: "py-4", children: [_jsx("p", { className: "text-gray-700 x-small mb-2", children: intl.formatMessage(messages.addLearnerInstructions) }), _jsx(FormControl, { name: "identifier", as: "textarea", rows: 4, placeholder: intl.formatMessage(messages.userIdentifierPlaceholder), onChange: (e) => setEmails(e.target.value) }), _jsxs("div", { className: "d-flex mt-3 text-primary-500", children: [_jsx(Form.Checkbox, { controlClassName: "border-primary-500", checked: autoEnroll, onChange: (e) => setAutoEnroll(e.target.checked), children: intl.formatMessage(messages.autoEnrollCheckbox) }), _jsx(Form.Checkbox, { controlClassName: "border-primary-500", className: "ml-4", checked: emailStudents, onChange: (e) => setEmailStudents(e.target.checked), children: intl.formatMessage(messages.notifyUsersCheckbox) })] })] }) }), _jsxs(ModalDialog.Footer, { className: "border-light-700 border-top", children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancelButton) }), _jsx(Button, { className: "ml-2", variant: "primary", onClick: handleSave, disabled: emails.trim().length === 0, children: intl.formatMessage(messages.saveButton) })] })] }));
51
+ };
52
+ export default EnrollLearnersModal;
53
+ //# sourceMappingURL=EnrollLearnersModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnrollLearnersModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/EnrollLearnersModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { isAxiosError } from 'axios';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, FormControl, ModalDialog, Form } from '@openedx/paragon';\nimport { useUpdateEnrollments } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\nimport { useAlert } from '@src/providers/AlertProvider';\n\nexport interface EnrollLearnersModalProps {\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst EnrollLearnersModal = ({\n isOpen,\n onClose\n}: EnrollLearnersModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [emails, setEmails] = useState('');\n const [autoEnroll, setAutoEnroll] = useState(true);\n const [emailStudents, setEmailStudents] = useState(true);\n const { mutate: enrollLearners } = useUpdateEnrollments(courseId);\n const { showModal, addAlert } = useAlert();\n\n const handleSave = () => {\n const identifier = emails.split(',').map(email => email.trim()).filter(email => email);\n enrollLearners({ identifier, action: 'enroll', autoEnroll, emailStudents }, {\n onSuccess: (data) => {\n const failedUsernames = data.results?.filter(user => user.invalidIdentifier).map(user => user.identifier) || [];\n if (failedUsernames.length > 0) {\n addAlert({\n type: 'danger',\n message: intl.formatMessage(messages.failedEnrollLearners),\n extraContent: (\n failedUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.unknownLearner, { learner })}</p>\n ))\n )\n });\n }\n setEmails('');\n setAutoEnroll(true);\n setEmailStudents(true);\n onClose();\n },\n onError: (error) => {\n const notFound = isAxiosError(error) && error.response?.status === 404;\n const errorMessage = notFound\n ? intl.formatMessage(messages.enrollLearnerNotFoundError)\n : intl.formatMessage(messages.enrollLearnerError);\n showModal({\n message: errorMessage,\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n };\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} isOverflowVisible={false} title={intl.formatMessage(messages.enrollLearners)}>\n <ModalDialog.Header className=\"border-light-700 border-bottom\">\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.enrollLearners)}</h3>\n </ModalDialog.Header>\n <div className=\"position-relative overflow-auto\">\n <ModalDialog.Body className=\"py-4\">\n <p className=\"text-gray-700 x-small mb-2\">{intl.formatMessage(messages.addLearnerInstructions)}</p>\n <FormControl\n name=\"identifier\"\n as=\"textarea\"\n rows={4}\n placeholder={intl.formatMessage(messages.userIdentifierPlaceholder)}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setEmails(e.target.value)}\n />\n <div className=\"d-flex mt-3 text-primary-500\">\n <Form.Checkbox\n controlClassName=\"border-primary-500\"\n checked={autoEnroll}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setAutoEnroll(e.target.checked)}\n >{intl.formatMessage(messages.autoEnrollCheckbox)}\n </Form.Checkbox>\n <Form.Checkbox\n controlClassName=\"border-primary-500\"\n className=\"ml-4\"\n checked={emailStudents}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmailStudents(e.target.checked)}\n >{intl.formatMessage(messages.notifyUsersCheckbox)}\n </Form.Checkbox>\n </div>\n </ModalDialog.Body>\n </div>\n <ModalDialog.Footer className=\"border-light-700 border-top\">\n <Button variant=\"tertiary\" onClick={onClose}>\n {intl.formatMessage(messages.cancelButton)}\n </Button>\n <Button className=\"ml-2\" variant=\"primary\" onClick={handleSave} disabled={emails.trim().length === 0}>\n {intl.formatMessage(messages.saveButton)}\n </Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EnrollLearnersModal;\n"]}
@@ -3,8 +3,8 @@ import { useState } from 'react';
3
3
  import { useParams } from 'react-router-dom';
4
4
  import { useIntl } from '@openedx/frontend-base';
5
5
  import { Button, FormControl, ModalDialog } from '@openedx/paragon';
6
- import { useEnrollmentByUserId } from '../data/apiHook';
7
- import messages from '../messages';
6
+ import { useEnrollmentByUserId } from '../../enrollments/data/apiHook';
7
+ import messages from '../../enrollments/messages';
8
8
  const EnrollmentStatusModal = ({ isOpen, onClose }) => {
9
9
  const intl = useIntl();
10
10
  const { courseId = '' } = useParams();
@@ -17,7 +17,7 @@ const EnrollmentStatusModal = ({ isOpen, onClose }) => {
17
17
  setLearnerIdentifier('');
18
18
  onClose();
19
19
  };
20
- return (_jsxs(ModalDialog, { title: intl.formatMessage(messages.checkEnrollmentStatus), isOpen: isOpen, onClose: handleClose, isOverflowVisible: false, children: [_jsx(ModalDialog.Header, { children: _jsx(ModalDialog.Title, { className: "text-primary-700", children: intl.formatMessage(messages.checkEnrollmentStatus) }) }), _jsx(ModalDialog.Body, { className: "border-bottom border-top border-light-700", children: _jsxs("div", { className: "my-2", children: [_jsx("p", { children: intl.formatMessage(messages.addLearnerInstructions) }), _jsx(FormControl, { placeholder: intl.formatMessage(messages.enrollLearnersPlaceholder), value: learnerIdentifier, onChange: (e) => setLearnerIdentifier(e.target.value) }), _jsx(Button, { className: "mt-3", onClick: handleSearch, disabled: !learnerIdentifier.trim(), children: intl.formatMessage(messages.checkEnrollmentStatus) }), data.enrollmentStatus && (_jsx("p", { className: "mt-3 mb-0", children: data.enrollmentStatus }))] }) }), _jsx(ModalDialog.Footer, { children: _jsx(Button, { onClick: handleClose, children: intl.formatMessage(messages.closeButton) }) })] }));
20
+ return (_jsxs(ModalDialog, { title: intl.formatMessage(messages.checkEnrollmentStatus), isOpen: isOpen, onClose: handleClose, isOverflowVisible: false, children: [_jsx(ModalDialog.Header, { children: _jsx(ModalDialog.Title, { className: "text-primary-700", children: intl.formatMessage(messages.checkEnrollmentStatus) }) }), _jsx(ModalDialog.Body, { className: "border-bottom border-top border-light-700", children: _jsxs("div", { className: "my-2", children: [_jsx("p", { children: intl.formatMessage(messages.addLearnerInstructions) }), _jsx(FormControl, { placeholder: intl.formatMessage(messages.enrollmentStatusPlaceholder), value: learnerIdentifier, onChange: (e) => setLearnerIdentifier(e.target.value) }), _jsx(Button, { className: "mt-3", onClick: handleSearch, disabled: !learnerIdentifier.trim(), children: intl.formatMessage(messages.checkEnrollmentStatus) }), data.enrollmentStatus && (_jsx("p", { className: "mt-3 mb-0", children: data.enrollmentStatus }))] }) }), _jsx(ModalDialog.Footer, { children: _jsx(Button, { onClick: handleClose, children: intl.formatMessage(messages.closeButton) }) })] }));
21
21
  };
22
22
  export default EnrollmentStatusModal;
23
23
  //# sourceMappingURL=EnrollmentStatusModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EnrollmentStatusModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/EnrollmentStatusModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAe,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,QAAQ,MAAM,aAAa,CAAC;AAOnC,MAAM,qBAAqB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAA8B,EAAE,EAAE;IAChF,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IACvE,MAAM,EAAE,IAAI,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAExG,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,WAAW,IAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,aACpI,KAAC,WAAW,CAAC,MAAM,cACjB,KAAC,WAAW,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAqB,GACrG,EACrB,KAAC,WAAW,CAAC,IAAI,IAAC,SAAS,EAAC,2CAA2C,YACrE,eAAK,SAAS,EAAC,MAAM,aACnB,sBAAI,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,GAAK,EAC5D,KAAC,WAAW,IACV,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EACnE,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,CAAC,CAAgC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GACpF,EACF,KAAC,MAAM,IACL,SAAS,EAAC,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,YAElC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAC5C,EAER,IAAI,CAAC,gBAAgB,IAAI,CACxB,YAAG,SAAS,EAAC,WAAW,YAAE,IAAI,CAAC,gBAAgB,GAAK,CACrD,IACG,GACW,EACnB,KAAC,WAAW,CAAC,MAAM,cACjB,KAAC,MAAM,IAAC,OAAO,EAAE,WAAW,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAU,GAC9D,IACT,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,qBAAqB,CAAC","sourcesContent":["import { useState, ChangeEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, FormControl, ModalDialog } from '@openedx/paragon';\nimport { useEnrollmentByUserId } from '../data/apiHook';\nimport messages from '../messages';\n\ninterface EnrollmentStatusModalProps {\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst EnrollmentStatusModal = ({ isOpen, onClose }: EnrollmentStatusModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [learnerIdentifier, setLearnerIdentifier] = useState<string>('');\n const { data = { enrollmentStatus: '' }, refetch } = useEnrollmentByUserId(courseId, learnerIdentifier);\n\n const handleSearch = () => {\n refetch();\n };\n\n const handleClose = () => {\n setLearnerIdentifier('');\n onClose();\n };\n\n return (\n <ModalDialog title={intl.formatMessage(messages.checkEnrollmentStatus)} isOpen={isOpen} onClose={handleClose} isOverflowVisible={false}>\n <ModalDialog.Header>\n <ModalDialog.Title className=\"text-primary-700\">{intl.formatMessage(messages.checkEnrollmentStatus)}</ModalDialog.Title>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"border-bottom border-top border-light-700\">\n <div className=\"my-2\">\n <p>{intl.formatMessage(messages.addLearnerInstructions)}</p>\n <FormControl\n placeholder={intl.formatMessage(messages.enrollLearnersPlaceholder)}\n value={learnerIdentifier}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setLearnerIdentifier(e.target.value)}\n />\n <Button\n className=\"mt-3\"\n onClick={handleSearch}\n disabled={!learnerIdentifier.trim()}\n >\n {intl.formatMessage(messages.checkEnrollmentStatus)}\n </Button>\n\n {data.enrollmentStatus && (\n <p className=\"mt-3 mb-0\">{data.enrollmentStatus}</p>\n )}\n </div>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button onClick={handleClose}>{intl.formatMessage(messages.closeButton)}</Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EnrollmentStatusModal;\n"]}
1
+ {"version":3,"file":"EnrollmentStatusModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/EnrollmentStatusModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAe,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AAOjD,MAAM,qBAAqB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAA8B,EAAE,EAAE;IAChF,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAC;IACvE,MAAM,EAAE,IAAI,GAAG,EAAE,gBAAgB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAExG,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,oBAAoB,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,WAAW,IAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,aACpI,KAAC,WAAW,CAAC,MAAM,cACjB,KAAC,WAAW,CAAC,KAAK,IAAC,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAqB,GACrG,EACrB,KAAC,WAAW,CAAC,IAAI,IAAC,SAAS,EAAC,2CAA2C,YACrE,eAAK,SAAS,EAAC,MAAM,aACnB,sBAAI,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,GAAK,EAC5D,KAAC,WAAW,IACV,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,2BAA2B,CAAC,EACrE,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,CAAC,CAAgC,EAAE,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GACpF,EACF,KAAC,MAAM,IACL,SAAS,EAAC,MAAM,EAChB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,YAElC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAC5C,EAER,IAAI,CAAC,gBAAgB,IAAI,CACxB,YAAG,SAAS,EAAC,WAAW,YAAE,IAAI,CAAC,gBAAgB,GAAK,CACrD,IACG,GACW,EACnB,KAAC,WAAW,CAAC,MAAM,cACjB,KAAC,MAAM,IAAC,OAAO,EAAE,WAAW,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAU,GAC9D,IACT,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,qBAAqB,CAAC","sourcesContent":["import { useState, ChangeEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, FormControl, ModalDialog } from '@openedx/paragon';\nimport { useEnrollmentByUserId } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\n\ninterface EnrollmentStatusModalProps {\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst EnrollmentStatusModal = ({ isOpen, onClose }: EnrollmentStatusModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [learnerIdentifier, setLearnerIdentifier] = useState<string>('');\n const { data = { enrollmentStatus: '' }, refetch } = useEnrollmentByUserId(courseId, learnerIdentifier);\n\n const handleSearch = () => {\n refetch();\n };\n\n const handleClose = () => {\n setLearnerIdentifier('');\n onClose();\n };\n\n return (\n <ModalDialog title={intl.formatMessage(messages.checkEnrollmentStatus)} isOpen={isOpen} onClose={handleClose} isOverflowVisible={false}>\n <ModalDialog.Header>\n <ModalDialog.Title className=\"text-primary-700\">{intl.formatMessage(messages.checkEnrollmentStatus)}</ModalDialog.Title>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"border-bottom border-top border-light-700\">\n <div className=\"my-2\">\n <p>{intl.formatMessage(messages.addLearnerInstructions)}</p>\n <FormControl\n placeholder={intl.formatMessage(messages.enrollmentStatusPlaceholder)}\n value={learnerIdentifier}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setLearnerIdentifier(e.target.value)}\n />\n <Button\n className=\"mt-3\"\n onClick={handleSearch}\n disabled={!learnerIdentifier.trim()}\n >\n {intl.formatMessage(messages.checkEnrollmentStatus)}\n </Button>\n\n {data.enrollmentStatus && (\n <p className=\"mt-3 mb-0\">{data.enrollmentStatus}</p>\n )}\n </div>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button onClick={handleClose}>{intl.formatMessage(messages.closeButton)}</Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EnrollmentStatusModal;\n"]}
@@ -1,6 +1,7 @@
1
- import { EnrolledLearner } from '../types';
1
+ import { EnrolledLearner } from '../../enrollments/types';
2
2
  interface EnrollmentsListProps {
3
3
  onUnenroll: (learner: EnrolledLearner) => void;
4
+ onBetaTesterChange: (learner: EnrolledLearner) => void;
4
5
  }
5
- declare const EnrollmentsList: ({ onUnenroll }: EnrollmentsListProps) => import("react/jsx-runtime").JSX.Element;
6
+ declare const EnrollmentsList: ({ onUnenroll, onBetaTesterChange }: EnrollmentsListProps) => import("react/jsx-runtime").JSX.Element;
6
7
  export default EnrollmentsList;
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useState } from 'react';
3
3
  import { useParams } from 'react-router-dom';
4
- import { ActionRow, Button, DataTable, FormControl, Icon, IconButton } from '@openedx/paragon';
5
4
  import { useIntl } from '@openedx/frontend-base';
6
- import { MoreVert, Search } from '@openedx/paragon/icons';
7
- import messages from '../messages';
8
- import { useEnrollments } from '../data/apiHook';
5
+ import { ActionRow, Button, DataTable, FormControl, Icon, IconButton, OverlayTrigger, Popover } from '@openedx/paragon';
6
+ import { FilterList, MoreVert, Search } from '@openedx/paragon/icons';
7
+ import messages from '../../enrollments/messages';
8
+ import { useEnrollments } from '../../enrollments/data/apiHook';
9
9
  import { useDebouncedFilter } from '../../hooks/useDebouncedFilter';
10
10
  const ENROLLMENTS_PAGE_SIZE = 25;
11
11
  const betaTesterOptions = [
@@ -29,9 +29,9 @@ const BetaTesterFilter = ({ column: { filterValue, setFilter } }) => {
29
29
  const handleSelectChange = (e) => {
30
30
  setFilter(e.target.value);
31
31
  };
32
- return (_jsx(FormControl, { as: "select", className: "mb-0", name: "isBetaTester", size: "md", value: filterValue, onChange: handleSelectChange, children: betaTesterOptions.map((option) => (_jsx("option", { value: option.value, children: intl.formatMessage(option.label) }, option.value))) }));
32
+ return (_jsx(FormControl, { as: "select", className: "mb-0", name: "isBetaTester", size: "md", value: filterValue, onChange: handleSelectChange, leadingElement: _jsx(Icon, { src: FilterList }), children: betaTesterOptions.map((option) => (_jsx("option", { value: option.value, children: intl.formatMessage(option.label) }, option.value))) }));
33
33
  };
34
- const EnrollmentsList = ({ onUnenroll }) => {
34
+ const EnrollmentsList = ({ onUnenroll, onBetaTesterChange }) => {
35
35
  const intl = useIntl();
36
36
  const { courseId = '' } = useParams();
37
37
  const [filters, setFilters] = useState({ page: 0, username: '', isBetaTester: '' });
@@ -56,10 +56,6 @@ const EnrollmentsList = ({ onUnenroll }) => {
56
56
  setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { page: data.pageIndex })));
57
57
  }
58
58
  };
59
- const handleMoreButton = () => {
60
- // Handle more button click
61
- console.log('More button clicked');
62
- };
63
59
  const tableColumns = [
64
60
  { accessor: 'username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter },
65
61
  { accessor: 'fullName', Header: intl.formatMessage(messages.fullName), disableFilters: true },
@@ -77,14 +73,17 @@ const EnrollmentsList = ({ onUnenroll }) => {
77
73
  Filter: BetaTesterFilter
78
74
  },
79
75
  ];
80
- const actionCustomCell = useCallback(({ row: { original } }) => {
81
- return (_jsxs(ActionRow, { className: "justify-content-start", children: [_jsx(Button, { className: "pl-0", onClick: () => onUnenroll(original), variant: "link", children: intl.formatMessage(messages.unenrollButton) }), _jsx(IconButton, { alt: intl.formatMessage(messages.changeBetaTesterStatus), className: "lead", iconAs: MoreVert, onClick: handleMoreButton })] }));
82
- }, [onUnenroll, intl]);
76
+ const ActionCustomCell = useCallback(({ row: { original } }) => {
77
+ const popoverContent = (_jsx(Popover, { id: `popover-${original.username}`, className: "border-0 shadow-sm", children: _jsx(Popover.Content, { className: "p-0 border-0", children: _jsx("div", { className: "dropdown-menu show position-static border shadow-sm", children: _jsx("button", { type: "button", className: "dropdown-item", onClick: () => onBetaTesterChange(original), children: original.isBetaTester
78
+ ? intl.formatMessage(messages.revokeBetaTester)
79
+ : intl.formatMessage(messages.grantBetaTester) }) }) }) }));
80
+ return (_jsxs(ActionRow, { className: "justify-content-start", children: [_jsx(Button, { className: "pl-0", onClick: () => onUnenroll(original), variant: "link", children: intl.formatMessage(messages.unenrollButton) }), _jsx(OverlayTrigger, { trigger: "click", placement: "bottom-end", overlay: popoverContent, rootClose: true, children: _jsx(IconButton, { alt: intl.formatMessage(messages.changeBetaTesterStatus), className: "lead", iconAs: MoreVert }) })] }));
81
+ }, [intl, onBetaTesterChange, onUnenroll]);
83
82
  return (_jsxs(DataTable, { className: "mt-3", columns: tableColumns, additionalColumns: [
84
83
  {
85
84
  id: 'actions',
86
85
  Header: intl.formatMessage(messages.actions),
87
- Cell: actionCustomCell,
86
+ Cell: ActionCustomCell,
88
87
  }
89
88
  ], data: data.results, fetchData: handleFetchData, state: {
90
89
  pageIndex: filters.page,
@@ -1 +1 @@
1
- {"version":3,"file":"EnrollmentsList.js","sourceRoot":"","sources":["../../../src/enrollments/components/EnrollmentsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ActionRow, Button, DataTable, FormControl, Icon, IconButton } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport { MoreVert, Search } from '@openedx/paragon/icons';\nimport messages from '../messages';\nimport { useEnrollments } from '../data/apiHook';\nimport { EnrolledLearner } from '../types';\nimport { DataTableFetchDataProps, TableCellValue } from '@src/types';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\n\nconst ENROLLMENTS_PAGE_SIZE = 25;\n\nconst betaTesterOptions = [\n { value: '', label: messages.allEnrollees },\n { value: 'true', label: messages.betaTesters },\n { value: 'false', label: messages.nonBetaTesters },\n];\n\ninterface EnrollmentsListProps {\n onUnenroll: (learner: EnrolledLearner) => void,\n}\n\nconst UsernameFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n const { inputValue, handleChange } = useDebouncedFilter({\n filterValue,\n setFilter,\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n handleChange(e.target.value);\n };\n\n return (\n <FormControl\n className=\"mb-0\"\n onChange={handleInputChange}\n placeholder={intl.formatMessage(messages.searchPlaceholder)}\n trailingElement={<Icon src={Search} />}\n value={inputValue}\n />\n );\n};\n\nconst BetaTesterFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n setFilter(e.target.value);\n };\n\n return (\n <FormControl\n as=\"select\"\n className=\"mb-0\"\n name=\"isBetaTester\"\n size=\"md\"\n value={filterValue}\n onChange={handleSelectChange}\n >\n {\n betaTesterOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {intl.formatMessage(option.label)}\n </option>\n ))\n }\n </FormControl>\n );\n};\n\nconst EnrollmentsList = ({ onUnenroll }: EnrollmentsListProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams();\n const [filters, setFilters] = useState({ page: 0, username: '', isBetaTester: '' });\n const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useEnrollments(courseId, {\n page: filters.page,\n pageSize: ENROLLMENTS_PAGE_SIZE,\n emailOrUsername: filters.username,\n isBetaTester: filters.isBetaTester,\n });\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const usernameFilter = data.filters?.find((f) => f.id === 'username');\n const newEmailOrUsername = usernameFilter ? usernameFilter.value : '';\n const betaTesterFilter = data.filters?.find((f) => f.id === 'isBetaTester');\n const newIsBetaTester = betaTesterFilter ? betaTesterFilter.value : '';\n const filtersChanged = (newEmailOrUsername !== filters.username) || (newIsBetaTester !== filters.isBetaTester);\n\n if (filtersChanged) {\n setFilters((prevFilters) => ({\n ...prevFilters,\n username: newEmailOrUsername,\n isBetaTester: newIsBetaTester,\n page: 0,\n }));\n return;\n }\n\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n const handleMoreButton = () => {\n // Handle more button click\n console.log('More button clicked');\n };\n\n const tableColumns = [\n { accessor: 'username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter },\n { accessor: 'fullName', Header: intl.formatMessage(messages.fullName), disableFilters: true },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true },\n {\n accessor: 'mode',\n Header: intl.formatMessage(messages.track),\n Cell: ({ value }: { value: string }) => (\n <span className=\"text-capitalize\">{value || 'N/A'}</span>\n ),\n disableFilters: true,\n },\n {\n accessor: 'isBetaTester',\n Header: intl.formatMessage(messages.betaTester),\n Cell: ({ value }: { value: string }) => (value ? intl.formatMessage(messages.trueLabel) : ''),\n Filter: BetaTesterFilter\n },\n ];\n\n const actionCustomCell = useCallback(({ row: { original } }: TableCellValue<EnrolledLearner>) => {\n return (\n <ActionRow className=\"justify-content-start\">\n <Button className=\"pl-0\" onClick={() => onUnenroll(original)} variant=\"link\">\n {intl.formatMessage(messages.unenrollButton)}\n </Button>\n <IconButton\n alt={intl.formatMessage(messages.changeBetaTesterStatus)}\n className=\"lead\"\n iconAs={MoreVert}\n onClick={handleMoreButton}\n />\n </ActionRow>\n );\n }, [onUnenroll, intl]);\n\n return (\n <DataTable\n className=\"mt-3\"\n columns={tableColumns}\n additionalColumns={[\n {\n id: 'actions',\n Header: intl.formatMessage(messages.actions),\n Cell: actionCustomCell,\n }\n ]}\n data={data.results}\n fetchData={handleFetchData}\n state={{\n pageIndex: filters.page,\n pageSize: ENROLLMENTS_PAGE_SIZE,\n filters: [\n { id: 'username', value: filters.username },\n { id: 'isBetaTester', value: filters.isBetaTester },\n ]\n }}\n isFilterable\n isLoading={isLoading}\n isPaginated\n itemCount={data.count}\n manualFilters\n manualPagination\n numBreakoutFilters={2}\n pageSize={ENROLLMENTS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <DataTable.TableControlBar className=\"px-3 pt-3 pb-2\" />\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noEnrollments)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default EnrollmentsList;\n"]}
1
+ {"version":3,"file":"EnrollmentsList.js","sourceRoot":"","sources":["../../../src/enrollments/components/EnrollmentsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, DataTable, FormControl, Icon, IconButton, OverlayTrigger, Popover } from '@openedx/paragon';\nimport { FilterList, MoreVert, Search } from '@openedx/paragon/icons';\nimport messages from '@src/enrollments/messages';\nimport { useEnrollments } from '@src/enrollments/data/apiHook';\nimport { EnrolledLearner } from '@src/enrollments/types';\nimport { useDebouncedFilter } from '@src/hooks/useDebouncedFilter';\nimport { DataTableFetchDataProps, TableCellValue } from '@src/types';\n\nconst ENROLLMENTS_PAGE_SIZE = 25;\n\nconst betaTesterOptions = [\n { value: '', label: messages.allEnrollees },\n { value: 'true', label: messages.betaTesters },\n { value: 'false', label: messages.nonBetaTesters },\n];\n\ninterface EnrollmentsListProps {\n onUnenroll: (learner: EnrolledLearner) => void,\n onBetaTesterChange: (learner: EnrolledLearner) => void,\n}\n\nconst UsernameFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n const { inputValue, handleChange } = useDebouncedFilter({\n filterValue,\n setFilter,\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n handleChange(e.target.value);\n };\n\n return (\n <FormControl\n className=\"mb-0\"\n onChange={handleInputChange}\n placeholder={intl.formatMessage(messages.searchPlaceholder)}\n trailingElement={<Icon src={Search} />}\n value={inputValue}\n />\n );\n};\n\nconst BetaTesterFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n setFilter(e.target.value);\n };\n\n return (\n <FormControl\n as=\"select\"\n className=\"mb-0\"\n name=\"isBetaTester\"\n size=\"md\"\n value={filterValue}\n onChange={handleSelectChange}\n leadingElement={<Icon src={FilterList} />}\n >\n {\n betaTesterOptions.map((option) => (\n <option key={option.value} value={option.value}>\n {intl.formatMessage(option.label)}\n </option>\n ))\n }\n </FormControl>\n );\n};\n\nconst EnrollmentsList = ({ onUnenroll, onBetaTesterChange }: EnrollmentsListProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams();\n const [filters, setFilters] = useState({ page: 0, username: '', isBetaTester: '' });\n const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useEnrollments(courseId, {\n page: filters.page,\n pageSize: ENROLLMENTS_PAGE_SIZE,\n emailOrUsername: filters.username,\n isBetaTester: filters.isBetaTester,\n });\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const usernameFilter = data.filters?.find((f) => f.id === 'username');\n const newEmailOrUsername = usernameFilter ? usernameFilter.value : '';\n const betaTesterFilter = data.filters?.find((f) => f.id === 'isBetaTester');\n const newIsBetaTester = betaTesterFilter ? betaTesterFilter.value : '';\n const filtersChanged = (newEmailOrUsername !== filters.username) || (newIsBetaTester !== filters.isBetaTester);\n\n if (filtersChanged) {\n setFilters((prevFilters) => ({\n ...prevFilters,\n username: newEmailOrUsername,\n isBetaTester: newIsBetaTester,\n page: 0,\n }));\n return;\n }\n\n if (data.pageIndex !== filters.page) {\n setFilters((prevFilters) => ({ ...prevFilters, page: data.pageIndex }));\n }\n };\n\n const tableColumns = [\n { accessor: 'username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter },\n { accessor: 'fullName', Header: intl.formatMessage(messages.fullName), disableFilters: true },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true },\n {\n accessor: 'mode',\n Header: intl.formatMessage(messages.track),\n Cell: ({ value }: { value: string }) => (\n <span className=\"text-capitalize\">{value || 'N/A'}</span>\n ),\n disableFilters: true,\n },\n {\n accessor: 'isBetaTester',\n Header: intl.formatMessage(messages.betaTester),\n Cell: ({ value }: { value: string }) => (value ? intl.formatMessage(messages.trueLabel) : ''),\n Filter: BetaTesterFilter\n },\n ];\n\n const ActionCustomCell = useCallback(({ row: { original } }: TableCellValue<EnrolledLearner>) => {\n const popoverContent = (\n <Popover\n id={`popover-${original.username}`}\n className=\"border-0 shadow-sm\"\n >\n <Popover.Content className=\"p-0 border-0\">\n <div className=\"dropdown-menu show position-static border shadow-sm\">\n <button\n type=\"button\"\n className=\"dropdown-item\"\n onClick={() => onBetaTesterChange(original)}\n >\n {original.isBetaTester\n ? intl.formatMessage(messages.revokeBetaTester)\n : intl.formatMessage(messages.grantBetaTester)}\n </button>\n </div>\n </Popover.Content>\n </Popover>\n );\n\n return (\n <ActionRow className=\"justify-content-start\">\n <Button className=\"pl-0\" onClick={() => onUnenroll(original)} variant=\"link\">\n {intl.formatMessage(messages.unenrollButton)}\n </Button>\n <OverlayTrigger\n trigger=\"click\"\n placement=\"bottom-end\"\n overlay={popoverContent}\n rootClose\n >\n <IconButton\n alt={intl.formatMessage(messages.changeBetaTesterStatus)}\n className=\"lead\"\n iconAs={MoreVert}\n />\n </OverlayTrigger>\n </ActionRow>\n );\n }, [intl, onBetaTesterChange, onUnenroll]);\n\n return (\n <DataTable\n className=\"mt-3\"\n columns={tableColumns}\n additionalColumns={[\n {\n id: 'actions',\n Header: intl.formatMessage(messages.actions),\n Cell: ActionCustomCell,\n }\n ]}\n data={data.results}\n fetchData={handleFetchData}\n state={{\n pageIndex: filters.page,\n pageSize: ENROLLMENTS_PAGE_SIZE,\n filters: [\n { id: 'username', value: filters.username },\n { id: 'isBetaTester', value: filters.isBetaTester },\n ]\n }}\n isFilterable\n isLoading={isLoading}\n isPaginated\n itemCount={data.count}\n manualFilters\n manualPagination\n numBreakoutFilters={2}\n pageSize={ENROLLMENTS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={() => null}\n >\n <DataTable.TableControlBar className=\"px-3 pt-3 pb-2\" />\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noEnrollments)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default EnrollmentsList;\n"]}
@@ -1,4 +1,4 @@
1
- import { EnrolledLearner } from '../types';
1
+ import { EnrolledLearner } from '../../enrollments/types';
2
2
  interface UnenrollModalProps {
3
3
  learner: EnrolledLearner;
4
4
  isOpen: boolean;
@@ -1,7 +1,33 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useParams } from 'react-router-dom';
3
+ import { useIntl } from '@openedx/frontend-base';
4
+ import { Button, ModalDialog } from '@openedx/paragon';
5
+ import { useAlert } from '../../providers/AlertProvider';
6
+ import { useUpdateEnrollments } from '../../enrollments/data/apiHook';
7
+ import messages from '../../enrollments/messages';
2
8
  const UnenrollModal = ({ learner, isOpen, onClose }) => {
3
- console.log(learner, isOpen, onClose);
4
- return _jsx("div", { children: "Unenroll Modal" });
9
+ const intl = useIntl();
10
+ const { courseId = '' } = useParams();
11
+ const { mutate: unenrollLearners, isPending } = useUpdateEnrollments(courseId);
12
+ const { showModal } = useAlert();
13
+ const handleUnenroll = () => {
14
+ unenrollLearners({
15
+ identifier: [learner.username],
16
+ action: 'unenroll',
17
+ }, {
18
+ onSuccess: () => {
19
+ onClose();
20
+ },
21
+ onError: (error) => {
22
+ showModal({
23
+ message: error.message || intl.formatMessage(messages.unenrollLearnerError),
24
+ variant: 'danger',
25
+ confirmText: intl.formatMessage(messages.closeButton),
26
+ });
27
+ }
28
+ });
29
+ };
30
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, title: intl.formatMessage(messages.unenrollLearners), isOverflowVisible: false, children: [_jsx(ModalDialog.Header, { children: _jsx("h3", { className: "text-primary-500", children: intl.formatMessage(messages.unenrollLearnerTitle) }) }), _jsx(ModalDialog.Body, { className: "py-4", children: _jsx("p", { children: intl.formatMessage(messages.unenrollLearnersConfirmation, { name: learner.fullName }) }) }), _jsxs(ModalDialog.Footer, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancelButton) }), _jsx(Button, { className: "ml-2", onClick: handleUnenroll, disabled: isPending, children: intl.formatMessage(messages.unenrollButton) })] })] }));
5
31
  };
6
32
  export default UnenrollModal;
7
33
  //# sourceMappingURL=UnenrollModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UnenrollModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/UnenrollModal.tsx"],"names":[],"mappings":";AAOA,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAsB,EAAE,EAAE;IACzE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEtC,OAAO,2CAAyB,CAAC;AACnC,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import { EnrolledLearner } from '../types';\ninterface UnenrollModalProps {\n learner: EnrolledLearner,\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst UnenrollModal = ({ learner, isOpen, onClose }: UnenrollModalProps) => {\n console.log(learner, isOpen, onClose);\n\n return <div>Unenroll Modal</div>;\n};\n\nexport default UnenrollModal;\n"]}
1
+ {"version":3,"file":"UnenrollModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/UnenrollModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AASjD,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAsB,EAAE,EAAE;IACzE,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/E,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEjC,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,gBAAgB,CAAC;YACf,UAAU,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC9B,MAAM,EAAE,UAAU;SACnB,EAAE;YACD,SAAS,EAAE,GAAG,EAAE;gBACd,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,SAAS,CAAC;oBACR,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC;oBAC3E,OAAO,EAAE,QAAQ;oBACjB,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC;iBACtD,CAAC,CAAC;YACL,CAAC;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,WAAW,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,iBAAiB,EAAE,KAAK,aAC3H,KAAC,WAAW,CAAC,MAAM,cACjB,aAAI,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,GAAM,GACtE,EACrB,KAAC,WAAW,CAAC,IAAI,IAAC,SAAS,EAAC,MAAM,YAChC,sBAAI,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAK,GAC7E,EACnB,MAAC,WAAW,CAAC,MAAM,eACjB,KAAC,MAAM,IAAC,OAAO,EAAC,UAAU,EAAC,OAAO,EAAE,OAAO,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAU,EACjG,KAAC,MAAM,IACL,SAAS,EAAC,MAAM,EAChB,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,SAAS,YAElB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,GACrC,IACU,IACT,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, ModalDialog } from '@openedx/paragon';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { useUpdateEnrollments } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\nimport { EnrolledLearner } from '@src/enrollments/types';\n\ninterface UnenrollModalProps {\n learner: EnrolledLearner,\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst UnenrollModal = ({ learner, isOpen, onClose }: UnenrollModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { mutate: unenrollLearners, isPending } = useUpdateEnrollments(courseId);\n const { showModal } = useAlert();\n\n const handleUnenroll = () => {\n unenrollLearners({\n identifier: [learner.username],\n action: 'unenroll',\n }, {\n onSuccess: () => {\n onClose();\n },\n onError: (error) => {\n showModal({\n message: error.message || intl.formatMessage(messages.unenrollLearnerError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n };\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.unenrollLearners)} isOverflowVisible={false}>\n <ModalDialog.Header>\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.unenrollLearnerTitle)}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"py-4\">\n <p>{intl.formatMessage(messages.unenrollLearnersConfirmation, { name: learner.fullName })}</p>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button\n className=\"ml-2\"\n onClick={handleUnenroll}\n disabled={isPending}\n >\n {intl.formatMessage(messages.unenrollButton)}\n </Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default UnenrollModal;\n"]}
@@ -0,0 +1,8 @@
1
+ import { EnrolledLearner } from '../../enrollments/types';
2
+ interface UpdateBetaTesterModalProps {
3
+ learner: EnrolledLearner;
4
+ isOpen: boolean;
5
+ onClose: () => void;
6
+ }
7
+ declare const UpdateBetaTesterModal: ({ learner, isOpen, onClose }: UpdateBetaTesterModalProps) => import("react/jsx-runtime").JSX.Element | null;
8
+ export default UpdateBetaTesterModal;
@@ -0,0 +1,52 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useParams } from 'react-router-dom';
3
+ import { useCallback, useEffect } from 'react';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import { Button, ModalDialog } from '@openedx/paragon';
6
+ import { useAlert } from '../../providers/AlertProvider';
7
+ import { useUpdateBetaTesters } from '../../enrollments/data/apiHook';
8
+ import messages from '../../enrollments/messages';
9
+ const UpdateBetaTesterModal = ({ learner, isOpen, onClose }) => {
10
+ const intl = useIntl();
11
+ const { courseId = '' } = useParams();
12
+ const { mutate: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);
13
+ const { addAlert, showModal } = useAlert();
14
+ const handleUpdateBetaTester = useCallback(() => {
15
+ updateBetaTester({
16
+ identifier: [learner.username],
17
+ action: learner.isBetaTester ? 'remove' : 'add',
18
+ }, {
19
+ onSuccess: (data) => {
20
+ var _a;
21
+ const failedUsernames = ((_a = data.results) === null || _a === void 0 ? void 0 : _a.filter(user => user.userDoesNotExist).map(user => user.identifier)) || [];
22
+ if (failedUsernames.length > 0) {
23
+ addAlert({
24
+ type: 'danger',
25
+ message: intl.formatMessage(messages.failedBetaTesters),
26
+ extraContent: (failedUsernames.map((learner) => (_jsxs("p", { className: "mb-0", children: ["\u2022 ", intl.formatMessage(messages.unknownLearner, { learner })] }, learner))))
27
+ });
28
+ }
29
+ },
30
+ onError: () => {
31
+ showModal({
32
+ message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),
33
+ variant: 'danger',
34
+ confirmText: intl.formatMessage(messages.closeButton),
35
+ });
36
+ }
37
+ });
38
+ onClose();
39
+ }, [updateBetaTester, learner.username, learner.isBetaTester, addAlert, intl, showModal, onClose]);
40
+ useEffect(() => {
41
+ if (isOpen && !learner.isBetaTester) {
42
+ handleUpdateBetaTester();
43
+ }
44
+ }, [handleUpdateBetaTester, isOpen, learner.isBetaTester]);
45
+ // Only show modal for removing beta testers (requires confirmation)
46
+ if (!isOpen || !learner.isBetaTester) {
47
+ return null;
48
+ }
49
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, title: intl.formatMessage(messages.removeBetaTesterTitle), isOverflowVisible: false, children: [_jsx(ModalDialog.Header, { children: _jsx("h3", { className: "text-primary-500", children: intl.formatMessage(messages.removeBetaTesterTitle) }) }), _jsx(ModalDialog.Body, { className: "py-4", children: _jsx("p", { children: intl.formatMessage(messages.removeBetaTesterDescription) }) }), _jsxs(ModalDialog.Footer, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancelButton) }), _jsx(Button, { className: "ml-2", onClick: handleUpdateBetaTester, disabled: isPending, children: intl.formatMessage(messages.revoke) })] })] }));
50
+ };
51
+ export default UpdateBetaTesterModal;
52
+ //# sourceMappingURL=UpdateBetaTesterModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UpdateBetaTesterModal.js","sourceRoot":"","sources":["../../../src/enrollments/components/UpdateBetaTesterModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useCallback, useEffect } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, ModalDialog } from '@openedx/paragon';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { useUpdateBetaTesters } from '@src/enrollments/data/apiHook';\nimport messages from '@src/enrollments/messages';\nimport { EnrolledLearner } from '@src/enrollments/types';\n\ninterface UpdateBetaTesterModalProps {\n learner: EnrolledLearner,\n isOpen: boolean,\n onClose: () => void,\n}\n\nconst UpdateBetaTesterModal = ({ learner, isOpen, onClose }: UpdateBetaTesterModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { mutate: updateBetaTester, isPending } = useUpdateBetaTesters(courseId);\n const { addAlert, showModal } = useAlert();\n\n const handleUpdateBetaTester = useCallback(() => {\n updateBetaTester({\n identifier: [learner.username],\n action: learner.isBetaTester ? 'remove' : 'add',\n }, {\n onSuccess: (data) => {\n const failedUsernames = data.results?.filter(user => user.userDoesNotExist).map(user => user.identifier) || [];\n if (failedUsernames.length > 0) {\n addAlert({\n type: 'danger',\n message: intl.formatMessage(messages.failedBetaTesters),\n extraContent: (\n failedUsernames.map((learner: string) => (\n <p key={learner} className=\"mb-0\">• {intl.formatMessage(messages.unknownLearner, { learner })}</p>\n ))\n )\n });\n }\n },\n onError: () => {\n showModal({\n message: learner.isBetaTester ? intl.formatMessage(messages.removeBetaTesterError) : intl.formatMessage(messages.addBetaTesterError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n\n onClose();\n }, [updateBetaTester, learner.username, learner.isBetaTester, addAlert, intl, showModal, onClose]);\n\n useEffect(() => {\n if (isOpen && !learner.isBetaTester) {\n handleUpdateBetaTester();\n }\n }, [handleUpdateBetaTester, isOpen, learner.isBetaTester]);\n\n // Only show modal for removing beta testers (requires confirmation)\n if (!isOpen || !learner.isBetaTester) {\n return null;\n }\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={intl.formatMessage(messages.removeBetaTesterTitle)} isOverflowVisible={false}>\n <ModalDialog.Header>\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.removeBetaTesterTitle)}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"py-4\">\n <p>{intl.formatMessage(messages.removeBetaTesterDescription)}</p>\n </ModalDialog.Body>\n <ModalDialog.Footer>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button\n className=\"ml-2\"\n onClick={handleUpdateBetaTester}\n disabled={isPending}\n >\n {intl.formatMessage(messages.revoke)}\n </Button>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default UpdateBetaTesterModal;\n"]}
@@ -1,4 +1,6 @@
1
- import { EnrollmentsParams, EnrollmentStatusResponse, EnrolledLearner } from '../types';
1
+ import { EnrollmentsParams, EnrollmentStatusResponse, EnrolledLearner, UpdateEnrollmentsParams, UpdateBetaTestersParams, UpdateEnrollmentsResponse, UpdateBetaTestersResponse } from '../../enrollments/types';
2
2
  import { DataList } from '../../types';
3
3
  export declare const getEnrollments: (courseId: string, params: EnrollmentsParams) => Promise<DataList<EnrolledLearner>>;
4
4
  export declare const getEnrollmentStatus: (courseId: string, userIdentifier: string) => Promise<EnrollmentStatusResponse>;
5
+ export declare const updateEnrollments: (courseId: string, params: UpdateEnrollmentsParams) => Promise<UpdateEnrollmentsResponse>;
6
+ export declare const updateBetaTesters: (courseId: string, params: UpdateBetaTestersParams) => Promise<UpdateBetaTestersResponse>;
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';
10
+ import { camelCaseObject, getAuthenticatedHttpClient, snakeCaseObject } from '@openedx/frontend-base';
11
11
  import { getApiBaseUrl } from '../../data/api';
12
12
  export const getEnrollments = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
13
13
  const queryParams = new URLSearchParams({
@@ -29,4 +29,14 @@ export const getEnrollmentStatus = (courseId, userIdentifier) => __awaiter(void
29
29
  });
30
30
  return camelCaseObject(data);
31
31
  });
32
+ export const updateEnrollments = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
33
+ const snakeCaseParams = snakeCaseObject(params);
34
+ const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/enrollments/modify`, snakeCaseParams);
35
+ return camelCaseObject(data);
36
+ });
37
+ export const updateBetaTesters = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
38
+ const snakeCaseParams = snakeCaseObject(params);
39
+ const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/beta_testers/modify`, snakeCaseParams);
40
+ return camelCaseObject(data);
41
+ });
32
42
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/enrollments/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAgB,EAChB,MAAyB,EACW,EAAE;IACtC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;QAClC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;KACtC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,WAAW,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,gBAAgB,WAAW,CAAC,QAAQ,EAAE,EAAE,CACjG,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,QAAgB,EAChB,cAAsB,EACa,EAAE;IACrC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,YAAY,QAAQ,+CAA+C,EAAE;QACrF,yBAAyB,EAAE,cAAc;KAC1C,CACF,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC","sourcesContent":["import { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { getApiBaseUrl } from '../../data/api';\nimport { EnrollmentsParams, EnrollmentStatusResponse, EnrolledLearner } from '../types';\nimport { DataList } from '@src/types';\n\nexport const getEnrollments = async (\n courseId: string,\n params: EnrollmentsParams\n): Promise<DataList<EnrolledLearner>> => {\n const queryParams = new URLSearchParams({\n page: (params.page + 1).toString(),\n page_size: params.pageSize.toString(),\n });\n\n if (params.emailOrUsername) {\n queryParams.append('search', params.emailOrUsername);\n }\n\n if (params.isBetaTester) {\n queryParams.append('is_beta_tester', params.isBetaTester);\n }\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/enrollments?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getEnrollmentStatus = async (\n courseId: string,\n userIdentifier: string\n): Promise<EnrollmentStatusResponse> => {\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/courses/${courseId}/instructor/api/get_student_enrollment_status`, {\n unique_student_identifier: userIdentifier,\n }\n );\n return camelCaseObject(data);\n};\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/enrollments/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAgB,EAChB,MAAyB,EACW,EAAE;IACtC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;QAClC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;KACtC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,WAAW,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,gBAAgB,WAAW,CAAC,QAAQ,EAAE,EAAE,CACjG,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,QAAgB,EAChB,cAAsB,EACa,EAAE;IACrC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,YAAY,QAAQ,+CAA+C,EAAE;QACrF,yBAAyB,EAAE,cAAc;KAC1C,CACF,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAgB,EAChB,MAA+B,EACK,EAAE;IACtC,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,qBAAqB,EAC7E,eAAe,CAChB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAgB,EAChB,MAA+B,EACK,EAAE;IACtC,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,sBAAsB,EAC9E,eAAe,CAChB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC","sourcesContent":["import { camelCaseObject, getAuthenticatedHttpClient, snakeCaseObject } from '@openedx/frontend-base';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { EnrollmentsParams, EnrollmentStatusResponse, EnrolledLearner, UpdateEnrollmentsParams, UpdateBetaTestersParams, UpdateEnrollmentsResponse, UpdateBetaTestersResponse } from '@src/enrollments/types';\nimport { DataList } from '@src/types';\n\nexport const getEnrollments = async (\n courseId: string,\n params: EnrollmentsParams\n): Promise<DataList<EnrolledLearner>> => {\n const queryParams = new URLSearchParams({\n page: (params.page + 1).toString(),\n page_size: params.pageSize.toString(),\n });\n\n if (params.emailOrUsername) {\n queryParams.append('search', params.emailOrUsername);\n }\n\n if (params.isBetaTester) {\n queryParams.append('is_beta_tester', params.isBetaTester);\n }\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/enrollments?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getEnrollmentStatus = async (\n courseId: string,\n userIdentifier: string\n): Promise<EnrollmentStatusResponse> => {\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/courses/${courseId}/instructor/api/get_student_enrollment_status`, {\n unique_student_identifier: userIdentifier,\n }\n );\n return camelCaseObject(data);\n};\n\nexport const updateEnrollments = async (\n courseId: string,\n params: UpdateEnrollmentsParams\n): Promise<UpdateEnrollmentsResponse> => {\n const snakeCaseParams = snakeCaseObject(params);\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/enrollments/modify`,\n snakeCaseParams\n );\n return camelCaseObject(data);\n};\n\nexport const updateBetaTesters = async (\n courseId: string,\n params: UpdateBetaTestersParams\n): Promise<UpdateBetaTestersResponse> => {\n const snakeCaseParams = snakeCaseObject(params);\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/beta_testers/modify`,\n snakeCaseParams\n );\n return camelCaseObject(data);\n};\n"]}
@@ -1,3 +1,5 @@
1
- import { EnrollmentsParams } from '../types';
2
- export declare const useEnrollments: (courseId: string, params: EnrollmentsParams) => import("@tanstack/react-query").UseQueryResult<import("../../types").DataList<import("../types").EnrolledLearner>, Error>;
3
- export declare const useEnrollmentByUserId: (courseId: string, userIdentifier: string) => import("@tanstack/react-query").UseQueryResult<import("../types").EnrollmentStatusResponse, Error>;
1
+ import { EnrollmentsParams, UpdateBetaTestersParams, UpdateEnrollmentsParams } from '../../enrollments/types';
2
+ export declare const useEnrollments: (courseId: string, params: EnrollmentsParams) => import("@tanstack/react-query").UseQueryResult<import("../../types").DataList<import("../../enrollments/types").EnrolledLearner>, Error>;
3
+ export declare const useEnrollmentByUserId: (courseId: string, userIdentifier: string) => import("@tanstack/react-query").UseQueryResult<import("../../enrollments/types").EnrollmentStatusResponse, Error>;
4
+ export declare const useUpdateEnrollments: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../enrollments/types").UpdateEnrollmentsResponse, Error, UpdateEnrollmentsParams, unknown>;
5
+ export declare const useUpdateBetaTesters: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../enrollments/types").UpdateBetaTestersResponse, Error, UpdateBetaTestersParams, unknown>;
@@ -1,6 +1,6 @@
1
- import { useQuery } from '@tanstack/react-query';
2
- import { getEnrollments, getEnrollmentStatus } from './api';
3
- import { enrollmentsQueryKeys } from './queryKeys';
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { getEnrollments, getEnrollmentStatus, updateBetaTesters, updateEnrollments } from '../../enrollments/data/api';
3
+ import { enrollmentsQueryKeys } from '../../enrollments/data/queryKeys';
4
4
  export const useEnrollments = (courseId, params) => (useQuery({
5
5
  queryKey: enrollmentsQueryKeys.byCoursePaginated(courseId, params),
6
6
  queryFn: () => getEnrollments(courseId, params),
@@ -11,4 +11,22 @@ export const useEnrollmentByUserId = (courseId, userIdentifier) => (useQuery({
11
11
  queryFn: () => getEnrollmentStatus(courseId, userIdentifier),
12
12
  enabled: false,
13
13
  }));
14
+ export const useUpdateEnrollments = (courseId) => {
15
+ const queryClient = useQueryClient();
16
+ return (useMutation({
17
+ mutationFn: (params) => updateEnrollments(courseId, params),
18
+ onSuccess: () => {
19
+ queryClient.invalidateQueries({ queryKey: enrollmentsQueryKeys.byCourse(courseId) });
20
+ },
21
+ }));
22
+ };
23
+ export const useUpdateBetaTesters = (courseId) => {
24
+ const queryClient = useQueryClient();
25
+ return (useMutation({
26
+ mutationFn: (params) => updateBetaTesters(courseId, params),
27
+ onSuccess: () => {
28
+ queryClient.invalidateQueries({ queryKey: enrollmentsQueryKeys.byCourse(courseId) });
29
+ },
30
+ }));
31
+ };
14
32
  //# sourceMappingURL=apiHook.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/enrollments/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,MAAyB,EAAE,EAAE,CAAC,CAC7E,QAAQ,CAAC;IACP,QAAQ,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IAClE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAAgB,EAAE,cAAsB,EAAE,EAAE,CAAC,CACjF,QAAQ,CAAC;IACP,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IACjE,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC;IAC5D,OAAO,EAAE,KAAK;CACf,CAAC,CACH,CAAC","sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { getEnrollments, getEnrollmentStatus } from './api';\nimport { enrollmentsQueryKeys } from './queryKeys';\nimport { EnrollmentsParams } from '../types';\n\nexport const useEnrollments = (courseId: string, params: EnrollmentsParams) => (\n useQuery({\n queryKey: enrollmentsQueryKeys.byCoursePaginated(courseId, params),\n queryFn: () => getEnrollments(courseId, params),\n enabled: !!courseId,\n })\n);\n\nexport const useEnrollmentByUserId = (courseId: string, userIdentifier: string) => (\n useQuery({\n queryKey: enrollmentsQueryKeys.byUserId(courseId, userIdentifier),\n queryFn: () => getEnrollmentStatus(courseId, userIdentifier),\n enabled: false,\n })\n);\n"]}
1
+ {"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/enrollments/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACtH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,MAAyB,EAAE,EAAE,CAAC,CAC7E,QAAQ,CAAC;IACP,QAAQ,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IAClE,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAAgB,EAAE,cAAsB,EAAE,EAAE,CAAC,CACjF,QAAQ,CAAC;IACP,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IACjE,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC;IAC5D,OAAO,EAAE,KAAK;CACf,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACvD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,MAA+B,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;QACpF,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;KACF,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACvD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,MAA+B,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;QACpF,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;KACF,CAAC,CAAC,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { getEnrollments, getEnrollmentStatus, updateBetaTesters, updateEnrollments } from '@src/enrollments/data/api';\nimport { enrollmentsQueryKeys } from '@src/enrollments/data/queryKeys';\nimport { EnrollmentsParams, UpdateBetaTestersParams, UpdateEnrollmentsParams } from '@src/enrollments/types';\n\nexport const useEnrollments = (courseId: string, params: EnrollmentsParams) => (\n useQuery({\n queryKey: enrollmentsQueryKeys.byCoursePaginated(courseId, params),\n queryFn: () => getEnrollments(courseId, params),\n enabled: !!courseId,\n })\n);\n\nexport const useEnrollmentByUserId = (courseId: string, userIdentifier: string) => (\n useQuery({\n queryKey: enrollmentsQueryKeys.byUserId(courseId, userIdentifier),\n queryFn: () => getEnrollmentStatus(courseId, userIdentifier),\n enabled: false,\n })\n);\n\nexport const useUpdateEnrollments = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: (params: UpdateEnrollmentsParams) => updateEnrollments(courseId, params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: enrollmentsQueryKeys.byCourse(courseId) });\n },\n }));\n};\n\nexport const useUpdateBetaTesters = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: (params: UpdateBetaTestersParams) => updateBetaTesters(courseId, params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: enrollmentsQueryKeys.byCourse(courseId) });\n },\n }));\n};\n"]}
@@ -1,7 +1,7 @@
1
- import { EnrollmentsParams } from '../types';
1
+ import { EnrollmentsParams } from '../../enrollments/types';
2
2
  export declare const enrollmentsQueryKeys: {
3
- all: readonly ["org.openedx.frontend.app.instructor", "enrollments"];
4
- byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructor", "enrollments", string];
5
- byCoursePaginated: (courseId: string, params: EnrollmentsParams) => readonly ["org.openedx.frontend.app.instructor", "enrollments", string, number, number, string, string];
6
- byUserId: (courseId: string, userIdentifier: string) => readonly ["org.openedx.frontend.app.instructor", "enrollments", string, "enrollment", string];
3
+ all: readonly ["org.openedx.frontend.app.instructorDashboard", "enrollments"];
4
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "enrollments", string];
5
+ byCoursePaginated: (courseId: string, params: EnrollmentsParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "enrollments", string, number, number, string, string];
6
+ byUserId: (courseId: string, userIdentifier: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "enrollments", string, "enrollment", string];
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/enrollments/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,CAAU;IACpC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAU;IAChF,iBAAiB,EAAE,CAAC,QAAgB,EAAE,MAAyB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,CAAU;IACpM,QAAQ,EAAE,CAAC,QAAgB,EAAE,cAAsB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,cAAc,CAAU;CAC5I,CAAC","sourcesContent":["import { appId } from '../../constants';\nimport { EnrollmentsParams } from '../types';\n\nexport const enrollmentsQueryKeys = {\n all: [appId, 'enrollments'] as const,\n byCourse: (courseId: string) => [...enrollmentsQueryKeys.all, courseId] as const,\n byCoursePaginated: (courseId: string, params: EnrollmentsParams) => [...enrollmentsQueryKeys.byCourse(courseId), params.page, params.pageSize, params.emailOrUsername, params.isBetaTester] as const,\n byUserId: (courseId: string, userIdentifier: string) => [...enrollmentsQueryKeys.byCourse(courseId), 'enrollment', userIdentifier] as const,\n};\n"]}
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/enrollments/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,CAAU;IACpC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAU;IAChF,iBAAiB,EAAE,CAAC,QAAgB,EAAE,MAAyB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,CAAU;IACpM,QAAQ,EAAE,CAAC,QAAgB,EAAE,cAAsB,EAAE,EAAE,CAAC,CAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,EAAE,cAAc,CAAU;CAC5I,CAAC","sourcesContent":["import { appId } from '@src/constants';\nimport { EnrollmentsParams } from '@src/enrollments/types';\n\nexport const enrollmentsQueryKeys = {\n all: [appId, 'enrollments'] as const,\n byCourse: (courseId: string) => [...enrollmentsQueryKeys.all, courseId] as const,\n byCoursePaginated: (courseId: string, params: EnrollmentsParams) => [...enrollmentsQueryKeys.byCourse(courseId), params.page, params.pageSize, params.emailOrUsername, params.isBetaTester] as const,\n byUserId: (courseId: string, userIdentifier: string) => [...enrollmentsQueryKeys.byCourse(courseId), 'enrollment', userIdentifier] as const,\n};\n"]}