@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,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { useParams } from 'react-router-dom';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import { ActionRow, Button, Form, FormControl, FormLabel, ModalDialog } from '@openedx/paragon';
6
+ import { useAddTeamMember, useRemoveTeamMember, useRoles } from '../../courseTeam/data/apiHook';
7
+ import messages from '../../courseTeam/messages';
8
+ import { useAlert } from '../../providers/AlertProvider';
9
+ const EditTeamMemberModal = ({ isOpen, user, onClose }) => {
10
+ const intl = useIntl();
11
+ const { courseId = '' } = useParams();
12
+ const [selectedRole, setSelectedRole] = useState('');
13
+ const [keepRoles, setKeepRoles] = useState([]);
14
+ const { mutate: addTeamMember, isPending: isAdding } = useAddTeamMember(courseId);
15
+ const { mutate: removeTeamMember, isPending: isRemoving } = useRemoveTeamMember(courseId);
16
+ const { showModal } = useAlert();
17
+ const { data: { results } = { results: [] } } = useRoles(courseId);
18
+ useEffect(() => {
19
+ if (isOpen) {
20
+ setKeepRoles(user.roles.map(role => role.role));
21
+ setSelectedRole('');
22
+ }
23
+ }, [isOpen, user]);
24
+ const filteredRoles = (results === null || results === void 0 ? void 0 : results.filter(role => !user.roles.some(userRole => userRole.role === role.role))) || [];
25
+ const roles = [{ role: '', displayName: intl.formatMessage(messages.rolePlaceholder) }, ...filteredRoles];
26
+ const handleToggleRole = (roleName) => {
27
+ if (keepRoles.includes(roleName)) {
28
+ setKeepRoles(keepRoles.filter(role => role !== roleName));
29
+ }
30
+ else {
31
+ setKeepRoles([...keepRoles, roleName]);
32
+ }
33
+ };
34
+ const handleSave = () => {
35
+ const rolesToRemove = user.roles.filter(role => !keepRoles.includes(role.role)).map(role => role.role);
36
+ const hasRolesToAdd = selectedRole;
37
+ const hasRolesToRemove = rolesToRemove.length > 0;
38
+ // Sequential approach: remove roles first, then add new role
39
+ if (hasRolesToRemove) {
40
+ removeTeamMember({ identifier: user.username, roles: rolesToRemove }, {
41
+ onSuccess: () => {
42
+ // After successful removal, add new role if needed
43
+ if (hasRolesToAdd) {
44
+ addTeamMember({ identifiers: [user.username], role: selectedRole }, {
45
+ onSuccess: () => {
46
+ onClose();
47
+ },
48
+ onError: () => {
49
+ showModal({
50
+ message: intl.formatMessage(messages.addRoleError),
51
+ variant: 'danger',
52
+ confirmText: intl.formatMessage(messages.closeButton),
53
+ });
54
+ }
55
+ });
56
+ }
57
+ else {
58
+ onClose();
59
+ }
60
+ },
61
+ onError: () => {
62
+ showModal({
63
+ message: intl.formatMessage(messages.removeTeamMemberError, { username: user.username }),
64
+ variant: 'danger',
65
+ confirmText: intl.formatMessage(messages.closeButton),
66
+ });
67
+ }
68
+ });
69
+ }
70
+ else if (hasRolesToAdd) {
71
+ // Only add operation needed
72
+ addTeamMember({ identifiers: [user.username], role: selectedRole }, {
73
+ onSuccess: () => {
74
+ onClose();
75
+ },
76
+ onError: () => {
77
+ showModal({
78
+ message: intl.formatMessage(messages.addRoleError),
79
+ variant: 'danger',
80
+ confirmText: intl.formatMessage(messages.closeButton),
81
+ });
82
+ }
83
+ });
84
+ }
85
+ };
86
+ return (_jsxs(ModalDialog, { isOpen: isOpen, title: intl.formatMessage(messages.editTeamTitle, { username: user.username }), onClose: onClose, isOverflowVisible: false, children: [_jsx(ModalDialog.Header, { className: "border-light-700 border-bottom", children: _jsx("h3", { className: "text-primary-500", children: intl.formatMessage(messages.editTeamTitle, { username: user.username }) }) }), _jsxs(ModalDialog.Body, { className: "position-relative overflow-auto", children: [_jsx("p", { children: intl.formatMessage(messages.editInstructions, { username: user.username }) }), _jsx(Form.CheckboxSet, { onChange: (e) => handleToggleRole(e.target.value), value: keepRoles, name: "keepRoles", children: (user.roles || [])
87
+ .map((role) => (_jsx(Form.Checkbox, { className: "mt-2", value: role.role, children: role.displayName }, role.role))) }), _jsx(FormLabel, { className: "mt-4", children: intl.formatMessage(messages.addRole) }), _jsx(FormControl, { as: "select", disabled: roles.length === 1, onChange: (e) => setSelectedRole(e.target.value), value: selectedRole, children: roles.map((role) => (_jsx("option", { value: role.role, children: role.displayName }, role.role))) })] }), _jsx(ModalDialog.Footer, { className: "border-light-700 border-top", children: _jsxs(ActionRow, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancelButton) }), _jsx(Button, { variant: "primary", onClick: handleSave, disabled: isAdding || isRemoving || (keepRoles.length === user.roles.length && !selectedRole), children: intl.formatMessage(messages.saveButton) })] }) })] }));
88
+ };
89
+ export default EditTeamMemberModal;
90
+ //# sourceMappingURL=EditTeamMemberModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EditTeamMemberModal.js","sourceRoot":"","sources":["../../../src/courseTeam/components/EditTeamMemberModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { ActionRow, Button, Form, FormControl, FormLabel, ModalDialog } from '@openedx/paragon';\nimport { useAddTeamMember, useRemoveTeamMember, useRoles } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { CourseTeamMember, Role } from '@src/courseTeam/types';\nimport { useAlert } from '@src/providers/AlertProvider';\n\ninterface EditTeamMemberModalProps {\n isOpen: boolean,\n user: CourseTeamMember,\n onClose: () => void,\n}\n\nconst EditTeamMemberModal = ({ isOpen, user, onClose }: EditTeamMemberModalProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [selectedRole, setSelectedRole] = useState('');\n const [keepRoles, setKeepRoles] = useState<string[]>([]);\n const { mutate: addTeamMember, isPending: isAdding } = useAddTeamMember(courseId);\n const { mutate: removeTeamMember, isPending: isRemoving } = useRemoveTeamMember(courseId);\n const { showModal } = useAlert();\n\n const { data: { results } = { results: [] } } = useRoles(courseId);\n\n useEffect(() => {\n if (isOpen) {\n setKeepRoles(user.roles.map(role => role.role));\n setSelectedRole('');\n }\n }, [isOpen, user]);\n\n const filteredRoles = results?.filter(role => !user.roles.some(userRole => userRole.role === role.role)) || [];\n\n const roles = [{ role: '', displayName: intl.formatMessage(messages.rolePlaceholder) }, ...filteredRoles];\n\n const handleToggleRole = (roleName: string) => {\n if (keepRoles.includes(roleName)) {\n setKeepRoles(keepRoles.filter(role => role !== roleName));\n } else {\n setKeepRoles([...keepRoles, roleName]);\n }\n };\n\n const handleSave = () => {\n const rolesToRemove = user.roles.filter(role => !keepRoles.includes(role.role)).map(role => role.role);\n const hasRolesToAdd = selectedRole;\n const hasRolesToRemove = rolesToRemove.length > 0;\n\n // Sequential approach: remove roles first, then add new role\n if (hasRolesToRemove) {\n removeTeamMember({ identifier: user.username, roles: rolesToRemove }, {\n onSuccess: () => {\n // After successful removal, add new role if needed\n if (hasRolesToAdd) {\n addTeamMember({ identifiers: [user.username], role: selectedRole }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else {\n onClose();\n }\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.removeTeamMemberError, { username: user.username }),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n } else if (hasRolesToAdd) {\n // Only add operation needed\n addTeamMember({ identifiers: [user.username], role: selectedRole }, {\n onSuccess: () => {\n onClose();\n },\n onError: () => {\n showModal({\n message: intl.formatMessage(messages.addRoleError),\n variant: 'danger',\n confirmText: intl.formatMessage(messages.closeButton),\n });\n }\n });\n }\n };\n\n return (\n <ModalDialog\n isOpen={isOpen}\n title={intl.formatMessage(messages.editTeamTitle, { username: user.username })}\n onClose={onClose}\n isOverflowVisible={false}\n >\n <ModalDialog.Header className=\"border-light-700 border-bottom\">\n <h3 className=\"text-primary-500\">{intl.formatMessage(messages.editTeamTitle, { username: user.username })}</h3>\n </ModalDialog.Header>\n <ModalDialog.Body className=\"position-relative overflow-auto\">\n <p>{intl.formatMessage(messages.editInstructions, { username: user.username })}</p>\n <Form.CheckboxSet onChange={(e: React.ChangeEvent<HTMLInputElement>) => handleToggleRole(e.target.value)} value={keepRoles} name=\"keepRoles\">\n {\n (user.roles || [])\n .map((role: Role) => (\n <Form.Checkbox className=\"mt-2\" key={role.role} value={role.role}>\n {role.displayName}\n </Form.Checkbox>\n ))\n }\n </Form.CheckboxSet>\n <FormLabel className=\"mt-4\">{intl.formatMessage(messages.addRole)}</FormLabel>\n <FormControl\n as=\"select\"\n disabled={roles.length === 1}\n onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setSelectedRole(e.target.value)}\n value={selectedRole}\n >\n {\n roles.map((role) => (\n <option key={role.role} value={role.role}>\n {role.displayName}\n </option>\n ))\n }\n </FormControl>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"border-light-700 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancelButton)}</Button>\n <Button variant=\"primary\" onClick={handleSave} disabled={isAdding || isRemoving || (keepRoles.length === user.roles.length && !selectedRole)}>\n {intl.formatMessage(messages.saveButton)}\n </Button>\n </ActionRow>\n </ModalDialog.Footer>\n </ModalDialog>\n );\n};\n\nexport default EditTeamMemberModal;\n"]}
@@ -0,0 +1,6 @@
1
+ import { CourseTeamMember } from '../../courseTeam/types';
2
+ interface MembersContentProps {
3
+ onEdit: (user: CourseTeamMember) => void;
4
+ }
5
+ declare const MembersContent: ({ onEdit }: MembersContentProps) => import("react/jsx-runtime").JSX.Element;
6
+ export default MembersContent;
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo } from 'react';
3
+ import { useParams } from 'react-router-dom';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import { Button, DataTable } from '@openedx/paragon';
6
+ import UsernameFilter from '../../components/UsernameFilter';
7
+ import RoleFilter from '../../courseTeam/components/RoleFilter';
8
+ import { useTeamMembers } from '../../courseTeam/data/apiHook';
9
+ import messages from '../../courseTeam/messages';
10
+ const TEAM_MEMBERS_PAGE_SIZE = 25;
11
+ const MembersContent = ({ onEdit }) => {
12
+ const intl = useIntl();
13
+ const { courseId = '' } = useParams();
14
+ const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', role: '' });
15
+ const { data: { results: teamMembers = [], numPages = 1, count = 0 } = {}, isLoading = false } = useTeamMembers(courseId, Object.assign(Object.assign({}, filters), { pageSize: TEAM_MEMBERS_PAGE_SIZE }));
16
+ const tableColumns = useMemo(() => [
17
+ { accessor: 'username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter },
18
+ { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true },
19
+ { accessor: 'roles', Header: intl.formatMessage(messages.role), Cell: ({ cell: { value } }) => value.map(role => role.displayName).join(', '), Filter: RoleFilter },
20
+ ], [intl]);
21
+ const additionalColumns = useMemo(() => [{
22
+ id: 'actions',
23
+ Header: intl.formatMessage(messages.actions),
24
+ Cell: ({ row }) => (_jsx(Button, { variant: "link", size: "inline", onClick: () => onEdit(row.original), children: intl.formatMessage(messages.edit) }))
25
+ }], [intl, onEdit]);
26
+ const handleFetchData = (data) => {
27
+ var _a, _b;
28
+ const usernameFilter = (_a = data.filters) === null || _a === void 0 ? void 0 : _a.find((f) => f.id === 'username');
29
+ const newEmailOrUsername = usernameFilter ? usernameFilter.value : '';
30
+ const rolesFilter = (_b = data.filters) === null || _b === void 0 ? void 0 : _b.find((f) => f.id === 'roles');
31
+ const newRole = rolesFilter ? rolesFilter.value : '';
32
+ const filtersChanged = (newEmailOrUsername !== filters.emailOrUsername) || (newRole !== filters.role);
33
+ if (filtersChanged) {
34
+ setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { emailOrUsername: newEmailOrUsername, role: newRole, page: 0 })));
35
+ return;
36
+ }
37
+ if (data.pageIndex !== filters.page) {
38
+ setFilters((prevFilters) => (Object.assign(Object.assign({}, prevFilters), { page: data.pageIndex })));
39
+ }
40
+ };
41
+ const tableState = useMemo(() => ({
42
+ pageIndex: filters.page,
43
+ pageSize: TEAM_MEMBERS_PAGE_SIZE,
44
+ }), [filters.page]);
45
+ return (_jsxs(DataTable, { additionalColumns: additionalColumns, columns: tableColumns, data: teamMembers, fetchData: handleFetchData, state: tableState, isFilterable: true, isLoading: isLoading, isPaginated: true, itemCount: count, manualFilters: true, manualPagination: true, numBreakoutFilters: 2, pageSize: TEAM_MEMBERS_PAGE_SIZE, pageCount: numPages, RowStatusComponent: () => null, children: [_jsx(DataTable.TableControlBar, {}), _jsx(DataTable.Table, {}), _jsx(DataTable.EmptyTable, { content: intl.formatMessage(messages.noTeamMembers) }), _jsx(DataTable.TableFooter, {})] }));
46
+ };
47
+ export default MembersContent;
48
+ //# sourceMappingURL=MembersContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MembersContent.js","sourceRoot":"","sources":["../../../src/courseTeam/components/MembersContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, DataTable } from '@openedx/paragon';\nimport UsernameFilter from '@src/components/UsernameFilter';\nimport RoleFilter from '@src/courseTeam/components/RoleFilter';\nimport { useTeamMembers } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { CourseTeamMember, Role } from '@src/courseTeam/types';\nimport { DataTableFetchDataProps } from '@src/types';\n\nconst TEAM_MEMBERS_PAGE_SIZE = 25;\n\ninterface MembersContentProps {\n onEdit: (user: CourseTeamMember) => void,\n}\n\nconst MembersContent = ({ onEdit }: MembersContentProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState({ page: 0, emailOrUsername: '', role: '' });\n const { data: { results: teamMembers = [], numPages = 1, count = 0 } = {}, isLoading = false } = useTeamMembers(courseId, { ...filters, pageSize: TEAM_MEMBERS_PAGE_SIZE });\n\n const tableColumns = useMemo(() => [\n { accessor: 'username', Header: intl.formatMessage(messages.username), Filter: UsernameFilter },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true },\n { accessor: 'roles', Header: intl.formatMessage(messages.role), Cell: ({ cell: { value } }: { cell: { value: Role[] } }) => value.map(role => role.displayName).join(', '), Filter: RoleFilter },\n ], [intl]);\n\n const additionalColumns = useMemo(() => [{\n id: 'actions',\n Header: intl.formatMessage(messages.actions),\n Cell: ({ row }: { row: { original: any } }) => (\n <Button variant=\"link\" size=\"inline\" onClick={() => onEdit(row.original)}>\n {intl.formatMessage(messages.edit)}\n </Button>\n )\n }], [intl, onEdit]);\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const usernameFilter = data.filters?.find((f) => f.id === 'username');\n const newEmailOrUsername = usernameFilter ? usernameFilter.value : '';\n const rolesFilter = data.filters?.find((f) => f.id === 'roles');\n const newRole = rolesFilter ? rolesFilter.value : '';\n const filtersChanged = (newEmailOrUsername !== filters.emailOrUsername) || (newRole !== filters.role);\n\n if (filtersChanged) {\n setFilters((prevFilters) => ({\n ...prevFilters,\n emailOrUsername: newEmailOrUsername,\n role: newRole,\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 tableState = useMemo(() => ({\n pageIndex: filters.page,\n pageSize: TEAM_MEMBERS_PAGE_SIZE,\n }), [filters.page]);\n\n return (\n <DataTable\n additionalColumns={additionalColumns}\n columns={tableColumns}\n data={teamMembers}\n fetchData={handleFetchData}\n state={tableState}\n isFilterable\n isLoading={isLoading}\n isPaginated\n itemCount={count}\n manualFilters\n manualPagination\n numBreakoutFilters={2}\n pageSize={TEAM_MEMBERS_PAGE_SIZE}\n pageCount={numPages}\n RowStatusComponent={() => null}\n >\n <DataTable.TableControlBar />\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noTeamMembers)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default MembersContent;\n"]}
@@ -0,0 +1,7 @@
1
+ declare const RoleFilter: ({ column: { filterValue, setFilter } }: {
2
+ column: {
3
+ filterValue: string;
4
+ setFilter: (value: string) => void;
5
+ };
6
+ }) => import("react/jsx-runtime").JSX.Element;
7
+ export default RoleFilter;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { useParams } from 'react-router-dom';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import { FormControl, Icon } from '@openedx/paragon';
6
+ import { FilterList } from '@openedx/paragon/icons';
7
+ import { useRoles } from '../../courseTeam/data/apiHook';
8
+ import messages from '../../courseTeam/messages';
9
+ const RoleFilter = ({ column: { filterValue, setFilter } }) => {
10
+ const intl = useIntl();
11
+ const { courseId = '' } = useParams();
12
+ const { data } = useRoles(courseId);
13
+ const handleSelectChange = (e) => {
14
+ setFilter(e.target.value);
15
+ };
16
+ const roles = useMemo(() => {
17
+ return [{ value: '', label: intl.formatMessage(messages.allRoles) }, ...((data === null || data === void 0 ? void 0 : data.results) || []).map((role) => ({ value: role.role, label: role.displayName }))];
18
+ }, [data, intl]);
19
+ return (_jsx(FormControl, { as: "select", className: "mb-0", disabled: !data, name: "role", size: "md", value: filterValue, onChange: handleSelectChange, leadingElement: _jsx(Icon, { src: FilterList }), children: roles.map(role => (_jsx("option", { value: role.value, children: role.label }, role.value))) }));
20
+ };
21
+ export default RoleFilter;
22
+ //# sourceMappingURL=RoleFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoleFilter.js","sourceRoot":"","sources":["../../../src/courseTeam/components/RoleFilter.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAGhD,MAAM,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,EAA2E,EAAE,EAAE;IACrI,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEpC,MAAM,kBAAkB,GAAG,CAAC,CAAuC,EAAE,EAAE;QACrE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;QACzB,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,KAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAU,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;IACtK,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjB,OAAO,CACL,KAAC,WAAW,IACV,EAAE,EAAC,QAAQ,EACX,SAAS,EAAC,MAAM,EAChB,QAAQ,EAAE,CAAC,IAAI,EACf,IAAI,EAAC,MAAM,EACX,IAAI,EAAC,IAAI,EACT,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,kBAAkB,EAC5B,cAAc,EAAE,KAAC,IAAI,IAAC,GAAG,EAAE,UAAU,GAAI,YAExC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CACjB,iBAAyB,KAAK,EAAE,IAAI,CAAC,KAAK,YACvC,IAAI,CAAC,KAAK,IADA,IAAI,CAAC,KAAK,CAEd,CACV,CAAC,GACU,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC","sourcesContent":["import { useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { FormControl, Icon } from '@openedx/paragon';\nimport { FilterList } from '@openedx/paragon/icons';\nimport { useRoles } from '@src/courseTeam/data/apiHook';\nimport messages from '@src/courseTeam/messages';\nimport { Role } from '@src/courseTeam/types';\n\nconst RoleFilter = ({ column: { filterValue, setFilter } }: { column: { filterValue: string, setFilter: (value: string) => void } }) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { data } = useRoles(courseId);\n\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n setFilter(e.target.value);\n };\n\n const roles = useMemo(() => {\n return [{ value: '', label: intl.formatMessage(messages.allRoles) }, ...(data?.results || []).map((role: Role) => ({ value: role.role, label: role.displayName }))];\n }, [data, intl]);\n\n return (\n <FormControl\n as=\"select\"\n className=\"mb-0\"\n disabled={!data}\n name=\"role\"\n size=\"md\"\n value={filterValue}\n onChange={handleSelectChange}\n leadingElement={<Icon src={FilterList} />}\n >\n {roles.map(role => (\n <option key={role.value} value={role.value}>\n {role.label}\n </option>\n ))}\n </FormControl>\n );\n};\n\nexport default RoleFilter;\n"]}
@@ -0,0 +1,3 @@
1
+ export declare const rolesOrder: readonly ["staff", "limitedStaff", "admin", "beta", "courseDataResearchers", "discussionAdmin", "discussionModerator", "groupCommunityTA", "communityTA"];
2
+ declare const RolesContent: () => import("react/jsx-runtime").JSX.Element;
3
+ export default RolesContent;
@@ -0,0 +1,25 @@
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 messages from '../../courseTeam/messages';
5
+ import { useRoles } from '../../courseTeam/data/apiHook';
6
+ export const rolesOrder = [
7
+ 'staff',
8
+ 'limitedStaff',
9
+ 'admin',
10
+ 'beta',
11
+ 'courseDataResearchers',
12
+ 'discussionAdmin',
13
+ 'discussionModerator',
14
+ 'groupCommunityTA',
15
+ 'communityTA'
16
+ ];
17
+ const RolesContent = () => {
18
+ const intl = useIntl();
19
+ const { courseId = '' } = useParams();
20
+ const { data: { results } = { results: [] } } = useRoles(courseId);
21
+ const isCCXCoachEnabled = !!(results === null || results === void 0 ? void 0 : results.find(({ role }) => role === 'ccx_coach'));
22
+ return (_jsxs("div", { className: "mt-4", children: [rolesOrder.map((role) => (_jsxs("div", { className: "mb-4", children: [_jsx("h4", { className: "text-primary-500", children: intl.formatMessage(messages[role]) }), _jsx("p", { className: "text-gray-700", children: intl.formatMessage(messages[`${role}Description`]) })] }, role))), isCCXCoachEnabled && (_jsxs("div", { className: "mb-4", children: [_jsx("h4", { className: "text-primary-500", children: intl.formatMessage(messages.ccxCoach) }), _jsx("p", { className: "text-gray-700", children: intl.formatMessage(messages.ccxCoachDescription) })] }))] }));
23
+ };
24
+ export default RolesContent;
25
+ //# sourceMappingURL=RolesContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RolesContent.js","sourceRoot":"","sources":["../../../src/courseTeam/components/RolesContent.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAGxD,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO;IACP,cAAc;IACd,OAAO;IACP,MAAM;IACN,uBAAuB;IACvB,iBAAiB;IACjB,qBAAqB;IACrB,kBAAkB;IAClB,aAAa;CACL,CAAC;AAEX,MAAM,YAAY,GAAG,GAAG,EAAE;IACxB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,iBAAiB,GAAG,CAAC,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAQ,EAAE,EAAE,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA,CAAC;IAEpF,OAAO,CACL,eAAK,SAAS,EAAC,MAAM,aAEjB,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACvB,eAAgB,SAAS,EAAC,MAAM,aAC9B,aAAI,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAM,EAC1E,YAAG,SAAS,EAAC,eAAe,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI,aAAa,CAAC,CAAC,GAAK,KAF7E,IAAI,CAGR,CACP,CAAC,EAGF,iBAAiB,IAAI,CACnB,eAAK,SAAS,EAAC,MAAM,aACnB,aAAI,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAM,EAC7E,YAAG,SAAS,EAAC,eAAe,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GAAK,IAC/E,CACP,IAEC,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,YAAY,CAAC","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport messages from '@src/courseTeam/messages';\nimport { useRoles } from '@src/courseTeam/data/apiHook';\nimport { Role } from '@src/courseTeam/types';\n\nexport const rolesOrder = [\n 'staff',\n 'limitedStaff',\n 'admin',\n 'beta',\n 'courseDataResearchers',\n 'discussionAdmin',\n 'discussionModerator',\n 'groupCommunityTA',\n 'communityTA'\n] as const;\n\nconst RolesContent = () => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { data: { results } = { results: [] } } = useRoles(courseId);\n const isCCXCoachEnabled = !!results?.find(({ role }: Role) => role === 'ccx_coach');\n\n return (\n <div className=\"mt-4\">\n {\n rolesOrder.map((role) => (\n <div key={role} className=\"mb-4\">\n <h4 className=\"text-primary-500\">{intl.formatMessage(messages[role])}</h4>\n <p className=\"text-gray-700\">{intl.formatMessage(messages[`${role}Description`])}</p>\n </div>\n ))\n }\n {\n isCCXCoachEnabled && (\n <div className=\"mb-4\">\n <h4 className=\"text-primary-500\">{intl.formatMessage(messages.ccxCoach)}</h4>\n <p className=\"text-gray-700\">{intl.formatMessage(messages.ccxCoachDescription)}</p>\n </div>\n )\n }\n </div>\n );\n};\n\nexport default RolesContent;\n"]}
@@ -0,0 +1,6 @@
1
+ import { DataList } from '../../types';
2
+ import { TeamMembersResponse, CourseTeamMember, CourseTeamMemberQueryParams, Role } from '../../courseTeam/types';
3
+ export declare const getTeamMembers: (courseId: string, params: CourseTeamMemberQueryParams) => Promise<DataList<CourseTeamMember>>;
4
+ export declare const getRoles: (courseId: string) => Promise<Omit<DataList<Role>, "numPages" | "count">>;
5
+ export declare const addTeamMember: (courseId: string, identifiers: string[], role: string) => Promise<TeamMembersResponse>;
6
+ export declare const removeTeamMember: (courseId: string, identifier: string, roles: string[]) => Promise<TeamMembersResponse>;
@@ -0,0 +1,38 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';
11
+ import { getApiBaseUrl } from '../../data/api';
12
+ export const getTeamMembers = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
13
+ const queryParams = new URLSearchParams({
14
+ page: (params.page + 1).toString(),
15
+ page_size: params.pageSize.toString(),
16
+ });
17
+ if (params.emailOrUsername) {
18
+ queryParams.append('email_or_username', params.emailOrUsername);
19
+ }
20
+ if (params.role) {
21
+ queryParams.append('role', params.role);
22
+ }
23
+ const { data } = yield getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team?${queryParams.toString()}`);
24
+ return camelCaseObject(data);
25
+ });
26
+ export const getRoles = (courseId) => __awaiter(void 0, void 0, void 0, function* () {
27
+ const { data } = yield getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/roles`);
28
+ return camelCaseObject(data);
29
+ });
30
+ export const addTeamMember = (courseId, identifiers, role) => __awaiter(void 0, void 0, void 0, function* () {
31
+ const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team`, { identifiers, role });
32
+ return camelCaseObject(data);
33
+ });
34
+ export const removeTeamMember = (courseId, identifier, roles) => __awaiter(void 0, void 0, void 0, function* () {
35
+ const { data } = yield getAuthenticatedHttpClient().delete(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/${identifier}`, { data: { roles } });
36
+ return camelCaseObject(data);
37
+ });
38
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/courseTeam/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI9C,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAgB,EAChB,MAAmC,EACE,EAAE;IACvC,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,mBAAmB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,SAAS,WAAW,CAAC,QAAQ,EAAE,EAAE,CAC1F,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAO,QAAgB,EAAuD,EAAE;IACtG,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,aAAa,CACtE,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAO,QAAgB,EAAE,WAAqB,EAAE,IAAY,EAAgC,EAAE;IACzH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,OAAO,EAC/D,EAAE,WAAW,EAAE,IAAI,EAAE,CACtB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAO,QAAgB,EAAE,UAAkB,EAAE,KAAe,EAAgC,EAAE;IAC5H,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,MAAM,CACxD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,SAAS,UAAU,EAAE,EAC7E,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CACpB,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC","sourcesContent":["import { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { DataList } from '@src/types';\nimport { TeamMembersResponse, CourseTeamMember, CourseTeamMemberQueryParams, Role } from '@src/courseTeam/types';\n\nexport const getTeamMembers = async (\n courseId: string,\n params: CourseTeamMemberQueryParams\n): Promise<DataList<CourseTeamMember>> => {\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('email_or_username', params.emailOrUsername);\n }\n\n if (params.role) {\n queryParams.append('role', params.role);\n }\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const getRoles = async (courseId: string): Promise<Omit<DataList<Role>, 'numPages' | 'count'>> => {\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/roles`\n );\n return camelCaseObject(data);\n};\n\nexport const addTeamMember = async (courseId: string, identifiers: string[], role: string): Promise<TeamMembersResponse> => {\n const { data } = await getAuthenticatedHttpClient().post(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team`,\n { identifiers, role }\n );\n return camelCaseObject(data);\n};\n\nexport const removeTeamMember = async (courseId: string, identifier: string, roles: string[]): Promise<TeamMembersResponse> => {\n const { data } = await getAuthenticatedHttpClient().delete(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/team/${identifier}`,\n { data: { roles } }\n );\n return camelCaseObject(data);\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { CourseTeamMemberQueryParams } from '../../courseTeam/types';
2
+ export declare const useTeamMembers: (courseId: string, params: CourseTeamMemberQueryParams) => import("@tanstack/react-query").UseQueryResult<import("../../types").DataList<import("../../courseTeam/types").CourseTeamMember>, Error>;
3
+ export declare const useRoles: (courseId: string) => import("@tanstack/react-query").UseQueryResult<Omit<import("../../types").DataList<import("../../courseTeam/types").Role>, "count" | "numPages">, Error>;
4
+ export declare const useAddTeamMember: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../courseTeam/types").TeamMembersResponse, Error, {
5
+ identifiers: string[];
6
+ role: string;
7
+ }, unknown>;
8
+ export declare const useRemoveTeamMember: (courseId: string) => import("@tanstack/react-query").UseMutationResult<import("../../courseTeam/types").TeamMembersResponse, Error, {
9
+ identifier: string;
10
+ roles: string[];
11
+ }, unknown>;
@@ -0,0 +1,32 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { addTeamMember, getRoles, getTeamMembers, removeTeamMember } from '../../courseTeam/data/api';
3
+ import { courseTeamQueryKeys } from '../../courseTeam/data/queryKeys';
4
+ export const useTeamMembers = (courseId, params) => (useQuery({
5
+ queryKey: courseTeamQueryKeys.byCoursePaginated(courseId, params),
6
+ queryFn: () => getTeamMembers(courseId, params),
7
+ enabled: !!courseId,
8
+ }));
9
+ export const useRoles = (courseId) => (useQuery({
10
+ queryKey: courseTeamQueryKeys.roles(courseId),
11
+ queryFn: () => getRoles(courseId),
12
+ enabled: !!courseId,
13
+ }));
14
+ export const useAddTeamMember = (courseId) => {
15
+ const queryClient = useQueryClient();
16
+ return (useMutation({
17
+ mutationFn: ({ identifiers, role }) => addTeamMember(courseId, identifiers, role),
18
+ onSuccess: () => {
19
+ queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });
20
+ }
21
+ }));
22
+ };
23
+ export const useRemoveTeamMember = (courseId) => {
24
+ const queryClient = useQueryClient();
25
+ return (useMutation({
26
+ mutationFn: ({ identifier, roles }) => removeTeamMember(courseId, identifier, roles),
27
+ onSuccess: () => {
28
+ queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });
29
+ }
30
+ }));
31
+ };
32
+ //# sourceMappingURL=apiHook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/courseTeam/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAGrE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,MAAmC,EAAE,EAAE,CAAC,CACvF,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACjE,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,QAAQ,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAC5C,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7C,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACnD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAA2C,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC;QAC1H,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC,CACD,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,EAAE;IACtD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC;QAClB,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAA2C,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC;QAC7H,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC,CACD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { addTeamMember, getRoles, getTeamMembers, removeTeamMember } from '@src/courseTeam/data/api';\nimport { courseTeamQueryKeys } from '@src/courseTeam/data/queryKeys';\nimport { CourseTeamMemberQueryParams } from '@src/courseTeam/types';\n\nexport const useTeamMembers = (courseId: string, params: CourseTeamMemberQueryParams) => (\n useQuery({\n queryKey: courseTeamQueryKeys.byCoursePaginated(courseId, params),\n queryFn: () => getTeamMembers(courseId, params),\n enabled: !!courseId,\n })\n);\n\nexport const useRoles = (courseId: string) => (\n useQuery({\n queryKey: courseTeamQueryKeys.roles(courseId),\n queryFn: () => getRoles(courseId),\n enabled: !!courseId,\n })\n);\n\nexport const useAddTeamMember = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: ({ identifiers, role }: { identifiers: string[], role: string }) => addTeamMember(courseId, identifiers, role),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });\n }\n })\n );\n};\n\nexport const useRemoveTeamMember = (courseId: string) => {\n const queryClient = useQueryClient();\n return (useMutation({\n mutationFn: ({ identifier, roles }: { identifier: string, roles: string[] }) => removeTeamMember(courseId, identifier, roles),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: courseTeamQueryKeys.byCourse(courseId) });\n }\n })\n );\n};\n"]}
@@ -0,0 +1,7 @@
1
+ import { CourseTeamMemberQueryParams } from '../../courseTeam/types';
2
+ export declare const courseTeamQueryKeys: {
3
+ all: readonly ["org.openedx.frontend.app.instructorDashboard", "courseTeam"];
4
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "courseTeam", string];
5
+ byCoursePaginated: (courseId: string, params: CourseTeamMemberQueryParams) => readonly ["org.openedx.frontend.app.instructorDashboard", "courseTeam", string, number, number, string, string];
6
+ roles: (courseId: string) => readonly ["org.openedx.frontend.app.instructorDashboard", "courseTeam", string, "roles"];
7
+ };
@@ -0,0 +1,14 @@
1
+ import { appId } from '../../constants';
2
+ export const courseTeamQueryKeys = {
3
+ all: [appId, 'courseTeam'],
4
+ byCourse: (courseId) => [...courseTeamQueryKeys.all, courseId],
5
+ byCoursePaginated: (courseId, params) => [
6
+ ...courseTeamQueryKeys.byCourse(courseId),
7
+ params.page,
8
+ params.pageSize,
9
+ params.emailOrUsername || '',
10
+ params.role || ''
11
+ ],
12
+ roles: (courseId) => [...courseTeamQueryKeys.byCourse(courseId), 'roles'],
13
+ };
14
+ //# sourceMappingURL=queryKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/courseTeam/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,CAAU;IACnC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,mBAAmB,CAAC,GAAG,EAAE,QAAQ,CAAU;IAC/E,iBAAiB,EAAE,CACjB,QAAgB,EAChB,MAAmC,EACnC,EAAE,CAAC;QACH,GAAG,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzC,MAAM,CAAC,IAAI;QACX,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,eAAe,IAAI,EAAE;QAC5B,MAAM,CAAC,IAAI,IAAI,EAAE;KACT;IACV,KAAK,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAU;CAC3F,CAAC","sourcesContent":["import { appId } from '@src/constants';\nimport { CourseTeamMemberQueryParams } from '@src/courseTeam/types';\n\nexport const courseTeamQueryKeys = {\n all: [appId, 'courseTeam'] as const,\n byCourse: (courseId: string) => [...courseTeamQueryKeys.all, courseId] as const,\n byCoursePaginated: (\n courseId: string,\n params: CourseTeamMemberQueryParams\n ) => [\n ...courseTeamQueryKeys.byCourse(courseId),\n params.page,\n params.pageSize,\n params.emailOrUsername || '',\n params.role || ''\n ] as const,\n roles: (courseId: string) => [...courseTeamQueryKeys.byCourse(courseId), 'roles'] as const,\n};\n"]}