feat: mark all as read (#1982)

This commit is contained in:
Aaryan Khandelwal 2023-08-28 13:26:38 +05:30 committed by GitHub
parent 47abe9db5e
commit a1acd2772e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 16 deletions

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
// components // components
import { Icon, Tooltip } from "components/ui"; import { CustomMenu, Icon, Tooltip } from "components/ui";
// helpers // helpers
import { getNumberCount } from "helpers/string.helper"; import { getNumberCount } from "helpers/string.helper";
@ -21,6 +21,7 @@ type NotificationHeaderProps = {
setArchived: React.Dispatch<React.SetStateAction<boolean>>; setArchived: React.Dispatch<React.SetStateAction<boolean>>;
setReadNotification: React.Dispatch<React.SetStateAction<boolean>>; setReadNotification: React.Dispatch<React.SetStateAction<boolean>>;
setSelectedTab: React.Dispatch<React.SetStateAction<NotificationType>>; setSelectedTab: React.Dispatch<React.SetStateAction<NotificationType>>;
markAllNotificationsAsRead: () => Promise<void>;
}; };
export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) => { export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) => {
@ -37,6 +38,7 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
setArchived, setArchived,
setReadNotification, setReadNotification,
setSelectedTab, setSelectedTab,
markAllNotificationsAsRead,
} = props; } = props;
const notificationTabs: Array<{ const notificationTabs: Array<{
@ -88,33 +90,51 @@ export const NotificationHeader: React.FC<NotificationHeaderProps> = (props) =>
<Icon iconName="filter_list" /> <Icon iconName="filter_list" />
</button> </button>
</Tooltip> </Tooltip>
<Tooltip tooltipContent="Snoozed notifications"> <CustomMenu
<button customButton={
type="button" <div className="grid place-items-center ">
<Icon iconName="more_vert" />
</div>
}
>
<CustomMenu.MenuItem renderAs="button" onClick={markAllNotificationsAsRead}>
<div className="flex items-center gap-2">
<Icon iconName="done_all" />
Mark all as read
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
renderAs="button"
onClick={() => { onClick={() => {
setArchived(false); setArchived(false);
setReadNotification(false); setReadNotification(false);
setSnoozed((prev) => !prev); setSnoozed((prev) => !prev);
}} }}
> >
<Icon iconName="schedule" /> <div className="flex items-center gap-2">
</button> <Icon iconName="schedule" />
</Tooltip> Show snoozed
<Tooltip tooltipContent="Archived notifications"> </div>
<button </CustomMenu.MenuItem>
type="button" <CustomMenu.MenuItem
renderAs="button"
onClick={() => { onClick={() => {
setSnoozed(false); setSnoozed(false);
setReadNotification(false); setReadNotification(false);
setArchived((prev) => !prev); setArchived((prev) => !prev);
}} }}
> >
<Icon iconName="archive" /> <div className="flex items-center gap-2">
<Icon iconName="archive" />
Show archived
</div>
</CustomMenu.MenuItem>
</CustomMenu>
<Tooltip tooltipContent="Close">
<button type="button" onClick={() => closePopover()}>
<Icon iconName="close" />
</button> </button>
</Tooltip> </Tooltip>
<button type="button" onClick={() => closePopover()}>
<Icon iconName="close" />
</button>
</div> </div>
</div> </div>
<div className="border-b border-custom-border-300 w-full px-5 mt-5"> <div className="border-b border-custom-border-300 w-full px-5 mt-5">

View File

@ -51,6 +51,7 @@ export const NotificationPopover = () => {
hasMore, hasMore,
isRefreshing, isRefreshing,
setFetchNotifications, setFetchNotifications,
markAllNotificationsAsRead,
} = useUserNotification(); } = useUserNotification();
// theme context // theme context
@ -112,7 +113,7 @@ export const NotificationPopover = () => {
leaveFrom="opacity-100 translate-y-0" leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1" leaveTo="opacity-0 translate-y-1"
> >
<Popover.Panel className="absolute bg-custom-background-100 flex flex-col left-0 md:left-full ml-8 z-10 -top-44 md:w-[36rem] w-[20rem] h-[75vh] border border-custom-border-300 shadow-lg rounded-xl"> <Popover.Panel className="absolute bg-custom-background-100 flex flex-col left-0 md:left-full ml-8 z-10 -top-36 md:w-[36rem] w-[20rem] h-[50vh] border border-custom-border-300 shadow-lg rounded-xl">
<NotificationHeader <NotificationHeader
notificationCount={notificationCount} notificationCount={notificationCount}
notificationMutate={notificationMutate} notificationMutate={notificationMutate}
@ -126,6 +127,7 @@ export const NotificationPopover = () => {
setArchived={setArchived} setArchived={setArchived}
setReadNotification={setReadNotification} setReadNotification={setReadNotification}
setSelectedTab={setSelectedTab} setSelectedTab={setSelectedTab}
markAllNotificationsAsRead={markAllNotificationsAsRead}
/> />
{notifications ? ( {notifications ? (

View File

@ -9,11 +9,14 @@ import useSWRInfinite from "swr/infinite";
// services // services
import userNotificationServices from "services/notifications.service"; import userNotificationServices from "services/notifications.service";
// hooks
import useToast from "./use-toast";
// fetch-keys // fetch-keys
import { UNREAD_NOTIFICATIONS_COUNT, getPaginatedNotificationKey } from "constants/fetch-keys"; import { UNREAD_NOTIFICATIONS_COUNT, getPaginatedNotificationKey } from "constants/fetch-keys";
// type // type
import type { NotificationType, NotificationCount } from "types"; import type { NotificationType, NotificationCount, IMarkAllAsReadPayload } from "types";
const PER_PAGE = 30; const PER_PAGE = 30;
@ -21,6 +24,8 @@ const useUserNotification = () => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
const { setToastAlert } = useToast();
const [snoozed, setSnoozed] = useState<boolean>(false); const [snoozed, setSnoozed] = useState<boolean>(false);
const [archived, setArchived] = useState<boolean>(false); const [archived, setArchived] = useState<boolean>(false);
const [readNotification, setReadNotification] = useState<boolean>(false); const [readNotification, setReadNotification] = useState<boolean>(false);
@ -274,6 +279,29 @@ const useUserNotification = () => {
} }
}; };
const markAllNotificationsAsRead = async () => {
if (!workspaceSlug) return;
let markAsReadParams: IMarkAllAsReadPayload;
if (snoozed) markAsReadParams = { archived: false, snoozed: true };
else if (archived) markAsReadParams = { archived: true, snoozed: false };
else markAsReadParams = { archived: false, snoozed: false, type: selectedTab };
await userNotificationServices
.markAllNotificationsAsRead(workspaceSlug.toString(), markAsReadParams)
.catch(() => {
setToastAlert({
type: "error",
title: "Error!",
message: "Something went wrong. Please try again.",
});
})
.finally(() => {
notificationMutate();
});
};
return { return {
notifications, notifications,
notificationMutate, notificationMutate,
@ -304,6 +332,7 @@ const useUserNotification = () => {
isRefreshing, isRefreshing,
setFetchNotifications, setFetchNotifications,
markNotificationAsRead, markNotificationAsRead,
markAllNotificationsAsRead,
}; };
}; };

View File

@ -9,6 +9,7 @@ import type {
INotificationParams, INotificationParams,
NotificationCount, NotificationCount,
PaginatedUserNotification, PaginatedUserNotification,
IMarkAllAsReadPayload,
} from "types"; } from "types";
class UserNotificationsServices extends APIService { class UserNotificationsServices extends APIService {
@ -172,6 +173,19 @@ class UserNotificationsServices extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
} }
async markAllNotificationsAsRead(
workspaceSlug: string,
payload: IMarkAllAsReadPayload
): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/users/notifications/mark-all-read/`, {
...payload,
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
} }
const userNotificationServices = new UserNotificationsServices(); const userNotificationServices = new UserNotificationsServices();

View File

@ -71,3 +71,9 @@ export type NotificationCount = {
my_issues: number; my_issues: number;
watching_issues: number; watching_issues: number;
}; };
export interface IMarkAllAsReadPayload {
archived?: boolean;
snoozed?: boolean;
type?: NotificationType;
}