diff --git a/apps/client/src/components/layouts/global/aside.tsx b/apps/client/src/components/layouts/global/aside.tsx index 735ac21d..1d6d3f41 100644 --- a/apps/client/src/components/layouts/global/aside.tsx +++ b/apps/client/src/components/layouts/global/aside.tsx @@ -38,13 +38,17 @@ export default function Aside() { {t(title)} - -
{component}
-
+ {tab === "comments" ? ( + + ) : ( + +
{component}
+
+ )} )} diff --git a/apps/client/src/features/comment/components/comment-list-with-tabs.tsx b/apps/client/src/features/comment/components/comment-list-with-tabs.tsx index 86fb1120..cef83e85 100644 --- a/apps/client/src/features/comment/components/comment-list-with-tabs.tsx +++ b/apps/client/src/features/comment/components/comment-list-with-tabs.tsx @@ -1,6 +1,6 @@ import React, { useState, useRef, useCallback, memo, useMemo } from "react"; import { useParams } from "react-router-dom"; -import { Divider, Paper, Tabs, Badge, Text } from "@mantine/core"; +import { Divider, Paper, Tabs, Badge, Text, ScrollArea } from "@mantine/core"; import CommentListItem from "@/features/comment/components/comment-list-item"; import { useCommentsQuery, @@ -43,7 +43,7 @@ function CommentListWithTabs() { const canComment: boolean = spaceAbility.can( SpaceCaslAction.Manage, - SpaceCaslSubject.Page, + SpaceCaslSubject.Page ); // Separate active and resolved comments @@ -53,14 +53,14 @@ function CommentListWithTabs() { } const parentComments = comments.items.filter( - (comment: IComment) => comment.parentCommentId === null, + (comment: IComment) => comment.parentCommentId === null ); const active = parentComments.filter( - (comment: IComment) => !comment.resolvedAt, + (comment: IComment) => !comment.resolvedAt ); const resolved = parentComments.filter( - (comment: IComment) => comment.resolvedAt, + (comment: IComment) => comment.resolvedAt ); return { activeComments: active, resolvedComments: resolved }; @@ -88,7 +88,7 @@ function CommentListWithTabs() { setIsLoading(false); } }, - [createCommentMutation, page?.id], + [createCommentMutation, page?.id] ); const renderComments = useCallback( @@ -128,7 +128,7 @@ function CommentListWithTabs() { )} ), - [comments, handleAddReply, isLoading], + [comments, handleAddReply, isLoading] ); if (isCommentsLoading) { @@ -141,66 +141,78 @@ function CommentListWithTabs() { const totalComments = activeComments.length + resolvedComments.length; - if (totalComments === 0) { - return <>{t("No comments yet.")}; - } - // If not cloud/enterprise, show simple list without tabs if (!isCloudEE) { + if (totalComments === 0) { + return <>{t("No comments yet.")}; + } + return ( -
- {comments?.items - .filter((comment: IComment) => comment.parentCommentId === null) - .map(renderComments)} -
+ +
+ {comments?.items + .filter((comment: IComment) => comment.parentCommentId === null) + .map(renderComments)} +
+
); } return ( - - - - {activeComments.length} - - } - > - {t("Open")} - - - {resolvedComments.length} - - } - > - {t("Resolved")} - - +
+ + + + {activeComments.length} + + } + > + {t("Open")} + + + {resolvedComments.length} + + } + > + {t("Resolved")} + + - - {activeComments.length === 0 ? ( - - {t("No open comments.")} - - ) : ( - activeComments.map(renderComments) - )} - + +
+ + {activeComments.length === 0 ? ( + + {t("No open comments.")} + + ) : ( + activeComments.map(renderComments) + )} + - - {resolvedComments.length === 0 ? ( - - {t("No resolved comments.")} - - ) : ( - resolvedComments.map(renderComments) - )} - - + + {resolvedComments.length === 0 ? ( + + {t("No resolved comments.")} + + ) : ( + resolvedComments.map(renderComments) + )} + +
+
+
+
); } @@ -219,9 +231,9 @@ const ChildComments = ({ const getChildComments = useCallback( (parentId: string) => comments.items.filter( - (comment: IComment) => comment.parentCommentId === parentId, + (comment: IComment) => comment.parentCommentId === parentId ), - [comments.items], + [comments.items] ); return ( diff --git a/packages/editor-ext/src/lib/comment/comment.ts b/packages/editor-ext/src/lib/comment/comment.ts index 9b45c6ff..1c40809f 100644 --- a/packages/editor-ext/src/lib/comment/comment.ts +++ b/packages/editor-ext/src/lib/comment/comment.ts @@ -1,5 +1,6 @@ import { Mark, mergeAttributes } from "@tiptap/core"; import { commentDecoration } from "./comment-decoration"; +import { Plugin } from "@tiptap/pm/state"; export interface ICommentOptions { HTMLAttributes: Record; @@ -76,9 +77,9 @@ export const Comment = Mark.create({ const element = el as HTMLSpanElement; const commentId = element.getAttribute("data-comment-id")?.trim(); const resolved = element.hasAttribute("data-resolved"); - + if (!commentId) return false; - + return { commentId, resolved, @@ -123,7 +124,7 @@ export const Comment = Mark.create({ const commentMark = node.marks.find( (mark) => mark.type.name === this.name && - mark.attrs.commentId === commentId, + mark.attrs.commentId === commentId ); if (commentMark) { @@ -145,16 +146,20 @@ export const Comment = Mark.create({ const commentMark = node.marks.find( (mark) => mark.type.name === this.name && - mark.attrs.commentId === commentId, + mark.attrs.commentId === commentId ); if (commentMark) { // Remove the existing mark and add a new one with updated resolved state tr = tr.removeMark(from, to, commentMark); - tr = tr.addMark(from, to, this.type.create({ - commentId: commentMark.attrs.commentId, - resolved: resolved, - })); + tr = tr.addMark( + from, + to, + this.type.create({ + commentId: commentMark.attrs.commentId, + resolved: resolved, + }) + ); } }); @@ -173,7 +178,7 @@ export const Comment = Mark.create({ return [ "span", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { - class: resolved ? 'comment-mark resolved' : 'comment-mark', + class: resolved ? "comment-mark resolved" : "comment-mark", "data-comment-id": commentId, ...(resolved && { "data-resolved": "true" }), }), @@ -184,12 +189,12 @@ export const Comment = Mark.create({ const elem = document.createElement("span"); Object.entries( - mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes) ).forEach(([attr, val]) => elem.setAttribute(attr, val)); // Add resolved class if the comment is resolved if (resolved) { - elem.classList.add('resolved'); + elem.classList.add("resolved"); } elem.addEventListener("click", (e) => { @@ -208,9 +213,7 @@ export const Comment = Mark.create({ return elem; }, - // @ts-ignore addProseMirrorPlugins(): Plugin[] { - // @ts-ignore return [commentDecoration()]; }, });