feat: make notification channel headings clickable in notification preferences
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user