@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,2 @@
1
+ declare const GeneralCourseInfo: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export { GeneralCourseInfo };
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, Skeleton } from '@openedx/paragon';
3
+ import { StatusBadge } from './StatusBadge';
4
+ import { useCourseInfo } from '../../../data/apiHook';
5
+ import { useParams } from 'react-router';
6
+ import { FormattedDate, useIntl } from '@openedx/frontend-base';
7
+ import { useCallback } from 'react';
8
+ import messages from './messages';
9
+ const COURSE_STATUS = {
10
+ ACTIVE: 'Active',
11
+ ARCHIVED: 'Archived',
12
+ UPCOMING: 'Upcoming',
13
+ };
14
+ const GeneralCourseInfo = () => {
15
+ var _a, _b, _c, _d;
16
+ const intl = useIntl();
17
+ const { courseId = '' } = useParams();
18
+ const { data: courseInfo, isLoading } = useCourseInfo(courseId);
19
+ const NOT_SET_FALLBACK = intl.formatMessage(messages.courseInfoNotSetFallback);
20
+ const getCourseStatus = useCallback((courseInfo) => {
21
+ if (!courseInfo || (courseInfo.hasStarted === undefined && courseInfo.hasEnded === undefined))
22
+ return NOT_SET_FALLBACK;
23
+ if (!courseInfo.hasStarted)
24
+ return COURSE_STATUS.UPCOMING;
25
+ if (courseInfo.hasStarted && !courseInfo.hasEnded)
26
+ return COURSE_STATUS.ACTIVE;
27
+ if (courseInfo.hasStarted && courseInfo.hasEnded)
28
+ return COURSE_STATUS.ARCHIVED;
29
+ return NOT_SET_FALLBACK;
30
+ }, [NOT_SET_FALLBACK]);
31
+ const renderDate = (date) => {
32
+ if (!date)
33
+ return NOT_SET_FALLBACK;
34
+ /// Added UTC timezone because it was showing the date with 1 day offset
35
+ return _jsx(FormattedDate, { value: date, year: "numeric", month: "short", day: "2-digit", timeZone: "UTC" });
36
+ };
37
+ if (isLoading && !courseInfo) {
38
+ return (_jsx(Card, { className: "general-course-info", children: _jsx(Card.Section, { children: _jsx(Skeleton, { count: 3 }) }) }));
39
+ }
40
+ if (!courseInfo) {
41
+ return null;
42
+ }
43
+ return (_jsx(Card, { className: "general-course-info", children: _jsxs(Card.Section, { children: [_jsxs("div", { className: "x-small mb-1.5", children: [_jsx("span", { className: "mr-2", children: (_a = courseInfo.org) !== null && _a !== void 0 ? _a : NOT_SET_FALLBACK }), "/", _jsx("span", { className: "mx-2", children: (_b = courseInfo.courseId) !== null && _b !== void 0 ? _b : NOT_SET_FALLBACK }), "/", _jsx("span", { className: "ml-2", children: (_c = courseInfo.courseRun) !== null && _c !== void 0 ? _c : NOT_SET_FALLBACK })] }), _jsx("h3", { className: "text-primary-700 mb-3", children: (_d = courseInfo.displayName) !== null && _d !== void 0 ? _d : NOT_SET_FALLBACK }), _jsxs("div", { className: "d-flex align-items-center", children: [_jsx("div", { className: "mr-4", children: _jsx(StatusBadge, { status: getCourseStatus(courseInfo) }) }), _jsx("div", { className: "x-small text-body", children: _jsxs("p", { className: "mb-0", children: [renderDate(courseInfo.start), ' – ', renderDate(courseInfo.end)] }) })] })] }) }));
44
+ };
45
+ export { GeneralCourseInfo };
46
+ //# sourceMappingURL=GeneralCourseInfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeneralCourseInfo.js","sourceRoot":"","sources":["../../../../src/courseInfo/components/generalCourseInfo/GeneralCourseInfo.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Card, Skeleton } from '@openedx/paragon';\nimport { StatusBadge } from './StatusBadge';\nimport { useCourseInfo } from '@src/data/apiHook';\nimport { useParams } from 'react-router';\nimport { FormattedDate, useIntl } from '@openedx/frontend-base';\nimport { useCallback } from 'react';\nimport messages from './messages';\n\nconst COURSE_STATUS = {\n ACTIVE: 'Active',\n ARCHIVED: 'Archived',\n UPCOMING: 'Upcoming',\n};\n\nconst GeneralCourseInfo = () => {\n const intl = useIntl();\n const { courseId = '' } = useParams();\n const { data: courseInfo, isLoading } = useCourseInfo(courseId);\n const NOT_SET_FALLBACK = intl.formatMessage(messages.courseInfoNotSetFallback);\n\n const getCourseStatus = useCallback((courseInfo) => {\n if (!courseInfo || (courseInfo.hasStarted === undefined && courseInfo.hasEnded === undefined)) return NOT_SET_FALLBACK;\n if (!courseInfo.hasStarted) return COURSE_STATUS.UPCOMING;\n if (courseInfo.hasStarted && !courseInfo.hasEnded) return COURSE_STATUS.ACTIVE;\n if (courseInfo.hasStarted && courseInfo.hasEnded) return COURSE_STATUS.ARCHIVED;\n return NOT_SET_FALLBACK;\n }, [NOT_SET_FALLBACK]);\n\n const renderDate = (date: string | null) => {\n if (!date) return NOT_SET_FALLBACK;\n /// Added UTC timezone because it was showing the date with 1 day offset\n return <FormattedDate value={date} year=\"numeric\" month=\"short\" day=\"2-digit\" timeZone=\"UTC\" />;\n };\n\n if (isLoading && !courseInfo) {\n return (\n <Card className=\"general-course-info\">\n <Card.Section>\n <Skeleton count={3} />\n </Card.Section>\n </Card>\n );\n }\n\n if (!courseInfo) {\n return null;\n }\n\n return (\n <Card className=\"general-course-info\">\n <Card.Section>\n <div className=\"x-small mb-1.5\">\n <span className=\"mr-2\">{courseInfo.org ?? NOT_SET_FALLBACK}</span>/\n <span className=\"mx-2\">{courseInfo.courseId ?? NOT_SET_FALLBACK}</span>/\n <span className=\"ml-2\">{courseInfo.courseRun ?? NOT_SET_FALLBACK}</span>\n </div>\n <h3 className=\"text-primary-700 mb-3\">{courseInfo.displayName ?? NOT_SET_FALLBACK}</h3>\n <div className=\"d-flex align-items-center\">\n <div className=\"mr-4\">\n <StatusBadge status={getCourseStatus(courseInfo)} />\n </div>\n <div className=\"x-small text-body\">\n <p className=\"mb-0\">\n {renderDate(courseInfo.start)}\n {' – '}\n {renderDate(courseInfo.end)}\n </p>\n </div>\n </div>\n </Card.Section>\n </Card>\n );\n};\n\nexport { GeneralCourseInfo };\n"]}
@@ -0,0 +1,5 @@
1
+ interface StatusBadgeProps {
2
+ status: string;
3
+ }
4
+ declare const StatusBadge: ({ status }: StatusBadgeProps) => import("react/jsx-runtime").JSX.Element;
5
+ export { StatusBadge };
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Badge } from '@openedx/paragon';
3
+ const STATUS_VARIANTS = {
4
+ active: 'success',
5
+ archived: 'light',
6
+ upcoming: 'warning',
7
+ };
8
+ const StatusBadge = ({ status }) => {
9
+ const getBadgeVariant = (status) => {
10
+ return STATUS_VARIANTS[status.toLowerCase()] || 'light';
11
+ };
12
+ return (_jsx(Badge, { variant: getBadgeVariant(status), className: "py-1.5 px-3 x-small font-weight-normal", children: status }));
13
+ };
14
+ export { StatusBadge };
15
+ //# sourceMappingURL=StatusBadge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBadge.js","sourceRoot":"","sources":["../../../../src/courseInfo/components/generalCourseInfo/StatusBadge.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAMzC,MAAM,eAAe,GAA2B;IAC9C,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,SAAS;CACpB,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,EAAE,MAAM,EAAoB,EAAE,EAAE;IACnD,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,EAAE;QACzC,OAAO,eAAe,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC;IAC1D,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,KAAK,IAAC,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,SAAS,EAAC,wCAAwC,YAAE,MAAM,GAAS,CAC7G,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC","sourcesContent":["import { Badge } from '@openedx/paragon';\n\ninterface StatusBadgeProps {\n status: string,\n}\n\nconst STATUS_VARIANTS: Record<string, string> = {\n active: 'success',\n archived: 'light',\n upcoming: 'warning',\n};\n\nconst StatusBadge = ({ status }: StatusBadgeProps) => {\n const getBadgeVariant = (status: string) => {\n return STATUS_VARIANTS[status.toLowerCase()] || 'light';\n };\n\n return (\n <Badge variant={getBadgeVariant(status)} className=\"py-1.5 px-3 x-small font-weight-normal\">{status}</Badge>\n );\n};\n\nexport { StatusBadge };\n"]}
@@ -0,0 +1 @@
1
+ export { GeneralCourseInfo } from './GeneralCourseInfo';
@@ -0,0 +1,2 @@
1
+ export { GeneralCourseInfo } from './GeneralCourseInfo';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/courseInfo/components/generalCourseInfo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["export { GeneralCourseInfo } from './GeneralCourseInfo';\n"]}
@@ -0,0 +1,8 @@
1
+ declare const messages: {
2
+ courseInfoNotSetFallback: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ };
8
+ export default messages;
@@ -0,0 +1,10 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ courseInfoNotSetFallback: {
4
+ id: 'instruct.courseInfo.generalInfo.notSetFallback',
5
+ defaultMessage: 'Not Set',
6
+ description: 'Fallback text used in case any of the course information is not available or provided',
7
+ },
8
+ });
9
+ export default messages;
10
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../../src/courseInfo/components/generalCourseInfo/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,wBAAwB,EAAE;QACxB,EAAE,EAAE,gDAAgD;QACpD,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,uFAAuF;KACrG;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n courseInfoNotSetFallback: {\n id: 'instruct.courseInfo.generalInfo.notSetFallback',\n defaultMessage: 'Not Set',\n description: 'Fallback text used in case any of the course information is not available or provided',\n },\n});\n\nexport default messages;\n"]}
@@ -0,0 +1,8 @@
1
+ declare const messages: {
2
+ courseInfoTitle: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ };
8
+ export default messages;
@@ -0,0 +1,10 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ courseInfoTitle: {
4
+ id: 'instruct.courseInfo.page.title',
5
+ defaultMessage: 'Course Info',
6
+ description: 'Title for the course information page',
7
+ },
8
+ });
9
+ export default messages;
10
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/courseInfo/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,eAAe,EAAE;QACf,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,uCAAuC;KACrD;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n courseInfoTitle: {\n id: 'instruct.courseInfo.page.title',\n defaultMessage: 'Course Info',\n description: 'Title for the course information page',\n },\n});\n\nexport default messages;\n"]}
@@ -0,0 +1,27 @@
1
+ import { TabProps } from '../instructorNav/InstructorNav';
2
+ export interface CourseInfoResponse {
3
+ courseId: string;
4
+ displayName: string;
5
+ courseNumber: string;
6
+ courseRun: string;
7
+ enrollmentCounts: EnrollmentCounts;
8
+ start: string | null;
9
+ end: string | null;
10
+ tabs?: TabProps[];
11
+ totalEnrollment: number;
12
+ studioUrl: string;
13
+ pacing: string;
14
+ org?: string;
15
+ numSections: number;
16
+ hasStarted: boolean;
17
+ hasEnded: boolean;
18
+ enrollmentEnd: string | null;
19
+ enrollmentStart: string | null;
20
+ gradeCutoffs: string | null;
21
+ staffCount: number;
22
+ learnerCount: number;
23
+ }
24
+ interface EnrollmentCounts extends Record<string, number> {
25
+ total: number;
26
+ }
27
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/courseInfo/types.ts"],"names":[],"mappings":"","sourcesContent":["import { TabProps } from '@src/instructorNav/InstructorNav';\n\nexport interface CourseInfoResponse {\n courseId: string,\n displayName: string,\n courseNumber: string,\n courseRun: string,\n enrollmentCounts: EnrollmentCounts,\n start: string | null,\n end: string | null,\n tabs?: TabProps[],\n totalEnrollment: number,\n studioUrl: string,\n pacing: string,\n org?: string,\n numSections: number,\n hasStarted: boolean,\n hasEnded: boolean,\n enrollmentEnd: string | null,\n enrollmentStart: string | null,\n gradeCutoffs: string | null,\n staffCount: number,\n learnerCount: number,\n}\n\ninterface EnrollmentCounts extends Record<string, number> {\n total: number,\n}\n"]}
@@ -0,0 +1,2 @@
1
+ declare const CourseTeamPage: () => import("react/jsx-runtime").JSX.Element;
2
+ export default CourseTeamPage;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const CourseTeamPage = () => {
3
+ return (_jsx("div", { children: _jsx("h3", { children: "Course Team" }) }));
4
+ };
5
+ export default CourseTeamPage;
6
+ //# sourceMappingURL=CourseTeamPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CourseTeamPage.js","sourceRoot":"","sources":["../../src/courseTeam/CourseTeamPage.tsx"],"names":[],"mappings":";AAAA,MAAM,cAAc,GAAG,GAAG,EAAE;IAC1B,OAAO,CACL,wBACE,uCAAoB,GAChB,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["const CourseTeamPage = () => {\n return (\n <div>\n <h3>Course Team</h3>\n </div>\n );\n};\n\nexport default CourseTeamPage;\n"]}
@@ -0,0 +1,14 @@
1
+ import { CourseInfoResponse } from '../courseInfo/types';
2
+ export declare const getApiBaseUrl: () => unknown;
3
+ /**
4
+ * Get course settings.
5
+ * @param {string} courseId
6
+ * @returns {Promise<Object>}
7
+ */
8
+ export declare const getCourseInfo: (courseId: string) => Promise<CourseInfoResponse>;
9
+ /**
10
+ * Fetch pending instructor tasks for a course.
11
+ * @param {string} courseId
12
+ * @returns {Promise<Array>}
13
+ */
14
+ export declare const fetchPendingTasks: (courseId: string) => Promise<any>;
@@ -0,0 +1,33 @@
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, getAppConfig, getAuthenticatedHttpClient } from '@openedx/frontend-base';
11
+ import { appId } from '../constants';
12
+ export const getApiBaseUrl = () => getAppConfig(appId).LMS_BASE_URL;
13
+ /**
14
+ * Get course settings.
15
+ * @param {string} courseId
16
+ * @returns {Promise<Object>}
17
+ */
18
+ export const getCourseInfo = (courseId) => __awaiter(void 0, void 0, void 0, function* () {
19
+ const { data } = yield getAuthenticatedHttpClient()
20
+ .get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}`);
21
+ return camelCaseObject(data);
22
+ });
23
+ /**
24
+ * Fetch pending instructor tasks for a course.
25
+ * @param {string} courseId
26
+ * @returns {Promise<Array>}
27
+ */
28
+ export const fetchPendingTasks = (courseId) => __awaiter(void 0, void 0, void 0, function* () {
29
+ var _a, _b;
30
+ const response = yield getAuthenticatedHttpClient().post(`${getApiBaseUrl()}/courses/${courseId}/instructor/api/list_instructor_tasks`);
31
+ return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.tasks) === null || _b === void 0 ? void 0 : _b.map(camelCaseObject);
32
+ });
33
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/data/api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACnG,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;AAEpE;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAO,QAAgB,EAA+B,EAAE;IACnF,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,0BAA0B,EAAE;SAChD,GAAG,CAAC,GAAG,aAAa,EAAE,8BAA8B,QAAQ,EAAE,CAAC,CAAC;IACnE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAA,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAO,QAAgB,EAAE,EAAE;;IAC1D,MAAM,QAAQ,GAAG,MAAM,0BAA0B,EAAE,CAAC,IAAI,CACtD,GAAG,aAAa,EAAE,YAAY,QAAQ,uCAAuC,CAC9E,CAAC;IACF,OAAO,MAAA,MAAA,QAAQ,CAAC,IAAI,0CAAE,KAAK,0CAAE,GAAG,CAAC,eAAe,CAAC,CAAC;AACpD,CAAC,CAAA,CAAC","sourcesContent":["import { camelCaseObject, getAppConfig, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { appId } from '@src/constants';\nimport { CourseInfoResponse } from '@src/courseInfo/types';\n\nexport const getApiBaseUrl = () => getAppConfig(appId).LMS_BASE_URL;\n\n/**\n * Get course settings.\n * @param {string} courseId\n * @returns {Promise<Object>}\n */\nexport const getCourseInfo = async (courseId: string): Promise<CourseInfoResponse> => {\n const { data } = await getAuthenticatedHttpClient()\n .get(`${getApiBaseUrl()}/api/instructor/v2/courses/${courseId}`);\n return camelCaseObject(data);\n};\n\n/**\n * Fetch pending instructor tasks for a course.\n * @param {string} courseId\n * @returns {Promise<Array>}\n */\nexport const fetchPendingTasks = async (courseId: string) => {\n const response = await getAuthenticatedHttpClient().post<{ results: Record<string, any>[] }>(\n `${getApiBaseUrl()}/courses/${courseId}/instructor/api/list_instructor_tasks`\n );\n return response.data?.tasks?.map(camelCaseObject);\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export declare const useCourseInfo: (courseId: string) => import("@tanstack/react-query").UseQueryResult<import("../courseInfo/types").CourseInfoResponse, Error>;
2
+ export declare const usePendingTasks: (courseId: string, options?: {
3
+ enablePolling?: boolean;
4
+ }) => import("@tanstack/react-query").UseQueryResult<any, Error>;
@@ -0,0 +1,28 @@
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 { useQuery } from '@tanstack/react-query';
11
+ import { fetchPendingTasks, getCourseInfo } from './api';
12
+ import { courseInfoQueryKeys, pendingTasksQueryKey } from './queryKeys';
13
+ export const useCourseInfo = (courseId) => (useQuery({
14
+ queryKey: courseInfoQueryKeys.byCourse(courseId),
15
+ queryFn: () => getCourseInfo(courseId),
16
+ enabled: !!courseId,
17
+ refetchOnWindowFocus: false,
18
+ refetchOnMount: false,
19
+ }));
20
+ export const usePendingTasks = (courseId, options) => {
21
+ return useQuery({
22
+ queryKey: pendingTasksQueryKey.byCourse(courseId),
23
+ queryFn: () => __awaiter(void 0, void 0, void 0, function* () { return fetchPendingTasks(courseId); }),
24
+ enabled: !!courseId,
25
+ refetchInterval: (options === null || options === void 0 ? void 0 : options.enablePolling) ? 3000 : false,
26
+ });
27
+ };
28
+ //# sourceMappingURL=apiHook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiHook.js","sourceRoot":"","sources":["../../src/data/apiHook.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CACjD,QAAQ,CAAC;IACP,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAChD,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,QAAQ;IACnB,oBAAoB,EAAE,KAAK;IAC3B,cAAc,EAAE,KAAK;CACtB,CAAC,CACH,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,OAAqC,EAAE,EAAE;IACzF,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACjD,OAAO,EAAE,GAAS,EAAE,kDAAC,OAAA,iBAAiB,CAAC,QAAQ,CAAC,CAAA,GAAA;QAChD,OAAO,EAAE,CAAC,CAAC,QAAQ;QACnB,eAAe,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,aAAa,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;KACvD,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { fetchPendingTasks, getCourseInfo } from './api';\nimport { courseInfoQueryKeys, pendingTasksQueryKey } from './queryKeys';\n\nexport const useCourseInfo = (courseId: string) => (\n useQuery({\n queryKey: courseInfoQueryKeys.byCourse(courseId),\n queryFn: () => getCourseInfo(courseId),\n enabled: !!courseId,\n refetchOnWindowFocus: false,\n refetchOnMount: false,\n })\n);\n\nexport const usePendingTasks = (courseId: string, options?: { enablePolling?: boolean }) => {\n return useQuery({\n queryKey: pendingTasksQueryKey.byCourse(courseId),\n queryFn: async () => fetchPendingTasks(courseId),\n enabled: !!courseId,\n refetchInterval: options?.enablePolling ? 3000 : false,\n });\n};\n"]}
@@ -0,0 +1,8 @@
1
+ export declare const courseInfoQueryKeys: {
2
+ all: readonly ["org.openedx.frontend.app.instructor", "courseInfo"];
3
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructor", "courseInfo", string];
4
+ };
5
+ export declare const pendingTasksQueryKey: {
6
+ all: readonly ["org.openedx.frontend.app.instructor", "pendingTasks"];
7
+ byCourse: (courseId: string) => readonly ["org.openedx.frontend.app.instructor", "pendingTasks", string];
8
+ };
@@ -0,0 +1,10 @@
1
+ import { appId } from '../constants';
2
+ export const courseInfoQueryKeys = {
3
+ all: [appId, 'courseInfo'],
4
+ byCourse: (courseId) => [appId, 'courseInfo', courseId],
5
+ };
6
+ export const pendingTasksQueryKey = {
7
+ all: [appId, 'pendingTasks'],
8
+ byCourse: (courseId) => [appId, 'pendingTasks', courseId],
9
+ };
10
+ //# sourceMappingURL=queryKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/data/queryKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,CAAU;IACnC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAU;CACzE,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,GAAG,EAAE,CAAC,KAAK,EAAE,cAAc,CAAU;IACrC,QAAQ,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,CAAU;CAC3E,CAAC","sourcesContent":["import { appId } from '@src/constants';\n\nexport const courseInfoQueryKeys = {\n all: [appId, 'courseInfo'] as const,\n byCourse: (courseId: string) => [appId, 'courseInfo', courseId] as const,\n};\n\nexport const pendingTasksQueryKey = {\n all: [appId, 'pendingTasks'] as const,\n byCourse: (courseId: string) => [appId, 'pendingTasks', courseId] as const,\n};\n"]}
@@ -0,0 +1,2 @@
1
+ declare const DataDownloadsPage: () => import("react/jsx-runtime").JSX.Element;
2
+ export default DataDownloadsPage;
@@ -0,0 +1,162 @@
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 { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import messages from './messages';
12
+ import { useIntl, getAuthenticatedHttpClient } from '@openedx/frontend-base';
13
+ import { DataDownloadTable } from './components/DataDownloadTable';
14
+ import { GenerateReports } from './components/GenerateReports';
15
+ import { useParams } from 'react-router-dom';
16
+ import { useGeneratedReports, useGenerateReportLink } from './data/apiHook';
17
+ import { useCallback, useState, useRef, useEffect } from 'react';
18
+ import { getApiBaseUrl } from '../data/api';
19
+ import { getReportTypeDisplayName } from './utils';
20
+ import PageNotFound from '../components/PageNotFound';
21
+ import { useAlert } from '../providers/AlertProvider';
22
+ import { PendingTasks } from '../components/PendingTasks';
23
+ const DataDownloadsPage = () => {
24
+ var _a, _b, _c, _d;
25
+ const intl = useIntl();
26
+ const { courseId = '' } = useParams();
27
+ const [isPolling, setIsPolling] = useState(false);
28
+ const [problemResponsesError, setProblemResponsesError] = useState(undefined);
29
+ const { showToast, showModal } = useAlert();
30
+ const pollingTimeoutRef = useRef(null);
31
+ const initialReportCountRef = useRef(null);
32
+ const { data: reportsData, isLoading, error } = useGeneratedReports(courseId, { enablePolling: isPolling });
33
+ const { mutate: generateReportLinkMutate, isPending: isGenerating } = useGenerateReportLink(courseId);
34
+ // Check if we got a 404 error
35
+ const is404 = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) === 404;
36
+ // Cleanup polling timeout on unmount
37
+ useEffect(() => {
38
+ return () => {
39
+ if (pollingTimeoutRef.current) {
40
+ clearTimeout(pollingTimeoutRef.current);
41
+ }
42
+ };
43
+ }, []);
44
+ // Stop polling when new reports appear
45
+ useEffect(() => {
46
+ if (!isPolling || !(reportsData === null || reportsData === void 0 ? void 0 : reportsData.downloads)) {
47
+ return;
48
+ }
49
+ const currentCount = reportsData.downloads.length;
50
+ // If we have a baseline count and it has increased, stop polling
51
+ if (initialReportCountRef.current !== null && currentCount > initialReportCountRef.current) {
52
+ setIsPolling(false);
53
+ if (pollingTimeoutRef.current) {
54
+ clearTimeout(pollingTimeoutRef.current);
55
+ pollingTimeoutRef.current = null;
56
+ }
57
+ initialReportCountRef.current = null;
58
+ }
59
+ }, [reportsData === null || reportsData === void 0 ? void 0 : reportsData.downloads, isPolling]);
60
+ const startPolling = useCallback(() => {
61
+ var _a, _b;
62
+ // Clear any existing timeout before starting new one
63
+ if (pollingTimeoutRef.current) {
64
+ clearTimeout(pollingTimeoutRef.current);
65
+ }
66
+ // Store the current report count as baseline
67
+ initialReportCountRef.current = (_b = (_a = reportsData === null || reportsData === void 0 ? void 0 : reportsData.downloads) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
68
+ setIsPolling(true);
69
+ pollingTimeoutRef.current = setTimeout(() => {
70
+ setIsPolling(false);
71
+ pollingTimeoutRef.current = null;
72
+ initialReportCountRef.current = null;
73
+ }, 60000);
74
+ }, [(_b = reportsData === null || reportsData === void 0 ? void 0 : reportsData.downloads) === null || _b === void 0 ? void 0 : _b.length]);
75
+ // Extract downloads array from API response and transform to match expected format
76
+ const data = (_d = (_c = reportsData === null || reportsData === void 0 ? void 0 : reportsData.downloads) === null || _c === void 0 ? void 0 : _c.map(report => ({
77
+ dateGenerated: report.dateGenerated,
78
+ reportType: getReportTypeDisplayName(report.reportType, intl),
79
+ reportName: report.reportName,
80
+ downloadLink: report.reportUrl, // Map reportUrl to downloadLink
81
+ }))) !== null && _d !== void 0 ? _d : [];
82
+ const handleDownload = useCallback((downloadLink, reportName) => __awaiter(void 0, void 0, void 0, function* () {
83
+ try {
84
+ // The downloadLink is a relative path, so we need to prepend the LMS base URL
85
+ const baseUrl = getApiBaseUrl();
86
+ const fullUrl = downloadLink.startsWith('http') ? downloadLink : `${baseUrl}${downloadLink}`;
87
+ // Use authenticated HTTP client to fetch the file as a blob
88
+ const response = yield getAuthenticatedHttpClient().get(fullUrl, {
89
+ responseType: 'blob',
90
+ });
91
+ // Use the reportName from the API as the filename
92
+ const filename = reportName || 'report.csv';
93
+ // Create blob URL and trigger download
94
+ const blob = new Blob([response.data]);
95
+ const blobUrl = window.URL.createObjectURL(blob);
96
+ const link = document.createElement('a');
97
+ link.href = blobUrl;
98
+ link.download = filename;
99
+ document.body.appendChild(link);
100
+ link.click();
101
+ document.body.removeChild(link);
102
+ // Clean up blob URL
103
+ window.URL.revokeObjectURL(blobUrl);
104
+ }
105
+ catch (error) {
106
+ showModal({
107
+ title: intl.formatMessage(messages.downloadReportError),
108
+ message: intl.formatMessage(messages.downloadReportError),
109
+ variant: 'danger',
110
+ confirmText: 'OK',
111
+ });
112
+ }
113
+ }), [intl, showModal]);
114
+ const handleGenerateReport = useCallback((reportType) => {
115
+ generateReportLinkMutate({ reportType }, {
116
+ onSuccess: () => {
117
+ const reportTypeName = getReportTypeDisplayName(reportType, intl);
118
+ showToast(intl.formatMessage(messages.generateReportSuccess, { reportType: reportTypeName }));
119
+ // Start polling for 60 seconds to check for the new report
120
+ startPolling();
121
+ },
122
+ onError: (error) => {
123
+ var _a, _b;
124
+ console.error('Error generating report:', error);
125
+ const errorMessage = ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || intl.formatMessage(messages.generateReportError);
126
+ showModal({
127
+ title: intl.formatMessage(messages.generateReportError),
128
+ message: errorMessage,
129
+ variant: 'danger',
130
+ confirmText: 'OK',
131
+ });
132
+ }
133
+ });
134
+ }, [generateReportLinkMutate, intl, showToast, showModal, startPolling]);
135
+ const handleGenerateProblemResponsesReport = useCallback((problemLocation) => {
136
+ // Clear any previous error
137
+ setProblemResponsesError(undefined);
138
+ generateReportLinkMutate({
139
+ reportType: 'problem_responses',
140
+ problemLocation,
141
+ }, {
142
+ onSuccess: () => {
143
+ const reportTypeName = getReportTypeDisplayName('problem_responses', intl);
144
+ showToast(intl.formatMessage(messages.generateReportSuccess, { reportType: reportTypeName }));
145
+ // Start polling for 60 seconds to check for the new report
146
+ startPolling();
147
+ },
148
+ onError: (error) => {
149
+ var _a, _b;
150
+ console.error('Error generating report:', error);
151
+ const errorMessage = ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) || intl.formatMessage(messages.generateReportError);
152
+ setProblemResponsesError(errorMessage);
153
+ }
154
+ });
155
+ }, [generateReportLinkMutate, intl, showToast, startPolling]);
156
+ if (is404) {
157
+ return _jsx(PageNotFound, {});
158
+ }
159
+ return (_jsxs(_Fragment, { children: [_jsx("h3", { className: "text-primary-700", children: intl.formatMessage(messages.dataDownloadsTitle) }), _jsx("p", { className: "text-primary-700", children: intl.formatMessage(messages.dataDownloadsDescription) }), _jsx("p", { className: "text-primary-700", children: intl.formatMessage(messages.dataDownloadsReportExpirationPolicyMessage) }), _jsx(DataDownloadTable, { data: data, isLoading: isLoading, onDownloadClick: handleDownload }), _jsx(GenerateReports, { onGenerateReport: handleGenerateReport, onGenerateProblemResponsesReport: handleGenerateProblemResponsesReport, isGenerating: isGenerating, problemResponsesError: problemResponsesError }), _jsx(PendingTasks, {})] }));
160
+ };
161
+ export default DataDownloadsPage;
162
+ //# sourceMappingURL=DataDownloadsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataDownloadsPage.js","sourceRoot":"","sources":["../../src/dataDownloads/DataDownloadsPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import messages from './messages';\nimport { useIntl, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { DataDownloadTable } from './components/DataDownloadTable';\nimport { GenerateReports } from './components/GenerateReports';\nimport { useParams } from 'react-router-dom';\nimport { useGeneratedReports, useGenerateReportLink } from './data/apiHook';\nimport { useCallback, useState, useRef, useEffect } from 'react';\nimport { getApiBaseUrl } from '@src/data/api';\nimport { getReportTypeDisplayName } from './utils';\nimport PageNotFound from '@src/components/PageNotFound';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { PendingTasks } from '@src/components/PendingTasks';\n\nconst DataDownloadsPage = () => {\n const intl = useIntl();\n const { courseId = '' } = useParams<{ courseId: string }>();\n const [isPolling, setIsPolling] = useState(false);\n const [problemResponsesError, setProblemResponsesError] = useState<string | undefined>(undefined);\n const { showToast, showModal } = useAlert();\n const pollingTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const initialReportCountRef = useRef<number | null>(null);\n\n const { data: reportsData, isLoading, error } = useGeneratedReports(courseId, { enablePolling: isPolling });\n const { mutate: generateReportLinkMutate, isPending: isGenerating } = useGenerateReportLink(courseId);\n\n // Check if we got a 404 error\n const is404 = (error as any)?.response?.status === 404;\n\n // Cleanup polling timeout on unmount\n useEffect(() => {\n return () => {\n if (pollingTimeoutRef.current) {\n clearTimeout(pollingTimeoutRef.current);\n }\n };\n }, []);\n\n // Stop polling when new reports appear\n useEffect(() => {\n if (!isPolling || !reportsData?.downloads) {\n return;\n }\n\n const currentCount = reportsData.downloads.length;\n\n // If we have a baseline count and it has increased, stop polling\n if (initialReportCountRef.current !== null && currentCount > initialReportCountRef.current) {\n setIsPolling(false);\n if (pollingTimeoutRef.current) {\n clearTimeout(pollingTimeoutRef.current);\n pollingTimeoutRef.current = null;\n }\n initialReportCountRef.current = null;\n }\n }, [reportsData?.downloads, isPolling]);\n\n const startPolling = useCallback(() => {\n // Clear any existing timeout before starting new one\n if (pollingTimeoutRef.current) {\n clearTimeout(pollingTimeoutRef.current);\n }\n\n // Store the current report count as baseline\n initialReportCountRef.current = reportsData?.downloads?.length ?? 0;\n\n setIsPolling(true);\n pollingTimeoutRef.current = setTimeout(() => {\n setIsPolling(false);\n pollingTimeoutRef.current = null;\n initialReportCountRef.current = null;\n }, 60000);\n }, [reportsData?.downloads?.length]);\n\n // Extract downloads array from API response and transform to match expected format\n const data = reportsData?.downloads?.map(report => ({\n dateGenerated: report.dateGenerated,\n reportType: getReportTypeDisplayName(report.reportType, intl),\n reportName: report.reportName,\n downloadLink: report.reportUrl, // Map reportUrl to downloadLink\n })) ?? [];\n\n const handleDownload = useCallback(async (downloadLink: string, reportName: string) => {\n try {\n // The downloadLink is a relative path, so we need to prepend the LMS base URL\n const baseUrl = getApiBaseUrl();\n const fullUrl = downloadLink.startsWith('http') ? downloadLink : `${baseUrl}${downloadLink}`;\n\n // Use authenticated HTTP client to fetch the file as a blob\n const response = await getAuthenticatedHttpClient().get(fullUrl, {\n responseType: 'blob',\n });\n\n // Use the reportName from the API as the filename\n const filename = reportName || 'report.csv';\n\n // Create blob URL and trigger download\n const blob = new Blob([response.data]);\n const blobUrl = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = blobUrl;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n // Clean up blob URL\n window.URL.revokeObjectURL(blobUrl);\n } catch (error) {\n showModal({\n title: intl.formatMessage(messages.downloadReportError),\n message: intl.formatMessage(messages.downloadReportError),\n variant: 'danger',\n confirmText: 'OK',\n });\n }\n }, [intl, showModal]);\n\n const handleGenerateReport = useCallback((reportType: string) => {\n generateReportLinkMutate(\n { reportType },\n {\n onSuccess: () => {\n const reportTypeName = getReportTypeDisplayName(reportType, intl);\n showToast(\n intl.formatMessage(messages.generateReportSuccess, { reportType: reportTypeName }),\n );\n // Start polling for 60 seconds to check for the new report\n startPolling();\n },\n onError: (error: any) => {\n console.error('Error generating report:', error);\n const errorMessage = error?.response?.data?.error || intl.formatMessage(messages.generateReportError);\n showModal({\n title: intl.formatMessage(messages.generateReportError),\n message: errorMessage,\n variant: 'danger',\n confirmText: 'OK',\n });\n }\n }\n );\n }, [generateReportLinkMutate, intl, showToast, showModal, startPolling]);\n\n const handleGenerateProblemResponsesReport = useCallback((problemLocation?: string) => {\n // Clear any previous error\n setProblemResponsesError(undefined);\n\n generateReportLinkMutate(\n {\n reportType: 'problem_responses',\n problemLocation,\n },\n {\n onSuccess: () => {\n const reportTypeName = getReportTypeDisplayName('problem_responses', intl);\n showToast(\n intl.formatMessage(messages.generateReportSuccess, { reportType: reportTypeName }),\n );\n // Start polling for 60 seconds to check for the new report\n startPolling();\n },\n onError: (error: any) => {\n console.error('Error generating report:', error);\n const errorMessage = error?.response?.data?.error || intl.formatMessage(messages.generateReportError);\n setProblemResponsesError(errorMessage);\n }\n }\n );\n }, [generateReportLinkMutate, intl, showToast, startPolling]);\n\n if (is404) {\n return <PageNotFound />;\n }\n\n return (\n <>\n <h3 className=\"text-primary-700\">{intl.formatMessage(messages.dataDownloadsTitle)}</h3>\n <p className=\"text-primary-700\">{intl.formatMessage(messages.dataDownloadsDescription)}</p>\n <p className=\"text-primary-700\">{intl.formatMessage(messages.dataDownloadsReportExpirationPolicyMessage)}</p>\n <DataDownloadTable data={data} isLoading={isLoading} onDownloadClick={handleDownload} />\n <GenerateReports\n onGenerateReport={handleGenerateReport}\n onGenerateProblemResponsesReport={handleGenerateProblemResponsesReport}\n isGenerating={isGenerating}\n problemResponsesError={problemResponsesError}\n />\n <PendingTasks />\n </>\n );\n};\n\nexport default DataDownloadsPage;\n"]}
@@ -0,0 +1,8 @@
1
+ import { DownloadReportData } from '../../dataDownloads/types';
2
+ interface DataDownloadTableProps {
3
+ data: DownloadReportData[];
4
+ isLoading: boolean;
5
+ onDownloadClick: (downloadLink: string, reportName: string) => void;
6
+ }
7
+ declare const DataDownloadTable: ({ data, isLoading, onDownloadClick }: DataDownloadTableProps) => import("react/jsx-runtime").JSX.Element;
8
+ export { DataDownloadTable };
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useIntl } from '@openedx/frontend-base';
3
+ import { DataTable } from '@openedx/paragon';
4
+ import { useCallback, useMemo } from 'react';
5
+ import messages from '../../dataDownloads/messages';
6
+ import { DownloadLinkCell } from './DownloadLinkCell';
7
+ import { ReportNameCell } from './ReportNameCell';
8
+ const DEFAULT_PAGE_SIZE = 10;
9
+ const DataDownloadTable = ({ data, isLoading, onDownloadClick }) => {
10
+ const intl = useIntl();
11
+ const pageCount = Math.ceil(data.length / DEFAULT_PAGE_SIZE);
12
+ const tableColumns = useMemo(() => [
13
+ {
14
+ accessor: 'dateGenerated',
15
+ Header: intl.formatMessage(messages.dateGeneratedColumnName),
16
+ },
17
+ {
18
+ accessor: 'reportType',
19
+ Header: intl.formatMessage(messages.reportTypeColumnName),
20
+ },
21
+ ], [intl]);
22
+ const DownloadCustomCell = useCallback(({ row }) => {
23
+ return _jsx(DownloadLinkCell, { row: row, onDownloadClick: onDownloadClick });
24
+ }, [onDownloadClick]);
25
+ return (_jsxs(DataTable, { columns: tableColumns, data: data, isLoading: isLoading, isSortable: true, isPaginated: true, itemCount: data.length, pageCount: pageCount, initialState: {
26
+ pageSize: DEFAULT_PAGE_SIZE,
27
+ pageIndex: 0,
28
+ }, additionalColumns: [
29
+ {
30
+ id: 'reportName',
31
+ Header: intl.formatMessage(messages.reportNameColumnName),
32
+ Cell: ReportNameCell,
33
+ },
34
+ {
35
+ id: 'downloadLink',
36
+ Header: '',
37
+ Cell: DownloadCustomCell,
38
+ }
39
+ ], RowStatusComponent: () => null, children: [_jsx(DataTable.Table, {}), _jsx(DataTable.EmptyTable, { content: intl.formatMessage(messages.noReportsFoundMessage) }), pageCount > 1 && (_jsxs(DataTable.TableFooter, { children: [_jsx(DataTable.RowStatus, {}), _jsx(DataTable.TablePagination, {}), _jsx(DataTable.TablePaginationMinimal, {})] }))] }));
40
+ };
41
+ export { DataDownloadTable };
42
+ //# sourceMappingURL=DataDownloadTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataDownloadTable.js","sourceRoot":"","sources":["../../../src/dataDownloads/components/DataDownloadTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,QAAQ,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAQlD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,MAAM,iBAAiB,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAA0B,EAAE,EAAE;IACzF,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAC;IAE7D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACjC;YACE,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,uBAAuB,CAAC;SAC7D;QACD;YACE,QAAQ,EAAE,YAAY;YACtB,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC;SAC1D;KACF,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,kBAAkB,GAAG,WAAW,CAAC,CAAC,EAAE,GAAG,EAAgB,EAAE,EAAE;QAC/D,OAAO,KAAC,gBAAgB,IAAC,GAAG,EAAE,GAAG,EAAE,eAAe,EAAE,eAAe,GAAI,CAAC;IAC1E,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,OAAO,CACL,MAAC,SAAS,IACR,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,UAAU,QACV,WAAW,QACX,SAAS,EAAE,IAAI,CAAC,MAAM,EACtB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE;YACZ,QAAQ,EAAE,iBAAiB;YAC3B,SAAS,EAAE,CAAC;SACb,EACD,iBAAiB,EAAE;YACjB;gBACE,EAAE,EAAE,YAAY;gBAChB,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC;gBACzD,IAAI,EAAE,cAAc;aACrB;YACD;gBACE,EAAE,EAAE,cAAc;gBAClB,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,kBAAkB;aACzB;SACF,EACD,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI,aAE9B,KAAC,SAAS,CAAC,KAAK,KAAG,EACnB,KAAC,SAAS,CAAC,UAAU,IAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAI,EACpF,SAAS,GAAG,CAAC,IAAI,CAChB,MAAC,SAAS,CAAC,WAAW,eACpB,KAAC,SAAS,CAAC,SAAS,KAAG,EACvB,KAAC,SAAS,CAAC,eAAe,KAAG,EAC7B,KAAC,SAAS,CAAC,sBAAsB,KAAG,IACd,CACzB,IACS,CACb,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import { useIntl } from '@openedx/frontend-base';\nimport { DataTable } from '@openedx/paragon';\nimport { useCallback, useMemo } from 'react';\nimport messages from '@src/dataDownloads/messages';\nimport { DownloadLinkCell } from './DownloadLinkCell';\nimport { DownloadReportData } from '@src/dataDownloads/types';\nimport { ReportNameCell } from './ReportNameCell';\n\ninterface DataDownloadTableProps {\n data: DownloadReportData[],\n isLoading: boolean,\n onDownloadClick: (downloadLink: string, reportName: string) => void,\n}\n\nconst DEFAULT_PAGE_SIZE = 10;\n\nconst DataDownloadTable = ({ data, isLoading, onDownloadClick }: DataDownloadTableProps) => {\n const intl = useIntl();\n const pageCount = Math.ceil(data.length / DEFAULT_PAGE_SIZE);\n\n const tableColumns = useMemo(() => [\n {\n accessor: 'dateGenerated',\n Header: intl.formatMessage(messages.dateGeneratedColumnName),\n },\n {\n accessor: 'reportType',\n Header: intl.formatMessage(messages.reportTypeColumnName),\n },\n ], [intl]);\n\n const DownloadCustomCell = useCallback(({ row }: { row: any }) => {\n return <DownloadLinkCell row={row} onDownloadClick={onDownloadClick} />;\n }, [onDownloadClick]);\n\n return (\n <DataTable\n columns={tableColumns}\n data={data}\n isLoading={isLoading}\n isSortable\n isPaginated\n itemCount={data.length}\n pageCount={pageCount}\n initialState={{\n pageSize: DEFAULT_PAGE_SIZE,\n pageIndex: 0,\n }}\n additionalColumns={[\n {\n id: 'reportName',\n Header: intl.formatMessage(messages.reportNameColumnName),\n Cell: ReportNameCell,\n },\n {\n id: 'downloadLink',\n Header: '',\n Cell: DownloadCustomCell,\n }\n ]}\n RowStatusComponent={() => null}\n >\n <DataTable.Table />\n <DataTable.EmptyTable content={intl.formatMessage(messages.noReportsFoundMessage)} />\n {pageCount > 1 && (\n <DataTable.TableFooter>\n <DataTable.RowStatus />\n <DataTable.TablePagination />\n <DataTable.TablePaginationMinimal />\n </DataTable.TableFooter>\n )}\n </DataTable>\n );\n};\n\nexport { DataDownloadTable };\n"]}
@@ -0,0 +1,6 @@
1
+ import { DataDownloadsCellProps } from '../../dataDownloads/types';
2
+ interface DownloadLinkCellProps extends DataDownloadsCellProps {
3
+ onDownloadClick: (downloadLink: string, reportName: string) => void;
4
+ }
5
+ declare const DownloadLinkCell: ({ row, onDownloadClick }: DownloadLinkCellProps) => import("react/jsx-runtime").JSX.Element;
6
+ export { DownloadLinkCell };