feat: make notification channel headings clickable in notification preferences

This commit is contained in:
eemaanamir
2024-01-22 15:01:11 +05:00
parent 208c7a1ada
commit d3e8b36e69
4 changed files with 98 additions and 6 deletions

View File

@@ -2,18 +2,20 @@ import React, { useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Collapsible } from '@edx/paragon';
import { Collapsible, NavItem } from '@edx/paragon';
import classNames from 'classnames';
import messages from './messages';
import ToggleSwitch from './ToggleSwitch';
import {
selectPreferenceAppToggleValue,
selectPreferenceAppToggleValue, selectPreferenceNonEditable,
selectPreferencesOfApp,
selectSelectedCourseId,
selectUpdatePreferencesStatus,
} from './data/selectors';
import NotificationPreferenceRow from './NotificationPreferenceRow';
import { updateAppPreferenceToggle } from './data/thunks';
import { updateAppPreferenceToggle, updateChannelPreferenceToggle } from './data/thunks';
import { LOADING_STATUS } from '../constants';
import NOTIFICATION_CHANNELS from './data/constants';
const NotificationPreferenceApp = ({ appId }) => {
const dispatch = useDispatch();
@@ -22,6 +24,35 @@ const NotificationPreferenceApp = ({ appId }) => {
const appPreferences = useSelector(selectPreferencesOfApp(appId));
const appToggle = useSelector(selectPreferenceAppToggleValue(appId));
const updatePreferencesStatus = useSelector(selectUpdatePreferencesStatus());
const nonEditable = useSelector(selectPreferenceNonEditable(appId));
const onColumnToggle = useCallback(
(event) => {
const {
id: notificationChannel,
} = event.target;
const truePreferences = appPreferences.filter((preference) => {
const isPreferenceNonEditable = nonEditable?.[preference.id]?.includes(notificationChannel) || false;
return preference[notificationChannel] === true && !isPreferenceNonEditable;
});
if (truePreferences.length > 0) {
dispatch(updateChannelPreferenceToggle(
courseId,
appId,
notificationChannel,
false,
));
} else {
dispatch(updateChannelPreferenceToggle(
courseId,
appId,
notificationChannel,
true,
));
}
},
[appId, appPreferences, courseId, dispatch, nonEditable],
);
const preferences = useMemo(() => (
appPreferences.map(preference => (
@@ -36,7 +67,6 @@ const NotificationPreferenceApp = ({ appId }) => {
dispatch(updateAppPreferenceToggle(courseId, appId, event.target.checked));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [appId]);
if (!courseId) {
return null;
}
@@ -62,7 +92,27 @@ const NotificationPreferenceApp = ({ appId }) => {
<div className="d-flex flex-row header-label">
<span className="col-8 px-0">{intl.formatMessage(messages.typeLabel)}</span>
<span className="d-flex col-4 px-0">
<span className="ml-auto">{intl.formatMessage(messages.webLabel)}</span>
{NOTIFICATION_CHANNELS.map((channel) => (
<NavItem
id={channel}
className={classNames(
'd-flex',
{ 'ml-auto': channel === 'web' },
{ 'mx-auto': channel === 'email' },
{ 'ml-auto mr-0': channel === 'push' },
)}
role="button"
onClick={onColumnToggle}
>
{
// eslint-disable-next-line no-nested-ternary
channel === 'web' ? intl.formatMessage(messages.webLabel)
// eslint-disable-next-line no-nested-ternary
: channel === 'email' ? intl.formatMessage(messages.notificationHelpEmail)
: channel === 'push' ? intl.formatMessage(messages.notificationHelpPush) : null
}
</NavItem>
))}
</span>
</div>
<div className="my-3">

View File

@@ -54,6 +54,10 @@ export const selectPreferenceNonEditableChannels = (appId, name) => state => (
state?.notificationPreferences.preferences.nonEditable[appId]?.[name] || []
);
export const selectPreferenceNonEditable = (appId) => state => (
state?.notificationPreferences.preferences.nonEditable[appId] || []
);
export const selectSelectedCourseId = () => state => (
state.notificationPreferences.preferences.selectedCourse
);

View File

@@ -42,3 +42,19 @@ export const patchPreferenceToggle = async (
const { data } = await getAuthenticatedHttpClient().patch(url, patchData);
return data;
};
export const patchChannelPreferenceToggle = async (
courseId,
notificationApp,
notificationChannel,
value,
) => {
const patchData = snakeCaseObject({
notificationApp,
notificationChannel,
value,
});
const url = `${getConfig().LMS_BASE_URL}/api/notifications/channel/configurations/${courseId}`;
const { data } = await getAuthenticatedHttpClient().patch(url, patchData);
return data;
};

View File

@@ -13,7 +13,7 @@ import {
import {
getCourseList,
getCourseNotificationPreferences,
patchAppPreferenceToggle,
patchAppPreferenceToggle, patchChannelPreferenceToggle,
patchPreferenceToggle,
} from './service';
@@ -148,3 +148,25 @@ export const updatePreferenceToggle = (
}
}
);
export const updateChannelPreferenceToggle = (
courseId,
notificationApp,
notificationChannel,
value,
) => (
async (dispatch) => {
try {
const data = await patchChannelPreferenceToggle(
courseId,
notificationApp,
notificationChannel,
value,
);
const normalizedData = normalizePreferences(camelCaseObject(data));
dispatch(fetchNotificationPreferenceSuccess(courseId, normalizedData));
} catch (errors) {
dispatch(fetchNotificationPreferenceFailed());
}
}
);