refactor: editor code splitting (#6102)

* fix: merge conflicts resolved from preview

* fix: space app build errors

* fix: product updates modal

* fix: build errors

* fix: lite text read only editor

* refactor: additional options push logic
This commit is contained in:
Aaryan Khandelwal 2024-12-02 13:51:27 +05:30 committed by GitHub
parent 11bfbe560a
commit 9f14167ef5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 218 additions and 46 deletions

View file

@ -0,0 +1,12 @@
import { Extensions } from "@tiptap/core";
// types
import { TExtensions } from "@/types";
type Props = {
disabledExtensions: TExtensions[];
};
export const CoreEditorAdditionalExtensions = (props: Props): Extensions => {
const {} = props;
return [];
};

View file

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

View file

@ -0,0 +1,12 @@
import { Extensions } from "@tiptap/core";
// types
import { TExtensions } from "@/types";
type Props = {
disabledExtensions: TExtensions[];
};
export const CoreReadOnlyEditorAdditionalExtensions = (props: Props): Extensions => {
const {} = props;
return [];
};

View file

@ -0,0 +1,3 @@
import { Extensions } from "@tiptap/core";
export const CoreEditorAdditionalExtensionsWithoutProps: Extensions = [];

View file

@ -15,7 +15,13 @@ type Props = {
export const DocumentEditorAdditionalExtensions = (_props: Props) => { export const DocumentEditorAdditionalExtensions = (_props: Props) => {
const { disabledExtensions } = _props; const { disabledExtensions } = _props;
const extensions: Extensions = disabledExtensions?.includes("slash-commands") ? [] : [SlashCommands()]; const extensions: Extensions = disabledExtensions?.includes("slash-commands")
? []
: [
SlashCommands({
disabledExtensions,
}),
];
return extensions; return extensions;
}; };

View file

@ -1 +1,3 @@
export * from "./core";
export * from "./document-extensions"; export * from "./document-extensions";
export * from "./slash-commands";

View file

@ -0,0 +1,14 @@
// extensions
import { TSlashCommandAdditionalOption } from "@/extensions";
// types
import { TExtensions } from "@/types";
type Props = {
disabledExtensions: TExtensions[];
};
export const coreEditorAdditionalSlashCommandOptions = (props: Props): TSlashCommandAdditionalOption[] => {
const {} = props;
const options: TSlashCommandAdditionalOption[] = [];
return options;
};

View file

@ -15,6 +15,7 @@ import { EditorReadOnlyRefApi, ICollaborativeDocumentReadOnlyEditor } from "@/ty
const CollaborativeDocumentReadOnlyEditor = (props: ICollaborativeDocumentReadOnlyEditor) => { const CollaborativeDocumentReadOnlyEditor = (props: ICollaborativeDocumentReadOnlyEditor) => {
const { const {
containerClassName, containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG, displayConfig = DEFAULT_DISPLAY_CONFIG,
editorClassName = "", editorClassName = "",
embedHandler, embedHandler,
@ -37,6 +38,7 @@ const CollaborativeDocumentReadOnlyEditor = (props: ICollaborativeDocumentReadOn
} }
const { editor, hasServerConnectionFailed, hasServerSynced } = useReadOnlyCollaborativeEditor({ const { editor, hasServerConnectionFailed, hasServerSynced } = useReadOnlyCollaborativeEditor({
disabledExtensions,
editorClassName, editorClassName,
extensions, extensions,
fileHandler, fileHandler,

View file

@ -10,9 +10,10 @@ import { getEditorClassNames } from "@/helpers/common";
// hooks // hooks
import { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; import { useReadOnlyEditor } from "@/hooks/use-read-only-editor";
// types // types
import { EditorReadOnlyRefApi, IMentionHighlight, TDisplayConfig, TFileHandler } from "@/types"; import { EditorReadOnlyRefApi, IMentionHighlight, TDisplayConfig, TExtensions, TFileHandler } from "@/types";
interface IDocumentReadOnlyEditor { interface IDocumentReadOnlyEditor {
disabledExtensions: TExtensions[];
id: string; id: string;
initialValue: string; initialValue: string;
containerClassName: string; containerClassName: string;
@ -31,6 +32,7 @@ interface IDocumentReadOnlyEditor {
const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => {
const { const {
containerClassName, containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG, displayConfig = DEFAULT_DISPLAY_CONFIG,
editorClassName = "", editorClassName = "",
embedHandler, embedHandler,
@ -51,6 +53,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => {
} }
const editor = useReadOnlyEditor({ const editor = useReadOnlyEditor({
disabledExtensions,
editorClassName, editorClassName,
extensions, extensions,
fileHandler, fileHandler,

View file

@ -19,6 +19,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
const { const {
children, children,
containerClassName, containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG, displayConfig = DEFAULT_DISPLAY_CONFIG,
editorClassName = "", editorClassName = "",
extensions, extensions,
@ -37,6 +38,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
} = props; } = props;
const editor = useEditor({ const editor = useEditor({
disabledExtensions,
editorClassName, editorClassName,
enableHistory: true, enableHistory: true,
extensions, extensions,

View file

@ -12,6 +12,7 @@ import { IReadOnlyEditorProps } from "@/types";
export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => {
const { const {
containerClassName, containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG, displayConfig = DEFAULT_DISPLAY_CONFIG,
editorClassName = "", editorClassName = "",
fileHandler, fileHandler,
@ -22,6 +23,7 @@ export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => {
} = props; } = props;
const editor = useReadOnlyEditor({ const editor = useReadOnlyEditor({
disabledExtensions,
editorClassName, editorClassName,
fileHandler, fileHandler,
forwardedRef, forwardedRef,

View file

@ -8,12 +8,7 @@ import { SideMenuExtension, SlashCommands } from "@/extensions";
import { EditorRefApi, IRichTextEditor } from "@/types"; import { EditorRefApi, IRichTextEditor } from "@/types";
const RichTextEditor = (props: IRichTextEditor) => { const RichTextEditor = (props: IRichTextEditor) => {
const { const { disabledExtensions, dragDropEnabled, bubbleMenuEnabled = true, extensions: externalExtensions = [] } = props;
disabledExtensions,
dragDropEnabled,
bubbleMenuEnabled = true,
extensions: externalExtensions = [],
} = props;
const getExtensions = useCallback(() => { const getExtensions = useCallback(() => {
const extensions = [ const extensions = [
@ -24,7 +19,11 @@ const RichTextEditor = (props: IRichTextEditor) => {
}), }),
]; ];
if (!disabledExtensions?.includes("slash-commands")) { if (!disabledExtensions?.includes("slash-commands")) {
extensions.push(SlashCommands()); extensions.push(
SlashCommands({
disabledExtensions,
})
);
} }
return extensions; return extensions;

View file

@ -19,6 +19,8 @@ import { TableHeader, TableCell, TableRow, Table } from "./table";
import { CustomTextAlignExtension } from "./text-align"; import { CustomTextAlignExtension } from "./text-align";
import { CustomCalloutExtensionConfig } from "./callout/extension-config"; import { CustomCalloutExtensionConfig } from "./callout/extension-config";
import { CustomColorExtension } from "./custom-color"; import { CustomColorExtension } from "./custom-color";
// plane editor extensions
import { CoreEditorAdditionalExtensionsWithoutProps } from "@/plane-editor/extensions/core/without-props";
export const CoreEditorExtensionsWithoutProps = [ export const CoreEditorExtensionsWithoutProps = [
StarterKit.configure({ StarterKit.configure({
@ -89,6 +91,7 @@ export const CoreEditorExtensionsWithoutProps = [
CustomTextAlignExtension, CustomTextAlignExtension,
CustomCalloutExtensionConfig, CustomCalloutExtensionConfig,
CustomColorExtension, CustomColorExtension,
...CoreEditorAdditionalExtensionsWithoutProps,
]; ];
export const DocumentEditorExtensionsWithoutProps = [IssueWidgetWithoutProps()]; export const DocumentEditorExtensionsWithoutProps = [IssueWidgetWithoutProps()];

View file

@ -1,3 +1,4 @@
import { Extensions } from "@tiptap/core";
import CharacterCount from "@tiptap/extension-character-count"; import CharacterCount from "@tiptap/extension-character-count";
import Placeholder from "@tiptap/extension-placeholder"; import Placeholder from "@tiptap/extension-placeholder";
import TaskItem from "@tiptap/extension-task-item"; import TaskItem from "@tiptap/extension-task-item";
@ -32,9 +33,12 @@ import {
// helpers // helpers
import { isValidHttpUrl } from "@/helpers/common"; import { isValidHttpUrl } from "@/helpers/common";
// types // types
import { IMentionHighlight, IMentionSuggestion, TFileHandler } from "@/types"; import { IMentionHighlight, IMentionSuggestion, TExtensions, TFileHandler } from "@/types";
// plane editor extensions
import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions";
type TArguments = { type TArguments = {
disabledExtensions: TExtensions[];
enableHistory: boolean; enableHistory: boolean;
fileHandler: TFileHandler; fileHandler: TFileHandler;
mentionConfig: { mentionConfig: {
@ -45,8 +49,8 @@ type TArguments = {
tabIndex?: number; tabIndex?: number;
}; };
export const CoreEditorExtensions = (args: TArguments) => { export const CoreEditorExtensions = (args: TArguments): Extensions => {
const { enableHistory, fileHandler, mentionConfig, placeholder, tabIndex } = args; const { disabledExtensions, enableHistory, fileHandler, mentionConfig, placeholder, tabIndex } = args;
return [ return [
StarterKit.configure({ StarterKit.configure({
@ -162,5 +166,8 @@ export const CoreEditorExtensions = (args: TArguments) => {
CustomTextAlignExtension, CustomTextAlignExtension,
CustomCalloutExtension, CustomCalloutExtension,
CustomColorExtension, CustomColorExtension,
...CoreEditorAdditionalExtensions({
disabledExtensions,
}),
]; ];
}; };

View file

@ -1,3 +1,4 @@
import { Extensions } from "@tiptap/core";
import CharacterCount from "@tiptap/extension-character-count"; import CharacterCount from "@tiptap/extension-character-count";
import TaskItem from "@tiptap/extension-task-item"; import TaskItem from "@tiptap/extension-task-item";
import TaskList from "@tiptap/extension-task-list"; import TaskList from "@tiptap/extension-task-list";
@ -28,17 +29,20 @@ import {
// helpers // helpers
import { isValidHttpUrl } from "@/helpers/common"; import { isValidHttpUrl } from "@/helpers/common";
// types // types
import { IMentionHighlight, TFileHandler } from "@/types"; import { IMentionHighlight, TExtensions, TFileHandler } from "@/types";
// plane editor extensions
import { CoreReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extensions";
type Props = { type Props = {
disabledExtensions: TExtensions[];
fileHandler: Pick<TFileHandler, "getAssetSrc">; fileHandler: Pick<TFileHandler, "getAssetSrc">;
mentionConfig: { mentionConfig: {
mentionHighlights?: () => Promise<IMentionHighlight[]>; mentionHighlights?: () => Promise<IMentionHighlight[]>;
}; };
}; };
export const CoreReadOnlyEditorExtensions = (props: Props) => { export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => {
const { fileHandler, mentionConfig } = props; const { disabledExtensions, fileHandler, mentionConfig } = props;
return [ return [
StarterKit.configure({ StarterKit.configure({
@ -128,5 +132,8 @@ export const CoreReadOnlyEditorExtensions = (props: Props) => {
HeadingListExtension, HeadingListExtension,
CustomTextAlignExtension, CustomTextAlignExtension,
CustomCalloutReadOnlyExtension, CustomCalloutReadOnlyExtension,
...CoreReadOnlyEditorAdditionalExtensions({
disabledExtensions,
}),
]; ];
}; };

View file

@ -39,17 +39,27 @@ import {
setText, setText,
} from "@/helpers/editor-commands"; } from "@/helpers/editor-commands";
// types // types
import { CommandProps, ISlashCommandItem } from "@/types"; import { CommandProps, ISlashCommandItem, TExtensions, TSlashCommandSectionKeys } from "@/types";
// plane editor extensions
import { coreEditorAdditionalSlashCommandOptions } from "@/plane-editor/extensions";
// local types
import { TSlashCommandAdditionalOption } from "./root";
export type TSlashCommandSection = { export type TSlashCommandSection = {
key: string; key: TSlashCommandSectionKeys;
title?: string; title?: string;
items: ISlashCommandItem[]; items: ISlashCommandItem[];
}; };
type TArgs = {
additionalOptions?: TSlashCommandAdditionalOption[];
disabledExtensions: TExtensions[];
};
export const getSlashCommandFilteredSections = export const getSlashCommandFilteredSections =
(additionalOptions?: ISlashCommandItem[]) => (args: TArgs) =>
({ query }: { query: string }): TSlashCommandSection[] => { ({ query }: { query: string }): TSlashCommandSection[] => {
const { additionalOptions, disabledExtensions } = args;
const SLASH_COMMAND_SECTIONS: TSlashCommandSection[] = [ const SLASH_COMMAND_SECTIONS: TSlashCommandSection[] = [
{ {
key: "general", key: "general",
@ -201,7 +211,7 @@ export const getSlashCommandFilteredSections =
], ],
}, },
{ {
key: "text-color", key: "text-colors",
title: "Colors", title: "Colors",
items: [ items: [
{ {
@ -242,7 +252,7 @@ export const getSlashCommandFilteredSections =
], ],
}, },
{ {
key: "background-color", key: "background-colors",
title: "Background colors", title: "Background colors",
items: [ items: [
{ {
@ -279,8 +289,19 @@ export const getSlashCommandFilteredSections =
}, },
]; ];
additionalOptions?.map((item) => { [
SLASH_COMMAND_SECTIONS?.[0]?.items.push(item); ...(additionalOptions ?? []),
...coreEditorAdditionalSlashCommandOptions({
disabledExtensions,
}),
]?.forEach((item) => {
const sectionToPushTo = SLASH_COMMAND_SECTIONS.find((s) => s.key === item.section) ?? SLASH_COMMAND_SECTIONS[0];
const itemIndexToPushAfter = sectionToPushTo.items.findIndex((i) => i.commandKey === item.pushAfter);
if (itemIndexToPushAfter !== -1) {
sectionToPushTo.items.splice(itemIndexToPushAfter + 1, 0, item);
} else {
sectionToPushTo.items.push(item);
}
}); });
const filteredSlashSections = SLASH_COMMAND_SECTIONS.map((section) => ({ const filteredSlashSections = SLASH_COMMAND_SECTIONS.map((section) => ({

View file

@ -3,7 +3,7 @@ import { ReactRenderer } from "@tiptap/react";
import Suggestion, { SuggestionOptions } from "@tiptap/suggestion"; import Suggestion, { SuggestionOptions } from "@tiptap/suggestion";
import tippy from "tippy.js"; import tippy from "tippy.js";
// types // types
import { ISlashCommandItem } from "@/types"; import { ISlashCommandItem, TEditorCommands, TExtensions, TSlashCommandSectionKeys } from "@/types";
// components // components
import { getSlashCommandFilteredSections } from "./command-items-list"; import { getSlashCommandFilteredSections } from "./command-items-list";
import { SlashCommandsMenu, SlashCommandsMenuProps } from "./command-menu"; import { SlashCommandsMenu, SlashCommandsMenuProps } from "./command-menu";
@ -12,6 +12,11 @@ export type SlashCommandOptions = {
suggestion: Omit<SuggestionOptions, "editor">; suggestion: Omit<SuggestionOptions, "editor">;
}; };
export type TSlashCommandAdditionalOption = ISlashCommandItem & {
section: TSlashCommandSectionKeys;
pushAfter: TEditorCommands;
};
const Command = Extension.create<SlashCommandOptions>({ const Command = Extension.create<SlashCommandOptions>({
name: "slash-command", name: "slash-command",
addOptions() { addOptions() {
@ -102,10 +107,15 @@ const renderItems = () => {
}; };
}; };
export const SlashCommands = (additionalOptions?: ISlashCommandItem[]) => type TExtensionProps = {
additionalOptions?: TSlashCommandAdditionalOption[];
disabledExtensions: TExtensions[];
};
export const SlashCommands = (props: TExtensionProps) =>
Command.configure({ Command.configure({
suggestion: { suggestion: {
items: getSlashCommandFilteredSections(additionalOptions), items: getSlashCommandFilteredSections(props),
render: renderItems, render: renderItems,
}, },
}); });

View file

@ -75,6 +75,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
}, [provider, id]); }, [provider, id]);
const editor = useEditor({ const editor = useEditor({
disabledExtensions,
id, id,
onTransaction, onTransaction,
editorProps, editorProps,

View file

@ -16,12 +16,20 @@ import { IMarking, scrollSummary, scrollToNodeViaDOMCoordinates } from "@/helper
// props // props
import { CoreEditorProps } from "@/props"; import { CoreEditorProps } from "@/props";
// types // types
import { EditorRefApi, IMentionHighlight, IMentionSuggestion, TEditorCommands, TFileHandler } from "@/types"; import {
EditorRefApi,
IMentionHighlight,
IMentionSuggestion,
TEditorCommands,
TExtensions,
TFileHandler,
} from "@/types";
export interface CustomEditorProps { export interface CustomEditorProps {
editorClassName: string; editorClassName: string;
editorProps?: EditorProps; editorProps?: EditorProps;
enableHistory: boolean; enableHistory: boolean;
disabledExtensions: TExtensions[];
extensions?: any; extensions?: any;
fileHandler: TFileHandler; fileHandler: TFileHandler;
forwardedRef?: MutableRefObject<EditorRefApi | null>; forwardedRef?: MutableRefObject<EditorRefApi | null>;
@ -45,6 +53,7 @@ export interface CustomEditorProps {
export const useEditor = (props: CustomEditorProps) => { export const useEditor = (props: CustomEditorProps) => {
const { const {
disabledExtensions,
editorClassName, editorClassName,
editorProps = {}, editorProps = {},
enableHistory, enableHistory,
@ -79,6 +88,7 @@ export const useEditor = (props: CustomEditorProps) => {
}, },
extensions: [ extensions: [
...CoreEditorExtensions({ ...CoreEditorExtensions({
disabledExtensions,
enableHistory, enableHistory,
fileHandler, fileHandler,
mentionConfig: { mentionConfig: {

View file

@ -11,6 +11,7 @@ import { TReadOnlyCollaborativeEditorProps } from "@/types";
export const useReadOnlyCollaborativeEditor = (props: TReadOnlyCollaborativeEditorProps) => { export const useReadOnlyCollaborativeEditor = (props: TReadOnlyCollaborativeEditorProps) => {
const { const {
disabledExtensions,
editorClassName, editorClassName,
editorProps = {}, editorProps = {},
extensions, extensions,
@ -66,6 +67,7 @@ export const useReadOnlyCollaborativeEditor = (props: TReadOnlyCollaborativeEdit
}, [provider, id]); }, [provider, id]);
const editor = useReadOnlyEditor({ const editor = useReadOnlyEditor({
disabledExtensions,
editorProps, editorProps,
editorClassName, editorClassName,
extensions: [ extensions: [

View file

@ -11,14 +11,15 @@ import { IMarking, scrollSummary } from "@/helpers/scroll-to-node";
// props // props
import { CoreReadOnlyEditorProps } from "@/props"; import { CoreReadOnlyEditorProps } from "@/props";
// types // types
import { EditorReadOnlyRefApi, IMentionHighlight, TFileHandler } from "@/types"; import { EditorReadOnlyRefApi, IMentionHighlight, TExtensions, TFileHandler } from "@/types";
interface CustomReadOnlyEditorProps { interface CustomReadOnlyEditorProps {
initialValue?: string; disabledExtensions: TExtensions[];
editorClassName: string; editorClassName: string;
forwardedRef?: MutableRefObject<EditorReadOnlyRefApi | null>;
extensions?: any;
editorProps?: EditorProps; editorProps?: EditorProps;
extensions?: any;
forwardedRef?: MutableRefObject<EditorReadOnlyRefApi | null>;
initialValue?: string;
fileHandler: Pick<TFileHandler, "getAssetSrc">; fileHandler: Pick<TFileHandler, "getAssetSrc">;
handleEditorReady?: (value: boolean) => void; handleEditorReady?: (value: boolean) => void;
mentionHandler: { mentionHandler: {
@ -29,6 +30,7 @@ interface CustomReadOnlyEditorProps {
export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => { export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => {
const { const {
disabledExtensions,
initialValue, initialValue,
editorClassName, editorClassName,
forwardedRef, forwardedRef,
@ -54,6 +56,7 @@ export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => {
}, },
extensions: [ extensions: [
...CoreReadOnlyEditorExtensions({ ...CoreReadOnlyEditorExtensions({
disabledExtensions,
mentionConfig: { mentionConfig: {
mentionHighlights: mentionHandler.highlights, mentionHighlights: mentionHandler.highlights,
}, },

View file

@ -20,7 +20,7 @@ export type TServerHandler = {
}; };
type TCollaborativeEditorHookProps = { type TCollaborativeEditorHookProps = {
disabledExtensions?: TExtensions[]; disabledExtensions: TExtensions[];
editorClassName: string; editorClassName: string;
editorProps?: EditorProps; editorProps?: EditorProps;
extensions?: Extensions; extensions?: Extensions;

View file

@ -104,7 +104,7 @@ export interface EditorRefApi extends EditorReadOnlyRefApi {
export interface IEditorProps { export interface IEditorProps {
containerClassName?: string; containerClassName?: string;
displayConfig?: TDisplayConfig; displayConfig?: TDisplayConfig;
disabledExtensions?: TExtensions[]; disabledExtensions: TExtensions[];
editorClassName?: string; editorClassName?: string;
fileHandler: TFileHandler; fileHandler: TFileHandler;
forwardedRef?: React.MutableRefObject<EditorRefApi | null>; forwardedRef?: React.MutableRefObject<EditorRefApi | null>;
@ -146,6 +146,7 @@ export interface ICollaborativeDocumentEditor
// read only editor props // read only editor props
export interface IReadOnlyEditorProps { export interface IReadOnlyEditorProps {
containerClassName?: string; containerClassName?: string;
disabledExtensions: TExtensions[];
displayConfig?: TDisplayConfig; displayConfig?: TDisplayConfig;
editorClassName?: string; editorClassName?: string;
fileHandler: Pick<TFileHandler, "getAssetSrc">; fileHandler: Pick<TFileHandler, "getAssetSrc">;

View file

@ -8,6 +8,8 @@ export type CommandProps = {
range: Range; range: Range;
}; };
export type TSlashCommandSectionKeys = "general" | "text-colors" | "background-colors";
export type ISlashCommandItem = { export type ISlashCommandItem = {
commandKey: TEditorCommands; commandKey: TEditorCommands;
key: string; key: string;

View file

@ -10,7 +10,8 @@ import { isCommentEmpty } from "@/helpers/string.helper";
// hooks // hooks
import { useMention } from "@/hooks/use-mention"; import { useMention } from "@/hooks/use-mention";
interface LiteTextEditorWrapperProps extends Omit<ILiteTextEditor, "fileHandler" | "mentionHandler"> { interface LiteTextEditorWrapperProps
extends Omit<ILiteTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
anchor: string; anchor: string;
workspaceId: string; workspaceId: string;
isSubmitting?: boolean; isSubmitting?: boolean;
@ -41,6 +42,7 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
<div className="border border-custom-border-200 rounded p-3 space-y-3"> <div className="border border-custom-border-200 rounded p-3 space-y-3">
<LiteTextEditorWithRef <LiteTextEditorWithRef
ref={ref} ref={ref}
disabledExtensions={[]}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
anchor, anchor,
uploadFile, uploadFile,

View file

@ -7,7 +7,10 @@ import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// hooks // hooks
import { useMention } from "@/hooks/use-mention"; import { useMention } from "@/hooks/use-mention";
type LiteTextReadOnlyEditorWrapperProps = Omit<ILiteTextReadOnlyEditor, "fileHandler" | "mentionHandler"> & { type LiteTextReadOnlyEditorWrapperProps = Omit<
ILiteTextReadOnlyEditor,
"disabledExtensions" | "fileHandler" | "mentionHandler"
> & {
anchor: string; anchor: string;
}; };
@ -18,6 +21,7 @@ export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Lit
return ( return (
<LiteTextReadOnlyEditorWithRef <LiteTextReadOnlyEditorWithRef
ref={ref} ref={ref}
disabledExtensions={[]}
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({
anchor, anchor,
})} })}

View file

@ -1,12 +1,11 @@
import React, { forwardRef } from "react"; import React, { forwardRef } from "react";
// editor // editor
import { EditorRefApi, IMentionHighlight, IRichTextEditor, RichTextEditorWithRef } from "@plane/editor"; import { EditorRefApi, IMentionHighlight, IRichTextEditor, RichTextEditorWithRef } from "@plane/editor";
// types
// helpers // helpers
import { cn } from "@/helpers/common.helper";
import { getEditorFileHandlers } from "@/helpers/editor.helper"; import { getEditorFileHandlers } from "@/helpers/editor.helper";
interface RichTextEditorWrapperProps extends Omit<IRichTextEditor, "fileHandler" | "mentionHandler"> { interface RichTextEditorWrapperProps
extends Omit<IRichTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
uploadFile: (file: File) => Promise<string>; uploadFile: (file: File) => Promise<string>;
} }
@ -27,6 +26,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
suggestions: undefined, suggestions: undefined,
}} }}
ref={ref} ref={ref}
disabledExtensions={[]}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
uploadFile, uploadFile,
workspaceId: "", workspaceId: "",

View file

@ -7,7 +7,10 @@ import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// hooks // hooks
import { useMention } from "@/hooks/use-mention"; import { useMention } from "@/hooks/use-mention";
type RichTextReadOnlyEditorWrapperProps = Omit<IRichTextReadOnlyEditor, "fileHandler" | "mentionHandler"> & { type RichTextReadOnlyEditorWrapperProps = Omit<
IRichTextReadOnlyEditor,
"disabledExtensions" | "fileHandler" | "mentionHandler"
> & {
anchor: string; anchor: string;
}; };
@ -18,6 +21,7 @@ export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Ric
return ( return (
<RichTextReadOnlyEditorWithRef <RichTextReadOnlyEditorWithRef
ref={ref} ref={ref}
disabledExtensions={[]}
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({
anchor, anchor,
})} })}

View file

@ -4,10 +4,14 @@ import { TExtensions } from "@plane/editor";
/** /**
* @description extensions disabled in various editors * @description extensions disabled in various editors
*/ */
export const useEditorFlagging = (): { export const useEditorFlagging = (
workspaceSlug: string
): {
documentEditor: TExtensions[]; documentEditor: TExtensions[];
liteTextEditor: TExtensions[];
richTextEditor: TExtensions[]; richTextEditor: TExtensions[];
} => ({ } => ({
documentEditor: ["ai", "collaboration-cursor"], documentEditor: ["ai", "collaboration-cursor"],
liteTextEditor: ["ai", "collaboration-cursor"],
richTextEditor: ["ai", "collaboration-cursor"], richTextEditor: ["ai", "collaboration-cursor"],
}); });

View file

@ -14,9 +14,11 @@ import { isCommentEmpty } from "@/helpers/string.helper";
// hooks // hooks
import { useMember, useMention, useUser } from "@/hooks/store"; import { useMember, useMention, useUser } from "@/hooks/store";
// plane web hooks // plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { useFileSize } from "@/plane-web/hooks/use-file-size"; import { useFileSize } from "@/plane-web/hooks/use-file-size";
interface LiteTextEditorWrapperProps extends Omit<ILiteTextEditor, "fileHandler" | "mentionHandler"> { interface LiteTextEditorWrapperProps
extends Omit<ILiteTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
workspaceSlug: string; workspaceSlug: string;
workspaceId: string; workspaceId: string;
projectId: string; projectId: string;
@ -49,6 +51,8 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
getUserDetails, getUserDetails,
project: { getProjectMemberIds }, project: { getProjectMemberIds },
} = useMember(); } = useMember();
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// derived values // derived values
const projectMemberIds = getProjectMemberIds(projectId); const projectMemberIds = getProjectMemberIds(projectId);
const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite);
@ -72,6 +76,7 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
<div className="border border-custom-border-200 rounded p-3 space-y-3"> <div className="border border-custom-border-200 rounded p-3 space-y-3">
<LiteTextEditorWithRef <LiteTextEditorWithRef
ref={ref} ref={ref}
disabledExtensions={disabledExtensions}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
maxFileSize, maxFileSize,
projectId, projectId,

View file

@ -6,8 +6,13 @@ import { cn } from "@/helpers/common.helper";
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// hooks // hooks
import { useMention, useUser } from "@/hooks/store"; import { useMention, useUser } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
type LiteTextReadOnlyEditorWrapperProps = Omit<ILiteTextReadOnlyEditor, "fileHandler" | "mentionHandler"> & { type LiteTextReadOnlyEditorWrapperProps = Omit<
ILiteTextReadOnlyEditor,
"disabledExtensions" | "fileHandler" | "mentionHandler"
> & {
workspaceSlug: string; workspaceSlug: string;
projectId: string; projectId: string;
}; };
@ -19,10 +24,13 @@ export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Lit
const { mentionHighlights } = useMention({ const { mentionHighlights } = useMention({
user: currentUser, user: currentUser,
}); });
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
return ( return (
<LiteTextReadOnlyEditorWithRef <LiteTextReadOnlyEditorWithRef
ref={ref} ref={ref}
disabledExtensions={disabledExtensions}
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({
projectId, projectId,
workspaceSlug, workspaceSlug,

View file

@ -9,9 +9,11 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper";
// hooks // hooks
import { useMember, useMention, useUser } from "@/hooks/store"; import { useMember, useMention, useUser } from "@/hooks/store";
// plane web hooks // plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { useFileSize } from "@/plane-web/hooks/use-file-size"; import { useFileSize } from "@/plane-web/hooks/use-file-size";
interface RichTextEditorWrapperProps extends Omit<IRichTextEditor, "fileHandler" | "mentionHandler"> { interface RichTextEditorWrapperProps
extends Omit<IRichTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
workspaceSlug: string; workspaceSlug: string;
workspaceId: string; workspaceId: string;
projectId: string; projectId: string;
@ -26,6 +28,8 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
getUserDetails, getUserDetails,
project: { getProjectMemberIds }, project: { getProjectMemberIds },
} = useMember(); } = useMember();
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// derived values // derived values
const projectMemberIds = getProjectMemberIds(projectId); const projectMemberIds = getProjectMemberIds(projectId);
const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite);
@ -42,6 +46,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
return ( return (
<RichTextEditorWithRef <RichTextEditorWithRef
ref={ref} ref={ref}
disabledExtensions={disabledExtensions}
fileHandler={getEditorFileHandlers({ fileHandler={getEditorFileHandlers({
maxFileSize, maxFileSize,
projectId, projectId,

View file

@ -6,8 +6,13 @@ import { cn } from "@/helpers/common.helper";
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// hooks // hooks
import { useMention } from "@/hooks/store"; import { useMention } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
type RichTextReadOnlyEditorWrapperProps = Omit<IRichTextReadOnlyEditor, "fileHandler" | "mentionHandler"> & { type RichTextReadOnlyEditorWrapperProps = Omit<
IRichTextReadOnlyEditor,
"disabledExtensions" | "fileHandler" | "mentionHandler"
> & {
workspaceSlug: string; workspaceSlug: string;
projectId?: string; projectId?: string;
}; };
@ -15,10 +20,13 @@ type RichTextReadOnlyEditorWrapperProps = Omit<IRichTextReadOnlyEditor, "fileHan
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>( export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ workspaceSlug, projectId, ...props }, ref) => { ({ workspaceSlug, projectId, ...props }, ref) => {
const { mentionHighlights } = useMention({}); const { mentionHighlights } = useMention({});
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
return ( return (
<RichTextReadOnlyEditorWithRef <RichTextReadOnlyEditorWithRef
ref={ref} ref={ref}
disabledExtensions={disabledExtensions}
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({
projectId, projectId,
workspaceSlug, workspaceSlug,

View file

@ -59,6 +59,7 @@ export const ProductUpdatesModal: FC<ProductUpdatesModalProps> = observer((props
{data?.id && ( {data?.id && (
<DocumentReadOnlyEditorWithRef <DocumentReadOnlyEditorWithRef
ref={editorRef} ref={editorRef}
disabledExtensions={[]}
id={data.id} id={data.id}
initialValue={data.description_html ?? "<p></p>"} initialValue={data.description_html ?? "<p></p>"}
containerClassName="p-0 border-none" containerClassName="p-0 border-none"

View file

@ -84,7 +84,7 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
user: currentUser ?? undefined, user: currentUser ?? undefined,
}); });
// editor flaggings // editor flaggings
const { documentEditor } = useEditorFlagging(); const { documentEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// page filters // page filters
const { fontSize, fontStyle, isFullWidth } = usePageFilters(); const { fontSize, fontStyle, isFullWidth } = usePageFilters();
// issue-embed // issue-embed
@ -224,7 +224,7 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
realtimeConfig={realtimeConfig} realtimeConfig={realtimeConfig}
serverHandler={serverHandler} serverHandler={serverHandler}
user={userConfig} user={userConfig}
disabledExtensions={documentEditor} disabledExtensions={disabledExtensions}
aiHandler={{ aiHandler={{
menu: getAIMenu, menu: getAIMenu,
}} }}
@ -233,6 +233,7 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
<CollaborativeDocumentReadOnlyEditorWithRef <CollaborativeDocumentReadOnlyEditorWithRef
id={pageId} id={pageId}
ref={readOnlyEditorRef} ref={readOnlyEditorRef}
disabledExtensions={disabledExtensions}
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({
projectId: projectId?.toString() ?? "", projectId: projectId?.toString() ?? "",
workspaceSlug: workspaceSlug?.toString() ?? "", workspaceSlug: workspaceSlug?.toString() ?? "",

View file

@ -12,6 +12,7 @@ import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
import { useMember, useMention, useUser } from "@/hooks/store"; import { useMember, useMention, useUser } from "@/hooks/store";
import { usePageFilters } from "@/hooks/use-page-filters"; import { usePageFilters } from "@/hooks/use-page-filters";
// plane web hooks // plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed";
export type TVersionEditorProps = { export type TVersionEditorProps = {
@ -31,6 +32,8 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
getUserDetails, getUserDetails,
project: { getProjectMemberIds }, project: { getProjectMemberIds },
} = useMember(); } = useMember();
// editor flaggings
const { documentEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString() ?? "");
// derived values // derived values
const projectMemberIds = projectId ? getProjectMemberIds(projectId.toString()) : []; const projectMemberIds = projectId ? getProjectMemberIds(projectId.toString()) : [];
const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite);
@ -101,6 +104,7 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
id={activeVersion ?? ""} id={activeVersion ?? ""}
initialValue={description ?? "<p></p>"} initialValue={description ?? "<p></p>"}
containerClassName="p-0 pb-64 border-none" containerClassName="p-0 pb-64 border-none"
disabledExtensions={disabledExtensions}
displayConfig={displayConfig} displayConfig={displayConfig}
editorClassName="pl-10" editorClassName="pl-10"
fileHandler={getReadOnlyEditorFileHandlers({ fileHandler={getReadOnlyEditorFileHandlers({