@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.0

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 (299) hide show
  1. package/LICENSE +661 -0
  2. package/README.rst +235 -0
  3. package/dist/Main.d.ts +3 -0
  4. package/dist/Main.js +13 -0
  5. package/dist/Main.js.map +1 -0
  6. package/dist/app.d.ts +3 -0
  7. package/dist/app.js +18 -0
  8. package/dist/app.js.map +1 -0
  9. package/dist/app.scss +10 -0
  10. package/dist/certificates/CertificatesPage.d.ts +2 -0
  11. package/dist/certificates/CertificatesPage.js +6 -0
  12. package/dist/certificates/CertificatesPage.js.map +1 -0
  13. package/dist/cohorts/CohortsPage.d.ts +3 -0
  14. package/dist/cohorts/CohortsPage.js +41 -0
  15. package/dist/cohorts/CohortsPage.js.map +1 -0
  16. package/dist/cohorts/CohortsPage.scss +14 -0
  17. package/dist/cohorts/components/CohortCard.d.ts +6 -0
  18. package/dist/cohorts/components/CohortCard.js +53 -0
  19. package/dist/cohorts/components/CohortCard.js.map +1 -0
  20. package/dist/cohorts/components/CohortContext.d.ts +14 -0
  21. package/dist/cohorts/components/CohortContext.js +46 -0
  22. package/dist/cohorts/components/CohortContext.js.map +1 -0
  23. package/dist/cohorts/components/CohortsForm.d.ts +11 -0
  24. package/dist/cohorts/components/CohortsForm.js +58 -0
  25. package/dist/cohorts/components/CohortsForm.js.map +1 -0
  26. package/dist/cohorts/components/DisableCohortsModal.d.ts +7 -0
  27. package/dist/cohorts/components/DisableCohortsModal.js +10 -0
  28. package/dist/cohorts/components/DisableCohortsModal.js.map +1 -0
  29. package/dist/cohorts/components/DisabledCohortsView.d.ts +5 -0
  30. package/dist/cohorts/components/DisabledCohortsView.js +10 -0
  31. package/dist/cohorts/components/DisabledCohortsView.js.map +1 -0
  32. package/dist/cohorts/components/EnabledCohortsView.d.ts +2 -0
  33. package/dist/cohorts/components/EnabledCohortsView.js +96 -0
  34. package/dist/cohorts/components/EnabledCohortsView.js.map +1 -0
  35. package/dist/cohorts/components/ManageLearners.d.ts +2 -0
  36. package/dist/cohorts/components/ManageLearners.js +64 -0
  37. package/dist/cohorts/components/ManageLearners.js.map +1 -0
  38. package/dist/cohorts/components/SelectedCohortInfo.d.ts +2 -0
  39. package/dist/cohorts/components/SelectedCohortInfo.js +43 -0
  40. package/dist/cohorts/components/SelectedCohortInfo.js.map +1 -0
  41. package/dist/cohorts/constants.d.ts +4 -0
  42. package/dist/cohorts/constants.js +5 -0
  43. package/dist/cohorts/constants.js.map +1 -0
  44. package/dist/cohorts/data/api.d.ts +9 -0
  45. package/dist/cohorts/data/api.js +54 -0
  46. package/dist/cohorts/data/api.js.map +1 -0
  47. package/dist/cohorts/data/apiHook.d.ts +14 -0
  48. package/dist/cohorts/data/apiHook.js +64 -0
  49. package/dist/cohorts/data/apiHook.js.map +1 -0
  50. package/dist/cohorts/data/queryKeys.d.ts +7 -0
  51. package/dist/cohorts/data/queryKeys.js +9 -0
  52. package/dist/cohorts/data/queryKeys.js.map +1 -0
  53. package/dist/cohorts/messages.d.ts +233 -0
  54. package/dist/cohorts/messages.js +235 -0
  55. package/dist/cohorts/messages.js.map +1 -0
  56. package/dist/cohorts/types.d.ts +15 -0
  57. package/dist/cohorts/types.js +2 -0
  58. package/dist/cohorts/types.js.map +1 -0
  59. package/dist/components/ActionCard.d.ts +11 -0
  60. package/dist/components/ActionCard.js +7 -0
  61. package/dist/components/ActionCard.js.map +1 -0
  62. package/dist/components/CSVComponent.d.ts +10 -0
  63. package/dist/components/CSVComponent.js +21 -0
  64. package/dist/components/CSVComponent.js.map +1 -0
  65. package/dist/components/ObjectCell.d.ts +5 -0
  66. package/dist/components/ObjectCell.js +7 -0
  67. package/dist/components/ObjectCell.js.map +1 -0
  68. package/dist/components/PageNotFound.d.ts +2 -0
  69. package/dist/components/PageNotFound.js +12 -0
  70. package/dist/components/PageNotFound.js.map +1 -0
  71. package/dist/components/PendingTasks.d.ts +5 -0
  72. package/dist/components/PendingTasks.js +38 -0
  73. package/dist/components/PendingTasks.js.map +1 -0
  74. package/dist/components/SpecifyLearnerField.d.ts +5 -0
  75. package/dist/components/SpecifyLearnerField.js +10 -0
  76. package/dist/components/SpecifyLearnerField.js.map +1 -0
  77. package/dist/components/messages.d.ts +108 -0
  78. package/dist/components/messages.js +110 -0
  79. package/dist/components/messages.js.map +1 -0
  80. package/dist/constants.d.ts +1 -0
  81. package/dist/constants.js +2 -0
  82. package/dist/constants.js.map +1 -0
  83. package/dist/courseInfo/CourseInfoPage.d.ts +2 -0
  84. package/dist/courseInfo/CourseInfoPage.js +7 -0
  85. package/dist/courseInfo/CourseInfoPage.js.map +1 -0
  86. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentCounter.d.ts +8 -0
  87. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentCounter.js +13 -0
  88. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentCounter.js.map +1 -0
  89. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentSummary.d.ts +2 -0
  90. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentSummary.js +24 -0
  91. package/dist/courseInfo/components/EnrollmentSummary/EnrollmentSummary.js.map +1 -0
  92. package/dist/courseInfo/components/EnrollmentSummary/index.d.ts +2 -0
  93. package/dist/courseInfo/components/EnrollmentSummary/index.js +3 -0
  94. package/dist/courseInfo/components/EnrollmentSummary/index.js.map +1 -0
  95. package/dist/courseInfo/components/EnrollmentSummary/messages.d.ts +83 -0
  96. package/dist/courseInfo/components/EnrollmentSummary/messages.js +85 -0
  97. package/dist/courseInfo/components/EnrollmentSummary/messages.js.map +1 -0
  98. package/dist/courseInfo/components/EnrollmentSummary/utils.d.ts +1 -0
  99. package/dist/courseInfo/components/EnrollmentSummary/utils.js +9 -0
  100. package/dist/courseInfo/components/EnrollmentSummary/utils.js.map +1 -0
  101. package/dist/courseInfo/components/generalCourseInfo/GeneralCourseInfo.d.ts +2 -0
  102. package/dist/courseInfo/components/generalCourseInfo/GeneralCourseInfo.js +46 -0
  103. package/dist/courseInfo/components/generalCourseInfo/GeneralCourseInfo.js.map +1 -0
  104. package/dist/courseInfo/components/generalCourseInfo/StatusBadge.d.ts +5 -0
  105. package/dist/courseInfo/components/generalCourseInfo/StatusBadge.js +15 -0
  106. package/dist/courseInfo/components/generalCourseInfo/StatusBadge.js.map +1 -0
  107. package/dist/courseInfo/components/generalCourseInfo/index.d.ts +1 -0
  108. package/dist/courseInfo/components/generalCourseInfo/index.js +2 -0
  109. package/dist/courseInfo/components/generalCourseInfo/index.js.map +1 -0
  110. package/dist/courseInfo/components/generalCourseInfo/messages.d.ts +8 -0
  111. package/dist/courseInfo/components/generalCourseInfo/messages.js +10 -0
  112. package/dist/courseInfo/components/generalCourseInfo/messages.js.map +1 -0
  113. package/dist/courseInfo/messages.d.ts +8 -0
  114. package/dist/courseInfo/messages.js +10 -0
  115. package/dist/courseInfo/messages.js.map +1 -0
  116. package/dist/courseInfo/types.d.ts +27 -0
  117. package/dist/courseInfo/types.js +2 -0
  118. package/dist/courseInfo/types.js.map +1 -0
  119. package/dist/courseTeam/CourseTeamPage.d.ts +2 -0
  120. package/dist/courseTeam/CourseTeamPage.js +6 -0
  121. package/dist/courseTeam/CourseTeamPage.js.map +1 -0
  122. package/dist/data/api.d.ts +14 -0
  123. package/dist/data/api.js +33 -0
  124. package/dist/data/api.js.map +1 -0
  125. package/dist/data/apiHook.d.ts +4 -0
  126. package/dist/data/apiHook.js +28 -0
  127. package/dist/data/apiHook.js.map +1 -0
  128. package/dist/data/queryKeys.d.ts +8 -0
  129. package/dist/data/queryKeys.js +10 -0
  130. package/dist/data/queryKeys.js.map +1 -0
  131. package/dist/dataDownloads/DataDownloadsPage.d.ts +2 -0
  132. package/dist/dataDownloads/DataDownloadsPage.js +162 -0
  133. package/dist/dataDownloads/DataDownloadsPage.js.map +1 -0
  134. package/dist/dataDownloads/components/DataDownloadTable.d.ts +8 -0
  135. package/dist/dataDownloads/components/DataDownloadTable.js +42 -0
  136. package/dist/dataDownloads/components/DataDownloadTable.js.map +1 -0
  137. package/dist/dataDownloads/components/DownloadLinkCell.d.ts +6 -0
  138. package/dist/dataDownloads/components/DownloadLinkCell.js +13 -0
  139. package/dist/dataDownloads/components/DownloadLinkCell.js.map +1 -0
  140. package/dist/dataDownloads/components/GenerateReports.d.ts +8 -0
  141. package/dist/dataDownloads/components/GenerateReports.js +20 -0
  142. package/dist/dataDownloads/components/GenerateReports.js.map +1 -0
  143. package/dist/dataDownloads/components/ReportNameCell.d.ts +3 -0
  144. package/dist/dataDownloads/components/ReportNameCell.js +6 -0
  145. package/dist/dataDownloads/components/ReportNameCell.js.map +1 -0
  146. package/dist/dataDownloads/data/api.d.ts +2 -0
  147. package/dist/dataDownloads/data/api.js +23 -0
  148. package/dist/dataDownloads/data/api.js.map +1 -0
  149. package/dist/dataDownloads/data/apiHook.d.ts +7 -0
  150. package/dist/dataDownloads/data/apiHook.js +22 -0
  151. package/dist/dataDownloads/data/apiHook.js.map +1 -0
  152. package/dist/dataDownloads/data/queryKeys.d.ts +5 -0
  153. package/dist/dataDownloads/data/queryKeys.js +7 -0
  154. package/dist/dataDownloads/data/queryKeys.js.map +1 -0
  155. package/dist/dataDownloads/messages.d.ts +338 -0
  156. package/dist/dataDownloads/messages.js +341 -0
  157. package/dist/dataDownloads/messages.js.map +1 -0
  158. package/dist/dataDownloads/types.d.ts +8 -0
  159. package/dist/dataDownloads/types.js +2 -0
  160. package/dist/dataDownloads/types.js.map +1 -0
  161. package/dist/dataDownloads/utils.d.ts +26 -0
  162. package/dist/dataDownloads/utils.js +49 -0
  163. package/dist/dataDownloads/utils.js.map +1 -0
  164. package/dist/dateExtensions/DateExtensionsPage.d.ts +2 -0
  165. package/dist/dateExtensions/DateExtensionsPage.js +87 -0
  166. package/dist/dateExtensions/DateExtensionsPage.js.map +1 -0
  167. package/dist/dateExtensions/components/AddExtensionModal.d.ts +13 -0
  168. package/dist/dateExtensions/components/AddExtensionModal.js +34 -0
  169. package/dist/dateExtensions/components/AddExtensionModal.js.map +1 -0
  170. package/dist/dateExtensions/components/DateExtensionsList.d.ts +7 -0
  171. package/dist/dateExtensions/components/DateExtensionsList.js +103 -0
  172. package/dist/dateExtensions/components/DateExtensionsList.js.map +1 -0
  173. package/dist/dateExtensions/components/ResetExtensionsModal.d.ts +10 -0
  174. package/dist/dateExtensions/components/ResetExtensionsModal.js +10 -0
  175. package/dist/dateExtensions/components/ResetExtensionsModal.js.map +1 -0
  176. package/dist/dateExtensions/components/SelectGradedSubsection.d.ts +8 -0
  177. package/dist/dateExtensions/components/SelectGradedSubsection.js +15 -0
  178. package/dist/dateExtensions/components/SelectGradedSubsection.js.map +1 -0
  179. package/dist/dateExtensions/data/api.d.ts +6 -0
  180. package/dist/dateExtensions/data/api.js +40 -0
  181. package/dist/dateExtensions/data/api.js.map +1 -0
  182. package/dist/dateExtensions/data/apiHook.d.ts +11 -0
  183. package/dist/dateExtensions/data/apiHook.js +31 -0
  184. package/dist/dateExtensions/data/apiHook.js.map +1 -0
  185. package/dist/dateExtensions/data/queryKeys.d.ts +10 -0
  186. package/dist/dateExtensions/data/queryKeys.js +17 -0
  187. package/dist/dateExtensions/data/queryKeys.js.map +1 -0
  188. package/dist/dateExtensions/messages.d.ts +128 -0
  189. package/dist/dateExtensions/messages.js +130 -0
  190. package/dist/dateExtensions/messages.js.map +1 -0
  191. package/dist/dateExtensions/types.d.ts +24 -0
  192. package/dist/dateExtensions/types.js +2 -0
  193. package/dist/dateExtensions/types.js.map +1 -0
  194. package/dist/enrollments/EnrollmentsPage.d.ts +2 -0
  195. package/dist/enrollments/EnrollmentsPage.js +32 -0
  196. package/dist/enrollments/EnrollmentsPage.js.map +1 -0
  197. package/dist/enrollments/components/EnrollmentStatusModal.d.ts +6 -0
  198. package/dist/enrollments/components/EnrollmentStatusModal.js +23 -0
  199. package/dist/enrollments/components/EnrollmentStatusModal.js.map +1 -0
  200. package/dist/enrollments/components/EnrollmentsList.d.ts +6 -0
  201. package/dist/enrollments/components/EnrollmentsList.js +99 -0
  202. package/dist/enrollments/components/EnrollmentsList.js.map +1 -0
  203. package/dist/enrollments/components/UnenrollModal.d.ts +8 -0
  204. package/dist/enrollments/components/UnenrollModal.js +7 -0
  205. package/dist/enrollments/components/UnenrollModal.js.map +1 -0
  206. package/dist/enrollments/data/api.d.ts +4 -0
  207. package/dist/enrollments/data/api.js +32 -0
  208. package/dist/enrollments/data/api.js.map +1 -0
  209. package/dist/enrollments/data/apiHook.d.ts +3 -0
  210. package/dist/enrollments/data/apiHook.js +14 -0
  211. package/dist/enrollments/data/apiHook.js.map +1 -0
  212. package/dist/enrollments/data/queryKeys.d.ts +7 -0
  213. package/dist/enrollments/data/queryKeys.js +8 -0
  214. package/dist/enrollments/data/queryKeys.js.map +1 -0
  215. package/dist/enrollments/messages.d.ts +108 -0
  216. package/dist/enrollments/messages.js +110 -0
  217. package/dist/enrollments/messages.js.map +1 -0
  218. package/dist/enrollments/types.d.ts +15 -0
  219. package/dist/enrollments/types.js +2 -0
  220. package/dist/enrollments/types.js.map +1 -0
  221. package/dist/grading/GradingPage.d.ts +2 -0
  222. package/dist/grading/GradingPage.js +6 -0
  223. package/dist/grading/GradingPage.js.map +1 -0
  224. package/dist/hooks/useDebouncedFilter.d.ts +16 -0
  225. package/dist/hooks/useDebouncedFilter.js +27 -0
  226. package/dist/hooks/useDebouncedFilter.js.map +1 -0
  227. package/dist/i18n/index.d.ts +25 -0
  228. package/dist/i18n/index.js +26 -0
  229. package/dist/i18n/index.js.map +1 -0
  230. package/dist/index.d.ts +3 -0
  231. package/dist/index.js +4 -0
  232. package/dist/index.js.map +1 -0
  233. package/dist/instructorNav/InstructorNav.d.ts +8 -0
  234. package/dist/instructorNav/InstructorNav.js +42 -0
  235. package/dist/instructorNav/InstructorNav.js.map +1 -0
  236. package/dist/openResponses/OpenResponsesPage.d.ts +2 -0
  237. package/dist/openResponses/OpenResponsesPage.js +8 -0
  238. package/dist/openResponses/OpenResponsesPage.js.map +1 -0
  239. package/dist/openResponses/components/DetailAssessmentsList.d.ts +2 -0
  240. package/dist/openResponses/components/DetailAssessmentsList.js +44 -0
  241. package/dist/openResponses/components/DetailAssessmentsList.js.map +1 -0
  242. package/dist/openResponses/components/OpenResponsesSummary.d.ts +2 -0
  243. package/dist/openResponses/components/OpenResponsesSummary.js +30 -0
  244. package/dist/openResponses/components/OpenResponsesSummary.js.map +1 -0
  245. package/dist/openResponses/data/api.d.ts +4 -0
  246. package/dist/openResponses/data/api.js +23 -0
  247. package/dist/openResponses/data/api.js.map +1 -0
  248. package/dist/openResponses/data/apiHook.d.ts +2 -0
  249. package/dist/openResponses/data/apiHook.js +14 -0
  250. package/dist/openResponses/data/apiHook.js.map +1 -0
  251. package/dist/openResponses/data/queryKeys.d.ts +6 -0
  252. package/dist/openResponses/data/queryKeys.js +8 -0
  253. package/dist/openResponses/data/queryKeys.js.map +1 -0
  254. package/dist/openResponses/messages.d.ts +83 -0
  255. package/dist/openResponses/messages.js +85 -0
  256. package/dist/openResponses/messages.js.map +1 -0
  257. package/dist/openResponses/types.d.ts +12 -0
  258. package/dist/openResponses/types.js +2 -0
  259. package/dist/openResponses/types.js.map +1 -0
  260. package/dist/pageWrapper/PageWrapper.d.ts +4 -0
  261. package/dist/pageWrapper/PageWrapper.js +11 -0
  262. package/dist/pageWrapper/PageWrapper.js.map +1 -0
  263. package/dist/pageWrapper/messages.d.ts +8 -0
  264. package/dist/pageWrapper/messages.js +10 -0
  265. package/dist/pageWrapper/messages.js.map +1 -0
  266. package/dist/providers/AlertProvider.d.ts +41 -0
  267. package/dist/providers/AlertProvider.js +117 -0
  268. package/dist/providers/AlertProvider.js.map +1 -0
  269. package/dist/providers/QueryProvider.d.ts +6 -0
  270. package/dist/providers/QueryProvider.js +16 -0
  271. package/dist/providers/QueryProvider.js.map +1 -0
  272. package/dist/providers.d.ts +3 -0
  273. package/dist/providers.js +8 -0
  274. package/dist/providers.js.map +1 -0
  275. package/dist/routes.d.ts +20 -0
  276. package/dist/routes.js +72 -0
  277. package/dist/routes.js.map +1 -0
  278. package/dist/slots/PlaceholderSlot/PlaceholderSlot.d.ts +1 -0
  279. package/dist/slots/PlaceholderSlot/PlaceholderSlot.js +6 -0
  280. package/dist/slots/PlaceholderSlot/PlaceholderSlot.js.map +1 -0
  281. package/dist/slots/SlotUtils.d.ts +3 -0
  282. package/dist/slots/SlotUtils.js +17 -0
  283. package/dist/slots/SlotUtils.js.map +1 -0
  284. package/dist/slots.d.ts +3 -0
  285. package/dist/slots.js +3 -0
  286. package/dist/slots.js.map +1 -0
  287. package/dist/specialExams/SpecialExamsPage.d.ts +2 -0
  288. package/dist/specialExams/SpecialExamsPage.js +6 -0
  289. package/dist/specialExams/SpecialExamsPage.js.map +1 -0
  290. package/dist/testUtils.d.ts +4 -0
  291. package/dist/testUtils.js +24 -0
  292. package/dist/testUtils.js.map +1 -0
  293. package/dist/types/index.d.ts +40 -0
  294. package/dist/types/index.js +4 -0
  295. package/dist/types/index.js.map +1 -0
  296. package/dist/utils/formatters.d.ts +1 -0
  297. package/dist/utils/formatters.js +12 -0
  298. package/dist/utils/formatters.js.map +1 -0
  299. package/package.json +79 -0
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { ActionRow, Button, Form, FormControl, FormGroup, FormLabel, ModalDialog } from '@openedx/paragon';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import SpecifyLearnerField from '../../components/SpecifyLearnerField';
6
+ import messages from '../messages';
7
+ import SelectGradedSubsection from './SelectGradedSubsection';
8
+ const AddExtensionModal = ({ isOpen, title, onClose, onSubmit }) => {
9
+ const intl = useIntl();
10
+ const [formData, setFormData] = useState({
11
+ emailOrUsername: '',
12
+ blockId: '',
13
+ dueDate: '',
14
+ dueTime: '',
15
+ reason: '',
16
+ });
17
+ const handleSubmit = (event) => {
18
+ event.preventDefault();
19
+ const { emailOrUsername, blockId, dueDate, dueTime, reason } = formData;
20
+ onSubmit({
21
+ emailOrUsername,
22
+ blockId,
23
+ dueDatetime: new Date(`${dueDate}T${dueTime}`).toISOString(),
24
+ reason
25
+ });
26
+ };
27
+ const onChange = (event) => {
28
+ const { name, value } = event.target;
29
+ setFormData((prevData) => (Object.assign(Object.assign({}, prevData), { [name]: value })));
30
+ };
31
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, title: title, isOverflowVisible: false, size: "xl", children: [_jsx(ModalDialog.Header, { className: "p-3 pl-4 border-bottom", children: _jsx(ModalDialog.Title, { as: "h3", className: "m-0", children: title }) }), _jsxs(Form, { onSubmit: handleSubmit, className: "position-relative overflow-auto", children: [_jsx(ModalDialog.Body, { children: _jsxs("div", { className: "pt-3", children: [_jsx("p", { children: intl.formatMessage(messages.extensionInstructions) }), _jsx("div", { className: "container-fluid border-bottom mb-4.5 pb-3", children: _jsxs("div", { className: "row", children: [_jsx("div", { className: "col-sm-12 col-md-6", children: _jsx(SpecifyLearnerField, { onChange: onChange }) }), _jsx("div", { className: "col-sm-12 col-md-4", children: _jsx(SelectGradedSubsection, { label: intl.formatMessage(messages.selectGradedSubsection), placeholder: intl.formatMessage(messages.selectGradedSubsection), onChange: onChange }) })] }) }), _jsxs("div", { children: [_jsx("h4", { children: intl.formatMessage(messages.defineExtension) }), _jsxs(FormGroup, { size: "sm", children: [_jsxs(FormLabel, { children: [intl.formatMessage(messages.extensionDate), ":"] }), _jsxs("div", { className: "d-md-flex w-md-50 align-items-center", children: [_jsx(FormControl, { name: "dueDate", type: "date", size: "md", onChange: onChange }), _jsx(FormControl, { name: "dueTime", type: "time", size: "md", className: "mt-sm-3 mt-md-0", onChange: onChange })] })] }), _jsxs(FormGroup, { className: "mt-3", size: "sm", children: [_jsxs(FormLabel, { children: [intl.formatMessage(messages.reasonForExtension), ":"] }), _jsx(FormControl, { name: "reason", placeholder: intl.formatMessage(messages.reasonForExtension), size: "md", onChange: onChange })] })] })] }) }), _jsx(ModalDialog.Footer, { className: "p-4 border-top", children: _jsxs(ActionRow, { children: [_jsx(Button, { variant: "tertiary", onClick: onClose, children: intl.formatMessage(messages.cancel) }), _jsx(Button, { type: "submit", children: intl.formatMessage(messages.addExtension) })] }) })] })] }));
32
+ };
33
+ export default AddExtensionModal;
34
+ //# sourceMappingURL=AddExtensionModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddExtensionModal.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/AddExtensionModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { ActionRow, Button, Form, FormControl, FormGroup, FormLabel, ModalDialog } from '@openedx/paragon';\nimport { useIntl } from '@openedx/frontend-base';\nimport SpecifyLearnerField from '../../components/SpecifyLearnerField';\nimport messages from '../messages';\nimport SelectGradedSubsection from './SelectGradedSubsection';\n\ninterface AddExtensionModalProps {\n isOpen: boolean,\n title: string,\n onClose: () => void,\n onSubmit: ({ emailOrUsername, blockId, dueDatetime, reason }: {\n emailOrUsername: string,\n blockId: string,\n dueDatetime: string,\n reason: string,\n }) => void,\n}\n\nconst AddExtensionModal = ({ isOpen, title, onClose, onSubmit }: AddExtensionModalProps) => {\n const intl = useIntl();\n const [formData, setFormData] = useState({\n emailOrUsername: '',\n blockId: '',\n dueDate: '',\n dueTime: '',\n reason: '',\n });\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const { emailOrUsername, blockId, dueDate, dueTime, reason } = formData;\n onSubmit({\n emailOrUsername,\n blockId,\n dueDatetime: new Date(`${dueDate}T${dueTime}`).toISOString(),\n reason\n });\n };\n\n const onChange = (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {\n const { name, value } = event.target;\n setFormData((prevData) => ({\n ...prevData,\n [name]: value,\n }));\n };\n\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} title={title} isOverflowVisible={false} size=\"xl\">\n <ModalDialog.Header className=\"p-3 pl-4 border-bottom\">\n <ModalDialog.Title as=\"h3\" className=\"m-0\">\n {title}\n </ModalDialog.Title>\n </ModalDialog.Header>\n <Form onSubmit={handleSubmit} className=\"position-relative overflow-auto\">\n <ModalDialog.Body>\n <div className=\"pt-3\">\n <p>{intl.formatMessage(messages.extensionInstructions)}</p>\n <div className=\"container-fluid border-bottom mb-4.5 pb-3\">\n <div className=\"row\">\n <div className=\"col-sm-12 col-md-6\">\n <SpecifyLearnerField onChange={onChange} />\n </div>\n <div className=\"col-sm-12 col-md-4\">\n <SelectGradedSubsection\n label={intl.formatMessage(messages.selectGradedSubsection)}\n placeholder={intl.formatMessage(messages.selectGradedSubsection)}\n onChange={onChange}\n />\n </div>\n </div>\n </div>\n <div>\n <h4>{intl.formatMessage(messages.defineExtension)}</h4>\n <FormGroup size=\"sm\">\n <FormLabel>\n {intl.formatMessage(messages.extensionDate)}:\n </FormLabel>\n <div className=\"d-md-flex w-md-50 align-items-center\">\n <FormControl name=\"dueDate\" type=\"date\" size=\"md\" onChange={onChange} />\n <FormControl name=\"dueTime\" type=\"time\" size=\"md\" className=\"mt-sm-3 mt-md-0\" onChange={onChange} />\n </div>\n </FormGroup>\n <FormGroup className=\"mt-3\" size=\"sm\">\n <FormLabel>\n {intl.formatMessage(messages.reasonForExtension)}:\n </FormLabel>\n <FormControl name=\"reason\" placeholder={intl.formatMessage(messages.reasonForExtension)} size=\"md\" onChange={onChange} />\n </FormGroup>\n </div>\n </div>\n </ModalDialog.Body>\n <ModalDialog.Footer className=\"p-4 border-top\">\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onClose}>{intl.formatMessage(messages.cancel)}</Button>\n <Button type=\"submit\">{intl.formatMessage(messages.addExtension)}</Button>\n </ActionRow>\n </ModalDialog.Footer>\n </Form>\n </ModalDialog>\n );\n};\n\nexport default AddExtensionModal;\n"]}
@@ -0,0 +1,7 @@
1
+ import { LearnerDateExtension } from '../types';
2
+ export interface DateExtensionListProps {
3
+ onResetExtensions?: (user: LearnerDateExtension) => void;
4
+ onClickAdd?: () => void;
5
+ }
6
+ declare const DateExtensionsList: ({ onResetExtensions, onClickAdd, }: DateExtensionListProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default DateExtensionsList;
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useParams } from 'react-router-dom';
4
+ import { useIntl } from '@openedx/frontend-base';
5
+ import { Button, DataTable, FormControl, Icon } from '@openedx/paragon';
6
+ import messages from '../messages';
7
+ import { useDateExtensions } from '../data/apiHook';
8
+ import { Search } from '@openedx/paragon/icons';
9
+ import SelectGradedSubsection from './SelectGradedSubsection';
10
+ import { useDebouncedFilter } from '../../hooks/useDebouncedFilter';
11
+ const DATE_EXTENSIONS_PAGE_SIZE = 25;
12
+ const UsernameFilter = ({ column: { filterValue, setFilter } }) => {
13
+ const intl = useIntl();
14
+ const { inputValue, handleChange } = useDebouncedFilter({
15
+ filterValue,
16
+ setFilter,
17
+ });
18
+ const handleInputChange = (e) => {
19
+ handleChange(e.target.value);
20
+ };
21
+ return (_jsx(FormControl, { className: "mb-0", onChange: handleInputChange, placeholder: intl.formatMessage(messages.searchLearnerPlaceholder), trailingElement: _jsx(Icon, { src: Search }), value: inputValue }));
22
+ };
23
+ const GradedSubsectionFilter = ({ column: { filterValue, setFilter } }) => {
24
+ const intl = useIntl();
25
+ const { inputValue, handleChange } = useDebouncedFilter({
26
+ filterValue,
27
+ setFilter,
28
+ });
29
+ const handleSelectChange = (e) => {
30
+ handleChange(e.target.value);
31
+ };
32
+ return (_jsx(SelectGradedSubsection, { placeholder: intl.formatMessage(messages.allGradedSubsections), onChange: handleSelectChange, value: inputValue }));
33
+ };
34
+ const DateExtensionsList = ({ onResetExtensions = () => { }, onClickAdd = () => { }, }) => {
35
+ const intl = useIntl();
36
+ const { courseId = '' } = useParams();
37
+ const [filters, setFilters] = useState({
38
+ page: 0,
39
+ emailOrUsername: '',
40
+ blockId: '',
41
+ });
42
+ const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useDateExtensions(courseId !== null && courseId !== void 0 ? courseId : '', {
43
+ blockId: filters.blockId,
44
+ emailOrUsername: filters.emailOrUsername,
45
+ page: filters.page,
46
+ pageSize: DATE_EXTENSIONS_PAGE_SIZE,
47
+ });
48
+ const tableColumns = [
49
+ { accessor: 'username',
50
+ Header: intl.formatMessage(messages.username),
51
+ Filter: UsernameFilter,
52
+ },
53
+ { accessor: 'fullName', Header: intl.formatMessage(messages.fullname), disableFilters: true, },
54
+ { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true, },
55
+ { accessor: 'unitTitle',
56
+ Header: intl.formatMessage(messages.gradedSubsection),
57
+ Filter: GradedSubsectionFilter,
58
+ },
59
+ {
60
+ accessor: 'extendedDueDate',
61
+ Header: intl.formatMessage(messages.extendedDueDate),
62
+ Cell: ({ value }) => (intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })),
63
+ disableFilters: true,
64
+ },
65
+ ];
66
+ const additionalColumns = [{
67
+ id: 'reset',
68
+ Header: intl.formatMessage(messages.reset),
69
+ Cell: ({ row }) => (_jsx(Button, { variant: "link", size: "inline", onClick: () => onResetExtensions(row.original), children: intl.formatMessage(messages.resetExtensions) }))
70
+ }];
71
+ const handleFetchData = (data) => {
72
+ const emailOrUsernameFilter = data.filters.find((filter) => filter.id === 'username');
73
+ const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';
74
+ const blockIdFilter = data.filters.find((filter) => filter.id === 'unitTitle');
75
+ const newBlockId = blockIdFilter ? blockIdFilter.value : '';
76
+ const filterChanged = newEmailOrUsername !== filters.emailOrUsername || newBlockId !== filters.blockId;
77
+ const pageChanged = data.pageIndex !== filters.page;
78
+ // If filters changed, reset to page 0
79
+ if (filterChanged) {
80
+ setFilters({ page: 0, emailOrUsername: newEmailOrUsername, blockId: newBlockId });
81
+ }
82
+ else if (pageChanged) {
83
+ // If only page changed (filters didn't change), update page
84
+ setFilters({ page: data.pageIndex, emailOrUsername: newEmailOrUsername, blockId: newBlockId });
85
+ }
86
+ };
87
+ return (_jsxs(DataTable, { columns: tableColumns, additionalColumns: additionalColumns, data: data.results, fetchData: handleFetchData, state: {
88
+ pageIndex: filters.page,
89
+ pageSize: DATE_EXTENSIONS_PAGE_SIZE,
90
+ filters: [
91
+ {
92
+ id: 'username',
93
+ value: filters.emailOrUsername,
94
+ },
95
+ {
96
+ id: 'unitTitle',
97
+ value: filters.blockId,
98
+ }
99
+ ]
100
+ }, isFilterable: true, numBreakoutFilters: 2, isLoading: isLoading, isPaginated: true, itemCount: data.count, manualFilters: true, manualPagination: true, pageSize: DATE_EXTENSIONS_PAGE_SIZE, pageCount: data.numPages, FilterStatusComponent: DataTable.RowStatus, children: [_jsxs("div", { className: "d-flex justify-content-between align-items-start pt-1 mx-3 mb-3", children: [_jsx(DataTable.TableControlBar, {}), _jsxs(Button, { className: "mt-2.5", onClick: onClickAdd, children: ["+ ", intl.formatMessage(messages.addIndividualExtension)] })] }), _jsx(DataTable.Table, {}), _jsx(DataTable.EmptyTable, { content: intl.formatMessage(messages.noDateExtensions) }), _jsx(DataTable.TableFooter, {})] }));
101
+ };
102
+ export default DateExtensionsList;
103
+ //# sourceMappingURL=DateExtensionsList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateExtensionsList.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/DateExtensionsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Button, DataTable, FormControl, Icon } from '@openedx/paragon';\nimport messages from '../messages';\nimport { LearnerDateExtension } from '../types';\nimport { useDateExtensions } from '../data/apiHook';\nimport { Search } from '@openedx/paragon/icons';\nimport SelectGradedSubsection from './SelectGradedSubsection';\nimport { useDebouncedFilter } from '../../hooks/useDebouncedFilter';\nimport { DataTableFetchDataProps } from '@src/types';\n\nconst DATE_EXTENSIONS_PAGE_SIZE = 25;\n\nexport interface DateExtensionListProps {\n onResetExtensions?: (user: LearnerDateExtension) => void,\n onClickAdd?: () => 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.searchLearnerPlaceholder)}\n trailingElement={<Icon src={Search} />}\n value={inputValue}\n />\n );\n};\n\nconst GradedSubsectionFilter = ({ 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 handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n handleChange(e.target.value);\n };\n\n return (\n <SelectGradedSubsection\n placeholder={intl.formatMessage(messages.allGradedSubsections)}\n onChange={handleSelectChange}\n value={inputValue}\n />\n );\n};\n\nconst DateExtensionsList = ({\n onResetExtensions = () => {},\n onClickAdd = () => {},\n}: DateExtensionListProps) => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [filters, setFilters] = useState<{ page: number, emailOrUsername: string, blockId: string }>({\n page: 0,\n emailOrUsername: '',\n blockId: '',\n });\n\n const { data = { count: 0, results: [], numPages: 0 }, isLoading } = useDateExtensions(courseId ?? '', {\n blockId: filters.blockId,\n emailOrUsername: filters.emailOrUsername,\n page: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n });\n\n const tableColumns = [\n { accessor: 'username',\n Header: intl.formatMessage(messages.username),\n Filter: UsernameFilter,\n },\n { accessor: 'fullName', Header: intl.formatMessage(messages.fullname), disableFilters: true, },\n { accessor: 'email', Header: intl.formatMessage(messages.email), disableFilters: true, },\n { accessor: 'unitTitle',\n Header: intl.formatMessage(messages.gradedSubsection),\n Filter: GradedSubsectionFilter,\n },\n {\n accessor: 'extendedDueDate',\n Header: intl.formatMessage(messages.extendedDueDate),\n Cell: ({ value }: { value: string }) => (\n intl.formatDate(value, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', timeZone: 'UTC' })\n ),\n disableFilters: true,\n },\n ];\n\n const additionalColumns = [{\n id: 'reset',\n Header: intl.formatMessage(messages.reset),\n Cell: ({ row }: { row: { original: LearnerDateExtension } }) => (\n <Button\n variant=\"link\"\n size=\"inline\"\n onClick={() => onResetExtensions(row.original)}\n >\n {intl.formatMessage(messages.resetExtensions)}\n </Button>\n )\n }];\n\n const handleFetchData = (data: DataTableFetchDataProps) => {\n const emailOrUsernameFilter = data.filters.find((filter) => filter.id === 'username');\n const newEmailOrUsername = emailOrUsernameFilter ? emailOrUsernameFilter.value : '';\n const blockIdFilter = data.filters.find((filter) => filter.id === 'unitTitle');\n const newBlockId = blockIdFilter ? blockIdFilter.value : '';\n\n const filterChanged = newEmailOrUsername !== filters.emailOrUsername || newBlockId !== filters.blockId;\n const pageChanged = data.pageIndex !== filters.page;\n\n // If filters changed, reset to page 0\n if (filterChanged) {\n setFilters({ page: 0, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n } else if (pageChanged) {\n // If only page changed (filters didn't change), update page\n setFilters({ page: data.pageIndex, emailOrUsername: newEmailOrUsername, blockId: newBlockId });\n }\n };\n\n return (\n <DataTable\n columns={tableColumns}\n additionalColumns={additionalColumns}\n data={data.results}\n fetchData={handleFetchData}\n state={{\n pageIndex: filters.page,\n pageSize: DATE_EXTENSIONS_PAGE_SIZE,\n filters: [\n {\n id: 'username',\n value: filters.emailOrUsername,\n },\n {\n id: 'unitTitle',\n value: filters.blockId,\n }\n ]\n }}\n isFilterable\n numBreakoutFilters={2}\n isLoading={isLoading}\n isPaginated\n itemCount={data.count}\n manualFilters\n manualPagination\n pageSize={DATE_EXTENSIONS_PAGE_SIZE}\n pageCount={data.numPages}\n FilterStatusComponent={DataTable.RowStatus}\n >\n <div className=\"d-flex justify-content-between align-items-start pt-1 mx-3 mb-3\">\n <DataTable.TableControlBar />\n <Button className=\"mt-2.5\" onClick={onClickAdd}>+ {intl.formatMessage(messages.addIndividualExtension)}</Button>\n </div>\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noDateExtensions)} />\n <DataTable.TableFooter />\n </DataTable>\n );\n};\n\nexport default DateExtensionsList;\n"]}
@@ -0,0 +1,10 @@
1
+ interface ResetExtensionsModalProps {
2
+ isOpen: boolean;
3
+ message: string;
4
+ title: string;
5
+ onCancelReset: () => void;
6
+ onClose: () => void;
7
+ onConfirmReset: () => void;
8
+ }
9
+ declare const ResetExtensionsModal: ({ isOpen, message, title, onCancelReset, onClose, onConfirmReset, }: ResetExtensionsModalProps) => import("react/jsx-runtime").JSX.Element;
10
+ export default ResetExtensionsModal;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useIntl } from '@openedx/frontend-base';
3
+ import { ModalDialog, ActionRow, Button } from '@openedx/paragon';
4
+ import messages from '../messages';
5
+ const ResetExtensionsModal = ({ isOpen, message, title, onCancelReset, onClose, onConfirmReset, }) => {
6
+ const intl = useIntl();
7
+ return (_jsxs(ModalDialog, { isOpen: isOpen, onClose: onClose, hasCloseButton: false, title: title, isOverflowVisible: false, className: "p-4", children: [_jsx("h4", { className: "mb-2.5", children: title }), _jsx("p", { className: "mb-2.5", children: message }), _jsxs(ActionRow, { children: [_jsx(Button, { variant: "tertiary", onClick: onCancelReset, children: intl.formatMessage(messages.cancel) }), _jsx(Button, { variant: "primary", onClick: onConfirmReset, children: intl.formatMessage(messages.confirm) })] })] }));
8
+ };
9
+ export default ResetExtensionsModal;
10
+ //# sourceMappingURL=ResetExtensionsModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResetExtensionsModal.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/ResetExtensionsModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,QAAQ,MAAM,aAAa,CAAC;AAWnC,MAAM,oBAAoB,GAAG,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,KAAK,EACL,aAAa,EACb,OAAO,EACP,cAAc,GACY,EAAE,EAAE;IAC9B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,OAAO,CACL,MAAC,WAAW,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAC,KAAK,aAC3H,aAAI,SAAS,EAAC,QAAQ,YAAE,KAAK,GAAM,EACnC,YAAG,SAAS,EAAC,QAAQ,YAAE,OAAO,GAAK,EACnC,MAAC,SAAS,eACR,KAAC,MAAM,IAAC,OAAO,EAAC,UAAU,EAAC,OAAO,EAAE,aAAa,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAU,EACjG,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,cAAc,YAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAU,IACxF,IACA,CACf,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,oBAAoB,CAAC","sourcesContent":["import { useIntl } from '@openedx/frontend-base';\nimport { ModalDialog, ActionRow, Button } from '@openedx/paragon';\nimport messages from '../messages';\n\ninterface ResetExtensionsModalProps {\n isOpen: boolean,\n message: string,\n title: string,\n onCancelReset: () => void,\n onClose: () => void,\n onConfirmReset: () => void,\n}\n\nconst ResetExtensionsModal = ({\n isOpen,\n message,\n title,\n onCancelReset,\n onClose,\n onConfirmReset,\n}: ResetExtensionsModalProps) => {\n const intl = useIntl();\n return (\n <ModalDialog isOpen={isOpen} onClose={onClose} hasCloseButton={false} title={title} isOverflowVisible={false} className=\"p-4\">\n <h4 className=\"mb-2.5\">{title}</h4>\n <p className=\"mb-2.5\">{message}</p>\n <ActionRow>\n <Button variant=\"tertiary\" onClick={onCancelReset}>{intl.formatMessage(messages.cancel)}</Button>\n <Button variant=\"primary\" onClick={onConfirmReset}>{intl.formatMessage(messages.confirm)}</Button>\n </ActionRow>\n </ModalDialog>\n );\n};\n\nexport default ResetExtensionsModal;\n"]}
@@ -0,0 +1,8 @@
1
+ interface SelectGradedSubsectionProps {
2
+ label?: string;
3
+ placeholder: string;
4
+ value?: string;
5
+ onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
6
+ }
7
+ declare const SelectGradedSubsection: ({ label, placeholder, value, onChange }: SelectGradedSubsectionProps) => import("react/jsx-runtime").JSX.Element;
8
+ export default SelectGradedSubsection;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useParams } from 'react-router-dom';
3
+ import { FormLabel, FormControl, FormGroup } from '@openedx/paragon';
4
+ import { useGradedSubsections } from '../data/apiHook';
5
+ const SelectGradedSubsection = ({ label, placeholder, value, onChange }) => {
6
+ const { courseId = '' } = useParams();
7
+ const { data = { items: [] } } = useGradedSubsections(courseId);
8
+ const selectOptions = [{ displayName: placeholder, subsectionId: '' }, ...data.items];
9
+ const handleChange = (event) => {
10
+ onChange(event);
11
+ };
12
+ return (_jsxs(FormGroup, { className: "mb-0", size: "sm", children: [label && _jsx(FormLabel, { children: label }), _jsx(FormControl, { as: "select", name: "blockId", placeholder: placeholder, size: "md", value: value, onChange: handleChange, children: selectOptions.map((option) => (_jsx("option", { value: option.subsectionId, children: option.displayName }, option.subsectionId))) })] }));
13
+ };
14
+ export default SelectGradedSubsection;
15
+ //# sourceMappingURL=SelectGradedSubsection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectGradedSubsection.js","sourceRoot":"","sources":["../../../src/dateExtensions/components/SelectGradedSubsection.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AASvD,MAAM,sBAAsB,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAA+B,EAAE,EAAE;IACtG,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,IAAI,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAEtF,MAAM,YAAY,GAAG,CAAC,KAA2C,EAAE,EAAE;QACnE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CACL,MAAC,SAAS,IAAC,SAAS,EAAC,MAAM,EAAC,IAAI,EAAC,IAAI,aAClC,KAAK,IAAI,KAAC,SAAS,cAAE,KAAK,GAAa,EACxC,KAAC,WAAW,IACV,EAAE,EAAC,QAAQ,EACX,IAAI,EAAC,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,IAAI,EAAC,IAAI,EACT,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,YAGpB,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC5B,iBAAkC,KAAK,EAAE,MAAM,CAAC,YAAY,YACzD,MAAM,CAAC,WAAW,IADR,MAAM,CAAC,YAAY,CAEvB,CACV,CAAC,GAEQ,IACJ,CACb,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,sBAAsB,CAAC","sourcesContent":["import { useParams } from 'react-router-dom';\nimport { FormLabel, FormControl, FormGroup } from '@openedx/paragon';\nimport { useGradedSubsections } from '../data/apiHook';\n\ninterface SelectGradedSubsectionProps {\n label?: string,\n placeholder: string,\n value?: string,\n onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void,\n}\n\nconst SelectGradedSubsection = ({ label, placeholder, value, onChange }: SelectGradedSubsectionProps) => {\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { data = { items: [] } } = useGradedSubsections(courseId);\n const selectOptions = [{ displayName: placeholder, subsectionId: '' }, ...data.items];\n\n const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\n onChange(event);\n };\n\n return (\n <FormGroup className=\"mb-0\" size=\"sm\">\n {label && <FormLabel>{label}</FormLabel>}\n <FormControl\n as=\"select\"\n name=\"blockId\"\n placeholder={placeholder}\n size=\"md\"\n value={value}\n onChange={handleChange}\n >\n {\n selectOptions.map((option) => (\n <option key={option.subsectionId} value={option.subsectionId}>\n {option.displayName}\n </option>\n ))\n }\n </FormControl>\n </FormGroup>\n );\n};\n\nexport default SelectGradedSubsection;\n"]}
@@ -0,0 +1,6 @@
1
+ import { AddDateExtensionParams, DateExtensionQueryParams, LearnerDateExtension, ResetDueDateParams } from '../types';
2
+ import { DataList } from '../../types';
3
+ export declare const getDateExtensions: (courseId: string, params: DateExtensionQueryParams) => Promise<DataList<LearnerDateExtension>>;
4
+ export declare const resetDateExtension: (courseId: string, params: ResetDueDateParams) => Promise<any>;
5
+ export declare const addDateExtension: (courseId: string, extensionData: AddDateExtensionParams) => Promise<any>;
6
+ export declare const getGradedSubsections: (courseId: string) => Promise<any>;
@@ -0,0 +1,40 @@
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, snakeCaseObject } from '@openedx/frontend-base';
11
+ import { getApiBaseUrl } from '../../data/api';
12
+ export const getDateExtensions = (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.blockId) {
21
+ const blockId = encodeURI(params.blockId);
22
+ queryParams.append('block_id', blockId);
23
+ }
24
+ const { data } = yield getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/unit_extensions?${queryParams.toString()}`);
25
+ return camelCaseObject(data);
26
+ });
27
+ export const resetDateExtension = (courseId, params) => __awaiter(void 0, void 0, void 0, function* () {
28
+ const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/courses/${courseId}/instructor/api/reset_due_date`, params);
29
+ return camelCaseObject(data);
30
+ });
31
+ export const addDateExtension = (courseId, extensionData) => __awaiter(void 0, void 0, void 0, function* () {
32
+ const snakeCaseData = snakeCaseObject(extensionData);
33
+ const { data } = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/change_due_date`, snakeCaseData);
34
+ return camelCaseObject(data);
35
+ });
36
+ export const getGradedSubsections = (courseId) => __awaiter(void 0, void 0, void 0, function* () {
37
+ const { data } = yield getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/graded_subsections`);
38
+ return camelCaseObject(data);
39
+ });
40
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/dateExtensions/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAgB,EAChB,MAAgC,EACS,EAAE;IAC3C,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,OAAO,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1C,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,oBAAoB,WAAW,CAAC,QAAQ,EAAE,EAAE,CACrG,CAAC;IACF,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAO,QAAgB,EAAE,MAA0B,EAAE,EAAE;IACvF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CAAC,GAAG,aAAa,EAAE,YAAY,QAAQ,gCAAgC,EAAE,MAAM,CAAC,CAAC;IACzI,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAO,QAAgB,EAAE,aAAqC,EAAE,EAAE;IAChG,MAAM,aAAa,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IACrD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CAAC,GAAG,aAAa,EAAE,8BAA8B,QAAQ,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACpJ,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAO,QAAgB,EAAE,EAAE;IAC7D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE,CAAC,GAAG,CACrD,GAAG,aAAa,EAAE,8BAA8B,QAAQ,qBAAqB,CAC9E,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 '../../data/api';\nimport { AddDateExtensionParams, DateExtensionQueryParams, LearnerDateExtension, ResetDueDateParams } from '../types';\nimport { DataList } from '@src/types';\n\nexport const getDateExtensions = async (\n courseId: string,\n params: DateExtensionQueryParams\n): Promise<DataList<LearnerDateExtension>> => {\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.blockId) {\n const blockId = encodeURI(params.blockId);\n queryParams.append('block_id', blockId);\n }\n\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/unit_extensions?${queryParams.toString()}`\n );\n return camelCaseObject(data);\n};\n\nexport const resetDateExtension = async (courseId: string, params: ResetDueDateParams) => {\n const { data } = await getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/courses/${courseId}/instructor/api/reset_due_date`, params);\n return camelCaseObject(data);\n};\n\nexport const addDateExtension = async (courseId: string, extensionData: AddDateExtensionParams) => {\n const snakeCaseData = snakeCaseObject(extensionData);\n const { data } = await getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/change_due_date`, snakeCaseData);\n return camelCaseObject(data);\n};\n\nexport const getGradedSubsections = async (courseId: string) => {\n const { data } = await getAuthenticatedHttpClient().get(\n `${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}/graded_subsections`\n );\n return camelCaseObject(data);\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { DateExtensionQueryParams, ResetDueDateParams } from '../types';
2
+ export declare const useDateExtensions: (courseId: string, params: DateExtensionQueryParams) => import("@tanstack/react-query").UseQueryResult<import("../../types").DataList<import("../types").LearnerDateExtension>, Error>;
3
+ export declare const useResetDateExtensionMutation: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
4
+ courseId: string;
5
+ params: ResetDueDateParams;
6
+ }, unknown>;
7
+ export declare const useAddDateExtensionMutation: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
8
+ courseId: string;
9
+ extensionData: any;
10
+ }, unknown>;
11
+ export declare const useGradedSubsections: (courseId: string) => import("@tanstack/react-query").UseQueryResult<any, Error>;
@@ -0,0 +1,31 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { getDateExtensions, resetDateExtension, addDateExtension, getGradedSubsections } from './api';
3
+ import { dateExtensionsQueryKeys, gradedSubsectionsQueryKeys } from './queryKeys';
4
+ export const useDateExtensions = (courseId, params) => (useQuery({
5
+ queryKey: dateExtensionsQueryKeys.byCoursePaginated(courseId, params),
6
+ queryFn: () => getDateExtensions(courseId, params),
7
+ enabled: !!courseId,
8
+ }));
9
+ export const useResetDateExtensionMutation = () => {
10
+ const queryClient = useQueryClient();
11
+ return useMutation({
12
+ mutationFn: ({ courseId, params }) => resetDateExtension(courseId, params),
13
+ onSuccess: (_, { courseId }) => {
14
+ queryClient.invalidateQueries({ queryKey: dateExtensionsQueryKeys.byCourse(courseId), exact: false });
15
+ },
16
+ });
17
+ };
18
+ export const useAddDateExtensionMutation = () => {
19
+ const queryClient = useQueryClient();
20
+ return useMutation({
21
+ mutationFn: ({ courseId, extensionData }) => addDateExtension(courseId, extensionData),
22
+ onSuccess: ({ courseId }) => {
23
+ queryClient.invalidateQueries({ queryKey: dateExtensionsQueryKeys.byCourse(courseId) });
24
+ },
25
+ });
26
+ };
27
+ export const useGradedSubsections = (courseId) => (useQuery({
28
+ queryKey: gradedSubsectionsQueryKeys.byCourse(courseId),
29
+ queryFn: () => getGradedSubsections(courseId),
30
+ }));
31
+ //# sourceMappingURL=apiHook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../../src/dateExtensions/data/apiHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACtG,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAGlF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAE,MAAgC,EAAE,EAAE,CAAC,CACvF,QAAQ,CAAC;IACP,QAAQ,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IACrE,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC;IAClD,OAAO,EAAE,CAAC,CAAC,QAAQ;CACpB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,EAAE;IAChD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAoD,EAAE,EAAE,CACrF,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC;QACtC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC7B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACxG,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,EAAE;IAC9C,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,EAA4C,EAAE,EAAE,CACpF,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC;QAC3C,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC1B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1F,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CACxD,QAAQ,CAAC;IACP,QAAQ,EAAE,0BAA0B,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACvD,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;CAC9C,CAAC,CACH,CAAC","sourcesContent":["import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { getDateExtensions, resetDateExtension, addDateExtension, getGradedSubsections } from './api';\nimport { dateExtensionsQueryKeys, gradedSubsectionsQueryKeys } from './queryKeys';\nimport { DateExtensionQueryParams, ResetDueDateParams } from '../types';\n\nexport const useDateExtensions = (courseId: string, params: DateExtensionQueryParams) => (\n useQuery({\n queryKey: dateExtensionsQueryKeys.byCoursePaginated(courseId, params),\n queryFn: () => getDateExtensions(courseId, params),\n enabled: !!courseId,\n })\n);\n\nexport const useResetDateExtensionMutation = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ courseId, params }: { courseId: string, params: ResetDueDateParams }) =>\n resetDateExtension(courseId, params),\n onSuccess: (_, { courseId }) => {\n queryClient.invalidateQueries({ queryKey: dateExtensionsQueryKeys.byCourse(courseId), exact: false });\n },\n });\n};\n\nexport const useAddDateExtensionMutation = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: ({ courseId, extensionData }: { courseId: string, extensionData: any }) =>\n addDateExtension(courseId, extensionData),\n onSuccess: ({ courseId }) => {\n queryClient.invalidateQueries({ queryKey: dateExtensionsQueryKeys.byCourse(courseId) });\n },\n });\n};\n\nexport const useGradedSubsections = (courseId: string) => (\n useQuery({\n queryKey: gradedSubsectionsQueryKeys.byCourse(courseId),\n queryFn: () => getGradedSubsections(courseId),\n })\n);\n"]}
@@ -0,0 +1,10 @@
1
+ import { DateExtensionQueryParams } from '../types';
2
+ export declare const dateExtensionsQueryKeys: {
3
+ all: readonly ["org.openedx.frontend.app.instructor", "dateExtensions"];
4
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructor", "dateExtensions", string];
5
+ byCoursePaginated: (courseId: string, params: DateExtensionQueryParams) => readonly ["org.openedx.frontend.app.instructor", "dateExtensions", string, number, number, string, string];
6
+ };
7
+ export declare const gradedSubsectionsQueryKeys: {
8
+ all: readonly ["org.openedx.frontend.app.instructor", "gradedSubsections"];
9
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructor", "gradedSubsections", string];
10
+ };
@@ -0,0 +1,17 @@
1
+ import { appId } from '../../constants';
2
+ export const dateExtensionsQueryKeys = {
3
+ all: [appId, 'dateExtensions'],
4
+ byCourse: (courseId) => [...dateExtensionsQueryKeys.all, courseId],
5
+ byCoursePaginated: (courseId, params) => [
6
+ ...dateExtensionsQueryKeys.byCourse(courseId),
7
+ params.page,
8
+ params.pageSize,
9
+ params.emailOrUsername || '',
10
+ params.blockId || ''
11
+ ],
12
+ };
13
+ export const gradedSubsectionsQueryKeys = {
14
+ all: [appId, 'gradedSubsections'],
15
+ byCourse: (courseId) => [...gradedSubsectionsQueryKeys.all, courseId],
16
+ };
17
+ //# sourceMappingURL=queryKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../../src/dateExtensions/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGxC,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAU;IACvC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAU;IACnF,iBAAiB,EAAE,CACjB,QAAgB,EAChB,MAAgC,EAChC,EAAE,CAAC;QACH,GAAG,uBAAuB,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7C,MAAM,CAAC,IAAI;QACX,MAAM,CAAC,QAAQ;QACf,MAAM,CAAC,eAAe,IAAI,EAAE;QAC5B,MAAM,CAAC,OAAO,IAAI,EAAE;KACZ;CACX,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAU;IAC1C,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,0BAA0B,CAAC,GAAG,EAAE,QAAQ,CAAU;CACvF,CAAC","sourcesContent":["import { appId } from '../../constants';\nimport { DateExtensionQueryParams } from '../types';\n\nexport const dateExtensionsQueryKeys = {\n all: [appId, 'dateExtensions'] as const,\n byCourse: (courseId: string) => [...dateExtensionsQueryKeys.all, courseId] as const,\n byCoursePaginated: (\n courseId: string,\n params: DateExtensionQueryParams\n ) => [\n ...dateExtensionsQueryKeys.byCourse(courseId),\n params.page,\n params.pageSize,\n params.emailOrUsername || '',\n params.blockId || ''\n ] as const,\n};\n\nexport const gradedSubsectionsQueryKeys = {\n all: [appId, 'gradedSubsections'] as const,\n byCourse: (courseId: string) => [...gradedSubsectionsQueryKeys.all, courseId] as const,\n};\n"]}
@@ -0,0 +1,128 @@
1
+ declare const messages: {
2
+ dateExtensionsTitle: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ addIndividualExtension: {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ username: {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ fullname: {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ email: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ gradedSubsection: {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ extendedDueDate: {
33
+ id: string;
34
+ defaultMessage: string;
35
+ description: string;
36
+ };
37
+ reset: {
38
+ id: string;
39
+ defaultMessage: string;
40
+ description: string;
41
+ };
42
+ resetExtensions: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ resetConfirmationHeader: {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
52
+ resetConfirmationMessage: {
53
+ id: string;
54
+ defaultMessage: string;
55
+ description: string;
56
+ };
57
+ cancel: {
58
+ id: string;
59
+ defaultMessage: string;
60
+ description: string;
61
+ };
62
+ confirm: {
63
+ id: string;
64
+ defaultMessage: string;
65
+ description: string;
66
+ };
67
+ close: {
68
+ id: string;
69
+ defaultMessage: string;
70
+ description: string;
71
+ };
72
+ missingUserOrCourseIdError: {
73
+ id: string;
74
+ defaultMessage: string;
75
+ description: string;
76
+ };
77
+ addIndividualDueDateExtension: {
78
+ id: string;
79
+ defaultMessage: string;
80
+ description: string;
81
+ };
82
+ addExtension: {
83
+ id: string;
84
+ defaultMessage: string;
85
+ description: string;
86
+ };
87
+ extensionInstructions: {
88
+ id: string;
89
+ defaultMessage: string;
90
+ description: string;
91
+ };
92
+ defineExtension: {
93
+ id: string;
94
+ defaultMessage: string;
95
+ description: string;
96
+ };
97
+ extensionDate: {
98
+ id: string;
99
+ defaultMessage: string;
100
+ description: string;
101
+ };
102
+ reasonForExtension: {
103
+ id: string;
104
+ defaultMessage: string;
105
+ description: string;
106
+ };
107
+ selectGradedSubsection: {
108
+ id: string;
109
+ defaultMessage: string;
110
+ description: string;
111
+ };
112
+ allGradedSubsections: {
113
+ id: string;
114
+ defaultMessage: string;
115
+ description: string;
116
+ };
117
+ searchLearnerPlaceholder: {
118
+ id: string;
119
+ defaultMessage: string;
120
+ description: string;
121
+ };
122
+ noDateExtensions: {
123
+ id: string;
124
+ defaultMessage: string;
125
+ description: string;
126
+ };
127
+ };
128
+ export default messages;