Skip to content

[WIKI-511] [WIKI-572] fix: extended page root and editor body#7661

Merged
sriramveeraghanta merged 10 commits intopreviewfrom
fix/refactor-pages
Sep 1, 2025
Merged

[WIKI-511] [WIKI-572] fix: extended page root and editor body#7661
sriramveeraghanta merged 10 commits intopreviewfrom
fix/refactor-pages

Conversation

@Palanikannan1437
Copy link
Member

@Palanikannan1437 Palanikannan1437 commented Aug 28, 2025

Description

Refactoring page root and editor body

Summary by CodeRabbit

  • New Features

    • Restore a previous page version from the versions view.
    • Automatic redirection to a safe destination when a page is deleted.
    • Navigation pane supports extensions and deep-linked contextual views.
  • Refactor

    • Unified project/store context across pages, editor, and versions for consistent behavior.
    • Editor wrappers now manage extended editor options internally for simpler integration.
  • Chores

    • Consolidated exports to simplify imports.
    • Added placeholders for editor side effects and page modals for future enhancements.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

Introduces storeType- and project-aware page/editor wiring, navigation-pane extension API and CE facades, extended-editor props and side-effect scaffolding, content-aware comment emptiness checks, version-restore service and redirection-on-deleted-pages, plus multiple type re-exports and wrapper prop tightening.

Changes

Cohort / File(s) Summary
Page detail routing and handlers
apps/web/app/(all)/.../[pageId]/page.tsx
Adds router usage, central storeType = EPageStoreType.PROJECT, redirection when a page is deleted, and passes storeType/projectId to PageRoot.
Page root & editor wiring
apps/web/core/components/pages/editor/page-root.tsx, .../editor/editor-body.tsx, .../editor/header/root.tsx
Threads storeType and projectId through PageRoot, PageEditorBody, header; introduces restoreVersion handler in TPageRootHandlers and renders PageModals; uses extension hooks and extendedEditorProps.
Page versions UI
apps/web/core/components/pages/version/*, apps/web/core/services/page/project-page-version.service.ts
Adds storeType prop to versions components and ProjectPageVersionService.restoreVersion(...) API call to restore a version.
Navigation pane extension system
apps/web/core/components/pages/navigation-pane/root.tsx, .../navigation-pane/types/*, .../navigation-pane/index.ts, apps/web/ce/types/pages/pane-extensions.ts
New generic extension types, extensions and storeType props on the pane, active-extension detection by trigger param, dynamic width and conditional rendering, and re-exports for types.
CE hooks and modals
apps/web/ce/hooks/pages/*, apps/web/ce/components/pages/modals/*
Adds use-pages-pane-extensions, use-extended-editor-extensions, aggregator index, and placeholder PageModals component with page+storeType.
Editor extended types & side-effects
packages/editor/src/ce/types/*, packages/editor/src/core/types/*, packages/editor/src/core/components/editors/document/collaborative-editor.tsx, packages/editor/src/ce/components/document-editor-side-effects.ts
Adds extended editor type surface, threads extendedEditorProps into collaborative editor, and introduces DocumentEditorSideEffects placeholder.
Editor wrappers — omit extendedEditorProps
apps/web/core/components/editor/*, apps/space/core/components/editor/*
Wrapper prop types now omit extendedEditorProps; wrappers internally pass extendedEditorProps={{}}. useEditorFlagging usage updated to object arg.
Flagging hook
apps/web/ce/hooks/use-editor-flagging.ts
useEditorFlagging now accepts { workspaceSlug, storeType? } (public type TEditorFlaggingHookProps added); return shape unchanged.
Types and utils
packages/types/src/**, packages/utils/src/string.ts, packages/types/src/page/core.ts, packages/types/src/issues/activity/issue_comment.ts
Adds JSONContent/Content types and re-exports, TPage.deleted_at added, TIssueComment.comment_json -> JSONContent, implements content-aware `isCommentEmpty(Content
Store change
apps/web/core/store/pages/base-page.ts
BasePage gains observable `deleted_at: Date
Misc exports / re-exports
packages/editor/src/core/types/index.ts, packages/editor/src/ce/types/index.ts, apps/web/core/components/pages/navigation-pane/index.ts, apps/web/ce/components/pages/modals/index.ts
Added/adjusted re-exports to expose new types and CE facades; minor export-order change.
Space helper cleanup
apps/space/helpers/string.helper.ts
Removes local isCommentEmpty helper; callers should use new @plane/utils implementation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Page as PageDetailsPage
  participant Root as PageRoot
  participant Versions as PageVersionsOverlay
  participant Service as ProjectPageVersionService
  participant API as REST API

  User->>Versions: Click "Restore version"
  Versions-->>Root: restoreVersion(pageId, versionId)
  Root->>Service: restoreVersion(workspaceSlug, projectId, pageId, versionId)
  Service->>API: POST /workspaces/{ws}/projects/{p}/pages/{pg}/versions/{v}/restore/
  API-->>Service: 200 OK
  Service-->>Root: Promise resolved
  Root-->>Versions: Notify / trigger refresh
Loading
sequenceDiagram
  autonumber
  actor User
  participant Pane as PageNavigationPaneRoot
  participant Hook as usePagesPaneExtensions
  participant Ext as ActiveExtension(component)

  User->>Pane: Open navigation pane
  Pane->>Hook: Derive isOpen, handlers, extensions
  Pane->>Pane: Find ActiveExtension by triggerParam
  alt Extension active
    Pane->>Ext: Render component { page, extensionData, storeType }
  else No extension
    Pane->>Pane: Render default tabs/panels
  end
Loading
sequenceDiagram
  autonumber
  participant Body as PageEditorBody
  participant Collab as CollaborativeDocumentEditor
  participant SideFx as DocumentEditorSideEffects
  participant Renderer as PageRenderer

  Body->>Collab: Render with extendedEditorProps
  Collab->>SideFx: Render(editor, id, extendedEditorProps)
  SideFx-->>Collab: (placeholder/no-op)
  Collab->>Renderer: Render document UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Possibly related PRs

Suggested labels

✍️editor

Suggested reviewers

  • aaryan610
  • VipinDevelops
  • prateekshourya29

Poem

A nib of code, a hop of delight,
I stitched new panes to glow just right.
Restored old pages—poof!—they rise,
With tiny hooks and clearer eyes.
— a rabbit, twitching nose, celebrating merged supplies 🐇


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f37b4fe and 84fddfb.

📒 Files selected for processing (1)
  • packages/types/src/editor/editor-content.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/types/src/editor/editor-content.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/refactor-pages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@makeplane
Copy link

makeplane bot commented Aug 28, 2025

Pull Request Linked with Plane Work Items

Comment Automatically Generated by Plane

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/core/components/pages/version/main-content.tsx (1)

45-47: Avoid SWR cache collisions: include pageId (and storeType) in the key.

Current key omits pageId and may return stale data when switching pages with the same versionId.

Apply:

-  } = useSWR(
-    pageId && activeVersion ? `PAGE_VERSION_${activeVersion}` : null,
-    pageId && activeVersion ? () => fetchVersionDetails(pageId, activeVersion) : null
-  );
+  } = useSWR(
+    pageId && activeVersion ? `PAGE_VERSION_${storeType}_${pageId}_${activeVersion}` : null,
+    pageId && activeVersion ? () => fetchVersionDetails(pageId, activeVersion) : null
+  );
🧹 Nitpick comments (17)
apps/web/ce/components/pages/modals/modals.tsx (1)

11-18: Avoid unused-props warnings in stub by destructuring to underscores

Since this stub returns null, props are unused. Destructure to underscore-prefixed names to satisfy common eslint configs.

-export const PageModals: React.FC<TPageModalsProps> = observer((props) => null);
+export const PageModals: React.FC<TPageModalsProps> = observer(
+  ({ page: _page, storeType: _storeType, editorRef: _editorRef }) => null
+);

The CE scaffold itself is fine to land as a no-op.

packages/editor/src/ce/types/editor-extended.ts (1)

1-9: Tighten placeholders and add intent comments for DX
Unknowns are OK as scaffolding, but consider stricter defaults to reduce accidental misuse and clarify intent.

-export type IEditorExtensionOptions = unknown;
+// CE can augment this via module augmentation. Default: no options.
+export type IEditorExtensionOptions = Record<string, never>;

-export type IEditorPropsExtended = unknown;
+// Extra props passed into the editor by CE. Default: none.
+export type IEditorPropsExtended = Record<string, never>;

-export type TExtendedCommandExtraProps = unknown;
+// Extra payload for CE commands. Default: none.
+export type TExtendedCommandExtraProps = never;

-export type TExtendedEditorRefApi = unknown;
+// Extra editor ref surface for CE. Default: empty object.
+export type TExtendedEditorRefApi = Record<string, never>;

If you prefer maximum flexibility, keep unknown but add comments documenting the augmentation pattern.

apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (3)

4-4: Type-only import to avoid pulling runtime values
EPageStoreType is used only in types here. Use a type-only import to keep the module tree lean.

-import { EPageStoreType } from "../store";
+import type { EPageStoreType } from "../store";

6-14: Make optional params truly optional and prefer ReadonlyMap
Aligns with optional usage and avoids accidental mutation of handler registries.

 export type TExtendedEditorExtensionsHookParams = {
   workspaceSlug: string;
   page: TPageInstance;
   storeType: EPageStoreType;
   fetchEntity: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
-  getRedirectionLink: (pageId?: string) => string;
-  extensionHandlers?: Map<string, unknown>;
+  getRedirectionLink?: (pageId?: string) => string;
+  extensionHandlers?: ReadonlyMap<string, unknown>;
   projectId?: string;
 };

18-18: Annotate return type and prefer undefined over null
Better fits optional props (extendedEditorProps?) and appeases lint rules for unused params.

-export const useExtendedEditorExtensions = (params: TExtendedEditorExtensionsHookParams) => null;
+export const useExtendedEditorExtensions = (_params: TExtendedEditorExtensionsHookParams): TExtendedEditorExtensionsConfig | undefined => undefined;

If any consumer currently checks for null, confirm and adjust accordingly.

apps/web/core/components/pages/navigation-pane/index.ts (1)

5-5: Replace with a type-only export in apps/web/core/components/pages/navigation-pane/index.ts line 5
Since ./types only exports types, change

-export * from "./types";
+export type * from "./types";

TS 5.8.3 supports this syntax and it will be erased at compile time.

packages/editor/src/ce/types/index.ts (1)

2-2: Use type-only exports and imports for CE types

-export * from "./editor-extended";
+export type * from "./editor-extended";

Convert all consumer imports of @plane/editor to type-only form (e.g. import type { EditorRefApi } from "@plane/editor";) to avoid pulling in runtime code.

packages/editor/src/core/types/index.ts (1)

13-13: Prefer type-only re-export for types barrel.

If "@/plane-editor/types" contains only types, use a type-only re-export to avoid pulling any runtime values.

-export * from "@/plane-editor/types";
+export type * from "@/plane-editor/types";
apps/web/core/components/pages/version/editor.tsx (1)

12-14: storeType is required but unused—make it optional or wire it through.

Avoid forcing callers to pass an unused prop; either plumb it to the editor where needed or make it optional for now.

 export type TVersionEditorProps = {
   activeVersion: string | null;
   versionDetails: TPageVersion | undefined;
-  storeType: EPageStoreType;
+  storeType?: EPageStoreType;
 };

Also applies to: 18-19

apps/web/ce/hooks/use-editor-flagging.ts (1)

3-3: Unused parameters—prefix with underscore to satisfy linters.

storeType (and workspaceSlug) aren’t used. Prefix to signal intentional non-use.

-export const useEditorFlagging = (
-  workspaceSlug: string,
-  storeType?: EPageStoreType
-): TEditorFlaggingHookReturnType => ({
+export const useEditorFlagging = (
+  _workspaceSlug: string,
+  _storeType?: EPageStoreType
+): TEditorFlaggingHookReturnType => ({

Also applies to: 23-26

packages/editor/src/core/types/editor.ts (1)

9-9: Prefer importing from the CE types index to avoid deep paths.

Reduces churn if files move.

-import type { IEditorPropsExtended, TExtendedEditorCommands } from "@/plane-editor/types/editor-extended";
+import type { IEditorPropsExtended, TExtendedEditorCommands } from "@/plane-editor/types";
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (2)

14-19: Unused hook params (likely to trip linting).

params is declared but never used. Either prefix with _ or destructure only what you need.

-export const usePagesPaneExtensions = (params: TPageExtensionHookParams) => {
+export const usePagesPaneExtensions = (_params: TPageExtensionHookParams) => {

33-39: Optional: clear version param when opening the pane.

If a version is selected, opening the outline should likely drop PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM to avoid conflicting UI state.

   const handleOpenNavigationPane = useCallback(() => {
-    const updatedRoute = updateQueryParams({
-      paramsToAdd: { [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM]: "outline" },
-    });
+    const updatedRoute = updateQueryParams({
+      paramsToAdd: { [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM]: "outline" },
+      // paramsToRemove: [PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM], // uncomment if imported
+    });
     router.push(updatedRoute);
   }, [router, updateQueryParams]);
apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx (2)

150-155: Use replace to avoid back-navigating into a deleted page.

router.replace prevents the history stack from taking users back to a dead route.

-  useEffect(() => {
-    if (page?.deleted_at && page?.id) {
-      router.push(pageRootHandlers.getRedirectionLink());
-    }
-  }, [page?.deleted_at, page?.id, router, pageRootHandlers]);
+  useEffect(() => {
+    if (page?.deleted_at && page?.id) {
+      router.replace(pageRootHandlers.getRedirectionLink());
+    }
+  }, [page?.deleted_at, page?.id, router, pageRootHandlers]);

75-95: Handlers look good; minor nit: avoid early returns that silently no-op.

For fetchAllVersions/fetchVersionDetails, consider throwing or returning a typed undefined guard result with logging when required params are missing. Silent returns make failures harder to trace.

Would you like me to wire a minimal toast/logger for these early returns?

apps/web/core/components/pages/navigation-pane/types/extensions.ts (1)

5-21: Type surface looks solid.

Interfaces are minimal and align with the pane root’s usage. Consider documenting that width is pixels.

apps/web/core/components/pages/editor/page-root.tsx (1)

118-124: Close-pane cleans both tab and version params — good.

Keeps URL state tidy. Consider also clearing any extension-specific paneTab (handled implicitly).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0e6fbae and b729d64.

📒 Files selected for processing (25)
  • apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx (7 hunks)
  • apps/web/ce/components/pages/modals/index.ts (1 hunks)
  • apps/web/ce/components/pages/modals/modals.tsx (1 hunks)
  • apps/web/ce/hooks/pages/index.ts (1 hunks)
  • apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1 hunks)
  • apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1 hunks)
  • apps/web/ce/hooks/use-editor-flagging.ts (2 hunks)
  • apps/web/ce/types/pages/pane-extensions.ts (1 hunks)
  • apps/web/core/components/pages/editor/editor-body.tsx (7 hunks)
  • apps/web/core/components/pages/editor/header/root.tsx (1 hunks)
  • apps/web/core/components/pages/editor/page-root.tsx (5 hunks)
  • apps/web/core/components/pages/navigation-pane/index.ts (1 hunks)
  • apps/web/core/components/pages/navigation-pane/root.tsx (5 hunks)
  • apps/web/core/components/pages/navigation-pane/types/extensions.ts (1 hunks)
  • apps/web/core/components/pages/navigation-pane/types/index.ts (1 hunks)
  • apps/web/core/components/pages/version/editor.tsx (1 hunks)
  • apps/web/core/components/pages/version/main-content.tsx (3 hunks)
  • apps/web/core/components/pages/version/root.tsx (3 hunks)
  • apps/web/core/services/page/project-page-version.service.ts (1 hunks)
  • apps/web/core/store/pages/base-page.ts (4 hunks)
  • packages/editor/src/ce/types/editor-extended.ts (1 hunks)
  • packages/editor/src/ce/types/index.ts (1 hunks)
  • packages/editor/src/core/types/editor.ts (3 hunks)
  • packages/editor/src/core/types/index.ts (1 hunks)
  • packages/types/src/page/core.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-14T13:16:23.323Z
Learnt from: vamsikrishnamathala
PR: makeplane/plane#7061
File: web/core/components/workspace-notifications/root.tsx:18-18
Timestamp: 2025-05-14T13:16:23.323Z
Learning: In the Plane project codebase, the path alias `@/plane-web` resolves to the `ce` directory, making imports like `@/plane-web/hooks/use-notification-preview` correctly resolve to files in `web/ce/hooks/`.

Applied to files:

  • apps/web/core/components/pages/version/root.tsx
🧬 Code graph analysis (8)
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (6)
apps/web/core/store/pages/base-page.ts (1)
  • TPageInstance (69-72)
packages/editor/src/core/types/editor.ts (1)
  • EditorRefApi (95-133)
apps/web/core/hooks/use-app-router.tsx (1)
  • useAppRouter (4-4)
apps/web/core/components/pages/navigation-pane/index.ts (2)
  • PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM (9-9)
  • PAGE_NAVIGATION_PANE_TAB_KEYS (12-12)
apps/web/ce/types/pages/pane-extensions.ts (1)
  • INavigationPaneExtension (7-15)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (1)
  • INavigationPaneExtension (15-21)
apps/web/core/components/pages/version/editor.tsx (1)
packages/types/src/page/core.ts (1)
  • TPageVersion (50-64)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (2)
apps/web/core/store/pages/base-page.ts (1)
  • TPageInstance (69-72)
apps/web/ce/types/pages/pane-extensions.ts (1)
  • INavigationPaneExtension (7-15)
packages/editor/src/core/types/editor.ts (1)
packages/editor/src/ce/types/editor-extended.ts (2)
  • TExtendedEditorCommands (5-5)
  • IEditorPropsExtended (3-3)
apps/web/ce/types/pages/pane-extensions.ts (1)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (1)
  • INavigationPaneExtension (15-21)
apps/web/core/components/pages/navigation-pane/root.tsx (2)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (1)
  • INavigationPaneExtension (15-21)
apps/web/core/components/pages/navigation-pane/index.ts (2)
  • PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM (10-10)
  • PAGE_NAVIGATION_PANE_WIDTH (7-7)
apps/web/core/components/pages/editor/editor-body.tsx (2)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (23-39)
apps/web/core/components/pages/editor/header/root.tsx (1)
  • PageEditorHeaderRoot (17-71)
apps/web/core/components/pages/editor/page-root.tsx (2)
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1)
  • usePagesPaneExtensions (19-53)
apps/web/core/components/pages/navigation-pane/root.tsx (1)
  • PageNavigationPaneRoot (39-117)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (13)
packages/types/src/page/core.ts (1)

24-24: Align deleted_at with API and ensure correct handling

  • In packages/types/src/page/core.ts (line 24), change
    deleted_at: Date | undefined;
    to
    deleted_at: string | null | undefined;

  • Verify in apps/web/core/store/pages/base-page.ts (line 96) and in BasePage.asJSON that deleted_at is treated as a string (and/or converted from string) to avoid leaking Date objects.

apps/web/ce/components/pages/modals/index.ts (1)

2-2: Barrel exports are safe: no name collisions
Both modules export distinct symbols (TMovePageModalProps, MovePageModal vs TPageModalsProps, PageModals).

apps/web/ce/hooks/pages/index.ts (1)

1-2: Barrel index looks good.

Single entry-point for CE pages hooks improves DX and keeps imports tidy.

apps/web/core/components/pages/version/main-content.tsx (1)

9-11: Propagating storeType into VersionEditor looks correct.

Props surface and usage are consistent.

Also applies to: 22-22, 26-35, 121-121

apps/web/core/components/pages/navigation-pane/types/index.ts (1)

1-6: Type re-exports are clean and scoped.

Good centralization of extension types.

packages/editor/src/core/types/editor.ts (1)

163-164: Extended editor props wiring looks good.

Optional prop maintains backward compatibility.

apps/web/core/components/pages/navigation-pane/root.tsx (1)

34-37: Extension plumbing and dynamic width look good.

Defaulting extensions to [] avoids null checks; passing storeType to the extension component aligns with the store-aware design.

Please confirm that INavigationPaneExtensionComponent’s props include storeType: EPageStoreType so this call site is type-safe. You can verify by opening apps/web/core/components/pages/navigation-pane/types/extensions.ts and checking the component props.

Also applies to: 40-41, 105-114

apps/web/core/components/pages/editor/editor-body.tsx (4)

109-110: Flagging now respects storeType.

Passing storeType into useEditorFlagging matches the new store-aware editor stack.


218-219: Header now needs projectId — OK.

Prop is correctly threaded; no further action.


256-257: Extended editor props wired.

extendedEditorProps forwarded to the collab editor — LGTM.


47-50: New handler shape acknowledged.

Adding getRedirectionLink to TEditorBodyHandlers is fine; confirm all providers pass it (PageRoot does).

If there are other PageEditorBody call sites, run:

apps/web/core/components/pages/editor/page-root.tsx (2)

149-156: Prop threading is correct and stable.

isNavigationPaneOpen, storeType, projectId, and extendedEditorProps are correctly passed to children.


158-170: Modal wiring looks sane.

PageModals receives page, storeType, and the current editorRef. No issues spotted.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

53-66: Bug: unsafe dependency embedHandler.issue in useMemo.

Accessing embedHandler.issue will throw when embedHandler is undefined. Use optional chaining.

-  }, [externalExtensions, embedHandler.issue]);
+  }, [externalExtensions, embedHandler?.issue]);
🧹 Nitpick comments (2)
packages/editor/src/ce/components/editor-side-effects.ts (1)

1-3: Add React return type import for stricter typing.

Prepares for future hook usage and makes the component signature explicit.

 import { type Editor } from "@tiptap/core";
 import type { IEditorPropsExtended } from "@/types";
+import type { ReactElement } from "react";
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

103-119: Mount EditorSideEffects only when needed.

Avoid mounting a no-op component on every render if no extended behavior is provided.

-    <>
-      <EditorSideEffects editor={editor} id={id} extendedEditorProps={extendedEditorProps} />
+    <>
+      {extendedEditorProps && (
+        <EditorSideEffects editor={editor} id={id} extendedEditorProps={extendedEditorProps} />
+      )}
       <PageRenderer
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b729d64 and 268f987.

📒 Files selected for processing (2)
  • packages/editor/src/ce/components/editor-side-effects.ts (1 hunks)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (2)

16-16: Path alias for @/plane-editor is correctly configured
@/plane-editor/components/editor-side-effects resolves to packages/editor/src/ce/components/editor-side-effects.ts, so the import will work as expected.


32-32: extendedEditorProps is already included on ICollaborativeDocumentEditorProps
The extendedEditorProps field is declared on IEditorProps (packages/editor/src/core/types/editor.ts, line 163) and the Omit in ICollaborativeDocumentEditorProps only removes initialValue, onEnterKeyPress, and value, so extendedEditorProps remains part of the props interface. TS will not error here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/types/src/editor/editor-content.ts (1)

5-16: Tighten typing: prefer unknown over any for attrs and index signatures.

Reduces unsoundness without adding dependencies.

 export type JSONContent = {
   type?: string;
-  attrs?: Record<string, any>;
+  attrs?: Record<string, unknown>;
   content?: JSONContent[];
   marks?: {
     type: string;
-    attrs?: Record<string, any>;
-    [key: string]: any;
+    attrs?: Record<string, unknown>;
+    [key: string]: unknown;
   }[];
   text?: string;
-  [key: string]: any;
+  [key: string]: unknown;
 };
packages/types/src/index.ts (1)

31-31: Type-only re-export to avoid accidental value re-exports.

Harmless now (types only), but safer with TS emit/isolatedModules.

-export * from "./editor";
+export type * from "./editor";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 268f987 and 9ae11f7.

📒 Files selected for processing (7)
  • apps/space/core/components/editor/lite-text-editor.tsx (1 hunks)
  • apps/space/helpers/string.helper.ts (0 hunks)
  • packages/types/src/editor/editor-content.ts (1 hunks)
  • packages/types/src/editor/index.ts (1 hunks)
  • packages/types/src/index.ts (1 hunks)
  • packages/types/src/issues/activity/issue_comment.ts (2 hunks)
  • packages/utils/src/string.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • apps/space/helpers/string.helper.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/space/core/components/editor/lite-text-editor.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
packages/types/src/issues/activity/issue_comment.ts (1)
packages/types/src/editor/editor-content.ts (1)
  • JSONContent (5-16)
packages/utils/src/string.ts (2)
packages/types/src/editor/editor-content.ts (2)
  • JSONContent (5-16)
  • Content (20-20)
apps/space/helpers/string.helper.ts (1)
  • isEmptyHtmlString (53-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/types/src/editor/index.ts (1)

1-1: LGTM — focused type-only surface.

packages/utils/src/string.ts (1)

170-193: Align JSON and HTML emptiness semantics: in isJSONContentEmpty, include hardBreak in the empty-case check and exclude embed-component from the “empty” list so embed-only nodes are treated as non-empty. Verify that JSONContent actually uses embed-component nodes and that they should indeed count as content.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/core/components/pages/editor/page-root.tsx (1)

118-123: Close action should also clear custom extension query param.

Removing only the built-in params leaves paneTab behind, keeping extension state sticky.

Apply this diff:

-const updatedRoute = updateQueryParams({
-  paramsToRemove: [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM, PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM],
-});
+const updatedRoute = updateQueryParams({
+  paramsToRemove: [PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM, PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM, "paneTab"],
+});
♻️ Duplicate comments (1)
apps/web/core/components/pages/editor/page-root.tsx (1)

87-93: Pane open-state still ignores custom extensions.

isNavigationPaneOpen from usePagesPaneExtensions doesn’t account for extension triggerParams; extensions render off-canvas. Fix in the hook by OR-ing with “active extension exists”.

Run:

#!/bin/bash
sed -n '1,200p' apps/web/ce/hooks/pages/use-pages-pane-extensions.ts
rg -nP 'isNavigationPaneOpen' apps/web/ce/hooks/pages/use-pages-pane-extensions.ts -C3
rg -nP 'triggerParam|navigationPaneExtensions' apps/web/ce/hooks/pages/use-pages-pane-extensions.ts -C3
🧹 Nitpick comments (3)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (2)

6-14: Unify naming: use “EditorProps” across hook/types (and file).

For consistency with the exported hook, prefer TExtendedEditorPropsParams and TExtendedEditorProps. Consider renaming the file to use-extended-editor-props.ts.

Apply this diff:

-export type TExtendedEditorExtensionsHookParams = {
+export type TExtendedEditorPropsParams = {
   workspaceSlug: string;
   page: TPageInstance;
   storeType: EPageStoreType;
   fetchEntity: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
   getRedirectionLink: (pageId?: string) => string;
   extensionHandlers?: Map<string, unknown>;
   projectId?: string;
 };
 
-export type TExtendedEditorExtensionsConfig = IEditorPropsExtended;
+export type TExtendedEditorProps = IEditorPropsExtended;

And update usage:

-export const useExtendedEditorProps = (params: TExtendedEditorExtensionsHookParams): TExtendedEditorExtensionsConfig => ({} as unknown as TExtendedEditorExtensionsConfig);
+export const useExtendedEditorProps = (_params: TExtendedEditorPropsParams): TExtendedEditorProps =>
+  ({} as unknown as TExtendedEditorProps);

Also applies to: 16-16


12-12: Tighten handler typing.

Replace Map<string, unknown> with a concrete handler type (e.g., Map<string, EditorExtensionHandler> or Record<string, EditorExtensionHandler>) to retain type safety across the extension surface.

apps/web/core/components/pages/editor/page-root.tsx (1)

169-170: Guard possibly-null editorRef when passing to PageModals.

Avoid passing null if the prop isn’t nullable.

Apply this diff:

-<PageModals page={page} storeType={storeType} editorRef={editorRef.current} />
+<PageModals page={page} storeType={storeType} editorRef={editorRef.current ?? undefined} />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9ae11f7 and 24fb0d9.

📒 Files selected for processing (2)
  • apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1 hunks)
  • apps/web/core/components/pages/editor/page-root.tsx (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (2)
apps/web/core/store/pages/base-page.ts (1)
  • TPageInstance (69-72)
packages/editor/src/ce/types/editor-extended.ts (1)
  • IEditorPropsExtended (3-3)
apps/web/core/components/pages/editor/page-root.tsx (4)
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1)
  • usePagesPaneExtensions (19-53)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1)
  • useExtendedEditorProps (18-18)
apps/web/core/components/pages/navigation-pane/root.tsx (1)
  • PageNavigationPaneRoot (39-117)
apps/web/ce/components/pages/modals/modals.tsx (1)
  • PageModals (17-17)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/web/core/components/pages/editor/page-root.tsx (2)

42-45: Propagating storeType/projectId across the editor stack looks good.

Wiring through PageVersionsOverlay, PageEditorBody, PageNavigationPaneRoot, and PageModals is consistent.

Also applies to: 49-49, 134-135, 152-153, 159-159


99-101: No changes needed—handlers are declared via TEditorBodyHandlers
TPageRootHandlers is defined as & TEditorBodyHandlers, and TEditorBodyHandlers declares both fetchEntity and getRedirectionLink.

@Palanikannan1437 Palanikannan1437 changed the title [WIKI-511] fix: better refactoring of page root and editor body [WIKI-511] fix: extended page root and editor body Aug 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

65-65: Bug: unsafe dependency access in useMemo (possible runtime crash).

Dependency array references embedHandler.issue without optional chaining, but embedHandler can be undefined. This will throw at render time.

-  }, [externalExtensions, embedHandler.issue]);
+  }, [externalExtensions, embedHandler?.issue]);
+  // Alternatively, depend on the exact value used:
+  // }, [externalExtensions, embedHandler?.issue?.widgetCallback]);
apps/web/core/components/editor/document/editor.tsx (1)

84-87: Bug: spread on possibly undefined embedHandler throws at runtime.

...embedHandler will crash if embedHandler is undefined.

Fix via defaulting in destructure (preferred):

-    embedHandler,
+    embedHandler = {},

or locally:

-      embedHandler={{
-        issue: issueEmbedProps,
-        ...embedHandler,
-      }}
+      embedHandler={{ issue: issueEmbedProps, ...(embedHandler ?? {}) }}
♻️ Duplicate comments (3)
packages/editor/src/core/types/editor.ts (1)

9-9: CE placeholder fix is correctly consumed here.

Importing IEditorPropsExtended and TExtendedEditorCommands from the plane-editor entry looks good; with CE exporting TExtendedEditorCommands = never, this no longer widens TEditorCommands with an empty string.

apps/web/core/components/pages/editor/page-root.tsx (2)

54-55: Fix ref type to include null (strict TS).

-const editorRef = useRef<EditorRefApi>(null);
+const editorRef = useRef<EditorRefApi | null>(null);

87-93: Pane won’t open for custom extensions (hook returns empty extensions and ignores paneTab).

usePagesPaneExtensions currently returns navigationPaneExtensions = [] and sets isNavigationPaneOpen only for built-in tabs. When ?paneTab=<extension> is present, the aside stays off-canvas. Update the hook to populate extensions and treat an active extension as “open.”

Suggested change (in apps/web/ce/hooks/pages/use-pages-pane-extensions.ts):

-  const navigationPaneExtensions: INavigationPaneExtension[] = [];
-
-  return {
-    editorExtensionHandlers,
-    navigationPaneExtensions,
-    handleOpenNavigationPane,
-    isNavigationPaneOpen,
-  };
+  // TODO: load registered extensions instead of empty array
+  const navigationPaneExtensions: INavigationPaneExtension[] = getRegisteredNavigationPaneExtensions?.() ?? [];
+  const paneTabValue = searchParams.get("paneTab");
+  const hasActiveExtension = !!navigationPaneExtensions.find((e) => e.triggerParam === paneTabValue);
+
+  return {
+    editorExtensionHandlers,
+    navigationPaneExtensions,
+    handleOpenNavigationPane,
+    isNavigationPaneOpen: isNavigationPaneOpen || hasActiveExtension,
+  };

Verification: navigate to ?paneTab=<your-extension-trigger> and ensure the aside animates in.

🧹 Nitpick comments (11)
apps/web/ce/types/pages/pane-extensions.ts (1)

6-7: Make the data map augmentable via declaration merging (future-proof CE/EE).

Switching from Record to an interface enables external augmentation without touching this file.

Apply:

-// EE Union/map of extension data types (keyed by extension id)
-export type TNavigationPaneExtensionData = Record<string, unknown>;
+// EE Union/map of extension data types (keyed by extension id)
+// Interface form allows module augmentation by EE/plugins.
+export interface CEPaneExtensionDataMap {
+  [key: string]: unknown;
+}
+export type TNavigationPaneExtensionData = CEPaneExtensionDataMap;
packages/editor/src/core/types/editor.ts (1)

163-164: Mandatory extendedEditorProps is a breaking API — verify all call sites are updated.

IEditorProps now requires extendedEditorProps. Internal wrappers pass {} which is fine for CE’s unknown type. Please confirm no external consumers (outside this repo) rely on the old optional surface.

apps/space/core/components/editor/rich-text-editor.tsx (1)

59-59: Avoid new-object prop churn for extendedEditorProps.

Passing {} creates a new reference each render and can cause unnecessary re-renders downstream. Memoize a stable empty object.

 export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
   const {
@@
   const { richText: richTextEditorExtensions } = useEditorFlagging(anchor);
 
+  const emptyExtendedEditorProps = React.useMemo(() => ({} as const), []);
+
   return (
     <RichTextEditorWithRef
@@
-      extendedEditorProps={{}}
+      extendedEditorProps={emptyExtendedEditorProps}
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

16-16: Minor: incorrect comment section.

The "// constants" label doesn’t match the import (component). Consider correcting for readability.

-// constants
+// ce side-effects
 import { DocumentEditorSideEffects } from "@/plane-editor/components/editor-side-effects";
apps/space/core/components/editor/lite-text-editor.tsx (1)

65-65: Memoize empty extendedEditorProps to reduce re-renders.

 export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapperProps>((props, ref) => {
@@
   const { liteText: liteTextEditorExtensions } = useEditorFlagging(anchor);
+  const emptyExtendedEditorProps = React.useMemo(() => ({} as const), []);
@@
-        extendedEditorProps={{}}
+        extendedEditorProps={emptyExtendedEditorProps}
apps/web/core/components/editor/lite-text/editor.tsx (1)

131-131: Memoize empty extendedEditorProps to avoid prop identity churn.

 export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapperProps>((props, ref) => {
@@
   const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
+  const emptyExtendedEditorProps = React.useMemo(() => ({} as const), []);
@@
-        extendedEditorProps={{}}
+        extendedEditorProps={emptyExtendedEditorProps}
packages/editor/src/ce/components/editor-side-effects.ts (1)

5-10: Narrow the callback type; export it for reuse across CE/EE.

Avoid unknown for updatePageProperties; define a specific callback type and use it.

Apply:

 export type DocumentEditorSideEffectsProps = {
   editor: Editor;
   id: string;
-  updatePageProperties?: unknown;
+  /**
+   * Callback to update page metadata/properties.
+   * Keep broad but non-any to enable cross-package reuse.
+   */
+  updatePageProperties?: UpdatePageProperties;
   extendedEditorProps?: IEditorPropsExtended;
 };
 
+export type UpdatePageProperties = (changes: Record<string, unknown>) => void;
apps/web/core/components/editor/document/editor.tsx (1)

48-50: Nit: unnecessary toString/empty fallback.

workspaceSlug is already a string in props; pass it directly.

-  const { document: documentEditorExtensions } = useEditorFlagging({
-    workspaceSlug: workspaceSlug?.toString() ?? "",
-  });
+  const { document: documentEditorExtensions } = useEditorFlagging({ workspaceSlug });
apps/web/core/components/editor/rich-text/editor.tsx (1)

45-47: Nit: unnecessary toString/empty fallback.

-  const { richText: richTextEditorExtensions } = useEditorFlagging({
-    workspaceSlug: workspaceSlug?.toString() ?? "",
-  });
+  const { richText: richTextEditorExtensions } = useEditorFlagging({ workspaceSlug });
apps/web/core/components/editor/sticky-editor/editor.tsx (1)

54-56: Nit: unnecessary toString/empty fallback.

-  const { liteText: liteTextEditorExtensions } = useEditorFlagging({
-    workspaceSlug: workspaceSlug?.toString() ?? "",
-  });
+  const { liteText: liteTextEditorExtensions } = useEditorFlagging({ workspaceSlug });
apps/web/core/components/pages/editor/editor-body.tsx (1)

109-112: Nit: avoid defaulting storeType to an empty string.

storeType is typed; passing "" weakens type guarantees.

-  const { document: documentEditorExtensions } = useEditorFlagging({
-    workspaceSlug: workspaceSlug?.toString() ?? "",
-    storeType: storeType ?? "",
-  });
+  const { document: documentEditorExtensions } = useEditorFlagging({
+    workspaceSlug,
+    storeType,
+  });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 24fb0d9 and 920c6ce.

📒 Files selected for processing (17)
  • apps/space/core/components/editor/lite-text-editor.tsx (2 hunks)
  • apps/space/core/components/editor/rich-text-editor.tsx (2 hunks)
  • apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx (8 hunks)
  • apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1 hunks)
  • apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1 hunks)
  • apps/web/ce/hooks/use-editor-flagging.ts (2 hunks)
  • apps/web/ce/types/pages/pane-extensions.ts (1 hunks)
  • apps/web/core/components/editor/document/editor.tsx (3 hunks)
  • apps/web/core/components/editor/lite-text/editor.tsx (3 hunks)
  • apps/web/core/components/editor/rich-text/editor.tsx (3 hunks)
  • apps/web/core/components/editor/sticky-editor/editor.tsx (3 hunks)
  • apps/web/core/components/pages/editor/editor-body.tsx (7 hunks)
  • apps/web/core/components/pages/editor/page-root.tsx (5 hunks)
  • packages/editor/src/ce/components/editor-side-effects.ts (1 hunks)
  • packages/editor/src/ce/types/editor-extended.ts (1 hunks)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx (3 hunks)
  • packages/editor/src/core/types/editor.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/editor/src/ce/types/editor-extended.ts
  • apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx
  • apps/web/ce/hooks/pages/use-extended-editor-extensions.ts
  • apps/web/ce/hooks/pages/use-pages-pane-extensions.ts
  • apps/web/ce/hooks/use-editor-flagging.ts
🧰 Additional context used
🧬 Code graph analysis (12)
apps/web/ce/types/pages/pane-extensions.ts (1)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (2)
  • INavigationPaneExtension (15-21)
  • INavigationPaneExtensionComponent (11-13)
packages/editor/src/core/components/editors/document/collaborative-editor.tsx (2)
packages/editor/src/ce/components/editor-side-effects.ts (1)
  • DocumentEditorSideEffects (12-12)
packages/editor/src/core/components/editors/document/page-renderer.tsx (1)
  • PageRenderer (25-73)
apps/space/core/components/editor/rich-text-editor.tsx (1)
packages/editor/src/core/types/editor.ts (1)
  • IRichTextEditorProps (168-170)
apps/web/core/components/editor/rich-text/editor.tsx (3)
packages/editor/src/core/types/editor.ts (1)
  • IRichTextEditorProps (168-170)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (28-41)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/editor/document/editor.tsx (3)
packages/editor/src/core/types/editor.ts (1)
  • IDocumentEditorProps (183-188)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (28-41)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
packages/editor/src/ce/components/editor-side-effects.ts (1)
packages/editor/src/ce/types/editor-extended.ts (1)
  • IEditorPropsExtended (3-3)
packages/editor/src/core/types/editor.ts (1)
packages/editor/src/ce/types/editor-extended.ts (2)
  • TExtendedEditorCommands (5-5)
  • IEditorPropsExtended (3-3)
apps/space/core/components/editor/lite-text-editor.tsx (1)
packages/editor/src/core/types/editor.ts (1)
  • ILiteTextEditorProps (166-166)
apps/web/core/components/editor/lite-text/editor.tsx (3)
packages/editor/src/core/types/editor.ts (1)
  • ILiteTextEditorProps (166-166)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (28-41)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/editor/sticky-editor/editor.tsx (2)
packages/editor/src/core/types/editor.ts (1)
  • ILiteTextEditorProps (166-166)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (28-41)
apps/web/core/components/pages/editor/editor-body.tsx (3)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1)
  • TExtendedEditorExtensionsConfig (16-16)
apps/web/ce/hooks/use-editor-flagging.ts (1)
  • useEditorFlagging (28-41)
apps/web/core/components/pages/editor/header/root.tsx (1)
  • PageEditorHeaderRoot (17-71)
apps/web/core/components/pages/editor/page-root.tsx (4)
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1)
  • usePagesPaneExtensions (19-52)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1)
  • useExtendedEditorProps (18-18)
apps/web/core/components/pages/navigation-pane/root.tsx (1)
  • PageNavigationPaneRoot (39-117)
apps/web/ce/components/pages/modals/modals.tsx (1)
  • PageModals (17-17)
🔇 Additional comments (20)
apps/web/ce/types/pages/pane-extensions.ts (1)

1-4: Type-only imports via the barrel look good.

Using type-only imports keeps runtime clean and avoids circular deps at emit time. LGTM.

packages/editor/src/core/types/editor.ts (1)

55-56: Add extra-props mapping if external-embed requires parameters.

You’ve added "external-embed" to TEditorCommands. If this command needs runtime params (e.g., url, provider), add a corresponding entry to TCommandExtraProps to preserve type-safety for executeMenuItemCommand and isMenuItemActive.

apps/space/core/components/editor/rich-text-editor.tsx (1)

15-16: Good: tightened public API by omitting extendedEditorProps.

This aligns the wrapper with the new required prop on the inner editor while keeping the wrapper surface stable.

packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

103-119: Side-effects mount looks correct.

Rendering DocumentEditorSideEffects alongside PageRenderer cleanly injects lifecycle hooks without coupling. No functional issues spotted.

apps/space/core/components/editor/lite-text-editor.tsx (2)

5-5: Good: isCommentEmpty import relocation.

Switching to @plane/utils keeps helpers centralized.


14-15: Good: wrapper omits extendedEditorProps.

Keeps external API lean while satisfying inner editor’s required prop.

apps/web/core/components/editor/lite-text/editor.tsx (2)

21-23: Good: wrapper omits extendedEditorProps.

Matches the new core types and internalizes the concern.


71-73: Good: useEditorFlagging now takes a config object.

Passing workspaceSlug via an object aligns with the updated hook signature.

packages/editor/src/ce/components/editor-side-effects.ts (2)

1-3: Good: typed component and public props export.

Imports and explicit ReactElement | null return are correct. Props type is exported for reuse.


12-12: All DocumentEditorSideEffects calls use JSX with object props
Search across the codebase did not find any non-JSX invocations; no further changes required.

apps/web/core/components/editor/rich-text/editor.tsx (1)

14-16: LGTM: internalizing extendedEditorProps in the wrapper.

Public API tightened; defaulted internally to {}. Matches the document editor pattern.

Also applies to: 78-79

apps/web/core/components/editor/sticky-editor/editor.tsx (1)

18-20: LGTM: removed extendedEditorProps from public props.

Keeps the wrapper lean; forwards a stable default internally.

apps/web/core/components/pages/editor/editor-body.tsx (4)

28-31: LGTM: typed extension config and store type imports.

These align the editor with the extended-editor and store-type plumbing.


259-260: LGTM: forwarding extendedEditorProps to the collaborative editor.

Keeps extended-editor wiring consistent end-to-end.


49-50: Ensure implementers supply getRedirectionLink
No occurrences of <PageEditorBody handlers={…}> were found—manually review all consumers of TEditorBodyHandlers to implement the new getRedirectionLink handler.


221-221: Props include projectId in PageEditorHeaderRoot
The Props type in apps/web/core/components/pages/editor/header/root.tsx already declares projectId: string, so no changes are needed.

apps/web/core/components/pages/editor/page-root.tsx (4)

11-14: LGTM: CE integration wiring looks correct.

Imports for PageModals, pane/extended-editor hooks, and EPageStoreType are appropriate for the new architecture.


42-45: LGTM: storeType/projectId propagation is consistent.

Passing storeType and projectId through PageVersionsOverlay, PageEditorBody, and PageNavigationPaneRoot aligns with the new extensibility model.

Also applies to: 137-138, 154-156, 162-165, 170-170


172-172: Confirm PageModals editorRef prop type.

You pass editorRef={editorRef.current} (instance). If PageModals expects a ref object, pass editorRef={editorRef} instead. Verify the prop type and adjust accordingly.


121-127: Ignore redundant paneTab removal The PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM constant is defined as "paneTab", so the existing paramsToRemove already clears the extension pane tab. No change needed.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (5)
apps/web/core/components/pages/navigation-pane/root.tsx (1)

56-57: Good: using query-param constants instead of string literals.

Prevents drift and keeps routing consistent across components.

Also applies to: 76-78

apps/web/core/components/pages/editor/page-root.tsx (4)

105-111: Restore action updates UI only; persist to server and accept versionId.

Wire handlers.restoreVersion so the server state is updated, then refresh editor content.

-  const handleRestoreVersion = useCallback(
-    async (descriptionHTML: string) => {
-      editorRef.current?.clearEditor();
-      editorRef.current?.setEditorValue(descriptionHTML);
-    },
-    [editorRef]
-  );
+  const handleRestoreVersion = useCallback(
+    async (versionId: string, descriptionHTML: string) => {
+      try {
+        await handlers.restoreVersion(page.id ?? "", versionId);
+        editorRef.current?.clearEditor();
+        editorRef.current?.setEditorValue(descriptionHTML);
+      } catch (e) {
+        // surface/pipe to toast as needed
+        console.error("Failed to restore version", e);
+        throw e;
+      }
+    },
+    [editorRef, handlers, page.id]
+  );

Also update PageVersionsOverlay prop signature and calls accordingly (outside this file):

// apps/web/core/components/pages/version/root.tsx (prop type)
export type TPageVersionsOverlayProps = {
  handleRestore: (versionId: string, descriptionHTML: string) => Promise<void>;
  // ...
};

// wherever PageVersionsOverlay invokes the callback
props.handleRestore(version.id, version.descriptionHTML);

54-55: Fix strict TS ref typing.

Include null in the ref type to match the initial value.

-  const editorRef = useRef<EditorRefApi>(null);
+  const editorRef = useRef<EditorRefApi | null>(null);

95-103: Pass potentially-absent handlers conditionally to avoid hard dependency.

Avoid passing undefined fields unconditionally; keeps CE hooks flexible.

-  const extendedEditorProps = useExtendedEditorProps({
-    workspaceSlug,
-    page,
-    storeType,
-    fetchEntity: handlers.fetchEntity,
-    getRedirectionLink: handlers.getRedirectionLink,
-    extensionHandlers: editorExtensionHandlers,
-    projectId,
-  });
+  const extendedEditorProps = useExtendedEditorProps({
+    workspaceSlug,
+    page,
+    storeType,
+    extensionHandlers: editorExtensionHandlers,
+    projectId,
+    ...(handlers.fetchEntity && { fetchEntity: handlers.fetchEntity }),
+    ...(handlers.getRedirectionLink && { getRedirectionLink: handlers.getRedirectionLink }),
+  } as any);

27-34: Type drift: optional handlers referenced below aren’t declared on TPageRootHandlers.

handlers.fetchEntity and handlers.getRedirectionLink are passed later but not part of this type. Add them as optional to keep the build green and reflect reality.

 export type TPageRootHandlers = {
   create: (payload: Partial<TPage>) => Promise<Partial<TPage> | undefined>;
   fetchAllVersions: (pageId: string) => Promise<TPageVersion[] | undefined>;
   fetchDescriptionBinary: () => Promise<any>;
   fetchVersionDetails: (pageId: string, versionId: string) => Promise<TPageVersion | undefined>;
   restoreVersion: (pageId: string, versionId: string) => Promise<void>;
   updateDescription: (document: TDocumentPayload) => Promise<void>;
+  // optional wiring used by CE/editor extensions
+  getRedirectionLink?: (...args: any[]) => string;
+  fetchEntity?: (...args: any[]) => Promise<any>;
 } & TEditorBodyHandlers;
🧹 Nitpick comments (2)
apps/web/core/components/pages/editor/page-root.tsx (2)

11-13: Import EPageStoreType as a type-only import (if it’s not a runtime enum).

Prevents bundling an unnecessary runtime import; align with navigation-pane/root.tsx. Validate first since enums require runtime.

-import { PageModals } from "@/plane-web/components/pages";
-import { usePagesPaneExtensions, useExtendedEditorProps } from "@/plane-web/hooks/pages";
-import { EPageStoreType } from "@/plane-web/hooks/store";
+import { PageModals } from "@/plane-web/components/pages";
+import { usePagesPaneExtensions, useExtendedEditorProps } from "@/plane-web/hooks/pages";
+import { type EPageStoreType } from "@/plane-web/hooks/store";

87-93: Pane open-state likely ignores custom extensions; ensure hook treats extension triggers as open.

usePagesPaneExtensions (CE) returns an empty navigationPaneExtensions and sets open-state only for built-ins. With ?paneTab=<extension-trigger>, the pane may remain closed. Update the hook to populate extensions and mark open when the trigger matches an extension.

Suggested patch (in apps/web/ce/hooks/pages/use-pages-pane-extensions.ts):

const paneTab = searchParams.get(PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM);
const isBuiltin = PAGE_NAVIGATION_PANE_TAB_KEYS.includes(paneTab as any);
const hasActiveExtension = navigationPaneExtensions.some(e => e.triggerParam === paneTab);
const isNavigationPaneOpen = !!paneTab && (isBuiltin || hasActiveExtension);

If you want, I can open a follow-up PR to wire extension registration and tests.

Also applies to: 161-173

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b7fc21a and 539c761.

📒 Files selected for processing (4)
  • apps/web/ce/components/pages/modals/modals.tsx (1 hunks)
  • apps/web/core/components/pages/editor/editor-body.tsx (8 hunks)
  • apps/web/core/components/pages/editor/page-root.tsx (5 hunks)
  • apps/web/core/components/pages/navigation-pane/root.tsx (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/ce/components/pages/modals/modals.tsx
  • apps/web/core/components/pages/editor/editor-body.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/core/components/pages/editor/page-root.tsx (4)
apps/web/ce/hooks/pages/use-pages-pane-extensions.ts (1)
  • usePagesPaneExtensions (19-52)
apps/web/ce/hooks/pages/use-extended-editor-extensions.ts (1)
  • useExtendedEditorProps (18-20)
apps/web/core/components/pages/navigation-pane/root.tsx (1)
  • PageNavigationPaneRoot (39-117)
apps/web/ce/components/pages/modals/modals.tsx (1)
  • PageModals (15-15)
apps/web/core/components/pages/navigation-pane/root.tsx (3)
apps/web/ce/types/pages/pane-extensions.ts (1)
  • INavigationPaneExtension (10-16)
apps/web/core/components/pages/navigation-pane/types/extensions.ts (1)
  • INavigationPaneExtension (15-21)
apps/web/core/components/pages/navigation-pane/index.ts (3)
  • PAGE_NAVIGATION_PANE_TABS_QUERY_PARAM (9-9)
  • PAGE_NAVIGATION_PANE_VERSION_QUERY_PARAM (10-10)
  • PAGE_NAVIGATION_PANE_WIDTH (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)

aaryan610
aaryan610 previously approved these changes Aug 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/editor/src/ce/components/document-editor-side-effects.ts (1)

2-2: Optional: add a minimal editor “update” hook skeleton.

Keeps UI output null while demonstrating where page-prop side effects will wire in. Adjust the event name if your Tiptap Editor instance differs.

-import type { ReactElement } from "react";
+import { useEffect, type ReactElement } from "react";

-export const DocumentEditorSideEffects = (_props: DocumentEditorSideEffectsProps): ReactElement | null => null;
+export const DocumentEditorSideEffects = ({ editor, id, updatePageProperties }: DocumentEditorSideEffectsProps): ReactElement | null => {
+  useEffect(() => {
+    if (!updatePageProperties) return;
+    const onUpdate = () => {
+      // Example payload; replace with your actual page props patch
+      updatePageProperties({ lastEditedAt: new Date().toISOString() });
+    };
+    // Verify the event name against your Tiptap version (e.g., "update" or "transaction").
+    // @ts-expect-error - event signature depends on Editor version; confirm at call sites.
+    editor.on?.("update", onUpdate);
+    return () => {
+      // @ts-expect-error - see note above.
+      editor.off?.("update", onUpdate);
+    };
+  }, [editor, id, updatePageProperties]);
+  return null;
+};

Also applies to: 12-12

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 539c761 and f37b4fe.

📒 Files selected for processing (2)
  • packages/editor/src/ce/components/document-editor-side-effects.ts (1 hunks)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
packages/editor/src/ce/components/document-editor-side-effects.ts (1)
packages/editor/src/ce/types/editor-extended.ts (1)
  • IEditorPropsExtended (3-3)
🔇 Additional comments (2)
packages/editor/src/ce/components/document-editor-side-effects.ts (2)

1-1: Good use of type-only import for Editor.

Avoids pulling runtime code and keeps bundle clean.


12-12: No default import usage detected—named export is correct. Verified all call sites import DocumentEditorSideEffects as a named export; no default export needed.

Comment on lines +5 to +10
export type DocumentEditorSideEffectsProps = {
editor: Editor;
id: string;
updatePageProperties?: unknown;
extendedEditorProps?: IEditorPropsExtended;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Type the updatePageProperties callback (avoid unknown).

Use an explicit callable signature so consumers get type-safety and IntelliSense.

 export type DocumentEditorSideEffectsProps = {
   editor: Editor;
   id: string;
-  updatePageProperties?: unknown;
+  updatePageProperties?: (patch: Record<string, unknown>) => void | Promise<void>;
   extendedEditorProps?: IEditorPropsExtended;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export type DocumentEditorSideEffectsProps = {
editor: Editor;
id: string;
updatePageProperties?: unknown;
extendedEditorProps?: IEditorPropsExtended;
};
export type DocumentEditorSideEffectsProps = {
editor: Editor;
id: string;
updatePageProperties?: (patch: Record<string, unknown>) => void | Promise<void>;
extendedEditorProps?: IEditorPropsExtended;
};
🤖 Prompt for AI Agents
In packages/editor/src/ce/components/document-editor-side-effects.ts around
lines 5 to 10, replace the updatePageProperties field typed as unknown with a
concrete callable signature (for example: updatePageProperties?: (id: string,
properties: Partial<PageProperties>) => void | Promise<void>); import or define
the PageProperties type appropriate for your domain (or use a clearly named
interface if it doesn't exist yet) so consumers get type-safety and
IntelliSense, and update any call sites to match the new signature.

@Palanikannan1437 Palanikannan1437 changed the title [WIKI-511] fix: extended page root and editor body [WIKI-511] [WIKI-572] fix: extended page root and editor body Sep 1, 2025
@sriramveeraghanta sriramveeraghanta merged commit fd5ba6c into preview Sep 1, 2025
6 of 7 checks passed
@sriramveeraghanta sriramveeraghanta deleted the fix/refactor-pages branch September 1, 2025 16:47
@coderabbitai coderabbitai bot mentioned this pull request Sep 26, 2025
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants