@openedx/frontend-app-instructor-dashboard 1.0.0-alpha.4 → 1.0.0-alpha.41
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.
- package/dist/Main.d.ts +1 -1
- package/dist/Main.js +11 -18
- package/dist/Main.js.map +1 -1
- package/dist/app.js +0 -6
- package/dist/app.js.map +1 -1
- package/dist/certificates/CertificatesPage.d.ts +1 -0
- package/dist/certificates/CertificatesPage.js +315 -2
- package/dist/certificates/CertificatesPage.js.map +1 -1
- package/dist/certificates/CertificatesPage.scss +90 -0
- package/dist/certificates/components/CertificateTable.d.ts +14 -0
- package/dist/certificates/components/CertificateTable.js +88 -0
- package/dist/certificates/components/CertificateTable.js.map +1 -0
- package/dist/certificates/components/CertificatesPageHeader.d.ts +7 -0
- package/dist/certificates/components/CertificatesPageHeader.js +11 -0
- package/dist/certificates/components/CertificatesPageHeader.js.map +1 -0
- package/dist/certificates/components/CertificatesToolbar.d.ts +11 -0
- package/dist/certificates/components/CertificatesToolbar.js +33 -0
- package/dist/certificates/components/CertificatesToolbar.js.map +1 -0
- package/dist/certificates/components/DisableCertificatesModal.d.ts +9 -0
- package/dist/certificates/components/DisableCertificatesModal.js +24 -0
- package/dist/certificates/components/DisableCertificatesModal.js.map +1 -0
- package/dist/certificates/components/FilterDropdown.d.ts +8 -0
- package/dist/certificates/components/FilterDropdown.js +50 -0
- package/dist/certificates/components/FilterDropdown.js.map +1 -0
- package/dist/certificates/components/GenerateCertificatesModal.d.ts +9 -0
- package/dist/certificates/components/GenerateCertificatesModal.js +19 -0
- package/dist/certificates/components/GenerateCertificatesModal.js.map +1 -0
- package/dist/certificates/components/GenerationHistoryTable.d.ts +11 -0
- package/dist/certificates/components/GenerationHistoryTable.js +25 -0
- package/dist/certificates/components/GenerationHistoryTable.js.map +1 -0
- package/dist/certificates/components/GrantExceptionsModal.d.ts +9 -0
- package/dist/certificates/components/GrantExceptionsModal.js +55 -0
- package/dist/certificates/components/GrantExceptionsModal.js.map +1 -0
- package/dist/certificates/components/InvalidateCertificateModal.d.ts +8 -0
- package/dist/certificates/components/InvalidateCertificateModal.js +26 -0
- package/dist/certificates/components/InvalidateCertificateModal.js.map +1 -0
- package/dist/certificates/components/IssuedCertificatesTab.d.ts +18 -0
- package/dist/certificates/components/IssuedCertificatesTab.js +6 -0
- package/dist/certificates/components/IssuedCertificatesTab.js.map +1 -0
- package/dist/certificates/components/LearnerActionModal.d.ts +16 -0
- package/dist/certificates/components/LearnerActionModal.js +27 -0
- package/dist/certificates/components/LearnerActionModal.js.map +1 -0
- package/dist/certificates/components/RegenerateCertificatesModal.d.ts +11 -0
- package/dist/certificates/components/RegenerateCertificatesModal.js +46 -0
- package/dist/certificates/components/RegenerateCertificatesModal.js.map +1 -0
- package/dist/certificates/components/RemoveExceptionModal.d.ts +9 -0
- package/dist/certificates/components/RemoveExceptionModal.js +10 -0
- package/dist/certificates/components/RemoveExceptionModal.js.map +1 -0
- package/dist/certificates/components/RemoveInvalidationModal.d.ts +9 -0
- package/dist/certificates/components/RemoveInvalidationModal.js +10 -0
- package/dist/certificates/components/RemoveInvalidationModal.js.map +1 -0
- package/dist/certificates/constants.d.ts +15 -0
- package/dist/certificates/constants.js +16 -0
- package/dist/certificates/constants.js.map +1 -0
- package/dist/certificates/data/api.d.ts +30 -0
- package/dist/certificates/data/api.js +126 -0
- package/dist/certificates/data/api.js.map +1 -0
- package/dist/certificates/data/apiHook.d.ts +63 -0
- package/dist/certificates/data/apiHook.js +133 -0
- package/dist/certificates/data/apiHook.js.map +1 -0
- package/dist/certificates/data/queryKeys.d.ts +9 -0
- package/dist/certificates/data/queryKeys.js +9 -0
- package/dist/certificates/data/queryKeys.js.map +1 -0
- package/dist/certificates/messages.d.ts +548 -0
- package/dist/certificates/messages.js +550 -0
- package/dist/certificates/messages.js.map +1 -0
- package/dist/certificates/types.d.ts +66 -0
- package/dist/certificates/types.js +26 -0
- package/dist/certificates/types.js.map +1 -0
- package/dist/certificates/utils/errorHandling.d.ts +12 -0
- package/dist/certificates/utils/errorHandling.js +24 -0
- package/dist/certificates/utils/errorHandling.js.map +1 -0
- package/dist/certificates/utils/filterUtils.d.ts +4 -0
- package/dist/certificates/utils/filterUtils.js +31 -0
- package/dist/certificates/utils/filterUtils.js.map +1 -0
- package/dist/certificates/utils/index.d.ts +2 -0
- package/dist/certificates/utils/index.js +2 -0
- package/dist/certificates/utils/index.js.map +1 -0
- package/dist/components/ActionCard.d.ts +2 -2
- package/dist/components/ActionCard.js +1 -1
- package/dist/components/ActionCard.js.map +1 -1
- package/dist/components/CodeEditor.d.ts +5 -0
- package/dist/components/CodeEditor.js +34 -0
- package/dist/components/CodeEditor.js.map +1 -0
- package/dist/components/PendingTasks.d.ts +3 -1
- package/dist/components/PendingTasks.js +3 -2
- package/dist/components/PendingTasks.js.map +1 -1
- package/dist/components/SpecifyLearnerField.d.ts +4 -1
- package/dist/components/SpecifyLearnerField.js +55 -15
- package/dist/components/SpecifyLearnerField.js.map +1 -1
- package/dist/components/SpecifyProblemField.d.ts +13 -0
- package/dist/components/SpecifyProblemField.js +52 -0
- package/dist/components/SpecifyProblemField.js.map +1 -0
- package/dist/components/UsernameFilter.d.ts +7 -0
- package/dist/components/UsernameFilter.js +19 -0
- package/dist/components/UsernameFilter.js.map +1 -0
- package/dist/components/messages.d.ts +45 -0
- package/dist/components/messages.js +45 -0
- package/dist/components/messages.js.map +1 -1
- package/dist/courseInfo/types.d.ts +5 -0
- package/dist/courseInfo/types.js.map +1 -1
- package/dist/courseTeam/CourseTeamPage.js +25 -2
- package/dist/courseTeam/CourseTeamPage.js.map +1 -1
- package/dist/courseTeam/components/AddTeamMemberModal.d.ts +6 -0
- package/dist/courseTeam/components/AddTeamMemberModal.js +61 -0
- package/dist/courseTeam/components/AddTeamMemberModal.js.map +1 -0
- package/dist/courseTeam/components/EditTeamMemberModal.d.ts +8 -0
- package/dist/courseTeam/components/EditTeamMemberModal.js +102 -0
- package/dist/courseTeam/components/EditTeamMemberModal.js.map +1 -0
- package/dist/courseTeam/components/MembersContent.d.ts +6 -0
- package/dist/courseTeam/components/MembersContent.js +48 -0
- package/dist/courseTeam/components/MembersContent.js.map +1 -0
- package/dist/courseTeam/components/RoleFilter.d.ts +7 -0
- package/dist/courseTeam/components/RoleFilter.js +22 -0
- package/dist/courseTeam/components/RoleFilter.js.map +1 -0
- package/dist/courseTeam/components/RolesContent.d.ts +3 -0
- package/dist/courseTeam/components/RolesContent.js +25 -0
- package/dist/courseTeam/components/RolesContent.js.map +1 -0
- package/dist/courseTeam/constants.d.ts +3 -0
- package/dist/courseTeam/constants.js +4 -0
- package/dist/courseTeam/constants.js.map +1 -0
- package/dist/courseTeam/data/api.d.ts +6 -0
- package/dist/courseTeam/data/api.js +38 -0
- package/dist/courseTeam/data/api.js.map +1 -0
- package/dist/courseTeam/data/apiHook.d.ts +8 -0
- package/dist/courseTeam/data/apiHook.js +32 -0
- package/dist/courseTeam/data/apiHook.js.map +1 -0
- package/dist/courseTeam/data/queryKeys.d.ts +7 -0
- package/dist/courseTeam/data/queryKeys.js +14 -0
- package/dist/courseTeam/data/queryKeys.js.map +1 -0
- package/dist/courseTeam/messages.d.ts +258 -0
- package/dist/courseTeam/messages.js +260 -0
- package/dist/courseTeam/messages.js.map +1 -0
- package/dist/courseTeam/types.d.ts +29 -0
- package/dist/courseTeam/types.js +3 -0
- package/dist/courseTeam/types.js.map +1 -0
- package/dist/data/api.d.ts +2 -1
- package/dist/data/api.js +9 -3
- package/dist/data/api.js.map +1 -1
- package/dist/data/apiHook.d.ts +1 -0
- package/dist/data/apiHook.js +11 -2
- package/dist/data/apiHook.js.map +1 -1
- package/dist/data/queryKeys.d.ts +4 -0
- package/dist/data/queryKeys.js +4 -0
- package/dist/data/queryKeys.js.map +1 -1
- package/dist/data/utils.d.ts +2 -0
- package/dist/data/utils.js +9 -0
- package/dist/data/utils.js.map +1 -0
- package/dist/dateExtensions/components/AddExtensionModal.d.ts +1 -1
- package/dist/dateExtensions/components/AddExtensionModal.js +6 -7
- package/dist/dateExtensions/components/AddExtensionModal.js.map +1 -1
- package/dist/dateExtensions/components/DateExtensionsList.js +3 -14
- package/dist/dateExtensions/components/DateExtensionsList.js.map +1 -1
- package/dist/dateExtensions/data/apiHook.d.ts +2 -2
- package/dist/dateExtensions/data/apiHook.js +4 -4
- package/dist/dateExtensions/data/apiHook.js.map +1 -1
- package/dist/dateExtensions/messages.d.ts +0 -5
- package/dist/dateExtensions/messages.js +1 -6
- package/dist/dateExtensions/messages.js.map +1 -1
- package/dist/enrollments/EnrollmentsPage.js +34 -7
- package/dist/enrollments/EnrollmentsPage.js.map +1 -1
- package/dist/enrollments/components/AddBetaTestersModal.d.ts +6 -0
- package/dist/enrollments/components/AddBetaTestersModal.js +69 -0
- package/dist/enrollments/components/AddBetaTestersModal.js.map +1 -0
- package/dist/enrollments/components/EnrollLearnersModal.d.ts +6 -0
- package/dist/enrollments/components/EnrollLearnersModal.js +53 -0
- package/dist/enrollments/components/EnrollLearnersModal.js.map +1 -0
- package/dist/enrollments/components/EnrollmentStatusModal.js +3 -3
- package/dist/enrollments/components/EnrollmentStatusModal.js.map +1 -1
- package/dist/enrollments/components/EnrollmentsList.d.ts +3 -2
- package/dist/enrollments/components/EnrollmentsList.js +13 -14
- package/dist/enrollments/components/EnrollmentsList.js.map +1 -1
- package/dist/enrollments/components/UnenrollModal.d.ts +1 -1
- package/dist/enrollments/components/UnenrollModal.js +29 -3
- package/dist/enrollments/components/UnenrollModal.js.map +1 -1
- package/dist/enrollments/components/UpdateBetaTesterModal.d.ts +8 -0
- package/dist/enrollments/components/UpdateBetaTesterModal.js +72 -0
- package/dist/enrollments/components/UpdateBetaTesterModal.js.map +1 -0
- package/dist/enrollments/data/api.d.ts +3 -1
- package/dist/enrollments/data/api.js +11 -1
- package/dist/enrollments/data/api.js.map +1 -1
- package/dist/enrollments/data/apiHook.d.ts +5 -3
- package/dist/enrollments/data/apiHook.js +21 -3
- package/dist/enrollments/data/apiHook.js.map +1 -1
- package/dist/enrollments/data/queryKeys.d.ts +1 -1
- package/dist/enrollments/data/queryKeys.js.map +1 -1
- package/dist/enrollments/messages.d.ts +131 -1
- package/dist/enrollments/messages.js +136 -6
- package/dist/enrollments/messages.js.map +1 -1
- package/dist/enrollments/types.d.ts +25 -0
- package/dist/enrollments/types.js.map +1 -1
- package/dist/grading/GradingPage.js +15 -2
- package/dist/grading/GradingPage.js.map +1 -1
- package/dist/grading/components/GradingActionRow.d.ts +2 -0
- package/dist/grading/components/GradingActionRow.js +20 -0
- package/dist/grading/components/GradingActionRow.js.map +1 -0
- package/dist/grading/components/GradingConfigurationModal.d.ts +6 -0
- package/dist/grading/components/GradingConfigurationModal.js +15 -0
- package/dist/grading/components/GradingConfigurationModal.js.map +1 -0
- package/dist/grading/components/GradingLearnerContent.d.ts +7 -0
- package/dist/grading/components/GradingLearnerContent.js +199 -0
- package/dist/grading/components/GradingLearnerContent.js.map +1 -0
- package/dist/grading/data/api.d.ts +6 -0
- package/dist/grading/data/api.js +59 -0
- package/dist/grading/data/api.js.map +1 -0
- package/dist/grading/data/apiHook.d.ts +6 -0
- package/dist/grading/data/apiHook.js +29 -0
- package/dist/grading/data/apiHook.js.map +1 -0
- package/dist/grading/data/queryKeys.d.ts +9 -0
- package/dist/grading/data/queryKeys.js +8 -0
- package/dist/grading/data/queryKeys.js.map +1 -0
- package/dist/grading/messages.d.ts +248 -0
- package/dist/grading/messages.js +250 -0
- package/dist/grading/messages.js.map +1 -0
- package/dist/grading/types.d.ts +11 -0
- package/dist/grading/types.js +2 -0
- package/dist/grading/types.js.map +1 -0
- package/dist/hooks/useDebouncedFilter.d.ts +1 -0
- package/dist/hooks/useDebouncedFilter.js +5 -0
- package/dist/hooks/useDebouncedFilter.js.map +1 -1
- package/dist/instructorNav/InstructorNav.js +16 -4
- package/dist/instructorNav/InstructorNav.js.map +1 -1
- package/dist/messages.d.ts +8 -0
- package/dist/messages.js +10 -0
- package/dist/messages.js.map +1 -0
- package/dist/pageWrapper/PageWrapper.js +3 -1
- package/dist/pageWrapper/PageWrapper.js.map +1 -1
- package/dist/providers/AccessErrorObserver.d.ts +9 -0
- package/dist/providers/AccessErrorObserver.js +35 -0
- package/dist/providers/AccessErrorObserver.js.map +1 -0
- package/dist/providers/AccessErrorProvider.d.ts +19 -0
- package/dist/providers/AccessErrorProvider.js +51 -0
- package/dist/providers/AccessErrorProvider.js.map +1 -0
- package/dist/providers/AlertProvider.js +1 -1
- package/dist/providers/AlertProvider.js.map +1 -1
- package/dist/providers/messages.d.ts +33 -0
- package/dist/providers/messages.js +35 -0
- package/dist/providers/messages.js.map +1 -0
- package/dist/provides.d.ts +2 -1
- package/dist/provides.js +3 -2
- package/dist/provides.js.map +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/routes.js +2 -2
- package/dist/routes.js.map +1 -1
- package/dist/slots/CourseInfoSlot/CourseInfoSlot.d.ts +2 -0
- package/dist/slots/CourseInfoSlot/CourseInfoSlot.js +14 -0
- package/dist/slots/CourseInfoSlot/CourseInfoSlot.js.map +1 -0
- package/dist/slots.js +13 -1
- package/dist/slots.js.map +1 -1
- package/dist/specialExams/SpecialExamsPage.js +14 -2
- package/dist/specialExams/SpecialExamsPage.js.map +1 -1
- package/dist/specialExams/components/AddAllowanceModal.d.ts +6 -0
- package/dist/specialExams/components/AddAllowanceModal.js +84 -0
- package/dist/specialExams/components/AddAllowanceModal.js.map +1 -0
- package/dist/specialExams/components/Allowances.d.ts +2 -0
- package/dist/specialExams/components/Allowances.js +89 -0
- package/dist/specialExams/components/Allowances.js.map +1 -0
- package/dist/specialExams/components/AllowancesList.d.ts +8 -0
- package/dist/specialExams/components/AllowancesList.js +63 -0
- package/dist/specialExams/components/AllowancesList.js.map +1 -0
- package/dist/specialExams/components/AttemptsList.d.ts +3 -0
- package/dist/specialExams/components/AttemptsList.js +50 -0
- package/dist/specialExams/components/AttemptsList.js.map +1 -0
- package/dist/specialExams/components/DeleteAllowanceModal.d.ts +8 -0
- package/dist/specialExams/components/DeleteAllowanceModal.js +29 -0
- package/dist/specialExams/components/DeleteAllowanceModal.js.map +1 -0
- package/dist/specialExams/components/EditAllowanceModal.d.ts +8 -0
- package/dist/specialExams/components/EditAllowanceModal.js +62 -0
- package/dist/specialExams/components/EditAllowanceModal.js.map +1 -0
- package/dist/specialExams/constants.d.ts +43 -0
- package/dist/specialExams/constants.js +19 -0
- package/dist/specialExams/constants.js.map +1 -0
- package/dist/specialExams/data/api.d.ts +7 -0
- package/dist/specialExams/data/api.js +55 -0
- package/dist/specialExams/data/api.js.map +1 -0
- package/dist/specialExams/data/apiHook.d.ts +6 -0
- package/dist/specialExams/data/apiHook.js +37 -0
- package/dist/specialExams/data/apiHook.js.map +1 -0
- package/dist/specialExams/data/queryKeys.d.ts +8 -0
- package/dist/specialExams/data/queryKeys.js +9 -0
- package/dist/specialExams/data/queryKeys.js.map +1 -0
- package/dist/specialExams/messages.d.ts +228 -0
- package/dist/specialExams/messages.js +230 -0
- package/dist/specialExams/messages.js.map +1 -0
- package/dist/specialExams/types.d.ts +65 -0
- package/dist/specialExams/types.js +2 -0
- package/dist/specialExams/types.js.map +1 -0
- package/dist/style.scss +16 -0
- package/dist/testUtils.js +2 -2
- package/dist/testUtils.js.map +1 -1
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/formatters.d.ts +5 -0
- package/dist/utils/formatters.js +10 -0
- package/dist/utils/formatters.js.map +1 -1
- package/package.json +6 -6
- package/dist/app.scss +0 -10
- package/dist/providers/QueryProvider.d.ts +0 -6
- package/dist/providers/QueryProvider.js +0 -16
- package/dist/providers/QueryProvider.js.map +0 -1
- package/dist/providers.d.ts +0 -3
- package/dist/providers.js +0 -8
- package/dist/providers.js.map +0 -1
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { defineMessages } from '@openedx/frontend-base';
|
|
2
|
+
const messages = defineMessages({
|
|
3
|
+
pageTitle: {
|
|
4
|
+
id: 'instruct.grading.pageTitle',
|
|
5
|
+
defaultMessage: 'Grading Tools',
|
|
6
|
+
description: 'Title for the grading page'
|
|
7
|
+
},
|
|
8
|
+
configurationAlt: {
|
|
9
|
+
id: 'instruct.grading.configurationAlt',
|
|
10
|
+
defaultMessage: 'Grading Configuration and Settings',
|
|
11
|
+
description: 'Alt text for the configuration icon button'
|
|
12
|
+
},
|
|
13
|
+
viewGradebook: {
|
|
14
|
+
id: 'instruct.grading.viewGradebook',
|
|
15
|
+
defaultMessage: 'View Gradebook',
|
|
16
|
+
description: 'Text for the button to view the gradebook'
|
|
17
|
+
},
|
|
18
|
+
singleLearner: {
|
|
19
|
+
id: 'instruct.grading.singleLearner',
|
|
20
|
+
defaultMessage: 'Single Learner',
|
|
21
|
+
description: 'Single Learner button label to display corresponding grading tools'
|
|
22
|
+
},
|
|
23
|
+
allLearners: {
|
|
24
|
+
id: 'instruct.grading.allLearners',
|
|
25
|
+
defaultMessage: 'All Learners',
|
|
26
|
+
description: 'All learners button label to display corresponding grading tools'
|
|
27
|
+
},
|
|
28
|
+
descriptionSingleLearner: {
|
|
29
|
+
id: 'instruct.grading.descriptionSingleLearner',
|
|
30
|
+
defaultMessage: 'These grading tools allow for grade review and adjustment for a specific learner on a specific problem.',
|
|
31
|
+
description: 'Description for single learner grading tools'
|
|
32
|
+
},
|
|
33
|
+
descriptionAllLearners: {
|
|
34
|
+
id: 'instruct.grading.descriptionAllLearners',
|
|
35
|
+
defaultMessage: 'These grading tools allow for grade review and adjustment all enrolled learners on a specific problem.',
|
|
36
|
+
description: 'Description for all learners grading tools'
|
|
37
|
+
},
|
|
38
|
+
gradingConfiguration: {
|
|
39
|
+
id: 'instruct.grading.gradingConfiguration',
|
|
40
|
+
defaultMessage: 'Grading Configuration',
|
|
41
|
+
description: 'Title for the grading configuration modal'
|
|
42
|
+
},
|
|
43
|
+
close: {
|
|
44
|
+
id: 'instruct.grading.modals.close',
|
|
45
|
+
defaultMessage: 'Close',
|
|
46
|
+
description: 'Text for the close button in the grading configuration modal'
|
|
47
|
+
},
|
|
48
|
+
viewGradingConfiguration: {
|
|
49
|
+
id: 'instruct.grading.viewGradingConfiguration',
|
|
50
|
+
defaultMessage: 'View Grading Configuration',
|
|
51
|
+
description: 'View grading configuration menu item label'
|
|
52
|
+
},
|
|
53
|
+
viewCourseGradingSettings: {
|
|
54
|
+
id: 'instruct.grading.viewCourseGradingSettings',
|
|
55
|
+
defaultMessage: 'View Course Grading Settings',
|
|
56
|
+
description: 'View course grading settings menu item label'
|
|
57
|
+
},
|
|
58
|
+
noGradingConfiguration: {
|
|
59
|
+
id: 'instruct.grading.noGradingConfiguration',
|
|
60
|
+
defaultMessage: 'No grading configuration found for this course.',
|
|
61
|
+
description: 'Message to display when there is no grading configuration for the course'
|
|
62
|
+
},
|
|
63
|
+
resetAttempts: {
|
|
64
|
+
id: 'instruct.grading.resetAttempts',
|
|
65
|
+
defaultMessage: 'Reset Attempts',
|
|
66
|
+
description: 'Title for the reset attempts action card'
|
|
67
|
+
},
|
|
68
|
+
resetAttemptsDescription: {
|
|
69
|
+
id: 'instruct.grading.resetAttemptsDescription',
|
|
70
|
+
defaultMessage: 'Allow a learner who has used up all attempts to work on the problem again.',
|
|
71
|
+
description: 'Description for the reset attempts action card'
|
|
72
|
+
},
|
|
73
|
+
resetAttemptsButtonLabel: {
|
|
74
|
+
id: 'instruct.grading.resetAttemptsButtonLabel',
|
|
75
|
+
defaultMessage: 'Reset Attempts to Zero',
|
|
76
|
+
description: 'Button label for the reset attempts action card'
|
|
77
|
+
},
|
|
78
|
+
rescoreSubmission: {
|
|
79
|
+
id: 'instruct.grading.rescoreSubmission',
|
|
80
|
+
defaultMessage: 'Rescore Submission',
|
|
81
|
+
description: 'Title for the rescore submission action card'
|
|
82
|
+
},
|
|
83
|
+
rescoreSubmissionDescription: {
|
|
84
|
+
id: 'instruct.grading.rescoreSubmissionDescription',
|
|
85
|
+
defaultMessage: 'For the specified problem, two tools exist for rescoring learner responses.',
|
|
86
|
+
description: 'Description for the rescore submission action card'
|
|
87
|
+
},
|
|
88
|
+
rescoreSubmissionButtonLabel: {
|
|
89
|
+
id: 'instruct.grading.rescoreSubmissionButtonLabel',
|
|
90
|
+
defaultMessage: 'Rescore Learner\'s Submission',
|
|
91
|
+
description: 'Button label for the rescore submission action card'
|
|
92
|
+
},
|
|
93
|
+
rescoreIfImprovesScoreButtonLabel: {
|
|
94
|
+
id: 'instruct.grading.rescoreIfImprovesScoreButtonLabel',
|
|
95
|
+
defaultMessage: 'Rescore Only if Score Improves',
|
|
96
|
+
description: 'Button label for the rescore if improves score action in the rescore submission'
|
|
97
|
+
},
|
|
98
|
+
overrideScore: {
|
|
99
|
+
id: 'instruct.grading.overrideScore',
|
|
100
|
+
defaultMessage: 'Override Score',
|
|
101
|
+
description: 'Title for the override score action card'
|
|
102
|
+
},
|
|
103
|
+
overrideScoreDescription: {
|
|
104
|
+
id: 'instruct.grading.overrideScoreDescription',
|
|
105
|
+
defaultMessage: 'For the specified problem, override the learner\'s score. Input the new score, out of the total points available for this problem.',
|
|
106
|
+
description: 'Description for the override score action card'
|
|
107
|
+
},
|
|
108
|
+
overrideScoreButtonLabel: {
|
|
109
|
+
id: 'instruct.grading.overrideScoreButtonLabel',
|
|
110
|
+
defaultMessage: 'Override Learner\'s Score',
|
|
111
|
+
description: 'Button label for the override score action card'
|
|
112
|
+
},
|
|
113
|
+
deleteHistory: {
|
|
114
|
+
id: 'instruct.grading.deleteHistory',
|
|
115
|
+
defaultMessage: 'Delete History',
|
|
116
|
+
description: 'Title for the delete history action card'
|
|
117
|
+
},
|
|
118
|
+
deleteHistoryDescription: {
|
|
119
|
+
id: 'instruct.grading.deleteHistoryDescription',
|
|
120
|
+
defaultMessage: 'For the specified problem, permanently and completely delete the learner\'s answers and scores from the database.',
|
|
121
|
+
description: 'Description for the delete history action card'
|
|
122
|
+
},
|
|
123
|
+
deleteHistoryButtonLabel: {
|
|
124
|
+
id: 'instruct.grading.deleteHistoryButtonLabel',
|
|
125
|
+
defaultMessage: 'Delete Learner\'s State',
|
|
126
|
+
description: 'Button label for the delete history action card'
|
|
127
|
+
},
|
|
128
|
+
taskStatus: {
|
|
129
|
+
id: 'instruct.grading.taskStatus',
|
|
130
|
+
defaultMessage: 'Task Status',
|
|
131
|
+
description: 'Title for the task status action card'
|
|
132
|
+
},
|
|
133
|
+
taskStatusDescription: {
|
|
134
|
+
id: 'instruct.grading.taskStatusDescription',
|
|
135
|
+
defaultMessage: 'Show the status for the tasks that you submitted for this problem.',
|
|
136
|
+
description: 'Description for the task status action card'
|
|
137
|
+
},
|
|
138
|
+
taskStatusButtonLabel: {
|
|
139
|
+
id: 'instruct.grading.taskStatusButtonLabel',
|
|
140
|
+
defaultMessage: 'Show Task Status',
|
|
141
|
+
description: 'Button label for the task status action card'
|
|
142
|
+
},
|
|
143
|
+
specifyProblem: {
|
|
144
|
+
id: 'instruct.grading.specifyProblem',
|
|
145
|
+
defaultMessage: 'Specify Problem:',
|
|
146
|
+
description: 'Label for the specify problem input field'
|
|
147
|
+
},
|
|
148
|
+
select: {
|
|
149
|
+
id: 'instruct.grading.select',
|
|
150
|
+
defaultMessage: 'Select',
|
|
151
|
+
description: 'Label for the select button in the specify problem field'
|
|
152
|
+
},
|
|
153
|
+
overrideScorePlaceholder: {
|
|
154
|
+
id: 'instruct.grading.overrideScorePlaceholder',
|
|
155
|
+
defaultMessage: 'Score',
|
|
156
|
+
description: 'Placeholder text for the override score input field'
|
|
157
|
+
},
|
|
158
|
+
resetAllLearnersAttemptsDescription: {
|
|
159
|
+
id: 'instruct.grading.resetAllLearnersAttemptsDescription',
|
|
160
|
+
defaultMessage: 'Allows all learners to work on the problem again.',
|
|
161
|
+
description: 'Description for the reset attempts action card in the all learners view'
|
|
162
|
+
},
|
|
163
|
+
rescoreSubmissionAllLearnersDescription: {
|
|
164
|
+
id: 'instruct.grading.rescoreSubmissionAllLearnersDescription',
|
|
165
|
+
defaultMessage: 'For the specified problem, rescore all learners\' responses.',
|
|
166
|
+
description: 'Description for the rescore submission action card in the all learners view'
|
|
167
|
+
},
|
|
168
|
+
rescoreAllSubmissionButtonLabel: {
|
|
169
|
+
id: 'instruct.grading.rescoreAllSubmissionButtonLabel',
|
|
170
|
+
defaultMessage: 'Rescore All Learners\' Submissions',
|
|
171
|
+
description: 'Button label for the rescore submission action card in the all learners view'
|
|
172
|
+
},
|
|
173
|
+
currentScore: {
|
|
174
|
+
id: 'instruct.grading.currentScore',
|
|
175
|
+
defaultMessage: 'Current Score',
|
|
176
|
+
description: 'Label for the current score displayed in the single learner view'
|
|
177
|
+
},
|
|
178
|
+
viewProgress: {
|
|
179
|
+
id: 'instruct.grading.viewProgress',
|
|
180
|
+
defaultMessage: 'View Progress Page',
|
|
181
|
+
description: 'Label for the view progress button displayed next to the current score in the single learner view'
|
|
182
|
+
},
|
|
183
|
+
score: {
|
|
184
|
+
id: 'instruct.grading.score',
|
|
185
|
+
defaultMessage: 'Score',
|
|
186
|
+
description: 'Label for the score displayed in the current status section of the single learner view'
|
|
187
|
+
},
|
|
188
|
+
attempts: {
|
|
189
|
+
id: 'instruct.grading.attempts',
|
|
190
|
+
defaultMessage: 'Attempts',
|
|
191
|
+
description: 'Label for the attempts displayed in the current status section of the single learner view'
|
|
192
|
+
},
|
|
193
|
+
rescore: {
|
|
194
|
+
id: 'instruct.grading.rescore',
|
|
195
|
+
defaultMessage: 'Rescore',
|
|
196
|
+
description: 'Label for the rescore confirmation action'
|
|
197
|
+
},
|
|
198
|
+
resetAttemptsConfirmation: {
|
|
199
|
+
id: 'instruct.grading.resetAttemptsConfirmation',
|
|
200
|
+
defaultMessage: 'Reset attempts for {student} on problem "{blockId}"?',
|
|
201
|
+
description: 'Confirmation message for resetting attempts'
|
|
202
|
+
},
|
|
203
|
+
overrideScoreConfirmation: {
|
|
204
|
+
id: 'instruct.grading.overrideScoreConfirmation',
|
|
205
|
+
defaultMessage: 'Override score for {student} for problem "{blockId}"?',
|
|
206
|
+
description: 'Confirmation message for overriding score'
|
|
207
|
+
},
|
|
208
|
+
deleteStateConfirmation: {
|
|
209
|
+
id: 'instruct.grading.deleteStateConfirmation',
|
|
210
|
+
defaultMessage: 'Delete state for student "{student}" on problem "{blockId}"?',
|
|
211
|
+
description: 'Confirmation message for deleting state'
|
|
212
|
+
},
|
|
213
|
+
rescoreConfirmation: {
|
|
214
|
+
id: 'instruct.grading.rescoreConfirmation',
|
|
215
|
+
defaultMessage: 'Rescore problem for {student} for "{blockId}"?',
|
|
216
|
+
description: 'Confirmation message for rescoring a submission'
|
|
217
|
+
},
|
|
218
|
+
deleteStateButtonLabel: {
|
|
219
|
+
id: 'instruct.grading.deleteStateButtonLabel',
|
|
220
|
+
defaultMessage: 'Delete State',
|
|
221
|
+
description: 'Button label for the delete state confirmation action'
|
|
222
|
+
},
|
|
223
|
+
resetAttemptsSuccess: {
|
|
224
|
+
id: 'instruct.grading.resetAttemptsSuccess',
|
|
225
|
+
defaultMessage: 'Successfully reset problem attempts for {student} on problem "{blockId}".',
|
|
226
|
+
description: 'Success message for resetting attempts'
|
|
227
|
+
},
|
|
228
|
+
overrideScoreSuccess: {
|
|
229
|
+
id: 'instruct.grading.overrideScoreSuccess',
|
|
230
|
+
defaultMessage: 'Started task to override the score for {student} on problem "{blockId}". \n \n Click the \'Show Task Status\' button to see the status of the task.',
|
|
231
|
+
description: 'Success message for overriding score'
|
|
232
|
+
},
|
|
233
|
+
rescoreSubmissionSuccess: {
|
|
234
|
+
id: 'instruct.grading.rescoreSubmissionSuccess',
|
|
235
|
+
defaultMessage: 'Successfully started task to rescore problem "{blockId}" for {student}. \n \n Click the \'Show Task Status\' button to see the status of the task.',
|
|
236
|
+
description: 'Success message for rescoring submission'
|
|
237
|
+
},
|
|
238
|
+
deleteHistorySuccess: {
|
|
239
|
+
id: 'instruct.grading.deleteHistorySuccess',
|
|
240
|
+
defaultMessage: 'State for student "{student}" successfully deleted.',
|
|
241
|
+
description: 'Success message for deleting history'
|
|
242
|
+
},
|
|
243
|
+
unexpectedError: {
|
|
244
|
+
id: 'instruct.grading.unexpectedError',
|
|
245
|
+
defaultMessage: 'An unexpected error occurred. Please try again.',
|
|
246
|
+
description: 'Message to display when an unexpected error occurs'
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
export default messages;
|
|
250
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/grading/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,SAAS,EAAE;QACT,EAAE,EAAE,4BAA4B;QAChC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,4BAA4B;KAC1C;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,mCAAmC;QACvC,cAAc,EAAE,oCAAoC;QACpD,WAAW,EAAE,4CAA4C;KAC1D;IACD,aAAa,EAAE;QACb,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,gBAAgB;QAChC,WAAW,EAAE,2CAA2C;KACzD;IACD,aAAa,EAAE;QACb,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,gBAAgB;QAChC,WAAW,EAAE,oEAAoE;KAClF;IACD,WAAW,EAAE;QACX,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,kEAAkE;KAChF;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,yGAAyG;QACzH,WAAW,EAAE,8CAA8C;KAC5D;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,wGAAwG;QACxH,WAAW,EAAE,4CAA4C;KAC1D;IACD,oBAAoB,EAAE;QACpB,EAAE,EAAE,uCAAuC;QAC3C,cAAc,EAAE,uBAAuB;QACvC,WAAW,EAAE,2CAA2C;KACzD;IACD,KAAK,EAAE;QACL,EAAE,EAAE,+BAA+B;QACnC,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,8DAA8D;KAC5E;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,4BAA4B;QAC5C,WAAW,EAAE,4CAA4C;KAC1D;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,4CAA4C;QAChD,cAAc,EAAE,8BAA8B;QAC9C,WAAW,EAAE,8CAA8C;KAC5D;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,iDAAiD;QACjE,WAAW,EAAE,0EAA0E;KACxF;IACD,aAAa,EAAE;QACb,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,gBAAgB;QAChC,WAAW,EAAE,0CAA0C;KACxD;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,4EAA4E;QAC5F,WAAW,EAAE,gDAAgD;KAC9D;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,wBAAwB;QACxC,WAAW,EAAE,iDAAiD;KAC/D;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,8CAA8C;KAC5D;IACD,4BAA4B,EAAE;QAC5B,EAAE,EAAE,+CAA+C;QACnD,cAAc,EAAE,6EAA6E;QAC7F,WAAW,EAAE,oDAAoD;KAClE;IACD,4BAA4B,EAAE;QAC5B,EAAE,EAAE,+CAA+C;QACnD,cAAc,EAAE,+BAA+B;QAC/C,WAAW,EAAE,qDAAqD;KACnE;IACD,iCAAiC,EAAE;QACjC,EAAE,EAAE,oDAAoD;QACxD,cAAc,EAAE,gCAAgC;QAChD,WAAW,EAAE,iFAAiF;KAC/F;IACD,aAAa,EAAE;QACb,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,gBAAgB;QAChC,WAAW,EAAE,0CAA0C;KACxD;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,oIAAoI;QACpJ,WAAW,EAAE,gDAAgD;KAC9D;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,2BAA2B;QAC3C,WAAW,EAAE,iDAAiD;KAC/D;IACD,aAAa,EAAE;QACb,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,gBAAgB;QAChC,WAAW,EAAE,0CAA0C;KACxD;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,mHAAmH;QACnI,WAAW,EAAE,gDAAgD;KAC9D;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,yBAAyB;QACzC,WAAW,EAAE,iDAAiD;KAC/D;IACD,UAAU,EAAE;QACV,EAAE,EAAE,6BAA6B;QACjC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,uCAAuC;KACrD;IACD,qBAAqB,EAAE;QACrB,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,oEAAoE;QACpF,WAAW,EAAE,6CAA6C;KAC3D;IACD,qBAAqB,EAAE;QACrB,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,8CAA8C;KAC5D;IACD,cAAc,EAAE;QACd,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,kBAAkB;QAClC,WAAW,EAAE,2CAA2C;KACzD;IACD,MAAM,EAAE;QACN,EAAE,EAAE,yBAAyB;QAC7B,cAAc,EAAE,QAAQ;QACxB,WAAW,EAAE,0DAA0D;KACxE;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,qDAAqD;KACnE;IACD,mCAAmC,EAAE;QACnC,EAAE,EAAE,sDAAsD;QAC1D,cAAc,EAAE,mDAAmD;QACnE,WAAW,EAAE,yEAAyE;KACvF;IACD,uCAAuC,EAAE;QACvC,EAAE,EAAE,0DAA0D;QAC9D,cAAc,EAAE,8DAA8D;QAC9E,WAAW,EAAE,6EAA6E;KAC3F;IACD,+BAA+B,EAAE;QAC/B,EAAE,EAAE,kDAAkD;QACtD,cAAc,EAAE,oCAAoC;QACpD,WAAW,EAAE,8EAA8E;KAC5F;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,+BAA+B;QACnC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,kEAAkE;KAChF;IACD,YAAY,EAAE;QACZ,EAAE,EAAE,+BAA+B;QACnC,cAAc,EAAE,oBAAoB;QACpC,WAAW,EAAE,mGAAmG;KACjH;IACD,KAAK,EAAE;QACL,EAAE,EAAE,wBAAwB;QAC5B,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,wFAAwF;KACtG;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,2BAA2B;QAC/B,cAAc,EAAE,UAAU;QAC1B,WAAW,EAAE,2FAA2F;KACzG;IACD,OAAO,EAAE;QACP,EAAE,EAAE,0BAA0B;QAC9B,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,2CAA2C;KACzD;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,4CAA4C;QAChD,cAAc,EAAE,sDAAsD;QACtE,WAAW,EAAE,6CAA6C;KAC3D;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,4CAA4C;QAChD,cAAc,EAAE,uDAAuD;QACvE,WAAW,EAAE,2CAA2C;KACzD;IACD,uBAAuB,EAAE;QACvB,EAAE,EAAE,0CAA0C;QAC9C,cAAc,EAAE,8DAA8D;QAC9E,WAAW,EAAE,yCAAyC;KACvD;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,sCAAsC;QAC1C,cAAc,EAAE,gDAAgD;QAChE,WAAW,EAAE,iDAAiD;KAC/D;IACD,sBAAsB,EAAE;QACtB,EAAE,EAAE,yCAAyC;QAC7C,cAAc,EAAE,cAAc;QAC9B,WAAW,EAAE,uDAAuD;KACrE;IACD,oBAAoB,EAAE;QACpB,EAAE,EAAE,uCAAuC;QAC3C,cAAc,EAAE,2EAA2E;QAC3F,WAAW,EAAE,wCAAwC;KACtD;IACD,oBAAoB,EAAE;QACpB,EAAE,EAAE,uCAAuC;QAC3C,cAAc,EAAE,qJAAqJ;QACrK,WAAW,EAAE,sCAAsC;KACpD;IACD,wBAAwB,EAAE;QACxB,EAAE,EAAE,2CAA2C;QAC/C,cAAc,EAAE,oJAAoJ;QACpK,WAAW,EAAE,0CAA0C;KACxD;IACD,oBAAoB,EAAE;QACpB,EAAE,EAAE,uCAAuC;QAC3C,cAAc,EAAE,qDAAqD;QACrE,WAAW,EAAE,sCAAsC;KACpD;IACD,eAAe,EAAE;QACf,EAAE,EAAE,kCAAkC;QACtC,cAAc,EAAE,iDAAiD;QACjE,WAAW,EAAE,oDAAoD;KAClE;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n pageTitle: {\n id: 'instruct.grading.pageTitle',\n defaultMessage: 'Grading Tools',\n description: 'Title for the grading page'\n },\n configurationAlt: {\n id: 'instruct.grading.configurationAlt',\n defaultMessage: 'Grading Configuration and Settings',\n description: 'Alt text for the configuration icon button'\n },\n viewGradebook: {\n id: 'instruct.grading.viewGradebook',\n defaultMessage: 'View Gradebook',\n description: 'Text for the button to view the gradebook'\n },\n singleLearner: {\n id: 'instruct.grading.singleLearner',\n defaultMessage: 'Single Learner',\n description: 'Single Learner button label to display corresponding grading tools'\n },\n allLearners: {\n id: 'instruct.grading.allLearners',\n defaultMessage: 'All Learners',\n description: 'All learners button label to display corresponding grading tools'\n },\n descriptionSingleLearner: {\n id: 'instruct.grading.descriptionSingleLearner',\n defaultMessage: 'These grading tools allow for grade review and adjustment for a specific learner on a specific problem.',\n description: 'Description for single learner grading tools'\n },\n descriptionAllLearners: {\n id: 'instruct.grading.descriptionAllLearners',\n defaultMessage: 'These grading tools allow for grade review and adjustment all enrolled learners on a specific problem.',\n description: 'Description for all learners grading tools'\n },\n gradingConfiguration: {\n id: 'instruct.grading.gradingConfiguration',\n defaultMessage: 'Grading Configuration',\n description: 'Title for the grading configuration modal'\n },\n close: {\n id: 'instruct.grading.modals.close',\n defaultMessage: 'Close',\n description: 'Text for the close button in the grading configuration modal'\n },\n viewGradingConfiguration: {\n id: 'instruct.grading.viewGradingConfiguration',\n defaultMessage: 'View Grading Configuration',\n description: 'View grading configuration menu item label'\n },\n viewCourseGradingSettings: {\n id: 'instruct.grading.viewCourseGradingSettings',\n defaultMessage: 'View Course Grading Settings',\n description: 'View course grading settings menu item label'\n },\n noGradingConfiguration: {\n id: 'instruct.grading.noGradingConfiguration',\n defaultMessage: 'No grading configuration found for this course.',\n description: 'Message to display when there is no grading configuration for the course'\n },\n resetAttempts: {\n id: 'instruct.grading.resetAttempts',\n defaultMessage: 'Reset Attempts',\n description: 'Title for the reset attempts action card'\n },\n resetAttemptsDescription: {\n id: 'instruct.grading.resetAttemptsDescription',\n defaultMessage: 'Allow a learner who has used up all attempts to work on the problem again.',\n description: 'Description for the reset attempts action card'\n },\n resetAttemptsButtonLabel: {\n id: 'instruct.grading.resetAttemptsButtonLabel',\n defaultMessage: 'Reset Attempts to Zero',\n description: 'Button label for the reset attempts action card'\n },\n rescoreSubmission: {\n id: 'instruct.grading.rescoreSubmission',\n defaultMessage: 'Rescore Submission',\n description: 'Title for the rescore submission action card'\n },\n rescoreSubmissionDescription: {\n id: 'instruct.grading.rescoreSubmissionDescription',\n defaultMessage: 'For the specified problem, two tools exist for rescoring learner responses.',\n description: 'Description for the rescore submission action card'\n },\n rescoreSubmissionButtonLabel: {\n id: 'instruct.grading.rescoreSubmissionButtonLabel',\n defaultMessage: 'Rescore Learner\\'s Submission',\n description: 'Button label for the rescore submission action card'\n },\n rescoreIfImprovesScoreButtonLabel: {\n id: 'instruct.grading.rescoreIfImprovesScoreButtonLabel',\n defaultMessage: 'Rescore Only if Score Improves',\n description: 'Button label for the rescore if improves score action in the rescore submission'\n },\n overrideScore: {\n id: 'instruct.grading.overrideScore',\n defaultMessage: 'Override Score',\n description: 'Title for the override score action card'\n },\n overrideScoreDescription: {\n id: 'instruct.grading.overrideScoreDescription',\n defaultMessage: 'For the specified problem, override the learner\\'s score. Input the new score, out of the total points available for this problem.',\n description: 'Description for the override score action card'\n },\n overrideScoreButtonLabel: {\n id: 'instruct.grading.overrideScoreButtonLabel',\n defaultMessage: 'Override Learner\\'s Score',\n description: 'Button label for the override score action card'\n },\n deleteHistory: {\n id: 'instruct.grading.deleteHistory',\n defaultMessage: 'Delete History',\n description: 'Title for the delete history action card'\n },\n deleteHistoryDescription: {\n id: 'instruct.grading.deleteHistoryDescription',\n defaultMessage: 'For the specified problem, permanently and completely delete the learner\\'s answers and scores from the database.',\n description: 'Description for the delete history action card'\n },\n deleteHistoryButtonLabel: {\n id: 'instruct.grading.deleteHistoryButtonLabel',\n defaultMessage: 'Delete Learner\\'s State',\n description: 'Button label for the delete history action card'\n },\n taskStatus: {\n id: 'instruct.grading.taskStatus',\n defaultMessage: 'Task Status',\n description: 'Title for the task status action card'\n },\n taskStatusDescription: {\n id: 'instruct.grading.taskStatusDescription',\n defaultMessage: 'Show the status for the tasks that you submitted for this problem.',\n description: 'Description for the task status action card'\n },\n taskStatusButtonLabel: {\n id: 'instruct.grading.taskStatusButtonLabel',\n defaultMessage: 'Show Task Status',\n description: 'Button label for the task status action card'\n },\n specifyProblem: {\n id: 'instruct.grading.specifyProblem',\n defaultMessage: 'Specify Problem:',\n description: 'Label for the specify problem input field'\n },\n select: {\n id: 'instruct.grading.select',\n defaultMessage: 'Select',\n description: 'Label for the select button in the specify problem field'\n },\n overrideScorePlaceholder: {\n id: 'instruct.grading.overrideScorePlaceholder',\n defaultMessage: 'Score',\n description: 'Placeholder text for the override score input field'\n },\n resetAllLearnersAttemptsDescription: {\n id: 'instruct.grading.resetAllLearnersAttemptsDescription',\n defaultMessage: 'Allows all learners to work on the problem again.',\n description: 'Description for the reset attempts action card in the all learners view'\n },\n rescoreSubmissionAllLearnersDescription: {\n id: 'instruct.grading.rescoreSubmissionAllLearnersDescription',\n defaultMessage: 'For the specified problem, rescore all learners\\' responses.',\n description: 'Description for the rescore submission action card in the all learners view'\n },\n rescoreAllSubmissionButtonLabel: {\n id: 'instruct.grading.rescoreAllSubmissionButtonLabel',\n defaultMessage: 'Rescore All Learners\\' Submissions',\n description: 'Button label for the rescore submission action card in the all learners view'\n },\n currentScore: {\n id: 'instruct.grading.currentScore',\n defaultMessage: 'Current Score',\n description: 'Label for the current score displayed in the single learner view'\n },\n viewProgress: {\n id: 'instruct.grading.viewProgress',\n defaultMessage: 'View Progress Page',\n description: 'Label for the view progress button displayed next to the current score in the single learner view'\n },\n score: {\n id: 'instruct.grading.score',\n defaultMessage: 'Score',\n description: 'Label for the score displayed in the current status section of the single learner view'\n },\n attempts: {\n id: 'instruct.grading.attempts',\n defaultMessage: 'Attempts',\n description: 'Label for the attempts displayed in the current status section of the single learner view'\n },\n rescore: {\n id: 'instruct.grading.rescore',\n defaultMessage: 'Rescore',\n description: 'Label for the rescore confirmation action'\n },\n resetAttemptsConfirmation: {\n id: 'instruct.grading.resetAttemptsConfirmation',\n defaultMessage: 'Reset attempts for {student} on problem \"{blockId}\"?',\n description: 'Confirmation message for resetting attempts'\n },\n overrideScoreConfirmation: {\n id: 'instruct.grading.overrideScoreConfirmation',\n defaultMessage: 'Override score for {student} for problem \"{blockId}\"?',\n description: 'Confirmation message for overriding score'\n },\n deleteStateConfirmation: {\n id: 'instruct.grading.deleteStateConfirmation',\n defaultMessage: 'Delete state for student \"{student}\" on problem \"{blockId}\"?',\n description: 'Confirmation message for deleting state'\n },\n rescoreConfirmation: {\n id: 'instruct.grading.rescoreConfirmation',\n defaultMessage: 'Rescore problem for {student} for \"{blockId}\"?',\n description: 'Confirmation message for rescoring a submission'\n },\n deleteStateButtonLabel: {\n id: 'instruct.grading.deleteStateButtonLabel',\n defaultMessage: 'Delete State',\n description: 'Button label for the delete state confirmation action'\n },\n resetAttemptsSuccess: {\n id: 'instruct.grading.resetAttemptsSuccess',\n defaultMessage: 'Successfully reset problem attempts for {student} on problem \"{blockId}\".',\n description: 'Success message for resetting attempts'\n },\n overrideScoreSuccess: {\n id: 'instruct.grading.overrideScoreSuccess',\n defaultMessage: 'Started task to override the score for {student} on problem \"{blockId}\". \\n \\n Click the \\'Show Task Status\\' button to see the status of the task.',\n description: 'Success message for overriding score'\n },\n rescoreSubmissionSuccess: {\n id: 'instruct.grading.rescoreSubmissionSuccess',\n defaultMessage: 'Successfully started task to rescore problem \"{blockId}\" for {student}. \\n \\n Click the \\'Show Task Status\\' button to see the status of the task.',\n description: 'Success message for rescoring submission'\n },\n deleteHistorySuccess: {\n id: 'instruct.grading.deleteHistorySuccess',\n defaultMessage: 'State for student \"{student}\" successfully deleted.',\n description: 'Success message for deleting history'\n },\n unexpectedError: {\n id: 'instruct.grading.unexpectedError',\n defaultMessage: 'An unexpected error occurred. Please try again.',\n description: 'Message to display when an unexpected error occurs'\n }\n});\n\nexport default messages;\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type GradingToolsType = 'single' | 'all';
|
|
2
|
+
export interface GradingParams {
|
|
3
|
+
learner?: string;
|
|
4
|
+
problem: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RescoreParams extends GradingParams {
|
|
7
|
+
onlyIfHigher: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ScoreParams extends GradingParams {
|
|
10
|
+
newScore: number;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/grading/types.ts"],"names":[],"mappings":"","sourcesContent":["export type GradingToolsType = 'single' | 'all';\n\nexport interface GradingParams {\n learner?: string,\n problem: string,\n}\n\nexport interface RescoreParams extends GradingParams {\n onlyIfHigher: boolean,\n}\n\nexport interface ScoreParams extends GradingParams {\n newScore: number,\n}\n"]}
|
|
@@ -19,9 +19,14 @@ export const useDebouncedFilter = ({ filterValue, setFilter, delay = 600 }) => {
|
|
|
19
19
|
setInputValue(value);
|
|
20
20
|
debouncedSetFilter(value);
|
|
21
21
|
};
|
|
22
|
+
const resetFilter = () => {
|
|
23
|
+
setInputValue('');
|
|
24
|
+
setFilter('');
|
|
25
|
+
};
|
|
22
26
|
return {
|
|
23
27
|
inputValue,
|
|
24
28
|
handleChange,
|
|
29
|
+
resetFilter,
|
|
25
30
|
};
|
|
26
31
|
};
|
|
27
32
|
//# sourceMappingURL=useDebouncedFilter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDebouncedFilter.js","sourceRoot":"","sources":["../../src/hooks/useDebouncedFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAQlC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,WAAW,EACX,SAAS,EACT,KAAK,GAAG,GAAG,EACa,EAAE,EAAE;IAC5B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAEhE,0CAA0C;IAC1C,6GAA6G;IAC7G,uDAAuD;IACvD,MAAM,kBAAkB,GAAG,WAAW,CACpC,QAAQ,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EACpD,CAAC,SAAS,EAAE,KAAK,CAAC,CACnB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO;QACL,UAAU;QACV,YAAY;
|
|
1
|
+
{"version":3,"file":"useDebouncedFilter.js","sourceRoot":"","sources":["../../src/hooks/useDebouncedFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAQlC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,WAAW,EACX,SAAS,EACT,KAAK,GAAG,GAAG,EACa,EAAE,EAAE;IAC5B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAEhE,0CAA0C;IAC1C,6GAA6G;IAC7G,uDAAuD;IACvD,MAAM,kBAAkB,GAAG,WAAW,CACpC,QAAQ,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EACpD,CAAC,SAAS,EAAE,KAAK,CAAC,CACnB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,aAAa,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,UAAU;QACV,YAAY;QACZ,WAAW;KACZ,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { debounce } from 'lodash';\n\ninterface UseDebouncedFilterProps {\n filterValue: string,\n setFilter: (value: string) => void,\n delay?: number,\n}\n\n/**\n * Hook for handling debounced filter input with automatic synchronization\n * @param filterValue - Current filter value from parent component\n * @param setFilter - Function to update the filter in parent component\n * @param delay - Debounce delay in milliseconds (default: 600ms)\n */\nexport const useDebouncedFilter = ({\n filterValue,\n setFilter,\n delay = 600\n}: UseDebouncedFilterProps) => {\n const [inputValue, setInputValue] = useState(filterValue || '');\n\n // Debounced function to update the filter\n // Added 600ms delay after testing on 3G network - good balance between responsiveness and reducing API calls\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const debouncedSetFilter = useCallback(\n debounce((value: string) => setFilter(value), delay),\n [setFilter, delay]\n );\n\n useEffect(() => {\n setInputValue(filterValue || '');\n }, [filterValue]);\n\n const handleChange = (value: string) => {\n setInputValue(value);\n debouncedSetFilter(value);\n };\n\n const resetFilter = () => {\n setInputValue('');\n setFilter('');\n };\n\n return {\n inputValue,\n handleChange,\n resetFilter,\n };\n};\n"]}
|
|
@@ -4,15 +4,22 @@ import { useParams, Link } from 'react-router-dom';
|
|
|
4
4
|
import { Nav, Navbar, Skeleton } from '@openedx/paragon';
|
|
5
5
|
import { useCourseInfo } from '../data/apiHook';
|
|
6
6
|
import { useAlert } from '../providers/AlertProvider';
|
|
7
|
+
import { useAccessError } from '../providers/AccessErrorProvider';
|
|
7
8
|
import { useWidgetProps } from '../slots/SlotUtils';
|
|
8
9
|
const InstructorNav = () => {
|
|
9
10
|
const { courseId = '', tabId = '' } = useParams();
|
|
10
11
|
const { data: courseInfo, isLoading } = useCourseInfo(courseId);
|
|
11
12
|
const widgetPropsArray = useWidgetProps('org.openedx.frontend.slot.instructorDashboard.tabs.v1');
|
|
12
13
|
const { clearAlerts } = useAlert();
|
|
14
|
+
const { clearError, errorType } = useAccessError();
|
|
15
|
+
const handleTabClick = () => {
|
|
16
|
+
clearAlerts();
|
|
17
|
+
clearError();
|
|
18
|
+
};
|
|
19
|
+
const hasError = errorType !== null;
|
|
13
20
|
const sortedTabs = useMemo(() => {
|
|
14
21
|
var _a;
|
|
15
|
-
if (isLoading)
|
|
22
|
+
if (isLoading || hasError)
|
|
16
23
|
return [];
|
|
17
24
|
const apiTabs = (_a = courseInfo === null || courseInfo === void 0 ? void 0 : courseInfo.tabs) !== null && _a !== void 0 ? _a : [];
|
|
18
25
|
const tabMap = new Map();
|
|
@@ -30,13 +37,18 @@ const InstructorNav = () => {
|
|
|
30
37
|
const allTabs = Array.from(tabMap.values());
|
|
31
38
|
// Tabs are sorted by sortOrder, with a fallback to 1000 to be placed at the end for tabs that don't have sortOrder defined (to avoid NaN issues)
|
|
32
39
|
return allTabs.sort((a, b) => { var _a, _b; return ((_a = a.sortOrder) !== null && _a !== void 0 ? _a : 1000) - ((_b = b.sortOrder) !== null && _b !== void 0 ? _b : 1000); });
|
|
33
|
-
}, [courseInfo === null || courseInfo === void 0 ? void 0 : courseInfo.tabs, isLoading, widgetPropsArray]);
|
|
40
|
+
}, [courseInfo === null || courseInfo === void 0 ? void 0 : courseInfo.tabs, isLoading, widgetPropsArray, hasError]);
|
|
34
41
|
if (isLoading) {
|
|
35
42
|
return _jsx(Skeleton, { className: "lead" });
|
|
36
43
|
}
|
|
37
|
-
if (sortedTabs.length === 0)
|
|
44
|
+
if (sortedTabs.length === 0 || hasError)
|
|
38
45
|
return null;
|
|
39
|
-
return (_jsx(Navbar, { expand: "md", className: "py-0", children: _jsxs(Nav, { variant: "tabs", activeKey: tabId, children: [_jsx(Navbar.Toggle, { "aria-controls": "instructor-nav" }), _jsx(Navbar.Collapse, { id: "instructor-nav", children: sortedTabs.map((tab) =>
|
|
46
|
+
return (_jsx(Navbar, { expand: "md", className: "py-0", children: _jsxs(Nav, { variant: "tabs", activeKey: tabId, children: [_jsx(Navbar.Toggle, { "aria-controls": "instructor-nav" }), _jsx(Navbar.Collapse, { id: "instructor-nav", children: sortedTabs.map((tab) => {
|
|
47
|
+
const isInternal = tab.url.startsWith('/');
|
|
48
|
+
return (_jsx(Nav.Item, { children: _jsx(Nav.Link, Object.assign({}, (isInternal
|
|
49
|
+
? { to: tab.url, as: Link }
|
|
50
|
+
: { href: tab.url }), { active: tab.tabId === tabId, onClick: handleTabClick, children: tab.title })) }, tab.tabId));
|
|
51
|
+
}) })] }) }));
|
|
40
52
|
};
|
|
41
53
|
export default InstructorNav;
|
|
42
54
|
//# sourceMappingURL=InstructorNav.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstructorNav.js","sourceRoot":"","sources":["../../src/instructorNav/InstructorNav.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"InstructorNav.js","sourceRoot":"","sources":["../../src/instructorNav/InstructorNav.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { useParams, Link } from 'react-router-dom';\nimport { Nav, Navbar, Skeleton } from '@openedx/paragon';\nimport { useCourseInfo } from '@src/data/apiHook';\nimport { useAlert } from '@src/providers/AlertProvider';\nimport { useAccessError } from '@src/providers/AccessErrorProvider';\nimport { useWidgetProps } from '@src/slots/SlotUtils';\n\nexport interface TabProps {\n tabId: string,\n url: string,\n title: string,\n sortOrder: number,\n}\n\nconst InstructorNav = () => {\n const { courseId = '', tabId = '' } = useParams<{ courseId: string, tabId?: string }>();\n const { data: courseInfo, isLoading } = useCourseInfo(courseId);\n const widgetPropsArray = useWidgetProps('org.openedx.frontend.slot.instructorDashboard.tabs.v1') as TabProps[];\n const { clearAlerts } = useAlert();\n const { clearError, errorType } = useAccessError();\n\n const handleTabClick = () => {\n clearAlerts();\n clearError();\n };\n\n const hasError = errorType !== null;\n\n const sortedTabs = useMemo(() => {\n if (isLoading || hasError) return [];\n const apiTabs: TabProps[] = courseInfo?.tabs ?? [];\n const tabMap = new Map<string, TabProps>();\n\n // Adding tabs from API and from slot into a map to avoid duplicates\n apiTabs.forEach(tab => {\n tabMap.set(tab.tabId, tab);\n });\n\n widgetPropsArray.forEach(slotTab => {\n // If the slotTab doesn't have a tabId or title, we can't render it properly, so we skip it.\n if (!slotTab.tabId || !slotTab.title) {\n return;\n }\n\n tabMap.set(slotTab.tabId, slotTab);\n });\n\n const allTabs = Array.from(tabMap.values());\n\n // Tabs are sorted by sortOrder, with a fallback to 1000 to be placed at the end for tabs that don't have sortOrder defined (to avoid NaN issues)\n return allTabs.sort((a, b) => (a.sortOrder ?? 1000) - (b.sortOrder ?? 1000));\n }, [courseInfo?.tabs, isLoading, widgetPropsArray, hasError]);\n\n if (isLoading) {\n return <Skeleton className=\"lead\" />;\n }\n\n if (sortedTabs.length === 0 || hasError) return null;\n\n return (\n <Navbar expand=\"md\" className=\"py-0\">\n <Nav\n variant=\"tabs\"\n activeKey={tabId}\n >\n <Navbar.Toggle aria-controls=\"instructor-nav\" />\n <Navbar.Collapse id=\"instructor-nav\">\n {\n sortedTabs.map((tab) => {\n const isInternal = tab.url.startsWith('/');\n return (\n <Nav.Item key={tab.tabId}>\n <Nav.Link\n {...(isInternal\n ? { to: tab.url, as: Link }\n : { href: tab.url }\n )}\n active={tab.tabId === tabId}\n onClick={handleTabClick}\n >\n {tab.title}\n </Nav.Link>\n </Nav.Item>\n );\n })\n }\n </Navbar.Collapse>\n </Nav>\n </Navbar>\n );\n};\n\nexport default InstructorNav;\n"]}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineMessages } from '@openedx/frontend-base';
|
|
2
|
+
const messages = defineMessages({
|
|
3
|
+
'instructor-dashboard.page.title': {
|
|
4
|
+
id: 'instructor-dashboard.page.title',
|
|
5
|
+
defaultMessage: 'Instructor Dashboard | {siteName}',
|
|
6
|
+
description: 'Document title for the instructor dashboard page',
|
|
7
|
+
},
|
|
8
|
+
});
|
|
9
|
+
export default messages;
|
|
10
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAAC;IAC9B,iCAAiC,EAAE;QACjC,EAAE,EAAE,iCAAiC;QACrC,cAAc,EAAE,mCAAmC;QACnD,WAAW,EAAE,kDAAkD;KAChE;CACF,CAAC,CAAC;AAEH,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages({\n 'instructor-dashboard.page.title': {\n id: 'instructor-dashboard.page.title',\n defaultMessage: 'Instructor Dashboard | {siteName}',\n description: 'Document title for the instructor dashboard page',\n },\n});\n\nexport default messages;\n"]}
|
|
@@ -3,9 +3,11 @@ import { useIntl } from '@openedx/frontend-base';
|
|
|
3
3
|
import messages from './messages';
|
|
4
4
|
import { Container } from '@openedx/paragon';
|
|
5
5
|
import InstructorNav from '../instructorNav/InstructorNav';
|
|
6
|
+
import { AccessErrorGuard } from '../providers/AccessErrorProvider';
|
|
7
|
+
import AccessErrorObserver from '../providers/AccessErrorObserver';
|
|
6
8
|
const PageWrapper = ({ children }) => {
|
|
7
9
|
const { formatMessage } = useIntl();
|
|
8
|
-
return (_jsxs(Container, { size: "xl", fluid: true, children: [_jsx("h2", { className: "text-primary-700 m-4", children: formatMessage(messages.pageTitle) }), _jsx(InstructorNav, {}), _jsx("div", { className: "m-4", children: children })] }));
|
|
10
|
+
return (_jsxs(Container, { size: "xl", fluid: true, children: [_jsx(AccessErrorObserver, {}), _jsx("h2", { className: "text-primary-700 m-4", children: formatMessage(messages.pageTitle) }), _jsx(InstructorNav, {}), _jsx(AccessErrorGuard, { children: _jsx("div", { className: "m-4", children: children }) })] }));
|
|
9
11
|
};
|
|
10
12
|
export default PageWrapper;
|
|
11
13
|
//# sourceMappingURL=PageWrapper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageWrapper.js","sourceRoot":"","sources":["../../src/pageWrapper/PageWrapper.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,aAAa,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"PageWrapper.js","sourceRoot":"","sources":["../../src/pageWrapper/PageWrapper.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,aAAa,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,mBAAmB,MAAM,oCAAoC,CAAC;AAErE,MAAM,WAAW,GAAG,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE;IAClE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,CAAC;IACpC,OAAO,CACL,MAAC,SAAS,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,mBACxB,KAAC,mBAAmB,KAAG,EACvB,aAAI,SAAS,EAAC,sBAAsB,YAAE,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAM,EAC7E,KAAC,aAAa,KAAG,EACjB,KAAC,gBAAgB,cACf,cAAK,SAAS,EAAC,KAAK,YACjB,QAAQ,GACL,GACW,IACT,CACb,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC","sourcesContent":["import { useIntl } from '@openedx/frontend-base';\nimport messages from './messages';\nimport { Container } from '@openedx/paragon';\nimport InstructorNav from '@src/instructorNav/InstructorNav';\nimport { AccessErrorGuard } from '@src/providers/AccessErrorProvider';\nimport AccessErrorObserver from '@src/providers/AccessErrorObserver';\n\nconst PageWrapper = ({ children }: { children: React.ReactNode }) => {\n const { formatMessage } = useIntl();\n return (\n <Container size=\"xl\" fluid>\n <AccessErrorObserver />\n <h2 className=\"text-primary-700 m-4\">{formatMessage(messages.pageTitle)}</h2>\n <InstructorNav />\n <AccessErrorGuard>\n <div className=\"m-4\">\n {children}\n </div>\n </AccessErrorGuard>\n </Container>\n );\n};\n\nexport default PageWrapper;\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observes the courseInfo query and syncs 401/403 errors with the AccessErrorProvider.
|
|
3
|
+
* This component must be rendered inside AccessErrorProvider.
|
|
4
|
+
* By keeping this logic here (instead of inside useCourseInfo), the hook stays
|
|
5
|
+
* decoupled from the provider and can be used in slots or other contexts
|
|
6
|
+
* that live outside the provider tree.
|
|
7
|
+
*/
|
|
8
|
+
declare const AccessErrorObserver: () => null;
|
|
9
|
+
export default AccessErrorObserver;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useParams } from 'react-router-dom';
|
|
3
|
+
import { useCourseInfo } from '../data/apiHook';
|
|
4
|
+
import { isForbiddenError, isUnauthorizedError } from '../data/utils';
|
|
5
|
+
import { useAccessError } from '../providers/AccessErrorProvider';
|
|
6
|
+
/**
|
|
7
|
+
* Observes the courseInfo query and syncs 401/403 errors with the AccessErrorProvider.
|
|
8
|
+
* This component must be rendered inside AccessErrorProvider.
|
|
9
|
+
* By keeping this logic here (instead of inside useCourseInfo), the hook stays
|
|
10
|
+
* decoupled from the provider and can be used in slots or other contexts
|
|
11
|
+
* that live outside the provider tree.
|
|
12
|
+
*/
|
|
13
|
+
const AccessErrorObserver = () => {
|
|
14
|
+
const { courseId = '' } = useParams();
|
|
15
|
+
const { isLoading, error } = useCourseInfo(courseId);
|
|
16
|
+
const { setErrorType, setLoading } = useAccessError();
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
setLoading(isLoading);
|
|
19
|
+
if (error && isForbiddenError(error)) {
|
|
20
|
+
setErrorType('forbidden');
|
|
21
|
+
}
|
|
22
|
+
else if (error && isUnauthorizedError(error)) {
|
|
23
|
+
setErrorType('unauthorized');
|
|
24
|
+
}
|
|
25
|
+
else if (error) {
|
|
26
|
+
setErrorType('generic');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
setErrorType(null);
|
|
30
|
+
}
|
|
31
|
+
}, [isLoading, error, setErrorType, setLoading]);
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
34
|
+
export default AccessErrorObserver;
|
|
35
|
+
//# sourceMappingURL=AccessErrorObserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessErrorObserver.js","sourceRoot":"","sources":["../../src/providers/AccessErrorObserver.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,GAAG,EAAE;IAC/B,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,SAAS,EAAwB,CAAC;IAC5D,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,cAAc,EAAE,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,SAAS,CAAC,CAAC;QACtB,IAAI,KAAK,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,YAAY,CAAC,cAAc,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IAEjD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC","sourcesContent":["import { useEffect } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useCourseInfo } from '@src/data/apiHook';\nimport { isForbiddenError, isUnauthorizedError } from '@src/data/utils';\nimport { useAccessError } from '@src/providers/AccessErrorProvider';\n\n/**\n * Observes the courseInfo query and syncs 401/403 errors with the AccessErrorProvider.\n * This component must be rendered inside AccessErrorProvider.\n * By keeping this logic here (instead of inside useCourseInfo), the hook stays\n * decoupled from the provider and can be used in slots or other contexts\n * that live outside the provider tree.\n */\nconst AccessErrorObserver = () => {\n const { courseId = '' } = useParams<{ courseId: string }>();\n const { isLoading, error } = useCourseInfo(courseId);\n const { setErrorType, setLoading } = useAccessError();\n\n useEffect(() => {\n setLoading(isLoading);\n if (error && isForbiddenError(error)) {\n setErrorType('forbidden');\n } else if (error && isUnauthorizedError(error)) {\n setErrorType('unauthorized');\n } else if (error) {\n setErrorType('generic');\n } else {\n setErrorType(null);\n }\n }, [isLoading, error, setErrorType, setLoading]);\n\n return null;\n};\n\nexport default AccessErrorObserver;\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactNode, FC } from 'react';
|
|
2
|
+
type ErrorType = 'forbidden' | 'unauthorized' | 'generic' | null;
|
|
3
|
+
interface AccessErrorContextType {
|
|
4
|
+
errorType: ErrorType;
|
|
5
|
+
setErrorType: (error: ErrorType) => void;
|
|
6
|
+
clearError: () => void;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
setLoading: (loading: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
interface AccessErrorProviderProps {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare const AccessErrorProvider: FC<AccessErrorProviderProps>;
|
|
14
|
+
interface AccessErrorGuardProps {
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare const AccessErrorGuard: FC<AccessErrorGuardProps>;
|
|
18
|
+
export declare const useAccessError: () => AccessErrorContextType;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useState, useCallback, useMemo } from 'react';
|
|
3
|
+
import { Alert, Skeleton } from '@openedx/paragon';
|
|
4
|
+
import { Error as ErrorIcon } from '@openedx/paragon/icons';
|
|
5
|
+
import { useIntl } from '@openedx/frontend-base';
|
|
6
|
+
import messages from '../providers/messages';
|
|
7
|
+
const AccessErrorContext = createContext(undefined);
|
|
8
|
+
export const AccessErrorProvider = ({ children }) => {
|
|
9
|
+
const [errorType, setErrorType] = useState(null);
|
|
10
|
+
const [isLoading, setLoading] = useState(false);
|
|
11
|
+
const clearError = useCallback(() => {
|
|
12
|
+
setErrorType(null);
|
|
13
|
+
}, []);
|
|
14
|
+
const value = useMemo(() => ({
|
|
15
|
+
errorType,
|
|
16
|
+
setErrorType,
|
|
17
|
+
clearError,
|
|
18
|
+
isLoading,
|
|
19
|
+
setLoading,
|
|
20
|
+
}), [errorType, clearError, isLoading]);
|
|
21
|
+
return (_jsx(AccessErrorContext.Provider, { value: value, children: children }));
|
|
22
|
+
};
|
|
23
|
+
export const AccessErrorGuard = ({ children }) => {
|
|
24
|
+
const intl = useIntl();
|
|
25
|
+
const { errorType, isLoading } = useAccessError();
|
|
26
|
+
if (isLoading) {
|
|
27
|
+
return _jsx(Skeleton, { className: "lead" });
|
|
28
|
+
}
|
|
29
|
+
if (errorType) {
|
|
30
|
+
const headingMap = {
|
|
31
|
+
unauthorized: messages.unauthorizedErrorHeading,
|
|
32
|
+
forbidden: messages.forbiddenErrorHeading,
|
|
33
|
+
generic: messages.genericErrorHeading,
|
|
34
|
+
};
|
|
35
|
+
const messageMap = {
|
|
36
|
+
unauthorized: messages.unauthorizedErrorMessage,
|
|
37
|
+
forbidden: messages.forbiddenErrorMessage,
|
|
38
|
+
generic: messages.genericErrorMessage,
|
|
39
|
+
};
|
|
40
|
+
return (_jsxs(Alert, { variant: "danger", icon: ErrorIcon, children: [_jsx(Alert.Heading, { children: intl.formatMessage(headingMap[errorType]) }), _jsx("p", { children: intl.formatMessage(messageMap[errorType]) })] }));
|
|
41
|
+
}
|
|
42
|
+
return _jsx(_Fragment, { children: children });
|
|
43
|
+
};
|
|
44
|
+
export const useAccessError = () => {
|
|
45
|
+
const context = useContext(AccessErrorContext);
|
|
46
|
+
if (context === undefined) {
|
|
47
|
+
throw new Error('useAccessError must be used within a AccessErrorProvider');
|
|
48
|
+
}
|
|
49
|
+
return context;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=AccessErrorProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessErrorProvider.js","sourceRoot":"","sources":["../../src/providers/AccessErrorProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAa,WAAW,EAAE,OAAO,EAAM,MAAM,OAAO,CAAC;AACjG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAY/C,MAAM,kBAAkB,GAAG,aAAa,CAAqC,SAAS,CAAC,CAAC;AAMxF,MAAM,CAAC,MAAM,mBAAmB,GAAiC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAChF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAY,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,YAAY,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3B,SAAS;QACT,YAAY;QACZ,UAAU;QACV,SAAS;QACT,UAAU;KACX,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;IAExC,OAAO,CACL,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACtC,QAAQ,GACmB,CAC/B,CAAC;AACJ,CAAC,CAAC;AAMF,MAAM,CAAC,MAAM,gBAAgB,GAA8B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC1E,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,CAAC;IAElD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,KAAC,QAAQ,IAAC,SAAS,EAAC,MAAM,GAAG,CAAC;IACvC,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,UAAU,GAAG;YACjB,YAAY,EAAE,QAAQ,CAAC,wBAAwB;YAC/C,SAAS,EAAE,QAAQ,CAAC,qBAAqB;YACzC,OAAO,EAAE,QAAQ,CAAC,mBAAmB;SACtC,CAAC;QACF,MAAM,UAAU,GAAG;YACjB,YAAY,EAAE,QAAQ,CAAC,wBAAwB;YAC/C,SAAS,EAAE,QAAQ,CAAC,qBAAqB;YACzC,OAAO,EAAE,QAAQ,CAAC,mBAAmB;SACtC,CAAC;QAEF,OAAO,CACL,MAAC,KAAK,IACJ,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAE,SAAS,aAEf,KAAC,KAAK,CAAC,OAAO,cAAE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,GAAiB,EAC1E,sBACG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,GACxC,IACE,CACT,CAAC;IACJ,CAAC;IAED,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAA2B,EAAE;IACzD,MAAM,OAAO,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { createContext, useContext, useState, ReactNode, useCallback, useMemo, FC } from 'react';\nimport { Alert, Skeleton } from '@openedx/paragon';\nimport { Error as ErrorIcon } from '@openedx/paragon/icons';\nimport { useIntl } from '@openedx/frontend-base';\nimport messages from '@src/providers/messages';\n\ntype ErrorType = 'forbidden' | 'unauthorized' | 'generic' | null;\n\ninterface AccessErrorContextType {\n errorType: ErrorType,\n setErrorType: (error: ErrorType) => void,\n clearError: () => void,\n isLoading: boolean,\n setLoading: (loading: boolean) => void,\n}\n\nconst AccessErrorContext = createContext<AccessErrorContextType | undefined>(undefined);\n\ninterface AccessErrorProviderProps {\n children: ReactNode,\n}\n\nexport const AccessErrorProvider: FC<AccessErrorProviderProps> = ({ children }) => {\n const [errorType, setErrorType] = useState<ErrorType>(null);\n const [isLoading, setLoading] = useState(false);\n\n const clearError = useCallback(() => {\n setErrorType(null);\n }, []);\n\n const value = useMemo(() => ({\n errorType,\n setErrorType,\n clearError,\n isLoading,\n setLoading,\n }), [errorType, clearError, isLoading]);\n\n return (\n <AccessErrorContext.Provider value={value}>\n {children}\n </AccessErrorContext.Provider>\n );\n};\n\ninterface AccessErrorGuardProps {\n children: ReactNode,\n}\n\nexport const AccessErrorGuard: FC<AccessErrorGuardProps> = ({ children }) => {\n const intl = useIntl();\n const { errorType, isLoading } = useAccessError();\n\n if (isLoading) {\n return <Skeleton className=\"lead\" />;\n }\n\n if (errorType) {\n const headingMap = {\n unauthorized: messages.unauthorizedErrorHeading,\n forbidden: messages.forbiddenErrorHeading,\n generic: messages.genericErrorHeading,\n };\n const messageMap = {\n unauthorized: messages.unauthorizedErrorMessage,\n forbidden: messages.forbiddenErrorMessage,\n generic: messages.genericErrorMessage,\n };\n\n return (\n <Alert\n variant=\"danger\"\n icon={ErrorIcon}\n >\n <Alert.Heading>{intl.formatMessage(headingMap[errorType])}</Alert.Heading>\n <p>\n {intl.formatMessage(messageMap[errorType])}\n </p>\n </Alert>\n );\n }\n\n return <>{children}</>;\n};\n\nexport const useAccessError = (): AccessErrorContextType => {\n const context = useContext(AccessErrorContext);\n if (context === undefined) {\n throw new Error('useAccessError must be used within a AccessErrorProvider');\n }\n return context;\n};\n"]}
|
|
@@ -100,7 +100,7 @@ export const AlertProvider = ({ children }) => {
|
|
|
100
100
|
return (_jsxs(AlertContext.Provider, { value: value, children: [children, _jsx("div", { className: "toast-container", children: toasts.map(toast => (_jsx(Toast, { show: toast.visible, onClose: () => discardToast(toast.id), delay: toast.delay, className: "text-break", children: toast.message }, toast.id))) }), modals.length > 0 && (() => {
|
|
101
101
|
const modal = modals[0];
|
|
102
102
|
const icon = variantIcons[modal.variant];
|
|
103
|
-
return (_jsx(AlertModal, Object.assign({ title: modal.title, isOpen: modal.isOpen, onClose: () => closeModal(modal.id, true), variant: modal.variant }, (icon && { icon }), { hasHeader: !!modal.title, footerNode: (_jsxs(ActionRow, { children: [modal.cancelText && (_jsx(Button, { variant: "tertiary", onClick: () => closeModal(modal.id, true), children: modal.cancelText })), modal.confirmText && (_jsx(Button, { variant: modal.variant === 'danger' ? 'danger' : 'primary', onClick: () => confirmModal(modal.id), children: modal.confirmText }))] })), children: _jsx("p", { children: modal.message }) }), modal.id));
|
|
103
|
+
return (_jsx(AlertModal, Object.assign({ title: modal.title, isOpen: modal.isOpen, onClose: () => closeModal(modal.id, true), variant: modal.variant }, (icon && { icon }), { hasHeader: !!modal.title, footerNode: (_jsxs(ActionRow, { children: [modal.cancelText && (_jsx(Button, { variant: "tertiary", onClick: () => closeModal(modal.id, true), children: modal.cancelText })), modal.confirmText && (_jsx(Button, { variant: modal.variant === 'danger' ? 'danger' : 'primary', onClick: () => modal.onConfirm ? confirmModal(modal.id) : closeModal(modal.id, false), children: modal.confirmText }))] })), children: _jsx("p", { children: modal.message }) }), modal.id));
|
|
104
104
|
})()] }));
|
|
105
105
|
};
|
|
106
106
|
export const AlertOutlet = () => {
|