Skip to content

[WEB-4852]chore: views refactor#7729

Merged
sriramveeraghanta merged 4 commits intopreviewfrom
chore_views-refactor
Sep 11, 2025
Merged

[WEB-4852]chore: views refactor#7729
sriramveeraghanta merged 4 commits intopreviewfrom
chore_views-refactor

Conversation

@vamsikrishnamathala
Copy link
Member

@vamsikrishnamathala vamsikrishnamathala commented Sep 5, 2025

Description

This PR implements a significant refactoring of the views-related code across the application, focusing on improving code organization, reducing duplication, and centralizing view-related functionality.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Unified, permission-aware view action menu across project and workspace views (edit for owners, delete for owners/admins, open in new tab, copy link) with localized labels.
  • Changes

    • Locked views no longer show update or “Save as” controls; locked-state UI/tooltips removed.
    • Publish and lock/unlock actions removed from view menus and stores for a simpler experience.
  • Style

    • Header right section vertically centered for improved alignment.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 5, 2025

Walkthrough

Centralizes view context-menu construction into a new hook-based factory, refactors quick-action components to consume it, removes CE-specific no-op service stubs, standardizes workspace/view service constructors to use API_BASE_URL, simplifies global/project view stores by removing publish/lock/access APIs, updates import/re-export paths, and makes a small header alignment tweak.

Changes

Cohort / File(s) Summary
Menu items factory & usage
apps/web/ce/components/views/helper.tsx, apps/web/core/components/views/quick-actions.tsx, apps/web/core/components/workspace/views/quick-action.tsx
Adds TMenuItemsFactoryProps, useMenuItemsFactory, and useViewMenuItems to produce permission-aware context menu items; replaces hard-coded MENU_ITEMS in quick-action components with the hook output.
Update view UI simplification
apps/web/core/components/views/update-view-component.tsx
Removes LockedComponent and tooltip usage; only renders save/update actions when not locked and filters differ.
CE service stubs removed
apps/web/ce/services/workspace.service.ts (deleted), apps/web/ce/services/project/view.service.ts (deleted)
Deletes CE-specific WorkspaceService and ViewService stub implementations; callers will use core implementations.
Service constructor & export path refactors
apps/web/core/services/workspace.service.ts, apps/web/core/services/view.service.ts, apps/web/core/local-db/utils/load-workspace.ts, apps/web/ce/services/index.ts, apps/web/ce/services/project/index.ts, apps/web/ee/services/index.ts, apps/web/ee/services/project/index.ts
Change constructors to parameterless and call super(API_BASE_URL); update several re-export/import paths to alias-based module specifiers; remove some cross-package re-exports.
Store API streamlining (views)
apps/web/core/store/global-view.store.ts, apps/web/core/store/project-view.store.ts
Convert create/update to class methods, add try/catch and revert semantics, remove publish/lock/updateViewAccess APIs and related logic, simplify update/create flows.
CE store barrels
apps/web/ce/store/global-view.store.ts, apps/web/ce/store/project-view.store.ts
Add CE-level re-exports that forward to core/alias store modules.
Hook/store import path updates
apps/web/core/hooks/store/use-global-view.ts, apps/web/core/hooks/store/use-project-view.ts, apps/web/core/store/user/base-permissions.store.ts
Adjust import paths to point to @/plane-web/... or @/plane-web/services where types/services are consumed.
Minor UI alignment
apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/header.tsx
Adds items-center class to Header.RightItem for vertical alignment.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Component as QuickActions Component
  participant Hook as useViewMenuItems
  participant Factory as useMenuItemsFactory
  Note over Component,Hook: Build menu at render time
  User->>Component: Open context menu
  Component->>Hook: useViewMenuItems(props)
  Hook->>Factory: create item builders (edit/open/copy/delete)
  Factory-->>Hook: item creators (permission-aware)
  Hook-->>Component: TContextMenuItem[]
  Component->>User: Render menu
  alt Edit
    User->>Component: Click "Edit"
    Component->>Component: captureClick()
    Component->>Component: setCreateUpdateViewModal(true)
  else Open in new tab
    User->>Component: Click "Open in new tab"
    Component->>Component: handleOpenInNewTab()
  else Copy link
    User->>Component: Click "Copy link"
    Component->>Component: handleCopyText()
  else Delete
    User->>Component: Click "Delete"
    Component->>Component: setDeleteViewModal(true)
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant UVC as UpdateViewComponent
  participant Store as View Store
  Note over UVC: Locked-state UI removed
  User->>UVC: View header
  alt isLocked or filtersEqual or unauthorized
    UVC-->>User: No action buttons rendered
  else
    UVC-->>User: Show "Save as" (+ optional "Update view")
    User->>UVC: Click "Update view"
    UVC->>Store: handleUpdateView()
    Store-->>UVC: Updated view
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

Suggested labels

🌐frontend, 🛠️refactor

Suggested reviewers

  • sriramveeraghanta
  • prateekshourya29
  • aaryan610

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The description correctly labels the change as a code refactor and gives a brief high-level summary, but it omits reviewer-critical details: there are no test scenarios or QA steps, no references/issue links, and it does not document breaking changes or migration notes visible in the diff (removed CE workspace/view service files, removed publish/lock APIs from stores, and constructor/signature changes). This lack of detail makes it difficult for reviewers to assess risk and required downstream updates. Please expand the PR description to include a concise changelog of breaking changes (files removed and public API methods/signatures altered), explicit migration steps or consumer impact, the tests and manual QA steps performed (or steps for reviewers to verify), and links to related issues or design/docs so reviewers can evaluate impact and approve safely.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "[WEB-4852]chore: views refactor" is concise, includes the issue tag and conventional commit type, and accurately summarizes the primary change—a refactor of view-related code across the repository—so it is clear and relevant to the changes shown in the diff.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Poem

I nibble menus, tidy hops in tow,
Icons and hooks arranged in row.
Stubs hopped out, the core now leads,
Views refresh with simpler deeds.
A rabbit cheers the cleaner code—hip-hop, let's go! 🐇✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c216586 and 065035f.

📒 Files selected for processing (2)
  • apps/web/ce/components/views/helper.tsx (2 hunks)
  • apps/web/ee/services/project/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/ee/services/project/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/ce/components/views/helper.tsx
⏰ 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 chore_views-refactor

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@vamsikrishnamathala vamsikrishnamathala changed the title chore: views refactor [WEB-4852]chore: views refactor Sep 5, 2025
@makeplane
Copy link

makeplane bot commented Sep 5, 2025

Pull Request Linked with Plane Work Items

Comment Automatically Generated by Plane

@prateekshourya29 prateekshourya29 marked this pull request as ready for review September 11, 2025 09:34
pushya22
pushya22 previously approved these changes Sep 11, 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 (5)
apps/web/core/store/global-view.store.ts (2)

171-180: Potential crash when prior filters are missing

Accessing workspaceIssuesFilter.filters[viewId].filters can be undefined, causing a runtime error.

-          const currentGlobalViewFilters: IIssueFilterOptions = this.rootStore.issue.workspaceIssuesFilter.filters[
-            viewId
-          ].filters as IIssueFilterOptions;
+          const currentGlobalViewFilters =
+            (this.rootStore.issue.workspaceIssuesFilter.filters?.[viewId]?.filters as IIssueFilterOptions | undefined) ??
+            {};
           const newFilters: IIssueFilterOptions = {};
-          Object.keys(currentGlobalViewFilters ?? {}).forEach((key) => {
+          Object.keys(currentGlobalViewFilters).forEach((key) => {
             newFilters[key as keyof IIssueFilterOptions] = [];
           });

200-204: Don’t swallow errors; wrap revert in runInAction and rethrow

Swallowing makes upstream UX inconsistent versus createGlobalView which rethrows.

-    } catch {
-      Object.keys(data).forEach((key) => {
-        const currentKey = key as keyof IWorkspaceView;
-        if (currentViewData) set(this.globalViewMap, [viewId, currentKey], currentViewData[currentKey]);
-      });
+    } catch (error) {
+      runInAction(() => {
+        Object.keys(data).forEach((key) => {
+          const currentKey = key as keyof IWorkspaceView;
+          if (currentViewData) set(this.globalViewMap, [viewId, currentKey], currentViewData[currentKey]);
+        });
+      });
+      throw error;
     }
apps/web/core/store/project-view.store.ts (1)

26-26: Fix type mismatch: getViewById may return null but interface disallows it

The interface promises IProjectView, while the implementation returns IProjectView | null. This will fail TS interface conformance.

Apply:

-  getViewById: (viewId: string) => IProjectView;
+  getViewById: (viewId: string) => IProjectView | null;

Also applies to: 132-132

apps/web/core/local-db/utils/load-workspace.ts (1)

2-2: Remove unused API_BASE_URL import

After switching to parameterless WorkspaceService, this import is unused and may fail lint.

-import { API_BASE_URL } from "@plane/constants";
apps/web/core/services/view.service.ts (1)

12-26: Tighten return types for stronger contracts

createView/patchView return any but callers treat them as IProjectView. Make the types explicit.

-  async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<any> {
+  async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<IProjectView> {
...
-  async patchView(workspaceSlug: string, projectId: string, viewId: string, data: Partial<IProjectView>): Promise<any> {
+  async patchView(workspaceSlug: string, projectId: string, viewId: string, data: Partial<IProjectView>): Promise<IProjectView> {
🧹 Nitpick comments (14)
apps/web/core/hooks/store/use-project-view.ts (1)

5-5: Type import path shift — IProjectViewStore exported from file; no barrel re-export

IProjectViewStore is declared/exported in apps/web/core/store/project-view.store.ts (export interface at line 14); use-project-view.ts imports it from '@/plane-web/store/project-view.store' — the import is valid and no type drift observed. No store-level barrel re-export of IProjectViewStore was found; add a re-export if you want consumers to import from '@/plane-web/store' instead of the file path.

apps/web/core/components/views/update-view-component.tsx (2)

16-17: Unused prop: remove lockedTooltipContent from Props

lockedTooltipContent is no longer destructured or used. Drop it from Props to avoid dead API surface.

Apply:

 type Props = {
   isLocked: boolean;
   areFiltersEqual: boolean;
   isOwner: boolean;
   isAuthorizedUser: boolean;
   setIsModalOpen: (value: SetStateAction<boolean>) => void;
   handleUpdateView: () => void;
-  lockedTooltipContent?: string;
   trackerElement: string;
 };

48-61: Locked views now hide all actions — confirm intended UX (Save as may be desirable while locked)

Current condition hides both “Save as” and “Update view” when isLocked. If “Save as” should remain available for authorized users on locked views, decouple its visibility from isLocked.

Optionally:

-      {!isLocked && !areFiltersEqual && isAuthorizedUser && (
+      {!areFiltersEqual && isAuthorizedUser && (
         <>
           <Button
             variant="outline-primary"
             size="md"
             className="flex-shrink-0"
             data-ph-element={trackerElement}
             onClick={() => setIsModalOpen(true)}
           >
             Save as
           </Button>
-          {isOwner && <>{updateButton}</>}
+          {isOwner && !isLocked && <>{updateButton}</>}
         </>
       )}
apps/web/core/components/views/quick-actions.tsx (1)

57-71: Avoid brittle fixed-index splice for publish item

Inserting at index 2 assumes a specific base order from the factory. Prefer injecting via the factory or compute position relative to a known key.

Apply:

-  if (publishContextMenu) MENU_ITEMS.splice(2, 0, publishContextMenu);
+  if (publishContextMenu) {
+    const anchorIdx = MENU_ITEMS.findIndex((i) => i.key === "copy-link" || i.key === "open-in-new-tab");
+    const insertAt = anchorIdx >= 0 ? anchorIdx + 1 : MENU_ITEMS.length;
+    MENU_ITEMS.splice(insertAt, 0, publishContextMenu);
+  }

Or expose a withPublishItem() from the menu factory to control placement centrally.

apps/web/ce/components/views/helper.tsx (2)

5-5: Mark TWorkspaceLayoutProps as a type-only import to avoid runtime cycles

Helps tree-shaking and prevents potential circular deps at runtime.

-import { TWorkspaceLayoutProps } from "@/components/views/helper";
+import type { TWorkspaceLayoutProps } from "@/components/views/helper";

17-28: Trim or document unused props (workspaceSlug, projectId, viewId)

They’re not consumed by the factory. Either remove for now or add a comment indicating upcoming usage to avoid confusion.

apps/web/core/components/workspace/views/quick-action.tsx (1)

36-45: Localize toast messages

"Link Copied!" and "View link copied to clipboard." are user-facing. Prefer i18n for consistency.

-  copyUrlToClipboard(viewLink).then(() => {
-      setToast({
-        type: TOAST_TYPE.SUCCESS,
-        title: "Link Copied!",
-        message: "View link copied to clipboard.",
-      });
-    });
+  copyUrlToClipboard(viewLink).then(() => {
+    setToast({
+      type: TOAST_TYPE.SUCCESS,
+      title: t("link_copied_title"),
+      message: t("view_link_copied_message"),
+    });
+  });

If these keys don’t exist, I can add them to i18n. Want me to open a PR?

apps/web/core/store/project-view.store.ts (3)

159-176: Return fetched views and always reset loader

Currently the success path implicitly returns undefined. Also, consider finally to ensure loader reset.

-  fetchViews = async (workspaceSlug: string, projectId: string) => {
-    try {
-      this.loader = true;
-      await this.viewService.getViews(workspaceSlug, projectId).then((response) => {
-        runInAction(() => {
-          response.forEach((view) => {
-            set(this.viewMap, [view.id], view);
-          });
-          set(this.fetchedMap, projectId, true);
-          this.loader = false;
-        });
-        return response;
-      });
-    } catch (error) {
-      this.loader = false;
-      return undefined;
-    }
-  };
+  fetchViews = async (workspaceSlug: string, projectId: string) => {
+    try {
+      this.loader = true;
+      const response = await this.viewService.getViews(workspaceSlug, projectId);
+      runInAction(() => {
+        response.forEach((view) => set(this.viewMap, [view.id], view));
+        set(this.fetchedMap, projectId, true);
+      });
+      return response;
+    } catch {
+      return undefined;
+    } finally {
+      runInAction(() => {
+        this.loader = false;
+      });
+    }
+  };

200-208: Avoid mutating caller’s data in createView

getValidatedViewFilters mutates its input; clone before validating to avoid side effects.

-import { set } from "lodash";
+import { set, cloneDeep } from "lodash";
...
-  async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<IProjectView> {
-    const response = await this.viewService.createView(workspaceSlug, projectId, getValidatedViewFilters(data));
+  async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<IProjectView> {
+    const response = await this.viewService.createView(
+      workspaceSlug,
+      projectId,
+      getValidatedViewFilters(cloneDeep(data))
+    );

103-109: Minor naming consistency

Prefer viewsList (camelCase) over ViewsList.

-    const ViewsList = Object.values(this.viewMap ?? {});
+    const viewsList = Object.values(this.viewMap ?? {});
-    let filteredViews = ViewsList.filter((view) => view?.project === projectId);
+    let filteredViews = viewsList.filter((view) => view?.project === projectId);

Apply similarly in getFilteredProjectViews.

Also applies to: 116-127

apps/web/core/services/view.service.ts (1)

12-18: Preserve error details when response is absent

Re-throwing error?.response?.data can yield undefined on network errors. Prefer fallback to the original error.

-      .catch((error) => {
-        throw error?.response?.data;
-      });
+      .catch((error) => {
+        throw (error?.response?.data ?? error);
+      });

Consider centralizing this in APIService to avoid repetition.

Also applies to: 20-26, 28-34, 36-42, 44-50, 52-58, 60-72, 74-80

apps/web/core/services/workspace.service.ts (3)

27-29: Prefer a backward-compatible constructor to avoid breakages and keep testability

Retain an optional baseUrl param with a default to API_BASE_URL. This keeps overrides/mocking simple and cushions any missed call-site updates.

-export class WorkspaceService extends APIService {
-  constructor() {
-    super(API_BASE_URL);
-  }
-}
+export class WorkspaceService extends APIService {
+  constructor(baseUrl: string = API_BASE_URL) {
+    super(baseUrl);
+  }
+}

31-37: Normalize thrown error shapes across methods

Some methods throw error.response while others throw error.response?.data. This inconsistency bleeds into UI error handling. Consider centralizing error extraction in APIService (e.g., an interceptor or helper) and always throwing a typed APIError.

Example approach in APIService:

protected extractError(e: any) {
  const res = e?.response;
  return {
    status: res?.status,
    data: res?.data ?? res,
    message: res?.data?.message ?? e?.message ?? "Request failed",
  };
}
// Usage in services: .catch((e) => { throw this.extractError(e); })

Also applies to: 39-45, 113-119, 290-298, 336-347, 349-356, 358-368, 370-376, 378-388


323-329: Guard query_type joining to avoid runtime errors

If query_type is unexpectedly missing or not an array, join() will throw. Make it tolerant without changing the API.

-    return this.get(`/api/workspaces/${workspaceSlug}/entity-search/`, {
-      params: {
-        ...params,
-        query_type: params.query_type.join(","),
-      },
-    })
+    return this.get(`/api/workspaces/${workspaceSlug}/entity-search/`, {
+      params: {
+        ...params,
+        ...(params.query_type
+          ? { query_type: Array.isArray(params.query_type) ? params.query_type.join(",") : params.query_type }
+          : {}),
+      },
+    })
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af1dcd3 and c216586.

📒 Files selected for processing (21)
  • apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/header.tsx (1 hunks)
  • apps/web/ce/components/views/helper.tsx (2 hunks)
  • apps/web/ce/services/index.ts (1 hunks)
  • apps/web/ce/services/project/index.ts (1 hunks)
  • apps/web/ce/services/project/view.service.ts (0 hunks)
  • apps/web/ce/services/workspace.service.ts (0 hunks)
  • apps/web/ce/store/global-view.store.ts (1 hunks)
  • apps/web/ce/store/project-view.store.ts (1 hunks)
  • apps/web/core/components/views/quick-actions.tsx (2 hunks)
  • apps/web/core/components/views/update-view-component.tsx (2 hunks)
  • apps/web/core/components/workspace/views/quick-action.tsx (2 hunks)
  • apps/web/core/hooks/store/use-global-view.ts (1 hunks)
  • apps/web/core/hooks/store/use-project-view.ts (1 hunks)
  • apps/web/core/local-db/utils/load-workspace.ts (1 hunks)
  • apps/web/core/services/view.service.ts (1 hunks)
  • apps/web/core/services/workspace.service.ts (2 hunks)
  • apps/web/core/store/global-view.store.ts (4 hunks)
  • apps/web/core/store/project-view.store.ts (4 hunks)
  • apps/web/core/store/user/base-permissions.store.ts (1 hunks)
  • apps/web/ee/services/index.ts (1 hunks)
  • apps/web/ee/services/project/index.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/ce/services/workspace.service.ts
  • apps/web/ce/services/project/view.service.ts
🧰 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/hooks/store/use-project-view.ts
🧬 Code graph analysis (6)
apps/web/core/local-db/utils/load-workspace.ts (1)
apps/web/core/services/workspace.service.ts (1)
  • WorkspaceService (26-389)
apps/web/ce/components/views/helper.tsx (3)
packages/i18n/src/hooks/use-translation.ts (1)
  • useTranslation (23-35)
packages/ui/src/dropdowns/context-menu/root.tsx (1)
  • TContextMenuItem (10-23)
packages/types/src/views.ts (1)
  • IProjectView (9-30)
apps/web/core/components/workspace/views/quick-action.tsx (2)
packages/ui/src/dropdowns/context-menu/root.tsx (1)
  • TContextMenuItem (10-23)
apps/web/ce/components/views/helper.tsx (1)
  • useViewMenuItems (73-77)
apps/web/core/components/views/quick-actions.tsx (2)
packages/ui/src/dropdowns/context-menu/root.tsx (1)
  • TContextMenuItem (10-23)
apps/web/ce/components/views/helper.tsx (1)
  • useViewMenuItems (73-77)
apps/web/core/store/global-view.store.ts (1)
packages/types/src/workspace-views.ts (1)
  • IWorkspaceView (9-33)
apps/web/core/store/project-view.store.ts (2)
packages/types/src/views.ts (1)
  • IProjectView (9-30)
packages/utils/src/project-views.ts (1)
  • getValidatedViewFilters (87-93)
⏰ 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: Build and lint web apps
🔇 Additional comments (21)
apps/web/core/store/user/base-permissions.store.ts (1)

21-21: Switch to plane-web services barrel — confirm export & constructor compatibility

Confirm WorkspaceService is re-exported from @/plane-web/services and that its constructor accepts no required args as used in apps/web/core/store/user/base-permissions.store.ts:21. Per prior learnings, @/plane-web resolves to CE paths — ensure the CE barrel exposes WorkspaceService identically.

apps/web/ce/store/global-view.store.ts (1)

1-1: CE barrel looks good

Re-export keeps CE aligned with the centralized store. No issues spotted.

apps/web/app/(all)/[workspaceSlug]/(projects)/workspace-views/header.tsx (1)

194-194: Centering fix for RightItem

Adding items-center to Header.RightItem is a safe visual improvement. LGTM.

apps/web/core/hooks/store/use-global-view.ts (1)

5-5: Resolved — IGlobalViewStore is exported from global-view.store
Confirmed: apps/web/core/store/global-view.store.ts contains export interface IGlobalViewStore (line 15), so the type is available from that module.

apps/web/core/components/views/quick-actions.tsx (1)

15-16: Good move to hook-based menu factory

Importing useViewMenuItems centralizes menu logic and reduces duplication. Nice.

apps/web/ce/components/views/helper.tsx (2)

73-77: Factory composition LGTM

The hook-based composition is clean and simplifies consumers.


33-33: Translations present — no action required

Keys "edit", "open_in_new_tab", "copy_link", and "delete" are defined in packages/i18n/src/locales/en/translations.json and mirrored across other locale files.

apps/web/core/components/workspace/views/quick-action.tsx (1)

47-57: Good delegation to useViewMenuItems; ensure helper enforces locking

Hook usage looks correct. After applying the helper changes to respect isLocked, the menu will align with permissions.

Please validate that locked views disable Edit/Delete for non-owner/admin as intended after the helper change.

apps/web/core/store/global-view.store.ts (1)

136-148: createGlobalView: pattern looks good

Optimistic write + rethrow on failure is consistent. No changes needed.

apps/web/core/store/project-view.store.ts (1)

86-87: Method binding looks good

Binding class methods prevents context loss when passed as callbacks.

apps/web/ce/store/project-view.store.ts (1)

1-1: CE barrel re-export aligns with core store

Re-exporting the core project-view store via CE path is consistent with the refactor.

apps/web/ee/services/project/index.ts (1)

1-1: No callers import ViewService from ee/services/project — removing the re-export is safe.

Repo search found no imports from ee/services/project; apps/web/ee/services/project/index.ts only exports estimate.service, while ViewService is defined at apps/web/core/services/view.service.ts and consumers import it via @/plane-web/services (no migration required).

Likely an incorrect or invalid review comment.

apps/web/ce/services/index.ts (1)

2-2: Switch to alias-based workspace service export looks correct

Matches centralization to @/services/workspace.service.

apps/web/ce/services/project/index.ts (1)

2-2: Re-exporting view.service from shared alias is consistent

Good consolidation.

apps/web/core/local-db/utils/load-workspace.ts (1)

102-105: Constructor change usage is correct

Instantiating new WorkspaceService() matches the updated service API.

apps/web/ee/services/index.ts (2)

2-2: EE workspace service re-export aligns with centralization

Looks good.


2-2: Ensure "@/services" alias resolves across packages

Found alias usages; confirm your TypeScript path mappings (or the extended @plane/typescript-config/nextjs.json) map "@/services/*" to the shared services package (packages/services/src) or replace with package-relative/relative imports.

Locations:

  • apps/web/ee/services/index.ts:2 — export * from "@/services/workspace.service";
  • apps/web/ce/services/index.ts:2 — export * from "@/services/workspace.service";
  • apps/web/core/local-db/utils/load-workspace.ts:9 — import { WorkspaceService } from "@/services/workspace.service";
  • packages/services/src/workspace/index.ts:5 — export * from "./workspace.service";
apps/web/core/services/view.service.ts (2)

8-10: Constructor update is consistent with centralized API_BASE_URL

No issues.


1-11: No legacy constructor usages found — callers instantiate ViewService with no args.

  • apps/web/core/store/project-view.store.ts:84 — this.viewService = new ViewService();
  • apps/web/core/store/issue/project-views/filter.store.ts:70 — this.issueFilterService = new ViewService();
apps/web/core/services/workspace.service.ts (2)

1-1: Centralizing base URL import looks good

Using API_BASE_URL aligns this service with the new convention and reduces constructor noise.


27-29: Verify no callers still pass a base URL or import the CE/EE service

Automated grep attempts here couldn't confirm (ripgrep skipped files); run the checks below locally and update any matches to use new WorkspaceService() and import from '@/services/workspace.service'.

# (preferred) in a git repo
git grep -n --no-color -E 'new[[:space:]]+WorkspaceService[[:space:]]*\([[:space:]]*[^)\s]' || true
git grep -n --no-color -E "from ['\"][^'\"]*(ce|ee)/services/workspace\.service['\"]" || true

# fallback using ripgrep
rg -n --hidden -S 'new\s+WorkspaceService\s*\(\s*[^)\s]' || true
rg -n --hidden -S "from\s+['\"][^'\"]*(ce|ee)/services/workspace\.service['\"]" || true

@sriramveeraghanta sriramveeraghanta merged commit 85f23b4 into preview Sep 11, 2025
6 of 7 checks passed
@sriramveeraghanta sriramveeraghanta deleted the chore_views-refactor branch September 11, 2025 11:39
yarikoptic pushed a commit to yarikoptic/plane that referenced this pull request Oct 1, 2025
* chore: refactored view store and services

* chore: removed unused import

* chore: refactored update view component

* fix: lint errors
@coderabbitai coderabbitai bot mentioned this pull request Feb 10, 2026
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.

4 participants