diff --git a/packages/editor/src/core/extensions/extensions.tsx b/packages/editor/src/core/extensions/extensions.tsx index 8b9290d62d..80394c51d9 100644 --- a/packages/editor/src/core/extensions/extensions.tsx +++ b/packages/editor/src/core/extensions/extensions.tsx @@ -130,7 +130,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { CustomCodeInlineExtension, Markdown.configure({ html: true, - transformCopiedText: true, + transformCopiedText: false, transformPastedText: true, breaks: true, }), diff --git a/packages/editor/src/core/extensions/mentions/extension-config.ts b/packages/editor/src/core/extensions/mentions/extension-config.ts index 827137a1df..a8921648a0 100644 --- a/packages/editor/src/core/extensions/mentions/extension-config.ts +++ b/packages/editor/src/core/extensions/mentions/extension-config.ts @@ -1,12 +1,15 @@ import { mergeAttributes } from "@tiptap/core"; import Mention, { MentionOptions } from "@tiptap/extension-mention"; +import { MarkdownSerializerState } from "@tiptap/pm/markdown"; +import { Node as NodeType } from "@tiptap/pm/model"; // types import { TMentionHandler } from "@/types"; // local types -import { EMentionComponentAttributeNames } from "./types"; +import { EMentionComponentAttributeNames, TMentionComponentAttributes } from "./types"; export type TMentionExtensionOptions = MentionOptions & { renderComponent: TMentionHandler["renderComponent"]; + getMentionedEntityDetails: TMentionHandler["getMentionedEntityDetails"]; }; export const CustomMentionExtensionConfig = Mention.extend({ @@ -40,9 +43,26 @@ export const CustomMentionExtensionConfig = Mention.extend { - const { searchCallback, renderComponent } = props; + const { searchCallback, renderComponent, getMentionedEntityDetails } = props; return CustomMentionExtensionConfig.extend({ addOptions(this) { return { ...this.parent?.(), renderComponent, + getMentionedEntityDetails, }; }, diff --git a/packages/editor/src/core/types/mention.ts b/packages/editor/src/core/types/mention.ts index 20f1ec0dcc..b7a65f8b4c 100644 --- a/packages/editor/src/core/types/mention.ts +++ b/packages/editor/src/core/types/mention.ts @@ -1,5 +1,5 @@ // plane types -import { TSearchEntities } from "@plane/types"; +import { IUserLite, TSearchEntities } from "@plane/types"; export type TMentionSuggestion = { entity_identifier: string; @@ -20,6 +20,7 @@ export type TMentionComponentProps = Pick React.ReactNode; + getMentionedEntityDetails?: (entity_identifier: string) => { display_name: string } | undefined; }; export type TMentionHandler = TReadOnlyMentionHandler & { diff --git a/space/core/components/editor/lite-text-read-only-editor.tsx b/space/core/components/editor/lite-text-read-only-editor.tsx index 5c8785e90b..acb5cf14d1 100644 --- a/space/core/components/editor/lite-text-read-only-editor.tsx +++ b/space/core/components/editor/lite-text-read-only-editor.tsx @@ -7,6 +7,8 @@ import { EditorMentionsRoot } from "@/components/editor"; // helpers import { cn } from "@/helpers/common.helper"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; +// store hooks +import { useMember } from "@/hooks/store"; type LiteTextReadOnlyEditorWrapperProps = MakeOptional< Omit, @@ -17,22 +19,29 @@ type LiteTextReadOnlyEditorWrapperProps = MakeOptional< }; export const LiteTextReadOnlyEditor = React.forwardRef( - ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => ( - , - }} - {...props} - // overriding the customClassName to add relative class passed - containerClassName={cn(props.containerClassName, "relative p-2")} - /> - ) + ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => { + const { getMemberById } = useMember(); + + return ( + , + getMentionedEntityDetails: (id: string) => ({ + display_name: getMemberById(id)?.member__display_name ?? "", + }), + }} + {...props} + // overriding the customClassName to add relative class passed + containerClassName={cn(props.containerClassName, "relative p-2")} + /> + ); + } ); LiteTextReadOnlyEditor.displayName = "LiteTextReadOnlyEditor"; diff --git a/space/core/components/editor/rich-text-editor.tsx b/space/core/components/editor/rich-text-editor.tsx index 9296b25d2d..d938466dfd 100644 --- a/space/core/components/editor/rich-text-editor.tsx +++ b/space/core/components/editor/rich-text-editor.tsx @@ -6,6 +6,8 @@ import { MakeOptional } from "@plane/types"; import { EditorMentionsRoot } from "@/components/editor"; // helpers import { getEditorFileHandlers } from "@/helpers/editor.helper"; +// store hooks +import { useMember } from "@/hooks/store"; interface RichTextEditorWrapperProps extends MakeOptional, "disabledExtensions"> { @@ -16,11 +18,14 @@ interface RichTextEditorWrapperProps export const RichTextEditor = forwardRef((props, ref) => { const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, ...rest } = props; - + const { getMemberById } = useMember(); return ( , + getMentionedEntityDetails: (id: string) => ({ + display_name: getMemberById(id)?.member__display_name ?? "", + }), }} ref={ref} disabledExtensions={disabledExtensions ?? []} diff --git a/space/core/components/editor/rich-text-read-only-editor.tsx b/space/core/components/editor/rich-text-read-only-editor.tsx index b989e1e411..f2d386629f 100644 --- a/space/core/components/editor/rich-text-read-only-editor.tsx +++ b/space/core/components/editor/rich-text-read-only-editor.tsx @@ -7,6 +7,8 @@ import { EditorMentionsRoot } from "@/components/editor"; // helpers import { cn } from "@/helpers/common.helper"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; +// store hooks +import { useMember } from "@/hooks/store"; type RichTextReadOnlyEditorWrapperProps = MakeOptional< Omit, @@ -17,22 +19,29 @@ type RichTextReadOnlyEditorWrapperProps = MakeOptional< }; export const RichTextReadOnlyEditor = React.forwardRef( - ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => ( - , - }} - {...props} - // overriding the customClassName to add relative class passed - containerClassName={cn("relative p-0 border-none", props.containerClassName)} - /> - ) + ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => { + const { getMemberById } = useMember(); + + return ( + , + getMentionedEntityDetails: (id: string) => ({ + display_name: getMemberById(id)?.member__display_name ?? "", + }), + }} + {...props} + // overriding the customClassName to add relative class passed + containerClassName={cn("relative p-0 border-none", props.containerClassName)} + /> + ); + } ); RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor"; diff --git a/web/core/components/editor/lite-text-editor/lite-text-editor.tsx b/web/core/components/editor/lite-text-editor/lite-text-editor.tsx index b06d39c855..714b773a41 100644 --- a/web/core/components/editor/lite-text-editor/lite-text-editor.tsx +++ b/web/core/components/editor/lite-text-editor/lite-text-editor.tsx @@ -13,6 +13,8 @@ import { cn } from "@/helpers/common.helper"; import { isCommentEmpty } from "@/helpers/string.helper"; // hooks import { useEditorConfig, useEditorMention } from "@/hooks/editor"; +// store hooks +import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; // plane web services @@ -57,6 +59,8 @@ export const LiteTextEditor = React.forwardRef @@ -97,6 +101,7 @@ export const LiteTextEditor = React.forwardRef , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} placeholder={placeholder} containerClassName={cn(containerClassName, "relative")} diff --git a/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx b/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx index 0763a49f96..a8747538e0 100644 --- a/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx +++ b/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx @@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor"; import { cn } from "@/helpers/common.helper"; // hooks import { useEditorConfig } from "@/hooks/editor"; +// store hooks +import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; @@ -22,6 +24,9 @@ type LiteTextReadOnlyEditorWrapperProps = MakeOptional< export const LiteTextReadOnlyEditor = React.forwardRef( ({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => { + // store hooks + const { getUserDetails } = useMember(); + // editor flaggings const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString()); // editor config @@ -38,6 +43,7 @@ export const LiteTextReadOnlyEditor = React.forwardRef , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} {...props} // overriding the containerClassName to add relative class passed diff --git a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx index b18fc18590..ea27ec45d7 100644 --- a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx +++ b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx @@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor"; import { cn } from "@/helpers/common.helper"; // hooks import { useEditorConfig, useEditorMention } from "@/hooks/editor"; +// store hooks +import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; @@ -31,6 +33,8 @@ export const RichTextEditor = forwardRef , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} {...rest} containerClassName={cn("relative pl-3 pb-3", containerClassName)} diff --git a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx index 31ce65159d..50eb65e78e 100644 --- a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx +++ b/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx @@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor"; import { cn } from "@/helpers/common.helper"; // hooks import { useEditorConfig } from "@/hooks/editor"; +// store hooks +import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; @@ -22,6 +24,9 @@ type RichTextReadOnlyEditorWrapperProps = MakeOptional< export const RichTextReadOnlyEditor = React.forwardRef( ({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => { + // store hooks + const { getUserDetails } = useMember(); + // editor flaggings const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString()); // editor config @@ -38,6 +43,7 @@ export const RichTextReadOnlyEditor = React.forwardRef , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} {...props} // overriding the containerClassName to add relative class passed diff --git a/web/core/components/pages/editor/editor-body.tsx b/web/core/components/pages/editor/editor-body.tsx index 72533c3dc0..aba274affe 100644 --- a/web/core/components/pages/editor/editor-body.tsx +++ b/web/core/components/pages/editor/editor-body.tsx @@ -22,7 +22,7 @@ import { cn, LIVE_BASE_PATH, LIVE_BASE_URL } from "@/helpers/common.helper"; import { generateRandomColor } from "@/helpers/string.helper"; // hooks import { useEditorMention } from "@/hooks/editor"; -import { useUser, useWorkspace } from "@/hooks/store"; +import { useUser, useWorkspace, useMember } from "@/hooks/store"; import { usePageFilters } from "@/hooks/use-page-filters"; // plane web components import { EditorAIMenu } from "@/plane-web/components/pages"; @@ -68,6 +68,8 @@ export const PageEditorBody: React.FC = observer((props) => { // store hooks const { data: currentUser } = useUser(); const { getWorkspaceBySlug } = useWorkspace(); + const { getUserDetails } = useMember(); + // derived values const { id: pageId, name: pageTitle, isContentEditable, updateTitle } = page; const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id ?? ""; @@ -192,6 +194,7 @@ export const PageEditorBody: React.FC = observer((props) => { return res; }, renderComponent: (props) => , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} embedHandler={{ issue: issueEmbedProps, diff --git a/web/core/components/pages/version/editor.tsx b/web/core/components/pages/version/editor.tsx index d201232904..c067c5d9ed 100644 --- a/web/core/components/pages/version/editor.tsx +++ b/web/core/components/pages/version/editor.tsx @@ -12,6 +12,8 @@ import { EditorMentionsRoot } from "@/components/editor"; import { useEditorConfig } from "@/hooks/editor"; import { useWorkspace } from "@/hooks/store"; import { usePageFilters } from "@/hooks/use-page-filters"; +// store hooks +import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; @@ -25,6 +27,8 @@ export type TVersionEditorProps = { export const PagesVersionEditor: React.FC = observer((props) => { const { activeVersion, currentVersionDescription, isCurrentVersionActive, versionDetails } = props; + // store hooks + const { getUserDetails } = useMember(); // params const { workspaceSlug, projectId } = useParams(); // store hooks @@ -108,6 +112,7 @@ export const PagesVersionEditor: React.FC = observer((props })} mentionHandler={{ renderComponent: (props) => , + getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} embedHandler={{ issue: {