@openedx/frontend-app-gradebook 2.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.
- package/LICENSE +661 -0
- package/README.rst +279 -0
- package/dist/Main.d.ts +3 -0
- package/dist/Main.js +17 -0
- package/dist/Main.js.map +1 -0
- package/dist/app.d.ts +3 -0
- package/dist/app.js +10 -0
- package/dist/app.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/BulkManagementAlerts.d.ts +5 -0
- package/dist/components/BulkManagementHistoryView/BulkManagementAlerts.js +20 -0
- package/dist/components/BulkManagementHistoryView/BulkManagementAlerts.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/BulkManagementHistoryView.scss +6 -0
- package/dist/components/BulkManagementHistoryView/HistoryTable.d.ts +33 -0
- package/dist/components/BulkManagementHistoryView/HistoryTable.js +53 -0
- package/dist/components/BulkManagementHistoryView/HistoryTable.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/ResultsSummary.d.ts +16 -0
- package/dist/components/BulkManagementHistoryView/ResultsSummary.js +19 -0
- package/dist/components/BulkManagementHistoryView/ResultsSummary.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/data/api.d.ts +5 -0
- package/dist/components/BulkManagementHistoryView/data/api.js +16 -0
- package/dist/components/BulkManagementHistoryView/data/api.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/data/apiHook.d.ts +16 -0
- package/dist/components/BulkManagementHistoryView/data/apiHook.js +34 -0
- package/dist/components/BulkManagementHistoryView/data/apiHook.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/data/queryKeys.d.ts +5 -0
- package/dist/components/BulkManagementHistoryView/data/queryKeys.js +7 -0
- package/dist/components/BulkManagementHistoryView/data/queryKeys.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/data/utils.d.ts +34 -0
- package/dist/components/BulkManagementHistoryView/data/utils.js +45 -0
- package/dist/components/BulkManagementHistoryView/data/utils.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/index.d.ts +2 -0
- package/dist/components/BulkManagementHistoryView/index.js +12 -0
- package/dist/components/BulkManagementHistoryView/index.js.map +1 -0
- package/dist/components/BulkManagementHistoryView/messages.d.ts +24 -0
- package/dist/components/BulkManagementHistoryView/messages.js +20 -0
- package/dist/components/BulkManagementHistoryView/messages.js.map +1 -0
- package/dist/components/GradebookFilters/AssignmentFilter/index.d.ts +10 -0
- package/dist/components/GradebookFilters/AssignmentFilter/index.js +31 -0
- package/dist/components/GradebookFilters/AssignmentFilter/index.js.map +1 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/hooks.d.ts +19 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/hooks.js +31 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/hooks.js.map +1 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/index.d.ts +10 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/index.js +17 -0
- package/dist/components/GradebookFilters/AssignmentGradeFilter/index.js.map +1 -0
- package/dist/components/GradebookFilters/AssignmentTypeFilter/index.d.ts +10 -0
- package/dist/components/GradebookFilters/AssignmentTypeFilter/index.js +38 -0
- package/dist/components/GradebookFilters/AssignmentTypeFilter/index.js.map +1 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/hooks.d.ts +15 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/hooks.js +34 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/hooks.js.map +1 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/index.d.ts +10 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/index.js +17 -0
- package/dist/components/GradebookFilters/CourseGradeFilter/index.js.map +1 -0
- package/dist/components/GradebookFilters/GradebookFilters.scss +6 -0
- package/dist/components/GradebookFilters/PercentGroup.d.ts +22 -0
- package/dist/components/GradebookFilters/PercentGroup.js +16 -0
- package/dist/components/GradebookFilters/PercentGroup.js.map +1 -0
- package/dist/components/GradebookFilters/SelectGroup.d.ts +24 -0
- package/dist/components/GradebookFilters/SelectGroup.js +17 -0
- package/dist/components/GradebookFilters/SelectGroup.js.map +1 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/hooks.d.ts +16 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/hooks.js +46 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/hooks.js.map +1 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/index.d.ts +10 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/index.js +23 -0
- package/dist/components/GradebookFilters/StudentGroupsFilter/index.js.map +1 -0
- package/dist/components/GradebookFilters/data/api.d.ts +10 -0
- package/dist/components/GradebookFilters/data/api.js +27 -0
- package/dist/components/GradebookFilters/data/api.js.map +1 -0
- package/dist/components/GradebookFilters/data/apiHook.d.ts +16 -0
- package/dist/components/GradebookFilters/data/apiHook.js +24 -0
- package/dist/components/GradebookFilters/data/apiHook.js.map +1 -0
- package/dist/components/GradebookFilters/data/hooks.d.ts +7 -0
- package/dist/components/GradebookFilters/data/hooks.js +53 -0
- package/dist/components/GradebookFilters/data/hooks.js.map +1 -0
- package/dist/components/GradebookFilters/data/queryKeys.d.ts +10 -0
- package/dist/components/GradebookFilters/data/queryKeys.js +12 -0
- package/dist/components/GradebookFilters/data/queryKeys.js.map +1 -0
- package/dist/components/GradebookFilters/index.d.ts +10 -0
- package/dist/components/GradebookFilters/index.js +32 -0
- package/dist/components/GradebookFilters/index.js.map +1 -0
- package/dist/components/GradebookFilters/messages.d.ts +112 -0
- package/dist/components/GradebookFilters/messages.js +75 -0
- package/dist/components/GradebookFilters/messages.js.map +1 -0
- package/dist/components/GradebookHeader/hooks.d.ts +13 -0
- package/dist/components/GradebookHeader/hooks.js +28 -0
- package/dist/components/GradebookHeader/hooks.js.map +1 -0
- package/dist/components/GradebookHeader/index.d.ts +2 -0
- package/dist/components/GradebookHeader/index.js +14 -0
- package/dist/components/GradebookHeader/index.js.map +1 -0
- package/dist/components/GradebookHeader/messages.d.ts +48 -0
- package/dist/components/GradebookHeader/messages.js +35 -0
- package/dist/components/GradebookHeader/messages.js.map +1 -0
- package/dist/components/GradesView/BulkManagementControls/index.d.ts +2 -0
- package/dist/components/GradesView/BulkManagementControls/index.js +26 -0
- package/dist/components/GradesView/BulkManagementControls/index.js.map +1 -0
- package/dist/components/GradesView/BulkManagementControls/messages.d.ts +8 -0
- package/dist/components/GradesView/BulkManagementControls/messages.js +10 -0
- package/dist/components/GradesView/BulkManagementControls/messages.js.map +1 -0
- package/dist/components/GradesView/EditModal/HistoryHeader.d.ts +21 -0
- package/dist/components/GradesView/EditModal/HistoryHeader.js +20 -0
- package/dist/components/GradesView/EditModal/HistoryHeader.js.map +1 -0
- package/dist/components/GradesView/EditModal/ModalHeaders.d.ts +3 -0
- package/dist/components/GradesView/EditModal/ModalHeaders.js +26 -0
- package/dist/components/GradesView/EditModal/ModalHeaders.js.map +1 -0
- package/dist/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.d.ts +5 -0
- package/dist/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.js +23 -0
- package/dist/components/GradesView/EditModal/OverrideTable/AdjustedGradeInput/index.js.map +1 -0
- package/dist/components/GradesView/EditModal/OverrideTable/ReasonInput/index.d.ts +6 -0
- package/dist/components/GradesView/EditModal/OverrideTable/ReasonInput/index.js +25 -0
- package/dist/components/GradesView/EditModal/OverrideTable/ReasonInput/index.js.map +1 -0
- package/dist/components/GradesView/EditModal/OverrideTable/index.d.ts +5 -0
- package/dist/components/GradesView/EditModal/OverrideTable/index.js +39 -0
- package/dist/components/GradesView/EditModal/OverrideTable/index.js.map +1 -0
- package/dist/components/GradesView/EditModal/OverrideTable/messages.d.ts +32 -0
- package/dist/components/GradesView/EditModal/OverrideTable/messages.js +25 -0
- package/dist/components/GradesView/EditModal/OverrideTable/messages.js.map +1 -0
- package/dist/components/GradesView/EditModal/index.d.ts +2 -0
- package/dist/components/GradesView/EditModal/index.js +35 -0
- package/dist/components/GradesView/EditModal/index.js.map +1 -0
- package/dist/components/GradesView/EditModal/messages.d.ts +72 -0
- package/dist/components/GradesView/EditModal/messages.js +50 -0
- package/dist/components/GradesView/EditModal/messages.js.map +1 -0
- package/dist/components/GradesView/FilterBadges/FilterBadge.d.ts +9 -0
- package/dist/components/GradesView/FilterBadges/FilterBadge.js +27 -0
- package/dist/components/GradesView/FilterBadges/FilterBadge.js.map +1 -0
- package/dist/components/GradesView/FilterBadges/index.d.ts +8 -0
- package/dist/components/GradesView/FilterBadges/index.js +15 -0
- package/dist/components/GradesView/FilterBadges/index.js.map +1 -0
- package/dist/components/GradesView/FilterMenuToggle/index.d.ts +5 -0
- package/dist/components/GradesView/FilterMenuToggle/index.js +18 -0
- package/dist/components/GradesView/FilterMenuToggle/index.js.map +1 -0
- package/dist/components/GradesView/FilterMenuToggle/messages.d.ts +8 -0
- package/dist/components/GradesView/FilterMenuToggle/messages.js +10 -0
- package/dist/components/GradesView/FilterMenuToggle/messages.js.map +1 -0
- package/dist/components/GradesView/FilteredUsersLabel/index.d.ts +15 -0
- package/dist/components/GradesView/FilteredUsersLabel/index.js +27 -0
- package/dist/components/GradesView/FilteredUsersLabel/index.js.map +1 -0
- package/dist/components/GradesView/FilteredUsersLabel/messages.d.ts +8 -0
- package/dist/components/GradesView/FilteredUsersLabel/messages.js +10 -0
- package/dist/components/GradesView/FilteredUsersLabel/messages.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/Fields.d.ts +2 -0
- package/dist/components/GradesView/GradebookTable/Fields.js +32 -0
- package/dist/components/GradesView/GradebookTable/Fields.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/GradeButton.d.ts +26 -0
- package/dist/components/GradesView/GradebookTable/GradeButton.js +56 -0
- package/dist/components/GradesView/GradebookTable/GradeButton.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/LabelReplacements.d.ts +3 -0
- package/dist/components/GradesView/GradebookTable/LabelReplacements.js +42 -0
- package/dist/components/GradesView/GradebookTable/LabelReplacements.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/hooks.d.ts +11 -0
- package/dist/components/GradesView/GradebookTable/hooks.js +45 -0
- package/dist/components/GradesView/GradebookTable/hooks.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/index.d.ts +5 -0
- package/dist/components/GradesView/GradebookTable/index.js +16 -0
- package/dist/components/GradesView/GradebookTable/index.js.map +1 -0
- package/dist/components/GradesView/GradebookTable/messages.d.ts +64 -0
- package/dist/components/GradesView/GradebookTable/messages.js +45 -0
- package/dist/components/GradesView/GradebookTable/messages.js.map +1 -0
- package/dist/components/GradesView/GradesView.scss +156 -0
- package/dist/components/GradesView/ImportGradesButton/index.d.ts +5 -0
- package/dist/components/GradesView/ImportGradesButton/index.js +38 -0
- package/dist/components/GradesView/ImportGradesButton/index.js.map +1 -0
- package/dist/components/GradesView/ImportGradesButton/messages.d.ts +16 -0
- package/dist/components/GradesView/ImportGradesButton/messages.js +15 -0
- package/dist/components/GradesView/ImportGradesButton/messages.js.map +1 -0
- package/dist/components/GradesView/ImportSuccessToast/hooks.d.ts +10 -0
- package/dist/components/GradesView/ImportSuccessToast/hooks.js +31 -0
- package/dist/components/GradesView/ImportSuccessToast/hooks.js.map +1 -0
- package/dist/components/GradesView/ImportSuccessToast/index.d.ts +5 -0
- package/dist/components/GradesView/ImportSuccessToast/index.js +15 -0
- package/dist/components/GradesView/ImportSuccessToast/index.js.map +1 -0
- package/dist/components/GradesView/ImportSuccessToast/messages.d.ts +17 -0
- package/dist/components/GradesView/ImportSuccessToast/messages.js +15 -0
- package/dist/components/GradesView/ImportSuccessToast/messages.js.map +1 -0
- package/dist/components/GradesView/InterventionsReport/index.d.ts +2 -0
- package/dist/components/GradesView/InterventionsReport/index.js +27 -0
- package/dist/components/GradesView/InterventionsReport/index.js.map +1 -0
- package/dist/components/GradesView/InterventionsReport/messages.d.ts +25 -0
- package/dist/components/GradesView/InterventionsReport/messages.js +20 -0
- package/dist/components/GradesView/InterventionsReport/messages.js.map +1 -0
- package/dist/components/GradesView/PageButtons/index.d.ts +5 -0
- package/dist/components/GradesView/PageButtons/index.js +14 -0
- package/dist/components/GradesView/PageButtons/index.js.map +1 -0
- package/dist/components/GradesView/PageButtons/messages.d.ts +16 -0
- package/dist/components/GradesView/PageButtons/messages.js +15 -0
- package/dist/components/GradesView/PageButtons/messages.js.map +1 -0
- package/dist/components/GradesView/ScoreViewInput/index.d.ts +5 -0
- package/dist/components/GradesView/ScoreViewInput/index.js +20 -0
- package/dist/components/GradesView/ScoreViewInput/index.js.map +1 -0
- package/dist/components/GradesView/ScoreViewInput/messages.d.ts +24 -0
- package/dist/components/GradesView/ScoreViewInput/messages.js +20 -0
- package/dist/components/GradesView/ScoreViewInput/messages.js.map +1 -0
- package/dist/components/GradesView/SearchControls/hooks.d.ts +9 -0
- package/dist/components/GradesView/SearchControls/hooks.js +34 -0
- package/dist/components/GradesView/SearchControls/hooks.js.map +1 -0
- package/dist/components/GradesView/SearchControls/index.d.ts +5 -0
- package/dist/components/GradesView/SearchControls/index.js +14 -0
- package/dist/components/GradesView/SearchControls/index.js.map +1 -0
- package/dist/components/GradesView/SearchControls/messages.d.ts +16 -0
- package/dist/components/GradesView/SearchControls/messages.js +15 -0
- package/dist/components/GradesView/SearchControls/messages.js.map +1 -0
- package/dist/components/GradesView/SpinnerIcon.d.ts +5 -0
- package/dist/components/GradesView/SpinnerIcon.js +15 -0
- package/dist/components/GradesView/SpinnerIcon.js.map +1 -0
- package/dist/components/GradesView/StatusAlerts/index.d.ts +5 -0
- package/dist/components/GradesView/StatusAlerts/index.js +16 -0
- package/dist/components/GradesView/StatusAlerts/index.js.map +1 -0
- package/dist/components/GradesView/StatusAlerts/messages.d.ts +24 -0
- package/dist/components/GradesView/StatusAlerts/messages.js +20 -0
- package/dist/components/GradesView/StatusAlerts/messages.js.map +1 -0
- package/dist/components/GradesView/data/api.d.ts +44 -0
- package/dist/components/GradesView/data/api.js +64 -0
- package/dist/components/GradesView/data/api.js.map +1 -0
- package/dist/components/GradesView/data/apiHook.d.ts +92 -0
- package/dist/components/GradesView/data/apiHook.js +191 -0
- package/dist/components/GradesView/data/apiHook.js.map +1 -0
- package/dist/components/GradesView/data/hooks.d.ts +32 -0
- package/dist/components/GradesView/data/hooks.js +242 -0
- package/dist/components/GradesView/data/hooks.js.map +1 -0
- package/dist/components/GradesView/data/queryKeys.d.ts +13 -0
- package/dist/components/GradesView/data/queryKeys.js +15 -0
- package/dist/components/GradesView/data/queryKeys.js.map +1 -0
- package/dist/components/GradesView/data/utils.d.ts +96 -0
- package/dist/components/GradesView/data/utils.js +103 -0
- package/dist/components/GradesView/data/utils.js.map +1 -0
- package/dist/components/GradesView/index.d.ts +10 -0
- package/dist/components/GradesView/index.js +35 -0
- package/dist/components/GradesView/index.js.map +1 -0
- package/dist/components/GradesView/messages.d.ts +24 -0
- package/dist/components/GradesView/messages.js +20 -0
- package/dist/components/GradesView/messages.js.map +1 -0
- package/dist/components/NetworkButton/index.d.ts +23 -0
- package/dist/components/NetworkButton/index.js +54 -0
- package/dist/components/NetworkButton/index.js.map +1 -0
- package/dist/components/WithSidebar/WithSidebar.scss +36 -0
- package/dist/components/WithSidebar/index.d.ts +9 -0
- package/dist/components/WithSidebar/index.js +34 -0
- package/dist/components/WithSidebar/index.js.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -0
- package/dist/containers/GradebookPage/GradebookDataLoader.d.ts +10 -0
- package/dist/containers/GradebookPage/GradebookDataLoader.js +19 -0
- package/dist/containers/GradebookPage/GradebookDataLoader.js.map +1 -0
- package/dist/containers/GradebookPage/index.d.ts +2 -0
- package/dist/containers/GradebookPage/index.js +40 -0
- package/dist/containers/GradebookPage/index.js.map +1 -0
- package/dist/data/api.d.ts +20 -0
- package/dist/data/api.js +36 -0
- package/dist/data/api.js.map +1 -0
- package/dist/data/apiHook.d.ts +40 -0
- package/dist/data/apiHook.js +65 -0
- package/dist/data/apiHook.js.map +1 -0
- package/dist/data/constants/app.d.ts +13 -0
- package/dist/data/constants/app.js +58 -0
- package/dist/data/constants/app.js.map +1 -0
- package/dist/data/constants/errors.d.ts +2 -0
- package/dist/data/constants/errors.js +3 -0
- package/dist/data/constants/errors.js.map +1 -0
- package/dist/data/constants/filters.d.ts +15 -0
- package/dist/data/constants/filters.js +71 -0
- package/dist/data/constants/filters.js.map +1 -0
- package/dist/data/constants/filters.messages.d.ts +56 -0
- package/dist/data/constants/filters.messages.js +40 -0
- package/dist/data/constants/filters.messages.js.map +1 -0
- package/dist/data/constants/grades.d.ts +6 -0
- package/dist/data/constants/grades.js +17 -0
- package/dist/data/constants/grades.js.map +1 -0
- package/dist/data/filtersContext.d.ts +60 -0
- package/dist/data/filtersContext.js +212 -0
- package/dist/data/filtersContext.js.map +1 -0
- package/dist/data/filtersSnapshot.d.ts +20 -0
- package/dist/data/filtersSnapshot.js +15 -0
- package/dist/data/filtersSnapshot.js.map +1 -0
- package/dist/data/formatUtils.d.ts +15 -0
- package/dist/data/formatUtils.js +35 -0
- package/dist/data/formatUtils.js.map +1 -0
- package/dist/data/gradebookUiContext.d.ts +99 -0
- package/dist/data/gradebookUiContext.js +143 -0
- package/dist/data/gradebookUiContext.js.map +1 -0
- package/dist/data/queryClient.d.ts +10 -0
- package/dist/data/queryClient.js +34 -0
- package/dist/data/queryClient.js.map +1 -0
- package/dist/data/queryKeys.d.ts +11 -0
- package/dist/data/queryKeys.js +21 -0
- package/dist/data/queryKeys.js.map +1 -0
- package/dist/data/services/lms/api.d.ts +2 -0
- package/dist/data/services/lms/api.js +104 -0
- package/dist/data/services/lms/api.js.map +1 -0
- package/dist/data/services/lms/constants.d.ts +3 -0
- package/dist/data/services/lms/constants.js +16 -0
- package/dist/data/services/lms/constants.js.map +1 -0
- package/dist/data/services/lms/index.d.ts +2 -0
- package/dist/data/services/lms/index.js +8 -0
- package/dist/data/services/lms/index.js.map +1 -0
- package/dist/data/services/lms/messages.d.ts +2 -0
- package/dist/data/services/lms/messages.js +8 -0
- package/dist/data/services/lms/messages.js.map +1 -0
- package/dist/data/services/lms/urls.d.ts +19 -0
- package/dist/data/services/lms/urls.js +47 -0
- package/dist/data/services/lms/urls.js.map +1 -0
- package/dist/data/services/lms/utils.d.ts +4 -0
- package/dist/data/services/lms/utils.js +34 -0
- package/dist/data/services/lms/utils.js.map +1 -0
- package/dist/data/services/segment/constants.d.ts +8 -0
- package/dist/data/services/segment/constants.js +26 -0
- package/dist/data/services/segment/constants.js.map +1 -0
- package/dist/data/services/segment/events.d.ts +14 -0
- package/dist/data/services/segment/events.js +32 -0
- package/dist/data/services/segment/events.js.map +1 -0
- package/dist/data/utils.d.ts +10 -0
- package/dist/data/utils.js +14 -0
- package/dist/data/utils.js.map +1 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/utils.d.ts +2 -0
- package/dist/i18n/utils.js +21 -0
- package/dist/i18n/utils.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.d.ts +8 -0
- package/dist/messages.js +10 -0
- package/dist/messages.js.map +1 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +13 -0
- package/dist/providers.js.map +1 -0
- package/dist/routes.d.ts +11 -0
- package/dist/routes.js +16 -0
- package/dist/routes.js.map +1 -0
- package/dist/style.scss +13 -0
- package/dist/utils/StrictDict.d.ts +2 -0
- package/dist/utils/StrictDict.js +19 -0
- package/dist/utils/StrictDict.js.map +1 -0
- package/dist/utils/formatDate.d.ts +15 -0
- package/dist/utils/formatDate.js +19 -0
- package/dist/utils/formatDate.js.map +1 -0
- package/dist/utils/hoc.d.ts +3 -0
- package/dist/utils/hoc.js +21 -0
- package/dist/utils/hoc.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/keyStore.d.ts +2 -0
- package/dist/utils/keyStore.js +4 -0
- package/dist/utils/keyStore.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useMemo, useRef, useState, } from 'react';
|
|
3
|
+
import { useSearchParams } from 'react-router-dom';
|
|
4
|
+
import initialFilters from './constants/filters';
|
|
5
|
+
import { filtersSnapshot } from './filtersSnapshot';
|
|
6
|
+
const FiltersContext = createContext(undefined);
|
|
7
|
+
export const FiltersProvider = ({ children }) => {
|
|
8
|
+
const [searchParams] = useSearchParams();
|
|
9
|
+
// Initial values seeded from the URL query (mirrors the legacy
|
|
10
|
+
// `filters.initialize(urlQuery)`). Computed once.
|
|
11
|
+
const initialValues = useMemo(() => {
|
|
12
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
13
|
+
return ({
|
|
14
|
+
assignmentType: (_a = searchParams.get('assignmentType')) !== null && _a !== void 0 ? _a : initialFilters.assignmentType,
|
|
15
|
+
assignment: (_b = searchParams.get('assignment')) !== null && _b !== void 0 ? _b : initialFilters.assignment,
|
|
16
|
+
includeCourseRoleMembers: searchParams.get('includeCourseRoleMembers') === 'true',
|
|
17
|
+
cohort: (_c = searchParams.get('cohort')) !== null && _c !== void 0 ? _c : initialFilters.cohort,
|
|
18
|
+
track: (_d = searchParams.get('track')) !== null && _d !== void 0 ? _d : initialFilters.track,
|
|
19
|
+
assignmentGradeMin: (_e = searchParams.get('assignmentGradeMin')) !== null && _e !== void 0 ? _e : initialFilters.assignmentGradeMin,
|
|
20
|
+
assignmentGradeMax: (_f = searchParams.get('assignmentGradeMax')) !== null && _f !== void 0 ? _f : initialFilters.assignmentGradeMax,
|
|
21
|
+
courseGradeMin: (_g = searchParams.get('courseGradeMin')) !== null && _g !== void 0 ? _g : initialFilters.courseGradeMin,
|
|
22
|
+
courseGradeMax: (_h = searchParams.get('courseGradeMax')) !== null && _h !== void 0 ? _h : initialFilters.courseGradeMax,
|
|
23
|
+
searchValue: '',
|
|
24
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
|
+
});
|
|
26
|
+
}, []);
|
|
27
|
+
// Seed the synchronous snapshot from the URL values on the first render, before
|
|
28
|
+
// the grades query (which reads it in its queryFn) fires — the query is gated on
|
|
29
|
+
// the roles query, so it resolves well after this. The wrapped setters below keep
|
|
30
|
+
// the snapshot in sync synchronously thereafter.
|
|
31
|
+
const snapshotSeeded = useRef(false);
|
|
32
|
+
if (!snapshotSeeded.current) {
|
|
33
|
+
Object.assign(filtersSnapshot, initialValues);
|
|
34
|
+
snapshotSeeded.current = true;
|
|
35
|
+
}
|
|
36
|
+
const [assignmentType, setAssignmentTypeState] = useState(initialValues.assignmentType);
|
|
37
|
+
const [assignment, setAssignmentState] = useState(initialValues.assignment);
|
|
38
|
+
const [includeCourseRoleMembers, setIncludeCourseRoleMembersState] = useState(initialValues.includeCourseRoleMembers);
|
|
39
|
+
const [cohort, setCohortState] = useState(initialValues.cohort);
|
|
40
|
+
const [track, setTrackState] = useState(initialValues.track);
|
|
41
|
+
// Grade-limit "live" values (previously the Redux `app.filters` sub-slice).
|
|
42
|
+
const [assignmentGradeMin, setAssignmentGradeMinState] = useState(initialValues.assignmentGradeMin);
|
|
43
|
+
const [assignmentGradeMax, setAssignmentGradeMaxState] = useState(initialValues.assignmentGradeMax);
|
|
44
|
+
const [courseGradeMin, setCourseGradeMinState] = useState(initialValues.courseGradeMin);
|
|
45
|
+
const [courseGradeMax, setCourseGradeMaxState] = useState(initialValues.courseGradeMax);
|
|
46
|
+
const [searchValue, setSearchValueState] = useState(initialValues.searchValue);
|
|
47
|
+
// Applied grade-limit values (committed on Apply). Seeded from the URL values, so
|
|
48
|
+
// on a deep link the badges/export match the initial fetch.
|
|
49
|
+
const [appliedAssignmentGradeMin, setAppliedAssignmentGradeMin] = useState(initialValues.assignmentGradeMin);
|
|
50
|
+
const [appliedAssignmentGradeMax, setAppliedAssignmentGradeMax] = useState(initialValues.assignmentGradeMax);
|
|
51
|
+
const [appliedCourseGradeMin, setAppliedCourseGradeMin] = useState(initialValues.courseGradeMin);
|
|
52
|
+
const [appliedCourseGradeMax, setAppliedCourseGradeMax] = useState(initialValues.courseGradeMax);
|
|
53
|
+
// Wrapped setters: update the synchronous snapshot first (so the grades queryFn
|
|
54
|
+
// reads the latest value at invalidate time), then the React state.
|
|
55
|
+
const setAssignmentType = useCallback((v) => {
|
|
56
|
+
filtersSnapshot.assignmentType = v;
|
|
57
|
+
setAssignmentTypeState(v);
|
|
58
|
+
}, []);
|
|
59
|
+
const setAssignment = useCallback((v) => {
|
|
60
|
+
filtersSnapshot.assignment = v;
|
|
61
|
+
setAssignmentState(v);
|
|
62
|
+
}, []);
|
|
63
|
+
const setIncludeCourseRoleMembers = useCallback((v) => {
|
|
64
|
+
filtersSnapshot.includeCourseRoleMembers = v;
|
|
65
|
+
setIncludeCourseRoleMembersState(v);
|
|
66
|
+
}, []);
|
|
67
|
+
const setCohort = useCallback((v) => {
|
|
68
|
+
filtersSnapshot.cohort = v;
|
|
69
|
+
setCohortState(v);
|
|
70
|
+
}, []);
|
|
71
|
+
const setTrack = useCallback((v) => {
|
|
72
|
+
filtersSnapshot.track = v;
|
|
73
|
+
setTrackState(v);
|
|
74
|
+
}, []);
|
|
75
|
+
// The grade-limit setters hold live (per-keystroke) input values, so they do
|
|
76
|
+
// NOT touch the snapshot: fetches must only ever see the applied values, which
|
|
77
|
+
// `applyAssignmentGradeLimits`/`applyCourseGradeLimits`/`resetFilters` commit
|
|
78
|
+
// to the snapshot below (matching the legacy split between the live `app`
|
|
79
|
+
// inputs and the apply-committed `filters` slice the fetch read).
|
|
80
|
+
const setAssignmentGradeMin = useCallback((v) => {
|
|
81
|
+
setAssignmentGradeMinState(v);
|
|
82
|
+
}, []);
|
|
83
|
+
const setAssignmentGradeMax = useCallback((v) => {
|
|
84
|
+
setAssignmentGradeMaxState(v);
|
|
85
|
+
}, []);
|
|
86
|
+
const setCourseGradeMin = useCallback((v) => {
|
|
87
|
+
setCourseGradeMinState(v);
|
|
88
|
+
}, []);
|
|
89
|
+
const setCourseGradeMax = useCallback((v) => {
|
|
90
|
+
setCourseGradeMaxState(v);
|
|
91
|
+
}, []);
|
|
92
|
+
const setSearchValue = useCallback((v) => {
|
|
93
|
+
filtersSnapshot.searchValue = v;
|
|
94
|
+
setSearchValueState(v);
|
|
95
|
+
}, []);
|
|
96
|
+
const applyAssignmentGradeLimits = useCallback(({ assignmentGradeMin: min, assignmentGradeMax: max }) => {
|
|
97
|
+
filtersSnapshot.assignmentGradeMin = min;
|
|
98
|
+
filtersSnapshot.assignmentGradeMax = max;
|
|
99
|
+
setAppliedAssignmentGradeMin(min);
|
|
100
|
+
setAppliedAssignmentGradeMax(max);
|
|
101
|
+
}, []);
|
|
102
|
+
const applyCourseGradeLimits = useCallback(({ courseGradeMin: min, courseGradeMax: max }) => {
|
|
103
|
+
filtersSnapshot.courseGradeMin = min;
|
|
104
|
+
filtersSnapshot.courseGradeMax = max;
|
|
105
|
+
setAppliedCourseGradeMin(min);
|
|
106
|
+
setAppliedCourseGradeMax(max);
|
|
107
|
+
}, []);
|
|
108
|
+
// Reset the named filters to their defaults (badge close). Mirrors the Redux
|
|
109
|
+
// `filters.reset`; also clears the applied grade-limit values so the badges/export
|
|
110
|
+
// update. The wrapped setters keep the snapshot in sync for the grades fetch.
|
|
111
|
+
const resetFilters = useCallback((filterNames) => {
|
|
112
|
+
filterNames.forEach((name) => {
|
|
113
|
+
switch (name) {
|
|
114
|
+
case 'assignmentType':
|
|
115
|
+
setAssignmentType(initialFilters.assignmentType);
|
|
116
|
+
break;
|
|
117
|
+
case 'assignment':
|
|
118
|
+
setAssignment(initialFilters.assignment);
|
|
119
|
+
break;
|
|
120
|
+
case 'cohort':
|
|
121
|
+
setCohort(initialFilters.cohort);
|
|
122
|
+
break;
|
|
123
|
+
case 'track':
|
|
124
|
+
setTrack(initialFilters.track);
|
|
125
|
+
break;
|
|
126
|
+
case 'includeCourseRoleMembers':
|
|
127
|
+
setIncludeCourseRoleMembers(initialFilters.includeCourseRoleMembers);
|
|
128
|
+
break;
|
|
129
|
+
case 'assignmentGradeMin':
|
|
130
|
+
filtersSnapshot.assignmentGradeMin = initialFilters.assignmentGradeMin;
|
|
131
|
+
setAssignmentGradeMin(initialFilters.assignmentGradeMin);
|
|
132
|
+
setAppliedAssignmentGradeMin(initialFilters.assignmentGradeMin);
|
|
133
|
+
break;
|
|
134
|
+
case 'assignmentGradeMax':
|
|
135
|
+
filtersSnapshot.assignmentGradeMax = initialFilters.assignmentGradeMax;
|
|
136
|
+
setAssignmentGradeMax(initialFilters.assignmentGradeMax);
|
|
137
|
+
setAppliedAssignmentGradeMax(initialFilters.assignmentGradeMax);
|
|
138
|
+
break;
|
|
139
|
+
case 'courseGradeMin':
|
|
140
|
+
filtersSnapshot.courseGradeMin = initialFilters.courseGradeMin;
|
|
141
|
+
setCourseGradeMin(initialFilters.courseGradeMin);
|
|
142
|
+
setAppliedCourseGradeMin(initialFilters.courseGradeMin);
|
|
143
|
+
break;
|
|
144
|
+
case 'courseGradeMax':
|
|
145
|
+
filtersSnapshot.courseGradeMax = initialFilters.courseGradeMax;
|
|
146
|
+
setCourseGradeMax(initialFilters.courseGradeMax);
|
|
147
|
+
setAppliedCourseGradeMax(initialFilters.courseGradeMax);
|
|
148
|
+
break;
|
|
149
|
+
default: break;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}, [
|
|
153
|
+
setAssignmentType, setAssignment, setCohort, setTrack, setIncludeCourseRoleMembers,
|
|
154
|
+
setAssignmentGradeMin, setAssignmentGradeMax, setCourseGradeMin, setCourseGradeMax,
|
|
155
|
+
]);
|
|
156
|
+
const value = useMemo(() => ({
|
|
157
|
+
assignmentType,
|
|
158
|
+
setAssignmentType,
|
|
159
|
+
assignment,
|
|
160
|
+
setAssignment,
|
|
161
|
+
includeCourseRoleMembers,
|
|
162
|
+
setIncludeCourseRoleMembers,
|
|
163
|
+
cohort,
|
|
164
|
+
setCohort,
|
|
165
|
+
track,
|
|
166
|
+
setTrack,
|
|
167
|
+
assignmentGradeMin,
|
|
168
|
+
setAssignmentGradeMin,
|
|
169
|
+
assignmentGradeMax,
|
|
170
|
+
setAssignmentGradeMax,
|
|
171
|
+
courseGradeMin,
|
|
172
|
+
setCourseGradeMin,
|
|
173
|
+
courseGradeMax,
|
|
174
|
+
setCourseGradeMax,
|
|
175
|
+
searchValue,
|
|
176
|
+
setSearchValue,
|
|
177
|
+
appliedAssignmentGradeMin,
|
|
178
|
+
appliedAssignmentGradeMax,
|
|
179
|
+
appliedCourseGradeMin,
|
|
180
|
+
appliedCourseGradeMax,
|
|
181
|
+
applyAssignmentGradeLimits,
|
|
182
|
+
applyCourseGradeLimits,
|
|
183
|
+
resetFilters,
|
|
184
|
+
}), [
|
|
185
|
+
assignmentType, assignment, includeCourseRoleMembers, cohort, track,
|
|
186
|
+
assignmentGradeMin, assignmentGradeMax, courseGradeMin, courseGradeMax,
|
|
187
|
+
searchValue,
|
|
188
|
+
appliedAssignmentGradeMin, appliedAssignmentGradeMax,
|
|
189
|
+
appliedCourseGradeMin, appliedCourseGradeMax,
|
|
190
|
+
// Wrapped setters + apply ops are stable (useCallback []) but listed to
|
|
191
|
+
// satisfy exhaustive-deps:
|
|
192
|
+
setAssignmentType, setAssignment, setIncludeCourseRoleMembers, setCohort,
|
|
193
|
+
setTrack, setAssignmentGradeMin, setAssignmentGradeMax, setCourseGradeMin,
|
|
194
|
+
setCourseGradeMax, setSearchValue,
|
|
195
|
+
applyAssignmentGradeLimits, applyCourseGradeLimits, resetFilters,
|
|
196
|
+
]);
|
|
197
|
+
return (_jsx(FiltersContext.Provider, { value: value, children: children }));
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* useFilters()
|
|
201
|
+
* Accessor for the gradebook filter context. Throws if used outside a
|
|
202
|
+
* <FiltersProvider>.
|
|
203
|
+
*/
|
|
204
|
+
export const useFilters = () => {
|
|
205
|
+
const context = useContext(FiltersContext);
|
|
206
|
+
if (context === undefined) {
|
|
207
|
+
throw new Error('useFilters must be used within a FiltersProvider');
|
|
208
|
+
}
|
|
209
|
+
return context;
|
|
210
|
+
};
|
|
211
|
+
export default FiltersContext;
|
|
212
|
+
//# sourceMappingURL=filtersContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filtersContext.js","sourceRoot":"","sources":["../../src/data/filtersContext.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n createContext, useCallback, useContext, useMemo, useRef, useState,\n} from 'react';\nimport { useSearchParams } from 'react-router-dom';\n\nimport initialFilters from '@src/data/constants/filters';\nimport { filtersSnapshot } from '@src/data/filtersSnapshot';\n\n/**\n * Client-side gradebook filter state, held in React (Context + useState).\n *\n * Replaces the Redux `filters` slice (and the live grade-limit inputs from the\n * `app` slice). The provider also mirrors the fetch-relevant values into the\n * synchronous `filtersSnapshot`, which the grades queryFn reads at fetch time.\n */\nexport interface FiltersContextValue {\n assignmentType: string;\n setAssignmentType: (value: string) => void;\n // The selected assignment id; the label/type are derived from the grades\n // query results.\n assignment: string;\n setAssignment: (value: string) => void;\n includeCourseRoleMembers: boolean;\n setIncludeCourseRoleMembers: (value: boolean) => void;\n cohort: string;\n setCohort: (value: string) => void;\n track: string;\n setTrack: (value: string) => void;\n assignmentGradeMin: string;\n setAssignmentGradeMin: (value: string) => void;\n assignmentGradeMax: string;\n setAssignmentGradeMax: (value: string) => void;\n courseGradeMin: string;\n setCourseGradeMin: (value: string) => void;\n courseGradeMax: string;\n setCourseGradeMax: (value: string) => void;\n // Username/email search text (was Redux `app.searchValue`). Not persisted in the\n // URL, so it starts empty.\n searchValue: string;\n setSearchValue: (value: string) => void;\n // Applied (committed-on-Apply) grade-limit values. The setters above hold the\n // \"live\" input values (per keystroke); these hold what was last applied and are\n // what the filter badges + export URLs reflect (was the Redux `filters` slice\n // grade limits, set by `update.assignmentLimits`/`update.courseGradeLimits`).\n appliedAssignmentGradeMin: string;\n appliedAssignmentGradeMax: string;\n appliedCourseGradeMin: string;\n appliedCourseGradeMax: string;\n applyAssignmentGradeLimits: (limits: { assignmentGradeMin: string; assignmentGradeMax: string }) => void;\n applyCourseGradeLimits: (limits: { courseGradeMin: string; courseGradeMax: string }) => void;\n /**\n * Reset the given filter names to their defaults (used by the active-filter\n * badge close buttons). Resets both the live and applied grade-limit values.\n * Was the Redux `filters.reset` action.\n */\n resetFilters: (filterNames: string[]) => void;\n}\n\nconst FiltersContext = createContext<FiltersContextValue | undefined>(undefined);\n\ninterface FiltersProviderProps {\n children: React.ReactNode;\n}\n\nexport const FiltersProvider = ({ children }: FiltersProviderProps) => {\n const [searchParams] = useSearchParams();\n // Initial values seeded from the URL query (mirrors the legacy\n // `filters.initialize(urlQuery)`). Computed once.\n const initialValues = useMemo(() => ({\n assignmentType: searchParams.get('assignmentType') ?? initialFilters.assignmentType,\n assignment: searchParams.get('assignment') ?? initialFilters.assignment,\n includeCourseRoleMembers: searchParams.get('includeCourseRoleMembers') === 'true',\n cohort: searchParams.get('cohort') ?? initialFilters.cohort,\n track: searchParams.get('track') ?? initialFilters.track,\n assignmentGradeMin: searchParams.get('assignmentGradeMin') ?? initialFilters.assignmentGradeMin,\n assignmentGradeMax: searchParams.get('assignmentGradeMax') ?? initialFilters.assignmentGradeMax,\n courseGradeMin: searchParams.get('courseGradeMin') ?? initialFilters.courseGradeMin,\n courseGradeMax: searchParams.get('courseGradeMax') ?? initialFilters.courseGradeMax,\n searchValue: '',\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }), []);\n\n // Seed the synchronous snapshot from the URL values on the first render, before\n // the grades query (which reads it in its queryFn) fires — the query is gated on\n // the roles query, so it resolves well after this. The wrapped setters below keep\n // the snapshot in sync synchronously thereafter.\n const snapshotSeeded = useRef(false);\n if (!snapshotSeeded.current) {\n Object.assign(filtersSnapshot, initialValues);\n snapshotSeeded.current = true;\n }\n\n const [assignmentType, setAssignmentTypeState] = useState<string>(initialValues.assignmentType);\n const [assignment, setAssignmentState] = useState<string>(initialValues.assignment);\n const [includeCourseRoleMembers, setIncludeCourseRoleMembersState] = useState<boolean>(\n initialValues.includeCourseRoleMembers,\n );\n const [cohort, setCohortState] = useState<string>(initialValues.cohort);\n const [track, setTrackState] = useState<string>(initialValues.track);\n // Grade-limit \"live\" values (previously the Redux `app.filters` sub-slice).\n const [assignmentGradeMin, setAssignmentGradeMinState] = useState<string>(\n initialValues.assignmentGradeMin,\n );\n const [assignmentGradeMax, setAssignmentGradeMaxState] = useState<string>(\n initialValues.assignmentGradeMax,\n );\n const [courseGradeMin, setCourseGradeMinState] = useState<string>(initialValues.courseGradeMin);\n const [courseGradeMax, setCourseGradeMaxState] = useState<string>(initialValues.courseGradeMax);\n const [searchValue, setSearchValueState] = useState<string>(initialValues.searchValue);\n\n // Applied grade-limit values (committed on Apply). Seeded from the URL values, so\n // on a deep link the badges/export match the initial fetch.\n const [appliedAssignmentGradeMin, setAppliedAssignmentGradeMin] = useState<string>(\n initialValues.assignmentGradeMin,\n );\n const [appliedAssignmentGradeMax, setAppliedAssignmentGradeMax] = useState<string>(\n initialValues.assignmentGradeMax,\n );\n const [appliedCourseGradeMin, setAppliedCourseGradeMin] = useState<string>(\n initialValues.courseGradeMin,\n );\n const [appliedCourseGradeMax, setAppliedCourseGradeMax] = useState<string>(\n initialValues.courseGradeMax,\n );\n\n // Wrapped setters: update the synchronous snapshot first (so the grades queryFn\n // reads the latest value at invalidate time), then the React state.\n const setAssignmentType = useCallback((v: string) => {\n filtersSnapshot.assignmentType = v;\n setAssignmentTypeState(v);\n }, []);\n const setAssignment = useCallback((v: string) => {\n filtersSnapshot.assignment = v;\n setAssignmentState(v);\n }, []);\n const setIncludeCourseRoleMembers = useCallback((v: boolean) => {\n filtersSnapshot.includeCourseRoleMembers = v;\n setIncludeCourseRoleMembersState(v);\n }, []);\n const setCohort = useCallback((v: string) => {\n filtersSnapshot.cohort = v;\n setCohortState(v);\n }, []);\n const setTrack = useCallback((v: string) => {\n filtersSnapshot.track = v;\n setTrackState(v);\n }, []);\n // The grade-limit setters hold live (per-keystroke) input values, so they do\n // NOT touch the snapshot: fetches must only ever see the applied values, which\n // `applyAssignmentGradeLimits`/`applyCourseGradeLimits`/`resetFilters` commit\n // to the snapshot below (matching the legacy split between the live `app`\n // inputs and the apply-committed `filters` slice the fetch read).\n const setAssignmentGradeMin = useCallback((v: string) => {\n setAssignmentGradeMinState(v);\n }, []);\n const setAssignmentGradeMax = useCallback((v: string) => {\n setAssignmentGradeMaxState(v);\n }, []);\n const setCourseGradeMin = useCallback((v: string) => {\n setCourseGradeMinState(v);\n }, []);\n const setCourseGradeMax = useCallback((v: string) => {\n setCourseGradeMaxState(v);\n }, []);\n const setSearchValue = useCallback((v: string) => {\n filtersSnapshot.searchValue = v;\n setSearchValueState(v);\n }, []);\n\n const applyAssignmentGradeLimits = useCallback(\n ({ assignmentGradeMin: min, assignmentGradeMax: max }: {\n assignmentGradeMin: string; assignmentGradeMax: string;\n }) => {\n filtersSnapshot.assignmentGradeMin = min;\n filtersSnapshot.assignmentGradeMax = max;\n setAppliedAssignmentGradeMin(min);\n setAppliedAssignmentGradeMax(max);\n },\n [],\n );\n const applyCourseGradeLimits = useCallback(\n ({ courseGradeMin: min, courseGradeMax: max }: {\n courseGradeMin: string; courseGradeMax: string;\n }) => {\n filtersSnapshot.courseGradeMin = min;\n filtersSnapshot.courseGradeMax = max;\n setAppliedCourseGradeMin(min);\n setAppliedCourseGradeMax(max);\n },\n [],\n );\n\n // Reset the named filters to their defaults (badge close). Mirrors the Redux\n // `filters.reset`; also clears the applied grade-limit values so the badges/export\n // update. The wrapped setters keep the snapshot in sync for the grades fetch.\n const resetFilters = useCallback((filterNames: string[]) => {\n filterNames.forEach((name) => {\n switch (name) {\n case 'assignmentType':\n setAssignmentType(initialFilters.assignmentType);\n break;\n case 'assignment':\n setAssignment(initialFilters.assignment);\n break;\n case 'cohort':\n setCohort(initialFilters.cohort);\n break;\n case 'track':\n setTrack(initialFilters.track);\n break;\n case 'includeCourseRoleMembers':\n setIncludeCourseRoleMembers(initialFilters.includeCourseRoleMembers);\n break;\n case 'assignmentGradeMin':\n filtersSnapshot.assignmentGradeMin = initialFilters.assignmentGradeMin;\n setAssignmentGradeMin(initialFilters.assignmentGradeMin);\n setAppliedAssignmentGradeMin(initialFilters.assignmentGradeMin);\n break;\n case 'assignmentGradeMax':\n filtersSnapshot.assignmentGradeMax = initialFilters.assignmentGradeMax;\n setAssignmentGradeMax(initialFilters.assignmentGradeMax);\n setAppliedAssignmentGradeMax(initialFilters.assignmentGradeMax);\n break;\n case 'courseGradeMin':\n filtersSnapshot.courseGradeMin = initialFilters.courseGradeMin;\n setCourseGradeMin(initialFilters.courseGradeMin);\n setAppliedCourseGradeMin(initialFilters.courseGradeMin);\n break;\n case 'courseGradeMax':\n filtersSnapshot.courseGradeMax = initialFilters.courseGradeMax;\n setCourseGradeMax(initialFilters.courseGradeMax);\n setAppliedCourseGradeMax(initialFilters.courseGradeMax);\n break;\n default: break;\n }\n });\n }, [\n setAssignmentType, setAssignment, setCohort, setTrack, setIncludeCourseRoleMembers,\n setAssignmentGradeMin, setAssignmentGradeMax, setCourseGradeMin, setCourseGradeMax,\n ]);\n\n const value = useMemo<FiltersContextValue>(\n () => ({\n assignmentType,\n setAssignmentType,\n assignment,\n setAssignment,\n includeCourseRoleMembers,\n setIncludeCourseRoleMembers,\n cohort,\n setCohort,\n track,\n setTrack,\n assignmentGradeMin,\n setAssignmentGradeMin,\n assignmentGradeMax,\n setAssignmentGradeMax,\n courseGradeMin,\n setCourseGradeMin,\n courseGradeMax,\n setCourseGradeMax,\n searchValue,\n setSearchValue,\n appliedAssignmentGradeMin,\n appliedAssignmentGradeMax,\n appliedCourseGradeMin,\n appliedCourseGradeMax,\n applyAssignmentGradeLimits,\n applyCourseGradeLimits,\n resetFilters,\n }),\n [\n assignmentType, assignment, includeCourseRoleMembers, cohort, track,\n assignmentGradeMin, assignmentGradeMax, courseGradeMin, courseGradeMax,\n searchValue,\n appliedAssignmentGradeMin, appliedAssignmentGradeMax,\n appliedCourseGradeMin, appliedCourseGradeMax,\n // Wrapped setters + apply ops are stable (useCallback []) but listed to\n // satisfy exhaustive-deps:\n setAssignmentType, setAssignment, setIncludeCourseRoleMembers, setCohort,\n setTrack, setAssignmentGradeMin, setAssignmentGradeMax, setCourseGradeMin,\n setCourseGradeMax, setSearchValue,\n applyAssignmentGradeLimits, applyCourseGradeLimits, resetFilters,\n ],\n );\n\n return (\n <FiltersContext.Provider value={value}>\n {children}\n </FiltersContext.Provider>\n );\n};\n\n/**\n * useFilters()\n * Accessor for the gradebook filter context. Throws if used outside a\n * <FiltersProvider>.\n */\nexport const useFilters = (): FiltersContextValue => {\n const context = useContext(FiltersContext);\n if (context === undefined) {\n throw new Error('useFilters must be used within a FiltersProvider');\n }\n return context;\n};\n\nexport default FiltersContext;\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous mirror of the `FiltersProvider` filter values, read by the grades
|
|
3
|
+
* queryFn at fetch time. The grade-limit values mirror the APPLIED limits (they
|
|
4
|
+
* are only committed on apply/reset), not the live input values.
|
|
5
|
+
*/
|
|
6
|
+
export interface FiltersSnapshot {
|
|
7
|
+
assignmentType: string;
|
|
8
|
+
/** Selected assignment id (the label/type are derived from the query results). */
|
|
9
|
+
assignment: string;
|
|
10
|
+
includeCourseRoleMembers: boolean;
|
|
11
|
+
cohort: string;
|
|
12
|
+
track: string;
|
|
13
|
+
assignmentGradeMin: string;
|
|
14
|
+
assignmentGradeMax: string;
|
|
15
|
+
courseGradeMin: string;
|
|
16
|
+
courseGradeMax: string;
|
|
17
|
+
searchValue: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const filtersSnapshot: FiltersSnapshot;
|
|
20
|
+
export default filtersSnapshot;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import initialFilters from './constants/filters';
|
|
2
|
+
export const filtersSnapshot = {
|
|
3
|
+
assignmentType: initialFilters.assignmentType,
|
|
4
|
+
assignment: initialFilters.assignment,
|
|
5
|
+
includeCourseRoleMembers: initialFilters.includeCourseRoleMembers,
|
|
6
|
+
cohort: initialFilters.cohort,
|
|
7
|
+
track: initialFilters.track,
|
|
8
|
+
assignmentGradeMin: initialFilters.assignmentGradeMin,
|
|
9
|
+
assignmentGradeMax: initialFilters.assignmentGradeMax,
|
|
10
|
+
courseGradeMin: initialFilters.courseGradeMin,
|
|
11
|
+
courseGradeMax: initialFilters.courseGradeMax,
|
|
12
|
+
searchValue: '',
|
|
13
|
+
};
|
|
14
|
+
export default filtersSnapshot;
|
|
15
|
+
//# sourceMappingURL=filtersSnapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filtersSnapshot.js","sourceRoot":"","sources":["../../src/data/filtersSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,6BAA6B,CAAC;AAsBzD,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,cAAc,EAAE,cAAc,CAAC,cAAc;IAC7C,UAAU,EAAE,cAAc,CAAC,UAAU;IACrC,wBAAwB,EAAE,cAAc,CAAC,wBAAwB;IACjE,MAAM,EAAE,cAAc,CAAC,MAAM;IAC7B,KAAK,EAAE,cAAc,CAAC,KAAK;IAC3B,kBAAkB,EAAE,cAAc,CAAC,kBAAkB;IACrD,kBAAkB,EAAE,cAAc,CAAC,kBAAkB;IACrD,cAAc,EAAE,cAAc,CAAC,cAAc;IAC7C,cAAc,EAAE,cAAc,CAAC,cAAc;IAC7C,WAAW,EAAE,EAAE;CAChB,CAAC;AAEF,eAAe,eAAe,CAAC","sourcesContent":["import initialFilters from '@src/data/constants/filters';\n\n/**\n * Synchronous mirror of the `FiltersProvider` filter values, read by the grades\n * queryFn at fetch time. The grade-limit values mirror the APPLIED limits (they\n * are only committed on apply/reset), not the live input values.\n */\n\nexport interface FiltersSnapshot {\n assignmentType: string;\n /** Selected assignment id (the label/type are derived from the query results). */\n assignment: string;\n includeCourseRoleMembers: boolean;\n cohort: string;\n track: string;\n assignmentGradeMin: string;\n assignmentGradeMax: string;\n courseGradeMin: string;\n courseGradeMax: string;\n searchValue: string;\n}\n\nexport const filtersSnapshot: FiltersSnapshot = {\n assignmentType: initialFilters.assignmentType,\n assignment: initialFilters.assignment,\n includeCourseRoleMembers: initialFilters.includeCourseRoleMembers,\n cohort: initialFilters.cohort,\n track: initialFilters.track,\n assignmentGradeMin: initialFilters.assignmentGradeMin,\n assignmentGradeMax: initialFilters.assignmentGradeMax,\n courseGradeMin: initialFilters.courseGradeMin,\n courseGradeMax: initialFilters.courseGradeMax,\n searchValue: '',\n};\n\nexport default filtersSnapshot;\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export namespace options {
|
|
2
|
+
let year: string;
|
|
3
|
+
let month: string;
|
|
4
|
+
let day: string;
|
|
5
|
+
let timeZone: string;
|
|
6
|
+
}
|
|
7
|
+
export namespace timeOptions {
|
|
8
|
+
export let hour: string;
|
|
9
|
+
export let minute: string;
|
|
10
|
+
let timeZone_1: string;
|
|
11
|
+
export { timeZone_1 as timeZone };
|
|
12
|
+
export let timeZoneName: string;
|
|
13
|
+
}
|
|
14
|
+
export function formatDateForDisplay(inputDate: any): string;
|
|
15
|
+
export function sortAlphaAsc(gradeRowA: any, gradeRowB: any): 1 | -1 | 0;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Pure, framework-agnostic formatting helpers used by the live data layer. These
|
|
2
|
+
// were previously exported from `data/actions/utils.js` (a Redux module that also
|
|
3
|
+
// imported `@reduxjs/toolkit`); they are relocated here so the runtime path no
|
|
4
|
+
// longer pulls Redux in. Logic is unchanged.
|
|
5
|
+
export const options = {
|
|
6
|
+
year: 'numeric',
|
|
7
|
+
month: 'long',
|
|
8
|
+
day: 'numeric',
|
|
9
|
+
timeZone: 'UTC',
|
|
10
|
+
};
|
|
11
|
+
export const timeOptions = {
|
|
12
|
+
hour: '2-digit',
|
|
13
|
+
minute: '2-digit',
|
|
14
|
+
timeZone: 'UTC',
|
|
15
|
+
timeZoneName: 'short',
|
|
16
|
+
};
|
|
17
|
+
/** Formats a Date as "Month D, YYYY at HH:MM TZ" (UTC), for history/modal display. */
|
|
18
|
+
export const formatDateForDisplay = (inputDate) => {
|
|
19
|
+
const date = inputDate.toLocaleDateString('en-US', options);
|
|
20
|
+
const time = inputDate.toLocaleTimeString('en-US', timeOptions);
|
|
21
|
+
return `${date} at ${time}`;
|
|
22
|
+
};
|
|
23
|
+
/** Case-insensitive comparator sorting grade rows by username (ascending). */
|
|
24
|
+
export const sortAlphaAsc = (gradeRowA, gradeRowB) => {
|
|
25
|
+
const a = gradeRowA.username.toUpperCase();
|
|
26
|
+
const b = gradeRowB.username.toUpperCase();
|
|
27
|
+
if (a < b) {
|
|
28
|
+
return -1;
|
|
29
|
+
}
|
|
30
|
+
if (a > b) {
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=formatUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatUtils.js","sourceRoot":"","sources":["../../src/data/formatUtils.js"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,kFAAkF;AAClF,+EAA+E;AAC/E,6CAA6C;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,MAAM;IACb,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,KAAK;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,OAAO;CACtB,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAS,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAChE,OAAO,GAAG,IAAI,OAAO,IAAI,EAAE,CAAC;AAC9B,CAAC,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE;IACnD,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC","sourcesContent":["// Pure, framework-agnostic formatting helpers used by the live data layer. These\n// were previously exported from `data/actions/utils.js` (a Redux module that also\n// imported `@reduxjs/toolkit`); they are relocated here so the runtime path no\n// longer pulls Redux in. Logic is unchanged.\n\nexport const options = {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n timeZone: 'UTC',\n};\n\nexport const timeOptions = {\n hour: '2-digit',\n minute: '2-digit',\n timeZone: 'UTC',\n timeZoneName: 'short',\n};\n\n/** Formats a Date as \"Month D, YYYY at HH:MM TZ\" (UTC), for history/modal display. */\nexport const formatDateForDisplay = (inputDate) => {\n const date = inputDate.toLocaleDateString('en-US', options);\n const time = inputDate.toLocaleTimeString('en-US', timeOptions);\n return `${date} at ${time}`;\n};\n\n/** Case-insensitive comparator sorting grade rows by username (ascending). */\nexport const sortAlphaAsc = (gradeRowA, gradeRowB) => {\n const a = gradeRowA.username.toUpperCase();\n const b = gradeRowB.username.toUpperCase();\n if (a < b) {\n return -1;\n }\n if (a > b) {\n return 1;\n }\n return 0;\n};\n"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/** Edit-grade modal state (was the Redux `app.modalState` slice). */
|
|
3
|
+
export interface ModalState {
|
|
4
|
+
open: boolean;
|
|
5
|
+
adjustedGradePossible: string | number;
|
|
6
|
+
adjustedGradeValue: string | number;
|
|
7
|
+
assignmentName: string;
|
|
8
|
+
reasonForChange: string;
|
|
9
|
+
todaysDate: string;
|
|
10
|
+
updateModuleId: string | null;
|
|
11
|
+
updateUserId: number | null;
|
|
12
|
+
updateUserName: string | null;
|
|
13
|
+
}
|
|
14
|
+
/** Payload for opening the modal from a grade-table cell. */
|
|
15
|
+
export interface ModalStateFromTablePayload {
|
|
16
|
+
subsection: {
|
|
17
|
+
attempted?: boolean;
|
|
18
|
+
score_possible?: number;
|
|
19
|
+
subsection_name?: string;
|
|
20
|
+
module_id?: string;
|
|
21
|
+
};
|
|
22
|
+
userEntry: {
|
|
23
|
+
user_id?: number;
|
|
24
|
+
username?: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Client-side gradebook **UI** state, held in React (Context + useState).
|
|
29
|
+
*
|
|
30
|
+
* Replaces the non-filter UI bits of the old Redux `app` and `grades` slices:
|
|
31
|
+
* grade format toggle, success banner, import toast, active view, filter-menu
|
|
32
|
+
* open/transition, modal state, pagination cursor, and CSV-upload feedback.
|
|
33
|
+
*/
|
|
34
|
+
export interface GradebookUiContextValue {
|
|
35
|
+
/** Grade display format: 'percent' | 'absolute'. */
|
|
36
|
+
gradeFormat: string;
|
|
37
|
+
setGradeFormat: (value: string) => void;
|
|
38
|
+
/** Success banner shown after a grade override is saved. */
|
|
39
|
+
showSuccess: boolean;
|
|
40
|
+
setShowSuccess: (value: boolean) => void;
|
|
41
|
+
/** Toast shown after a successful bulk grade CSV import. */
|
|
42
|
+
showImportSuccessToast: boolean;
|
|
43
|
+
setShowImportSuccessToast: (value: boolean) => void;
|
|
44
|
+
/** Active top-level tab: views.grades | views.bulkManagementHistory. */
|
|
45
|
+
activeView: string;
|
|
46
|
+
setActiveView: (value: string) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Filter sidebar open/close state, with the same two-phase transition the old
|
|
49
|
+
* Redux `app.filterMenu` slice modeled (`open` + `transitioning`). Consumers
|
|
50
|
+
* derive `isClosed`/`isOpening` from these two.
|
|
51
|
+
*/
|
|
52
|
+
filterMenuOpen: boolean;
|
|
53
|
+
filterMenuTransitioning: boolean;
|
|
54
|
+
/** Toggle the sidebar (starts the transition, flips `open` on the next frame). */
|
|
55
|
+
toggleFilterMenu: () => void;
|
|
56
|
+
/** Close the sidebar if it is currently open (no-op otherwise). */
|
|
57
|
+
closeFilterMenu: () => void;
|
|
58
|
+
/** onTransitionEnd handler for the sidebar; ends the transition phase. */
|
|
59
|
+
handleFilterMenuTransitionEnd: (event: React.TransitionEvent) => void;
|
|
60
|
+
/** Edit-grade modal state (was Redux `app.modalState`). */
|
|
61
|
+
modalState: ModalState;
|
|
62
|
+
/** Merge a partial update into modalState (filtered to the known modal fields). */
|
|
63
|
+
setModalState: (partial: Partial<ModalState>) => void;
|
|
64
|
+
/** Open the modal seeded from a grade-table cell (subsection + user entry). */
|
|
65
|
+
setModalStateFromTable: (payload: ModalStateFromTablePayload) => void;
|
|
66
|
+
/** Reset the modal to its initial (closed) state. */
|
|
67
|
+
closeModal: () => void;
|
|
68
|
+
/**
|
|
69
|
+
* Current grades pagination cursor: the opaque prev/next URL from the last
|
|
70
|
+
* grades response, or null for the first (unpaged) page. Held here so the
|
|
71
|
+
* `useGrades` query can key/refetch off it; filter changes reset it to null.
|
|
72
|
+
*/
|
|
73
|
+
gradesPageEndpoint: string | null;
|
|
74
|
+
setGradesPageEndpoint: (endpoint: string | null) => void;
|
|
75
|
+
/**
|
|
76
|
+
* Bulk grade CSV-upload result feedback shown by `BulkManagementAlerts` (was the
|
|
77
|
+
* Redux `grades.bulkManagement` `uploadSuccess`/`errorMessages`).
|
|
78
|
+
*/
|
|
79
|
+
csvUploadSuccess: boolean;
|
|
80
|
+
csvUploadErrorMessages: string[];
|
|
81
|
+
/** Reset the CSV-upload feedback (upload started). */
|
|
82
|
+
resetCsvUpload: () => void;
|
|
83
|
+
/** Mark the CSV upload succeeded. */
|
|
84
|
+
markCsvUploadSuccess: () => void;
|
|
85
|
+
/** Record CSV-upload error messages. */
|
|
86
|
+
setCsvUploadErrors: (messages: string[]) => void;
|
|
87
|
+
}
|
|
88
|
+
declare const GradebookUiContext: React.Context<GradebookUiContextValue | undefined>;
|
|
89
|
+
interface GradebookUiProviderProps {
|
|
90
|
+
children: React.ReactNode;
|
|
91
|
+
}
|
|
92
|
+
export declare const GradebookUiProvider: ({ children }: GradebookUiProviderProps) => React.JSX.Element;
|
|
93
|
+
/**
|
|
94
|
+
* useGradebookUi()
|
|
95
|
+
* Accessor for the gradebook UI-state context. Throws if used outside a
|
|
96
|
+
* <GradebookUiProvider>.
|
|
97
|
+
*/
|
|
98
|
+
export declare const useGradebookUi: () => GradebookUiContextValue;
|
|
99
|
+
export default GradebookUiContext;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
|
+
import { views, modalFieldKeys } from './constants/app';
|
|
4
|
+
import { formatDateForDisplay } from './formatUtils';
|
|
5
|
+
// Mirrors the Redux `app` reducer's `initialState.modalState`.
|
|
6
|
+
const initialModalState = {
|
|
7
|
+
open: false,
|
|
8
|
+
adjustedGradePossible: '',
|
|
9
|
+
adjustedGradeValue: 0,
|
|
10
|
+
assignmentName: '',
|
|
11
|
+
reasonForChange: '',
|
|
12
|
+
todaysDate: '',
|
|
13
|
+
updateModuleId: null,
|
|
14
|
+
updateUserId: null,
|
|
15
|
+
updateUserName: null,
|
|
16
|
+
};
|
|
17
|
+
const GradebookUiContext = createContext(undefined);
|
|
18
|
+
export const GradebookUiProvider = ({ children }) => {
|
|
19
|
+
const [gradeFormat, setGradeFormat] = useState('percent');
|
|
20
|
+
const [showSuccess, setShowSuccess] = useState(false);
|
|
21
|
+
const [showImportSuccessToast, setShowImportSuccessToast] = useState(false);
|
|
22
|
+
const [activeView, setActiveView] = useState(views.grades);
|
|
23
|
+
// Filter sidebar animation state. This mirrors the old Redux `filterMenu` thunks:
|
|
24
|
+
// `toggle` flips `open` one frame after starting the transition, and the sidebar's
|
|
25
|
+
// onTransitionEnd ends the transition. `close` reads the latest `open` via a ref
|
|
26
|
+
// so it can be a stable callback.
|
|
27
|
+
const [filterMenuOpen, setFilterMenuOpen] = useState(false);
|
|
28
|
+
const [filterMenuTransitioning, setFilterMenuTransitioning] = useState(false);
|
|
29
|
+
const filterMenuOpenRef = useRef(filterMenuOpen);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
filterMenuOpenRef.current = filterMenuOpen;
|
|
32
|
+
}, [filterMenuOpen]);
|
|
33
|
+
const toggleFilterMenu = useCallback(() => {
|
|
34
|
+
setFilterMenuTransitioning(true);
|
|
35
|
+
window.requestAnimationFrame(() => {
|
|
36
|
+
window.setTimeout(() => {
|
|
37
|
+
setFilterMenuOpen((open) => !open);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}, []);
|
|
41
|
+
const closeFilterMenu = useCallback(() => {
|
|
42
|
+
if (filterMenuOpenRef.current) {
|
|
43
|
+
toggleFilterMenu();
|
|
44
|
+
}
|
|
45
|
+
}, [toggleFilterMenu]);
|
|
46
|
+
const handleFilterMenuTransitionEnd = useCallback((event) => {
|
|
47
|
+
if (event.currentTarget === event.target) {
|
|
48
|
+
setFilterMenuTransitioning(false);
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
// Edit-grade modal state. These ops are a faithful port of the Redux `app`
|
|
52
|
+
// reducer cases: `setModalState` merges a field-filtered partial, `closeModal`
|
|
53
|
+
// resets to the initial state, and `setModalStateFromTable` opens the modal
|
|
54
|
+
// seeded from the clicked grade cell.
|
|
55
|
+
const [modalState, setModalStateValue] = useState(initialModalState);
|
|
56
|
+
const setModalState = useCallback((partial) => {
|
|
57
|
+
const filtered = Object.keys(modalFieldKeys).reduce((obj, key) => (partial[key] !== undefined ? Object.assign(Object.assign({}, obj), { [key]: partial[key] }) : obj), {});
|
|
58
|
+
setModalStateValue((prev) => (Object.assign(Object.assign({}, prev), filtered)));
|
|
59
|
+
}, []);
|
|
60
|
+
const setModalStateFromTable = useCallback(({ subsection, userEntry }) => {
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
setModalStateValue({
|
|
63
|
+
open: true,
|
|
64
|
+
adjustedGradeValue: '',
|
|
65
|
+
reasonForChange: '',
|
|
66
|
+
todaysDate: formatDateForDisplay(new Date()),
|
|
67
|
+
adjustedGradePossible: subsection.attempted ? ((_a = subsection.score_possible) !== null && _a !== void 0 ? _a : '') : '',
|
|
68
|
+
assignmentName: `${subsection.subsection_name}`,
|
|
69
|
+
updateModuleId: (_b = subsection.module_id) !== null && _b !== void 0 ? _b : null,
|
|
70
|
+
updateUserId: (_c = userEntry.user_id) !== null && _c !== void 0 ? _c : null,
|
|
71
|
+
updateUserName: (_d = userEntry.username) !== null && _d !== void 0 ? _d : null,
|
|
72
|
+
});
|
|
73
|
+
}, []);
|
|
74
|
+
const closeModal = useCallback(() => {
|
|
75
|
+
setModalStateValue(initialModalState);
|
|
76
|
+
}, []);
|
|
77
|
+
// Grades pagination cursor (opaque prev/next URL, or null for the first page).
|
|
78
|
+
const [gradesPageEndpoint, setGradesPageEndpoint] = useState(null);
|
|
79
|
+
// Bulk CSV-upload result feedback (was Redux `grades.bulkManagement`).
|
|
80
|
+
const [csvUploadSuccess, setCsvUploadSuccess] = useState(false);
|
|
81
|
+
const [csvUploadErrorMessages, setCsvUploadErrorMessages] = useState([]);
|
|
82
|
+
const resetCsvUpload = useCallback(() => {
|
|
83
|
+
setCsvUploadSuccess(false);
|
|
84
|
+
setCsvUploadErrorMessages([]);
|
|
85
|
+
}, []);
|
|
86
|
+
const markCsvUploadSuccess = useCallback(() => {
|
|
87
|
+
setCsvUploadSuccess(true);
|
|
88
|
+
setCsvUploadErrorMessages([]);
|
|
89
|
+
}, []);
|
|
90
|
+
const setCsvUploadErrors = useCallback((messages) => {
|
|
91
|
+
setCsvUploadSuccess(false);
|
|
92
|
+
setCsvUploadErrorMessages(messages);
|
|
93
|
+
}, []);
|
|
94
|
+
const value = useMemo(() => ({
|
|
95
|
+
gradeFormat,
|
|
96
|
+
setGradeFormat,
|
|
97
|
+
showSuccess,
|
|
98
|
+
setShowSuccess,
|
|
99
|
+
showImportSuccessToast,
|
|
100
|
+
setShowImportSuccessToast,
|
|
101
|
+
activeView,
|
|
102
|
+
setActiveView,
|
|
103
|
+
filterMenuOpen,
|
|
104
|
+
filterMenuTransitioning,
|
|
105
|
+
toggleFilterMenu,
|
|
106
|
+
closeFilterMenu,
|
|
107
|
+
handleFilterMenuTransitionEnd,
|
|
108
|
+
modalState,
|
|
109
|
+
setModalState,
|
|
110
|
+
setModalStateFromTable,
|
|
111
|
+
closeModal,
|
|
112
|
+
gradesPageEndpoint,
|
|
113
|
+
setGradesPageEndpoint,
|
|
114
|
+
csvUploadSuccess,
|
|
115
|
+
csvUploadErrorMessages,
|
|
116
|
+
resetCsvUpload,
|
|
117
|
+
markCsvUploadSuccess,
|
|
118
|
+
setCsvUploadErrors,
|
|
119
|
+
}), [
|
|
120
|
+
gradeFormat, showSuccess, showImportSuccessToast, activeView,
|
|
121
|
+
filterMenuOpen, filterMenuTransitioning,
|
|
122
|
+
toggleFilterMenu, closeFilterMenu, handleFilterMenuTransitionEnd,
|
|
123
|
+
modalState, setModalState, setModalStateFromTable, closeModal,
|
|
124
|
+
gradesPageEndpoint,
|
|
125
|
+
csvUploadSuccess, csvUploadErrorMessages,
|
|
126
|
+
resetCsvUpload, markCsvUploadSuccess, setCsvUploadErrors,
|
|
127
|
+
]);
|
|
128
|
+
return (_jsx(GradebookUiContext.Provider, { value: value, children: children }));
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* useGradebookUi()
|
|
132
|
+
* Accessor for the gradebook UI-state context. Throws if used outside a
|
|
133
|
+
* <GradebookUiProvider>.
|
|
134
|
+
*/
|
|
135
|
+
export const useGradebookUi = () => {
|
|
136
|
+
const context = useContext(GradebookUiContext);
|
|
137
|
+
if (context === undefined) {
|
|
138
|
+
throw new Error('useGradebookUi must be used within a GradebookUiProvider');
|
|
139
|
+
}
|
|
140
|
+
return context;
|
|
141
|
+
};
|
|
142
|
+
export default GradebookUiContext;
|
|
143
|
+
//# sourceMappingURL=gradebookUiContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradebookUiContext.js","sourceRoot":"","sources":["../../src/data/gradebookUiContext.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n createContext, useCallback, useContext, useEffect, useMemo, useRef, useState,\n} from 'react';\n\nimport { views, modalFieldKeys } from '@src/data/constants/app';\nimport { formatDateForDisplay } from '@src/data/formatUtils';\n\n/** Edit-grade modal state (was the Redux `app.modalState` slice). */\nexport interface ModalState {\n open: boolean;\n adjustedGradePossible: string | number;\n adjustedGradeValue: string | number;\n assignmentName: string;\n reasonForChange: string;\n todaysDate: string;\n updateModuleId: string | null;\n updateUserId: number | null;\n updateUserName: string | null;\n}\n\n/** Payload for opening the modal from a grade-table cell. */\nexport interface ModalStateFromTablePayload {\n subsection: {\n attempted?: boolean;\n score_possible?: number;\n subsection_name?: string;\n module_id?: string;\n };\n userEntry: {\n user_id?: number;\n username?: string;\n };\n}\n\n// Mirrors the Redux `app` reducer's `initialState.modalState`.\nconst initialModalState: ModalState = {\n open: false,\n adjustedGradePossible: '',\n adjustedGradeValue: 0,\n assignmentName: '',\n reasonForChange: '',\n todaysDate: '',\n updateModuleId: null,\n updateUserId: null,\n updateUserName: null,\n};\n\n/**\n * Client-side gradebook **UI** state, held in React (Context + useState).\n *\n * Replaces the non-filter UI bits of the old Redux `app` and `grades` slices:\n * grade format toggle, success banner, import toast, active view, filter-menu\n * open/transition, modal state, pagination cursor, and CSV-upload feedback.\n */\nexport interface GradebookUiContextValue {\n /** Grade display format: 'percent' | 'absolute'. */\n gradeFormat: string;\n setGradeFormat: (value: string) => void;\n /** Success banner shown after a grade override is saved. */\n showSuccess: boolean;\n setShowSuccess: (value: boolean) => void;\n /** Toast shown after a successful bulk grade CSV import. */\n showImportSuccessToast: boolean;\n setShowImportSuccessToast: (value: boolean) => void;\n /** Active top-level tab: views.grades | views.bulkManagementHistory. */\n activeView: string;\n setActiveView: (value: string) => void;\n /**\n * Filter sidebar open/close state, with the same two-phase transition the old\n * Redux `app.filterMenu` slice modeled (`open` + `transitioning`). Consumers\n * derive `isClosed`/`isOpening` from these two.\n */\n filterMenuOpen: boolean;\n filterMenuTransitioning: boolean;\n /** Toggle the sidebar (starts the transition, flips `open` on the next frame). */\n toggleFilterMenu: () => void;\n /** Close the sidebar if it is currently open (no-op otherwise). */\n closeFilterMenu: () => void;\n /** onTransitionEnd handler for the sidebar; ends the transition phase. */\n handleFilterMenuTransitionEnd: (event: React.TransitionEvent) => void;\n /** Edit-grade modal state (was Redux `app.modalState`). */\n modalState: ModalState;\n /** Merge a partial update into modalState (filtered to the known modal fields). */\n setModalState: (partial: Partial<ModalState>) => void;\n /** Open the modal seeded from a grade-table cell (subsection + user entry). */\n setModalStateFromTable: (payload: ModalStateFromTablePayload) => void;\n /** Reset the modal to its initial (closed) state. */\n closeModal: () => void;\n /**\n * Current grades pagination cursor: the opaque prev/next URL from the last\n * grades response, or null for the first (unpaged) page. Held here so the\n * `useGrades` query can key/refetch off it; filter changes reset it to null.\n */\n gradesPageEndpoint: string | null;\n setGradesPageEndpoint: (endpoint: string | null) => void;\n /**\n * Bulk grade CSV-upload result feedback shown by `BulkManagementAlerts` (was the\n * Redux `grades.bulkManagement` `uploadSuccess`/`errorMessages`).\n */\n csvUploadSuccess: boolean;\n csvUploadErrorMessages: string[];\n /** Reset the CSV-upload feedback (upload started). */\n resetCsvUpload: () => void;\n /** Mark the CSV upload succeeded. */\n markCsvUploadSuccess: () => void;\n /** Record CSV-upload error messages. */\n setCsvUploadErrors: (messages: string[]) => void;\n}\n\nconst GradebookUiContext = createContext<GradebookUiContextValue | undefined>(undefined);\n\ninterface GradebookUiProviderProps {\n children: React.ReactNode;\n}\n\nexport const GradebookUiProvider = ({ children }: GradebookUiProviderProps) => {\n const [gradeFormat, setGradeFormat] = useState<string>('percent');\n const [showSuccess, setShowSuccess] = useState<boolean>(false);\n const [showImportSuccessToast, setShowImportSuccessToast] = useState<boolean>(false);\n const [activeView, setActiveView] = useState<string>(views.grades);\n\n // Filter sidebar animation state. This mirrors the old Redux `filterMenu` thunks:\n // `toggle` flips `open` one frame after starting the transition, and the sidebar's\n // onTransitionEnd ends the transition. `close` reads the latest `open` via a ref\n // so it can be a stable callback.\n const [filterMenuOpen, setFilterMenuOpen] = useState<boolean>(false);\n const [filterMenuTransitioning, setFilterMenuTransitioning] = useState<boolean>(false);\n const filterMenuOpenRef = useRef<boolean>(filterMenuOpen);\n useEffect(() => {\n filterMenuOpenRef.current = filterMenuOpen;\n }, [filterMenuOpen]);\n\n const toggleFilterMenu = useCallback(() => {\n setFilterMenuTransitioning(true);\n window.requestAnimationFrame(() => {\n window.setTimeout(() => {\n setFilterMenuOpen((open) => !open);\n });\n });\n }, []);\n\n const closeFilterMenu = useCallback(() => {\n if (filterMenuOpenRef.current) {\n toggleFilterMenu();\n }\n }, [toggleFilterMenu]);\n\n const handleFilterMenuTransitionEnd = useCallback((event: React.TransitionEvent) => {\n if (event.currentTarget === event.target) {\n setFilterMenuTransitioning(false);\n }\n }, []);\n\n // Edit-grade modal state. These ops are a faithful port of the Redux `app`\n // reducer cases: `setModalState` merges a field-filtered partial, `closeModal`\n // resets to the initial state, and `setModalStateFromTable` opens the modal\n // seeded from the clicked grade cell.\n const [modalState, setModalStateValue] = useState<ModalState>(initialModalState);\n\n const setModalState = useCallback((partial: Partial<ModalState>) => {\n const filtered = (Object.keys(modalFieldKeys) as (keyof ModalState)[]).reduce(\n (obj, key) => (partial[key] !== undefined ? { ...obj, [key]: partial[key] } : obj),\n {} as Partial<ModalState>,\n );\n setModalStateValue((prev) => ({ ...prev, ...filtered }));\n }, []);\n\n const setModalStateFromTable = useCallback(\n ({ subsection, userEntry }: ModalStateFromTablePayload) => {\n setModalStateValue({\n open: true,\n adjustedGradeValue: '',\n reasonForChange: '',\n todaysDate: formatDateForDisplay(new Date()),\n adjustedGradePossible: subsection.attempted ? (subsection.score_possible ?? '') : '',\n assignmentName: `${subsection.subsection_name}`,\n updateModuleId: subsection.module_id ?? null,\n updateUserId: userEntry.user_id ?? null,\n updateUserName: userEntry.username ?? null,\n });\n },\n [],\n );\n\n const closeModal = useCallback(() => {\n setModalStateValue(initialModalState);\n }, []);\n\n // Grades pagination cursor (opaque prev/next URL, or null for the first page).\n const [gradesPageEndpoint, setGradesPageEndpoint] = useState<string | null>(null);\n\n // Bulk CSV-upload result feedback (was Redux `grades.bulkManagement`).\n const [csvUploadSuccess, setCsvUploadSuccess] = useState<boolean>(false);\n const [csvUploadErrorMessages, setCsvUploadErrorMessages] = useState<string[]>([]);\n const resetCsvUpload = useCallback(() => {\n setCsvUploadSuccess(false);\n setCsvUploadErrorMessages([]);\n }, []);\n const markCsvUploadSuccess = useCallback(() => {\n setCsvUploadSuccess(true);\n setCsvUploadErrorMessages([]);\n }, []);\n const setCsvUploadErrors = useCallback((messages: string[]) => {\n setCsvUploadSuccess(false);\n setCsvUploadErrorMessages(messages);\n }, []);\n\n const value = useMemo<GradebookUiContextValue>(\n () => ({\n gradeFormat,\n setGradeFormat,\n showSuccess,\n setShowSuccess,\n showImportSuccessToast,\n setShowImportSuccessToast,\n activeView,\n setActiveView,\n filterMenuOpen,\n filterMenuTransitioning,\n toggleFilterMenu,\n closeFilterMenu,\n handleFilterMenuTransitionEnd,\n modalState,\n setModalState,\n setModalStateFromTable,\n closeModal,\n gradesPageEndpoint,\n setGradesPageEndpoint,\n csvUploadSuccess,\n csvUploadErrorMessages,\n resetCsvUpload,\n markCsvUploadSuccess,\n setCsvUploadErrors,\n }),\n [\n gradeFormat, showSuccess, showImportSuccessToast, activeView,\n filterMenuOpen, filterMenuTransitioning,\n toggleFilterMenu, closeFilterMenu, handleFilterMenuTransitionEnd,\n modalState, setModalState, setModalStateFromTable, closeModal,\n gradesPageEndpoint,\n csvUploadSuccess, csvUploadErrorMessages,\n resetCsvUpload, markCsvUploadSuccess, setCsvUploadErrors,\n ],\n );\n\n return (\n <GradebookUiContext.Provider value={value}>\n {children}\n </GradebookUiContext.Provider>\n );\n};\n\n/**\n * useGradebookUi()\n * Accessor for the gradebook UI-state context. Throws if used outside a\n * <GradebookUiProvider>.\n */\nexport const useGradebookUi = (): GradebookUiContextValue => {\n const context = useContext(GradebookUiContext);\n if (context === undefined) {\n throw new Error('useGradebookUi must be used within a GradebookUiProvider');\n }\n return context;\n};\n\nexport default GradebookUiContext;\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
/**
|
|
3
|
+
* Application-wide React Query client.
|
|
4
|
+
*
|
|
5
|
+
* Defaults are promoted here (rather than repeated per hook) to keep individual
|
|
6
|
+
* query hooks lean: cache server data for 5 minutes and skip retries on 4xx.
|
|
7
|
+
*/
|
|
8
|
+
export declare const makeQueryClient: () => QueryClient;
|
|
9
|
+
declare const queryClient: QueryClient;
|
|
10
|
+
export default queryClient;
|