feat: added notification APIs
This commit is contained in:
@@ -4,21 +4,25 @@ import React, {
|
||||
import { Tabs, Tab } from '@edx/paragon';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import NotificationSections from './NotificationSections';
|
||||
import { getNotificationTotalUnseenCounts, getSelectedNotificationType } from './data/selectors';
|
||||
import { fetchNotificationList } from './data/thunks';
|
||||
import { getNotificationTotalUnseenCounts, getSelectedAppName } from './data/selectors';
|
||||
import { fetchNotificationList, markNotificationsAsSeen } from './data/thunks';
|
||||
import { notificationTabsOptions } from './data/constants';
|
||||
|
||||
const NotificationTabs = () => {
|
||||
const notificationUnseenCounts = useSelector(getNotificationTotalUnseenCounts());
|
||||
const selectedNotificationType = useSelector(getSelectedNotificationType());
|
||||
const selectedappName = useSelector(getSelectedAppName());
|
||||
const [activeTab, setActiveTab] = useState(notificationTabsOptions[0].key);
|
||||
const [loadMoreCount, setLoadMoreCount] = useState(10);
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchNotificationList({ notificationType: activeTab, notificationCount: loadMoreCount }));
|
||||
}, [dispatch, activeTab, loadMoreCount]);
|
||||
dispatch(fetchNotificationList({
|
||||
appName: activeTab, notificationCount: loadMoreCount, page, pageSize: 10,
|
||||
}));
|
||||
dispatch(markNotificationsAsSeen(activeTab));
|
||||
}, [dispatch, activeTab, loadMoreCount, page]);
|
||||
|
||||
const handleActiveTab = useCallback((tab) => {
|
||||
setActiveTab(tab);
|
||||
@@ -26,7 +30,8 @@ const NotificationTabs = () => {
|
||||
|
||||
const handleLoadMoreNotification = useCallback((count) => {
|
||||
setLoadMoreCount(count);
|
||||
}, []);
|
||||
setPage(page + 1);
|
||||
}, [page]);
|
||||
|
||||
const tabArray = useMemo(() => notificationTabsOptions.map((option) => (
|
||||
<Tab
|
||||
@@ -35,10 +40,10 @@ const NotificationTabs = () => {
|
||||
notification={notificationUnseenCounts.countByAppName[option.key]}
|
||||
tabClassName="pt-0 pb-2.5 px-2.5 d-flex flex-row align-items-center line-height-24"
|
||||
>
|
||||
{option.key === selectedNotificationType
|
||||
{option.key === selectedappName
|
||||
&& <NotificationSections handleLoadMoreNotification={handleLoadMoreNotification} loadMoreCount={loadMoreCount} />}
|
||||
</Tab>
|
||||
)), [notificationUnseenCounts, handleLoadMoreNotification, loadMoreCount, selectedNotificationType]);
|
||||
)), [notificationUnseenCounts, handleLoadMoreNotification, loadMoreCount, selectedappName]);
|
||||
|
||||
// This code is used to replace More... text to More to match the UI
|
||||
const buttons = document.getElementsByClassName('dropdown-toggle');
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { camelCaseObject } from '@edx/frontend-platform';
|
||||
import { camelCaseObject, getConfig, snakeCaseObject } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
export const getNotificationsCountApiUrl = () => `${getConfig().LMS_BASE_URL}/api/notifications/count/`;
|
||||
export const getNotificationsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/notifications/`;
|
||||
export const markNotificationsSeenApiUrl = (appName) => `${getConfig().LMS_BASE_URL}/api/notifications/mark-notifications-unseen/${appName}/`;
|
||||
|
||||
const parseNotificationList = (notificationList) => {
|
||||
const currentTime = Date.now();
|
||||
@@ -11,7 +16,12 @@ const parseNotificationList = (notificationList) => {
|
||||
});
|
||||
return { today, earlier };
|
||||
};
|
||||
export async function getNotifications(notificationType, notificationCount) {
|
||||
|
||||
export async function getNotifications(appName, notificationCount, page, pageSize) {
|
||||
const params = snakeCaseObject({ page, pageSize });
|
||||
|
||||
let { data } = await getAuthenticatedHttpClient().get(getNotificationsApiUrl(), { params });
|
||||
|
||||
const notificationData = [
|
||||
{
|
||||
type: 'post',
|
||||
@@ -194,8 +204,7 @@ export async function getNotifications(notificationType, notificationCount) {
|
||||
];
|
||||
|
||||
const { today, earlier } = parseNotificationList(camelCaseObject(notificationData));
|
||||
|
||||
const data = {
|
||||
data = {
|
||||
discussions: {
|
||||
TODAY: today,
|
||||
EARLIER: earlier,
|
||||
@@ -205,7 +214,8 @@ export async function getNotifications(notificationType, notificationCount) {
|
||||
EARLIER: earlier,
|
||||
},
|
||||
};
|
||||
const notifications = data[notificationType];
|
||||
|
||||
const notifications = data[appName];
|
||||
const { TODAY = [], EARLIER = [] } = notifications || [];
|
||||
let todayNotifications = TODAY;
|
||||
let earlierNotifications = [];
|
||||
@@ -225,7 +235,8 @@ export async function getNotifications(notificationType, notificationCount) {
|
||||
}
|
||||
|
||||
export async function getNotificationCounts() {
|
||||
const data = {
|
||||
let { data } = await getAuthenticatedHttpClient().get(getNotificationsCountApiUrl());
|
||||
data = {
|
||||
count: 25,
|
||||
count_by_app_name: {
|
||||
reminders: 10,
|
||||
@@ -236,3 +247,9 @@ export async function getNotificationCounts() {
|
||||
};
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function markNotificationSeen(appName) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.put(`${markNotificationsSeenApiUrl(appName)}`);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const getNotificationStatus = () => state => state.notifications.notificationStatus;
|
||||
export const getNotificationTotalUnseenCounts = () => state => state.notifications.totalUnseenCounts;
|
||||
export const getNotifications = () => state => state.notifications.notifications;
|
||||
export const getSelectedNotificationType = () => state => state.notifications.notificationType;
|
||||
export const getSelectedAppName = () => state => state.notifications.appName;
|
||||
|
||||
@@ -12,19 +12,19 @@ const slice = createSlice({
|
||||
notificationStatus: 'idle',
|
||||
notifications: {},
|
||||
totalUnseenCounts: {},
|
||||
notificationType: '',
|
||||
appName: '',
|
||||
},
|
||||
reducers: {
|
||||
fetchNotificationDenied: (state, { payload }) => {
|
||||
state.notificationType = payload.notificationType;
|
||||
state.appName = payload.appName;
|
||||
state.notificationStatus = DENIED;
|
||||
},
|
||||
fetchNotificationFailure: (state, { payload }) => {
|
||||
state.notificationType = payload.notificationType;
|
||||
state.appName = payload.appName;
|
||||
state.notificationStatus = FAILED;
|
||||
},
|
||||
fetchNotificationRequest: (state, { payload }) => {
|
||||
state.notificationType = payload.notificationType;
|
||||
state.appName = payload.appName;
|
||||
state.notificationStatus = LOADING;
|
||||
},
|
||||
fetchNotificationSuccess: (state, { payload }) => {
|
||||
@@ -45,6 +45,18 @@ const slice = createSlice({
|
||||
state.notificationStatus = LOADED;
|
||||
state.totalUnseenCounts = payload;
|
||||
},
|
||||
markNotificationsAsSeenRequest: (state) => {
|
||||
state.notificationStatus = LOADING;
|
||||
},
|
||||
markNotificationsAsSeenSuccess: (state) => {
|
||||
state.notificationStatus = LOADED;
|
||||
},
|
||||
markNotificationsAsSeenDenied: (state) => {
|
||||
state.notificationStatus = DENIED;
|
||||
},
|
||||
markNotificationsAsSeenFailure: (state) => {
|
||||
state.notificationStatus = FAILED;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -57,6 +69,10 @@ export const {
|
||||
fetchNotificationsCountFailure,
|
||||
fetchNotificationsCountRequest,
|
||||
fetchNotificationsCountSuccess,
|
||||
markNotificationsAsSeenRequest,
|
||||
markNotificationsAsSeenSuccess,
|
||||
markNotificationsAsSeenFailure,
|
||||
markNotificationsAsSeenDenied,
|
||||
} = slice.actions;
|
||||
|
||||
export const notificationsReducer = slice.reducer;
|
||||
|
||||
@@ -5,20 +5,26 @@ import {
|
||||
fetchNotificationsCountFailure,
|
||||
fetchNotificationsCountRequest,
|
||||
fetchNotificationsCountSuccess,
|
||||
markNotificationsAsSeenRequest,
|
||||
markNotificationsAsSeenSuccess,
|
||||
markNotificationsAsSeenFailure,
|
||||
} from './slice';
|
||||
import {
|
||||
getNotifications,
|
||||
getNotificationCounts,
|
||||
markNotificationSeen,
|
||||
} from './api';
|
||||
|
||||
export const fetchNotificationList = ({ notificationType, notificationCount }) => (
|
||||
export const fetchNotificationList = ({
|
||||
appName, notificationCount, page, pageSize,
|
||||
}) => (
|
||||
async (dispatch) => {
|
||||
try {
|
||||
dispatch(fetchNotificationRequest({ notificationType }));
|
||||
const data = await getNotifications(notificationType, notificationCount);
|
||||
dispatch(fetchNotificationRequest({ appName }));
|
||||
const data = await getNotifications(appName, notificationCount, page, pageSize);
|
||||
dispatch(fetchNotificationSuccess(data));
|
||||
} catch (errors) {
|
||||
dispatch(fetchNotificationFailure({ notificationType }));
|
||||
dispatch(fetchNotificationFailure({ appName }));
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -34,3 +40,15 @@ export const fetchNotificationsCountsList = () => (
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const markNotificationsAsSeen = (appName) => (
|
||||
async (dispatch) => {
|
||||
try {
|
||||
dispatch(markNotificationsAsSeenRequest({ appName }));
|
||||
const data = await markNotificationSeen(appName);
|
||||
dispatch(markNotificationsAsSeenSuccess(data));
|
||||
} catch (errors) {
|
||||
dispatch(markNotificationsAsSeenFailure({ appName }));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -128,7 +128,6 @@ $white: #fff;
|
||||
.font-size-12{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.font-size-9{
|
||||
font-size: 9px;
|
||||
}
|
||||
@@ -155,7 +154,7 @@ $white: #fff;
|
||||
.expandable{
|
||||
position: relative !important;
|
||||
margin-left: 4px;
|
||||
padding: 2px 6px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 10rem;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user