mirror of
https://github.com/gosticks/plane.git
synced 2025-10-16 12:45:33 +00:00
[WIKI-345] chore: pass disabled and flagged extensions to block menu (#7152)
* chore: refactor editor * sync changes * feat: api service update * refactor : update sync * fix : package sync * fix: requested changes * fix : embedhandler type * fix : remove commands * refactor : space * refactor : rich lite editors * refactor : minor ce changes * chore : minor ui fix * package: tldjs * refactor : remove tldjs * refactor: flagged * refactor: flagged * chore : remove disbaled check in menu * refactor: fix space * refactor: NodeViewProps * refactor: type * refactor : update community types * refactor : remove external embed CE * remove : external embed config from ce * refactor : update disabled * chore: pass disabled * chore : update utils
This commit is contained in:
parent
8801ab0081
commit
0fe7da6265
@ -14,6 +14,7 @@ export abstract class APIService {
|
||||
this.axiosInstance = axios.create({
|
||||
baseURL,
|
||||
withCredentials: true,
|
||||
timeout: 20000,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => {
|
||||
return (
|
||||
comment?.trim() === "" ||
|
||||
comment === "<p></p>" ||
|
||||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"])
|
||||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"])
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
// plane imports
|
||||
// plane constants
|
||||
import { EIssueCommentAccessSpecifier } from "@plane/constants";
|
||||
// plane imports
|
||||
import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import type { MakeOptional } from "@plane/types";
|
||||
@ -87,7 +88,6 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
|
||||
// derived values
|
||||
const isEmpty = isCommentEmpty(props.initialValue);
|
||||
const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
||||
@ -59,7 +59,6 @@ export const StickyEditor = React.forwardRef<EditorRefApi, StickyEditorWrapperPr
|
||||
}
|
||||
// derived values
|
||||
const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("relative border border-custom-border-200 rounded", parentClassName)}
|
||||
|
||||
@ -12,7 +12,7 @@ const nextConfig = {
|
||||
return [
|
||||
{
|
||||
source: "/(.*)?",
|
||||
headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }],
|
||||
headers: [{ key: "X-Frame-Options", value: "DENY" }],
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
@ -108,6 +108,8 @@ const CollaborativeDocumentEditor: React.FC<ICollaborativeDocumentEditorProps> =
|
||||
isTouchDevice={!!isTouchDevice}
|
||||
isLoading={!hasServerSynced && !hasServerConnectionFailed}
|
||||
tabIndex={tabIndex}
|
||||
flaggedExtensions={flaggedExtensions}
|
||||
disabledExtensions={disabledExtensions}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -82,6 +82,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
|
||||
initialValue: value,
|
||||
mentionHandler,
|
||||
onChange,
|
||||
embedHandler,
|
||||
});
|
||||
|
||||
const editorContainerClassName = getEditorClassNames({
|
||||
@ -98,6 +99,8 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
|
||||
editorContainerClassName={cn(editorContainerClassName, "document-editor")}
|
||||
id={id}
|
||||
isTouchDevice={!!isTouchDevice}
|
||||
flaggedExtensions={flaggedExtensions}
|
||||
disabledExtensions={disabledExtensions}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@ import { cn } from "@plane/utils";
|
||||
import { DocumentContentLoader, EditorContainer, EditorContentWrapper } from "@/components/editors";
|
||||
import { AIFeaturesMenu, BlockMenu, EditorBubbleMenu } from "@/components/menus";
|
||||
// types
|
||||
import { TAIHandler, TDisplayConfig } from "@/types";
|
||||
import { IEditorProps, TAIHandler, TDisplayConfig } from "@/types";
|
||||
|
||||
type Props = {
|
||||
aiHandler?: TAIHandler;
|
||||
@ -18,6 +18,8 @@ type Props = {
|
||||
isLoading?: boolean;
|
||||
isTouchDevice: boolean;
|
||||
tabIndex?: number;
|
||||
flaggedExtensions?: IEditorProps["flaggedExtensions"];
|
||||
disabledExtensions?: IEditorProps["disabledExtensions"];
|
||||
};
|
||||
|
||||
export const PageRenderer = (props: Props) => {
|
||||
@ -32,6 +34,8 @@ export const PageRenderer = (props: Props) => {
|
||||
isLoading,
|
||||
isTouchDevice,
|
||||
tabIndex,
|
||||
flaggedExtensions,
|
||||
disabledExtensions,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@ -54,7 +58,11 @@ export const PageRenderer = (props: Props) => {
|
||||
{editor.isEditable && !isTouchDevice && (
|
||||
<div>
|
||||
{bubbleMenuEnabled && <EditorBubbleMenu editor={editor} />}
|
||||
<BlockMenu editor={editor} />
|
||||
<BlockMenu
|
||||
editor={editor}
|
||||
flaggedExtensions={flaggedExtensions}
|
||||
disabledExtensions={disabledExtensions}
|
||||
/>
|
||||
<AIFeaturesMenu menu={aiHandler?.menu} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -41,6 +41,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
|
||||
placeholder,
|
||||
tabIndex,
|
||||
value,
|
||||
embedHandler,
|
||||
} = props;
|
||||
|
||||
const editor = useEditor({
|
||||
@ -65,6 +66,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
|
||||
placeholder,
|
||||
tabIndex,
|
||||
value,
|
||||
embedHandler,
|
||||
});
|
||||
|
||||
const editorContainerClassName = getEditorClassNames({
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import { autoUpdate, flip, hide, shift, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
|
||||
import { Editor, useEditorState } from "@tiptap/react";
|
||||
import { FC, useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
// components
|
||||
import { LinkView, LinkViewProps } from "@/components/links";
|
||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||
// components
|
||||
import { getExtensionStorage } from "@/helpers/get-extension-storage";
|
||||
|
||||
type Props = {
|
||||
editor: Editor;
|
||||
@ -18,7 +22,7 @@ export const LinkViewContainer: FC<Props> = ({ editor, containerRef }) => {
|
||||
const editorState = useEditorState({
|
||||
editor,
|
||||
selector: ({ editor }: { editor: Editor }) => ({
|
||||
linkExtensionStorage: editor.storage.link,
|
||||
linkExtensionStorage: getExtensionStorage(editor, CORE_EXTENSIONS.CUSTOM_LINK),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -4,9 +4,12 @@ import { useCallback, useEffect, useRef } from "react";
|
||||
import tippy, { Instance } from "tippy.js";
|
||||
// constants
|
||||
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||
import { IEditorProps } from "@/types";
|
||||
|
||||
type Props = {
|
||||
editor: Editor;
|
||||
flaggedExtensions?: IEditorProps["flaggedExtensions"];
|
||||
disabledExtensions?: IEditorProps["disabledExtensions"];
|
||||
};
|
||||
|
||||
export const BlockMenu = (props: Props) => {
|
||||
|
||||
@ -81,6 +81,7 @@ declare module "@tiptap/core" {
|
||||
export type CustomLinkStorage = {
|
||||
isPreviewOpen: boolean;
|
||||
posToInsert: { from: number; to: number };
|
||||
isBubbleMenuOpen: boolean;
|
||||
};
|
||||
|
||||
export const CustomLinkExtension = Mark.create<LinkOptions, CustomLinkStorage>({
|
||||
|
||||
@ -29,7 +29,7 @@ import {
|
||||
// plane editor extensions
|
||||
import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions";
|
||||
// types
|
||||
import type { IEditorProps } from "@/types";
|
||||
import type { IEditorProps, TEmbedConfig } from "@/types";
|
||||
// local imports
|
||||
import { CustomImageExtension } from "./custom-image/extension";
|
||||
import { EmojiExtension } from "./emoji/extension";
|
||||
@ -45,9 +45,11 @@ type TArguments = Pick<
|
||||
| "mentionHandler"
|
||||
| "placeholder"
|
||||
| "tabIndex"
|
||||
| "embedHandler"
|
||||
> & {
|
||||
enableHistory: boolean;
|
||||
editable: boolean;
|
||||
embedHandler?: TEmbedConfig;
|
||||
};
|
||||
|
||||
export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
||||
@ -60,6 +62,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
||||
mentionHandler,
|
||||
placeholder,
|
||||
tabIndex,
|
||||
embedHandler,
|
||||
editable,
|
||||
} = args;
|
||||
|
||||
@ -115,6 +118,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
||||
disabledExtensions,
|
||||
flaggedExtensions,
|
||||
fileHandler,
|
||||
embedHandler,
|
||||
}),
|
||||
];
|
||||
|
||||
|
||||
@ -80,6 +80,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) =>
|
||||
);
|
||||
|
||||
const editor = useEditor({
|
||||
embedHandler,
|
||||
disabledExtensions,
|
||||
id,
|
||||
editable,
|
||||
|
||||
@ -32,6 +32,7 @@ export const useEditor = (props: TEditorHookProps) => {
|
||||
onAssetChange,
|
||||
onChange,
|
||||
onEditorFocus,
|
||||
embedHandler,
|
||||
onTransaction,
|
||||
placeholder,
|
||||
provider,
|
||||
@ -63,6 +64,7 @@ export const useEditor = (props: TEditorHookProps) => {
|
||||
mentionHandler,
|
||||
placeholder,
|
||||
tabIndex,
|
||||
embedHandler,
|
||||
}),
|
||||
...extensions,
|
||||
],
|
||||
|
||||
@ -21,6 +21,7 @@ const generalSelectors = [
|
||||
".image-component",
|
||||
".image-upload-component",
|
||||
".editor-callout-component",
|
||||
".editor-embed-component",
|
||||
].join(", ");
|
||||
|
||||
const maxScrollSpeed = 20;
|
||||
@ -103,6 +104,11 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip elements inside .editor-embed-component
|
||||
if (elem.closest(".editor-embed-component") && !elem.matches(".editor-embed-component")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// apply general selector
|
||||
if (elem.matches(generalSelectors)) {
|
||||
return elem;
|
||||
|
||||
@ -2,6 +2,7 @@ import type { Content, Extensions, JSONContent, RawCommands } from "@tiptap/core
|
||||
import type { MarkType, NodeType } from "@tiptap/pm/model";
|
||||
import type { Selection } from "@tiptap/pm/state";
|
||||
import type { EditorProps, EditorView } from "@tiptap/pm/view";
|
||||
import type { NodeViewProps as TNodeViewProps } from "@tiptap/react";
|
||||
// extension types
|
||||
import type { TTextAlign } from "@/extensions";
|
||||
// types
|
||||
@ -48,7 +49,8 @@ export type TEditorCommands =
|
||||
| "text-align"
|
||||
| "callout"
|
||||
| "attachment"
|
||||
| "emoji";
|
||||
| "emoji"
|
||||
| "external-embed";
|
||||
|
||||
export type TCommandExtraProps = {
|
||||
image: {
|
||||
@ -138,6 +140,7 @@ export type IEditorProps = {
|
||||
editorClassName?: string;
|
||||
editorProps?: EditorProps;
|
||||
extensions?: Extensions;
|
||||
embedHandler?: TEmbedConfig;
|
||||
flaggedExtensions: TExtensions[];
|
||||
fileHandler: TFileHandler;
|
||||
forwardedRef?: React.MutableRefObject<EditorRefApi | null>;
|
||||
@ -191,3 +194,5 @@ export type EditorEvents = {
|
||||
destroy: never;
|
||||
ready: { height: number };
|
||||
};
|
||||
|
||||
export type NodeViewProps = TNodeViewProps;
|
||||
|
||||
@ -13,6 +13,7 @@ type TCoreHookProps = Pick<
|
||||
| "handleEditorReady"
|
||||
| "isTouchDevice"
|
||||
| "onEditorFocus"
|
||||
| "embedHandler"
|
||||
>;
|
||||
|
||||
export type TEditorHookProps = TCoreHookProps &
|
||||
|
||||
@ -174,7 +174,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => {
|
||||
return (
|
||||
comment?.trim() === "" ||
|
||||
comment === "<p></p>" ||
|
||||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"])
|
||||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"])
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user