import type { FC } from "react"; import { useRef, useState } from "react"; import { observer } from "mobx-react"; import { useForm, Controller } from "react-hook-form"; // plane imports import { EIssueCommentAccessSpecifier } from "@plane/constants"; import type { EditorRefApi } from "@plane/editor"; import type { TIssueComment, TCommentsOperations } from "@plane/types"; import { cn, isCommentEmpty } from "@plane/utils"; // components import { LiteTextEditor } from "@/components/editor/lite-text"; // hooks import { useWorkspace } from "@/hooks/store/use-workspace"; // services import { FileService } from "@/services/file.service"; type TCommentCreate = { entityId: string; workspaceSlug: string; activityOperations: TCommentsOperations; showToolbarInitially?: boolean; projectId?: string; onSubmitCallback?: (elementId: string) => void; }; // services const fileService = new FileService(); export const CommentCreate: FC = observer((props) => { const { workspaceSlug, entityId, activityOperations, showToolbarInitially = false, projectId, onSubmitCallback, } = props; // states const [uploadedAssetIds, setUploadedAssetIds] = useState([]); // refs const editorRef = useRef(null); // store hooks const workspaceStore = useWorkspace(); // derived values const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string; // form info const { handleSubmit, control, watch, formState: { isSubmitting }, reset, } = useForm>({ defaultValues: { comment_html: "

", }, }); const onSubmit = async (formData: Partial) => { try { const comment = await activityOperations.createComment(formData); if (comment?.id) onSubmitCallback?.(comment.id); if (uploadedAssetIds.length > 0) { if (projectId) { await fileService.updateBulkProjectAssetsUploadStatus(workspaceSlug, projectId.toString(), entityId, { asset_ids: uploadedAssetIds, }); } else { await fileService.updateBulkWorkspaceAssetsUploadStatus(workspaceSlug, entityId, { asset_ids: uploadedAssetIds, }); } setUploadedAssetIds([]); } } catch (error) { console.error(error); } finally { reset({ comment_html: "

", }); editorRef.current?.clearEditor(); } }; const commentHTML = watch("comment_html"); const isEmpty = isCommentEmpty(commentHTML ?? undefined); return (
{ if ( e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty && !isSubmitting && editorRef.current?.isEditorReadyToDiscard() ) handleSubmit(onSubmit)(e); }} > ( (

"} workspaceSlug={workspaceSlug} projectId={projectId} onEnterKeyPress={(e) => { if (!isEmpty && !isSubmitting) { handleSubmit(onSubmit)(e); } }} ref={editorRef} initialValue={value ?? "

"} containerClassName="min-h-min" onChange={(comment_json, comment_html) => onChange(comment_html)} accessSpecifier={accessValue ?? EIssueCommentAccessSpecifier.INTERNAL} handleAccessChange={onAccessChange} isSubmitting={isSubmitting} uploadFile={async (blockId, file) => { const { asset_id } = await activityOperations.uploadCommentAsset(blockId, file); setUploadedAssetIds((prev) => [...prev, asset_id]); return asset_id; }} showToolbarInitially={showToolbarInitially} parentClassName="p-2" displayConfig={{ fontSize: "small-font", }} /> )} /> )} />
); });