diff --git a/web/core/components/workspace-notifications/root.tsx b/web/core/components/workspace-notifications/root.tsx index fa17060d59..1c38678564 100644 --- a/web/core/components/workspace-notifications/root.tsx +++ b/web/core/components/workspace-notifications/root.tsx @@ -1,6 +1,6 @@ "use client"; - import { FC, useCallback } from "react"; + import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // components @@ -19,8 +19,10 @@ import { cn } from "@/helpers/common.helper"; import { getNumberCount } from "@/helpers/string.helper"; // hooks import { useWorkspace, useWorkspaceNotifications } from "@/hooks/store"; +import { useFlag } from "@/plane-web/hooks/store"; -import { NotificationCardListRoot } from "@/plane-web/components/workspace-notifications"; +import { NotificationCardListRoot as NotificationCardListRootCe } from "ce/components/workspace-notifications"; +import { NotificationCardListRoot as NotificationCardListRootEe } from "ee/components/workspace-notifications"; export const NotificationsSidebarRoot: FC = observer(() => { const { workspaceSlug } = useParams(); @@ -47,16 +49,18 @@ export const NotificationsSidebarRoot: FC = observer(() => { [currentNotificationTab, setCurrentNotificationTab] ); + const isFeatureEnabled = useFlag(workspaceSlug.toString(), "INBOX_STACKING"); + if (!workspaceSlug || !workspace) return <>; return (
-
+
@@ -100,7 +104,11 @@ export const NotificationsSidebarRoot: FC = observer(() => { <> {notificationIds && notificationIds.length > 0 ? ( - + {isFeatureEnabled ? ( + + ) : ( + + )} ) : (
diff --git a/web/ee/components/workspace-notifications/index.ts b/web/ee/components/workspace-notifications/index.ts index ff8925d4e1..5f9897922a 100644 --- a/web/ee/components/workspace-notifications/index.ts +++ b/web/ee/components/workspace-notifications/index.ts @@ -1,2 +1 @@ -export * from "./root"; export * from "./notification-card"; diff --git a/web/ee/components/workspace-notifications/notification-card/item.tsx b/web/ee/components/workspace-notifications/notification-card/item.tsx index a418d5fce2..8c7308e354 100644 --- a/web/ee/components/workspace-notifications/notification-card/item.tsx +++ b/web/ee/components/workspace-notifications/notification-card/item.tsx @@ -1,3 +1,5 @@ +"use client"; + import { FC, useMemo, useState, Fragment } from "react"; import { uniq } from "lodash"; import orderBy from "lodash/orderBy"; @@ -27,25 +29,29 @@ export const NotificationItem: FC = observer((props) => { const [isSnoozeStateModalOpen, setIsSnoozeStateModalOpen] = useState(false); const [customSnoozeModal, setCustomSnoozeModal] = useState(false); //hooks - const { groupedNotificationsByIssueId, markNotificationGroupRead, hasInboxIssue, setCurrentSelectedNotificationId } = - useWorkspaceNotifications(); + const { + getNotificationsGroupedByIssue, + markBulkNotificationsAsRead, + containsInboxIssue, + setCurrentSelectedNotificationId, + } = useWorkspaceNotifications(); const { getIsIssuePeeked, setPeekIssue } = useIssueDetail(); //derived values - const groupedNotifications = groupedNotificationsByIssueId(workspaceId); - const notificationGroup = groupedNotifications[issueId]; - const issue = notificationGroup[0].data?.issue; - const unreadCount = notificationGroup.filter((e) => !e.read_at).length; - const projectId = notificationGroup[0].project; + const groupedNotifications = getNotificationsGroupedByIssue(workspaceId); + const notificationList = groupedNotifications[issueId]; + const issue = notificationList[0].data?.issue; + const unreadCount = notificationList.filter((e) => !e.read_at).length; + const projectId = notificationList[0].project; const authorIds: string[] = uniq( - notificationGroup.map((e) => e.triggered_by).filter((id): id is string => id != undefined && id != null) + notificationList.map((e) => e.triggered_by).filter((id): id is string => id != undefined && id != null) ); const latestNotificationTime = useMemo(() => { - const latestNotification = orderBy(notificationGroup, (n) => convertToEpoch(n.created_at), "desc")[0]; + const latestNotification = orderBy(notificationList, (n) => convertToEpoch(n.created_at), "desc")[0]; if (latestNotification.created_at) return calculateTimeAgo(latestNotification.created_at); - }, [notificationGroup]); + }, [notificationList]); const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: "right-start", @@ -54,18 +60,18 @@ export const NotificationItem: FC = observer((props) => { const handleNotificationIssuePeekOverview = async () => { if (workspaceSlug && projectId && issueId && !isSnoozeStateModalOpen && !customSnoozeModal) { setPeekIssue(undefined); - setCurrentSelectedNotificationId(notificationGroup[0].id); + setCurrentSelectedNotificationId(notificationList[0].id); // make the notification as read if (unreadCount > 0) { try { - await markNotificationGroupRead(notificationGroup, workspaceSlug); + await markBulkNotificationsAsRead(notificationList, workspaceSlug); } catch (error) { console.error(error); } } - if (!hasInboxIssue(notificationGroup)) { + if (!containsInboxIssue(notificationList)) { if (!getIsIssuePeeked(issueId)) setPeekIssue({ workspaceSlug, projectId, issueId }); } } @@ -74,7 +80,7 @@ export const NotificationItem: FC = observer((props) => { // states const [showPreview, setShowPreview] = useState(false); - if (!notificationGroup || !issue || !issue.id || !authorIds || !projectId) return <>; + if (!notificationList || !issue || !issue.id || !authorIds || !projectId) return <>; return ( @@ -107,7 +113,7 @@ export const NotificationItem: FC = observer((props) => { workspaceSlug={workspaceSlug} issueId={issueId} unreadCount={unreadCount} - notificationGroup={notificationGroup} + notificationList={notificationList} isSnoozeStateModalOpen={isSnoozeStateModalOpen} setIsSnoozeStateModalOpen={setIsSnoozeStateModalOpen} customSnoozeModal={customSnoozeModal} @@ -147,7 +153,7 @@ export const NotificationItem: FC = observer((props) => {
= observer((props) => { - const { workspaceSlug, notificationGroup, issueId } = props; + const { workspaceSlug, notificationList, issueId } = props; // hooks const { captureEvent } = useEventTracker(); const { currentNotificationTab } = useWorkspaceNotifications(); //derived values - const archivedCount = notificationGroup.filter(n=>!!n.archived_at).length; + const archivedCount = notificationList.filter((n) => !!n.archived_at).length; - const { archiveNotificationGroup, unArchiveNotificationGroup } = useWorkspaceNotifications() + const { archiveNotificationList, unArchiveNotificationList } = useWorkspaceNotifications(); const handleNotificationUpdate = async () => { try { - const request = archivedCount > 0 ? unArchiveNotificationGroup : archiveNotificationGroup; - await request(notificationGroup,workspaceSlug); + const request = archivedCount > 0 ? unArchiveNotificationList : archiveNotificationList; + await request(notificationList, workspaceSlug); captureEvent(NOTIFICATION_ARCHIVED, { issue_id: issueId, tab: currentNotificationTab, diff --git a/web/ee/components/workspace-notifications/notification-card/options/read.tsx b/web/ee/components/workspace-notifications/notification-card/options/read.tsx index 65d9b5c663..38c27ce571 100644 --- a/web/ee/components/workspace-notifications/notification-card/options/read.tsx +++ b/web/ee/components/workspace-notifications/notification-card/options/read.tsx @@ -15,23 +15,23 @@ import { INotification } from "@/store/notifications/notification"; type TNotificationItemReadOption = { workspaceSlug: string; - notificationGroup: INotification[]; + notificationList: INotification[]; issueId: string; - unreadCount: number + unreadCount: number; }; export const NotificationItemReadOption: FC = observer((props) => { - const { workspaceSlug, notificationGroup, issueId, unreadCount } = props; + const { workspaceSlug, notificationList, issueId, unreadCount } = props; // hooks const { captureEvent } = useEventTracker(); const { currentNotificationTab } = useWorkspaceNotifications(); - const { markNotificationGroupRead, markNotificationGroupUnRead } = useWorkspaceNotifications(); + const { markBulkNotificationsAsRead, markBulkNotificationsAsUnread } = useWorkspaceNotifications(); const handleNotificationUpdate = async () => { try { - const request = unreadCount === 0 ? markNotificationGroupUnRead : markNotificationGroupRead; - await request(notificationGroup,workspaceSlug); + const request = unreadCount === 0 ? markBulkNotificationsAsUnread : markBulkNotificationsAsRead; + await request(notificationList, workspaceSlug); captureEvent(NOTIFICATIONS_READ, { issue_id: issueId, tab: currentNotificationTab, diff --git a/web/ee/components/workspace-notifications/notification-card/options/root.tsx b/web/ee/components/workspace-notifications/notification-card/options/root.tsx index d2b6836199..5db01e3ac5 100644 --- a/web/ee/components/workspace-notifications/notification-card/options/root.tsx +++ b/web/ee/components/workspace-notifications/notification-card/options/root.tsx @@ -6,7 +6,6 @@ import { observer } from "mobx-react"; // helpers import { cn } from "@/helpers/common.helper"; // hooks -import { useNotification } from "@/hooks/store"; import { NotificationItemReadOption, NotificationItemArchiveOption, @@ -16,7 +15,7 @@ import { INotification } from "@/store/notifications/notification"; type TNotificationOption = { workspaceSlug: string; - notificationGroup: INotification[]; + notificationList: INotification[]; issueId: string; unreadCount: number; isSnoozeStateModalOpen: boolean; @@ -28,7 +27,7 @@ type TNotificationOption = { export const NotificationOption: FC = observer((props) => { const { workspaceSlug, - notificationGroup, + notificationList, issueId, unreadCount, isSnoozeStateModalOpen, @@ -43,7 +42,7 @@ export const NotificationOption: FC = observer((props) => { {/* read */} @@ -51,14 +50,14 @@ export const NotificationOption: FC = observer((props) => { {/* archive */} {/* snooze notification */} >; customSnoozeModal: boolean; setCustomSnoozeModal: Dispatch>; }; export const NotificationItemSnoozeOption: FC = observer((props) => { - const { workspaceSlug, notificationGroup, setIsSnoozeStateModalOpen, customSnoozeModal, setCustomSnoozeModal } = - props; + const { workspaceSlug, notificationList, setIsSnoozeStateModalOpen, customSnoozeModal, setCustomSnoozeModal } = props; // hooks const { isMobile } = usePlatformOS(); - const { snoozeNotificationGroup, unSnoozeNotificationGroup } = useWorkspaceNotifications(); + const { snoozeNotificationList, unSnoozeNotificationList } = useWorkspaceNotifications(); - const snoozedCount = notificationGroup.filter((n) => !!n.snoozed_till).length; + const snoozedCount = notificationList.filter((n) => !!n.snoozed_till).length; const handleNotificationSnoozeDate = async (snoozeTill: Date | undefined) => { if (snoozedCount === 0 && snoozeTill) { try { - await snoozeNotificationGroup(notificationGroup, workspaceSlug, snoozeTill); + await snoozeNotificationList(notificationList, workspaceSlug, snoozeTill); setToast({ title: "Success!", message: "Notification(s) snoozed successfully", @@ -47,7 +46,7 @@ export const NotificationItemSnoozeOption: FC = o } } else { try { - await unSnoozeNotificationGroup(notificationGroup, workspaceSlug); + await unSnoozeNotificationList(notificationList, workspaceSlug); setToast({ title: "Success!", message: "Notification(s) un snoozed successfully", diff --git a/web/ee/components/workspace-notifications/notification-card/preview/acitvity-block.tsx b/web/ee/components/workspace-notifications/notification-card/preview/acitvity-block.tsx index 58e8bed866..57b62e0c84 100644 --- a/web/ee/components/workspace-notifications/notification-card/preview/acitvity-block.tsx +++ b/web/ee/components/workspace-notifications/notification-card/preview/acitvity-block.tsx @@ -30,28 +30,29 @@ type TIssueActivityBlock = { triggeredBy: IUserLite | undefined; }; +export const acitvityIconsMap: Record = { + state: