mirror of
https://github.com/makeplane/plane.git
synced 2026-01-07 14:20:29 -06:00
[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:
committed by
GitHub
parent
7d141f26ad
commit
6f27ec031d
@@ -1,5 +1,5 @@
|
||||
export * from "./embeds";
|
||||
export * from "./lite-text-editor";
|
||||
export * from "./lite-text-read-only-editor";
|
||||
export * from "./rich-text-read-only-editor";
|
||||
export * from "./rich-text-editor";
|
||||
export * from "./toolbar";
|
||||
|
||||
@@ -9,18 +9,24 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper";
|
||||
// store hooks
|
||||
import { useMember } from "@/hooks/store";
|
||||
|
||||
interface RichTextEditorWrapperProps
|
||||
extends MakeOptional<
|
||||
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
|
||||
"disabledExtensions" | "flaggedExtensions"
|
||||
> {
|
||||
type RichTextEditorWrapperProps = MakeOptional<
|
||||
Omit<IRichTextEditorProps, "editable" | "fileHandler" | "mentionHandler">,
|
||||
"disabledExtensions" | "flaggedExtensions"
|
||||
> & {
|
||||
anchor: string;
|
||||
uploadFile: TFileHandler["upload"];
|
||||
workspaceId: string;
|
||||
}
|
||||
} & (
|
||||
| {
|
||||
editable: false;
|
||||
}
|
||||
| {
|
||||
editable: true;
|
||||
uploadFile: TFileHandler["upload"];
|
||||
}
|
||||
);
|
||||
|
||||
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();
|
||||
return (
|
||||
<RichTextEditorWithRef
|
||||
@@ -32,9 +38,10 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
|
||||
}}
|
||||
ref={ref}
|
||||
disabledExtensions={disabledExtensions ?? []}
|
||||
editable={editable}
|
||||
fileHandler={getEditorFileHandlers({
|
||||
anchor,
|
||||
uploadFile,
|
||||
uploadFile: editable ? props.uploadFile : async () => "",
|
||||
workspaceId,
|
||||
})}
|
||||
flaggedExtensions={flaggedExtensions ?? []}
|
||||
|
||||
@@ -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";
|
||||
@@ -1,6 +1,6 @@
|
||||
import { observer } from "mobx-react";
|
||||
// components
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
import { IssueReactions } from "@/components/issues/peek-overview";
|
||||
import { usePublish } from "@/hooks/store";
|
||||
// types
|
||||
@@ -25,7 +25,8 @@ export const PeekOverviewIssueDetails: React.FC<Props> = observer((props) => {
|
||||
</h6>
|
||||
<h4 className="break-words text-2xl font-medium">{issueDetails.name}</h4>
|
||||
{description !== "" && description !== "<p></p>" && (
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
anchor={anchor}
|
||||
id={issueDetails.id}
|
||||
initialValue={
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CircleArrowUp, CornerDownRight, RefreshCcw, Sparkles } from "lucide-rea
|
||||
import { Tooltip } from "@plane/ui";
|
||||
// components
|
||||
import { cn } from "@plane/utils";
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
// helpers
|
||||
// hooks
|
||||
import { useWorkspace } from "@/hooks/store";
|
||||
@@ -38,7 +38,8 @@ export const AskPiMenu: React.FC<Props> = (props) => {
|
||||
</span>
|
||||
{response ? (
|
||||
<div>
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
displayConfig={{
|
||||
fontSize: "small-font",
|
||||
}}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { EditorRefApi } from "@plane/editor";
|
||||
import { Tooltip } from "@plane/ui";
|
||||
// components
|
||||
import { cn } from "@plane/utils";
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
// helpers
|
||||
// plane web constants
|
||||
import { AI_EDITOR_TASKS, LOADING_TEXTS } from "@/plane-web/constants/ai";
|
||||
@@ -208,10 +208,11 @@ export const EditorAIMenu: React.FC<Props> = (props) => {
|
||||
</span>
|
||||
{response ? (
|
||||
<div>
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
displayConfig={{
|
||||
fontSize: "small-font",
|
||||
}}
|
||||
editable={false}
|
||||
id="editor-ai-response"
|
||||
initialValue={response}
|
||||
containerClassName="!p-0 border-none"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useRef } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { ChevronLeft, ChevronRight, Copy } from "lucide-react";
|
||||
// plane imports
|
||||
import { EditorReadOnlyRefApi } from "@plane/editor";
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { TDescriptionVersion } from "@plane/types";
|
||||
import {
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "@plane/ui";
|
||||
import { calculateTimeAgo, cn, copyTextToClipboard, getFileURL } from "@plane/utils";
|
||||
// components
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
// hooks
|
||||
import { useMember, useWorkspace } from "@/hooks/store";
|
||||
|
||||
@@ -52,7 +52,7 @@ export const DescriptionVersionsModal: React.FC<Props> = observer((props) => {
|
||||
workspaceSlug,
|
||||
} = props;
|
||||
// refs
|
||||
const editorRef = useRef<EditorReadOnlyRefApi>(null);
|
||||
const editorRef = useRef<EditorRefApi>(null);
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
const { getWorkspaceBySlug } = useWorkspace();
|
||||
@@ -131,7 +131,8 @@ export const DescriptionVersionsModal: React.FC<Props> = observer((props) => {
|
||||
{/* Version description */}
|
||||
<div className="mt-4 pb-4">
|
||||
{activeVersionDescription ? (
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
containerClassName="p-0 !pl-0 border-none"
|
||||
editorClassName="pl-0"
|
||||
id={activeVersionId ?? ""}
|
||||
|
||||
@@ -6,12 +6,11 @@ import { Controller, useForm } from "react-hook-form"; // services
|
||||
import { usePopper } from "react-popper";
|
||||
import { AlertCircle } from "lucide-react";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
// plane editor
|
||||
import { EditorReadOnlyRefApi } from "@plane/editor";
|
||||
// ui
|
||||
// plane imports
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
// services
|
||||
import { AIService } from "@/services/ai.service";
|
||||
const aiService = new AIService();
|
||||
@@ -55,8 +54,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||
// refs
|
||||
const editorRef = useRef<EditorReadOnlyRefApi>(null);
|
||||
const responseRef = useRef<any>(null);
|
||||
const editorRef = useRef<EditorRefApi>(null);
|
||||
const responseRef = useRef<EditorRefApi>(null);
|
||||
// popper
|
||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: placement ?? "auto",
|
||||
@@ -217,7 +216,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
{prompt && (
|
||||
<div className="text-sm">
|
||||
Content:
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
id="ai-assistant-content"
|
||||
initialValue={prompt}
|
||||
containerClassName="-m-3"
|
||||
@@ -231,7 +231,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
{response !== "" && (
|
||||
<div className="page-block-section max-h-[8rem] text-sm">
|
||||
Response:
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
id="ai-assistant-response"
|
||||
initialValue={`<p>${response}</p>`}
|
||||
ref={responseRef}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./rich-text-editor";
|
||||
export * from "./rich-text-read-only-editor";
|
||||
|
||||
@@ -13,26 +13,31 @@ import { useMember } from "@/hooks/store";
|
||||
// plane web hooks
|
||||
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
|
||||
|
||||
interface RichTextEditorWrapperProps
|
||||
extends MakeOptional<
|
||||
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
|
||||
"disabledExtensions" | "flaggedExtensions"
|
||||
> {
|
||||
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
|
||||
type RichTextEditorWrapperProps = MakeOptional<
|
||||
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
|
||||
"disabledExtensions" | "editable" | "flaggedExtensions"
|
||||
> & {
|
||||
workspaceSlug: string;
|
||||
workspaceId: string;
|
||||
projectId?: string;
|
||||
uploadFile: TFileHandler["upload"];
|
||||
}
|
||||
} & (
|
||||
| {
|
||||
editable: false;
|
||||
}
|
||||
| {
|
||||
editable: true;
|
||||
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
|
||||
uploadFile: TFileHandler["upload"];
|
||||
}
|
||||
);
|
||||
|
||||
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
|
||||
const {
|
||||
containerClassName,
|
||||
editable,
|
||||
workspaceSlug,
|
||||
workspaceId,
|
||||
projectId,
|
||||
searchMentionCallback,
|
||||
uploadFile,
|
||||
disabledExtensions: additionalDisabledExtensions,
|
||||
...rest
|
||||
} = props;
|
||||
@@ -42,7 +47,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
|
||||
const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
|
||||
// use editor mention
|
||||
const { fetchMentions } = useEditorMention({
|
||||
searchEntity: async (payload) => await searchMentionCallback(payload),
|
||||
searchEntity: editable ? async (payload) => await props.searchMentionCallback(payload) : async () => ({}),
|
||||
});
|
||||
// editor config
|
||||
const { getEditorFileHandlers } = useEditorConfig();
|
||||
@@ -51,10 +56,11 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
|
||||
<RichTextEditorWithRef
|
||||
ref={ref}
|
||||
disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
|
||||
editable={editable}
|
||||
flaggedExtensions={richTextEditorExtensions.flagged}
|
||||
fileHandler={getEditorFileHandlers({
|
||||
projectId,
|
||||
uploadFile,
|
||||
uploadFile: editable ? props.uploadFile : async () => "",
|
||||
workspaceId,
|
||||
workspaceSlug,
|
||||
})}
|
||||
|
||||
@@ -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";
|
||||
@@ -62,6 +62,7 @@ export const InboxIssueDescription: FC<TInboxIssueDescription> = observer((props
|
||||
|
||||
return (
|
||||
<RichTextEditor
|
||||
editable
|
||||
id="inbox-modal-editor"
|
||||
initialValue={!data?.description_html || data?.description_html === "" ? "<p></p>" : data?.description_html}
|
||||
ref={editorRef}
|
||||
|
||||
@@ -5,13 +5,13 @@ import debounce from "lodash/debounce";
|
||||
import { observer } from "mobx-react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// plane imports
|
||||
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor";
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { EFileAssetType, TIssue, TNameDescriptionLoader } from "@plane/types";
|
||||
import { Loader } from "@plane/ui";
|
||||
// components
|
||||
import { getDescriptionPlaceholderI18n } from "@plane/utils";
|
||||
import { RichTextEditor, RichTextReadOnlyEditor } from "@/components/editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
import { TIssueOperations } from "@/components/issues/issue-detail";
|
||||
// helpers
|
||||
// hooks
|
||||
@@ -22,7 +22,6 @@ const workspaceService = new WorkspaceService();
|
||||
|
||||
export type IssueDescriptionInputProps = {
|
||||
containerClassName?: string;
|
||||
editorReadOnlyRef?: React.RefObject<EditorReadOnlyRefApi>;
|
||||
editorRef?: React.RefObject<EditorRefApi>;
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
@@ -38,7 +37,6 @@ export type IssueDescriptionInputProps = {
|
||||
export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((props) => {
|
||||
const {
|
||||
containerClassName,
|
||||
editorReadOnlyRef,
|
||||
editorRef,
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
@@ -109,66 +107,55 @@ export const IssueDescriptionInput: FC<IssueDescriptionInputProps> = observer((p
|
||||
<Controller
|
||||
name="description_html"
|
||||
control={control}
|
||||
render={({ field: { onChange } }) =>
|
||||
!disabled ? (
|
||||
<RichTextEditor
|
||||
id={issueId}
|
||||
initialValue={localIssueDescription.description_html ?? "<p></p>"}
|
||||
value={swrIssueDescription ?? null}
|
||||
workspaceSlug={workspaceSlug}
|
||||
workspaceId={workspaceId}
|
||||
projectId={projectId}
|
||||
dragDropEnabled
|
||||
onChange={(_description: object, description_html: string) => {
|
||||
setIsSubmitting("submitting");
|
||||
onChange(description_html);
|
||||
debouncedFormSave();
|
||||
}}
|
||||
placeholder={
|
||||
placeholder
|
||||
? placeholder
|
||||
: (isFocused, value) => t(`${getDescriptionPlaceholderI18n(isFocused, value)}`)
|
||||
render={({ field: { onChange } }) => (
|
||||
<RichTextEditor
|
||||
editable={!disabled}
|
||||
id={issueId}
|
||||
initialValue={localIssueDescription.description_html ?? "<p></p>"}
|
||||
value={swrIssueDescription ?? null}
|
||||
workspaceSlug={workspaceSlug}
|
||||
workspaceId={workspaceId}
|
||||
projectId={projectId}
|
||||
dragDropEnabled
|
||||
onChange={(_description: object, description_html: string) => {
|
||||
setIsSubmitting("submitting");
|
||||
onChange(description_html);
|
||||
debouncedFormSave();
|
||||
}}
|
||||
placeholder={
|
||||
placeholder
|
||||
? placeholder
|
||||
: (isFocused, value) => t(`${getDescriptionPlaceholderI18n(isFocused, value)}`)
|
||||
}
|
||||
searchMentionCallback={async (payload) =>
|
||||
await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", {
|
||||
...payload,
|
||||
project_id: projectId?.toString() ?? "",
|
||||
issue_id: issueId?.toString(),
|
||||
})
|
||||
}
|
||||
containerClassName={containerClassName}
|
||||
uploadFile={async (blockId, file) => {
|
||||
try {
|
||||
const { asset_id } = await uploadEditorAsset({
|
||||
blockId,
|
||||
data: {
|
||||
entity_identifier: issueId,
|
||||
entity_type: EFileAssetType.ISSUE_DESCRIPTION,
|
||||
},
|
||||
file,
|
||||
projectId,
|
||||
workspaceSlug,
|
||||
});
|
||||
return asset_id;
|
||||
} catch (error) {
|
||||
console.log("Error in uploading work item asset:", error);
|
||||
throw new Error("Asset upload failed. Please try again later.");
|
||||
}
|
||||
searchMentionCallback={async (payload) =>
|
||||
await workspaceService.searchEntity(workspaceSlug?.toString() ?? "", {
|
||||
...payload,
|
||||
project_id: projectId?.toString() ?? "",
|
||||
issue_id: issueId?.toString(),
|
||||
})
|
||||
}
|
||||
containerClassName={containerClassName}
|
||||
uploadFile={async (blockId, file) => {
|
||||
try {
|
||||
const { asset_id } = await uploadEditorAsset({
|
||||
blockId,
|
||||
data: {
|
||||
entity_identifier: issueId,
|
||||
entity_type: EFileAssetType.ISSUE_DESCRIPTION,
|
||||
},
|
||||
file,
|
||||
projectId,
|
||||
workspaceSlug,
|
||||
});
|
||||
return asset_id;
|
||||
} catch (error) {
|
||||
console.log("Error in uploading work item asset:", error);
|
||||
throw new Error("Asset upload failed. Please try again later.");
|
||||
}
|
||||
}}
|
||||
ref={editorRef}
|
||||
/>
|
||||
) : (
|
||||
<RichTextReadOnlyEditor
|
||||
id={issueId}
|
||||
initialValue={localIssueDescription.description_html ?? ""}
|
||||
containerClassName={containerClassName}
|
||||
workspaceId={workspaceId}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
ref={editorReadOnlyRef}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}}
|
||||
ref={editorRef}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<Loader>
|
||||
|
||||
@@ -6,13 +6,9 @@ import { Control, Controller } from "react-hook-form";
|
||||
import { Sparkle } from "lucide-react";
|
||||
// plane imports
|
||||
import { ETabIndices } from "@plane/constants";
|
||||
// editor
|
||||
import { EditorRefApi } from "@plane/editor";
|
||||
// i18n
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
// types
|
||||
import { EFileAssetType, TIssue } from "@plane/types";
|
||||
// ui
|
||||
import { Loader, setToast, TOAST_TYPE } from "@plane/ui";
|
||||
import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils";
|
||||
// components
|
||||
@@ -177,6 +173,7 @@ export const IssueDescriptionEditor: React.FC<TIssueDescriptionEditorProps> = ob
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<RichTextEditor
|
||||
editable
|
||||
id="issue-modal-editor"
|
||||
initialValue={value ?? ""}
|
||||
value={descriptionHtmlData}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { calculateTimeAgo, getFileURL } from "@plane/utils";
|
||||
// components
|
||||
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
|
||||
// editor
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
// ui
|
||||
import { ActivitySettingsLoader } from "@/components/ui";
|
||||
// helpers
|
||||
@@ -73,7 +73,8 @@ export const ActivityList: React.FC<Props> = observer((props) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="issue-comments-section p-0">
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
id={activityItem.id}
|
||||
initialValue={
|
||||
activityItem?.new_value !== ""
|
||||
|
||||
@@ -6,8 +6,8 @@ import useSWR from "swr";
|
||||
import { History, MessageSquare } from "lucide-react";
|
||||
import { calculateTimeAgo, getFileURL } from "@plane/utils";
|
||||
// hooks
|
||||
import { ActivityIcon, ActivityMessage, IssueLink } from "@/components/core";
|
||||
import { RichTextReadOnlyEditor } from "@/components/editor/rich-text-editor/rich-text-read-only-editor";
|
||||
import { ActivityIcon, ActivityMessage } from "@/components/core";
|
||||
import { RichTextEditor } from "@/components/editor";
|
||||
import { ActivitySettingsLoader } from "@/components/ui";
|
||||
// constants
|
||||
import { USER_ACTIVITY } from "@/constants/fetch-keys";
|
||||
@@ -96,7 +96,8 @@ export const ProfileActivityListPage: React.FC<Props> = observer((props) => {
|
||||
</p>
|
||||
</div>
|
||||
<div className="issue-comments-section p-0">
|
||||
<RichTextReadOnlyEditor
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
id={activityItem.id}
|
||||
initialValue={
|
||||
activityItem?.new_value !== "" ? activityItem.new_value : activityItem.old_value
|
||||
|
||||
@@ -12,6 +12,7 @@ import { EditorContentWrapper } from "./editor-content";
|
||||
|
||||
type Props = IEditorProps & {
|
||||
children?: (editor: Editor) => React.ReactNode;
|
||||
editable: boolean;
|
||||
extensions: Extensions;
|
||||
};
|
||||
|
||||
@@ -21,6 +22,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
|
||||
containerClassName,
|
||||
disabledExtensions,
|
||||
displayConfig = DEFAULT_DISPLAY_CONFIG,
|
||||
editable,
|
||||
editorClassName = "",
|
||||
extensions,
|
||||
id,
|
||||
@@ -39,7 +41,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
|
||||
} = props;
|
||||
|
||||
const editor = useEditor({
|
||||
editable: true,
|
||||
editable,
|
||||
disabledExtensions,
|
||||
editorClassName,
|
||||
enableHistory: true,
|
||||
|
||||
@@ -19,7 +19,7 @@ const LiteTextEditor: React.FC<ILiteTextEditorProps> = (props) => {
|
||||
return resolvedExtensions;
|
||||
}, [externalExtensions, disabledExtensions, onEnterKeyPress]);
|
||||
|
||||
return <EditorWrapper {...props} extensions={extensions} />;
|
||||
return <EditorWrapper {...props} editable extensions={extensions} />;
|
||||
};
|
||||
|
||||
const LiteTextEditorWithRef = forwardRef<EditorRefApi, ILiteTextEditorProps>((props, ref) => (
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from "./editor";
|
||||
export * from "./read-only-editor";
|
||||
|
||||
@@ -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 };
|
||||
@@ -143,9 +143,11 @@ export interface IEditorProps {
|
||||
}
|
||||
|
||||
export type ILiteTextEditorProps = IEditorProps;
|
||||
export interface IRichTextEditorProps extends IEditorProps {
|
||||
|
||||
export type IRichTextEditorProps = IEditorProps & {
|
||||
dragDropEnabled?: boolean;
|
||||
}
|
||||
editable: boolean;
|
||||
};
|
||||
|
||||
export interface ICollaborativeDocumentEditorProps
|
||||
extends Omit<IEditorProps, "extensions" | "initialValue" | "onEnterKeyPress" | "value"> {
|
||||
@@ -178,8 +180,6 @@ export interface IReadOnlyEditorProps
|
||||
|
||||
export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps;
|
||||
|
||||
export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps;
|
||||
|
||||
export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps {
|
||||
embedHandler: TEmbedConfig;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ export {
|
||||
LiteTextEditorWithRef,
|
||||
LiteTextReadOnlyEditorWithRef,
|
||||
RichTextEditorWithRef,
|
||||
RichTextReadOnlyEditorWithRef,
|
||||
} from "@/components/editors";
|
||||
|
||||
export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection";
|
||||
|
||||
Reference in New Issue
Block a user