@@ -4,11 +4,16 @@ import { FC, useEffect, useRef, useState } from "react";
44import { observer } from "mobx-react" ;
55import { useForm } from "react-hook-form" ;
66import { Check , Globe2 , Lock , Pencil , Trash2 , X } from "lucide-react" ;
7+ // plane constants
78import { EIssueCommentAccessSpecifier } from "@plane/constants" ;
9+ // plane editor
810import { EditorReadOnlyRefApi , EditorRefApi } from "@plane/editor" ;
11+ // plane types
912import { TIssueComment } from "@plane/types" ;
10- // ui
13+ // plane ui
1114import { CustomMenu } from "@plane/ui" ;
15+ // plane utils
16+ import { cn } from "@plane/utils" ;
1217// components
1318import { LiteTextEditor , LiteTextReadOnlyEditor } from "@/components/editor" ;
1419// helpers
@@ -42,21 +47,21 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
4247 showAccessSpecifier = false ,
4348 disabled = false ,
4449 } = props ;
45- // hooks
50+ // states
51+ const [ isEditing , setIsEditing ] = useState ( false ) ;
52+ // refs
53+ const editorRef = useRef < EditorRefApi > ( null ) ;
54+ const showEditorRef = useRef < EditorReadOnlyRefApi > ( null ) ;
55+ // store hooks
4656 const {
4757 comment : { getCommentById } ,
4858 } = useIssueDetail ( ) ;
4959 const { data : currentUser } = useUser ( ) ;
50- // refs
51- const editorRef = useRef < EditorRefApi > ( null ) ;
52- const showEditorRef = useRef < EditorReadOnlyRefApi > ( null ) ;
53- // state
54- const [ isEditing , setIsEditing ] = useState ( false ) ;
55-
60+ // derived values
5661 const comment = getCommentById ( commentId ) ;
5762 const workspaceStore = useWorkspace ( ) ;
5863 const workspaceId = workspaceStore . getWorkspaceBySlug ( comment ?. workspace_detail ?. slug as string ) ?. id as string ;
59-
64+ // form info
6065 const {
6166 formState : { isSubmitting } ,
6267 handleSubmit,
@@ -66,6 +71,11 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
6671 } = useForm < Partial < TIssueComment > > ( {
6772 defaultValues : { comment_html : comment ?. comment_html } ,
6873 } ) ;
74+ // derived values
75+ const commentHTML = watch ( "comment_html" ) ;
76+ const isEmpty = isCommentEmpty ( commentHTML ) ;
77+ const isEditorReadyToDiscard = editorRef . current ?. isEditorReadyToDiscard ( ) ;
78+ const isSubmitButtonDisabled = isSubmitting || ! isEditorReadyToDiscard ;
6979
7080 const onEnter = async ( formData : Partial < TIssueComment > ) => {
7181 if ( isSubmitting || ! comment ) return ;
@@ -83,10 +93,8 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
8393 }
8494 } , [ isEditing , setFocus ] ) ;
8595
86- const commentHTML = watch ( "comment_html" ) ;
87- const isEmpty = isCommentEmpty ( commentHTML ) ;
88-
8996 if ( ! comment || ! currentUser ) return < > </ > ;
97+
9098 return (
9199 < IssueCommentBlock
92100 commentId = { commentId }
@@ -95,8 +103,8 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
95103 { ! disabled && currentUser ?. id === comment . actor && (
96104 < CustomMenu ellipsis closeOnSelect >
97105 < CustomMenu . MenuItem onClick = { ( ) => setIsEditing ( true ) } className = "flex items-center gap-1" >
98- < Pencil className = "h-3 w -3" />
99- Edit comment
106+ < Pencil className = "flex-shrink-0 size -3" />
107+ Edit
100108 </ CustomMenu . MenuItem >
101109 { showAccessSpecifier && (
102110 < >
@@ -107,7 +115,7 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
107115 }
108116 className = "flex items-center gap-1"
109117 >
110- < Globe2 className = "h-3 w -3" />
118+ < Globe2 className = "flex-shrink-0 size -3" />
111119 Switch to public comment
112120 </ CustomMenu . MenuItem >
113121 ) : (
@@ -117,7 +125,7 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
117125 }
118126 className = "flex items-center gap-1"
119127 >
120- < Lock className = "h-3 w -3" />
128+ < Lock className = "flex-shrink-0 size -3" />
121129 Switch to private comment
122130 </ CustomMenu . MenuItem >
123131 ) }
@@ -127,8 +135,8 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
127135 onClick = { ( ) => activityOperations . removeComment ( comment . id ) }
128136 className = "flex items-center gap-1"
129137 >
130- < Trash2 className = "h-3 w -3" />
131- Delete comment
138+ < Trash2 className = "flex-shrink-0 size -3" />
139+ Delete
132140 </ CustomMenu . MenuItem >
133141 </ CustomMenu >
134142 ) }
@@ -166,24 +174,27 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
166174 />
167175 </ div >
168176 < div className = "flex gap-1 self-end" >
169- < button
170- type = "button"
171- onClick = { handleSubmit ( onEnter ) }
172- disabled = { isSubmitting || isEmpty }
173- className = { `group rounded border border-green-500 bg-green-500/20 p-2 shadow-md duration-300 ${
174- isEmpty ? "cursor-not-allowed bg-gray-200" : "hover:bg-green-500"
175- } `}
176- >
177- < Check
178- className = { `h-3 w-3 text-green-500 duration-300 ${ isEmpty ? "text-black" : "group-hover:text-white" } ` }
179- />
180- </ button >
177+ { ! isEmpty && (
178+ < button
179+ type = "button"
180+ onClick = { handleSubmit ( onEnter ) }
181+ disabled = { isSubmitButtonDisabled }
182+ className = { cn (
183+ "group rounded border border-green-500 text-green-500 hover:text-white bg-green-500/20 hover:bg-green-500 p-2 shadow-md duration-300" ,
184+ {
185+ "pointer-events-none" : isSubmitButtonDisabled ,
186+ }
187+ ) }
188+ >
189+ < Check className = "size-3" />
190+ </ button >
191+ ) }
181192 < button
182193 type = "button"
183194 className = "group rounded border border-red-500 bg-red-500/20 p-2 shadow-md duration-300 hover:bg-red-500"
184195 onClick = { ( ) => setIsEditing ( false ) }
185196 >
186- < X className = "h-3 w -3 text-red-500 duration-300 group-hover:text-white" />
197+ < X className = "size -3 text-red-500 duration-300 group-hover:text-white" />
187198 </ button >
188199 </ div >
189200 </ form >
0 commit comments