[WEB-3964] refactor: permission layer#7094
Conversation
WalkthroughThis update introduces a new singular "member" translation key across all supported locales, refactors project membership types for improved flexibility, and restructures member and permission store logic for better abstraction and extensibility. Several React components and hooks are updated to use explicit props, new helper functions, and revised permission retrieval methods. Minor UI and translation improvements are also included. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI_Component
participant Store
participant PermissionStore
participant ProjectMemberStore
User->>UI_Component: Interact with project members/settings
UI_Component->>PermissionStore: getProjectRoleByWorkspaceSlugAndProjectId(workspaceSlug, projectId)
PermissionStore-->>UI_Component: Returns user role
UI_Component->>ProjectMemberStore: fetchProjectMembers(workspaceSlug, projectId)
ProjectMemberStore-->>UI_Component: Returns member list with roles and original_role
UI_Component->>ProjectMemberStore: updateMemberRole(workspaceSlug, projectId, userId, newRole)
ProjectMemberStore-->>UI_Component: Updates member role, preserves original_role
UI_Component-->>User: Renders updated member list and permissions
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 8
🔭 Outside diff range comments (3)
web/core/components/project/multi-select-modal.tsx (1)
87-87: 🛠️ Refactor suggestionTranslate the search placeholder
The placeholder text is still hardcoded ("Search for projects"). To complete the i18n coverage, wrap it int()and add a corresponding key in your translations.- placeholder="Search for projects" + placeholder={t("project_multi_select_modal.search_projects_placeholder")}And in your locale JSON:
"project_multi_select_modal": { "search_projects_placeholder": "Search for projects" }web/core/components/project/settings/member-columns.tsx (1)
125-133: 🛠️ Refactor suggestion
checkCurrentOptionWorkspaceRolefilters against workspace roles, not project rolesThe helper again leverages the
ROLEmap andEUserPermissions.GUEST, which restricts the dropdown based on workspace membership, not project membership.
This may unintentionally hide valid project-specific roles (e.g., Viewer, Maintainer). Consider re-implementing with the project-role enum and label map.web/core/store/member/base-project-member.store.ts (1)
108-113:⚠️ Potential issue
toLowerCasecan crash whendisplay_nameis undefined
projectMemberIdssorts by(m) => this.memberRoot.memberMap?.[m.member]?.display_name.toLowerCase()If the member exists in
projectMemberMapbut the correspondingmemberMapentry has not been fetched yet,display_nameisundefined, resulting in a runtimeTypeError.-(m) => this.memberRoot.memberMap?.[m.member]?.display_name.toLowerCase(), +(m) => this.memberRoot.memberMap?.[m.member]?.display_name?.toLowerCase(),The same safe-guard is already used in
getProjectMemberIds; bringing the two in sync prevents hard-to-trace crashes.
🧹 Nitpick comments (7)
web/core/components/project/member-list-item.tsx (1)
85-85: Enhanced styling for table headersAdded the additional CSS class
text-custom-text-400 font-mediumto improve table header styling and consistency.web/ce/store/user/permission.store.ts (1)
9-11: Remove unnecessary constructorThe constructor doesn't add any functionality beyond calling the parent constructor.
- constructor(store: RootStore) { - super(store); - }🧰 Tools
🪛 Biome (1.9.4)
[error] 9-11: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
web/ce/store/member/project-member.store.ts (2)
13-15: Remove unnecessary constructorThe constructor doesn't add any functionality beyond calling the parent constructor.
- constructor(_memberRoot: IMemberRootStore, rootStore: RootStore) { - super(_memberRoot, rootStore); - }🧰 Tools
🪛 Biome (1.9.4)
[error] 13-15: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
33-34: Simple pass-through method for role updatesThe
getProjectMemberRoleForUpdatemethod simply returns the role unchanged, which is fine if no transformations are needed. Consider adding a comment explaining why no transformation is needed here if that's the case.web/core/components/project/project-settings-member-defaults.tsx (1)
131-131: Consider using translation keys for UI textThe component currently uses hardcoded English strings for titles and descriptions in the
DefaultSettingItemcomponents. Consider using translation keys from the i18n system to maintain consistency with the rest of the application.- <DefaultSettingItem title="Project Lead" description="Select the project lead for the project."> + <DefaultSettingItem title={t("project_settings.members.project_lead")} description={t("project_settings.members.project_lead_description")}>And similarly for other hardcoded strings.
Also applies to: 152-152, 174-176
web/core/components/project/send-project-invitation-modal.tsx (2)
35-41: Avoid magic numbers – use the enum for default role instead of5
5is opaque and couples the component to the current numeric value ofEUserPermissions.MEMBER(or whichever role index 5 represents). Relying on the literal makes future enum re-ordering risky and hurts readability.
Consider:- role: 5, + role: EUserPermissions.MEMBER,and update the other occurrences (lines 123–124 & 132–133) similarly.
80-83: RedundanttoString()calls
workspaceSlugandprojectIdare already typed asstring; the extra.toString()is unnecessary and may hide unintendedundefined/nullpropagation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (63)
packages/i18n/src/locales/cs/translations.json(1 hunks)packages/i18n/src/locales/de/translations.json(2 hunks)packages/i18n/src/locales/en/translations.json(1 hunks)packages/i18n/src/locales/es/translations.json(1 hunks)packages/i18n/src/locales/fr/translations.json(1 hunks)packages/i18n/src/locales/id/translations.json(1 hunks)packages/i18n/src/locales/it/translations.json(1 hunks)packages/i18n/src/locales/ja/translations.json(1 hunks)packages/i18n/src/locales/ko/translations.json(1 hunks)packages/i18n/src/locales/pl/translations.json(1 hunks)packages/i18n/src/locales/pt-BR/translations.json(1 hunks)packages/i18n/src/locales/ro/translations.json(1 hunks)packages/i18n/src/locales/ru/translations.json(1 hunks)packages/i18n/src/locales/sk/translations.json(1 hunks)packages/i18n/src/locales/tr-TR/translations.json(1 hunks)packages/i18n/src/locales/ua/translations.json(1 hunks)packages/i18n/src/locales/vi-VN/translations.json(1 hunks)packages/i18n/src/locales/zh-CN/translations.json(1 hunks)packages/i18n/src/locales/zh-TW/translations.json(1 hunks)packages/types/src/project/projects.d.ts(2 hunks)packages/types/src/workspace.d.ts(2 hunks)packages/utils/src/index.ts(1 hunks)packages/utils/src/permission.ts(1 hunks)web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx(2 hunks)web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/sidebar.tsx(2 hunks)web/app/[workspaceSlug]/(projects)/settings/(with-sidebar)/layout.tsx(2 hunks)web/app/onboarding/page.tsx(0 hunks)web/ce/components/projects/settings/useProjectColumns.tsx(2 hunks)web/ce/components/projects/teamspaces/index.ts(1 hunks)web/ce/components/projects/teamspaces/teamspace-list.tsx(1 hunks)web/ce/constants/project/settings/tabs.ts(1 hunks)web/ce/helpers/project-settings.ts(1 hunks)web/ce/store/member/project-member.store.ts(1 hunks)web/ce/store/user/permission.store.ts(1 hunks)web/core/components/auth-screens/project/join-project.tsx(2 hunks)web/core/components/inbox/content/root.tsx(2 hunks)web/core/components/issues/issue-detail/issue-activity/root.tsx(1 hunks)web/core/components/project/create/header.tsx(0 hunks)web/core/components/project/create/project-create-buttons.tsx(1 hunks)web/core/components/project/member-list-item.tsx(3 hunks)web/core/components/project/member-list.tsx(4 hunks)web/core/components/project/member-select.tsx(4 hunks)web/core/components/project/multi-select-modal.tsx(2 hunks)web/core/components/project/project-settings-member-defaults.tsx(5 hunks)web/core/components/project/send-project-invitation-modal.tsx(3 hunks)web/core/components/project/settings/member-columns.tsx(7 hunks)web/core/components/ui/loader/settings/members.tsx(1 hunks)web/core/components/workspace/settings/members-list.tsx(1 hunks)web/core/hooks/store/user/user-permissions.ts(1 hunks)web/core/layouts/auth-layout/project-wrapper.tsx(3 hunks)web/core/lib/posthog-provider.tsx(1 hunks)web/core/local-db/utils/query-sanitizer.ts.ts(1 hunks)web/core/services/project/project-member.service.ts(4 hunks)web/core/store/member/base-project-member.store.ts(10 hunks)web/core/store/member/index.ts(2 hunks)web/core/store/pages/project-page.store.ts(1 hunks)web/core/store/pages/project-page.ts(1 hunks)web/core/store/root.store.ts(2 hunks)web/core/store/user/base-permissions.store.ts(5 hunks)web/core/store/user/index.ts(3 hunks)web/ee/helpers/project-settings.ts(1 hunks)web/ee/store/member/project-member.store.ts(1 hunks)web/ee/store/user/permission.store.ts(1 hunks)
💤 Files with no reviewable changes (2)
- web/core/components/project/create/header.tsx
- web/app/onboarding/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (17)
web/core/components/project/create/project-create-buttons.tsx (1)
packages/i18n/src/store/index.ts (1)
t(233-254)
web/core/components/workspace/settings/members-list.tsx (1)
packages/i18n/src/store/index.ts (1)
t(233-254)
web/core/components/inbox/content/root.tsx (1)
web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)
web/core/store/root.store.ts (2)
web/core/store/user/index.ts (1)
UserStore(57-304)web/core/store/member/index.ts (1)
MemberRootStore(22-49)
web/core/layouts/auth-layout/project-wrapper.tsx (3)
web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)web/core/store/router.store.ts (2)
workspaceSlug(69-71)projectId(85-87)web/core/components/auth-screens/project/join-project.tsx (1)
JoinProject(18-68)
packages/types/src/workspace.d.ts (1)
packages/types/src/project/projects.d.ts (1)
TProjectMembership(85-97)
web/core/components/project/member-list-item.tsx (2)
web/core/store/member/base-project-member.store.ts (1)
IProjectMemberDetails(22-24)web/ce/components/projects/settings/useProjectColumns.tsx (1)
useProjectColumns(19-83)
web/app/[workspaceSlug]/(projects)/settings/(with-sidebar)/layout.tsx (2)
web/core/store/router.store.ts (1)
workspaceSlug(69-71)web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)
web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx (4)
packages/i18n/src/hooks/use-translation.ts (1)
useTranslation(23-35)web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)web/ce/helpers/project-settings.ts (1)
getProjectSettingsPageLabelI18nKey(7-7)web/ce/components/projects/teamspaces/teamspace-list.tsx (1)
ProjectTeamspaceList(6-6)
web/core/components/auth-screens/project/join-project.tsx (1)
web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)
web/ce/store/user/permission.store.ts (2)
web/core/store/user/base-permissions.store.ts (1)
IBaseUserPermissionStore(28-54)web/core/store/router.store.ts (2)
workspaceSlug(69-71)projectId(85-87)
web/ce/store/member/project-member.store.ts (2)
web/core/store/member/base-project-member.store.ts (1)
IBaseProjectMemberStore(26-60)web/core/store/member/index.ts (1)
IMemberRootStore(11-20)
packages/types/src/project/projects.d.ts (1)
packages/types/src/enums.ts (1)
TUserPermissions(7-7)
web/core/store/user/index.ts (1)
web/core/store/router.store.ts (1)
workspaceSlug(69-71)
web/core/components/project/settings/member-columns.tsx (7)
web/ce/components/projects/settings/useProjectColumns.tsx (1)
RowData(10-12)packages/types/src/project/projects.d.ts (1)
TProjectMembership(85-97)apiserver/plane/db/models/user.py (1)
avatar_url(124-132)web/core/services/user.service.ts (1)
currentUser(48-55)packages/ui/src/dropdowns/custom-menu.tsx (1)
CustomMenu(232-232)web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)packages/constants/src/workspace.ts (1)
ROLE(145-149)
web/core/store/user/base-permissions.store.ts (4)
packages/types/src/workspace.d.ts (1)
IWorkspaceMemberMe(79-92)packages/types/src/project/projects.d.ts (1)
TProjectMembership(85-97)packages/types/src/users.d.ts (1)
IUserProjectsRole(166-168)packages/constants/src/workspace.ts (1)
WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS(297-303)
web/core/services/project/project-member.service.ts (2)
web/core/store/router.store.ts (2)
workspaceSlug(69-71)projectId(85-87)packages/types/src/project/projects.d.ts (1)
TProjectMembership(85-97)
🪛 Biome (1.9.4)
web/ce/store/user/permission.store.ts
[error] 9-11: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
web/ce/store/member/project-member.store.ts
[error] 13-15: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
web/core/store/user/base-permissions.store.ts
[error] 51-51: void is confusing inside a union type.
Unsafe fix: Use undefined instead.
(lint/suspicious/noConfusingVoidType)
🔇 Additional comments (94)
packages/i18n/src/locales/fr/translations.json (1)
851-851: Added singular 'member' translation
The new"member": "Membre"entry in thecommonsection correctly provides a singular form alongside the existing plural"members": "Membres". This aligns with updates across other locales and preserves valid JSON structure.packages/i18n/src/locales/tr-TR/translations.json (1)
853-854: Added singular translation key for 'member'
The new"member": "Üye"entry in the"common"section correctly provides the singular form alongside the existing plural"members". This change aligns with the updates in other locales.packages/i18n/src/locales/cs/translations.json (1)
850-851: Added singular translation key for 'member'
The new"member": "Člen"entry in the"common"section correctly provides the singular form alongside the existing plural"members". This change aligns with the updates in other locales.packages/i18n/src/locales/de/translations.json (1)
850-850: Add singular "member" translation
The new"member": "Mitglied"entry aligns with the PR’s introduction of the singular translation key and matches updates in other locales.packages/i18n/src/locales/ro/translations.json (1)
501-501: Add ICU pluralization for “member”.
The new entry"member": "{count, plural, one{# membru} other{# membri}}"correctly defines both singular and plural forms in Romanian. JSON syntax remains valid, and the placement at the root level follows the existing pattern for dynamic count-based translations.
packages/i18n/src/locales/zh-TW/translations.json (1)
852-852: Add singular “member” translation for Traditional Chinese.
The static key"member": "成員"introduces the singular form alongside the existing
"members"entry. The JSON is well-formed with no trailing comma issues.packages/i18n/src/locales/pl/translations.json (1)
852-852: Add singular form for "member"
This new key"member": "Członek"properly complements the existing"members"translation, ensuring the UI can handle both singular and plural forms.packages/i18n/src/locales/es/translations.json (1)
853-853: Validate addition of singular “member” key
The new"member": "Miembro"entry in thecommongroup correctly introduces the singular form alongside"members", matching the pattern in other locales.packages/i18n/src/locales/it/translations.json (1)
847-853: Approve translation addition
The singular key"member": "Membro"is correctly inserted immediately before"members"and follows the same indentation and comma conventions as surrounding entries.Please verify that the new
"member"key is added to your i18n type definitions (e.g., the generated TS translation keys) so that consumers can reference it without type errors.packages/i18n/src/locales/sk/translations.json (1)
852-852: Add singularmembertranslation in Slovak.The new key
"member": "Člen"correctly provides the singular form alongside the existing"members"entry. Syntax and placement are consistent with other locale files.packages/i18n/src/locales/ru/translations.json (1)
852-852: Add singularmembertranslation in Russian.The new key
"member": "Участник"correctly provides the singular form alongside the existing"members"entry. JSON structure and positioning are correct.packages/utils/src/permission.ts (1)
1-13: Well-structured utility function for role comparison.This utility function
getHighestRoleis cleanly implemented with proper typing using generics to maintain the specific role type. The JSDoc documentation clearly explains the purpose and parameters. This function will provide consistent role comparison across the codebase.The implementation is sound, using
reduce()to find the maximum value in the roles array, which is efficient and readable.packages/i18n/src/locales/zh-CN/translations.json (1)
851-851: Good addition of singular form translation key.Adding the singular form "member" alongside the existing plural "members" improves translation consistency and allows for more precise UI text references. This matches the pattern seen in other parts of the translations file where both singular and plural forms are provided.
web/core/components/project/create/project-create-buttons.tsx (1)
28-28: Improved translation key namespace usage.Changing the translation key from a likely top-level "cancel" to "common.cancel" improves organization of translation keys and maintains consistency with other UI components. This change aligns with the broader internationalization improvements in the codebase.
web/core/hooks/store/user/user-permissions.ts (1)
4-5: Updated import path for permission store.This change updates the import path for
IUserPermissionStoreto use the new location in the "plane-web" directory. The refactoring aligns with the PR objectives of improving the permission layer structure. This change maintains the existing interface functionality while pointing to the refactored implementation.packages/i18n/src/locales/ko/translations.json (1)
851-851: Add singular “member” key alongside plural “members”
Introduces the singular translation for “member” to match the existing plural key. This aligns with the PR’s goal of supporting both singular and plural forms across all locales.packages/i18n/src/locales/ja/translations.json (1)
851-851: Add singular “member” key alongside plural “members”
Provides the Japanese singular form “メンバー” to complement the existing plural “メンバー,” ensuring consistent i18n support for member terminology.packages/utils/src/index.ts (1)
18-18: Re-export new permission utilities
Includingexport * from "./permission";exposes thegetHighestRoleand other permission helpers centrally, supporting the refactored permission layer.web/ee/helpers/project-settings.ts (1)
1-1: Proxy CE helper for EE layer
Re-exportingce/helpers/project-settingshere maintains consistency with other EE modules that alias CE helpers, enabling enterprise builds to import the shared utility without path changes.web/core/components/workspace/settings/members-list.tsx (1)
69-71: Improve JSX readability for the Collapsible title
Splitting the<h4>into multiple lines makes the JSX more maintainable without altering behavior.web/ce/components/projects/teamspaces/index.ts (1)
1-1: Re-export of Teamspace List Component Looks Good
The index file cleanly re-exports everything from./teamspace-list, making theProjectTeamspaceListcomponent available via this directory.packages/i18n/src/locales/pt-BR/translations.json (1)
851-854:Details
❓ Verification inconclusive
Ensure Translation Key Consistency Across Locales
You’ve correctly added the singular"member": "Membro"key alongside"members". Please verify that the same key has been added to all other locale files’commonsections to maintain parity.Run this script from the repo root to catch any missing entries:
🏁 Script executed:
#!/bin/bash # Check for missing "member" key in all locale JSON files missing=$(rg -L '"member":' packages/i18n/src/locales/*/translations.json) if [ -n "$missing" ]; then echo "Missing 'member' key in these locale files:" echo "$missing" exit 1 else echo "All locale files contain the 'member' key" fiLength of output: 19928
Ensure Translation Key Consistency Across Locales
Therg -Linvocation is returning every file (it’s printing matches, not missing entries), so it won’t reliably surface any locales missing"member". Please manually confirm that eachpackages/i18n/src/locales/*/translations.jsonfile includes the"member"key in itscommonsection, or run this corrected script:#!/usr/bin/env bash # Report any locale missing the "member" key for file in packages/i18n/src/locales/*/translations.json; do if ! grep -q '"member":' "$file"; then echo "Missing 'member' in locale: $(basename "$(dirname "$file")")" fi doneIf any locales are flagged above, add
"member": "<translation>"alongside"members"under theircommonsection to maintain parity across all languages.web/core/components/project/multi-select-modal.tsx (2)
169-169: Approved: Button labels are now localized
Usingt("cancel")for the Cancel button aligns with our i18n practices and ensures it will render correctly in all locales.
179-179: Approved: Submit button label uses translation keys
Toggling betweent("confirm")andt("confirming")based onisSubmittingis a clear, consistent approach to localizing the confirm action.packages/i18n/src/locales/vi-VN/translations.json (1)
851-851: Added singular translation key
The insertion of"member": "Thành viên"alongside the existing"members"key in thecommonsection correctly provides a singular form. The Vietnamese term is identical for both singular and plural contexts, which is appropriate here.packages/i18n/src/locales/ua/translations.json (1)
852-852: Singular translation key added correctly
The new"member": "Учасник"entry under the"common"section aligns with other locales and provides the singular form.web/ee/store/member/project-member.store.ts (1)
1-1: Proxy module correctly re-exports CE store
This EE-specific file cleanly forwards all exports from the CE implementation to maintain consistency without duplication.web/ee/store/user/permission.store.ts (1)
1-1: EE permission store proxy is consistent
This file correctly re-exports all members from the CE permission store, following the established pattern.packages/i18n/src/locales/id/translations.json (1)
850-850: Added singular translation for "member"The addition of the singular form "member" complements the existing plural form "members", both translated to "Anggota" in Indonesian. This addition ensures consistent internationalization support across the application.
web/core/store/pages/project-page.ts (1)
76-79: Updated to use new permission methodThis change replaces direct access to project permissions with the new
getProjectRoleByWorkspaceSlugAndProjectIdmethod, aligning with the permission layer refactoring described in the PR objectives.web/ce/constants/project/settings/tabs.ts (1)
19-19: Updated i18n label key to use common namespaceThe i18n label for the members tab now uses the "common.members" path, aligning with the standardized approach for accessing member-related translations from the common namespace where both singular and plural forms are defined.
web/core/store/root.store.ts (3)
74-74: Updated type casting for UserStore instantiationThe code now correctly casts
thistoRootStorewhen instantiatingUserStore, which expects aRootStoreparameter, maintaining proper type relationships between stores.
78-78: Updated type casting for MemberRootStore instantiationSimilar to the UserStore change, this appropriately casts
thistoRootStorewhen instantiatingMemberRootStore, which expects aRootStoreparameter, maintaining type consistency.
109-109: Applied same type casting in resetOnSignOut methodThe same type casting improvements were consistently applied in the resetOnSignOut method, ensuring proper typing when reinstantiating stores during user sign-out.
Also applies to: 112-112
web/core/local-db/utils/query-sanitizer.ts.ts (1)
15-15: Correctly refactored to use the new permission methodThe change from direct property access to the
getProjectRoleByWorkspaceSlugAndProjectIdmethod aligns with the permission layer refactoring. This approach provides better encapsulation of permission logic and more consistent access patterns.web/core/components/inbox/content/root.tsx (2)
41-41: Properly destructured the new permission methodThe destructuring now includes
getProjectRoleByWorkspaceSlugAndProjectIdfrom the user permissions hook, correctly implementing the new permission access pattern.
70-70: Correctly implemented role-based permission checkThe isGuest check now uses the new method to retrieve the project role, maintaining the same behavior while following the new permission access pattern.
packages/types/src/workspace.d.ts (2)
1-1: Updated import to use the new membership typeThe import statement correctly uses
TProjectMembershipinstead of the previous membership interface, aligning with the broader type system refactoring.
96-96: Updated to use the new membership typeThe
project_detailsproperty has been correctly typed to useTProjectMembership[]instead of the previous interface type. This change provides better type safety with the conditional properties in the new type.web/core/components/project/member-select.tsx (4)
8-8: Updated to use the more specific project roles enumCorrectly replaced
EUserPermissionswithEUserProjectRoleswhich is more semantically appropriate for project member roles.
35-35: Updated role check to use project-specific enumProperly changed the guest role check to use
EUserProjectRoles.GUESTinstead ofEUserPermissions.GUEST, maintaining consistent behavior while using the more appropriate enum.
62-62: UI height adjustment for avatar containerReduced the height from
h-5toh-3.5for better visual alignment of the avatar and name in the selection component.
76-76: Enhanced button styling with background colorAdded
bg-custom-background-100class to provide consistent background styling for the selection button.web/core/lib/posthog-provider.tsx (1)
28-34: Well-structured permission access refactoringThe changes to retrieve workspace and project roles through dedicated methods (
getWorkspaceRoleByWorkspaceSlugandgetProjectRoleByWorkspaceSlugAndProjectId) fromuseUserPermissionshook is a good approach. This centralizes permission logic and improves encapsulation compared to directly accessing permission objects.web/core/components/issues/issue-detail/issue-activity/root.tsx (1)
52-59: Clean permission handling refactoringThe change from direct permission object access to using the
getProjectRoleByWorkspaceSlugAndProjectIdmethod improves code maintainability. The role comparison is now more straightforward by directly comparing with enum values rather than complex object property access.web/ce/components/projects/teamspaces/teamspace-list.tsx (1)
1-6: Placeholder component needs implementationThe component defines proper TypeScript types for props but currently only returns
null. This appears to be a placeholder for future implementation.Is this component intentionally returning
nullin the community edition, with actual implementation expected in enterprise edition? If not, it should be properly implemented or marked with a TODO comment explaining the future implementation plan.web/core/store/pages/project-page.store.ts (1)
116-123: Consistent permission access pattern appliedThe changes in the
canCurrentUserCreatePagegetter properly implement the new permission access pattern by using thegetProjectRoleByWorkspaceSlugAndProjectIdmethod. This maintains the same functionality while improving code consistency and maintainability.web/ce/helpers/project-settings.ts (1)
1-7: Clean implementation of the i18n helper functionThis new helper function follows good practices with comprehensive JSDoc comments. The function currently acts as a pass-through for the default label key, which seems intentional based on the underscore prefix for the unused parameter.
web/core/layouts/auth-layout/project-wrapper.tsx (3)
49-49: Implementation aligns with permission layer refactoringThe addition of
getProjectRoleByWorkspaceSlugAndProjectIdto the destructured import is consistent with the PR's objective to introduce computed methods for permission handling.
67-67: Good replacement of direct data access with computed methodReplacing direct access to
projectUserInfowith the new getter methodgetProjectRoleByWorkspaceSlugAndProjectIdimproves encapsulation and maintainability, aligning with the permission layer refactoring.
182-182: Proper prop passing to JoinProject componentUpdated to explicitly pass
projectIdas a prop to the JoinProject component, which makes the dependency clearer and aligns with the refactoring approach.web/core/components/project/member-list-item.tsx (3)
13-15: Updated import organization and pathThe import reorganization and updated path for
IProjectMemberDetailsreflects the store restructuring part of the permission layer refactoring.
19-20: Explicit props addition improves component contractAdding explicit
projectIdandworkspaceSlugprops improves the component's contract, making dependencies clear and supporting the permission layer refactoring.
35-38: Proper prop passing to useProjectColumns hookThe hook now receives explicit
projectIdandworkspaceSlugparameters, which is consistent with the refactoring approach to make data flow more explicit and dependencies clearer.web/app/[workspaceSlug]/(projects)/settings/(with-sidebar)/layout.tsx (2)
28-28: Implementation aligns with permission layer refactoringThe addition of
getWorkspaceRoleByWorkspaceSlugto the destructured imports fromuseUserPermissionsis consistent with the PR's objective to introduce computed methods for permission handling.
30-30: Good replacement of direct data access with computed methodReplacing direct access to
workspaceUserInfo[workspaceSlug]?.rolewith the new getter methodgetWorkspaceRoleByWorkspaceSlugimproves encapsulation and maintainability, aligning with the permission layer refactoring.web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx (4)
4-7: Well-organized imports with clear separation of concernsGood organization of imports with clear separation between Next.js, Plane imports, components, hooks, and plane-web imports. The addition of internationalization support is a nice improvement.
20-29: Clean parameter extraction and proper typingGood practice to extract router parameters at the top of the component and convert them to strings. This ensures type safety when passing these values to child components and makes the data flow more explicit.
45-49: Well-structured header with i18n supportGood addition of a styled header with proper internationalization. Using the helper function
getProjectSettingsPageLabelI18nKeyenhances maintainability and consistency across the project.
50-52: Improved component props patternExcellent refactoring to explicitly pass
projectIdandworkspaceSlugas props to child components rather than having them extract this information internally. This makes the component relationships clearer and improves reusability.web/core/store/member/index.ts (2)
3-8: Well-organized imports with clear separationGood organization of imports with clear separation between external libraries, Plane imports, Plane web imports, and local imports. This improves code readability and maintains consistent project structure.
29-29: Updated constructor parameter typeGood update to the constructor parameter type from
CoreRootStoretoRootStore. This change aligns with the broader store architecture refactoring and supports the new permission methods mentioned in the PR objectives.web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/sidebar.tsx (3)
27-27: Using the new permission access methodExcellent adoption of the new
getProjectRoleByWorkspaceSlugAndProjectIdmethod from the permission refactoring. This is a key part of the permission layer improvements mentioned in the PR objectives.
29-32: Improved role retrieval with explicit parametersGood implementation of the new permission access method with explicit parameters. This approach is more maintainable than direct access to
projectUserInfoand aligns with the permission layer refactoring goals.
68-68: Consistent i18n implementationGood use of the helper function
getProjectSettingsPageLabelI18nKeyfor internationalization. This ensures consistent label handling across the project settings pages.web/core/components/auth-screens/project/join-project.tsx (4)
13-16: Explicit props interface improves component reusabilityGood addition of explicit props for
projectIdandisPrivateProject. This makes the component more reusable and follows the pattern of explicit parameter passing established in the permission layer refactoring.
18-19: Clean component signature with props destructuringGood update to the component signature to accept and properly destructure the props. This makes the component's dependencies clearer and improves maintainability.
43-52: Improved user experience with conditional messagingGood enhancement to provide different messages based on whether the project is private. This improves the user experience by providing relevant information in each context.
54-65: Conditional UI rendering based on project privacyExcellent implementation of conditional rendering for the join button based on the project's privacy status. This provides appropriate user controls and messaging depending on the context.
web/ce/components/projects/settings/useProjectColumns.tsx (5)
10-11: Good update to the RowData interface.The interface now correctly extends
Pick<TProjectMembership, "original_role">, which aligns with the broader refactoring of project membership types. This change improves type safety by ensuring the component works with the new permission layer structure.
14-18: Proper props typing implementation.Defining an explicit props interface for the hook is a good practice. This makes the hook's contract clearer and more maintainable.
19-20: Good refactoring to accept explicit parameters.This change from using
useParams()to accepting explicit parameters improves reusability and testability of the hook.
25-34: Correctly implementing the new permission layer methods.The hook now properly uses the new permission methods
allowPermissionsandgetProjectRoleByWorkspaceSlugAndProjectIdwhich aligns with the permission layer refactoring goals. This ensures consistent permission handling across the system.
82-82: Clean return value.The return object is now more focused, only including what's necessary. This is a good cleanup that follows the principle of minimizing exposed API surface.
web/core/store/user/index.ts (2)
72-72: Type update for constructor parameter.Changing from
CoreRootStoretoRootStorealigns with the updated store typings used across the project.
269-269: Good implementation of the permission abstraction.This is a key improvement that replaces direct property access with the new encapsulated method
getProjectRolesByWorkspaceSlug. This change enhances maintainability by centralizing permission logic.web/core/components/ui/loader/settings/members.tsx (1)
4-14: UI improvement for members settings loader.The switch from flexbox to CSS grid with 5 columns creates a more consistent layout that better matches the actual data display. Reducing the number of placeholders from 4 to 3 and simplifying the layout improves the loading state appearance.
web/core/components/project/member-list.tsx (5)
16-20: Good props typing implementation.Creating an explicit props interface improves type safety and code readability.
21-22: Improved component parameters.Accepting explicit
projectIdandworkspaceSlugprops instead of extracting them from router parameters improves component reusability and testability.
35-38: Enhanced filtering logic.The update to exclude members lacking an
original_rolein addition to missingmemberdata reflects the improved type structure and prevents potential errors.
53-58: Consistent prop passing pattern.Passing
projectIdandworkspaceSlugas explicit props to child components maintains consistency throughout the component hierarchy.
89-94: Consistent prop passing to list items.Passing
projectIdandworkspaceSlugas explicit props toProjectMemberListItemcompletes the consistent parameter passing pattern throughout the component tree.web/ce/store/user/permission.store.ts (2)
8-22: Good implementation of the UserPermissionStore classThe implementation correctly extends BaseUserPermissionStore and adds the computed method
getProjectRoleByWorkspaceSlugAndProjectIdas mentioned in the PR objectives. This method serves as an access point to retrieve project role permissions by workspace slug and project ID.🧰 Tools
🪛 Biome (1.9.4)
[error] 9-11: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
19-22: Well-documented computed method for permission retrievalThe
getProjectRoleByWorkspaceSlugAndProjectIdmethod is properly implemented usingcomputedFnfor memoization and has clear JSDoc comments. This aligns with the PR objective of introducing computed methods for workspace and project access checks.packages/types/src/project/projects.d.ts (1)
85-97: Good type definition for project membershipThe new
TProjectMembershipdiscriminated union type improves type safety by clearly defining the structure of project membership data with mandatory fields and conditional type variations.This type definition aligns with the PR's goal of refactoring the permission layer for better type safety and consistency.
web/ce/store/member/project-member.store.ts (3)
12-43: Well-structured implementation of ProjectMemberStoreThe class properly extends BaseProjectMemberStore and implements all required methods with clear documentation and appropriate delegation to base class methods.
🧰 Tools
🪛 Biome (1.9.4)
[error] 13-15: This constructor is unnecessary.
Unsafe fix: Remove the unnecessary constructor.
(lint/complexity/noUselessConstructor)
23-25: Well-implemented computed method for role retrievalThe
getUserProjectRolemethod is properly implemented usingcomputedFnfor memoization and delegates to the base class method for retrieving the role from project membership.
42-42: Concise implementation of member removalThe
processMemberRemovalmethod elegantly delegates to the base class method for member removal, maintaining clean separation of concerns.web/core/components/project/project-settings-member-defaults.tsx (5)
24-38: Great component extraction for reusable UI patternThe new
DefaultSettingItemcomponent nicely encapsulates the repeated UI pattern for settings, improving code reusability and consistency.
40-46: Good prop interface design with explicit parametersThe component now accepts explicit
workspaceSlugandprojectIdprops rather than extracting them via hooks, which aligns with the PR's objectives of refactoring permission access patterns.
54-59: Improved permission checking with explicit parametersThe
allowPermissionscall now uses the explicit props for workspace and project identification, aligning with the permission layer refactoring.
63-66: Updated data fetching with explicit parametersThe
useSWRhook now correctly uses the passed props for the key and fetcher function, maintaining consistency with the rest of the refactoring.
130-187: Improved UI structure with consistent componentsThe UI structure now uses the
DefaultSettingItemcomponent consistently for all settings, resulting in cleaner and more maintainable code.web/core/services/project/project-member.service.ts (1)
12-18: Type refactor looks goodSwitching to
TProjectMembershipaligns this service with the new discriminated-union model – no issues spotted in this segment.
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
web/core/store/member/base-project-member.store.ts (1)
301-308: Rollback still writesoriginal_roleinto the permission mapThis is the same scalar-vs-object issue previously flagged – the rollback should
restore the current role, notoriginal_role, to
workspaceProjectsPermissions.- membershipBeforeUpdate?.original_role + membershipBeforeUpdate?.role
🧹 Nitpick comments (1)
web/core/store/user/base-permissions.store.ts (1)
254-258: Docstring return type is outdatedThe JSDoc still advertises
Promise<void | undefined>while the
implementation (and interface) now correctly returnsPromise<void>.
Update the comment for consistency.- * @returns { Promise<void | undefined> } + * @returns { Promise<void> }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
web/core/components/project/settings/member-columns.tsx(7 hunks)web/core/store/member/base-project-member.store.ts(10 hunks)web/core/store/user/base-permissions.store.ts(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/core/components/project/settings/member-columns.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
web/core/store/user/base-permissions.store.ts (4)
packages/types/src/workspace.d.ts (1)
IWorkspaceMemberMe(79-92)packages/types/src/project/projects.d.ts (1)
TProjectMembership(85-97)packages/types/src/users.d.ts (1)
IUserProjectsRole(166-168)packages/constants/src/workspace.ts (1)
WORKSPACE_SIDEBAR_DYNAMIC_NAVIGATION_ITEMS_LINKS(297-303)
|
Pull Request Linked with Plane Work Items
Comment Automatically Generated by Plane |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
packages/i18n/src/locales/cs/translations.json(1 hunks)packages/i18n/src/locales/de/translations.json(2 hunks)packages/i18n/src/locales/en/translations.json(1 hunks)packages/i18n/src/locales/es/translations.json(1 hunks)packages/i18n/src/locales/fr/translations.json(1 hunks)packages/i18n/src/locales/id/translations.json(1 hunks)packages/i18n/src/locales/it/translations.json(1 hunks)packages/i18n/src/locales/ja/translations.json(1 hunks)packages/i18n/src/locales/ko/translations.json(1 hunks)packages/i18n/src/locales/pl/translations.json(1 hunks)packages/i18n/src/locales/pt-BR/translations.json(1 hunks)packages/i18n/src/locales/ro/translations.json(1 hunks)packages/i18n/src/locales/ru/translations.json(1 hunks)packages/i18n/src/locales/sk/translations.json(1 hunks)packages/i18n/src/locales/tr-TR/translations.json(1 hunks)packages/i18n/src/locales/ua/translations.json(1 hunks)packages/i18n/src/locales/vi-VN/translations.json(1 hunks)packages/i18n/src/locales/zh-CN/translations.json(1 hunks)packages/i18n/src/locales/zh-TW/translations.json(1 hunks)web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx(2 hunks)web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/sidebar.tsx(2 hunks)
✅ Files skipped from review due to trivial changes (5)
- packages/i18n/src/locales/zh-CN/translations.json
- packages/i18n/src/locales/zh-TW/translations.json
- packages/i18n/src/locales/ja/translations.json
- packages/i18n/src/locales/ua/translations.json
- packages/i18n/src/locales/pt-BR/translations.json
🚧 Files skipped from review as they are similar to previous changes (14)
- packages/i18n/src/locales/en/translations.json
- packages/i18n/src/locales/pl/translations.json
- packages/i18n/src/locales/fr/translations.json
- packages/i18n/src/locales/cs/translations.json
- packages/i18n/src/locales/ro/translations.json
- packages/i18n/src/locales/sk/translations.json
- packages/i18n/src/locales/vi-VN/translations.json
- packages/i18n/src/locales/ko/translations.json
- packages/i18n/src/locales/ru/translations.json
- packages/i18n/src/locales/tr-TR/translations.json
- packages/i18n/src/locales/it/translations.json
- packages/i18n/src/locales/es/translations.json
- packages/i18n/src/locales/id/translations.json
- packages/i18n/src/locales/de/translations.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx (6)
packages/i18n/src/hooks/use-translation.ts (1)
useTranslation(23-35)web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)web/ce/helpers/project-settings.ts (1)
getProjectSettingsPageLabelI18nKey(7-7)web/core/components/project/project-settings-member-defaults.tsx (1)
ProjectSettingsMemberDefaults(45-190)web/ce/components/projects/teamspaces/teamspace-list.tsx (1)
ProjectTeamspaceList(6-6)web/core/components/project/member-list.tsx (1)
ProjectMemberList(21-102)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/sidebar.tsx (3)
27-27: LGTM: Proper destructuring of the new permission method.Good addition of the
getProjectRoleByWorkspaceSlugAndProjectIdmethod from the permissions hook, aligning with the broader permission layer refactor.
29-32: LGTM: Correctly implemented role retrieval refactor.The replacement of direct
projectUserInfoaccess with the encapsulatedgetProjectRoleByWorkspaceSlugAndProjectIdmethod improves type safety and follows the standardized permission handling pattern across the codebase.
68-68: LGTM: Standardized translation key generation.The use of
getProjectSettingsPageLabelI18nKeyhelper function centralizes label key generation and improves consistency across the project settings UI.web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx (4)
20-20: LGTM: Proper extraction of route parameters.Good use of Next.js
useParamshook with descriptive variable names to clearly indicate the source of the parameters.
27-28: LGTM: Safe parameter conversion to strings.Proper use of optional chaining with
toString()to safely convert route parameters to strings while handling potential undefined values.
45-49: LGTM: Enhanced header with internationalization.The addition of a styled header with the translated label improves the UI consistency and supports the internationalization improvements.
50-52:Details
✅ Verification successful
Verify that all components properly handle the new prop structure.
The explicit passing of
projectIdandworkspaceSlugas props follows the standardized pattern. However, ensure that all these components have been updated to accept these props correctly.
🏁 Script executed:
#!/bin/bash # Description: Verify that the components accept projectId and workspaceSlug props # Expected: All components should have proper TypeScript interfaces defining these props echo "Checking ProjectSettingsMemberDefaults props interface..." ast-grep --pattern 'interface $_ { $$$ projectId: $_ $$$ workspaceSlug: $_ $$$ }' echo "Checking ProjectTeamspaceList props interface..." ast-grep --pattern 'interface $_ { $$$ projectId: $_ $$$ workspaceSlug: $_ $$$ }' echo "Checking ProjectMemberList props interface..." ast-grep --pattern 'interface $_ { $$$ projectId: $_ $$$ workspaceSlug: $_ $$$ }'Length of output: 8690
🏁 Script executed:
#!/bin/bash # Locate component definitions and inspect their props in the relevant files echo "=== ProjectSettingsMemberDefaults ===" files=$(rg -l "ProjectSettingsMemberDefaults" --glob "*.tsx") echo "$files" for f in $files; do echo "----- $f (first 50 lines) -----" head -n 50 "$f" done echo "=== ProjectTeamspaceList ===" files=$(rg -l "ProjectTeamspaceList" --glob "*.tsx") echo "$files" for f in $files; do echo "----- $f (first 50 lines) -----" head -n 50 "$f" done echo "=== ProjectMemberList ===" files=$(rg -l "ProjectMemberList" --glob "*.tsx") echo "$files" for f in $files; do echo "----- $f (first 50 lines) -----" head -n 50 "$f" doneLength of output: 16548
All components correctly accept
projectIdandworkspaceSlugpropsVerified that each component defines the matching props interface:
- web/core/components/project/project-settings-member-defaults.tsx
–TProjectSettingsMemberDefaultsPropsincludesprojectId: stringandworkspaceSlug: string.- web/ce/components/projects/teamspaces/teamspace-list.tsx
–TProjectTeamspaceListincludesprojectId: stringandworkspaceSlug: string.- web/core/components/project/member-list.tsx
–TProjectMemberListPropsincludesprojectId: stringandworkspaceSlug: string.No further changes needed.
...spaceSlug]/(projects)/projects/(detail)/[projectId]/settings/(with-sidebar)/members/page.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
web/core/store/member/base-project-member.store.ts (3)
190-195: Use project-specific enum when filtering guest users.The code uses
EUserPermissions.GUEST(workspace-level) but should useEUserProjectRoles.GUESTfor project context filtering.- members = members.filter((m) => m.role !== EUserPermissions.GUEST); + members = members.filter((m) => m.role !== EUserProjectRoles.GUEST);
282-291: Critical: Corrupting original_role destroys audit history.Setting
original_roleto the newroleparameter (line 282) overwrites the immutable backend value needed for audit trails and rollbacks. This breaks the audit history mechanism.- set(this.projectMemberMap, [projectId, userId, "original_role"], role); - set(this.projectMemberMap, [projectId, userId, "role"], updatedProjectRole); + // Preserve immutable original_role – only mutate the live `role` + set(this.projectMemberMap, [projectId, userId, "role"], updatedProjectRole);Additionally, the permission update logic may have the scalar-object corruption issue mentioned in past reviews. The
workspaceProjectsPermissions[workspaceSlug][projectId]should be a scalar (TUserPermissions) but the code structure suggests it might be treated as an object.#!/bin/bash # Verify the type definition of workspaceProjectsPermissions to understand the data structure ast-grep --pattern 'workspaceProjectsPermissions: $_'
305-318: Critical: Rollback logic has the same audit history corruption.The rollback sets
original_roleback tomembershipBeforeUpdate?.original_role, but this only works if the original audit trail wasn't corrupted by the initial update. Since line 282 overwritesoriginal_role, the rollback may not restore the true original value.The same scalar-object corruption concern from the update logic applies here in the error handling path.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
apiserver/plane/app/serializers/project.py(1 hunks)packages/i18n/src/locales/en/translations.json(1 hunks)packages/types/src/project/projects.d.ts(2 hunks)packages/utils/src/index.ts(1 hunks)web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx(1 hunks)web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx(2 hunks)web/ce/constants/project/settings/tabs.ts(1 hunks)web/core/components/project/member-list-item.tsx(2 hunks)web/core/components/project/member-list.tsx(3 hunks)web/core/components/project/settings/member-columns.tsx(7 hunks)web/core/components/settings/project/sidebar/nav-item-children.tsx(2 hunks)web/core/store/member/base-project-member.store.ts(10 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/utils/src/index.ts
- web/ce/constants/project/settings/tabs.ts
- packages/i18n/src/locales/en/translations.json
- web/core/components/project/member-list-item.tsx
- apiserver/plane/app/serializers/project.py
- web/core/components/project/member-list.tsx
- packages/types/src/project/projects.d.ts
- web/core/components/project/settings/member-columns.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
web/core/components/settings/project/sidebar/nav-item-children.tsx (2)
packages/i18n/src/store/index.ts (1)
t(211-232)web/ce/helpers/project-settings.ts (1)
getProjectSettingsPageLabelI18nKey(7-7)
web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx (6)
packages/i18n/src/hooks/use-translation.ts (1)
useTranslation(23-35)web/core/hooks/store/user/user-permissions.ts (1)
useUserPermissions(7-12)web/ce/helpers/project-settings.ts (1)
getProjectSettingsPageLabelI18nKey(7-7)web/core/components/project/project-settings-member-defaults.tsx (1)
ProjectSettingsMemberDefaults(45-190)web/ce/components/projects/teamspaces/teamspace-list.tsx (1)
ProjectTeamspaceList(6-6)web/core/components/project/member-list.tsx (1)
ProjectMemberList(23-108)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Analyze (javascript)
🔇 Additional comments (14)
web/core/components/settings/project/sidebar/nav-item-children.tsx (2)
11-11: LGTM: Clean import addition for i18n helper.The import of
getProjectSettingsPageLabelI18nKeyhelper function is correctly structured and follows the established import pattern.
69-69: LGTM: Excellent abstraction for i18n key management.The refactoring to use
getProjectSettingsPageLabelI18nKey(link.key, link.i18n_label)instead of directlink.i18n_labelusage is well-executed. This change:
- Maintains functional equivalence (the helper currently returns
defaultLabelKeyunchanged)- Provides a clean abstraction layer for future customization
- Aligns with the broader i18n standardization effort mentioned in the PR objectives
- Enables potential EE-specific or conditional key resolution logic
The implementation correctly passes both the settings key and default label, setting up for extensible i18n key resolution.
web/app/(all)/[workspaceSlug]/(settings)/settings/(workspace)/layout.tsx (3)
24-24: LGTM! Good refactoring to use centralized permission methods.The addition of
getWorkspaceRoleByWorkspaceSlugaligns well with the PR objective of refactoring the permission layer to use computed methods instead of direct object access.
29-29: Improved encapsulation with the new getter method.Using
getWorkspaceRoleByWorkspaceSlug(workspaceSlug.toString())instead of direct property access provides better abstraction and consistency with the refactored permission layer.
31-34: Enhanced defensive programming with explicit authorization checks.The updated authorization logic is more robust:
- Explicit initialization of
isAuthorizedtofalse- Conditional checks ensuring all required values are truthy before proceeding
- Cleaner separation of concerns
web/core/store/member/base-project-member.store.ts (5)
4-4: LGTM! Good addition of unset utility.Adding
unsetfrom lodash is appropriate for the member removal functionality implemented in this refactor.
9-20: Excellent architectural refactoring with abstract base class.The introduction of
BaseProjectMemberStoreas an abstract class with defined interfaces provides better extensibility and separation of concerns. The updated imports and type definitions align well with the broader permission layer refactoring.
128-153: Well-designed computed functions for member access.The new protected computed functions (
getProjectMemberships,getProjectMembershipByUserId,getRoleFromProjectMembership) provide good encapsulation and reusability. The role precedence logic (original_role ?? role) is appropriate.
234-239: Preserve original roles when adding members.Good implementation that maintains the
original_roleas the backend value while allowing the currentroleto be updated based on computed project role logic.
329-344: Well-abstracted member removal with clear separation of concerns.The
handleMemberRemovaland abstractprocessMemberRemovalmethods provide good separation between common removal logic and implementation-specific cleanup. This pattern supports the extensible architecture introduced by the abstract base class.web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx (4)
4-4: LGTM! Import additions support the refactoring objectives.The new imports align well with the permission layer refactoring and internationalization goals:
useParamsenables explicit parameter extractionuseTranslationsupports i18n implementationProjectTeamspaceListextends functionality (though currently a placeholder)getProjectSettingsPageLabelI18nKeyprovides consistent label resolutionAlso applies to: 7-7, 16-17
21-23: Good implementation of hooks, consider parameter validation.The extraction of route parameters and translation setup is implemented correctly. The code properly uses Next.js
useParamsand the translation hook.Consider adding validation to ensure route parameters exist:
+ if (!routerWorkspaceSlug || !routerProjectId) { + return <div>Invalid route parameters</div>; + }However, this might be handled at a higher level in the routing system.
46-50: Excellent internationalization implementation.The replacement of the hardcoded "Members" title with a translated version is well-implemented:
- Uses proper fallback mechanism with
"common.members"- Leverages the helper function for consistent label resolution
- Follows i18n best practices
This change aligns perfectly with the broader internationalization effort across the platform.
51-53: Great improvement in component prop management.Passing
workspaceSlugandprojectIdas explicit props is an excellent refactoring that:
- Improves component reusability and testability
- Makes data flow more explicit and clear
- Aligns with the broader permission layer refactoring objectives
The addition of
ProjectTeamspaceListextends functionality appropriately, even though it's currently a placeholder.Ensure child components handle potentially undefined props gracefully, or implement the parameter validation suggested earlier to prevent undefined values from being passed down.
web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx
Show resolved
Hide resolved
* refactor: permission layer * refactor: add original_role to project member serializer * chore: minor fixes related to permission layer * fix: strict type checking while checking user permissions
Description
getWorkspaceRoleByWorkspaceSluggetProjectRolesByWorkspaceSluggetProjectRoleByWorkspaceSlugAndProjectIdAlso updated
allowPermissionsto rely on these methods internally for consistent permission handling.Type of Change
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores
Documentation