[WIKI-466] refactor: remove rich text read only editor (#7241)

* refactor: remove rich text read only editor

* fix: type imports
This commit is contained in:
Aaryan Khandelwal 2025-07-03 14:16:17 +05:30 committed by GitHub
parent 7d141f26ad
commit 6f27ec031d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 126 additions and 262 deletions

View file

@ -1,5 +1,5 @@
export * from "./embeds"; export * from "./embeds";
export * from "./lite-text-editor"; export * from "./lite-text-editor";
export * from "./lite-text-read-only-editor"; export * from "./lite-text-read-only-editor";
export * from "./rich-text-read-only-editor"; export * from "./rich-text-editor";
export * from "./toolbar"; export * from "./toolbar";

View file

@ -9,18 +9,24 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper";
// store hooks // store hooks
import { useMember } from "@/hooks/store"; import { useMember } from "@/hooks/store";
interface RichTextEditorWrapperProps type RichTextEditorWrapperProps = MakeOptional<
extends MakeOptional< Omit<IRichTextEditorProps, "editable" | "fileHandler" | "mentionHandler">,
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions" "disabledExtensions" | "flaggedExtensions"
> { > & {
anchor: string; anchor: string;
uploadFile: TFileHandler["upload"];
workspaceId: string; workspaceId: string;
} } & (
| {
editable: false;
}
| {
editable: true;
uploadFile: TFileHandler["upload"];
}
);
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => { export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props; const { anchor, containerClassName, editable, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props;
const { getMemberById } = useMember(); const { getMemberById } = useMember();
return ( return (
<RichTextEditorWithRef <RichTextEditorWithRef
@ -32,9 +38,10 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
}} }}
ref={ref} ref={ref}
disabledExtensions={disabledExtensions ?? []} disabledExtensions={disabledExtensions ?? []}
editable={editable}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
anchor, anchor,
uploadFile, uploadFile: editable ? props.uploadFile : async () => "",
workspaceId, workspaceId,
})} })}
flaggedExtensions={flaggedExtensions ?? []} flaggedExtensions={flaggedExtensions ?? []}

View file

@ -1,48 +0,0 @@
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
import { cn } from "@plane/utils";
// components
import { EditorMentionsRoot } from "@/components/editor";
// helpers
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// store hooks
import { useMember } from "@/hooks/store";
type RichTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<IRichTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
anchor: string;
workspaceId: string;
};
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => {
const { getMemberById } = useMember();
return (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
flaggedExtensions={flaggedExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
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";

View file

@ -1,6 +1,6 @@
import { observer } from "mobx-react"; import { observer } from "mobx-react";
// components // components
import { RichTextReadOnlyEditor } from "@/components/editor"; import { RichTextEditor } from "@/components/editor";
import { IssueReactions } from "@/components/issues/peek-overview"; import { IssueReactions } from "@/components/issues/peek-overview";
import { usePublish } from "@/hooks/store"; import { usePublish } from "@/hooks/store";
// types // types
@ -25,7 +25,8 @@ export const PeekOverviewIssueDetails: React.FC<Props> = observer((props) => {
</h6> </h6>
<h4 className="break-words text-2xl font-medium">{issueDetails.name}</h4> <h4 className="break-words text-2xl font-medium">{issueDetails.name}</h4>
{description !== "" && description !== "<p></p>" && ( {description !== "" && description !== "<p></p>" && (
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
anchor={anchor} anchor={anchor}
id={issueDetails.id} id={issueDetails.id}
initialValue={ initialValue={

View file

@ -4,7 +4,7 @@ import { CircleArrowUp, CornerDownRight, RefreshCcw, Sparkles } from "lucide-rea
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
// components // components
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
import { RichTextReadOnlyEditor } from "@/components/editor"; import { RichTextEditor } from "@/components/editor";
// helpers // helpers
// hooks // hooks
import { useWorkspace } from "@/hooks/store"; import { useWorkspace } from "@/hooks/store";
@ -38,7 +38,8 @@ export const AskPiMenu: React.FC<Props> = (props) => {
</span> </span>
{response ? ( {response ? (
<div> <div>
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
displayConfig={{ displayConfig={{
fontSize: "small-font", fontSize: "small-font",
}} }}

View file

@ -8,7 +8,7 @@ import { EditorRefApi } from "@plane/editor";
import { Tooltip } from "@plane/ui"; import { Tooltip } from "@plane/ui";
// components // components
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
import { RichTextReadOnlyEditor } from "@/components/editor"; import { RichTextEditor } from "@/components/editor";
// helpers // helpers
// plane web constants // plane web constants
import { AI_EDITOR_TASKS, LOADING_TEXTS } from "@/plane-web/constants/ai"; import { AI_EDITOR_TASKS, LOADING_TEXTS } from "@/plane-web/constants/ai";
@ -208,10 +208,11 @@ export const EditorAIMenu: React.FC<Props> = (props) => {
</span> </span>
{response ? ( {response ? (
<div> <div>
<RichTextReadOnlyEditor <RichTextEditor
displayConfig={{ displayConfig={{
fontSize: "small-font", fontSize: "small-font",
}} }}
editable={false}
id="editor-ai-response" id="editor-ai-response"
initialValue={response} initialValue={response}
containerClassName="!p-0 border-none" containerClassName="!p-0 border-none"

View file

@ -2,7 +2,7 @@ import { useCallback, useRef } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { ChevronLeft, ChevronRight, Copy } from "lucide-react"; import { ChevronLeft, ChevronRight, Copy } from "lucide-react";
// plane imports // plane imports
import { EditorReadOnlyRefApi } from "@plane/editor"; import type { EditorRefApi } from "@plane/editor";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { TDescriptionVersion } from "@plane/types"; import { TDescriptionVersion } from "@plane/types";
import { import {
@ -19,7 +19,7 @@ import {
} from "@plane/ui"; } from "@plane/ui";
import { calculateTimeAgo, cn, copyTextToClipboard, getFileURL } from "@plane/utils"; import { calculateTimeAgo, cn, copyTextToClipboard, getFileURL } from "@plane/utils";
// components // components
import { RichTextReadOnlyEditor } from "@/components/editor"; import { RichTextEditor } from "@/components/editor";
// hooks // hooks
import { useMember, useWorkspace } from "@/hooks/store"; import { useMember, useWorkspace } from "@/hooks/store";
@ -52,7 +52,7 @@ export const DescriptionVersionsModal: React.FC<Props> = observer((props) => {
workspaceSlug, workspaceSlug,
} = props; } = props;
// refs // refs
const editorRef = useRef<EditorReadOnlyRefApi>(null); const editorRef = useRef<EditorRefApi>(null);
// store hooks // store hooks
const { getUserDetails } = useMember(); const { getUserDetails } = useMember();
const { getWorkspaceBySlug } = useWorkspace(); const { getWorkspaceBySlug } = useWorkspace();
@ -131,7 +131,8 @@ export const DescriptionVersionsModal: React.FC<Props> = observer((props) => {
{/* Version description */} {/* Version description */}
<div className="mt-4 pb-4"> <div className="mt-4 pb-4">
{activeVersionDescription ? ( {activeVersionDescription ? (
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
containerClassName="p-0 !pl-0 border-none" containerClassName="p-0 !pl-0 border-none"
editorClassName="pl-0" editorClassName="pl-0"
id={activeVersionId ?? ""} id={activeVersionId ?? ""}

View file

@ -6,12 +6,11 @@ import { Controller, useForm } from "react-hook-form"; // services
import { usePopper } from "react-popper"; import { usePopper } from "react-popper";
import { AlertCircle } from "lucide-react"; import { AlertCircle } from "lucide-react";
import { Popover, Transition } from "@headlessui/react"; import { Popover, Transition } from "@headlessui/react";
// plane editor // plane imports
import { EditorReadOnlyRefApi } from "@plane/editor"; import type { EditorRefApi } from "@plane/editor";
// ui
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui"; import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
// components // components
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor"; import { RichTextEditor } from "@/components/editor";
// services // services
import { AIService } from "@/services/ai.service"; import { AIService } from "@/services/ai.service";
const aiService = new AIService(); const aiService = new AIService();
@ -55,8 +54,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null); const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null); const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
// refs // refs
const editorRef = useRef<EditorReadOnlyRefApi>(null); const editorRef = useRef<EditorRefApi>(null);
const responseRef = useRef<any>(null); const responseRef = useRef<EditorRefApi>(null);
// popper // popper
const { styles, attributes } = usePopper(referenceElement, popperElement, { const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "auto", placement: placement ?? "auto",
@ -217,7 +216,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
{prompt && ( {prompt && (
<div className="text-sm"> <div className="text-sm">
Content: Content:
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
id="ai-assistant-content" id="ai-assistant-content"
initialValue={prompt} initialValue={prompt}
containerClassName="-m-3" containerClassName="-m-3"
@ -231,7 +231,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
{response !== "" && ( {response !== "" && (
<div className="page-block-section max-h-[8rem] text-sm"> <div className="page-block-section max-h-[8rem] text-sm">
Response: Response:
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
id="ai-assistant-response" id="ai-assistant-response"
initialValue={`<p>${response}</p>`} initialValue={`<p>${response}</p>`}
ref={responseRef} ref={responseRef}

View file

@ -1,2 +1 @@
export * from "./rich-text-editor"; export * from "./rich-text-editor";
export * from "./rich-text-read-only-editor";

View file

@ -13,26 +13,31 @@ import { useMember } from "@/hooks/store";
// plane web hooks // plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
interface RichTextEditorWrapperProps type RichTextEditorWrapperProps = MakeOptional<
extends MakeOptional<
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">, Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions" "disabledExtensions" | "editable" | "flaggedExtensions"
> { > & {
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
workspaceSlug: string; workspaceSlug: string;
workspaceId: string; workspaceId: string;
projectId?: string; projectId?: string;
} & (
| {
editable: false;
}
| {
editable: true;
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
uploadFile: TFileHandler["upload"]; uploadFile: TFileHandler["upload"];
} }
);
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => { export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
const { const {
containerClassName, containerClassName,
editable,
workspaceSlug, workspaceSlug,
workspaceId, workspaceId,
projectId, projectId,
searchMentionCallback,
uploadFile,
disabledExtensions: additionalDisabledExtensions, disabledExtensions: additionalDisabledExtensions,
...rest ...rest
} = props; } = props;
@ -42,7 +47,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString()); const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// use editor mention // use editor mention
const { fetchMentions } = useEditorMention({ const { fetchMentions } = useEditorMention({
searchEntity: async (payload) => await searchMentionCallback(payload), searchEntity: editable ? async (payload) => await props.searchMentionCallback(payload) : async () => ({}),
}); });
// editor config // editor config
const { getEditorFileHandlers } = useEditorConfig(); const { getEditorFileHandlers } = useEditorConfig();
@ -51,10 +56,11 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
<RichTextEditorWithRef <RichTextEditorWithRef
ref={ref} ref={ref}
disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]} disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
editable={editable}
flaggedExtensions={richTextEditorExtensions.flagged} flaggedExtensions={richTextEditorExtensions.flagged}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
projectId, projectId,
uploadFile, uploadFile: editable ? props.uploadFile : async () => "",
workspaceId, workspaceId,
workspaceSlug, workspaceSlug,
})} })}

View file

@ -1,59 +0,0 @@
"use client";
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
// components
import { cn } from "@plane/utils";
import { EditorMentionsRoot } from "@/components/editor";
// helpers
// 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";
type RichTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<IRichTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
workspaceId: string;
workspaceSlug: string;
projectId?: string;
};
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => {
// store hooks
const { getUserDetails } = useMember();
// editor flaggings
const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
const { getReadOnlyEditorFileHandlers } = useEditorConfig();
return (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
flaggedExtensions={richTextEditorExtensions.flagged}
fileHandler={getReadOnlyEditorFileHandlers({
projectId,
workspaceId,
workspaceSlug,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
{...props}
// overriding the containerClassName to add relative class passed
containerClassName={cn(props.containerClassName, "relative pl-3")}
/>
);
}
);
RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor";

View file

@ -62,6 +62,7 @@ export const InboxIssueDescription: FC<TInboxIssueDescription> = observer((props
return ( return (
<RichTextEditor <RichTextEditor
editable
id="inbox-modal-editor" id="inbox-modal-editor"
initialValue={!data?.description_html || data?.description_html === "" ? "<p></p>" : data?.description_html} initialValue={!data?.description_html || data?.description_html === "" ? "<p></p>" : data?.description_html}
ref={editorRef} ref={editorRef}

View file

@ -5,13 +5,13 @@ import debounce from "lodash/debounce";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// plane imports // plane imports
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; import type { EditorRefApi } from "@plane/editor";
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
import { EFileAssetType, TIssue, TNameDescriptionLoader } from "@plane/types"; import { EFileAssetType, TIssue, TNameDescriptionLoader } from "@plane/types";
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
// components // components
import { getDescriptionPlaceholderI18n } from "@plane/utils"; import { getDescriptionPlaceholderI18n } from "@plane/utils";
import { RichTextEditor, RichTextReadOnlyEditor } from "@/components/editor"; import { RichTextEditor } from "@/components/editor";
import { TIssueOperations } from "@/components/issues/issue-detail"; import { TIssueOperations } from "@/components/issues/issue-detail";
// helpers // helpers
// hooks // hooks
@ -22,7 +22,6 @@ const workspaceService = new WorkspaceService();
export type IssueDescriptionInputProps = { export type IssueDescriptionInputProps = {
containerClassName?: string; containerClassName?: string;
editorReadOnlyRef?: React.RefObject<EditorReadOnlyRefApi>;
editorRef?: React.RefObject<EditorRefApi>; editorRef?: React.RefObject<EditorRefApi>;
workspaceSlug: string; workspaceSlug: string;
projectId: string; projectId: string;
@ -38,7 +37,6 @@ export type IssueDescriptionInputProps = {
export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((props) => { export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((props) => {
const { const {
containerClassName, containerClassName,
editorReadOnlyRef,
editorRef, editorRef,
workspaceSlug, workspaceSlug,
projectId, projectId,
@ -109,9 +107,9 @@ export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((p
<Controller <Controller
name="description_html" name="description_html"
control={control} control={control}
render={({ field: { onChange } }) => render={({ field: { onChange } }) => (
!disabled ? (
<RichTextEditor <RichTextEditor
editable={!disabled}
id={issueId} id={issueId}
initialValue={localIssueDescription.description_html ?? "<p></p>"} initialValue={localIssueDescription.description_html ?? "<p></p>"}
value={swrIssueDescription ?? null} value={swrIssueDescription ?? null}
@ -157,18 +155,7 @@ export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((p
}} }}
ref={editorRef} ref={editorRef}
/> />
) : ( )}
<RichTextReadOnlyEditor
id={issueId}
initialValue={localIssueDescription.description_html ?? ""}
containerClassName={containerClassName}
workspaceId={workspaceId}
workspaceSlug={workspaceSlug}
projectId={projectId}
ref={editorReadOnlyRef}
/>
)
}
/> />
) : ( ) : (
<Loader> <Loader>

View file

@ -6,13 +6,9 @@ import { Control, Controller } from "react-hook-form";
import { Sparkle } from "lucide-react"; import { Sparkle } from "lucide-react";
// plane imports // plane imports
import { ETabIndices } from "@plane/constants"; import { ETabIndices } from "@plane/constants";
// editor import type { EditorRefApi } from "@plane/editor";
import { EditorRefApi } from "@plane/editor";
// i18n
import { useTranslation } from "@plane/i18n"; import { useTranslation } from "@plane/i18n";
// types
import { EFileAssetType, TIssue } from "@plane/types"; import { EFileAssetType, TIssue } from "@plane/types";
// ui
import { Loader, setToast, TOAST_TYPE } from "@plane/ui"; import { Loader, setToast, TOAST_TYPE } from "@plane/ui";
import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils"; import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils";
// components // components
@ -177,6 +173,7 @@ export const IssueDescriptionEditor: React.FC<TIssueDescriptionEditorProps> = ob
control={control} control={control}
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<RichTextEditor <RichTextEditor
editable
id="issue-modal-editor" id="issue-modal-editor"
initialValue={value ?? ""} initialValue={value ?? ""}
value={descriptionHtmlData} value={descriptionHtmlData}

View file

@ -9,7 +9,7 @@ import { calculateTimeAgo, getFileURL } from "@plane/utils";
// components // components
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core"; import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
// editor // editor
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor"; import { RichTextEditor } from "@/components/editor";
// ui // ui
import { ActivitySettingsLoader } from "@/components/ui"; import { ActivitySettingsLoader } from "@/components/ui";
// helpers // helpers
@ -73,7 +73,8 @@ export const ActivityList: React.FC<Props> = observer((props) => {
</p> </p>
</div> </div>
<div className="issue-comments-section p-0"> <div className="issue-comments-section p-0">
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
id={activityItem.id} id={activityItem.id}
initialValue={ initialValue={
activityItem?.new_value !== "" activityItem?.new_value !== ""

View file

@ -6,8 +6,8 @@ import useSWR from "swr";
import { History, MessageSquare } from "lucide-react"; import { History, MessageSquare } from "lucide-react";
import { calculateTimeAgo, getFileURL } from "@plane/utils"; import { calculateTimeAgo, getFileURL } from "@plane/utils";
// hooks // hooks
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core"; import { ActivityIcon, ActivityMessage } from "@/components/core";
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor"; import { RichTextEditor } from "@/components/editor";
import { ActivitySettingsLoader } from "@/components/ui"; import { ActivitySettingsLoader } from "@/components/ui";
// constants // constants
import { USER_ACTIVITY } from "@/constants/fetch-keys"; import { USER_ACTIVITY } from "@/constants/fetch-keys";
@ -96,7 +96,8 @@ export const ProfileActivityListPage: React.FC<Props> = observer((props) => {
</p> </p>
</div> </div>
<div className="issue-comments-section p-0"> <div className="issue-comments-section p-0">
<RichTextReadOnlyEditor <RichTextEditor
editable={false}
id={activityItem.id} id={activityItem.id}
initialValue={ initialValue={
activityItem?.new_value !== "" ? activityItem.new_value : activityItem.old_value activityItem?.new_value !== "" ? activityItem.new_value : activityItem.old_value

View file

@ -12,6 +12,7 @@ import { EditorContentWrapper } from "./editor-content";
type Props = IEditorProps & { type Props = IEditorProps & {
children?: (editor: Editor) => React.ReactNode; children?: (editor: Editor) => React.ReactNode;
editable: boolean;
extensions: Extensions; extensions: Extensions;
}; };
@ -21,6 +22,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
containerClassName, containerClassName,
disabledExtensions, disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG, displayConfig = DEFAULT_DISPLAY_CONFIG,
editable,
editorClassName = "", editorClassName = "",
extensions, extensions,
id, id,
@ -39,7 +41,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
} = props; } = props;
const editor = useEditor({ const editor = useEditor({
editable: true, editable,
disabledExtensions, disabledExtensions,
editorClassName, editorClassName,
enableHistory: true, enableHistory: true,

View file

@ -19,7 +19,7 @@ const LiteTextEditor: React.FC<ILiteTextEditorProps> = (props) => {
return resolvedExtensions; return resolvedExtensions;
}, [externalExtensions, disabledExtensions, onEnterKeyPress]); }, [externalExtensions, disabledExtensions, onEnterKeyPress]);
return <EditorWrapper {...props} extensions={extensions} />; return <EditorWrapper {...props} editable extensions={extensions} />;
}; };
const LiteTextEditorWithRef = forwardRef<EditorRefApi, ILiteTextEditorProps>((props, ref) => ( const LiteTextEditorWithRef = forwardRef<EditorRefApi, ILiteTextEditorProps>((props, ref) => (

View file

@ -1,2 +1 @@
export * from "./editor"; export * from "./editor";
export * from "./read-only-editor";

View file

@ -1,33 +0,0 @@
import { forwardRef, useCallback } from "react";
// plane editor extensions
import { RichTextReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extensions/rich-text/read-only-extensions";
// types
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps } from "@/types";
// local imports
import { ReadOnlyEditorWrapper } from "../read-only-editor-wrapper";
const RichTextReadOnlyEditorWithRef = forwardRef<EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps>((props, ref) => {
const { disabledExtensions, fileHandler, flaggedExtensions } = props;
const getExtensions = useCallback(() => {
const extensions = RichTextReadOnlyEditorAdditionalExtensions({
disabledExtensions,
fileHandler,
flaggedExtensions,
});
return extensions;
}, [disabledExtensions, fileHandler, flaggedExtensions]);
return (
<ReadOnlyEditorWrapper
{...props}
extensions={getExtensions()}
forwardedRef={ref as React.MutableRefObject<EditorReadOnlyRefApi | null>}
/>
);
});
RichTextReadOnlyEditorWithRef.displayName = "RichReadOnlyEditorWithRef";
export { RichTextReadOnlyEditorWithRef };

View file

@ -143,9 +143,11 @@ export interface IEditorProps {
} }
export type ILiteTextEditorProps = IEditorProps; export type ILiteTextEditorProps = IEditorProps;
export interface IRichTextEditorProps extends IEditorProps {
export type IRichTextEditorProps = IEditorProps & {
dragDropEnabled?: boolean; dragDropEnabled?: boolean;
} editable: boolean;
};
export interface ICollaborativeDocumentEditorProps export interface ICollaborativeDocumentEditorProps
extends Omit<IEditorProps, "extensions" | "initialValue" | "onEnterKeyPress" | "value"> { extends Omit<IEditorProps, "extensions" | "initialValue" | "onEnterKeyPress" | "value"> {
@ -178,8 +180,6 @@ export interface IReadOnlyEditorProps
export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps; export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps;
export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps;
export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps { export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps {
embedHandler: TEmbedConfig; embedHandler: TEmbedConfig;
} }

View file

@ -13,7 +13,6 @@ export {
LiteTextEditorWithRef, LiteTextEditorWithRef,
LiteTextReadOnlyEditorWithRef, LiteTextReadOnlyEditorWithRef,
RichTextEditorWithRef, RichTextEditorWithRef,
RichTextReadOnlyEditorWithRef,
} from "@/components/editors"; } from "@/components/editors";
export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection";