mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
🚜 refactor: added a common place for all LiteTextEditor and it's read only instances
This commit is contained in:
parent
ae9c729fc7
commit
ce987833b7
@ -1,3 +1,4 @@
|
||||
export { LiteTextEditor, LiteTextEditorWithRef } from "src/ui";
|
||||
export { LiteReadOnlyEditor, LiteReadOnlyEditorWithRef } from "src/ui/read-only";
|
||||
export type { IMentionSuggestion, IMentionHighlight } from "@plane/editor-core";
|
||||
export type { LiteTextEditorProps, ILiteTextEditor } from "src/ui";
|
||||
export type { LiteTextEditorReadOnlyProps, ILiteReadOnlyEditor } from "src/ui/read-only";
|
||||
|
@ -12,12 +12,11 @@ import {
|
||||
import { FixedMenu } from "src/ui/menus/fixed-menu";
|
||||
import { LiteTextEditorExtensions } from "src/ui/extensions";
|
||||
|
||||
interface ILiteTextEditor {
|
||||
export type ILiteTextEditor = {
|
||||
value: string;
|
||||
uploadFile: UploadImage;
|
||||
deleteFile: DeleteImage;
|
||||
restoreFile: RestoreImage;
|
||||
|
||||
noBorder?: boolean;
|
||||
borderOnFocus?: boolean;
|
||||
customClassName?: string;
|
||||
@ -42,9 +41,9 @@ interface ILiteTextEditor {
|
||||
mentionHighlights?: string[];
|
||||
mentionSuggestions?: IMentionSuggestion[];
|
||||
submitButton?: React.ReactNode;
|
||||
}
|
||||
};
|
||||
|
||||
interface LiteTextEditorProps extends ILiteTextEditor {
|
||||
export interface LiteTextEditorProps extends ILiteTextEditor {
|
||||
forwardedRef?: React.Ref<EditorHandle>;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
import * as React from "react";
|
||||
import { EditorContainer, EditorContentWrapper, getEditorClassNames, useReadOnlyEditor } from "@plane/editor-core";
|
||||
|
||||
interface ICoreReadOnlyEditor {
|
||||
export type ILiteReadOnlyEditor = {
|
||||
value: string;
|
||||
editorContentCustomClassNames?: string;
|
||||
noBorder?: boolean;
|
||||
borderOnFocus?: boolean;
|
||||
customClassName?: string;
|
||||
mentionHighlights: string[];
|
||||
}
|
||||
};
|
||||
|
||||
interface EditorCoreProps extends ICoreReadOnlyEditor {
|
||||
export interface LiteTextEditorReadOnlyProps extends ILiteReadOnlyEditor {
|
||||
forwardedRef?: React.Ref<EditorHandle>;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ const LiteReadOnlyEditor = ({
|
||||
value,
|
||||
forwardedRef,
|
||||
mentionHighlights,
|
||||
}: EditorCoreProps) => {
|
||||
}: LiteTextEditorReadOnlyProps) => {
|
||||
const editor = useReadOnlyEditor({
|
||||
value,
|
||||
forwardedRef,
|
||||
@ -51,7 +51,7 @@ const LiteReadOnlyEditor = ({
|
||||
);
|
||||
};
|
||||
|
||||
const LiteReadOnlyEditorWithRef = React.forwardRef<EditorHandle, ICoreReadOnlyEditor>((props, ref) => (
|
||||
const LiteReadOnlyEditorWithRef = React.forwardRef<EditorHandle, ILiteReadOnlyEditor>((props, ref) => (
|
||||
<LiteReadOnlyEditor {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
export { RichTextEditor, RichTextEditorWithRef } from "src/ui";
|
||||
export { RichReadOnlyEditor, RichReadOnlyEditorWithRef } from "src/ui/read-only";
|
||||
export type { RichTextEditorProps, IRichTextEditor } from "src/ui";
|
||||
export type { IMentionHighlight, IMentionSuggestion } from "@plane/editor-core";
|
||||
|
41
web/components/editor/lite-text-editor.tsx
Normal file
41
web/components/editor/lite-text-editor.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { LiteTextEditorWithRef, ILiteTextEditor } from "@plane/lite-text-editor";
|
||||
|
||||
import { useMention } from "hooks/store";
|
||||
|
||||
import { FileService } from "services/file.service";
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
interface LiteTextEditorWrapperProps
|
||||
extends Omit<
|
||||
ILiteTextEditor,
|
||||
"uploadFile" | "deleteFile" | "restoreFile" | "mentionSuggestions" | "mentionHighlights"
|
||||
> {
|
||||
workspaceSlug: string;
|
||||
}
|
||||
|
||||
const fileService = new FileService();
|
||||
|
||||
export const LiteTextEditor = React.forwardRef<EditorHandle, LiteTextEditorWrapperProps>(
|
||||
({ workspaceSlug, ...props }, ref) => {
|
||||
const editorSuggestions = useMention();
|
||||
|
||||
return (
|
||||
<LiteTextEditorWithRef
|
||||
ref={ref}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
mentionSuggestions={editorSuggestions.mentionSuggestions}
|
||||
mentionHighlights={editorSuggestions.mentionHighlights}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
LiteTextEditor.displayName = "LiteTextEditor";
|
21
web/components/editor/lite-text-read-only-editor.tsx
Normal file
21
web/components/editor/lite-text-read-only-editor.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
import { ILiteReadOnlyEditor, LiteReadOnlyEditorWithRef } from "@plane/lite-text-editor";
|
||||
|
||||
import { useMention } from "hooks/store";
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
interface LiteTextReadOnlyEditorWrapperProps extends Omit<ILiteReadOnlyEditor, "mentionHighlights"> {}
|
||||
|
||||
export const LiteTextReadOnlyEditor = React.forwardRef<EditorHandle, LiteTextReadOnlyEditorWrapperProps>(
|
||||
({ ...props }, ref) => {
|
||||
const editorSuggestions = useMention();
|
||||
|
||||
return <LiteReadOnlyEditorWithRef ref={ref} mentionHighlights={editorSuggestions.mentionHighlights} {...props} />;
|
||||
}
|
||||
);
|
||||
|
||||
LiteTextReadOnlyEditor.displayName = "LiteTextReadOnlyEditor";
|
41
web/components/editor/rich-text-read-only-editor.tsx
Normal file
41
web/components/editor/rich-text-read-only-editor.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { RichTextEditorWithRef, IRichTextEditor } from "@plane/rich-text-editor";
|
||||
|
||||
import { useMention } from "hooks/store";
|
||||
|
||||
import { FileService } from "services/file.service";
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
interface RichTextEditorWrapperProps
|
||||
extends Omit<
|
||||
IRichTextEditor,
|
||||
"uploadFile" | "deleteFile" | "restoreFile" | "mentionSuggestions" | "mentionHighlights"
|
||||
> {
|
||||
workspaceSlug: string;
|
||||
}
|
||||
|
||||
const fileService = new FileService();
|
||||
|
||||
export const RichTextEditor = React.forwardRef<EditorHandle, RichTextEditorWrapperProps>(
|
||||
({ workspaceSlug, ...props }, ref) => {
|
||||
const editorSuggestions = useMention();
|
||||
|
||||
return (
|
||||
<RichTextEditorWithRef
|
||||
ref={ref}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
mentionSuggestions={editorSuggestions.mentionSuggestions}
|
||||
mentionHighlights={editorSuggestions.mentionHighlights}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
RichTextEditor.displayName = "RichTextEditor";
|
@ -12,7 +12,7 @@ import { AIService } from "services/ai.service";
|
||||
// components
|
||||
import { GptAssistantPopover } from "components/core";
|
||||
import { PriorityDropdown } from "components/dropdowns";
|
||||
import { RichTextEditor } from "components/editor/rich-text-wrapper";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
// ui
|
||||
import { Button, Input, ToggleSwitch } from "@plane/ui";
|
||||
// types
|
||||
|
@ -1,12 +1,8 @@
|
||||
import React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
// hooks
|
||||
import { useMention } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// components
|
||||
import { LiteTextEditorWithRef } from "@plane/lite-text-editor";
|
||||
import { LiteTextEditor } from "components/editor/lite-text-editor";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
import { Globe2, Lock } from "lucide-react";
|
||||
@ -42,17 +38,12 @@ const commentAccess: commentAccessType[] = [
|
||||
},
|
||||
];
|
||||
|
||||
// services
|
||||
const fileService = new FileService();
|
||||
|
||||
export const AddComment: React.FC<Props> = ({ disabled = false, onSubmit, showAccessSpecifier = false }) => {
|
||||
// refs
|
||||
const editorRef = React.useRef<any>(null);
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// store hooks
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -82,25 +73,19 @@ export const AddComment: React.FC<Props> = ({ disabled = false, onSubmit, showAc
|
||||
name="comment_html"
|
||||
control={control}
|
||||
render={({ field: { onChange: onCommentChange, value: commentValue } }) => (
|
||||
<LiteTextEditorWithRef
|
||||
<LiteTextEditor
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
onEnterKeyPress={handleSubmit(handleAddComment)}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
ref={editorRef}
|
||||
value={!commentValue || commentValue === "" ? "<p></p>" : commentValue}
|
||||
customClassName="p-2 h-full"
|
||||
editorContentCustomClassNames="min-h-[35px]"
|
||||
debouncedUpdatesEnabled={false}
|
||||
onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)}
|
||||
commentAccessSpecifier={
|
||||
showAccessSpecifier
|
||||
? { accessValue: accessValue ?? "INTERNAL", onAccessChange, showAccessSpecifier, commentAccess }
|
||||
: undefined
|
||||
}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
submitButton={
|
||||
<Button
|
||||
variant="primary"
|
||||
|
@ -2,23 +2,20 @@ import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useMention, useUser } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
import { useUser } from "hooks/store";
|
||||
// icons
|
||||
import { Check, Globe2, Lock, MessageSquare, Pencil, Trash2, X } from "lucide-react";
|
||||
// ui
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { CommentReaction } from "components/issues";
|
||||
import { LiteTextEditorWithRef, LiteReadOnlyEditorWithRef } from "@plane/lite-text-editor";
|
||||
// components
|
||||
import { LiteTextEditor } from "components/editor/lite-text-editor";
|
||||
import { LiteTextReadOnlyEditor } from "components/editor/lite-text-read-only-editor";
|
||||
// helpers
|
||||
import { calculateTimeAgo } from "helpers/date-time.helper";
|
||||
// types
|
||||
import type { IIssueActivity } from "@plane/types";
|
||||
|
||||
// services
|
||||
const fileService = new FileService();
|
||||
|
||||
type Props = {
|
||||
comment: IIssueActivity;
|
||||
handleCommentDeletion: (comment: string) => void;
|
||||
@ -36,7 +33,6 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
||||
const showEditorRef = React.useRef<any>(null);
|
||||
// store hooks
|
||||
const { currentUser } = useUser();
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
// form info
|
||||
const {
|
||||
formState: { isSubmitting },
|
||||
@ -97,19 +93,14 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
||||
<div className="issue-comments-section p-0">
|
||||
<form className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}>
|
||||
<div>
|
||||
<LiteTextEditorWithRef
|
||||
<LiteTextEditor
|
||||
workspaceSlug={workspaceSlug}
|
||||
onEnterKeyPress={handleSubmit(onEnter)}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
ref={editorRef}
|
||||
value={watch("comment_html") ?? ""}
|
||||
debouncedUpdatesEnabled={false}
|
||||
customClassName="min-h-[50px] p-3 shadow-sm"
|
||||
onChange={(comment_json: Object, comment_html: string) => setValue("comment_html", comment_html)}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-1 self-end">
|
||||
@ -136,11 +127,10 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
||||
{comment.access === "INTERNAL" ? <Lock className="h-3 w-3" /> : <Globe2 className="h-3 w-3" />}
|
||||
</div>
|
||||
)}
|
||||
<LiteReadOnlyEditorWithRef
|
||||
<LiteTextReadOnlyEditor
|
||||
ref={showEditorRef}
|
||||
value={comment.comment_html ?? ""}
|
||||
customClassName="text-xs border border-custom-border-200 bg-custom-background-100"
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
<CommentReaction projectId={comment.project} commentId={comment.id} />
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@ import useReloadConfirmations from "hooks/use-reload-confirmation";
|
||||
import debounce from "lodash/debounce";
|
||||
// components
|
||||
import { TextArea } from "@plane/ui";
|
||||
import { RichTextEditor } from "components/editor/rich-text-wrapper";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
import { TIssueOperations } from "./issue-detail";
|
||||
|
@ -25,7 +25,7 @@ import { ParentIssuesListModal } from "components/issues";
|
||||
import { IssueLabelSelect } from "components/issues/select";
|
||||
import { CreateLabelModal } from "components/labels";
|
||||
import { CreateStateModal } from "components/states";
|
||||
import { RichTextEditor } from "components/editor/rich-text-wrapper";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
// ui
|
||||
import { Button, CustomMenu, Input, ToggleSwitch } from "@plane/ui";
|
||||
// helpers
|
||||
|
@ -9,7 +9,7 @@ import useToast from "hooks/use-toast";
|
||||
// services
|
||||
import { AIService } from "services/ai.service";
|
||||
// components
|
||||
import { RichTextEditor } from "components/editor/rich-text-wrapper";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
import { GptAssistantPopover } from "components/core";
|
||||
import {
|
||||
CycleDropdown,
|
||||
|
@ -1,23 +1,17 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Check, Globe2, Lock, MessageSquare, Pencil, Trash2, X } from "lucide-react";
|
||||
// hooks
|
||||
import { useMention } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// ui
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
import { LiteTextEditorWithRef, LiteReadOnlyEditorWithRef } from "@plane/lite-text-editor";
|
||||
// components
|
||||
import { IssueCommentReaction } from "./comment-reaction";
|
||||
import { LiteTextReadOnlyEditor } from "components/editor/lite-text-read-only-editor";
|
||||
import { LiteTextEditor } from "components/editor/lite-text-editor";
|
||||
// helpers
|
||||
import { calculateTimeAgo } from "helpers/date-time.helper";
|
||||
// types
|
||||
import type { IIssueActivity, IUser } from "@plane/types";
|
||||
|
||||
// services
|
||||
const fileService = new FileService();
|
||||
|
||||
type IIssueCommentCard = {
|
||||
comment: IIssueActivity;
|
||||
handleCommentDeletion: (comment: string) => void;
|
||||
@ -49,8 +43,6 @@ export const IssueCommentCard: React.FC<IIssueCommentCard> = (props) => {
|
||||
// refs
|
||||
const editorRef = React.useRef<any>(null);
|
||||
const showEditorRef = React.useRef<any>(null);
|
||||
// store hooks
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
// form info
|
||||
const {
|
||||
formState: { isSubmitting },
|
||||
@ -113,19 +105,14 @@ export const IssueCommentCard: React.FC<IIssueCommentCard> = (props) => {
|
||||
<div className="issue-comments-section p-0">
|
||||
<div className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}>
|
||||
<div>
|
||||
<LiteTextEditorWithRef
|
||||
<LiteTextEditor
|
||||
workspaceSlug={workspaceSlug}
|
||||
onEnterKeyPress={handleSubmit(formSubmit)}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
ref={editorRef}
|
||||
value={watch("comment_html") ?? ""}
|
||||
debouncedUpdatesEnabled={false}
|
||||
customClassName="min-h-[50px] p-3 shadow-sm"
|
||||
onChange={(comment_json: Object, comment_html: string) => setValue("comment_html", comment_html)}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-1 self-end">
|
||||
@ -154,13 +141,11 @@ export const IssueCommentCard: React.FC<IIssueCommentCard> = (props) => {
|
||||
{comment.access === "INTERNAL" ? <Lock className="h-3 w-3" /> : <Globe2 className="h-3 w-3" />}
|
||||
</div>
|
||||
)}
|
||||
<LiteReadOnlyEditorWithRef
|
||||
<LiteTextReadOnlyEditor
|
||||
ref={showEditorRef}
|
||||
value={comment.comment_html ?? ""}
|
||||
customClassName="text-xs border border-custom-border-200 bg-custom-background-100"
|
||||
mentionHighlights={mentionHighlights}
|
||||
/>
|
||||
|
||||
<div className="mt-1">
|
||||
<IssueCommentReaction
|
||||
workspaceSlug={workspaceSlug}
|
||||
|
@ -2,12 +2,8 @@ import React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { Globe2, Lock } from "lucide-react";
|
||||
// hooks
|
||||
import { useMention } from "hooks/store";
|
||||
// services
|
||||
import { FileService } from "services/file.service";
|
||||
// components
|
||||
import { LiteTextEditorWithRef } from "@plane/lite-text-editor";
|
||||
import { LiteTextEditor } from "components/editor/lite-text-editor";
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
// types
|
||||
@ -42,9 +38,6 @@ const commentAccess: commentAccessType[] = [
|
||||
},
|
||||
];
|
||||
|
||||
// services
|
||||
const fileService = new FileService();
|
||||
|
||||
export const IssueCommentEditor: React.FC<IIssueCommentEditor> = (props) => {
|
||||
const { disabled = false, onSubmit, showAccessSpecifier = false } = props;
|
||||
// refs
|
||||
@ -52,8 +45,6 @@ export const IssueCommentEditor: React.FC<IIssueCommentEditor> = (props) => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// store hooks
|
||||
const { mentionHighlights, mentionSuggestions } = useMention();
|
||||
// form info
|
||||
const {
|
||||
control,
|
||||
@ -83,19 +74,13 @@ export const IssueCommentEditor: React.FC<IIssueCommentEditor> = (props) => {
|
||||
name="comment_html"
|
||||
control={control}
|
||||
render={({ field: { onChange: onCommentChange, value: commentValue } }) => (
|
||||
<LiteTextEditorWithRef
|
||||
<LiteTextEditor
|
||||
workspaceSlug={workspaceSlug as string}
|
||||
onEnterKeyPress={handleSubmit(handleAddComment)}
|
||||
cancelUploadImage={fileService.cancelUpload}
|
||||
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
|
||||
deleteFile={fileService.deleteImage}
|
||||
restoreFile={fileService.restoreImage}
|
||||
ref={editorRef}
|
||||
value={!commentValue || commentValue === "" ? "<p></p>" : commentValue}
|
||||
customClassName="p-2 h-full"
|
||||
editorContentCustomClassNames="min-h-[35px]"
|
||||
debouncedUpdatesEnabled={false}
|
||||
mentionSuggestions={mentionSuggestions}
|
||||
mentionHighlights={mentionHighlights}
|
||||
onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)}
|
||||
commentAccessSpecifier={
|
||||
showAccessSpecifier
|
||||
|
@ -5,7 +5,7 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { useProject, useUser } from "hooks/store";
|
||||
import useReloadConfirmations from "hooks/use-reload-confirmation";
|
||||
// components
|
||||
import { RichTextEditor } from "components/editor/rich-text-wrapper";
|
||||
import { RichTextEditor } from "components/editor/rich-text-editor";
|
||||
import { IssuePeekOverviewReactions } from "components/issues";
|
||||
// ui
|
||||
import { TextArea } from "@plane/ui";
|
||||
|
Loading…
Reference in New Issue
Block a user