mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
added additional props and Tiptap Integration with Comments
This commit is contained in:
parent
5c290e1302
commit
0b6d510cc7
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
|
||||||
@ -12,11 +11,12 @@ import issuesServices from "services/issues.service";
|
|||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// ui
|
// ui
|
||||||
import { Loader, SecondaryButton } from "components/ui";
|
import { SecondaryButton } from "components/ui";
|
||||||
// types
|
// types
|
||||||
import type { ICurrentUserResponse, IIssueComment } from "types";
|
import type { ICurrentUserResponse, IIssueComment } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
||||||
|
import Tiptap, { ITiptapRichTextEditor } from "components/tiptap";
|
||||||
|
|
||||||
// const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), {
|
// const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), {
|
||||||
// ssr: false,
|
// ssr: false,
|
||||||
@ -34,7 +34,14 @@ import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
|
|||||||
// >((props, ref) => <RemirrorRichTextEditor {...props} forwardedRef={ref} />);
|
// >((props, ref) => <RemirrorRichTextEditor {...props} forwardedRef={ref} />);
|
||||||
//
|
//
|
||||||
// WrappedRemirrorRichTextEditor.displayName = "WrappedRemirrorRichTextEditor";
|
// WrappedRemirrorRichTextEditor.displayName = "WrappedRemirrorRichTextEditor";
|
||||||
//
|
|
||||||
|
const TiptapEditor = React.forwardRef<
|
||||||
|
ITiptapRichTextEditor,
|
||||||
|
ITiptapRichTextEditor
|
||||||
|
>((props, ref) => <Tiptap {...props} forwardedRef={ref} />);
|
||||||
|
|
||||||
|
TiptapEditor.displayName = "TiptapEditor";
|
||||||
|
|
||||||
const defaultValues: Partial<IIssueComment> = {
|
const defaultValues: Partial<IIssueComment> = {
|
||||||
comment_json: "",
|
comment_json: "",
|
||||||
comment_html: "",
|
comment_html: "",
|
||||||
@ -51,6 +58,7 @@ export const AddComment: React.FC<Props> = ({ issueId, user, disabled = false })
|
|||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
setValue,
|
setValue,
|
||||||
|
watch,
|
||||||
formState: { isSubmitting },
|
formState: { isSubmitting },
|
||||||
reset,
|
reset,
|
||||||
} = useForm<IIssueComment>({ defaultValues });
|
} = useForm<IIssueComment>({ defaultValues });
|
||||||
@ -98,19 +106,26 @@ export const AddComment: React.FC<Props> = ({ issueId, user, disabled = false })
|
|||||||
<div>
|
<div>
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="issue-comments-section">
|
<div className="issue-comments-section">
|
||||||
{/* <Controller */}
|
<Controller
|
||||||
{/* name="comment_json" */}
|
name="comment_html"
|
||||||
{/* control={control} */}
|
control={control}
|
||||||
{/* render={({ field: { value } }) => ( */}
|
render={({ field: { value, onChange } }) =>
|
||||||
{/* <WrappedRemirrorRichTextEditor */}
|
<TiptapEditor
|
||||||
{/* value={value} */}
|
ref={editorRef}
|
||||||
{/* onJSONChange={(jsonValue) => setValue("comment_json", jsonValue)} */}
|
value={
|
||||||
{/* onHTMLChange={(htmlValue) => setValue("comment_html", htmlValue)} */}
|
!value || value === "" || (typeof value === "object" && Object.keys(value).length === 0)
|
||||||
{/* placeholder="Enter your comment..." */}
|
? watch("comment_html")
|
||||||
{/* ref={editorRef} */}
|
: value
|
||||||
{/* /> */}
|
}
|
||||||
{/* )} */}
|
customClassName="p-3 min-h-[50px]"
|
||||||
{/* /> */}
|
debouncedUpdatesEnabled={false}
|
||||||
|
onChange={(comment_json: Object, comment_html: string) => {
|
||||||
|
onChange(comment_html);
|
||||||
|
setValue("comment_json", comment_json);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<SecondaryButton type="submit" disabled={isSubmitting || disabled} className="mt-2">
|
<SecondaryButton type="submit" disabled={isSubmitting || disabled} className="mt-2">
|
||||||
{isSubmitting ? "Adding..." : "Comment"}
|
{isSubmitting ? "Adding..." : "Comment"}
|
||||||
|
@ -15,6 +15,7 @@ import { CommentReaction } from "components/issues";
|
|||||||
import { timeAgo } from "helpers/date-time.helper";
|
import { timeAgo } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import type { IIssueComment } from "types";
|
import type { IIssueComment } from "types";
|
||||||
|
import Tiptap, { ITiptapRichTextEditor } from "components/tiptap";
|
||||||
|
|
||||||
// const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), { ssr: false });
|
// const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), { ssr: false });
|
||||||
//
|
//
|
||||||
@ -26,7 +27,14 @@ import type { IIssueComment } from "types";
|
|||||||
// >((props, ref) => <RemirrorRichTextEditor {...props} forwardedRef={ref} />);
|
// >((props, ref) => <RemirrorRichTextEditor {...props} forwardedRef={ref} />);
|
||||||
//
|
//
|
||||||
// WrappedRemirrorRichTextEditor.displayName = "WrappedRemirrorRichTextEditor";
|
// WrappedRemirrorRichTextEditor.displayName = "WrappedRemirrorRichTextEditor";
|
||||||
//
|
|
||||||
|
const TiptapEditor = React.forwardRef<
|
||||||
|
ITiptapRichTextEditor,
|
||||||
|
ITiptapRichTextEditor
|
||||||
|
>((props, ref) => <Tiptap {...props} forwardedRef={ref} />);
|
||||||
|
|
||||||
|
TiptapEditor.displayName = "TiptapEditor";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
comment: IIssueComment;
|
comment: IIssueComment;
|
||||||
onSubmit: (comment: IIssueComment) => void;
|
onSubmit: (comment: IIssueComment) => void;
|
||||||
@ -45,6 +53,7 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
formState: { isSubmitting },
|
formState: { isSubmitting },
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
setFocus,
|
setFocus,
|
||||||
|
watch,
|
||||||
setValue,
|
setValue,
|
||||||
} = useForm<IIssueComment>({
|
} = useForm<IIssueComment>({
|
||||||
defaultValues: comment,
|
defaultValues: comment,
|
||||||
@ -55,9 +64,10 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
|
||||||
onSubmit(formData);
|
onSubmit(formData);
|
||||||
|
console.log("watching", formData.comment_html)
|
||||||
|
|
||||||
editorRef.current?.setEditorValue(formData.comment_json);
|
editorRef.current?.setEditorValue(formData.comment_html);
|
||||||
showEditorRef.current?.setEditorValue(formData.comment_json);
|
showEditorRef.current?.setEditorValue(formData.comment_html);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -105,14 +115,24 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}
|
className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}
|
||||||
onSubmit={handleSubmit(onEnter)}
|
onSubmit={handleSubmit(onEnter)}
|
||||||
>
|
>
|
||||||
<WrappedRemirrorRichTextEditor
|
{/* <WrappedRemirrorRichTextEditor */}
|
||||||
value={comment.comment_html}
|
{/* value={comment.comment_html} */}
|
||||||
onBlur={(jsonValue, htmlValue) => {
|
{/* onBlur={(jsonValue, htmlValue) => { */}
|
||||||
setValue("comment_json", jsonValue);
|
{/* setValue("comment_json", jsonValue); */}
|
||||||
setValue("comment_html", htmlValue);
|
{/* setValue("comment_html", htmlValue); */}
|
||||||
}}
|
{/* }} */}
|
||||||
placeholder="Enter Your comment..."
|
{/* placeholder="Enter Your comment..." */}
|
||||||
|
{/* ref={editorRef} */}
|
||||||
|
{/* /> */}
|
||||||
|
<TiptapEditor
|
||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
|
value={watch("comment_html")}
|
||||||
|
debouncedUpdatesEnabled={false}
|
||||||
|
customClassName="min-h-[50px] p-3"
|
||||||
|
onChange={(comment_json: Object, comment_html: string) => {
|
||||||
|
setValue("comment_json", comment_json);
|
||||||
|
setValue("comment_html", comment_html);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-1 self-end">
|
<div className="flex gap-1 self-end">
|
||||||
<button
|
<button
|
||||||
@ -132,6 +152,12 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div className={`${isEditing ? "hidden" : ""}`}>
|
<div className={`${isEditing ? "hidden" : ""}`}>
|
||||||
|
<TiptapEditor
|
||||||
|
ref={showEditorRef}
|
||||||
|
value={comment.comment_html}
|
||||||
|
editable={false}
|
||||||
|
customClassName="text-xs border border-custom-border-200 bg-custom-background-100"
|
||||||
|
/>
|
||||||
{/* <WrappedRemirrorRichTextEditor */}
|
{/* <WrappedRemirrorRichTextEditor */}
|
||||||
{/* value={comment.comment_html} */}
|
{/* value={comment.comment_html} */}
|
||||||
{/* editable={false} */}
|
{/* editable={false} */}
|
||||||
@ -139,7 +165,6 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
{/* customClassName="text-xs border border-custom-border-200 bg-custom-background-100" */}
|
{/* customClassName="text-xs border border-custom-border-200 bg-custom-background-100" */}
|
||||||
{/* ref={showEditorRef} */}
|
{/* ref={showEditorRef} */}
|
||||||
{/* /> */}
|
{/* /> */}
|
||||||
|
|
||||||
<CommentReaction projectId={comment.project} commentId={comment.id} />
|
<CommentReaction projectId={comment.project} commentId={comment.id} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -123,8 +123,12 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
|||||||
? watch("description_html")
|
? watch("description_html")
|
||||||
: value
|
: value
|
||||||
}
|
}
|
||||||
|
debouncedUpdatesEnabled={true}
|
||||||
setIsSubmitting={setIsSubmitting}
|
setIsSubmitting={setIsSubmitting}
|
||||||
|
customClassName="min-h-[150px]"
|
||||||
|
editorContentCustomClassNames="pt-9"
|
||||||
onChange={(description: Object, description_html: string) => {
|
onChange={(description: Object, description_html: string) => {
|
||||||
|
setIsSubmitting(true);
|
||||||
onChange(description_html);
|
onChange(description_html);
|
||||||
setValue("description", description);
|
setValue("description", description);
|
||||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting(false));
|
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting(false));
|
||||||
|
@ -372,6 +372,7 @@ export const IssueForm: FC<IssueFormProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Tiptap
|
<Tiptap
|
||||||
|
debouncedUpdatesEnabled={false}
|
||||||
value={
|
value={
|
||||||
!value || value === "" || (typeof value === "object" && Object.keys(value).length === 0)
|
!value || value === "" || (typeof value === "object" && Object.keys(value).length === 0)
|
||||||
? watch("description_html")
|
? watch("description_html")
|
||||||
|
@ -129,30 +129,30 @@ export const IssueMainContent: React.FC<Props> = ({
|
|||||||
isAllowed={memberRole.isMember || memberRole.isOwner || !uneditable}
|
isAllowed={memberRole.isMember || memberRole.isOwner || !uneditable}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <IssueReaction workspaceSlug={workspaceSlug} issueId={issueId} projectId={projectId} /> */}
|
<IssueReaction workspaceSlug={workspaceSlug} issueId={issueId} projectId={projectId} />
|
||||||
{/**/}
|
|
||||||
{/* <div className="mt-2 space-y-2"> */}
|
<div className="mt-2 space-y-2">
|
||||||
{/* <SubIssuesList parentIssue={issueDetails} user={user} disabled={uneditable} /> */}
|
<SubIssuesList parentIssue={issueDetails} user={user} disabled={uneditable} />
|
||||||
{/* </div> */}
|
</div>
|
||||||
{/* </div> */}
|
</div>
|
||||||
{/* <div className="flex flex-col gap-3 py-3"> */}
|
<div className="flex flex-col gap-3 py-3">
|
||||||
{/* <h3 className="text-lg">Attachments</h3> */}
|
<h3 className="text-lg">Attachments</h3>
|
||||||
{/* <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4"> */}
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
|
||||||
{/* <IssueAttachmentUpload disabled={uneditable} /> */}
|
<IssueAttachmentUpload disabled={uneditable} />
|
||||||
{/* <IssueAttachments /> */}
|
<IssueAttachments />
|
||||||
{/* </div> */}
|
</div>
|
||||||
{/* </div> */}
|
</div>
|
||||||
{/* <div className="space-y-5 pt-3"> */}
|
<div className="space-y-5 pt-3">
|
||||||
{/* <h3 className="text-lg text-custom-text-100">Comments/Activity</h3> */}
|
<h3 className="text-lg text-custom-text-100">Comments/Activity</h3>
|
||||||
{/* <IssueActivitySection */}
|
<IssueActivitySection
|
||||||
{/* issueId={(archivedIssueId as string) ?? (issueId as string)} */}
|
issueId={(archivedIssueId as string) ?? (issueId as string)}
|
||||||
{/* user={user} */}
|
user={user}
|
||||||
{/* /> */}
|
/>
|
||||||
{/* <AddComment */}
|
<AddComment
|
||||||
{/* issueId={(archivedIssueId as string) ?? (issueId as string)} */}
|
issueId={(archivedIssueId as string) ?? (issueId as string)}
|
||||||
{/* user={user} */}
|
user={user}
|
||||||
{/* disabled={uneditable} */}
|
disabled={uneditable}
|
||||||
{/* /> */}
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user