-
Notifications
You must be signed in to change notification settings - Fork 13k
chore: useHasLicenseModule return as a query result
#37552
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
Conversation
|
Looks like this PR is ready to merge! 🎉 |
|
WalkthroughThe hook useHasLicenseModule was changed to return the full query result (including .data and isPending) from useLicenseBase; ~60 consumer files were updated to destructure Changes
Sequence Diagram(s)sequenceDiagram
participant Consumer as Component / Hook Consumer
participant useHas as useHasLicenseModule
participant base as useLicenseBase
rect rgba(220,240,255,0.6)
Note over Consumer,useHas: BEFORE
Consumer->>useHas: const flag = useHasLicenseModule('mod')
useHas->>base: useLicenseBase({ select })
base-->>useHas: { data: boolean | undefined } or 'loading'
useHas-->>Consumer: boolean | 'loading' (simplified)
end
rect rgba(240,220,255,0.6)
Note over Consumer,useHas: AFTER
Consumer->>useHas: const { data: flag = false, isPending } = useHasLicenseModule('mod')
useHas->>base: useLicenseBase({ select, enabled })
base-->>useHas: { data, isPending, error, ... }
useHas-->>Consumer: { data, isPending, error, ... }
Consumer->>Consumer: use flag (from data) and isPending for loading UI
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #37552 +/- ##
===========================================
- Coverage 68.94% 68.87% -0.08%
===========================================
Files 3360 3361 +1
Lines 114282 114294 +12
Branches 20562 20622 +60
===========================================
- Hits 78790 78715 -75
- Misses 33406 33482 +76
- Partials 2086 2097 +11
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx (1)
42-48: Add loading state check to prevent flashing NotAuthorizedPage during query.The authorization check at line 46 evaluates
!hasDeviceManagementbefore the query completes. SincehasDeviceManagementdefaults tofalse, users will seeNotAuthorizedPageflash during the pending state, creating a poor UX.Apply this diff to show a loading state while the license query is pending:
if (isModalOpen) { return <PageSkeleton />; } + if (isPending) { + return <PageSkeleton />; + } + if (!canViewDeviceManagement || !hasDeviceManagement) { return <NotAuthorizedPage />; }apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx (1)
23-30: Guard against showing the upsell modal during license check loading.Currently, when the license query is loading and
context === 'new', the conditioncontext !== 'new' || hasCustomRolesModuleevaluates tofalse || false, which does not trigger the early return. This causes the upsell modal to display prematurely—before confirming the user actually lacks the license module.Apply this diff to wait for the query to resolve:
useEffect(() => { - if (context !== 'new' || hasCustomRolesModule) { + if (isLicenseCheckPending || context !== 'new' || hasCustomRolesModule) { return; } setModal(<CustomRoleUpsellModal onClose={() => setModal(null)} />); handleCloseContextualbar(); - }, [context, hasCustomRolesModule, handleCloseContextualbar, setModal]); + }, [context, hasCustomRolesModule, isLicenseCheckPending, handleCloseContextualbar, setModal]);apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx (1)
16-20: Handle loading state to prevent showing NotAuthorizedPage prematurely.The
isEnterprisecheck defaults tofalsewhile the license query is pending, causing the component to renderNotAuthorizedPageduring the initial load. This creates a poor user experience where authorized users briefly see an unauthorized screen before the actual content appears.Apply this diff to handle the loading state properly:
- const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); + const { data: isEnterprise = false, isPending } = useHasLicenseModule('livechat-enterprise'); - if (!hasPermission || !isEnterprise) { + if (isPending) { + return <PageSkeleton />; + } + + if (!hasPermission || !isEnterprise) { return <NotAuthorizedPage />; }Note: You may need to import
PageSkeletonor use an appropriate loading component.
🧹 Nitpick comments (14)
apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx (1)
7-7: LGTM! Correctly implements the new query-style hook pattern.The destructuring pattern correctly extracts the
dataproperty from the refactoreduseHasLicenseModulehook and provides a sensible default offalse. This ensures the component is safely hidden during loading and error states, which is appropriate for a license-gated component.If you want to provide visual feedback during the license check, you could optionally destructure
isPendingand render a loading indicator:- const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false, isPending } = useHasLicenseModule('livechat-enterprise'); - if (!hasLicense) { + if (isPending) { + return <Skeleton />; + } + + if (!hasLicense) { return null; }However, the current behavior of hiding during loading is acceptable for this use case.
apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx (1)
13-13: Consider handling loading state explicitly for better UX.During the initial query (while
isPendingistrue),datawill beundefined, causinghasLicenseto default tofalse. This results in the "Premium" tag appearing and the toggle being disabled during loading. For a smoother user experience, consider destructuringisPendingand handling the loading state:-const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); +const { data: hasLicense = false, isPending } = useHasLicenseModule('livechat-enterprise');Then conditionally render loading indicators or adjust the disabled state:
const cantSendTranscriptPDF = !canSendTranscriptPDF || !hasLicense || isPending;This is optional since the current behavior (brief flash of "no license" state) is acceptable and consistent with the broader refactoring pattern across ~60 files.
apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx (1)
14-14: LGTM! Consider loading state for better UX.The destructuring pattern correctly extracts the license status from the query result. The default value of
falseensures that premium features appear disabled during the initial license check, which is a safe fallback.For a more refined user experience, consider destructuring
isPendingto differentiate between "license loading" and "no license":-const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); +const { data: hasLicense = false, isPending } = useHasLicenseModule('livechat-enterprise');However, given that
useLicenseBaseuseskeepPreviousData, loading flashes would only occur on the very first mount before license data is fetched, which may be acceptable for this use case.apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx (1)
13-14: Consider showing loading state in verification tag.The destructuring correctly extracts the license status. However, during the initial license check, the tag will display "Unverified" (since
hasLicensedefaults tofalse), which could be misleading if the actual license is still loading.Consider adding a loading state to provide clearer feedback:
-const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); -const isVerified = hasLicense && verified; +const { data: hasLicense = false, isPending } = useHasLicenseModule('contact-id-verification'); +const isVerified = hasLicense && verified; + +if (isPending) { + return <Tag icon={<Icon size='x12' mie={4} name='loading' />}>{t('Checking')}</Tag>; +}apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts (1)
22-22: Consider handling the loading state to avoid query delays.The destructured
hasOutboundModuledefaults tofalsewhile the license query is pending. This means the providers query at line 29 will be disabled until the license check completes, potentially delaying data fetching. Consider also destructuringisPendingand handling it explicitly in theenabledcondition to avoid race conditions.Apply this diff to handle the loading state:
- const { data: hasOutboundModule = false } = useHasLicenseModule('outbound-messaging'); + const { data: hasOutboundModule = false, isPending: isLicenseLoading } = useHasLicenseModule('outbound-messaging'); const canSendOutboundMessages = usePermission('outbound.send-messages'); return useQuery<OutboundProvidersResponse, Error, TData>({ queryKey: omnichannelQueryKeys.outboundProviders({ type }), queryFn: () => getProviders({ type }), retry: 3, - enabled: isOmnichannelEnabled && hasOutboundModule && canSendOutboundMessages && enabled, + enabled: isOmnichannelEnabled && !isLicenseLoading && hasOutboundModule && canSendOutboundMessages && enabled, staleTime, ...queryOptions, });apps/meteor/client/contexts/CallContext.ts (1)
81-81: Consider destructuring for consistency with the rest of the codebase.While this implementation is functionally correct, it differs from the pattern used in other files where the hook result is destructured with a default value. Consider refactoring for consistency:
-export const useIsVoipEnterprise = (): boolean => useHasLicenseModule('voip-enterprise').data === true; +export const useIsVoipEnterprise = (): boolean => { + const { data: isVoipEnterprise = false } = useHasLicenseModule('voip-enterprise'); + return isVoipEnterprise; +};This makes the code more consistent with the patterns in files like
useOutboundProvidersList.ts,EditContactInfo.tsx, and others in this PR.apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx (1)
46-46: Consider checking loading state to avoid premature modal display.The destructuring is correct, but the logic at line 89 may show
AddonRequiredModalduring the initial license check (whenworkspaceHasAddondefaults tofalse). Consider destructuringisPendingand skipping the modal check until the query resolves:-const { data: workspaceHasAddon = false } = useHasLicenseModule(appAddon); +const { data: workspaceHasAddon = false, isPending: isCheckingAddon } = useHasLicenseModule(appAddon);Then at line 89:
-if (isAdminUser && appAddon && !workspaceHasAddon) { +if (isAdminUser && appAddon && !isCheckingAddon && !workspaceHasAddon) {This prevents the modal from appearing briefly if the workspace actually has the addon.
apps/meteor/client/hooks/useVoipClient.ts (1)
39-39: Consider checkingisPendingto avoid creating the wrong VoIP client initially.During the initial load,
isEEdefaults tofalse, which means the effect at line 50 will create aVoIPUserinstance. When the license check completes andisEEbecomestrue, the effect re-runs (line 113 dependency) and creates a newEEVoipClient, discarding the first client. This causes unnecessary client instantiation and cleanup.Consider destructuring
isPendingand only proceeding once the license status is known:-const { data: isEE = false } = useHasLicenseModule('voip-enterprise'); +const { data: isEE = false, isPending: isCheckingLicense } = useHasLicenseModule('voip-enterprise');Then update the guard at line 54:
-if (!uid || !userExtension || !voipEnabled) { +if (!uid || !userExtension || !voipEnabled || isCheckingLicense) { setResult(empty); return; }apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx (1)
12-12: Consider handling loading state for better UX.During the initial load,
federationModuleEnableddefaults tofalse, which may cause line 18's condition to briefly renderComposerFederationJoinRoomDisabledbefore the license data loads. Consider destructuringisPendingand showing an appropriate loading state to avoid flickering UI.Apply this diff to handle the loading state:
- const { data: federationModuleEnabled = false } = useHasLicenseModule('federation'); + const { isPending, data: federationModuleEnabled = false } = useHasLicenseModule('federation'); if (!federationEnabled) { return <ComposerFederationDisabled />; } + + if (isPending) { + return <ComposerMessage {...props} readOnly />; // or appropriate loading state + } if (!subscription && !federationModuleEnabled) { return <ComposerFederationJoinRoomDisabled />; }apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts (1)
25-52: Consider reducing the mockedUseQueryResultsurface to what's actually needed
createSuccessfulQueryResultmirrors almost the entireUseQueryResultshape. That keeps tests tightly coupled to@tanstack/react-queryinternals and will require maintenance whenever the library adds/removes fields, even if the code under test doesn't care.You could simplify to only the properties consumed by
useOutboundMessageAccessand cast toUseQueryResult<boolean, Error>to avoid the long literal, e.g. setdata,error, and a minimal set of status flags, and let the rest be left to the type system.apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx (1)
15-49: Confirm intended behavior when license data is still loadingBy destructuring
{ data: hasLicense = false }you will now treat an undefineddata(e.g. initial pending state) as “no license”, sohandleBlockwill openAdvancedContactModalwhile the license query is still resolving.If the previous triple-state behavior was effectively “only show the advanced contact flow once we definitively know there is no license”, you may want to incorporate
isPendinginto the condition instead of defaulting tofalse.apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx (1)
55-83: Federation gating now treats pending/absent license as “premium feature” — verify UX intent
getFederationHintKeyandcanUseFederationnow both hinge onfederatedModule.isPendingandfederatedModule.data. In practice this means:
- While the license query is pending, the federation toggle will be disabled and the hint will show the premium-feature message.
- If the query errors or returns no license, you also get the same premium hint.
If that’s the intended UX (anything other than “definitely licensed” is shown as premium/locked), this looks consistent. If you’d prefer to distinguish a transient loading/error state from a true “no license” upsell, you might want to branch on
isPending/isErrorseparately.apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx (1)
53-79: Federation license handling matches sidebar modal; consider sharing the logicThis file now mirrors the sidebar CreateChannel modal: pending or falsy
federatedModule.datayields the premium-feature hint and disables the federation toggle, while a resolved truthydata+federationEnabledenables it. That keeps federation behavior consistent across entry points.Given the duplication of
getFederationHintKeyandcanUseFederationlogic between the two modals, you might consider extracting a small shared helper to keep them in sync over time.apps/meteor/client/hooks/useHasLicenseModule.ts (1)
5-8: Consider disabling the query whenlicenseNameis undefined.When
licenseNameisundefined, the select function will returnfalse, but the underlying API call to fetch license data still executes. This is unnecessary since the result is predetermined.Apply this diff to avoid unnecessary API calls:
export const useHasLicenseModule = (licenseName: LicenseModule | undefined) => useLicenseBase({ + enabled: licenseName !== undefined, select: (data) => licenseName !== undefined && data.license.activeModules.includes(licenseName), });
📜 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.
📒 Files selected for processing (65)
apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx(2 hunks)apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts(1 hunks)apps/meteor/client/contexts/CallContext.ts(1 hunks)apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts(1 hunks)apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts(1 hunks)apps/meteor/client/hooks/useDevicesMenuOption.tsx(1 hunks)apps/meteor/client/hooks/useHasLicenseModule.ts(1 hunks)apps/meteor/client/hooks/useLicense.ts(2 hunks)apps/meteor/client/hooks/useVoipClient.ts(1 hunks)apps/meteor/client/hooks/useVoipWarningModal.tsx(1 hunks)apps/meteor/client/providers/MediaCallProvider.tsx(1 hunks)apps/meteor/client/providers/OmnichannelProvider.tsx(1 hunks)apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx(2 hunks)apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx(1 hunks)apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx(1 hunks)apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx(1 hunks)apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx(1 hunks)apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx(1 hunks)apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx(1 hunks)apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx(1 hunks)apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx(1 hunks)apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx(1 hunks)apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx(1 hunks)apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx(1 hunks)apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx(1 hunks)apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx(2 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts(7 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx(1 hunks)apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx(1 hunks)apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts(1 hunks)apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx(1 hunks)apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx(1 hunks)apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx(1 hunks)apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx(1 hunks)apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx(1 hunks)apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.
Applied to files:
apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.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/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx
📚 Learning: 2025-11-19T18:20:37.096Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.096Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.
Applied to files:
apps/meteor/client/providers/MediaCallProvider.tsx
📚 Learning: 2025-10-06T20:32:23.658Z
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.
Applied to files:
apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsxapps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx
🧬 Code graph analysis (59)
apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/contexts/CallContext.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useVoipWarningModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/providers/MediaCallProvider.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useVoipClient.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useHasLicenseModule.ts (2)
packages/core-typings/src/license/LicenseModule.ts (1)
LicenseModule(30-30)apps/meteor/client/hooks/useLicense.ts (1)
useLicenseBase(28-55)
apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/providers/OmnichannelProvider.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useDevicesMenuOption.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx
Outdated
Show resolved
Hide resolved
apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx
Outdated
Show resolved
Hide resolved
apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx
Outdated
Show resolved
Hide resolved
apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx
Outdated
Show resolved
Hide resolved
f492192 to
aef7eb8
Compare
aef7eb8 to
6cbe3dc
Compare
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
🧹 Nitpick comments (3)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx (1)
33-33: Migration pattern applied correctly.The destructuring pattern
{ data: hasLicense = false }correctly extracts the boolean from the query result with a safe default. This aligns with the PR's objective to return query-style results fromuseHasLicenseModule.Optionally, consider destructuring
isPendingto show a loading state instead of immediately rendering the "Unverified" button during the license check:-const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); +const { data: hasLicense = false, isPending } = useHasLicenseModule('contact-id-verification');Then on line 77, you could conditionally render a skeleton or spinner while
isPendingis true. However, the current fail-closed approach (showing "Unverified" during load) may be intentional for this security feature.apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx (1)
7-7: Migration to query-style result is correct.The destructuring pattern correctly adapts to the new
useHasLicenseModuleAPI. The default value offalseensures safe behavior during loading and error states—the component will simply not render until the license check confirms the module is available.Optional UX consideration:
While the current behavior is acceptable for gated features, you could destructure
isPendingto show a loading indicator or handle errors explicitly if a more responsive UX is desired:- const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false, isPending } = useHasLicenseModule('livechat-enterprise'); - if (!hasLicense) { + if (isPending) { + return <Skeleton />; // or null + } + + if (!hasLicense) { return null; }This is optional—showing nothing until loaded is a valid approach for enterprise-only fields.
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
5-8: Consider exposing theenabledparameter for flexibility.The
useLicenseBasehook now accepts anenabledparameter (added inuseLicense.ts), butuseHasLicenseModuledoesn't expose it. While this may be intentional for the current use cases, exposing it would allow consumers to conditionally enable/disable the query when needed.Apply this diff to optionally expose the
enabledparameter:-export const useHasLicenseModule = (licenseName: LicenseModule | undefined) => +export const useHasLicenseModule = (licenseName: LicenseModule | undefined, enabled?: boolean) => useLicenseBase({ + enabled, select: (data) => !!licenseName && data.license.activeModules.includes(licenseName), });
📜 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.
📒 Files selected for processing (65)
apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx(2 hunks)apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts(1 hunks)apps/meteor/client/contexts/CallContext.ts(1 hunks)apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts(1 hunks)apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts(1 hunks)apps/meteor/client/hooks/useDevicesMenuOption.tsx(1 hunks)apps/meteor/client/hooks/useHasLicenseModule.ts(1 hunks)apps/meteor/client/hooks/useLicense.ts(2 hunks)apps/meteor/client/hooks/useVoipClient.ts(1 hunks)apps/meteor/client/hooks/useVoipWarningModal.tsx(1 hunks)apps/meteor/client/providers/MediaCallProvider.tsx(1 hunks)apps/meteor/client/providers/OmnichannelProvider.tsx(1 hunks)apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx(2 hunks)apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx(1 hunks)apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx(1 hunks)apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx(2 hunks)apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx(2 hunks)apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx(1 hunks)apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx(1 hunks)apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx(1 hunks)apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx(1 hunks)apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx(1 hunks)apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx(1 hunks)apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx(1 hunks)apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx(1 hunks)apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx(1 hunks)apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx(2 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts(7 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts(1 hunks)apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx(1 hunks)apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx(1 hunks)apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx(1 hunks)apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx(1 hunks)apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts(1 hunks)apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx(1 hunks)apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx(1 hunks)apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx(1 hunks)apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx(1 hunks)apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx(1 hunks)apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx(1 hunks)apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx(1 hunks)apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (41)
- apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx
- apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts
- apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx
- apps/meteor/client/hooks/useVoipClient.ts
- apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx
- apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx
- apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx
- apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx
- apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx
- apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx
- apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx
- apps/meteor/client/hooks/useVoipWarningModal.tsx
- apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts
- apps/meteor/client/contexts/CallContext.ts
- apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx
- apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx
- apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx
- apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts
- apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx
- apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx
- apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx
- apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx
- apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx
- apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx
- apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts
- apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx
- apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx
- apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx
- apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx
- apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx
- apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx
- apps/meteor/client/providers/OmnichannelProvider.tsx
- apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx
- apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx
- apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx
- apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx
- apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx
- apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx
- apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx
- apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.
Applied to files:
apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.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/sidebar/header/CreateChannel/CreateChannelModal.tsxapps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx
📚 Learning: 2025-10-06T20:32:23.658Z
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.
Applied to files:
apps/meteor/client/hooks/useHasLicenseModule.ts
🧬 Code graph analysis (21)
apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useDevicesMenuOption.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/hooks/useHasLicenseModule.ts (2)
packages/core-typings/src/license/LicenseModule.ts (1)
LicenseModule(30-30)apps/meteor/client/hooks/useLicense.ts (1)
useLicenseBase(28-55)
apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/providers/MediaCallProvider.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx (1)
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
useHasLicenseModule(5-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: 📦 Build Packages
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (23)
apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx (1)
34-72: Loading-state wiring for license check looks correct nowDeriving
isPendinganddatafromuseHasLicenseModuleand short-circuiting to<PageSkeleton />whileisPendingcleanly fixes the earlier flash ofNotAuthorizedPageduring license loading. Defaultingdatatofalseis safe given the explicit loading guard, and the downstream upsell/authorization logic reads clearly.apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx (1)
313-313: LGTM! Consistent destructuring pattern.The license check now follows the query result pattern by destructuring
datawith a safe default. While the license check might briefly default tofalseduring initial load (potentially hiding transcript actions momentarily), this is acceptable behavior for non-critical feature gates.apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx (1)
8-8: LGTM! Clean destructuring with safe default.The change aligns with the query result pattern. The default of
falseensures the component safely returnsnullduring the initial license check.apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx (1)
17-31: Excellent state handling! Proper loading and error states implemented.The implementation correctly handles all query states:
- Shows
PageSkeletonduringisPending- Shows
GenericErroronisError- Only renders
EditRolePagewhen data is successfully loadedThis follows React Query best practices and prevents logic from executing with stale/default data.
apps/meteor/client/hooks/useDevicesMenuOption.tsx (1)
16-16: LGTM! Consistent pattern for feature gating.The destructuring with a safe default of
falseis appropriate for this menu option visibility check. The option will correctly appear once the license check completes.apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx (1)
10-10: LGTM! Safe default for optional field.The destructuring follows the consistent pattern. The field safely remains hidden during the initial license check and appears once validated.
apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts (1)
10-10: LGTM! Proper memoization with query result.The destructuring is consistent with the pattern, and the
useMemocorrectly includeslicensedin dependencies. The room action will properly register once the license check completes.apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx (1)
17-34: Excellent async handling in effect! Proper isPending guard prevents race conditions.The implementation correctly:
- Destructures
isPendingfrom the query result- Returns early from the effect during license check (lines 24-26)
- Includes
isPendingin the dependency arrayThis prevents the upsell modal logic from executing prematurely with default data, ensuring it only runs after the license check completes.
apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx (1)
13-13: LGTM! Consistent destructuring for modal data.The pattern matches other files in this PR. The modal component will receive the correct
hasModulevalue once the license check completes.apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx (1)
17-25: License query destructuring looks correct.Reading
{ data: hasLicense = false }fromuseHasLicenseModule('livechat-enterprise')and gating the component withif (!hasLicense) return null;is consistent with the new query-style hook shape and keeps the previous behavior semantics intact.apps/meteor/client/providers/MediaCallProvider.tsx (1)
15-39: Teams VoIP license gating aligns with new hook contract.Destructuring
{ data: hasModule = false }and usingif (!hasModule)to choose the unlicensed context matches the new query-style return and keeps the control flow straightforward.apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts (1)
17-23: Business-hours license check uses the query result correctly.Using
{ data: hasLicense = false }and gating registration onbusinessHourType && hasLicensecorrectly ties behavior registration to a resolved license boolean from the query.apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts (1)
12-34: Calls room action correctly derives license from query data.
{ data: licensed = false } = useHasLicenseModule('videoconference-enterprise')and returningundefinedwhen!licensedis consistent with the new hook contract and cleanly gates the toolbox item.apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx (1)
34-177: Enterprise license flag consumption is consistent and safe.Deriving
isEnterprisevia{ data: isEnterprise = false }and using it only to conditionally render the Units field matches the query-style license hook and avoids runtime issues when data is undefined.apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx (1)
12-20: Federation module license check correctly uses query data.Using
{ data: federationModuleEnabled = false }and gating the join-room-disabled state on!subscription && !federationModuleEnabledcleanly reflects the new hook’s query-style result without altering the intended UX.apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx (1)
20-47: Device management route now correctly handles the query loading state.Destructuring both
{ data: hasDeviceManagement = false, isPending }and usingif (isModalOpen || isPending) { return <PageSkeleton />; }ensures a proper loading experience while the license query resolves and passes a stable boolean into the upsell logic.apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx (1)
55-63: Federation license query integration and hinting logic look solid.Using the full
useHasLicenseModulequery object for bothgetFederationHintKeyandcanUseFederationcleanly combines license state (data), loading state (isPending), and thefederationEnabledtoggle. The toggle’s disabled state and the three hint branches (premium feature, disabled feature flag, fully enabled) are consistent and type-safe.Also applies to: 81-83, 290-308
apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx (1)
13-14: LGTM! Destructuring pattern correctly handles the query result.The destructuring of
.datawith afalsedefault properly handles the undefined case when the query is pending or disabled.apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx (2)
42-46: LGTM! Correct pattern for accessing multiple query properties.Storing the entire query result objects and accessing
.isPendingand.datathroughout the component is the correct approach when multiple properties are needed.
84-87: LGTM! Dependency array correctly optimized.Including only
.dataproperties in the dependency array (rather than entire query objects) prevents unnecessary re-renders while maintaining correct reactivity.apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx (1)
8-8: LGTM! Consistent with the refactored pattern.The destructuring pattern with default value correctly handles the query result.
apps/meteor/client/hooks/useHasLicenseModule.ts (1)
5-8: LGTM! Hook correctly delegates to useLicenseBase.The refactoring properly returns the query result from
useLicenseBase, allowing consumers to access.dataand.isPendingproperties. The selector logic remains correct.apps/meteor/client/hooks/useLicense.ts (1)
28-35: LGTM! Theenabledparameter addition is backward compatible.Adding the optional
enabledparameter (defaulting totrue) allows consumers to conditionally enable/disable queries while maintaining backward compatibility for existing callers.Also applies to: 53-53
Proposed changes (including videos or screenshots)
It replaces odd triple-state return type from
useHasLicenseModulederiving it fromuseQueryresult.Issue(s)
ARCH-1882
Steps to test or reproduce
Further comments
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.