Skip to content

Conversation

@aleksandernsilva
Copy link
Contributor

@aleksandernsilva aleksandernsilva commented Nov 28, 2025

Proposed changes (including videos or screenshots)

This pull request adds a visual badge for invited users in the room members contextual. The changes also add a new story and snapshot test for rooms with invited members.

Screenshot 2025-12-01 at 10 22 51

Issue(s)

FB-63

Steps to test or reproduce

ℹ️ Currently invitation requests are only available for federated rooms.
ℹ️ You'll need two workspaces with federation enabled (I'll refer to them as ws-a and ws-b)

  • Create a room federated room (ws-a)
  • Invite an user from ws-b to the room (ws-a)
  • Send a message
  • Access members list in the room toolbox
  • Invited status should be displayed besides the inviter user

Further comments

Summary by CodeRabbit

Release Notes

  • New Features

    • Added visual invitation badge to identify invited room members with invitation date information
    • Enhanced room member list display with improved status handling for invited members
  • Localization

    • Added "Message request" translation key
  • Tests

    • Added comprehensive test coverage for invitation badge component, including snapshot rendering and accessibility validation

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

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Nov 28, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Nov 28, 2025

⚠️ No Changeset found

Latest commit: fd8054d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 28, 2025

Walkthrough

Introduces an InvitationBadge component that displays a mail icon with invitation date formatting. Updates room member-related components and types to support propagating and displaying the invited status, includes Storybook stories and tests for the new component, and adds a translation key for the feature.

Changes

Cohort / File(s) Summary
InvitationBadge Component
apps/meteor/client/components/InvitationBadge/InvitationBadge.tsx, apps/meteor/client/components/InvitationBadge/InvitationBadge.stories.tsx, apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx, apps/meteor/client/components/InvitationBadge/index.ts
New React component that renders a mail icon with optional invitation date. Accepts invitationDate prop, formats it with useTimeAgo hook, and displays in title/aria-label. Includes Storybook stories with default export and test suite with snapshot and accessibility tests via jest-axe.
RoomMemberUser Type Refactoring
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx, apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx, apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
Extracts RoomMemberUser type from RoomMembers.tsx to a shared types module. Updates RoomMembersItemProps to use RoomMemberUser type and adds conditional rendering of InvitationBadge when status === 'INVITED'. RoomMembersRow updated to pass status prop through to RoomMembersItem.
Hook Type Update
apps/meteor/client/views/hooks/useMembersList.ts
Expands RoomMember type with Serialized wrapper, adds federated, freeSwitchExtension, and optional subscription properties. Updates roles type from IRole['_id'][] to IUser['roles'].
RoomMembers Stories
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
Adds new WithInvitedMember story with a members array containing a member with status: 'INVITED' to demonstrate invited member display.
Internationalization
packages/i18n/src/locales/en.i18n.json
Adds new translation entry "Message_request": "Message request".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Type consistency validation: RoomMemberUser type refactoring spans multiple files (RoomMembers.tsx, RoomMembersItem.tsx, RoomMembersRow.tsx) — verify all components use the consistent type and that the extraction doesn't introduce type mismatches.
  • InvitationBadge integration: Verify the conditional rendering logic (status === 'INVITED') correctly identifies invited members and the badge renders in the correct UI location within RoomMembersItem.
  • RoomMember type expansion: Ensure the expanded RoomMember type in useMembersList.ts (with Serialized wrapper, new fields, and subscription property) is compatible with all consuming code and backend contract.
  • Story consistency: The WithInvitedMember story uses a string literal 'INVITED' for status rather than an enum — confirm this matches the actual runtime type and doesn't diverge from other stories' patterns.

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ggazzo
  • dougfabris
  • tassoevan

Poem

🐰 A badge for the invited, so shiny and bright,
With mail-icon charm and dates formatted right,
Through RoomMembers it flows with refactored grace,
Each member now shows their invitation's sweet face! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a visual invitation badge to the room members list, which is the core feature introduced in this PR.
Linked Issues check ✅ Passed The PR implements the invitation badge feature for invited members in the room members list FB-63, including UI components, type refactoring, stories, and tests.
Out of Scope Changes check ✅ Passed All changes are within scope: invitation badge component, type refactoring to support the feature, related story/test files, and necessary translation keys.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/members-list-invite-badge

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.

@aleksandernsilva
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)

1-6: Shared RoomMemberUser type looks correct; consider reusing IUser['roles'] to avoid duplication

The alias cleanly centralizes the member shape and the status?: UserStatus | SubscriptionStatus union fits the invited-member use case.

You can make the roles typing more robust (and drop the IRole import) by reusing the existing IUser.roles definition instead of duplicating IRole['_id'][]:

-import type { IUser, IRole, SubscriptionStatus, UserStatus } from '@rocket.chat/core-typings';
-
-export type RoomMemberUser = Pick<IUser, 'username' | '_id' | 'name' | 'freeSwitchExtension' | 'federated'> & {
-	roles?: IRole['_id'][];
-	status?: UserStatus | SubscriptionStatus;
-};
+import type { IUser, SubscriptionStatus, UserStatus } from '@rocket.chat/core-typings';
+
+export type RoomMemberUser = Pick<IUser, 'username' | '_id' | 'name' | 'freeSwitchExtension' | 'federated'> &
+	Partial<Pick<IUser, 'roles'>> & {
+		status?: UserStatus | SubscriptionStatus;
+	};
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

96-96: Clarify isABACRoom configuration.

Setting isABACRoom: true in the invited member story appears unrelated to the invitation feature. This should likely be false to isolate the invitation badge functionality, unless ABAC rooms have specific invitation behavior.

Consider applying this diff if ABAC is not relevant to the invitation scenario:

 	reload: action('reload'),
-	isABACRoom: true,
+	isABACRoom: false,
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 54a4be7 and cd472aa.

⛔ Files ignored due to path filters (1)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/__snapshots__/RoomMembers.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (7)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (3 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (2 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx (1 hunks)
  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1 hunks)
  • packages/i18n/src/locales/en.i18n.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
🧠 Learnings (7)
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx
📚 Learning: 2025-11-17T15:07:13.273Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37398
File: packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx:357-363
Timestamp: 2025-11-17T15:07:13.273Z
Learning: In packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx, IconElement is a presentational, non-actionable element that does not require wrapping in AppIdProvider, similar to plain_text and mrkdwn renderers. Only actionable elements (those with actions, actionId, or interactive behavior) should be wrapped in AppIdProvider.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/badges/InvitationBadge.tsx
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • packages/i18n/src/locales/en.i18n.json
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx
  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
🧬 Code graph analysis (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (2)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)
  • RoomMemberUser (3-6)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (1)
apps/meteor/client/views/room/contextualBar/RoomMembers/types.ts (1)
  • RoomMemberUser (3-6)
🔇 Additional comments (4)
apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersRow.tsx (1)

1-41: LGTM! Type refactoring is clean.

The migration from local type definition to centralized RoomMemberUser type improves maintainability, and the new status prop is correctly wired to RoomMembersItem.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx (1)

1-12: LGTM! Type centralization is consistent.

Moving the RoomMemberUser type to a dedicated types module improves code organization and reusability.

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembersItem.tsx (1)

19-20: LGTM! Invitation badge integration is well-structured.

The component correctly:

  • Uses the centralized RoomMemberUser type
  • Conditionally renders InvitationBadge for invited members
  • Wraps the badge in OptionColumn for proper layout

The string literal comparison status === 'INVITED' should be verified to match the enum definition (see verification comment in the stories file).

Also applies to: 25-30, 37-37, 63-67

apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.stories.tsx (1)

82-82: Remove this comment—'INVITED' is a valid SubscriptionStatus value.

SubscriptionStatus is defined as type SubscriptionStatus = 'INVITED' in packages/core-typings/src/ISubscription.ts. The status value in the story correctly uses this type.

@ggazzo ggazzo force-pushed the feat/invites branch 2 times, most recently from b2cc5c0 to 0d14b19 Compare December 3, 2025 18:49
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from cd472aa to 8316778 Compare December 3, 2025 19:42
@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

📦 Docker Image Size Report

📈 Changes

Service Current Baseline Change Percent
sum of all images 1.2GiB 1.2GiB +12MiB
rocketchat 360MiB 349MiB +12MiB
omnichannel-transcript-service 132MiB 132MiB +697B
queue-worker-service 132MiB 132MiB +2.0KiB
ddp-streamer-service 126MiB 126MiB +362B
account-service 113MiB 113MiB +301B
stream-hub-service 111MiB 111MiB -470B
presence-service 111MiB 111MiB -206B
authorization-service 111MiB 111MiB -680B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/15 22:28", "11/16 01:28", "11/17 23:50", "11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/10 23:28 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
  line "queue-worker-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13]
  line "rocketchat" [0.36, 0.36, 0.35, 0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.35]
  line "stream-hub-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
Loading

Statistics (last 17 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.2GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 1.2GiB
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-37643
  • Baseline: develop
  • Timestamp: 2025-12-10 23:28:12 UTC
  • Historical data points: 17

Updated: Wed, 10 Dec 2025 23:28:12 GMT

@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

❌ Patch coverage is 50.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.70%. Comparing base (ddf6717) to head (fd8054d).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37643      +/-   ##
===========================================
- Coverage    67.70%   67.70%   -0.01%     
===========================================
  Files         3452     3453       +1     
  Lines       113975   113979       +4     
  Branches     20940    20943       +3     
===========================================
- Hits         77168    77165       -3     
- Misses       34678    34686       +8     
+ Partials      2129     2128       -1     
Flag Coverage Δ
e2e 57.25% <50.00%> (-0.02%) ⬇️
e2e-api 42.33% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch 3 times, most recently from bc5722b to 9c7345e Compare December 8, 2025 00:59
@sampaiodiego sampaiodiego force-pushed the feat/invites branch 2 times, most recently from c420eb2 to 36e006f Compare December 8, 2025 14:17
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from 9c7345e to b243f28 Compare December 8, 2025 17:53
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from b243f28 to 2fe6480 Compare December 8, 2025 23:11
Base automatically changed from feat/invites to develop December 10, 2025 01:45
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from 2fe6480 to ffa1368 Compare December 10, 2025 19:45
@aleksandernsilva aleksandernsilva changed the title feat: Added invitation badge to room members list feat(federation): Added invitation badge to room members list Dec 10, 2025
@aleksandernsilva aleksandernsilva changed the title feat(federation): Added invitation badge to room members list feat: Added invitation badge to room members list Dec 10, 2025
@aleksandernsilva aleksandernsilva force-pushed the feat/members-list-invite-badge branch from ffa1368 to fd8054d Compare December 10, 2025 23:11
@aleksandernsilva aleksandernsilva marked this pull request as ready for review December 11, 2025 00:01
@aleksandernsilva aleksandernsilva requested a review from a team as a code owner December 11, 2025 00:01
@aleksandernsilva aleksandernsilva added this to the 7.14.0 milestone Dec 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/meteor/client/components/InvitationBadge/InvitationBadge.tsx (2)

11-14: Consider handling undefined invitationDate.

When invitationDate is undefined, formattedDate becomes an empty string, resulting in a translated label like "Invited " with no actual date. Consider whether the component should render at all when invitationDate is not provided, or if the translation should handle this case differently.

If the component shouldn't render without a date, apply this diff:

 const InvitationBadge = ({ invitationDate, ...props }: InvitationBadgeProps) => {
 	const { t } = useTranslation();
 	const timeAgo = useTimeAgo();
+	
+	if (!invitationDate) {
+		return null;
+	}
+	
-	const formattedDate = invitationDate ? timeAgo(invitationDate) : '';
+	const formattedDate = timeAgo(invitationDate);

16-27: Remove redundant aria-hidden and optimize translation call.

Two minor optimizations:

  1. aria-hidden='false' is redundant as it's the default value for Icon components.
  2. The translation t('Invited__date__', { date: formattedDate }) is called twice for both title and aria-label.

Apply this diff:

 const InvitationBadge = ({ invitationDate, ...props }: InvitationBadgeProps) => {
 	const { t } = useTranslation();
 	const timeAgo = useTimeAgo();
 	const formattedDate = invitationDate ? timeAgo(invitationDate) : '';
+	const label = t('Invited__date__', { date: formattedDate });

 	return (
 		<Icon
 			size='x20'
 			{...props}
 			role='status'
 			color='info'
 			name='mail'
-			aria-hidden='false'
-			title={t('Invited__date__', { date: formattedDate })}
-			aria-label={t('Invited__date__', { date: formattedDate })}
+			title={label}
+			aria-label={label}
 		/>
 	);
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cd472aa and fd8054d.

⛔ Files ignored due to path filters (1)
  • apps/meteor/client/components/InvitationBadge/__snapshots__/InvitationBadge.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx (1 hunks)
  • apps/meteor/client/components/InvitationBadge/InvitationBadge.stories.tsx (1 hunks)
  • apps/meteor/client/components/InvitationBadge/InvitationBadge.tsx (1 hunks)
  • apps/meteor/client/components/InvitationBadge/index.ts (1 hunks)
  • apps/meteor/client/views/hooks/useMembersList.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/meteor/client/components/InvitationBadge/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.tsx
  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
  • apps/meteor/client/components/InvitationBadge/InvitationBadge.stories.tsx
  • apps/meteor/client/views/hooks/useMembersList.ts
🧠 Learnings (15)
📚 Learning: 2025-11-17T15:07:13.273Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37398
File: packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx:357-363
Timestamp: 2025-11-17T15:07:13.273Z
Learning: In packages/fuselage-ui-kit/src/surfaces/FuselageSurfaceRenderer.tsx, IconElement is a presentational, non-actionable element that does not require wrapping in AppIdProvider, similar to plain_text and mrkdwn renderers. Only actionable elements (those with actions, actionId, or interactive behavior) should be wrapped in AppIdProvider.

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-12-10T21:00:43.645Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:43.645Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/client/views/hooks/useMembersList.ts
🧬 Code graph analysis (1)
apps/meteor/client/components/InvitationBadge/InvitationBadge.stories.tsx (1)
packages/mock-providers/src/index.ts (1)
  • mockAppRoot (3-3)
🔇 Additional comments (4)
apps/meteor/client/views/hooks/useMembersList.ts (2)

1-1: LGTM!

The additional imports ISubscription and Serialized are correctly added to support the expanded RoomMember type definition.


23-28: Fix RoomMember type to match actual API response shapes.

The RoomMember type is incompatible with the /v1/im.members endpoint response. The DM members endpoint returns only _id | status | name | username | utcOffset, but RoomMember requires federated and freeSwitchExtension. Since useMembersList uses the same RoomMember type for both endpoints (DM and room), either:

  1. Define separate types for each endpoint response, or
  2. Make federated and freeSwitchExtension optional in RoomMember to match the actual DM response shape, or
  3. Ensure the backend returns these fields for all endpoints

Current state creates a type mismatch at runtime when fetching DM members.

⛔ Skipped due to learnings
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
apps/meteor/client/components/InvitationBadge/InvitationBadge.stories.tsx (1)

1-26: LGTM!

The Storybook story is well-structured with appropriate mocking of translations and a centered layout. The mockAppRoot decorator correctly provides the Invited__date__ translation key needed by the component.

apps/meteor/client/components/InvitationBadge/InvitationBadge.spec.tsx (1)

1-18: LGTM!

The test file follows best practices by:

  • Using composeStories to test all story variants
  • Including both snapshot tests and accessibility tests with jest-axe
  • Leveraging test.each for concise, maintainable test structure

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.

2 participants