Skip to content

Conversation

@tassoevan
Copy link
Contributor

@tassoevan tassoevan commented Nov 19, 2025

Proposed changes (including videos or screenshots)

It replaces odd triple-state return type from useHasLicenseModule deriving it from useQuery result.

Issue(s)

ARCH-1882

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • Refactor
    • License checks now use structured query results (loading/pending + data) for consistent gating across the app.
  • Bug Fixes
    • UI loading and access flows improved: components show proper loading skeletons and avoid premature/incorrect permission states.
  • Chores
    • Defaulted missing license data to false to prevent undefined behavior in feature gating.

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

@tassoevan tassoevan added this to the 7.13.0 milestone Nov 19, 2025
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Nov 19, 2025

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Nov 19, 2025

⚠️ No Changeset found

Latest commit: d93c253

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 19, 2025

Walkthrough

The hook useHasLicenseModule was changed to return the full query result (including .data and isPending) from useLicenseBase; ~60 consumer files were updated to destructure .data (with defaults) and replace string 'loading' checks with isPending boolean handling.

Changes

Cohort / File(s) Summary
Core Hook Changes
apps/meteor/client/hooks/useLicense.ts, apps/meteor/client/hooks/useHasLicenseModule.ts
useLicenseBase gains an optional enabled param and computes enabled as enabled && !!uid; useHasLicenseModule now returns the raw query result (no 'loading' fallback or explicit return type).
Federation UI Logic
apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx, apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx
Switched loading checks to isPending and gating to require .data presence; updated federation hint and canUseFederation to use .data/isPending shape.
Outbound Messaging
apps/meteor/client/views/omnichannel/components/outboundMessage/... (wizard, hooks, modals, spec)
Replaced 'loading' string checks with isPending; updated consumers to use .data values; spec mocks updated to return UseQueryResult shape.
Monitors & Admin Pages
apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx, apps/meteor/client/views/admin/*
Use { data, isPending } from hook; render PageSkeleton when isPending; added GenericError handling in permissions page.
VoIP / MediaCall / Calls
apps/meteor/client/providers/MediaCallProvider.tsx, apps/meteor/client/contexts/CallContext.ts, apps/meteor/client/hooks/*Calls*
License checks now destructure { data: ..., isPending? } with defaults; preserved gating logic but changed source shape.
Omnichannel Forms & Components
apps/meteor/client/views/omnichannel/additionalForms/*, apps/meteor/client/views/omnichannel/components/*, apps/meteor/client/views/omnichannel/contactInfo/*
~30+ files updated to destructure { data: ... = false } and use .data for feature gates; early returns and rendering guards preserved.
Marketplace & App Views
apps/meteor/client/views/marketplace/*, apps/meteor/client/views/marketplace/hooks/*
Addon/install checks now read .data with default false from hook.
Navigation / Room / Quick Actions
apps/meteor/client/views/navigation/..., apps/meteor/client/views/room/...
Updated quick actions and composer federation to read license flags from { data } and default booleans.
Misc. License Consumers
numerous other files under apps/meteor/client/...
Consistent pattern change: consume useHasLicenseModule as a query result ({ data: X = false, isPending }) instead of a boolean or 'loading' string.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay special attention to:
    • Federation gating and hint logic (CreateChannelModal files).
    • OutboundMessageWizard dependency arrays and loading gating.
    • MonitorsPageContainer and other pages switching from 'loading' string checks to isPending.
    • Tests/specs updated to mock UseQueryResult shapes (useOutboundMessageAccess.spec.ts).
    • Hook signature change in useHasLicenseModule — ensure TypeScript consumers still infer correctly.

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ggazzo
  • aleksandernsilva

Poem

🐰
I hopped through hooks with nimble paws,
Unwrapped the data, fixed the flaws.
No more 'loading' string in sight,
isPending guards keep UI right.
Hooray — the license checks now hop with glee!

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 pull request title clearly describes the main change: converting useHasLicenseModule to return a query-style result instead of a triple-state return type.
Linked Issues check ✅ Passed The pull request successfully implements the objective from ARCH-1882 by converting useHasLicenseModule to return a query-result style object with data, isPending, and isError properties instead of a triple-state return.
Out of Scope Changes check ✅ Passed All changes are directly related to the refactoring of useHasLicenseModule and its consumers to use the new query-result return shape, with no unrelated modifications detected.
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 chore/use-has-license-module

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.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 19, 2025

📦 Docker Image Size Report

📈 Changes

Service Current Baseline Change Percent
sum of all images 1.2GiB 1.2GiB +12MiB
rocketchat 358MiB 347MiB +12MiB
omnichannel-transcript-service 132MiB 132MiB -2.7KiB
queue-worker-service 132MiB 132MiB +1.1KiB
ddp-streamer-service 127MiB 127MiB -206B
account-service 114MiB 114MiB +4.3KiB
stream-hub-service 111MiB 111MiB -2.8KiB
authorization-service 111MiB 111MiB +1.4KiB
presence-service 111MiB 111MiB +745B

📊 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 13:35", "11/21 15:01 (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]
  line "authorization-service" [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]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.14, 0.14, 0.14, 0.13, 0.13]
  line "presence-service" [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]
  line "rocketchat" [0.36, 0.36, 0.35, 0.35, 0.35, 0.34, 0.35]
  line "stream-hub-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11]
Loading

Statistics (last 6 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-37552
  • Baseline: develop
  • Timestamp: 2025-11-21 15:01:22 UTC
  • Historical data points: 6

Updated: Fri, 21 Nov 2025 15:01:23 GMT

@codecov
Copy link

codecov bot commented Nov 19, 2025

Codecov Report

❌ Patch coverage is 20.25316% with 63 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.87%. Comparing base (7f1b834) to head (6cbe3dc).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             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     
Flag Coverage Δ
e2e 57.32% <20.25%> (-0.13%) ⬇️
e2e-api 42.49% <ø> (-1.01%) ⬇️

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.

@tassoevan tassoevan marked this pull request as ready for review November 20, 2025 05:16
@tassoevan tassoevan requested a review from a team as a code owner November 20, 2025 05:16
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: 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 !hasDeviceManagement before the query completes. Since hasDeviceManagement defaults to false, users will see NotAuthorizedPage flash 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 condition context !== 'new' || hasCustomRolesModule evaluates to false || 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 isEnterprise check defaults to false while the license query is pending, causing the component to render NotAuthorizedPage during 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 PageSkeleton or 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 data property from the refactored useHasLicenseModule hook and provides a sensible default of false. 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 isPending and 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 isPending is true), data will be undefined, causing hasLicense to default to false. This results in the "Premium" tag appearing and the toggle being disabled during loading. For a smoother user experience, consider destructuring isPending and 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 false ensures that premium features appear disabled during the initial license check, which is a safe fallback.

For a more refined user experience, consider destructuring isPending to 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 useLicenseBase uses keepPreviousData, 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 hasLicense defaults to false), 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 hasOutboundModule defaults to false while 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 destructuring isPending and handling it explicitly in the enabled condition 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 AddonRequiredModal during the initial license check (when workspaceHasAddon defaults to false). Consider destructuring isPending and 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 checking isPending to avoid creating the wrong VoIP client initially.

During the initial load, isEE defaults to false, which means the effect at line 50 will create a VoIPUser instance. When the license check completes and isEE becomes true, the effect re-runs (line 113 dependency) and creates a new EEVoipClient, discarding the first client. This causes unnecessary client instantiation and cleanup.

Consider destructuring isPending and 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, federationModuleEnabled defaults to false, which may cause line 18's condition to briefly render ComposerFederationJoinRoomDisabled before the license data loads. Consider destructuring isPending and 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 mocked UseQueryResult surface to what's actually needed

createSuccessfulQueryResult mirrors almost the entire UseQueryResult shape. That keeps tests tightly coupled to @tanstack/react-query internals 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 useOutboundMessageAccess and cast to UseQueryResult<boolean, Error> to avoid the long literal, e.g. set data, 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 loading

By destructuring { data: hasLicense = false } you will now treat an undefined data (e.g. initial pending state) as “no license”, so handleBlock will open AdvancedContactModal while 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 isPending into the condition instead of defaulting to false.

apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx (1)

55-83: Federation gating now treats pending/absent license as “premium feature” — verify UX intent

getFederationHintKey and canUseFederation now both hinge on federatedModule.isPending and federatedModule.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 / isError separately.

apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx (1)

53-79: Federation license handling matches sidebar modal; consider sharing the logic

This file now mirrors the sidebar CreateChannel modal: pending or falsy federatedModule.data yields the premium-feature hint and disables the federation toggle, while a resolved truthy data + federationEnabled enables it. That keeps federation behavior consistent across entry points.

Given the duplication of getFederationHintKey and canUseFederation logic 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 when licenseName is undefined.

When licenseName is undefined, the select function will return false, 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 9063d56 and f492192.

📒 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.tsx
  • apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx
  • apps/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.tsx
  • apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx
  • apps/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.tsx
  • apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx
  • apps/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.tsx
  • apps/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)

@tassoevan tassoevan force-pushed the chore/use-has-license-module branch from f492192 to aef7eb8 Compare November 20, 2025 19:13
@tassoevan tassoevan force-pushed the chore/use-has-license-module branch from aef7eb8 to 6cbe3dc Compare November 20, 2025 19:15
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 (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 from useHasLicenseModule.

Optionally, consider destructuring isPending to 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 isPending is 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 useHasLicenseModule API. The default value of false ensures 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 isPending to 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 the enabled parameter for flexibility.

The useLicenseBase hook now accepts an enabled parameter (added in useLicense.ts), but useHasLicenseModule doesn'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 enabled parameter:

-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.

📥 Commits

Reviewing files that changed from the base of the PR and between f492192 and 6cbe3dc.

📒 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.tsx
  • apps/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.tsx
  • apps/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.tsx
  • apps/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 now

Deriving isPending and data from useHasLicenseModule and short-circuiting to <PageSkeleton /> while isPending cleanly fixes the earlier flash of NotAuthorizedPage during license loading. Defaulting data to false is 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 data with a safe default. While the license check might briefly default to false during 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 false ensures the component safely returns null during 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 PageSkeleton during isPending
  • Shows GenericError on isError
  • Only renders EditRolePage when data is successfully loaded

This 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 false is 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 useMemo correctly includes licensed in 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 isPending from the query result
  • Returns early from the effect during license check (lines 24-26)
  • Includes isPending in the dependency array

This 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 hasModule value 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 } from useHasLicenseModule('livechat-enterprise') and gating the component with if (!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 using if (!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 on businessHourType && hasLicense correctly 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 returning undefined when !licensed is 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 isEnterprise via { 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 && !federationModuleEnabled cleanly 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 using if (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 useHasLicenseModule query object for both getFederationHintKey and canUseFederation cleanly combines license state (data), loading state (isPending), and the federationEnabled toggle. 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 .data with a false default 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 .isPending and .data throughout the component is the correct approach when multiple properties are needed.


84-87: LGTM! Dependency array correctly optimized.

Including only .data properties 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 .data and .isPending properties. The selector logic remains correct.

apps/meteor/client/hooks/useLicense.ts (1)

28-35: LGTM! The enabled parameter addition is backward compatible.

Adding the optional enabled parameter (defaulting to true) allows consumers to conditionally enable/disable queries while maintaining backward compatibility for existing callers.

Also applies to: 53-53

@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Nov 21, 2025
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Nov 21, 2025
@ggazzo ggazzo merged commit 4ca66c4 into develop Nov 24, 2025
6 of 7 checks passed
@ggazzo ggazzo deleted the chore/use-has-license-module branch November 24, 2025 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants