[WIKI-576] fix: trail node (#7527)

* fix : trail node

* remove flagged

* refactor : add disable flagging

* refactor:update disabled extension

* refactor: additional disabled

* refactor: update enum

* chore: add description key to page response type

* chore: update base page instance

---------

Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
Vipin Chaudhary 2025-08-04 16:12:46 +05:30 committed by GitHub
parent c3273b1a85
commit fa150c2b47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 70 additions and 19 deletions

View file

@ -0,0 +1,35 @@
// editor
import { TExtensions } from "@plane/editor";
export type TEditorFlaggingHookReturnType = {
document: {
disabled: TExtensions[];
flagged: TExtensions[];
};
liteText: {
disabled: TExtensions[];
flagged: TExtensions[];
};
richText: {
disabled: TExtensions[];
flagged: TExtensions[];
};
};
/**
* @description extensions disabled in various editors
*/
export const useEditorFlagging = (anchor: string): TEditorFlaggingHookReturnType => ({
document: {
disabled: [],
flagged: [],
},
liteText: {
disabled: [],
flagged: [],
},
richText: {
disabled: [],
flagged: [],
},
});

View file

@ -8,6 +8,7 @@ import { EditorMentionsRoot, IssueCommentToolbar } from "@/components/editor";
// helpers
import { getEditorFileHandlers } from "@/helpers/editor.helper";
import { isCommentEmpty } from "@/helpers/string.helper";
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
type LiteTextEditorWrapperProps = MakeOptional<
Omit<ILiteTextEditorProps, "fileHandler" | "mentionHandler">,
@ -31,9 +32,8 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
const {
anchor,
containerClassName,
disabledExtensions,
disabledExtensions: additionalDisabledExtensions = [],
editable,
flaggedExtensions,
isSubmitting = false,
showSubmitButton = true,
workspaceId,
@ -45,13 +45,14 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
// derived values
const isEmpty = isCommentEmpty(props.initialValue);
const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
const { liteText: liteTextEditorExtensions } = useEditorFlagging(anchor);
return (
<div className="border border-custom-border-200 rounded p-3 space-y-3">
<LiteTextEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
flaggedExtensions={flaggedExtensions ?? []}
disabledExtensions={[...liteTextEditorExtensions.disabled, ...additionalDisabledExtensions]}
flaggedExtensions={liteTextEditorExtensions.flagged}
editable={editable}
fileHandler={getEditorFileHandlers({
anchor,

View file

@ -1,5 +1,6 @@
import React, { forwardRef } from "react";
// plane imports
import { useEditorFlagging } from "ce/hooks/use-editor-flagging";
import { EditorRefApi, IRichTextEditorProps, RichTextEditorWithRef, TFileHandler } from "@plane/editor";
import { MakeOptional } from "@plane/types";
// components
@ -26,8 +27,17 @@ type RichTextEditorWrapperProps = MakeOptional<
);
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
const { anchor, containerClassName, editable, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props;
const {
anchor,
containerClassName,
editable,
workspaceId,
disabledExtensions: additionalDisabledExtensions = [],
...rest
} = props;
const { getMemberById } = useMember();
const { richText: richTextEditorExtensions } = useEditorFlagging(anchor);
return (
<RichTextEditorWithRef
mentionHandler={{
@ -37,14 +47,14 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
}),
}}
ref={ref}
disabledExtensions={disabledExtensions ?? []}
disabledExtensions={[...richTextEditorExtensions.disabled, ...additionalDisabledExtensions]}
editable={editable}
fileHandler={getEditorFileHandlers({
anchor,
uploadFile: editable ? props.uploadFile : async () => "",
workspaceId,
})}
flaggedExtensions={flaggedExtensions ?? []}
flaggedExtensions={richTextEditorExtensions.flagged}
{...rest}
containerClassName={containerClassName}
editorClassName="min-h-[100px] max-h-[200px] border-[0.5px] border-custom-border-300 rounded-md pl-3 py-2 overflow-hidden"

View file

@ -78,6 +78,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage {
id: string | undefined;
name: string | undefined;
logo_props: TLogoProps | undefined;
description: object | undefined;
description_html: string | undefined;
color: string | undefined;
label_ids: string[] | undefined;
@ -113,6 +114,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage {
this.id = page?.id || undefined;
this.name = page?.name;
this.logo_props = page?.logo_props || undefined;
this.description = page?.description || undefined;
this.description_html = page?.description_html || undefined;
this.color = page?.color || undefined;
this.label_ids = page?.label_ids || undefined;
@ -136,6 +138,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage {
id: observable.ref,
name: observable.ref,
logo_props: observable.ref,
description: observable,
description_html: observable.ref,
color: observable.ref,
label_ids: observable,
@ -208,6 +211,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage {
return {
id: this.id,
name: this.name,
description: this.description,
description_html: this.description_html,
color: this.color,
label_ids: this.label_ids,

View file

@ -50,17 +50,16 @@ export const EditorContainer: FC<Props> = (props) => {
return;
}
// Get the last node in the document
const docSize = editor.state.doc.content.size;
const lastNodePos = editor.state.doc.resolve(Math.max(0, docSize - 2));
const lastNode = lastNodePos.node();
// Get the last child node in the document
const doc = editor.state.doc;
const lastNode = doc.lastChild;
// Check if its last node and add new node
if (lastNode) {
const isLastNodeEmptyParagraph =
lastNode.type.name === CORE_EXTENSIONS.PARAGRAPH && lastNode.content.size === 0;
// Only insert a new paragraph if the last node is not an empty paragraph and not a doc node
if (!isLastNodeEmptyParagraph && lastNode.type.name !== "doc") {
const isLastNodeParagraph = lastNode.type.name === CORE_EXTENSIONS.PARAGRAPH;
// Insert a new paragraph if the last node is not a paragraph and not a doc node
if (!isLastNodeParagraph && lastNode.type.name !== CORE_EXTENSIONS.DOCUMENT) {
// Only insert a new paragraph if the last node is not an empty paragraph and not a doc node
const endPosition = editor?.state.doc.content.size;
editor?.chain().insertContentAt(endPosition, { type: "paragraph" }).focus("end").run();
}

View file

@ -32,6 +32,7 @@ export const CommandMenuItem: React.FC<Props> = (props) => {
{item.icon}
</span>
<p className="flex-grow truncate">{item.title}</p>
{item.badge}
</button>
);
};

View file

@ -1,7 +1,6 @@
import type { Editor, Range } from "@tiptap/core";
import type { CSSProperties } from "react";
// types
import { TEditorCommands } from "@/types";
import type { TEditorCommands } from "@/types";
export type CommandProps = {
editor: Editor;
@ -19,4 +18,5 @@ export type ISlashCommandItem = {
icon: React.ReactNode;
iconContainerStyle?: CSSProperties;
command: ({ editor, range }: CommandProps) => void;
badge?: React.ReactNode;
};

View file

@ -2,12 +2,13 @@ import { TLogoProps } from "../common";
import { EPageAccess } from "../enums";
import { TPageExtended } from "./extended";
export type TPage = TPageExtended & {
export type TPage = {
access: EPageAccess | undefined;
archived_at: string | null | undefined;
color: string | undefined;
created_at: Date | undefined;
created_by: string | undefined;
description: object | undefined;
description_html: string | undefined;
id: string | undefined;
is_favorite: boolean;
@ -20,7 +21,7 @@ export type TPage = TPageExtended & {
updated_by: string | undefined;
workspace: string | undefined;
logo_props: TLogoProps | undefined;
};
} & TPageExtended;
// page filters
export type TPageNavigationTabs = "public" | "private" | "archived";