From 6d635d867e522591af47967de8bd3bbf1f9bb77b Mon Sep 17 00:00:00 2001
From: gakshita
Date: Mon, 17 Mar 2025 13:59:11 +0530
Subject: [PATCH 01/11] fix: comments refactor
---
.../src/issues/activity/issue_comment.d.ts | 26 +++
web/ce/components/comments/comment-block.tsx | 74 ++++++++
web/ce/components/comments/index.ts | 1 +
.../comments/comment-card.tsx | 95 ++++-------
.../comments/comment-create.tsx | 53 +++---
.../components/comments/comment-reaction.tsx | 67 ++++++++
web/core/components/comments/comments.tsx | 56 +++++++
web/core/components/comments/index.ts | 1 +
.../lite-text-editor/lite-text-editor.tsx | 60 ++++---
.../lite-text-read-only-editor.tsx | 2 +-
.../issue-activity/activity-comment-root.tsx | 15 +-
.../actions/helpers/activity-block.tsx | 2 +-
.../issue-activity/comments/comment-block.tsx | 70 --------
.../issue-activity/comments/index.ts | 4 -
.../issue-activity/comments/root.tsx | 63 -------
.../issue-detail/issue-activity/helper.tsx | 158 ++++++++++++++++++
.../issue-detail/issue-activity/index.ts | 3 -
.../issue-detail/issue-activity/root.tsx | 99 ++---------
.../issue-details/comment_reaction.store.ts | 4 +-
web/ee/components/comments/index.ts | 1 +
20 files changed, 494 insertions(+), 360 deletions(-)
create mode 100644 web/ce/components/comments/comment-block.tsx
create mode 100644 web/ce/components/comments/index.ts
rename web/core/components/{issues/issue-detail/issue-activity => }/comments/comment-card.tsx (74%)
rename web/core/components/{issues/issue-detail/issue-activity => }/comments/comment-create.tsx (74%)
create mode 100644 web/core/components/comments/comment-reaction.tsx
create mode 100644 web/core/components/comments/comments.tsx
create mode 100644 web/core/components/comments/index.ts
delete mode 100644 web/core/components/issues/issue-detail/issue-activity/comments/comment-block.tsx
delete mode 100644 web/core/components/issues/issue-detail/issue-activity/comments/index.ts
delete mode 100644 web/core/components/issues/issue-detail/issue-activity/comments/root.tsx
create mode 100644 web/core/components/issues/issue-detail/issue-activity/helper.tsx
create mode 100644 web/ee/components/comments/index.ts
diff --git a/packages/types/src/issues/activity/issue_comment.d.ts b/packages/types/src/issues/activity/issue_comment.d.ts
index aef5134c674..95be9a7d449 100644
--- a/packages/types/src/issues/activity/issue_comment.d.ts
+++ b/packages/types/src/issues/activity/issue_comment.d.ts
@@ -5,7 +5,15 @@ import {
TIssueActivityUserDetail,
} from "./base";
import { EIssueCommentAccessSpecifier } from "../../enums";
+import { TFileSignedURLResponse } from "../../file";
+import { IUserLite } from "../../users";
+export type TCommentReaction = {
+ id: string;
+ reaction: string;
+ actor: string;
+ actor_detail: IUserLite;
+};
export type TIssueComment = {
id: string;
workspace: string;
@@ -17,6 +25,7 @@ export type TIssueComment = {
actor: string;
actor_detail: TIssueActivityUserDetail;
created_at: string;
+ edited_at?: string | undefined;
updated_at: string;
created_by: string | undefined;
updated_by: string | undefined;
@@ -30,6 +39,23 @@ export type TIssueComment = {
access: EIssueCommentAccessSpecifier;
};
+export type TCommentsOperations = {
+ createComment: (data: Partial) => Promise;
+ updateComment: (commentId: string, data: Partial) => Promise;
+ removeComment: (commentId: string) => Promise;
+ uploadCommentAsset: (blockId: string, file: File, commentId?: string) => Promise;
+ addCommentReaction: (commentId: string, reactionEmoji: string) => Promise;
+ deleteCommentReaction: (commentId: string, reactionEmoji: string, userReactions: TCommentReaction[]) => Promise;
+ react: (commentId: string, reactionEmoji: string, userReactions: string[]) => Promise;
+ reactionIds: (commentId: string) =>
+ | {
+ [reaction: string]: string[];
+ }
+ | undefined;
+ userReactions: (commentId: string) => string[] | undefined;
+ getReactionUsers: (reaction: string, reactionIds: Record) => string;
+};
+
export type TIssueCommentMap = {
[issue_id: string]: TIssueComment;
};
diff --git a/web/ce/components/comments/comment-block.tsx b/web/ce/components/comments/comment-block.tsx
new file mode 100644
index 00000000000..c9357d2f7cf
--- /dev/null
+++ b/web/ce/components/comments/comment-block.tsx
@@ -0,0 +1,74 @@
+import { FC, ReactNode, useRef } from "react";
+import { observer } from "mobx-react";
+// plane imports
+import { TIssueComment } from "@plane/types";
+import { Avatar, Tooltip } from "@plane/ui";
+import { calculateTimeAgo, cn, getFileURL, renderFormattedDate } from "@plane/utils";
+// hooks
+import { renderFormattedTime } from "@/helpers/date-time.helper";
+import { useMember } from "@/hooks/store";
+
+type TCommentBlock = {
+ comment: TIssueComment;
+ ends: "top" | "bottom" | undefined;
+ quickActions: ReactNode;
+ children: ReactNode;
+};
+
+export const CommentBlock: FC = observer((props) => {
+ const { comment, ends, quickActions, children } = props;
+ const commentBlockRef = useRef(null);
+ // store hooks
+ const { getUserDetails } = useMember();
+ const userDetails = getUserDetails(comment?.actor);
+
+ if (!comment || !userDetails) return <>>;
+ return (
+
+
+
+
+
+
+
+ {comment?.actor_detail?.is_bot
+ ? comment?.actor_detail?.first_name + " Bot"
+ : comment?.actor_detail?.display_name || userDetails.display_name}
+
+
+ commented{" "}
+
+
+ {calculateTimeAgo(comment.updated_at)}
+ {comment.edited_at && " (edited)"}
+
+
+
+
+
{quickActions}
+
+
{children}
+
+
+ );
+});
diff --git a/web/ce/components/comments/index.ts b/web/ce/components/comments/index.ts
new file mode 100644
index 00000000000..f0ef4e2b691
--- /dev/null
+++ b/web/ce/components/comments/index.ts
@@ -0,0 +1 @@
+export * from "./comment-block";
diff --git a/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx b/web/core/components/comments/comment-card.tsx
similarity index 74%
rename from web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx
rename to web/core/components/comments/comment-card.tsx
index 96f0960b605..2e0a07f037e 100644
--- a/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx
+++ b/web/core/components/comments/comment-card.tsx
@@ -4,66 +4,41 @@ import { FC, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useForm } from "react-hook-form";
import { Check, Globe2, Lock, Pencil, Trash2, X } from "lucide-react";
-// plane constants
+// PLane
import { EIssueCommentAccessSpecifier } from "@plane/constants";
-// plane editor
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
-// plane i18n
import { useTranslation } from "@plane/i18n";
-// plane types
-import { TIssueComment } from "@plane/types";
-// plane ui
+import { TIssueComment, TCommentsOperations } from "@plane/types";
import { CustomMenu } from "@plane/ui";
-// plane utils
-import { cn } from "@plane/utils";
// components
import { LiteTextEditor, LiteTextReadOnlyEditor } from "@/components/editor";
// helpers
import { isCommentEmpty } from "@/helpers/string.helper";
// hooks
-import { useIssueDetail, useUser, useWorkspace } from "@/hooks/store";
-// components
-import { IssueCommentReaction } from "../../reactions/issue-comment";
-import { TActivityOperations } from "../root";
-import { IssueCommentBlock } from "./comment-block";
+import { useUser } from "@/hooks/store";
+//
+import { CommentBlock } from "@/plane-web/components/comments";
+import { CommentReactions } from "./comment-reaction";
-type TIssueCommentCard = {
- projectId: string;
- issueId: string;
+type TCommentCard = {
workspaceSlug: string;
- commentId: string;
- activityOperations: TActivityOperations;
+ comment: TIssueComment | undefined;
+ activityOperations: TCommentsOperations;
ends: "top" | "bottom" | undefined;
showAccessSpecifier?: boolean;
disabled?: boolean;
};
-export const IssueCommentCard: FC = observer((props) => {
- const {
- workspaceSlug,
- projectId,
- issueId,
- commentId,
- activityOperations,
- ends,
- showAccessSpecifier = false,
- disabled = false,
- } = props;
+export const CommentCard: FC = observer((props) => {
+ const { workspaceSlug, comment, activityOperations, ends, showAccessSpecifier = false, disabled = false } = props;
const { t } = useTranslation();
- // states
- const [isEditing, setIsEditing] = useState(false);
// refs
const editorRef = useRef(null);
const showEditorRef = useRef(null);
+ // state
+ const [isEditing, setIsEditing] = useState(false);
// store hooks
- const {
- comment: { getCommentById },
- } = useIssueDetail();
const { data: currentUser } = useUser();
- // derived values
- const comment = getCommentById(commentId);
- const workspaceStore = useWorkspace();
- const workspaceId = workspaceStore.getWorkspaceBySlug(comment?.workspace_detail?.slug as string)?.id as string;
// form info
const {
formState: { isSubmitting },
@@ -75,13 +50,16 @@ export const IssueCommentCard: FC = observer((props) => {
defaultValues: { comment_html: comment?.comment_html },
});
// derived values
+ const workspaceId = comment?.workspace;
const commentHTML = watch("comment_html");
- const isEmpty = isCommentEmpty(commentHTML);
+ const isEmpty = isCommentEmpty(commentHTML ?? undefined);
const isEditorReadyToDiscard = editorRef.current?.isEditorReadyToDiscard();
const isSubmitButtonDisabled = isSubmitting || !isEditorReadyToDiscard;
+ // helpers
const onEnter = async (formData: Partial) => {
if (isSubmitting || !comment) return;
+
setIsEditing(false);
await activityOperations.updateComment(comment.id, formData);
@@ -96,11 +74,11 @@ export const IssueCommentCard: FC = observer((props) => {
}
}, [isEditing, setFocus]);
- if (!comment || !currentUser) return <>>;
+ if (!comment || !currentUser || !workspaceId) return <>>;
return (
-
{!disabled && currentUser?.id === comment.actor && (
@@ -156,8 +134,6 @@ export const IssueCommentCard: FC = observer((props) => {
>
"}
From d82debebb507c26ab1ac077399b3aab60e84c476 Mon Sep 17 00:00:00 2001
From: gakshita
Date: Mon, 17 Mar 2025 15:07:03 +0530
Subject: [PATCH 05/11] fix: edited at
---
web/core/services/issue/issue_comment.service.ts | 2 +-
web/core/store/issue/issue-details/comment.store.ts | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/web/core/services/issue/issue_comment.service.ts b/web/core/services/issue/issue_comment.service.ts
index ccfce8a86c1..8a55f49a1d5 100644
--- a/web/core/services/issue/issue_comment.service.ts
+++ b/web/core/services/issue/issue_comment.service.ts
@@ -63,7 +63,7 @@ export class IssueCommentService extends APIService {
issueId: string,
commentId: string,
data: Partial
- ): Promise {
+ ): Promise {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/comments/${commentId}/`,
data
diff --git a/web/core/store/issue/issue-details/comment.store.ts b/web/core/store/issue/issue-details/comment.store.ts
index b0fba6d3c05..9bb3a7d1937 100644
--- a/web/core/store/issue/issue-details/comment.store.ts
+++ b/web/core/store/issue/issue-details/comment.store.ts
@@ -155,6 +155,11 @@ export class IssueCommentStore implements IIssueCommentStore {
data
);
+ runInAction(() => {
+ set(this.commentMap, [commentId, "updated_at"], response.updated_at);
+ set(this.commentMap, [commentId, "edited_at"], response.edited_at);
+ });
+
return response;
} catch (error) {
this.rootIssueDetail.activity.fetchActivities(workspaceSlug, projectId, issueId);
From 806b96e676b13139cb320472a883f6fdfec8f435 Mon Sep 17 00:00:00 2001
From: gakshita
Date: Tue, 18 Mar 2025 18:07:19 +0530
Subject: [PATCH 06/11] fix: css
---
web/core/components/comments/comments.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/core/components/comments/comments.tsx b/web/core/components/comments/comments.tsx
index 7c95831d794..2dfb6c2abe5 100644
--- a/web/core/components/comments/comments.tsx
+++ b/web/core/components/comments/comments.tsx
@@ -29,7 +29,7 @@ export const CommentsWrapper: FC = observer((props) => {
)}
-
+
{comments?.map((r, index) => {
let comment;
if (typeof r === "string") {
From 39d2c25dab096754e0c1a604c2f6599bcbae9804 Mon Sep 17 00:00:00 2001
From: gakshita
Date: Fri, 21 Mar 2025 18:32:33 +0530
Subject: [PATCH 07/11] fix: added bulk asset upload api
---
web/core/components/comments/comment-create.tsx | 17 +++++++++++------
web/core/services/file.service.ts | 14 ++++++++++++++
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/web/core/components/comments/comment-create.tsx b/web/core/components/comments/comment-create.tsx
index 5d340b164b1..f4fd42e98a0 100644
--- a/web/core/components/comments/comment-create.tsx
+++ b/web/core/components/comments/comment-create.tsx
@@ -55,10 +55,15 @@ export const CommentCreate: FC = observer((props) => {
.createComment(formData)
.then(async () => {
if (uploadedAssetIds.length > 0) {
- // TODO: WHat is this
- // await fileService.updateBulkCommentAssetsUploadStatus(workspaceSlug, entityId, res?.id, {
- // asset_ids: uploadedAssetIds,
- // });
+ if (projectId) {
+ await fileService.updateBulkProjectAssetsUploadStatus(workspaceSlug, projectId.toString(), entityId, {
+ asset_ids: uploadedAssetIds,
+ });
+ } else {
+ await fileService.updateBulkWorkspaceAssetsUploadStatus(workspaceSlug, entityId, {
+ asset_ids: uploadedAssetIds,
+ });
+ }
setUploadedAssetIds([]);
}
})
@@ -90,7 +95,6 @@ export const CommentCreate: FC = observer((props) => {
control={control}
render={({ field: { value, onChange } }) => (