-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(web): members setting #1186
Conversation
This reverts commit e3f84da.
…o feat/members_setting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (5)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (5)
28-59
: Consider improving type definitions with JSDoc comments and specific error types.Add JSDoc comments to document the Props interface and use a more specific error type instead of
unknown
.+/** + * Props for the Members component + */ type Props = { + /** Adds a new member to the workspace */ handleAddMemberToWorkspace: ({ teamId, userId, role }: WorkspacePayload) => Promise<void>; + /** Searches for a user by name or email */ handleSearchUser: (nameOrEmail: string) => | { searchUser: { __typename?: "User"; id: string; name: string; email: string; } | null; searchUserStatus: string; error?: undefined; } | { - error: unknown; + error: Error; searchUser?: undefined; searchUserStatus?: undefined; }; // ... rest of the props };
125-142
: Add cleanup for search results state.Consider adding a cleanup function to reset the search results when the component unmounts or when the search input is cleared.
useEffect(() => { if ( searchUser && "name" in searchUser && !memberSearchResults.find( (memberSearchResult) => memberSearchResult.id === searchUser.id ) ) { setMemberSearchResults([ ...memberSearchResults, { userName: searchUser.name, email: searchUser.email, id: searchUser.id } ]); } + return () => { + setMemberSearchResults([]); + }; }, [memberSearchResults, searchUser]);
160-165
: Add ARIA labels for better accessibility.The table headers should have proper ARIA labels for better screen reader support.
-<Table> +<Table role="table" aria-label={t("Workspace members")}> - <TableHeader>{t("User Name")}</TableHeader> + <TableHeader role="columnheader">{t("User Name")}</TableHeader> - <TableHeader>{t("Email")}</TableHeader> + <TableHeader role="columnheader">{t("Email")}</TableHeader> - <TableHeader>{t("Role")}</TableHeader> + <TableHeader role="columnheader">{t("Role")}</TableHeader> - <TableHeader /> + <TableHeader role="columnheader" aria-label={t("Actions")} />
314-326
: Add loading state feedback for search input.The search input should provide visual feedback when the search is in progress.
<TextInput placeholder="name@reearth.io" value={memberSearchInput} + loading={searchUserStatus === "loading"} onChange={(input) => { setMemberSearchInput(input); }} onKeyDown={(e) => { if (e.key === "Enter" && memberSearchInput.trim() !== "") { setMemberSearchInput(""); setDebouncedInput(memberSearchInput.trim()); } }} />
436-442
: Use theme variables for DeleteIcon colors and add hover transition.Replace hardcoded colors with theme variables and add a smooth transition for the hover effect.
-const DeleteIcon = styled(IconButton)(() => ({ +const DeleteIcon = styled(IconButton)(({ theme }) => ({ cursor: "pointer", - color: "#fff", + color: theme.content.main, + transition: "color 0.2s ease-in-out", "&:hover": { - color: "red" + color: theme.danger.main } }));
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
- web/src/services/state/index.ts (2 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 339-364: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (2)
web/src/services/state/index.ts (2)
4-4
: LGTM: Clean type import additionThe TeamMember type import is well-placed and properly supports the type enhancement in the Workspace interface.
54-54
: Type enhancement improves safety, verify usageThe change from
any[]
toTeamMember[]
improves type safety and reduces potential runtime errors. However, as this is a breaking change, we should verify all usages of workspace.members have been updated accordingly.Let's verify all usages of workspace.members:
✅ Verification successful
Let me try a different approach to search for usages of the members property.
This should help us find:
- All occurrences of "members" in TypeScript files with context
- The Workspace interface definition to understand the full context
- By analyzing the context of these results, we can determine if there are any compatibility issues with the type change
Let me try one more time with a different search strategy.
This should help us:
- Confirm we can find TypeScript files
- Find occurrences of "members" with context
- Find usage of the Workspace type to understand the impact
Based on the search results, I can see that the
members
property is extensively used throughout the codebase in the context of workspaces/teams. The type change fromany[]
toTeamMember[]
is properly handled as:
- The GraphQL schema already defines members with proper typing (TeamMember type with user, userId, and role fields)
- All usages of workspace.members in components like Members, WorkspaceSettings, etc. expect and handle the TeamMember type
- The mutations (AddMemberToWorkspace, RemoveMemberFromWorkspace, etc.) all work with the properly typed TeamMember structure
- The state management and hooks are consistently using the TeamMember type
Type enhancement is safe and properly integrated
The change from
any[]
toTeamMember[]
aligns with the existing codebase implementation and improves type safety without breaking existing functionality, as all consumers are already working with the TeamMember structure.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Find all usages of workspace.members to ensure compatibility with the new type # Search for direct member access patterns echo "Checking direct workspace.members access:" rg -l "workspace\.members" --type ts --type tsx # Search for destructured member access patterns echo -e "\nChecking destructured members access:" rg -l "const.*\{.*members.*\}.*=.*workspace" --type ts --type tsxLength of output: 357
Script:
#!/bin/bash # Search for any mentions of members in TypeScript files echo "Searching for workspace members usage:" rg "members" --type typescript -C 2 # Search for Workspace interface usage echo -e "\nSearching for Workspace interface usage:" ast-grep --pattern 'interface Workspace { $$$ }'Length of output: 307
Script:
#!/bin/bash # Search for files with .ts extension first echo "TypeScript files in the repository:" fd ".*\.ts$" # Then search for members usage in those files echo -e "\nSearching for members usage:" rg "members" -t ts -C 2 # Look for Workspace type usage echo -e "\nSearching for Workspace type usage:" rg "Workspace" -t ts -C 2Length of output: 258609
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 340-365: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (5)
web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (1)
Type compatibility verified with potential issue found
The type verification reveals a potential issue with the email field access. In the User type definition,
email?: string
), which matches with the component's safe optional chaining usage (member.user?.email
). However, there's a risk of displaying empty content when email is undefined.
- Consider adding a fallback value or conditional rendering when
member.user?.email
is undefined- All other accessed properties are correctly defined:
role
is a required field in TeamMemberuser
is optional in TeamMember (correctly accessed with?.
)name
is a required string in User type🔗 Analysis chain
Line range hint
6-31
: Verify type compatibility with TeamMember interfaceThe component implementation looks good, but let's verify that all accessed properties are defined in the TeamMember interface.
Let me verify the User type definition to ensure it has the required fields (name and email) that are being accessed in the component.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the TeamMember interface contains all required fields # Expected fields: user.name, user.email, role # Search for TeamMember type definition ast-grep --pattern 'type TeamMember = { $$$ }' # Alternative: Search for TeamMember interface definition ast-grep --pattern 'interface TeamMember { $$$ }'Length of output: 504
Script:
#!/bin/bash # Search for User type definition to verify name and email fields ast-grep --pattern 'type User = { $$$ }' # Also search for Role type/enum since it's used in TeamMember ast-grep --pattern 'enum Role { $$$ }'Length of output: 754
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (4)
28-59
: Improve type safety and readability of Props interfaceConsider these improvements to the Props interface:
- Type the
role
parameter explicitly asRole
enum- Consider inlining the
WorkspacePayload
type for better readabilitytype Props = { handleAddMemberToWorkspace: ({ teamId, userId, - role + role: Role, + name?: string }: WorkspacePayload) => Promise<void>; // ... other handlers };
61-66
: Improve MembersData type definitionThe type could be more specific and clearer:
-type MembersData = { +interface Member { + id: string; + role: Role; + username: string; // Make required + email: string; // Make required +} + +type MembersData = Member[]; -}[];
161-166
: Improve table accessibilityThe table structure needs proper ARIA roles and labels for better accessibility.
-<Table> +<Table role="table" aria-label={t("Workspace members")}> - <TableHeader>{t("User Name")}</TableHeader> + <TableHeader role="columnheader">{t("User Name")}</TableHeader> - <TableHeader>{t("Email")}</TableHeader> + <TableHeader role="columnheader">{t("Email")}</TableHeader> - <TableHeader>{t("Role")}</TableHeader> + <TableHeader role="columnheader">{t("Role")}</TableHeader> - <TableHeader /> + <TableHeader role="columnheader" aria-label={t("Actions")} />
373-380
: Add reduced motion support for animationsConsider users who prefer reduced motion for accessibility reasons.
+const reducedMotion = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + const zoomIn = keyframes` from { opacity: 0; + transform: scale(0.95); } to { opacity: 1; + transform: scale(1); } `; + +const getAnimation = () => css` + @media (prefers-reduced-motion: no-preference) { + animation: ${zoomIn} 0.2s ease-in-out; + } + @media (prefers-reduced-motion: reduce) { + animation: ${reducedMotion} 0.2s ease-in-out; + } +`;Then update the components using the animation:
const TableRow = styled("div")(({ theme }) => ({ // ...other styles - animation: `${zoomIn} 0.2s ease-in-out` + ...getAnimation() })); const UserInfo = styled.div` // ...other styles - animation: ${zoomIn} 0.2s ease-in-out; + ${getAnimation()}; `;
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (1 hunks)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 340-365: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (2)
web/src/beta/features/Dashboard/ContentsContainer/Members/ListItem.tsx (2)
2-2
: LGTM: Proper typing from GraphQL schemaThe import of
TeamMember
from the GraphQL services ensures type safety and consistency with the backend schema.
Line range hint
33-62
: LGTM: Well-structured styled componentsThe styled components are well-organized and follow good practices:
- Proper use of theme variables
- Semantic naming
- Responsive grid layout
- Appropriate handling of text overflow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (1)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1)
70-74
: Follow TypeScript naming conventionsThe type name
memberSearchResult
should follow PascalCase convention for consistency with other type definitions.-type memberSearchResult = { +type MemberSearchResult = { userName: string; email: string; id: string; };
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- web/src/beta/features/WorkspaceSetting/hooks.ts (7 hunks)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 368-387: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (4)
web/src/beta/features/WorkspaceSetting/hooks.ts (4)
1-1
: LGTM! Type definitions align with the new functionality.The optional name field in WorkspacePayload and the new imports support the member management features appropriately.
Also applies to: 6-6
27-28
: LGTM! Hook initialization is correct.The addition of useUpdateMemberOfWorkspace is consistent with the new member management functionality.
96-104
: LGTM! Member update function follows established patterns.The implementation is consistent with other member management functions.
125-127
: LGTM! Return object properly exports all functions.The new functions are correctly added to the return object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 368-387: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (2)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (2)
23-24
: Simplify imports by importing 'Fragment' from 'react'To maintain consistency with other React imports, consider importing
Fragment
directly from"react"
instead of"react/jsx-runtime"
.Apply this diff:
import { FC, KeyboardEvent, useEffect, useState } from "react"; -import { Fragment } from "react/jsx-runtime"; +import { Fragment } from "react";
70-74
: Ensure consistent naming for 'username' propertyThe property is named
username
inMemberData
anduserName
inMemberSearchResult
. For consistency and better readability, consider usingusername
in both types.Apply this diff to
MemberSearchResult
:type MemberSearchResult = { - userName: string; + username: string; email: string; id: string; };And update all references of
userName
tousername
in the code.Also applies to: 62-65
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
- web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx
[error] 368-387: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (5)
web/src/beta/features/WorkspaceSetting/innerPages/Members/Members.tsx (5)
129-146
: Optimize search results update logicIncluding
memberSearchResults
in the dependency array while updating it can cause unnecessary re-renders. Consider removing it to optimize performance.
199-223
: Handle errors when adding members to the workspaceTo maintain UI consistency and handle potential failures, consider adding error handling to the
handleAddMember
function.
156-182
: Add error handling when updating member rolesIncluding error handling in
handleChangeRole
ensures that any issues during the role update are properly managed and the user is informed.
185-197
: Implement error handling when removing membersTo prevent inconsistencies and inform the user of any issues, add error handling to
handleRemoveMemberButtonClick
.
266-267
:⚠️ Potential issueUse unique keys when rendering list items
Using array indices as keys can lead to unexpected behavior. It's better to use a unique identifier like
user.id
for thekey
prop to ensure consistency during re-renders.Apply this diff:
-{workspaceMembers?.map((user, index) => ( - <Fragment key={index}> +{workspaceMembers?.map((user) => ( + <Fragment key={user.id}>Likely invalid or redundant comment.
Overview
What I've done
Add member's page for workspace.
What I haven't done
How I tested
Which point I want you to review particularly
Memo
Summary by CodeRabbit
Release Notes
New Features
Members
component for managing workspace members.Bug Fixes
Documentation
Chores