mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
[WIKI-537] refactor: document editor (#7384)
* refactor: document editor * chore: update user prop * fix: type warning * chore: update value prop name * chore: remove unnecessary exports * hore: update initialValue type * chore: revert initialValue type * refactor: unnecessary string handlers
This commit is contained in:
committed by
GitHub
parent
e20bfa55d6
commit
27f74206a3
92
apps/web/core/components/editor/document/editor.tsx
Normal file
92
apps/web/core/components/editor/document/editor.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import React, { forwardRef } from "react";
|
||||
// plane imports
|
||||
import { DocumentEditorWithRef, EditorRefApi, IDocumentEditorProps, TFileHandler } from "@plane/editor";
|
||||
import { MakeOptional, TSearchEntityRequestPayload, TSearchResponse } from "@plane/types";
|
||||
import { cn } from "@plane/utils";
|
||||
// components
|
||||
import { EditorMentionsRoot } from "@/components/editor";
|
||||
// hooks
|
||||
import { useEditorConfig, useEditorMention } from "@/hooks/editor";
|
||||
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";
|
||||
|
||||
type DocumentEditorWrapperProps = MakeOptional<
|
||||
Omit<IDocumentEditorProps, "fileHandler" | "mentionHandler" | "embedHandler" | "user">,
|
||||
"disabledExtensions" | "editable" | "flaggedExtensions"
|
||||
> & {
|
||||
embedHandler?: Partial<IDocumentEditorProps["embedHandler"]>;
|
||||
workspaceSlug: string;
|
||||
workspaceId: string;
|
||||
projectId?: string;
|
||||
} & (
|
||||
| {
|
||||
editable: false;
|
||||
}
|
||||
| {
|
||||
editable: true;
|
||||
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
|
||||
uploadFile: TFileHandler["upload"];
|
||||
}
|
||||
);
|
||||
|
||||
export const DocumentEditor = forwardRef<EditorRefApi, DocumentEditorWrapperProps>((props, ref) => {
|
||||
const {
|
||||
containerClassName,
|
||||
editable,
|
||||
embedHandler,
|
||||
workspaceSlug,
|
||||
workspaceId,
|
||||
projectId,
|
||||
disabledExtensions: additionalDisabledExtensions = [],
|
||||
...rest
|
||||
} = props;
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
// editor flaggings
|
||||
const { document: documentEditorExtensions } = useEditorFlagging(workspaceSlug);
|
||||
// use editor mention
|
||||
const { fetchMentions } = useEditorMention({
|
||||
searchEntity: editable ? async (payload) => await props.searchMentionCallback(payload) : async () => ({}),
|
||||
});
|
||||
// editor config
|
||||
const { getEditorFileHandlers } = useEditorConfig();
|
||||
// issue-embed
|
||||
const { issueEmbedProps } = useIssueEmbed({
|
||||
projectId,
|
||||
workspaceSlug,
|
||||
});
|
||||
|
||||
return (
|
||||
<DocumentEditorWithRef
|
||||
ref={ref}
|
||||
disabledExtensions={[...documentEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
|
||||
editable={editable}
|
||||
flaggedExtensions={documentEditorExtensions.flagged}
|
||||
fileHandler={getEditorFileHandlers({
|
||||
projectId,
|
||||
uploadFile: editable ? props.uploadFile : async () => "",
|
||||
workspaceId,
|
||||
workspaceSlug,
|
||||
})}
|
||||
mentionHandler={{
|
||||
searchCallback: async (query) => {
|
||||
const res = await fetchMentions(query);
|
||||
if (!res) throw new Error("Failed in fetching mentions");
|
||||
return res;
|
||||
},
|
||||
renderComponent: EditorMentionsRoot,
|
||||
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
|
||||
}}
|
||||
embedHandler={{
|
||||
issue: issueEmbedProps,
|
||||
...embedHandler,
|
||||
}}
|
||||
{...rest}
|
||||
containerClassName={cn("relative pl-3 pb-3", containerClassName)}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
DocumentEditor.displayName = "DocumentEditor";
|
||||
@@ -1,5 +1,5 @@
|
||||
export * from "./embeds";
|
||||
export * from "./lite-text-editor";
|
||||
export * from "./lite-text";
|
||||
export * from "./pdf";
|
||||
export * from "./rich-text-editor";
|
||||
export * from "./rich-text";
|
||||
export * from "./sticky-editor";
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from "./lite-text-editor";
|
||||
export * from "./lite-text-read-only-editor";
|
||||
export * from "./toolbar";
|
||||
3
apps/web/core/components/editor/lite-text/index.ts
Normal file
3
apps/web/core/components/editor/lite-text/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./editor";
|
||||
export * from "./read-only-editor";
|
||||
export * from "./toolbar";
|
||||
@@ -1 +0,0 @@
|
||||
export * from "./rich-text-editor";
|
||||
1
apps/web/core/components/editor/rich-text/index.ts
Normal file
1
apps/web/core/components/editor/rich-text/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./editor";
|
||||
@@ -10,7 +10,7 @@ import { EFileAssetType, TIssue } from "@plane/types";
|
||||
import { Loader } from "@plane/ui";
|
||||
import { getDescriptionPlaceholderI18n, getTabIndex } from "@plane/utils";
|
||||
// components
|
||||
import { RichTextEditor } from "@/components/editor/rich-text-editor/rich-text-editor";
|
||||
import { RichTextEditor } from "@/components/editor/rich-text/editor";
|
||||
// hooks
|
||||
import { useEditorAsset, useProjectInbox } from "@/hooks/store";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import { DocumentReadOnlyEditorWithRef, TDisplayConfig } from "@plane/editor";
|
||||
import { TDisplayConfig } from "@plane/editor";
|
||||
import { TPageVersion } from "@plane/types";
|
||||
import { Loader } from "@plane/ui";
|
||||
// components
|
||||
import { EditorMentionsRoot } from "@/components/editor";
|
||||
import { DocumentEditor } from "@/components/editor/document/editor";
|
||||
// hooks
|
||||
import { useEditorConfig } from "@/hooks/editor";
|
||||
import { useMember, useWorkspace } from "@/hooks/store";
|
||||
import { useWorkspace } from "@/hooks/store";
|
||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||
// plane web hooks
|
||||
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
|
||||
import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed";
|
||||
|
||||
export type TVersionEditorProps = {
|
||||
activeVersion: string | null;
|
||||
@@ -21,23 +17,12 @@ export type TVersionEditorProps = {
|
||||
|
||||
export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props) => {
|
||||
const { activeVersion, versionDetails } = props;
|
||||
// store hooks
|
||||
const { getUserDetails } = useMember();
|
||||
// params
|
||||
const { workspaceSlug, projectId } = useParams();
|
||||
// store hooks
|
||||
const { getWorkspaceBySlug } = useWorkspace();
|
||||
// derived values
|
||||
const workspaceDetails = getWorkspaceBySlug(workspaceSlug?.toString() ?? "");
|
||||
// editor flaggings
|
||||
const { document: documentEditorExtensions } = useEditorFlagging(workspaceSlug?.toString() ?? "");
|
||||
// editor config
|
||||
const { getReadOnlyEditorFileHandlers } = useEditorConfig();
|
||||
// issue-embed
|
||||
const { issueEmbedProps } = useIssueEmbed({
|
||||
projectId: projectId?.toString() ?? "",
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
});
|
||||
// page filters
|
||||
const { fontSize, fontStyle } = usePageFilters();
|
||||
|
||||
@@ -89,32 +74,21 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
|
||||
</div>
|
||||
);
|
||||
|
||||
const description = versionDetails?.description_html;
|
||||
if (description === undefined || description?.trim() === "") return null;
|
||||
const description = versionDetails?.description_json;
|
||||
if (!description) return null;
|
||||
|
||||
return (
|
||||
<DocumentReadOnlyEditorWithRef
|
||||
<DocumentEditor
|
||||
key={activeVersion ?? ""}
|
||||
editable={false}
|
||||
id={activeVersion ?? ""}
|
||||
initialValue={description ?? "<p></p>"}
|
||||
value={description}
|
||||
containerClassName="p-0 pb-64 border-none"
|
||||
disabledExtensions={documentEditorExtensions.disabled}
|
||||
flaggedExtensions={documentEditorExtensions.flagged}
|
||||
displayConfig={displayConfig}
|
||||
editorClassName="pl-10"
|
||||
fileHandler={getReadOnlyEditorFileHandlers({
|
||||
projectId: projectId?.toString() ?? "",
|
||||
workspaceId: workspaceDetails?.id ?? "",
|
||||
workspaceSlug: workspaceSlug?.toString() ?? "",
|
||||
})}
|
||||
mentionHandler={{
|
||||
renderComponent: (props) => <EditorMentionsRoot {...props} />,
|
||||
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
|
||||
}}
|
||||
embedHandler={{
|
||||
issue: {
|
||||
widgetCallback: issueEmbedProps.widgetCallback,
|
||||
},
|
||||
}}
|
||||
projectId={projectId?.toString()}
|
||||
workspaceId={workspaceDetails?.id ?? ""}
|
||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user