Compare commits
7 Commits
renovate/m
...
eemaan/INF
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6acce16bff | ||
|
|
09c02cb367 | ||
|
|
36f7c939e5 | ||
|
|
aeb8109d94 | ||
|
|
a6699f94c9 | ||
|
|
a3497adb6d | ||
|
|
d3e8b36e69 |
@@ -2,18 +2,21 @@ 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 '@openedx/paragon';
|
||||
import { Collapsible, NavItem } from '@edx/paragon';
|
||||
import classNames from 'classnames';
|
||||
import messages from './messages';
|
||||
import ToggleSwitch from './ToggleSwitch';
|
||||
import {
|
||||
selectPreferenceAppToggleValue,
|
||||
selectNonEditablePreferences,
|
||||
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 +25,18 @@ const NotificationPreferenceApp = ({ appId }) => {
|
||||
const appPreferences = useSelector(selectPreferencesOfApp(appId));
|
||||
const appToggle = useSelector(selectPreferenceAppToggleValue(appId));
|
||||
const updatePreferencesStatus = useSelector(selectUpdatePreferencesStatus());
|
||||
const nonEditable = useSelector(selectNonEditablePreferences(appId));
|
||||
|
||||
const onChannelToggle = useCallback((event) => {
|
||||
const { id: notificationChannel } = event.target;
|
||||
const isPreferenceNonEditable = (preference) => nonEditable?.[preference.id]?.includes(notificationChannel);
|
||||
|
||||
const hasActivePreferences = appPreferences.some(
|
||||
(preference) => preference[notificationChannel] && !isPreferenceNonEditable(preference),
|
||||
);
|
||||
|
||||
dispatch(updateChannelPreferenceToggle(courseId, appId, notificationChannel, !hasActivePreferences));
|
||||
}, [appId, appPreferences, courseId, dispatch, nonEditable]);
|
||||
|
||||
const preferences = useMemo(() => (
|
||||
appPreferences.map(preference => (
|
||||
@@ -36,10 +51,10 @@ const NotificationPreferenceApp = ({ appId }) => {
|
||||
dispatch(updateAppPreferenceToggle(courseId, appId, event.target.checked));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appId]);
|
||||
|
||||
if (!courseId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Collapsible.Advanced open={appToggle} data-testid="notification-app" className="mb-5">
|
||||
<Collapsible.Trigger>
|
||||
@@ -62,7 +77,22 @@ 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}
|
||||
key={channel}
|
||||
className={classNames(
|
||||
'd-flex',
|
||||
{ 'ml-auto': channel === 'web' },
|
||||
{ 'mx-auto': channel === 'email' },
|
||||
{ 'ml-auto mr-0': channel === 'push' },
|
||||
)}
|
||||
role="button"
|
||||
onClick={onChannelToggle}
|
||||
>
|
||||
{intl.formatMessage(messages.notificationChannel, { text: channel })}
|
||||
</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 selectNonEditablePreferences = appId => state => (
|
||||
state?.notificationPreferences.preferences.nonEditable[appId] || []
|
||||
);
|
||||
|
||||
export const selectSelectedCourseId = () => state => (
|
||||
state.notificationPreferences.preferences.selectedCourse
|
||||
);
|
||||
|
||||
@@ -42,3 +42,10 @@ 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;
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
getCourseList,
|
||||
getCourseNotificationPreferences,
|
||||
patchAppPreferenceToggle,
|
||||
patchChannelPreferenceToggle,
|
||||
patchPreferenceToggle,
|
||||
} from './service';
|
||||
|
||||
@@ -148,3 +149,15 @@ 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());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -28,6 +28,17 @@ const messages = defineMessages({
|
||||
}`,
|
||||
description: 'Display text for Notification Types',
|
||||
},
|
||||
notificationChannel: {
|
||||
id: 'notification.preference.channel',
|
||||
defaultMessage: `{
|
||||
text, select,
|
||||
web {Web}
|
||||
email {Email}
|
||||
push {Push}
|
||||
other {{text}}
|
||||
}`,
|
||||
description: 'Display text for Notification Channel',
|
||||
},
|
||||
typeLabel: {
|
||||
id: 'notification.preference.type.label',
|
||||
defaultMessage: 'Type',
|
||||
|
||||
Reference in New Issue
Block a user