From 81436902a3b8480aacb4321b82905a1ddbba84e3 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Thu, 7 Sep 2023 12:54:30 +0530 Subject: [PATCH] chore: option to switch access of a comment (#2116) --- web/components/inbox/inbox-issue-activity.tsx | 6 +- web/components/issues/activity.tsx | 9 ++- .../issues/comment/comment-card.tsx | 63 +++++++++++++++---- web/components/issues/main-content.tsx | 7 ++- .../issues/peek-overview/issue-activity.tsx | 19 +++--- web/services/issues.service.ts | 2 +- 6 files changed, 75 insertions(+), 31 deletions(-) diff --git a/web/components/inbox/inbox-issue-activity.tsx b/web/components/inbox/inbox-issue-activity.tsx index efa237162..dfcbf0262 100644 --- a/web/components/inbox/inbox-issue-activity.tsx +++ b/web/components/inbox/inbox-issue-activity.tsx @@ -38,7 +38,7 @@ export const InboxIssueActivity: React.FC = ({ issueDetails }) => { : null ); - const handleCommentUpdate = async (comment: IIssueComment) => { + const handleCommentUpdate = async (commentId: string, data: Partial) => { if (!workspaceSlug || !projectId || !inboxIssueId) return; await issuesService @@ -46,8 +46,8 @@ export const InboxIssueActivity: React.FC = ({ issueDetails }) => { workspaceSlug as string, projectId as string, inboxIssueId as string, - comment.id, - comment, + commentId, + data, user ) .then(() => mutateIssueActivity()); diff --git a/web/components/issues/activity.tsx b/web/components/issues/activity.tsx index 5a82907f2..fe322afe9 100644 --- a/web/components/issues/activity.tsx +++ b/web/components/issues/activity.tsx @@ -15,14 +15,16 @@ import { IIssueActivity, IIssueComment } from "types"; type Props = { activity: IIssueActivity[] | undefined; - handleCommentUpdate: (comment: IIssueComment) => Promise; + handleCommentUpdate: (commentId: string, data: Partial) => Promise; handleCommentDelete: (commentId: string) => Promise; + showAccessSpecifier?: boolean; }; export const IssueActivitySection: React.FC = ({ activity, handleCommentUpdate, handleCommentDelete, + showAccessSpecifier = false, }) => { const router = useRouter(); const { workspaceSlug } = router.query; @@ -131,10 +133,11 @@ export const IssueActivitySection: React.FC = ({ return (
); diff --git a/web/components/issues/comment/comment-card.tsx b/web/components/issues/comment/comment-card.tsx index 089aa9db9..3d3e43b39 100644 --- a/web/components/issues/comment/comment-card.tsx +++ b/web/components/issues/comment/comment-card.tsx @@ -7,7 +7,7 @@ import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon } from "@heroicons/rea // hooks import useUser from "hooks/use-user"; // ui -import { CustomMenu } from "components/ui"; +import { CustomMenu, Icon } from "components/ui"; import { CommentReaction } from "components/issues"; import { TipTapEditor } from "components/tiptap"; // helpers @@ -16,17 +16,19 @@ import { timeAgo } from "helpers/date-time.helper"; import type { IIssueComment } from "types"; type Props = { - workspaceSlug: string; comment: IIssueComment; - onSubmit: (comment: IIssueComment) => void; handleCommentDeletion: (comment: string) => void; + onSubmit: (commentId: string, data: Partial) => void; + showAccessSpecifier?: boolean; + workspaceSlug: string; }; export const CommentCard: React.FC = ({ comment, - workspaceSlug, - onSubmit, handleCommentDeletion, + onSubmit, + showAccessSpecifier = false, + workspaceSlug, }) => { const { user } = useUser(); @@ -45,11 +47,11 @@ export const CommentCard: React.FC = ({ defaultValues: comment, }); - const onEnter = (formData: IIssueComment) => { + const onEnter = (formData: Partial) => { if (isSubmitting) return; setIsEditing(false); - onSubmit(formData); + onSubmit(comment.id, formData); editorRef.current?.setEditorValue(formData.comment_html); showEditorRef.current?.setEditorValue(formData.comment_html); @@ -99,7 +101,7 @@ export const CommentCard: React.FC = ({ : comment.actor_detail.display_name}

- Commented {timeAgo(comment.created_at)} + commented {timeAgo(comment.created_at)}

@@ -137,7 +139,15 @@ export const CommentCard: React.FC = ({
-
+
+ {showAccessSpecifier && ( +
+ +
+ )} = ({
{user?.id === comment.actor && ( - setIsEditing(true)}>Edit + setIsEditing(true)} + className="flex items-center gap-1" + > + + Edit comment + + {showAccessSpecifier && ( + <> + {comment.access === "INTERNAL" ? ( + onSubmit(comment.id, { access: "EXTERNAL" })} + className="flex items-center gap-1" + > + + Switch to public comment + + ) : ( + onSubmit(comment.id, { access: "INTERNAL" })} + className="flex items-center gap-1" + > + + Switch to private comment + + )} + + )} { handleCommentDeletion(comment.id); }} + className="flex items-center gap-1" > - Delete + + Delete comment )} diff --git a/web/components/issues/main-content.tsx b/web/components/issues/main-content.tsx index bab384523..b7b154ce2 100644 --- a/web/components/issues/main-content.tsx +++ b/web/components/issues/main-content.tsx @@ -77,7 +77,7 @@ export const IssueMainContent: React.FC = ({ : null ); - const handleCommentUpdate = async (comment: IIssueComment) => { + const handleCommentUpdate = async (commentId: string, data: Partial) => { if (!workspaceSlug || !projectId || !issueId) return; await issuesService @@ -85,8 +85,8 @@ export const IssueMainContent: React.FC = ({ workspaceSlug as string, projectId as string, issueId as string, - comment.id, - comment, + commentId, + data, user ) .then(() => mutateIssueActivity()); @@ -222,6 +222,7 @@ export const IssueMainContent: React.FC = ({ activity={issueActivity} handleCommentUpdate={handleCommentUpdate} handleCommentDelete={handleCommentDelete} + showAccessSpecifier={projectDetails && projectDetails.is_deployed} /> = ({ workspaceSlug, issu const { setToastAlert } = useToast(); const { user } = useUser(); + const { projectDetails } = useProjectDetails(); const { data: issueActivity, mutate: mutateIssueActivity } = useSWR( workspaceSlug && issue ? PROJECT_ISSUES_ACTIVITY(issue.id) : null, @@ -30,18 +32,11 @@ export const PeekOverviewIssueActivity: React.FC = ({ workspaceSlug, issu : null ); - const handleCommentUpdate = async (comment: IIssueComment) => { + const handleCommentUpdate = async (commentId: string, data: Partial) => { if (!workspaceSlug || !issue) return; await issuesService - .patchIssueComment( - workspaceSlug as string, - issue.project, - issue.id, - comment.id, - comment, - user - ) + .patchIssueComment(workspaceSlug as string, issue.project, issue.id, commentId, data, user) .then(() => mutateIssueActivity()); }; @@ -80,9 +75,13 @@ export const PeekOverviewIssueActivity: React.FC = ({ workspaceSlug, issu activity={issueActivity} handleCommentUpdate={handleCommentUpdate} handleCommentDelete={handleCommentDelete} + showAccessSpecifier={projectDetails && projectDetails.is_deployed} />
- +
diff --git a/web/services/issues.service.ts b/web/services/issues.service.ts index b8875e6c5..af5d722e3 100644 --- a/web/services/issues.service.ts +++ b/web/services/issues.service.ts @@ -204,7 +204,7 @@ class ProjectIssuesServices extends APIService { projectId: string, issueId: string, commentId: string, - data: IIssueComment, + data: Partial, user: ICurrentUserResponse | undefined ): Promise { return this.patch(