diff --git a/src/data/redux/hooks/actions.js b/src/data/redux/hooks/actions.js index b1b5b4e..526971d 100644 --- a/src/data/redux/hooks/actions.js +++ b/src/data/redux/hooks/actions.js @@ -4,7 +4,11 @@ import { actionHook } from './utils'; const app = StrictDict({ useSetLocalFilter: actionHook(actions.app.setLocalFilter), + useSetSearchValue: actionHook(actions.app.setSearchValue), + useSetShowImportSuccessToast: actionHook(actions.app.setShowImportSuccessToast), useSetView: actionHook(actions.app.setView), + useCloseModal: actionHook(actions.app.closeModal), + useSetModalState: actionHook(actions.app.setModalState), }); const filters = StrictDict({ @@ -15,12 +19,15 @@ const filters = StrictDict({ useUpdateCourseGradeLimits: actionHook(actions.filters.update.courseGradeLimits), useUpdateIncludeCourseRoleMembers: actionHook(actions.filters.update.includeCourseRoleMembers), useUpdateTrack: actionHook(actions.filters.update.track), + useResetFilters: actionHook(actions.filters.reset), }); const grades = StrictDict({ - downloadReport: { - useBulkGrades: actionHook(actions.grades.downloadReport.bulkGrades), - }, + useDoneViewingAssignment: actionHook(actions.grades.doneViewingAssignment), + useDownloadBulkGradesReport: actionHook(actions.grades.downloadReport.bulkGrades), + useDownloadInterventionReport: actionHook(actions.grades.downloadReport.intervention), + useToggleGradeFormat: actionHook(actions.grades.toggleGradeFormat), + useCloseBanner: actionHook(actions.grades.banner.close), }); export default StrictDict({ diff --git a/src/data/redux/hooks/actions.test.js b/src/data/redux/hooks/actions.test.js index 5e66d03..9f7de29 100644 --- a/src/data/redux/hooks/actions.test.js +++ b/src/data/redux/hooks/actions.test.js @@ -4,23 +4,6 @@ import actions from 'data/actions'; import { actionHook } from './utils'; import actionHooks from './actions'; -jest.mock('data/actions', () => ({ - app: { - setLocalFilter: jest.fn(), - setView: jest.fn(), - }, - filters: { - update: { - assignment: jest.fn(), - assignmentLimits: jest.fn(), - }, - }, - grades: { - downloadReport: { - bulkGrades: jest.fn(), - }, - }, -})); jest.mock('./utils', () => ({ actionHook: (action) => ({ actionHook: action }), })); @@ -30,6 +13,7 @@ let hooks; const testActionHook = (hookKey, action) => { test(hookKey, () => { expect(hooks[hookKey]).toEqual(actionHook(action)); + expect(hooks[hookKey]).not.toEqual(undefined); }); }; @@ -38,7 +22,11 @@ describe('action hooks', () => { const hookKeys = keyStore(actionHooks.app); beforeEach(() => { hooks = actionHooks.app; }); testActionHook(hookKeys.useSetLocalFilter, actions.app.setLocalFilter); + testActionHook(hookKeys.useSetSearchValue, actions.app.setSearchValue); + testActionHook(hookKeys.useSetShowImportSuccessToast, actions.app.setShowImportSuccessToast); testActionHook(hookKeys.useSetView, actions.app.setView); + testActionHook(hookKeys.useCloseModal, actions.app.closeModal); + testActionHook(hookKeys.useSetModalState, actions.app.setModalState); }); describe('filters', () => { const hookKeys = keyStore(actionHooks.filters); @@ -46,19 +34,23 @@ describe('action hooks', () => { beforeEach(() => { hooks = actionHooks.filters; }); testActionHook(hookKeys.useUpdateAssignment, actionGroup.assignment); testActionHook(hookKeys.useUpdateAssignmentLimits, actionGroup.assignmentLimits); - testActionHook(hookKeys.useUpdateCohort, actionGroup.updateCohort); + testActionHook(hookKeys.useUpdateAssignmentType, actionGroup.assignmentType); + testActionHook(hookKeys.useUpdateCohort, actionGroup.cohort); testActionHook(hookKeys.useUpdateCourseGradeLimits, actionGroup.courseGradeLimits); testActionHook( hookKeys.useUpdateIncludeCourseRoleMembers, - actionGroup.updateIncludeCourseRoleMembers, + actionGroup.includeCourseRoleMembers, ); - testActionHook(hookKeys.useUpdateTrack, actionGroup.updateTrack); + testActionHook(hookKeys.useResetFilters, actions.filters.reset); }); describe('grades', () => { + const hookKeys = keyStore(actionHooks.grades); + const actionGroup = actions.grades; beforeEach(() => { hooks = actionHooks.grades; }); - test('downloadReport.useBulkGrades', () => { - expect(hooks.downloadReport.useBulkGrades) - .toEqual(actionHook(actions.grades.downloadReport.bulkGrades)); - }); + testActionHook(hookKeys.useDoneViewingAssignment, actionGroup.doneViewingAssignment); + testActionHook(hookKeys.useDownloadBulkGradesReport, actionGroup.downloadReport.bulkGrades); + testActionHook(hookKeys.useDownloadInterventionReport, actionGroup.downloadReport.intervention); + testActionHook(hookKeys.useToggleGradeFormat, actionGroup.toggleGradeFormat); + testActionHook(hookKeys.useCloseBanner, actionGroup.banner.close); }); }); diff --git a/src/data/redux/hooks/selectors.js b/src/data/redux/hooks/selectors.js index ddbd379..6f27ab0 100644 --- a/src/data/redux/hooks/selectors.js +++ b/src/data/redux/hooks/selectors.js @@ -3,48 +3,75 @@ import { useSelector } from 'react-redux'; import { StrictDict } from 'utils'; import selectors from 'data/selectors'; +const selectorHook = (selector) => () => useSelector(selector); + export const root = StrictDict({ - useGradeExportUrl: () => useSelector(selectors.root.gradeExportUrl), - useSelectedCohortEntry: () => useSelector(selectors.root.selectedCohortEntry), - useSelectedTrackEntry: () => useSelector(selectors.root.selectedTrackEntry), - useShowBulkManagement: () => useSelector(selectors.root.showBulkManagement), + useEditModalPossibleGrade: selectorHook(selectors.root.editModalPossibleGrade), + useGetHeadings: selectorHook(selectors.root.getHeadings), + useGradeExportUrl: selectorHook(selectors.root.gradeExportUrl), + useInterventionExportUrl: selectorHook(selectors.root.interventionExportUrl), + useSelectedCohortEntry: selectorHook(selectors.root.selectedCohortEntry), + useSelectedTrackEntry: selectorHook(selectors.root.selectedTrackEntry), + useShouldShowSpinner: selectorHook(selectors.root.shouldShowSpinner), + useShowBulkManagement: selectorHook(selectors.root.showBulkManagement), + useFilterBadgeConfig: (filterName) => useSelector( + (state) => selectors.root.filterBadgeConfig(state, filterName), + ), }); export const app = StrictDict({ - useActiveView: () => useSelector(selectors.app.activeView), - useAssignmentGradeLimits: () => useSelector(selectors.app.assignmentGradeLimits), - useAreCourseGradeFiltersValid: () => useSelector(selectors.app.areCourseGradeFiltersValid), - useCourseGradeLimits: () => useSelector(selectors.app.courseGradeLimits), - useCourseId: () => useSelector(selectors.app.courseId), + useActiveView: selectorHook(selectors.app.activeView), + useAssignmentGradeLimits: selectorHook(selectors.app.assignmentGradeLimits), + useAreCourseGradeFiltersValid: selectorHook(selectors.app.areCourseGradeFiltersValid), + useCourseGradeLimits: selectorHook(selectors.app.courseGradeLimits), + useCourseGradeFilterValidity: selectorHook(selectors.app.courseGradeFilterValidity), + useCourseId: selectorHook(selectors.app.courseId), + useModalData: selectorHook(selectors.app.modalData), + useSearchValue: selectorHook(selectors.app.searchValue), + useShowImportSuccessToast: selectorHook(selectors.app.showImportSuccessToast), }); export const assignmentTypes = StrictDict({ - useAllAssignmentTypes: () => useSelector(selectors.assignmentTypes.allAssignmentTypes), - useAreGradesFrozen: () => useSelector(selectors.assignmentTypes.areGradesFrozen), + useAllAssignmentTypes: selectorHook(selectors.assignmentTypes.allAssignmentTypes), + useAreGradesFrozen: selectorHook(selectors.assignmentTypes.areGradesFrozen), }); export const cohorts = StrictDict({ - useAllCohorts: () => useSelector(selectors.cohorts.allCohorts), + useAllCohorts: selectorHook(selectors.cohorts.allCohorts), // maybe not needed? - useCohortsByName: () => useSelector(selectors.cohorts.cohortsByName), + useCohortsByName: selectorHook(selectors.cohorts.cohortsByName), }); export const filters = StrictDict({ - useData: () => useSelector(selectors.filters.allFilters), - useIncludeCourseRoleMembers: () => useSelector(selectors.filters.includeCourseRoleMembers), - useSelectableAssignmentLabels: () => useSelector(selectors.filters.selectableAssignmentLabels), - useSelectedAssignmentLabel: () => useSelector(selectors.filters.selectedAssignmentLabel), - useAssignmentType: () => useSelector(selectors.filters.assignmentType), + useData: selectorHook(selectors.filters.allFilters), + useIncludeCourseRoleMembers: selectorHook(selectors.filters.includeCourseRoleMembers), + useSelectableAssignmentLabels: selectorHook(selectors.filters.selectableAssignmentLabels), + useSelectedAssignmentLabel: selectorHook(selectors.filters.selectedAssignmentLabel), + useAssignmentType: selectorHook(selectors.filters.assignmentType), +}); + +export const grades = StrictDict({ + useAllGrades: selectorHook(selectors.grades.allGrades), + useUserCounts: () => ({ + filteredUsersCount: useSelector(selectors.grades.filteredUsersCount), + totalUsersCount: useSelector(selectors.grades.totalUsersCount), + }), + useGradeData: selectorHook(selectors.grades.gradeData), + useHasOverrideErrors: selectorHook(selectors.grades.hasOverrideErrors), + useShowSuccess: selectorHook(selectors.grades.showSuccess), + useSubsectionGrade: ({ gradeFormat, subsection }) => () => ( + selectors.grades.subsectionGrade[gradeFormat](subsection) + ), }); export const roles = StrictDict({ - useCanUserViewGradebook: () => useSelector(selectors.roles.canUserViewGradebook), + useCanUserViewGradebook: selectorHook(selectors.roles.canUserViewGradebook), }); export const tracks = StrictDict({ - useAllTracks: () => useSelector(selectors.tracks.allTracks), + useAllTracks: selectorHook(selectors.tracks.allTracks), // maybe not needed? - useTracksByName: () => useSelector(selectors.tracks.tracksByName), + useTracksByName: selectorHook(selectors.tracks.tracksByName), }); export default StrictDict({ @@ -52,6 +79,7 @@ export default StrictDict({ assignmentTypes, cohorts, filters, + grades, roles, tracks, root, diff --git a/src/data/redux/hooks/selectors.test.js b/src/data/redux/hooks/selectors.test.js index c83443b..ad74e30 100644 --- a/src/data/redux/hooks/selectors.test.js +++ b/src/data/redux/hooks/selectors.test.js @@ -7,104 +7,102 @@ jest.mock('react-redux', () => ({ useSelector: (selector) => ({ useSelector: selector }), })); -jest.mock('data/selectors', () => ({ - app: { - activeView: jest.fn(), - assignmentGradeLimits: jest.fn(), - areCourseGradeFiltersValid: jest.fn(), - courseGradelimits: jest.fn(), - courseId: jest.fn(), - }, - assignmentTypes: { - allAssignmentTypes: jest.fn(), - areGradesFrozen: jest.fn(), - }, - cohorts: { - allCohorts: jest.fn(), - cohortsByName: jest.fn(), - }, - filters: { - allFilters: jest.fn(), - includeCourseRoleMembers: jest.fn(), - selectableAssignmentLabels: jest.fn(), - selectedAssignmentLabel: jest.fn(), - assignmentType: jest.fn(), - }, - roles: { - canUserViewGradebook: jest.fn(), - }, - tracks: { - allTracks: jest.fn(), - tracksByName: jest.fn(), - }, - root: { - gradeExportUrl: jest.fn(), - selectedCohortEntry: jest.fn(), - selectedTrackEntry: jest.fn(), - showBulkManagement: jest.fn(), - }, -})); +const testValue = 'test-value'; +const testState = { test: 'state value' }; +let hookKeys; let hooks; -const testHook = (hookKey, selector) => { - test(hookKey, () => { - expect(hooks[hookKey]()).toEqual(useSelector(selector)); +let selKeys; +let selectorGroup; + +const loadSelectorGroup = (hookGroup, selGroup) => { + hookKeys = keyStore(hookGroup); + selKeys = keyStore(selGroup); + beforeEach(() => { + hooks = hookGroup; + selectorGroup = selGroup; }); }; + +const testHook = (hookKey, selectorKey) => { + test(hookKey, () => { + expect(hooks[hookKey]()).toEqual(useSelector(selectorGroup[selectorKey])); + }); +}; + describe('selector hooks', () => { describe('root selectors', () => { - const hookKeys = keyStore(selectorHooks.root); - beforeEach(() => { hooks = selectorHooks.root; }); - testHook(hookKeys.useGradeExportUrl, selectors.root.gradeExportUrl); - testHook(hookKeys.useSelectedCohortEntry, selectors.root.selectedCohortEntry); - testHook(hookKeys.useSelectedTrackEntry, selectors.root.selectedTrackEntry); - testHook(hookKeys.useShowBulkManagement, selectors.root.showBulkManagement); + loadSelectorGroup(selectorHooks.root, selectors.root); + testHook(hookKeys.useEditModalPossibleGrade, selKeys.editModalPossibleGrade); + testHook(hookKeys.useGetHeadings, selKeys.getHeadings); + testHook(hookKeys.useGradeExportUrl, selKeys.gradeExportUrl); + testHook(hookKeys.useInterventionExportUrl, selKeys.interventionExportUrl); + testHook(hookKeys.useSelectedCohortEntry, selKeys.selectedCohortEntry); + testHook(hookKeys.useSelectedTrackEntry, selKeys.selectedTrackEntry); + testHook(hookKeys.useShouldShowSpinner, selKeys.shouldShowSpinner); + testHook(hookKeys.useShowBulkManagement, selKeys.showBulkManagement); + describe(hookKeys.useFilterBadgeConfig, () => { + test('calls filterBadgeConfig selector with passed filterName', () => { + const filterBadgeConfig = (state, filterName) => ({ + filterBadgeConfig: { state, filterName }, + }); + const rootKeys = keyStore(selectors.root); + jest.spyOn(selectors.root, rootKeys.filterBadgeConfig) + .mockImplementation(filterBadgeConfig); + const out = hooks.useFilterBadgeConfig(testValue); + expect(out.useSelector(testState)).toEqual(filterBadgeConfig(testState, testValue)); + }); + }); }); describe('app', () => { - const hookKeys = keyStore(selectorHooks.app); - const selGroup = selectors.app; - beforeEach(() => { hooks = selectorHooks.app; }); - testHook(hookKeys.useActiveView, selGroup.activeView); - testHook(hookKeys.useAssignmentGradeLimits, selGroup.assignmentGradeLimits); - testHook(hookKeys.useAreCourseGradeFiltersValid, selGroup.areCourseGradeFiltersValid); - testHook(hookKeys.useCourseGradeLimits, selGroup.courseGradeLimits); - testHook(hookKeys.useCourseId, selGroup.courseId); + loadSelectorGroup(selectorHooks.app, selectors.app); + testHook(hookKeys.useActiveView, selKeys.activeView); + testHook(hookKeys.useAssignmentGradeLimits, selKeys.assignmentGradeLimits); + testHook(hookKeys.useAreCourseGradeFiltersValid, selKeys.areCourseGradeFiltersValid); + testHook(hookKeys.useCourseGradeLimits, selKeys.courseGradeLimits); + testHook(hookKeys.useCourseId, selKeys.courseId); + testHook(hookKeys.useModalData, selKeys.modalData); + testHook(hookKeys.useSearchValue, selKeys.searchValue); + testHook(hookKeys.useShowImportSuccessToast, selKeys.showImportSuccessToast); }); describe('assignmentTypes', () => { - const hookKeys = keyStore(selectorHooks.assignmentTypes); - const selGroup = selectors.assignmentTypes; - beforeEach(() => { hooks = selectorHooks.assignmentTypes; }); - testHook(hookKeys.useAllAssignmentTypes, selGroup.allAssignmentTypes); - testHook(hookKeys.useAreGradesFrozen, selGroup.areGradesFrozen); + loadSelectorGroup(selectorHooks.assignmentTypes, selectors.assignmentTypes); + testHook(hookKeys.useAllAssignmentTypes, selKeys.allAssignmentTypes); + testHook(hookKeys.useAreGradesFrozen, selKeys.areGradesFrozen); }); describe('cohorts', () => { - const hookKeys = keyStore(selectorHooks.cohorts); - const selGroup = selectors.cohorts; - beforeEach(() => { hooks = selectorHooks.cohorts; }); - testHook(hookKeys.useAllCohorts, selGroup.allCohorts); - testHook(hookKeys.useCohortsByName, selGroup.cohortsByName); + loadSelectorGroup(selectorHooks.cohorts, selectors.cohorts); + testHook(hookKeys.useAllCohorts, selKeys.allCohorts); + testHook(hookKeys.useCohortsByName, selKeys.cohortsByName); }); describe('filters', () => { - const hookKeys = keyStore(selectorHooks.filters); - const selGroup = selectors.filters; - beforeEach(() => { hooks = selectorHooks.filters; }); - testHook(hookKeys.useData, selGroup.allFilters); - testHook(hookKeys.useIncludeCourseRoleMembers, selGroup.includeCourseRoleMembers); - testHook(hookKeys.useSelectableAssignmentLabels, selGroup.selectableAssignmentLabels); - testHook(hookKeys.useSelectedAssignmentLabel, selGroup.selectedAssignmentLabel); - testHook(hookKeys.useAssignmentType, selGroup.assignmentType); + loadSelectorGroup(selectorHooks.filters, selectors.filters); + testHook(hookKeys.useData, selKeys.allFilters); + testHook(hookKeys.useIncludeCourseRoleMembers, selKeys.includeCourseRoleMembers); + testHook(hookKeys.useSelectableAssignmentLabels, selKeys.selectableAssignmentLabels); + testHook(hookKeys.useSelectedAssignmentLabel, selKeys.selectedAssignmentLabel); + testHook(hookKeys.useAssignmentType, selKeys.assignmentType); + }); + describe('grades', () => { + loadSelectorGroup(selectorHooks.grades, selectors.grades); + testHook(hookKeys.useAllGrades, selKeys.allGrades); + testHook(hookKeys.useGradeData, selKeys.gradeData); + testHook(hookKeys.useHasOverrideErrors, selKeys.hasOverrideErrors); + testHook(hookKeys.useShowSuccess, selKeys.showSuccess); + test(hookKeys.useUserCounts, () => { + expect(hooks.useUserCounts()).toEqual({ + filteredUsersCount: useSelector(selectors.grades.filteredUsersCount), + totalUsersCount: useSelector(selectors.grades.totalUsersCount), + }); + }); }); describe('roles', () => { - const hookKeys = keyStore(selectorHooks.roles); - const selGroup = selectors.roles; - beforeEach(() => { hooks = selectorHooks.roles; }); - testHook(hookKeys.useCanUserViewGradebook, selGroup.canUserViewGradebook); + loadSelectorGroup(selectorHooks.roles, selectors.roles); + testHook(hookKeys.useCanUserViewGradebook, selKeys.canUserViewGradebook); }); describe('tracks', () => { - const hookKeys = keyStore(selectorHooks.tracks); - const selGroup = selectors.tracks; - beforeEach(() => { hooks = selectorHooks.tracks; }); - testHook(hookKeys.useAllTracks, selGroup.allTracks); - testHook(hookKeys.useTracksByName, selGroup.tracksByName); + loadSelectorGroup(selectorHooks.tracks, selectors.tracks); + testHook(hookKeys.useAllTracks, selKeys.allTracks); + testHook(hookKeys.useTracksByName, selKeys.tracksByName); }); }); diff --git a/src/data/redux/hooks/thunkActions.js b/src/data/redux/hooks/thunkActions.js index 6b5bc5b..5017c5a 100644 --- a/src/data/redux/hooks/thunkActions.js +++ b/src/data/redux/hooks/thunkActions.js @@ -3,15 +3,22 @@ import thunkActions from 'data/thunkActions'; import { actionHook } from './utils'; const app = StrictDict({ - useCloseFilterMenu: actionHook(thunkActions.app.filterMenu.close), + filterMenu: { + useCloseMenu: actionHook(thunkActions.app.filterMenu.close), + useHandleTransitionEnd: actionHook(thunkActions.app.filterMenu.handleTransitionEnd), + useToggleMenu: actionHook(thunkActions.app.filterMenu.toggle), + }, + useSetModalStateFromTable: actionHook(thunkActions.app.setModalStateFromTable), }); const grades = StrictDict({ useFetchGradesIfAssignmentGradeFiltersSet: actionHook( thunkActions.grades.fetchGradesIfAssignmentGradeFiltersSet, ), + useFetchPrevNextGrades: actionHook(thunkActions.grades.fetchPrevNextGrades), useFetchGrades: actionHook(thunkActions.grades.fetchGrades), useSubmitImportGradesButtonData: actionHook(thunkActions.grades.submitImportGradesButtonData), + useUpdateGrades: actionHook(thunkActions.grades.updateGrades), }); export default StrictDict({ diff --git a/src/data/redux/hooks/thunkActions.test.js b/src/data/redux/hooks/thunkActions.test.js index 7ec8ebb..51499f0 100644 --- a/src/data/redux/hooks/thunkActions.test.js +++ b/src/data/redux/hooks/thunkActions.test.js @@ -5,7 +5,11 @@ import thunkActionHooks from './thunkActions'; jest.mock('data/thunkActions', () => ({ app: { - filterMenu: { close: jest.fn() }, + filterMenu: { + close: jest.fn(), + handleTransitionEnd: jest.fn(), + toggle: jest.fn(), + }, }, grades: { fetchGrades: jest.fn(), @@ -25,24 +29,38 @@ const testActionHook = (hookKey, action) => { expect(hooks[hookKey]).toEqual(actionHook(action)); }); }; +let hookKeys; describe('thunkAction hooks', () => { describe('app', () => { - const hookKeys = keyStore(thunkActionHooks.app); + hookKeys = keyStore(thunkActionHooks.app); beforeEach(() => { hooks = thunkActionHooks.app; }); - testActionHook(hookKeys.useCloseFilterMenu, thunkActions.app.filterMenu.close); + testActionHook(hookKeys.useSetModalStateFromTable, thunkActions.app.setModalStateFromTable); + + describe('filterMenu', () => { + hookKeys = keyStore(thunkActionHooks.app.filterMenu); + beforeEach(() => { hooks = thunkActionHooks.app.filterMenu; }); + testActionHook(hookKeys.useCloseMenu, thunkActions.app.filterMenu.close); + testActionHook( + hookKeys.useHandleTransitionEnd, + thunkActions.app.filterMenu.handleTransitionEnd, + ); + testActionHook(hookKeys.useToggleMenu, thunkActions.app.filterMenu.toggle); + }); }); describe('grades', () => { - const hookKeys = keyStore(thunkActionHooks.grades); + hookKeys = keyStore(thunkActionHooks.grades); const actionGroup = thunkActions.grades; beforeEach(() => { hooks = thunkActionHooks.grades; }); - testActionHook(hookKeys.useFetchGrades, actionGroup.fetchGrades); testActionHook( hookKeys.useFetchGradesIfAssignmentGradeFiltersSet, actionGroup.fetchGradesIfAssignmentGradeFiltersSet, ); + testActionHook(hookKeys.useFetchPrevNextGrades, actionGroup.fetchPrevNextGrades); + testActionHook(hookKeys.useFetchGrades, actionGroup.fetchGrades); testActionHook( hookKeys.useSubmitImportGradesButtonData, actionGroup.submitImportGradesButtonData, ); + testActionHook(hookKeys.useUpdateGrades, actionGroup.updateGrades); }); }); diff --git a/src/data/redux/transforms.js b/src/data/redux/transforms.js new file mode 100644 index 0000000..e63af12 --- /dev/null +++ b/src/data/redux/transforms.js @@ -0,0 +1,31 @@ +import { StrictDict } from 'utils'; +import selectors from 'data/selectors'; + +// export const root = StrictDict({}); +// export const app = StrictDict({}); +export const assignmentTypes = StrictDict({}); +export const cohorts = StrictDict({}); +export const filters = StrictDict({}); +export const grades = StrictDict({ + subsectionGrade: ({ gradeFormat, subsection }) => () => ( + selectors.grades.subsectionGrade[gradeFormat](subsection) + ), + roundGrade: selectors.grades.roundGrade, +}); + +export const roles = StrictDict({ +}); + +export const tracks = StrictDict({ +}); + +export default StrictDict({ + app, + assignmentTypes, + cohorts, + filters, + grades, + roles, + tracks, + root, +}); diff --git a/src/data/selectors/app.js b/src/data/selectors/app.js index 6fd32bd..4ef2f7c 100644 --- a/src/data/selectors/app.js +++ b/src/data/selectors/app.js @@ -89,6 +89,16 @@ const modalSelectors = simpleSelectorFactory( ], ); +const modalData = ({ app: { modalState } }) => ({ + assignmentName: modalState.assignmentName, + adjustedGradePossible: modalState.adjustedGradePossible, + adjustedGradeValue: modalState.adjustedGradeValue, + open: modalState.open, + reasonForChange: modalState.reasonForChange, + todaysDate: modalState.todaysDate, + updateUserName: modalState.updateUserName, +}); + const filterMenuSelectors = simpleSelectorFactory( ({ app: { filterMenu } }) => filterMenu, ['open', 'transitioning'], @@ -115,6 +125,7 @@ export default StrictDict({ isFilterMenuOpening, ...simpleSelectors, modalState: StrictDict(modalSelectors), + modalData, filterMenu: StrictDict({ ...filterMenuSelectors, isClosed: isFilterMenuClosed, diff --git a/src/data/selectors/grades.js b/src/data/selectors/grades.js index 7bc3f12..e5d22b6 100644 --- a/src/data/selectors/grades.js +++ b/src/data/selectors/grades.js @@ -266,12 +266,26 @@ const simpleSelectors = simpleSelectorFactory( 'gradeOverrideHistoryError', 'gradeOriginalEarnedGraded', 'gradeOriginalPossibleGraded', - 'nextPage', - 'prevPage', 'showSuccess', ], ); +const gradeData = ({ grades }) => ({ + courseId: grades.courseId, + filteredUsersCount: grades.filteredUsersCount, + totalUsersCount: grades.totalUsersCount, + gradeFormat: grades.gradeFormat, + showSpinner: grades.showSpinner, + gradeOverrideCurrentEarnedGradedOverride: grades.gradeOverrideCurrentEarnedGradedOverride, + gradeOverrideHistoryError: grades.gradeOverrideHistoryError, + gradeOverrideHistoryResults: grades.gradeOverrideHistoryResults, + gradeOriginalEarnedGraded: grades.gradeOriginalEarnedGraded, + gradeOriginalPossibleGraded: grades.gradeOriginalPossibleGraded, + nextPage: grades.nextPage, + prevPage: grades.prevPage, + showSuccess: grades.showSuccess, +}); + export default StrictDict({ bulkImportError, formatGradeOverrideForDisplay, @@ -286,6 +300,7 @@ export default StrictDict({ subsectionGrade, ...simpleSelectors, + gradeData, allGrades, bulkManagementHistoryEntries, getExampleSectionBreakdown,