From 770e77f1014bba7f0f585e4dd605fd7770d8070c Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 11 Aug 2024 21:18:54 +0800 Subject: [PATCH] Remove notifications system (#3015) * Remove added files * Revert some changes * Revert remaining files * Update snapshots * Restore `courseIdWithoutPrefix` --- .../application/actions/SessionActions.ts | 16 -- .../application/reducers/SessionsReducer.ts | 6 - src/commons/application/types/SessionTypes.ts | 35 --- .../subcomponents/AcademyNavigationBar.tsx | 11 +- .../AcademyNavigationBar.tsx.snap | 42 ---- src/commons/sagas/BackendSaga.ts | 87 ------- src/commons/sagas/RequestsSaga.ts | 136 ----------- src/pages/academy/academyRoutes.tsx | 2 - src/pages/academy/adminPanel/AdminPanel.tsx | 3 - .../subcomponents/NotificationConfigPanel.tsx | 221 ------------------ .../assessmentConfigPanel/BooleanCell.tsx | 9 +- .../notificationConfigPanel/SelectCell.tsx | 75 ------ .../TimeOptionCell.tsx | 59 ----- .../academy/notiPreference/NotiPreference.tsx | 185 --------------- .../subcomponents/BooleanCell.tsx | 28 --- .../subcomponents/SelectCell.tsx | 92 -------- src/pages/localStorage.ts | 2 - 17 files changed, 4 insertions(+), 1005 deletions(-) delete mode 100644 src/pages/academy/adminPanel/subcomponents/NotificationConfigPanel.tsx delete mode 100644 src/pages/academy/adminPanel/subcomponents/notificationConfigPanel/SelectCell.tsx delete mode 100644 src/pages/academy/adminPanel/subcomponents/notificationConfigPanel/TimeOptionCell.tsx delete mode 100644 src/pages/academy/notiPreference/NotiPreference.tsx delete mode 100644 src/pages/academy/notiPreference/subcomponents/BooleanCell.tsx delete mode 100644 src/pages/academy/notiPreference/subcomponents/SelectCell.tsx diff --git a/src/commons/application/actions/SessionActions.ts b/src/commons/application/actions/SessionActions.ts index 21a011a691..5d7cdb63c1 100644 --- a/src/commons/application/actions/SessionActions.ts +++ b/src/commons/application/actions/SessionActions.ts @@ -22,9 +22,6 @@ import { Role, StoriesRole } from '../ApplicationTypes'; import { AdminPanelCourseRegistration, CourseRegistration, - NotificationConfiguration, - NotificationPreference, - TimeOption, Tokens, UpdateCourseConfiguration, User @@ -74,9 +71,6 @@ const SessionActions = createActions('session', { setCourseRegistration: (courseRegistration: Partial) => courseRegistration, setAssessmentConfigurations: (assessmentConfigurations: AssessmentConfiguration[]) => assessmentConfigurations, - setConfigurableNotificationConfigs: (notificationConfigs: NotificationConfiguration[]) => - notificationConfigs, - setNotificationConfigs: (notificationConfigs: NotificationConfiguration[]) => notificationConfigs, setAdminPanelCourseRegistrations: (courseRegistrations: AdminPanelCourseRegistration[]) => courseRegistrations, setGoogleUser: (user?: string) => user, @@ -141,18 +135,8 @@ const SessionActions = createActions('session', { updateCourseConfig: (courseConfiguration: UpdateCourseConfiguration) => courseConfiguration, fetchAssessmentConfigs: () => ({}), updateAssessmentConfigs: (assessmentConfigs: AssessmentConfiguration[]) => assessmentConfigs, - updateNotificationConfigs: (notificationConfigs: NotificationConfiguration[]) => - notificationConfigs, - updateNotificationPreferences: ( - notificationPreferences: NotificationPreference[], - courseRegId: number - ) => ({ notificationPreferences, courseRegId }), deleteAssessmentConfig: (assessmentConfig: AssessmentConfiguration) => assessmentConfig, fetchAdminPanelCourseRegistrations: () => ({}), - fetchConfigurableNotificationConfigs: (courseRegId: number) => ({ courseRegId }), - fetchNotificationConfigs: () => ({}), - updateTimeOptions: (timeOptions: TimeOption[]) => timeOptions, - deleteTimeOptions: (timeOptionIds: number[]) => timeOptionIds, updateUserRole: (courseRegId: number, role: Role) => ({ courseRegId, role }), deleteUserCourseRegistration: (courseRegId: number) => ({ courseRegId }), updateCourseResearchAgreement: (agreedToResearch: boolean) => ({ agreedToResearch }), diff --git a/src/commons/application/reducers/SessionsReducer.ts b/src/commons/application/reducers/SessionsReducer.ts index b2a3a362c4..dcd7b98349 100644 --- a/src/commons/application/reducers/SessionsReducer.ts +++ b/src/commons/application/reducers/SessionsReducer.ts @@ -45,12 +45,6 @@ const newSessionsReducer = createReducer(defaultSession, builder => { .addCase(SessionActions.setAssessmentConfigurations, (state, action) => { state.assessmentConfigurations = action.payload; }) - .addCase(SessionActions.setNotificationConfigs, (state, action) => { - state.notificationConfigs = action.payload; - }) - .addCase(SessionActions.setConfigurableNotificationConfigs, (state, action) => { - state.configurableNotificationConfigs = action.payload; - }) .addCase(SessionActions.setAdminPanelCourseRegistrations, (state, action) => { state.userCourseRegistrations = action.payload; }) diff --git a/src/commons/application/types/SessionTypes.ts b/src/commons/application/types/SessionTypes.ts index abe41d4422..20d4bb4402 100644 --- a/src/commons/application/types/SessionTypes.ts +++ b/src/commons/application/types/SessionTypes.ts @@ -47,9 +47,6 @@ export type SessionState = { readonly assessmentConfigurations?: AssessmentConfiguration[]; readonly userCourseRegistrations?: AdminPanelCourseRegistration[]; - readonly notificationConfigs?: NotificationConfiguration[]; - readonly configurableNotificationConfigs?: NotificationConfiguration[]; - // For research data collection readonly agreedToResearch?: boolean | null; readonly sessionId: number; @@ -124,35 +121,3 @@ export type AdminPanelCourseRegistration = { }; export type UpdateCourseConfiguration = Partial; - -export type TimeOption = { - id: number; - isDefault: boolean; - minutes: number; - notificationConfigId?: number; -}; - -export type NotificationPreference = { - id: number; - isEnabled: boolean | null; - timeOptionId: number | null; - notificationConfigId?: number; -}; - -export type NotificationConfiguration = { - id: number; - isEnabled: boolean; - notificationType: { - id: number; - name: string; - isEnabled: boolean; - forStaff: boolean; - }; - timeOptions: TimeOption[]; - assessmentConfig: { - id: number; - type: string; - } | null; - notificationPreference: NotificationPreference; - course: any; -}; diff --git a/src/commons/navigationBar/subcomponents/AcademyNavigationBar.tsx b/src/commons/navigationBar/subcomponents/AcademyNavigationBar.tsx index 0fde5cc1f3..1488814ac2 100644 --- a/src/commons/navigationBar/subcomponents/AcademyNavigationBar.tsx +++ b/src/commons/navigationBar/subcomponents/AcademyNavigationBar.tsx @@ -148,15 +148,6 @@ export const getAcademyNavbarRightInfo = ({ isEnrolledInACourse: boolean; courseId?: number; role?: Role; -}): NavbarEntryInfo[] => [ - ...getStaffNavlinkInfo({ courseId, role }), - { - to: `/courses/${courseId}/notipreference`, - icon: IconNames.NOTIFICATIONS, - text: 'Notifications', - disabled: !isEnrolledInACourse, - hiddenInBreakpoints: ['xs', 'sm', 'md', 'lg'] - } -]; +}): NavbarEntryInfo[] => [...getStaffNavlinkInfo({ courseId, role })]; export default AcademyNavigationBar; diff --git a/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/AcademyNavigationBar.tsx.snap b/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/AcademyNavigationBar.tsx.snap index b399045dae..c9cf0071ef 100644 --- a/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/AcademyNavigationBar.tsx.snap +++ b/src/commons/navigationBar/subcomponents/__tests__/__snapshots__/AcademyNavigationBar.tsx.snap @@ -167,20 +167,6 @@ exports[`MissionControl, GroundControl, Sourcereel, GameSimulator, Dashboard, Gr text="Admin Panel" to="/courses/0/adminpanel" /> - `; @@ -352,20 +338,6 @@ exports[`MissionControl, GroundControl, Sourcereel, GameSimulator, Dashboard, Gr text="Admin Panel" to="/courses/0/adminpanel" /> - `; @@ -537,20 +509,6 @@ exports[`MissionControl, GroundControl, Sourcereel, GameSimulator, Dashboard, Te text="Admin Panel" to="/courses/0/adminpanel" /> - `; diff --git a/src/commons/sagas/BackendSaga.ts b/src/commons/sagas/BackendSaga.ts index f4c0f038dc..eb76230b80 100644 --- a/src/commons/sagas/BackendSaga.ts +++ b/src/commons/sagas/BackendSaga.ts @@ -28,8 +28,6 @@ import { AdminPanelCourseRegistration, CourseConfiguration, CourseRegistration, - NotificationConfiguration, - TimeOption, Tokens, UpdateCourseConfiguration, User @@ -60,13 +58,11 @@ import { getAssessment, getAssessmentConfigs, getAssessmentOverviews, - getConfigurableNotificationConfigs, getCourseConfig, getGrading, getGradingOverviews, getGradingSummary, getLatestCourseRegistrationAndConfiguration, - getNotificationConfigs, getNotifications, getSourcecastIndex, getStudents, @@ -95,13 +91,9 @@ import { putCourseResearchAgreement, putLatestViewedCourse, putNewUsers, - putNotificationConfigs, - putNotificationPreferences, putTeams, - putTimeOptions, putUserRole, removeAssessmentConfig, - removeTimeOptions, removeUserCourseRegistration, unpublishGrading, unpublishGradingAll, @@ -859,32 +851,6 @@ const newBackendSagaTwo = combineSagaHandlers(sagaActions, { yield put(actions.setAssessmentConfigurations(assessmentConfigs)); } }, - fetchConfigurableNotificationConfigs: function* (action) { - const tokens: Tokens = yield selectTokens(); - const { courseRegId }: { courseRegId: number } = action.payload; - - const notificationConfigs: NotificationConfiguration[] | null = yield call( - getConfigurableNotificationConfigs, - tokens, - courseRegId - ); - - if (notificationConfigs) { - yield put(actions.setConfigurableNotificationConfigs(notificationConfigs)); - } - }, - fetchNotificationConfigs: function* () { - const tokens: Tokens = yield selectTokens(); - - const notificationConfigs: NotificationConfiguration[] | null = yield call( - getNotificationConfigs, - tokens - ); - - if (notificationConfigs) { - yield put(actions.setNotificationConfigs(notificationConfigs)); - } - }, updateAssessmentConfigs: function* (action) { const tokens: Tokens = yield selectTokens(); const assessmentConfigs: AssessmentConfiguration[] = action.payload; @@ -904,41 +870,6 @@ const newBackendSagaTwo = combineSagaHandlers(sagaActions, { } yield call(showSuccessMessage, 'Updated successfully!', 1000); }, - updateNotificationConfigs: function* (action) { - const tokens: Tokens = yield selectTokens(); - const notificationConfigs: NotificationConfiguration[] = action.payload; - - const resp: Response | null = yield call(putNotificationConfigs, tokens, notificationConfigs); - if (!resp || !resp.ok) { - return yield handleResponseError(resp); - } - - const updatedNotificationConfigs: NotificationConfiguration[] | null = yield call( - getNotificationConfigs, - tokens - ); - - if (updatedNotificationConfigs) { - yield put(actions.setNotificationConfigs(updatedNotificationConfigs)); - } - - yield call(showSuccessMessage, 'Updated successfully!', 1000); - }, - updateNotificationPreferences: function* (action) { - const tokens: Tokens = yield selectTokens(); - const { notificationPreferences, courseRegId } = action.payload; - const resp: Response | null = yield call( - putNotificationPreferences, - tokens, - notificationPreferences, - courseRegId - ); - if (!resp || !resp.ok) { - return yield handleResponseError(resp); - } - - yield call(showSuccessMessage, 'Updated successfully!', 1000); - }, deleteAssessmentConfig: function* (action) { const tokens: Tokens = yield selectTokens(); const assessmentConfig: AssessmentConfiguration = action.payload; @@ -948,24 +879,6 @@ const newBackendSagaTwo = combineSagaHandlers(sagaActions, { return yield handleResponseError(resp); } }, - updateTimeOptions: function* (action) { - const tokens: Tokens = yield selectTokens(); - const timeOptions: TimeOption[] = action.payload; - - const resp: Response | null = yield call(putTimeOptions, tokens, timeOptions); - if (!resp || !resp.ok) { - return yield handleResponseError(resp); - } - }, - deleteTimeOptions: function* (action) { - const tokens: Tokens = yield selectTokens(); - const timeOptionIds: number[] = action.payload; - - const resp: Response | null = yield call(removeTimeOptions, tokens, timeOptionIds); - if (!resp || !resp.ok) { - return yield handleResponseError(resp); - } - }, fetchAdminPanelCourseRegistrations: function* (action) { const tokens: Tokens = yield selectTokens(); diff --git a/src/commons/sagas/RequestsSaga.ts b/src/commons/sagas/RequestsSaga.ts index 6c7a1ee68b..2420da76da 100644 --- a/src/commons/sagas/RequestsSaga.ts +++ b/src/commons/sagas/RequestsSaga.ts @@ -37,9 +37,6 @@ import { AdminPanelCourseRegistration, CourseConfiguration, CourseRegistration, - NotificationConfiguration, - NotificationPreference, - TimeOption, Tokens, UpdateCourseConfiguration, User @@ -1345,50 +1342,6 @@ export const putAssessmentConfigs = async ( return resp; }; -export const putNotificationConfigs = async ( - tokens: Tokens, - notificationConfigs: NotificationConfiguration[] -) => { - return await request(`notifications/config`, 'PUT', { - ...tokens, - body: notificationConfigs, - noHeaderAccept: true - }); -}; - -export const putTimeOption = async ( - tokens: Tokens, - timeOption: TimeOption -): Promise => { - const resp = await request(`notifications/options/${timeOption.id}`, 'PUT', { - ...tokens, - body: { - isDefault: timeOption.isDefault - }, - noHeaderAccept: true - }); - - return resp; -}; - -export const postTimeOption = async ( - tokens: Tokens, - timeOption: TimeOption, - notificationConfigId: number -): Promise => { - const resp = await request(`notifications/options`, 'POST', { - ...tokens, - body: { - isDefault: timeOption.isDefault, - minutes: timeOption.minutes, - notification_config_id: notificationConfigId - }, - noHeaderAccept: true - }); - - return resp; -}; - /** * DELETE /courses/{courseId}/admin/config/assessment_config/{assessmentConfigId} */ @@ -1408,95 +1361,6 @@ export const removeAssessmentConfig = async ( return resp; }; -export const removeTimeOptions = async ( - tokens: Tokens, - timeOptionIds: number[] -): Promise => { - const resp = await request(`notifications/options`, 'DELETE', { - ...tokens, - body: timeOptionIds, - noHeaderAccept: true - }); - - return resp; -}; - -export const putTimeOptions = async ( - tokens: Tokens, - timeOptions: TimeOption[] -): Promise => { - const resp = await request(`notifications/options`, 'PUT', { - ...tokens, - body: timeOptions, - noHeaderAccept: true - }); - - return resp; -}; - -export const getNotificationConfigs = async ( - tokens: Tokens -): Promise => { - const resp = await request(`notifications/config/${courseIdWithoutPrefix()}`, 'GET', { - ...tokens - }); - if (!resp || !resp.ok) { - return null; - } - - return await resp.json(); -}; - -export const getConfigurableNotificationConfigs = async ( - tokens: Tokens, - courseRegId: number -): Promise => { - const resp = await request(`notifications/config/user/${courseRegId}`, 'GET', { - ...tokens - }); - if (!resp || !resp.ok) { - return null; - } - - return await resp.json(); -}; - -export const postNotificationPreference = async ( - tokens: Tokens, - notiPref: NotificationPreference, - notificationConfigId: number, - courseRegId: number -): Promise => { - const resp = await request(`notifications/preference`, 'POST', { - ...tokens, - body: { - is_enabled: notiPref.isEnabled, - time_option_id: notiPref.timeOptionId, - notification_config_id: notificationConfigId, - course_reg_id: courseRegId - }, - noHeaderAccept: true - }); - - return resp; -}; - -export const putNotificationPreferences = async ( - tokens: Tokens, - notiPrefs: NotificationPreference[], - courseRegId: number -): Promise => { - const resp = await request(`notifications/preferences`, 'PUT', { - ...tokens, - body: notiPrefs.map(pref => { - return { ...pref, courseRegId: courseRegId }; - }), - noHeaderAccept: true - }); - - return resp; -}; - /** * GET /courses/{courseId}/admin/users */ diff --git a/src/pages/academy/academyRoutes.tsx b/src/pages/academy/academyRoutes.tsx index c74c9111b0..0435bfaf9e 100644 --- a/src/pages/academy/academyRoutes.tsx +++ b/src/pages/academy/academyRoutes.tsx @@ -12,7 +12,6 @@ import { store } from '../createStore'; const notFoundPath = 'not_found'; const Game = () => import('./game/Game'); -const NotiPreference = () => import('./notiPreference/NotiPreference'); const Sourcecast = () => import('../sourcecast/Sourcecast'); const Achievement = () => import('../achievement/Achievement'); const NotFound = () => import('../notFound/NotFound'); @@ -72,7 +71,6 @@ const getCommonAcademyRoutes = (): RouteObject[] => { element: , loader: assessmentLoader }, - { path: 'notipreference', lazy: NotiPreference }, { path: 'sourcecast/:sourcecastId?', lazy: Sourcecast }, { path: 'achievements/*', lazy: Achievement }, { path: '*', lazy: NotFound } diff --git a/src/pages/academy/adminPanel/AdminPanel.tsx b/src/pages/academy/adminPanel/AdminPanel.tsx index 5b68b1b510..d60edb1647 100644 --- a/src/pages/academy/adminPanel/AdminPanel.tsx +++ b/src/pages/academy/adminPanel/AdminPanel.tsx @@ -18,7 +18,6 @@ import AssessmentConfigPanel, { ImperativeAssessmentConfigPanel } from './subcomponents/assessmentConfigPanel/AssessmentConfigPanel'; import CourseConfigPanel from './subcomponents/CourseConfigPanel'; -import NotificationConfigPanel from './subcomponents/NotificationConfigPanel'; import StoriesUserConfigPanel from './subcomponents/storiesUserConfigPanel/StoriesUserConfigPanel'; import UserConfigPanel from './subcomponents/userConfigPanel/UserConfigPanel'; @@ -46,7 +45,6 @@ const AdminPanel: React.FC = () => { dispatch(SessionActions.fetchCourseConfig()); dispatch(SessionActions.fetchAssessmentConfigs()); dispatch(SessionActions.fetchAdminPanelCourseRegistrations()); - dispatch(SessionActions.fetchNotificationConfigs()); }, [dispatch]); useEffect(() => { @@ -199,7 +197,6 @@ const AdminPanel: React.FC = () => { /> } /> - } /> ); diff --git a/src/pages/academy/adminPanel/subcomponents/NotificationConfigPanel.tsx b/src/pages/academy/adminPanel/subcomponents/NotificationConfigPanel.tsx deleted file mode 100644 index aeba61f2c3..0000000000 --- a/src/pages/academy/adminPanel/subcomponents/NotificationConfigPanel.tsx +++ /dev/null @@ -1,221 +0,0 @@ -import { Button, H2, Intent } from '@blueprintjs/core'; -import { ColDef, GridApi, GridReadyEvent, ValueFormatterFunc } from 'ag-grid-community'; -import { AgGridReact } from 'ag-grid-react'; -import { cloneDeep } from 'lodash'; -import React, { useEffect, useState } from 'react'; -import { useDispatch } from 'react-redux'; -import SessionActions from 'src/commons/application/actions/SessionActions'; -import { NotificationConfiguration, TimeOption } from 'src/commons/application/types/SessionTypes'; -import { useSession } from 'src/commons/utils/Hooks'; - -import BooleanCell from './assessmentConfigPanel/BooleanCell'; -import SelectCell from './notificationConfigPanel/SelectCell'; -import TimeOptionCell from './notificationConfigPanel/TimeOptionCell'; - -const defaultColumnDefs: ColDef = { - flex: 1, - minWidth: 70, - filter: false, - resizable: true, - sortable: false -}; - -const NotificationConfigPanel: React.FC = () => { - const gridApi = React.useRef(); - - const dispatch = useDispatch(); - const session = useSession(); - - /** - * Mutable ref to track the assessment configuration form state instead of useState. This is - * because ag-grid does not update the cellRendererParams whenever there is an update in rowData, - * leading to a stale closure problem where the handlers in AssessmentConfigPanel capture the old - * value of assessmentConfig. - * - * Also, useState causes a flicker in ag-grid during rerenders. Thus we use this mutable ref and - * ag-grid's API to update cell values instead. - */ - const notificationConfig = React.useRef( - session.notificationConfigs - ); - const [timeOptionsToDelete, setTimeOptionsToDelete] = useState([]); - const [hasChangesNotificationConfig, setHasChangesNotificationConfig] = useState(false); - - const setNotificationConfig = (val: NotificationConfiguration[]) => { - notificationConfig.current = val; - setHasChangesNotificationConfig(true); - }; - - const addTimeOptionsToDelete = (deletedElement: TimeOption) => { - // If it is not a newly created row that is yet to be persisted in the backend - if (deletedElement.id !== -1) { - const temp = [...timeOptionsToDelete]; - temp.push(deletedElement); - setTimeOptionsToDelete(temp); - } - }; - - useEffect(() => { - dispatch(SessionActions.fetchNotificationConfigs()); - }, [dispatch]); - - useEffect(() => { - notificationConfig.current = cloneDeep( - session.notificationConfigs - ) as NotificationConfiguration[]; - }, [session]); - - const setIsEnabled = (index: number, value: boolean) => { - const temp = [...(notificationConfig.current ?? [])]; - temp[index] = { - ...temp[index], - isEnabled: value - }; - setNotificationConfig(temp); - gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('isEnabled', value); - setHasChangesNotificationConfig(true); - }; - - const setTimeOptions = (index: number, value: TimeOption[]) => { - const temp = [...(notificationConfig.current ?? [])]; - - temp[index] = { - ...temp[index], - timeOptions: value - }; - setNotificationConfig(temp); - gridApi.current?.getDisplayedRowAtIndex(index)?.setDataValue('timeOptions', value); - setHasChangesNotificationConfig(true); - }; - - const assessmentTypeFormatter: ValueFormatterFunc = params => { - return params.data!.assessmentConfig?.type || '-'; - }; - - const recipientFormatter: ValueFormatterFunc = params => { - return params.data!.notificationType.forStaff ? 'Staff' : 'Student'; - }; - - const columnDefs: ColDef[] = [ - { - headerName: 'Notification Type', - field: 'notificationType.name', - rowDrag: true - }, - { - headerName: 'Assessment Type', - field: 'assessmentConfig.type', - valueFormatter: assessmentTypeFormatter - }, - { - headerName: 'Recipients', - field: 'notificationType.forStaff', - valueFormatter: recipientFormatter - }, - // TODO: Extension for notification configs - // { - // headerName: 'View Email Template', - // field: 'notificationType.name' - // }, - // { - // headerName: 'Past 30 Days', - // field: 'notificationType.id' - // }, - { - headerName: 'Reminder Time Options (hours)', - field: 'timeOptions', - cellRenderer: TimeOptionCell, - cellRendererParams: { - setStateHandler: setTimeOptions, - setDelete: addTimeOptionsToDelete, - field: 'timeOptions' - } - }, - { - headerName: 'Default Reminder (hours)', - field: 'timeOptions', - cellRenderer: SelectCell, - cellRendererParams: { - setStateHandler: setTimeOptions, - field: 'timeOptions' - } - }, - { - headerName: 'Enabled', - field: 'isEnabled', - cellRenderer: BooleanCell, - cellRendererParams: { - setStateHandler: setIsEnabled, - field: 'isEnabled' - } - } - ]; - - const onGridReady = (params: GridReadyEvent) => { - gridApi.current = params.api; - }; - - // Handler to submit changes to Notification Configration to the backend. - // Changes made to users, Course Configration and Assessment Configuration are handled separately. - const submitHandler = () => { - if (hasChangesNotificationConfig) { - setHasChangesNotificationConfig(false); - const allTimeOptions: TimeOption[] = []; - notificationConfig.current?.forEach(curr => { - const timeOptions = curr.timeOptions.map(timeOption => { - return { - ...timeOption, - notificationConfigId: curr.id - }; - }); - allTimeOptions.push(...timeOptions); - }); - - if (allTimeOptions.length > 0) { - dispatch(SessionActions.updateTimeOptions(allTimeOptions)); - } - - if (timeOptionsToDelete.length > 0) { - dispatch( - SessionActions.deleteTimeOptions(timeOptionsToDelete.map(timeOption => timeOption.id)) - ); - setTimeOptionsToDelete([]); - } - dispatch(SessionActions.updateNotificationConfigs(notificationConfig.current ?? [])); - } - }; - - const grid = ( -
- -
- ); - - return ( -
-
-

Notification Configuration

-
- {grid} -
- ); -}; - -export default NotificationConfigPanel; diff --git a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/BooleanCell.tsx b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/BooleanCell.tsx index 3ed54b2ec2..529d7222c0 100644 --- a/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/BooleanCell.tsx +++ b/src/pages/academy/adminPanel/subcomponents/assessmentConfigPanel/BooleanCell.tsx @@ -1,14 +1,11 @@ import { Switch } from '@blueprintjs/core'; import React from 'react'; +import { AssessmentConfiguration } from 'src/commons/assessment/AssessmentTypes'; import { KeysOfType } from 'src/commons/utils/TypeHelper'; -interface dataProps { - [key: string]: boolean; -} - type Props = { - data: dataProps; - field: KeysOfType; + data: AssessmentConfiguration; + field: KeysOfType; rowIndex: number; setStateHandler: (index: number, value: boolean) => void; }; diff --git a/src/pages/academy/adminPanel/subcomponents/notificationConfigPanel/SelectCell.tsx b/src/pages/academy/adminPanel/subcomponents/notificationConfigPanel/SelectCell.tsx deleted file mode 100644 index b00cb203f8..0000000000 --- a/src/pages/academy/adminPanel/subcomponents/notificationConfigPanel/SelectCell.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Button, MenuItem } from '@blueprintjs/core'; -import { ItemRenderer, Select2 } from '@blueprintjs/select'; -import React from 'react'; -import { NotificationConfiguration, TimeOption } from 'src/commons/application/types/SessionTypes'; -import { KeysOfType } from 'src/commons/utils/TypeHelper'; - -type Props = { - data: NotificationConfiguration; - rowIndex: number; - field: KeysOfType; - setStateHandler: (rowIndex: number, value: any) => void; -}; - -const SelectCell: React.FC = props => { - const [selectedOption, setSelectedOption] = React.useState(); - const timeOptions: TimeOption[] = props.data[props.field]; - timeOptions.sort((to1, to2) => to1.minutes - to2.minutes); - - const getUserFriendlyText = (option: TimeOption) => - option.minutes >= 60 - ? `${Math.round((option.minutes / 60) * 100) / 100} hour(s)` - : `${option.minutes} minute(s)`; - - const renderOption: ItemRenderer = ( - option: TimeOption, - { handleClick, handleFocus, modifiers, query } - ) => { - return ( - - ); - }; - - const defaultTimeOptions = timeOptions.filter(to => to.isDefault); - if (defaultTimeOptions.length === 1) { - if (!selectedOption || selectedOption.id !== defaultTimeOptions[0].id) { - setSelectedOption(defaultTimeOptions[0]); - } - } - - const handleSelect = (option: TimeOption) => { - setSelectedOption(option); - const updatedTimeOptions: TimeOption[] = timeOptions.map(timeOption => { - return { - ...timeOption, - isDefault: timeOption.id === option.id && timeOption.minutes === option.minutes - }; - }); - props.setStateHandler(props.rowIndex, updatedTimeOptions); - }; - - return ( - - filterable={false} - items={timeOptions} - itemRenderer={renderOption} - onItemSelect={handleSelect} - noResults={} - > -