Skip to content

Conversation

@sriramveeraghanta
Copy link
Member

@sriramveeraghanta sriramveeraghanta commented Dec 30, 2025

Reverts #8464

Summary by CodeRabbit

Release Notes

  • Refactor

    • Improved workspace member management components architecture for better maintainability.
    • Enhanced member activity synchronization when inviting, removing, or updating workspace members.
  • Chores

    • Cleaned up unused member activity-related code.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 30, 2025 15:58
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

This PR reorganizes workspace settings components by consolidating right-sidebar functionality under workspace instead of generic settings, removes unused member activity tracking components and methods, refactors WorkspaceMemberStore to use CoreRootStore, and integrates workspace member activity mutations into member management operations across multiple components.

Changes

Cohort / File(s) Summary
Component organization
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
Replaced SettingsRightSidebar import with WorkspaceSettingsRightSidebar from new workspace directory
Component updates
apps/web/core/components/workspace/settings/invitations-list-item.tsx, apps/web/core/components/workspace/settings/member-columns.tsx, apps/web/core/components/workspace/settings/members-list-item.tsx
Added useWorkspace hook usage to trigger mutateWorkspaceMembersActivity after member/invitation modifications (remove, update role, delete invitation)
Member activity removal (CE)
apps/web/ce/components/projects/members/members-activity-button.tsx, apps/web/ce/components/settings/right-sidebar.tsx, apps/web/ce/store/member/project-member.store.ts
Deleted empty ProjectMembersActivityButton component, removed SettingsRightSidebar component with props type, and removed no-op mutateProjectMembersActivity method from ProjectMemberStore
Right-sidebar consolidation
apps/web/ce/components/workspace/right-sidebar/index.ts, apps/web/ce/components/workspace/right-sidebar/root.tsx
Added new WorkspaceSettingsRightSidebar component as observer-wrapped function accepting workspaceSlug; added barrel export in index file
Project settings layout
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
Converted from exported named const to plain function, removed SettingsRightSidebar import and usage, moved observer wrapper to default export
Member list UI
apps/web/core/components/project/member-list.tsx
Removed ProjectMembersActivityButton import and rendering, removed size="lg" prop from Button, removed inline comment
Member activity hook
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
Extended useWorkspace hook destructure to include mutateWorkspaceMembersActivity, call mutation after successful workspace invite
Store refactoring
apps/web/core/store/member/workspace/workspace-member.store.ts
Replaced RootStore with CoreRootStore dependency, removed rootStore property, refactored async operations to use Promise chaining, removed mutateWorkspaceMembersActivity calls, updated inviteMembersToWorkspace to return response value, refactored member invitation and removal flows with delayed state updates
Project member store
apps/web/core/store/member/project/base-project-member.store.ts
Removed abstract mutateProjectMembersActivity method from interface and base class, inlined state mutation logic in bulkAddMembersToProject, updateMemberRole, and removeMemberFromProject methods
Constants cleanup
apps/web/core/constants/fetch-keys.ts
Removed PROJECT_MEMBER_ACTIVITY export, renamed underscore-prefixed parameters to proper names in PROJECT_DETAILS and PROJECT_ME_INFORMATION

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • prateekshourya29

Poem

🐰 Components shuffle left and right,
WorkspaceSettings find their home so bright,
Mutations trigger after every deed,
Old activity ghosts we no longer need,
Stores refactored, promises now chain,
The workspace hops forward, free from strain! 🌿

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimal and only references the reverted PR without following the provided template structure including description, type of change, test scenarios, or references. Expand the description to follow the template: add detailed explanation of why the revert is needed, select the appropriate type of change, describe testing performed, and reference the related issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Revert: refactor project member page' accurately describes the pull request's main purpose of reverting a previous refactoring commit.
✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR reverts PR #8464, which refactored the project member page. The revert restores the previous architecture where workspace and project member activity mutations are handled at the component level rather than within the store methods.

Key changes:

  • Removes centralized mutateProjectMembersActivity and workspace member activity tracking from stores
  • Restores component-level mutation calls after member operations (add, remove, update roles)
  • Reverts sidebar component organization from unified SettingsRightSidebar back to separate workspace/project sidebars

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/web/core/store/member/workspace/workspace-member.store.ts Reverts to CoreRootStore dependency, removes rootStore reference and centralized activity mutations
apps/web/core/store/member/project/base-project-member.store.ts Removes abstract mutateProjectMembersActivity method and its calls from member operations
apps/web/core/constants/fetch-keys.ts Restores parameter names without underscore prefix and removes PROJECT_MEMBER_ACTIVITY key
apps/web/core/components/workspace/settings/members-list-item.tsx Adds back component-level mutateWorkspaceMembersActivity call after member removal
apps/web/core/components/workspace/settings/member-columns.tsx Adds back activity mutation after role update
apps/web/core/components/workspace/settings/invitations-list-item.tsx Adds back activity mutation after invitation deletion
apps/web/core/components/project/member-list.tsx Removes ProjectMembersActivityButton and related imports, removes button size prop
apps/web/ce/store/member/project-member.store.ts Removes no-op mutateProjectMembersActivity implementation
apps/web/ce/components/workspace/right-sidebar/root.tsx Creates new WorkspaceSettingsRightSidebar stub component
apps/web/ce/components/workspace/right-sidebar/index.ts New export file for workspace right sidebar
apps/web/ce/components/settings/right-sidebar.tsx Removes unified SettingsRightSidebar component
apps/web/ce/components/projects/members/members-activity-button.tsx Removes ProjectMembersActivityButton stub component
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx Removes SettingsRightSidebar usage and observer wrapper
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx Adds back activity mutation after workspace invitation
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx Updates to use WorkspaceSettingsRightSidebar instead of SettingsRightSidebar

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

data: Partial<IWorkspaceMemberInvitation>
) => {
const originalMemberInvitations = [...(this.workspaceMemberInvitations?.[workspaceSlug] ?? [])]; // in case of error, we will revert back to original members
const originalMemberInvitations = [...this.workspaceMemberInvitations?.[workspaceSlug]]; // in case of error, we will revert back to original members
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The spread operator on line 320 may throw a runtime error if this.workspaceMemberInvitations?.[workspaceSlug] is undefined. The optional chaining will return undefined, and spreading undefined will cause an error. Consider using the nullish coalescing operator to provide a fallback empty array.

Suggested change
const originalMemberInvitations = [...this.workspaceMemberInvitations?.[workspaceSlug]]; // in case of error, we will revert back to original members
const originalMemberInvitations = [...(this.workspaceMemberInvitations?.[workspaceSlug] ?? [])]; // in case of error, we will revert back to original members

Copilot uses AI. Check for mistakes.
Comment on lines 303 to 307
inviteMembersToWorkspace = async (workspaceSlug: string, data: IWorkspaceBulkInviteFormData) => {
await this.workspaceService.inviteWorkspace(workspaceSlug, data);
const response = await this.workspaceService.inviteWorkspace(workspaceSlug, data);
await this.fetchWorkspaceMemberInvitations(workspaceSlug);
void this.rootStore.workspaceRoot.mutateWorkspaceMembersActivity(workspaceSlug);
return response;
};
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The interface declares that inviteMembersToWorkspace returns Promise<void>, but the implementation now returns response. The return type in the interface should be updated to match the implementation, or the implementation should be changed to not return the response.

Copilot uses AI. Check for mistakes.
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: 2

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/store/member/workspace/workspace-member.store.ts (1)

50-50: Interface return type mismatch.

The interface declares inviteMembersToWorkspace returning Promise<void> (line 50), but the implementation now returns response (line 306). Update the interface to reflect the actual return type.

🔎 Proposed fix for interface
-  inviteMembersToWorkspace: (workspaceSlug: string, data: IWorkspaceBulkInviteFormData) => Promise<void>;
+  inviteMembersToWorkspace: (workspaceSlug: string, data: IWorkspaceBulkInviteFormData) => Promise<IWorkspaceMemberInvitation[]>;

Note: Adjust the return type based on what this.workspaceService.inviteWorkspace actually returns.

Also applies to: 303-307

🧹 Nitpick comments (3)
apps/web/core/components/workspace/settings/invitations-list-item.tsx (1)

62-62: Consider adding .toString() for type consistency.

On line 56, workspaceSlug.toString() is used when calling deleteMemberInvitation. For consistency and type safety, consider doing the same here since workspaceSlug from useParams() can be string | string[].

🔎 Proposed fix
-      void mutateWorkspaceMembersActivity(workspaceSlug);
+      void mutateWorkspaceMembersActivity(workspaceSlug.toString());
apps/web/core/constants/fetch-keys.ts (2)

157-158: Consider removing the unused workspaceSlug parameter entirely.

The _workspaceSlug prefix correctly indicates this parameter is unused, but since the function body doesn't reference it and similar project-level functions (lines 163-200) don't include this parameter, consider removing it entirely for a cleaner API.

If the parameter must be retained for backward compatibility with existing callers, the current underscore prefix is appropriate.

🔎 Proposed simplification
-export const PROJECT_DETAILS = (workspaceSlug: string, projectId: string) =>
+export const PROJECT_DETAILS = (projectId: string) =>
   `PROJECT_DETAILS_${projectId.toString().toUpperCase()}`;

160-161: Consider removing the unused workspaceSlug parameter entirely.

Same as line 157-158: the _workspaceSlug parameter is unused in the function body. Consider removing it entirely unless required for backward compatibility.

🔎 Proposed simplification
-export const PROJECT_ME_INFORMATION = (workspaceSlug: string, projectId: string) =>
+export const PROJECT_ME_INFORMATION = (projectId: string) =>
   `PROJECT_ME_INFORMATION_${projectId.toString().toUpperCase()}`;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d61b157 and cfd7f62.

📒 Files selected for processing (15)
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
  • apps/web/ce/components/projects/members/members-activity-button.tsx
  • apps/web/ce/components/settings/right-sidebar.tsx
  • apps/web/ce/components/workspace/right-sidebar/index.ts
  • apps/web/ce/components/workspace/right-sidebar/root.tsx
  • apps/web/ce/store/member/project-member.store.ts
  • apps/web/core/components/project/member-list.tsx
  • apps/web/core/components/workspace/settings/invitations-list-item.tsx
  • apps/web/core/components/workspace/settings/member-columns.tsx
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • apps/web/core/constants/fetch-keys.ts
  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/core/store/member/workspace/workspace-member.store.ts
💤 Files with no reviewable changes (4)
  • apps/web/ce/components/settings/right-sidebar.tsx
  • apps/web/core/components/project/member-list.tsx
  • apps/web/ce/components/projects/members/members-activity-button.tsx
  • apps/web/ce/store/member/project-member.store.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
  • apps/web/ce/components/workspace/right-sidebar/root.tsx
  • apps/web/core/constants/fetch-keys.ts
  • apps/web/ce/components/workspace/right-sidebar/index.ts
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/core/components/workspace/settings/member-columns.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
  • apps/web/core/components/workspace/settings/invitations-list-item.tsx
  • apps/web/core/store/member/workspace/workspace-member.store.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Enable TypeScript strict mode and ensure all files are fully typed

Files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
  • apps/web/ce/components/workspace/right-sidebar/root.tsx
  • apps/web/core/constants/fetch-keys.ts
  • apps/web/ce/components/workspace/right-sidebar/index.ts
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/core/components/workspace/settings/member-columns.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
  • apps/web/core/components/workspace/settings/invitations-list-item.tsx
  • apps/web/core/store/member/workspace/workspace-member.store.ts
**/*.{js,jsx,ts,tsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with Tailwind plugin for code formatting, run pnpm fix:format

Files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
  • apps/web/ce/components/workspace/right-sidebar/root.tsx
  • apps/web/core/constants/fetch-keys.ts
  • apps/web/ce/components/workspace/right-sidebar/index.ts
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/core/components/workspace/settings/member-columns.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
  • apps/web/core/components/workspace/settings/invitations-list-item.tsx
  • apps/web/core/store/member/workspace/workspace-member.store.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Use ESLint with shared config across packages, adhering to max warnings limits per package
Use camelCase for variable and function names, PascalCase for components and types
Use try-catch with proper error types and log errors appropriately

Files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx
  • apps/web/ce/components/workspace/right-sidebar/root.tsx
  • apps/web/core/constants/fetch-keys.ts
  • apps/web/ce/components/workspace/right-sidebar/index.ts
  • apps/web/core/components/workspace/settings/members-list-item.tsx
  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/core/components/workspace/settings/member-columns.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
  • apps/web/core/components/workspace/settings/invitations-list-item.tsx
  • apps/web/core/store/member/workspace/workspace-member.store.ts
🧠 Learnings (8)
📚 Learning: 2025-09-02T08:14:49.260Z
Learnt from: sriramveeraghanta
Repo: makeplane/plane PR: 7697
File: apps/web/app/(all)/[workspaceSlug]/(projects)/header.tsx:12-13
Timestamp: 2025-09-02T08:14:49.260Z
Learning: The star-us-link.tsx file in apps/web/app/(all)/[workspaceSlug]/(projects)/ already has "use client" directive at the top, making it a proper Client Component for hook usage.

Applied to files:

  • apps/web/ce/components/workspace/right-sidebar/root.tsx
📚 Learning: 2025-12-12T15:20:36.542Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T15:20:36.542Z
Learning: Applies to **/package.json : Use `workspace:*` for internal packages and `catalog:` for external dependencies in imports

Applied to files:

  • apps/web/core/constants/fetch-keys.ts
📚 Learning: 2025-05-28T09:53:44.635Z
Learnt from: prateekshourya29
Repo: makeplane/plane PR: 7094
File: web/core/store/user/base-permissions.store.ts:196-201
Timestamp: 2025-05-28T09:53:44.635Z
Learning: All role enums in this codebase (EUserPermissions, EUserWorkspaceRoles, EUserProjectRoles) use the same consistent numeric values: ADMIN = 20, MEMBER = 15, GUEST = 5. None of these enums have a value of 0, so truthy checks work correctly with these enum values.

Applied to files:

  • apps/web/core/constants/fetch-keys.ts
📚 Learning: 2025-05-28T09:53:44.635Z
Learnt from: prateekshourya29
Repo: makeplane/plane PR: 7094
File: web/core/store/user/base-permissions.store.ts:196-201
Timestamp: 2025-05-28T09:53:44.635Z
Learning: The `EUserPermissions` enum in this codebase uses numeric values: ADMIN = 20, MEMBER = 15, GUEST = 5. All roles in this enum are always numbers, not string values.

Applied to files:

  • apps/web/core/constants/fetch-keys.ts
📚 Learning: 2025-06-16T07:23:39.497Z
Learnt from: vamsikrishnamathala
Repo: makeplane/plane PR: 7214
File: web/core/store/issue/helpers/base-issues.store.ts:117-117
Timestamp: 2025-06-16T07:23:39.497Z
Learning: In the updateIssueDates method of BaseIssuesStore (web/core/store/issue/helpers/base-issues.store.ts), the projectId parameter is intentionally made optional to support override implementations in subclasses. The base implementation requires projectId and includes an early return check, but making it optional allows derived classes to override the method with different parameter requirements.

Applied to files:

  • apps/web/core/store/member/project/base-project-member.store.ts
📚 Learning: 2025-12-12T15:20:36.542Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T15:20:36.542Z
Learning: Applies to packages/shared-state/**/*.{ts,tsx} : Maintain MobX stores in `packages/shared-state` using reactive patterns

Applied to files:

  • apps/web/core/store/member/project/base-project-member.store.ts
  • apps/web/core/store/member/workspace/workspace-member.store.ts
📚 Learning: 2025-10-21T17:22:05.204Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7989
File: apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx:45-46
Timestamp: 2025-10-21T17:22:05.204Z
Learning: In the makeplane/plane repository, the refactor from useParams() to params prop is specifically scoped to page.tsx and layout.tsx files in apps/web/app (Next.js App Router pattern). Other components (hooks, regular client components, utilities) should continue using the useParams() hook as that is the correct pattern for non-route components.

Applied to files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx
📚 Learning: 2025-10-01T15:30:17.605Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7888
File: packages/propel/src/avatar/avatar.stories.tsx:2-3
Timestamp: 2025-10-01T15:30:17.605Z
Learning: In the makeplane/plane repository, avoid suggesting inline type imports (e.g., `import { Avatar, type TAvatarSize }`) due to bundler compatibility issues. Keep type imports and value imports as separate statements.

Applied to files:

  • apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx
🧬 Code graph analysis (8)
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx (2)
apps/admin/core/hooks/store/use-workspace.tsx (1)
  • useWorkspace (6-10)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/constants/fetch-keys.ts (1)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/workspace/settings/members-list-item.tsx (2)
apps/admin/core/hooks/store/use-workspace.tsx (1)
  • useWorkspace (6-10)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/store/member/project/base-project-member.store.ts (1)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx (2)
apps/web/ce/components/workspace/right-sidebar/root.tsx (1)
  • WorkspaceSettingsRightSidebar (5-10)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/workspace/settings/member-columns.tsx (2)
apps/admin/core/hooks/store/use-workspace.tsx (1)
  • useWorkspace (6-10)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/components/workspace/settings/invitations-list-item.tsx (2)
apps/admin/core/hooks/store/use-workspace.tsx (1)
  • useWorkspace (6-10)
apps/space/core/store/publish/publish.store.ts (1)
  • workspaceSlug (93-95)
apps/web/core/store/member/workspace/workspace-member.store.ts (1)
apps/web/core/store/member/index.ts (1)
  • IMemberRootStore (13-22)
🪛 Biome (2.1.2)
apps/web/core/store/member/workspace/workspace-member.store.ts

[error] 320-320: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

⏰ 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). (4)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Build packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (10)
apps/web/ce/components/workspace/right-sidebar/index.ts (1)

1-1: LGTM!

Standard barrel export pattern for the new workspace right-sidebar module.

apps/web/core/components/workspace/settings/members-list-item.tsx (1)

35-35: LGTM!

The pattern of calling mutateWorkspaceMembersActivity after member removal is consistent with other components in this PR. Using void to explicitly discard the promise is appropriate for fire-and-forget operations.

Also applies to: 61-62

apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/members/page.tsx (1)

43-43: LGTM!

The integration of mutateWorkspaceMembersActivity follows the established pattern in this PR. Calling it after successful invitation ensures the workspace member activity state stays synchronized.

Also applies to: 55-56

apps/web/ce/components/workspace/right-sidebar/root.tsx (1)

5-10: Placeholder component noted.

This CE placeholder returns an empty fragment. The observer wrapper and eslint-disable comment indicate this is intentional scaffolding, likely for enterprise edition to extend.

apps/web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx (1)

12-12: LGTM!

The component replacement from SettingsRightSidebar to WorkspaceSettingsRightSidebar is correctly applied, with the import path and prop passing updated appropriately.

Also applies to: 51-51

apps/web/core/components/workspace/settings/member-columns.tsx (1)

19-19: LGTM!

The mutateWorkspaceMembersActivity integration follows the consistent pattern established across this PR. Triggering the mutation after a successful role update ensures the activity state remains synchronized.

Also applies to: 124-124, 159-159

apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx (2)

13-33: Observer pattern correctly implemented.

The observer wrapper is properly applied at the default export level, ensuring the component will reactively update when observable store data changes. The component structure follows Next.js App Router conventions with correct use of the params prop for layout.tsx files.


13-33: Export pattern change is safe. No files in the codebase import the named export ProjectDetailSettingsLayout, so the change from named export to default export poses no risk to dependent code.

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

432-436: LGTM! Proper async state update pattern.

The change correctly awaits the service call before updating state within runInAction, ensuring that member removal only occurs after successful deletion from the backend. This prevents state inconsistency if the API call fails.

apps/web/core/constants/fetch-keys.ts (1)

157-161: The removal of PROJECT_MEMBER_ACTIVITY is safe. No remaining references to this constant exist in the codebase.

Comment on lines +318 to +324
update(this.projectRoot.projectMap, [projectId, "members"], (memberIds) =>
uniq([...memberIds, ...data.members.map((m) => m.member_id)])
);
this.projectRoot.projectMap[projectId].members = this.projectRoot.projectMap?.[projectId]?.members?.concat(
data.members.map((m) => m.member_id)
);
void this.mutateProjectMembersActivity(workspaceSlug, projectId);

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Duplicate and conflicting member updates outside runInAction.

Lines 318-320 use update() with uniq() to deduplicate members, but lines 321-323 immediately overwrite this with a direct mutation that:

  1. Executes outside the runInAction block (which ends at line 317), violating MobX patterns
  2. Doesn't deduplicate, potentially introducing duplicate member IDs
  3. Directly mutates observable state without proper action wrapping
  4. Makes the first update (lines 318-320) redundant
🔎 Proposed fix: Remove the redundant direct mutation
      update(this.projectRoot.projectMap, [projectId, "members"], (memberIds) =>
        uniq([...memberIds, ...data.members.map((m) => m.member_id)])
      );
-      this.projectRoot.projectMap[projectId].members = this.projectRoot.projectMap?.[projectId]?.members?.concat(
-        data.members.map((m) => m.member_id)
-      );

      return response;

Alternatively, if you need both updates for some reason, wrap the second one in runInAction:

      update(this.projectRoot.projectMap, [projectId, "members"], (memberIds) =>
        uniq([...memberIds, ...data.members.map((m) => m.member_id)])
      );
-      this.projectRoot.projectMap[projectId].members = this.projectRoot.projectMap?.[projectId]?.members?.concat(
-        data.members.map((m) => m.member_id)
-      );
+      runInAction(() => {
+        set(this.projectRoot.projectMap, [projectId, "members"], 
+          uniq([...(this.projectRoot.projectMap?.[projectId]?.members ?? []), ...data.members.map((m) => m.member_id)])
+        );
+      });

      return response;

However, the first solution (removing lines 321-323) is preferred since the update() call already handles the mutation correctly.

🤖 Prompt for AI Agents
In apps/web/core/store/member/project/base-project-member.store.ts around lines
318 to 324, there is a redundant direct mutation that overwrites the prior
update: remove the direct assignment block (lines 321-323) that does
this.projectRoot.projectMap[projectId].members = ... since update(...) with
uniq(...) already performs the correct, deduplicated mutation inside the
runInAction; if you must keep a second assignment for some reason, instead wrap
it in runInAction and apply uniq to its result to avoid duplicates and avoid
mutating observables outside an action.

data: Partial<IWorkspaceMemberInvitation>
) => {
const originalMemberInvitations = [...(this.workspaceMemberInvitations?.[workspaceSlug] ?? [])]; // in case of error, we will revert back to original members
const originalMemberInvitations = [...this.workspaceMemberInvitations?.[workspaceSlug]]; // in case of error, we will revert back to original members
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unsafe optional chaining can throw TypeError.

If this.workspaceMemberInvitations?.[workspaceSlug] short-circuits to undefined, the spread operator will throw a TypeError: undefined is not iterable. The static analysis tool correctly flagged this.

🔎 Proposed fix
-    const originalMemberInvitations = [...this.workspaceMemberInvitations?.[workspaceSlug]]; // in case of error, we will revert back to original members
+    const originalMemberInvitations = [...(this.workspaceMemberInvitations?.[workspaceSlug] ?? [])]; // in case of error, we will revert back to original members
🧰 Tools
🪛 Biome (2.1.2)

[error] 320-320: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

🤖 Prompt for AI Agents
In apps/web/core/store/member/workspace/workspace-member.store.ts around line
320, the spread uses this.workspaceMemberInvitations?.[workspaceSlug] which can
be undefined and cause "undefined is not iterable"; change the expression to
default to an empty array before spreading (e.g., use nullish coalescing or
logical OR) so the spread always receives an iterable and preserves the original
invitations safely.

@sriramveeraghanta sriramveeraghanta merged commit 6129e8e into preview Dec 30, 2025
17 of 18 checks passed
@sriramveeraghanta sriramveeraghanta deleted the revert-8464-chore-project-members-enchancements branch December 30, 2025 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants