diff --git a/apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx b/apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx index 2ccdc1321a502..e9fabaea5f6d6 100644 --- a/apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx +++ b/apps/meteor/client/NavBarV2/NavBarPagesGroup/actions/CreateChannelModal.tsx @@ -51,7 +51,7 @@ type CreateChannelModalPayload = { }; const getFederationHintKey = (licenseModule: ReturnType, featureToggle: boolean): TranslationKey => { - if (licenseModule === 'loading' || !licenseModule) { + if (licenseModule.isPending || !licenseModule.data) { return 'error-this-is-a-premium-feature'; } if (!featureToggle) { @@ -75,7 +75,7 @@ const CreateChannelModal = ({ teamId = '', onClose, reload }: CreateChannelModal const channelNameRegex = useMemo(() => new RegExp(`^${namesValidation}$`), [namesValidation]); const federatedModule = useHasLicenseModule('federation'); - const canUseFederation = federatedModule !== 'loading' && federatedModule && federationEnabled; + const canUseFederation = !federatedModule.isPending && federatedModule.data && federationEnabled; const channelNameExists = useEndpoint('GET', '/v1/rooms.nameExists'); const createChannel = useEndpoint('POST', '/v1/channels.create'); diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.spec.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.spec.ts similarity index 100% rename from apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.spec.tsx rename to apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.spec.ts diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts similarity index 94% rename from apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.tsx rename to apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts index 744513c6316e0..8ec2f98f1edcb 100644 --- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.tsx +++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAuditMenu.ts @@ -8,7 +8,7 @@ export const useAuditMenu = () => { const router = useRouter(); const { t } = useTranslation(); - const hasAuditLicense = useHasLicenseModule('auditing') === true; + const { data: hasAuditLicense = false } = useHasLicenseModule('auditing'); const hasAuditPermission = usePermission('can-audit') && hasAuditLicense; const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense; diff --git a/apps/meteor/client/contexts/CallContext.ts b/apps/meteor/client/contexts/CallContext.ts index d420837bbc352..b1724b0d0d7b5 100644 --- a/apps/meteor/client/contexts/CallContext.ts +++ b/apps/meteor/client/contexts/CallContext.ts @@ -78,7 +78,7 @@ const CallContextValueDefault: CallContextValue = { export const CallContext = createContext(CallContextValueDefault); -export const useIsVoipEnterprise = (): boolean => useHasLicenseModule('voip-enterprise') === true; +export const useIsVoipEnterprise = (): boolean => useHasLicenseModule('voip-enterprise').data === true; export const useIsCallEnabled = (): boolean => { const { enabled } = useContext(CallContext); diff --git a/apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts b/apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts index 92c7ddf4c1c3d..e8738338f9336 100644 --- a/apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts +++ b/apps/meteor/client/hooks/quickActions/useOnHoldChatQuickAction.ts @@ -4,7 +4,7 @@ import { QuickActionsEnum, type QuickActionsActionConfig } from '../../views/roo import { useHasLicenseModule } from '../useHasLicenseModule'; export const useOnHoldChatQuickAction = (): QuickActionsActionConfig | undefined => { - const licensed = useHasLicenseModule('livechat-enterprise') === true; + const { data: licensed = false } = useHasLicenseModule('livechat-enterprise'); return useMemo(() => { if (!licensed) { diff --git a/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts b/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts index cbc2a594eb6ec..c5d86460b47c6 100644 --- a/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts +++ b/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts @@ -9,7 +9,7 @@ import { useHasLicenseModule } from '../useHasLicenseModule'; const VideoConfList = lazy(() => import('../../views/room/contextualBar/VideoConference/VideoConfList')); export const useCallsRoomAction = () => { - const licensed = useHasLicenseModule('videoconference-enterprise') === true; + const { data: licensed = false } = useHasLicenseModule('videoconference-enterprise'); const room = useContext(RoomContext)?.room; const federated = room ? isRoomFederated(room) : false; const { t } = useTranslation(); diff --git a/apps/meteor/client/hooks/useDevicesMenuOption.tsx b/apps/meteor/client/hooks/useDevicesMenuOption.tsx index 5af023da81dd7..ff770484ddb2f 100644 --- a/apps/meteor/client/hooks/useDevicesMenuOption.tsx +++ b/apps/meteor/client/hooks/useDevicesMenuOption.tsx @@ -13,7 +13,7 @@ type DevicesMenuOption = { }; export const useDevicesMenuOption = (): DevicesMenuOption | null => { - const isEnterprise = useHasLicenseModule('voip-enterprise'); + const { data: isEnterprise = false } = useHasLicenseModule('voip-enterprise'); const { t } = useTranslation(); const setModal = useSetModal(); diff --git a/apps/meteor/client/hooks/useHasLicenseModule.ts b/apps/meteor/client/hooks/useHasLicenseModule.ts index c28713019d4d5..4916cb3685198 100644 --- a/apps/meteor/client/hooks/useHasLicenseModule.ts +++ b/apps/meteor/client/hooks/useHasLicenseModule.ts @@ -2,10 +2,7 @@ import type { LicenseModule } from '@rocket.chat/core-typings'; import { useLicenseBase } from './useLicense'; -export const useHasLicenseModule = (licenseName: LicenseModule | undefined): 'loading' | boolean => { - return ( - useLicenseBase({ - select: (data) => !!licenseName && data.license.activeModules.includes(licenseName), - }).data ?? 'loading' - ); -}; +export const useHasLicenseModule = (licenseName: LicenseModule | undefined) => + useLicenseBase({ + select: (data) => !!licenseName && data.license.activeModules.includes(licenseName), + }); diff --git a/apps/meteor/client/hooks/useLicense.ts b/apps/meteor/client/hooks/useLicense.ts index c6f0c96a37dd2..5817eff2e0aa1 100644 --- a/apps/meteor/client/hooks/useLicense.ts +++ b/apps/meteor/client/hooks/useLicense.ts @@ -27,9 +27,11 @@ const invalidateQueryClientLicenses = (() => { export const useLicenseBase = ({ params, + enabled = true, select, }: { params?: LicenseParams; + enabled?: boolean; select: (data: LicenseDataType) => TData; }) => { const uid = useUserId(); @@ -48,7 +50,7 @@ export const useLicenseBase = ({ staleTime: Infinity, placeholderData: keepPreviousData, select, - enabled: !!uid, + enabled: enabled && !!uid, }); }; diff --git a/apps/meteor/client/hooks/useVoipClient.ts b/apps/meteor/client/hooks/useVoipClient.ts index 948fc7ce0183a..4a2eb19de47ee 100644 --- a/apps/meteor/client/hooks/useVoipClient.ts +++ b/apps/meteor/client/hooks/useVoipClient.ts @@ -36,7 +36,7 @@ export const useVoipClient = (): UseVoipClientResult => { const iceServers = useWebRtcServers(); const [result, setResult] = useSafely(useState({})); - const isEE = useHasLicenseModule('voip-enterprise'); + const { data: isEE = false } = useHasLicenseModule('voip-enterprise'); const voipEnabled = settingVoipEnabled && voipConnectorEnabled; useEffect(() => { diff --git a/apps/meteor/client/hooks/useVoipWarningModal.tsx b/apps/meteor/client/hooks/useVoipWarningModal.tsx index 4e6cedbd5977d..568475d3a5efa 100644 --- a/apps/meteor/client/hooks/useVoipWarningModal.tsx +++ b/apps/meteor/client/hooks/useVoipWarningModal.tsx @@ -8,7 +8,7 @@ import TeamsVoipConfigModal from '../views/room/contextualBar/TeamsVoipConfigMod export const useVoipWarningModal = (): (() => void) => { const setModal = useSetModal(); const isAdmin = useRole('admin'); - const hasModule = useHasLicenseModule('teams-voip') === true; + const { data: hasModule = false } = useHasLicenseModule('teams-voip'); const teamsVoipSettingsRoute = useRoute('admin-settings'); const handleClose = useEffectEvent(() => setModal(null)); diff --git a/apps/meteor/client/providers/MediaCallProvider.tsx b/apps/meteor/client/providers/MediaCallProvider.tsx index c1a461f9a0d0f..a1e8f552808a0 100644 --- a/apps/meteor/client/providers/MediaCallProvider.tsx +++ b/apps/meteor/client/providers/MediaCallProvider.tsx @@ -12,7 +12,7 @@ const MediaCallProvider = ({ children }: { children: ReactNode }) => { const canMakeInternalCall = usePermission('allow-internal-voice-calls'); const canMakeExternalCall = usePermission('allow-external-voice-calls'); - const hasModule = useHasLicenseModule('teams-voip'); + const { data: hasModule = false } = useHasLicenseModule('teams-voip'); const unauthorizedContextValue = useMemo( () => ({ diff --git a/apps/meteor/client/providers/OmnichannelProvider.tsx b/apps/meteor/client/providers/OmnichannelProvider.tsx index d96142b1c02ce..986b62d83721a 100644 --- a/apps/meteor/client/providers/OmnichannelProvider.tsx +++ b/apps/meteor/client/providers/OmnichannelProvider.tsx @@ -67,7 +67,7 @@ const OmnichannelProvider = ({ children }: OmnichannelProviderProps) => { const accessible = hasAccess && omniChannelEnabled; const iceServersSetting: any = useSetting('WebRTC_Servers'); - const isEnterprise = useHasLicenseModule('livechat-enterprise') === true; + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); const getPriorities = useEndpoint('GET', '/v1/livechat/priorities'); const subscribe = useStream('notify-logged'); diff --git a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx index f5176767fc817..9671e4e83b527 100644 --- a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx +++ b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx @@ -53,7 +53,7 @@ type CreateChannelModalPayload = { }; const getFederationHintKey = (licenseModule: ReturnType, featureToggle: boolean): TranslationKey => { - if (licenseModule === 'loading' || !licenseModule) { + if (licenseModule.isPending || !licenseModule.data) { return 'error-this-is-a-premium-feature'; } if (!featureToggle) { @@ -79,7 +79,7 @@ const CreateChannelModal = ({ teamId = '', mainRoom, onClose, reload }: CreateCh const channelNameRegex = useMemo(() => new RegExp(`^${namesValidation}$`), [namesValidation]); const federatedModule = useHasLicenseModule('federation'); - const canUseFederation = federatedModule !== 'loading' && federatedModule && federationEnabled; + const canUseFederation = !federatedModule.isPending && federatedModule.data && federationEnabled; const channelNameExists = useEndpoint('GET', '/v1/rooms.nameExists'); const createChannel = useEndpoint('POST', '/v1/channels.create'); diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx index 5734ffc9cac8a..6796784d920c1 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.tsx @@ -4,7 +4,7 @@ import { useTranslation, useRoute, usePermission } from '@rocket.chat/ui-context import { useHasLicenseModule } from '../../../../hooks/useHasLicenseModule'; export const useAuditItems = (): GenericMenuItemProps[] => { - const hasAuditLicense = useHasLicenseModule('auditing') === true; + const { data: hasAuditLicense = false } = useHasLicenseModule('auditing'); const hasAuditPermission = usePermission('can-audit') && hasAuditLicense; const hasAuditLogPermission = usePermission('can-audit-log') && hasAuditLicense; diff --git a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx index 1d0dfceeaa0df..35b7b55cafa16 100644 --- a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx +++ b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx @@ -10,7 +10,7 @@ const PreferencesConversationTranscript = () => { const { register } = useFormContext(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const alwaysSendEmailTranscript = useSetting('Livechat_transcript_send_always'); const canSendTranscriptPDF = usePermission('request-pdf-transcript'); const canSendTranscriptEmailPermission = usePermission('send-omnichannel-chat-transcript'); diff --git a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx index e8583f1cfab02..fd808444a4485 100644 --- a/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx +++ b/apps/meteor/client/views/admin/deviceManagement/DeviceManagementAdminRoute.tsx @@ -17,7 +17,7 @@ const DeviceManagementAdminRoute = (): ReactElement => { const setModal = useSetModal(); const isModalOpen = !!useCurrentModal(); - const hasDeviceManagement = useHasLicenseModule('device-management') as boolean; + const { data: hasDeviceManagement = false, isPending } = useHasLicenseModule('device-management'); const canViewDeviceManagement = usePermission('view-device-management'); const { shouldShowUpsell, handleManageSubscription } = useUpsellActions(hasDeviceManagement); @@ -39,7 +39,7 @@ const DeviceManagementAdminRoute = (): ReactElement => { } }, [shouldShowUpsell, router, setModal, t, handleManageSubscription]); - if (isModalOpen) { + if (isModalOpen || isPending) { return ; } diff --git a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx index 9da2b9c7b04c8..a1a74535025e6 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx +++ b/apps/meteor/client/views/admin/engagementDashboard/EngagementDashboardRoute.tsx @@ -31,7 +31,7 @@ const EngagementDashboardRoute = (): ReactElement | null => { const tab = useRouteParameter('tab'); const eventStats = useEndpoint('POST', '/v1/statistics.telemetry'); - const hasEngagementDashboard = useHasLicenseModule('engagement-dashboard') as boolean; + const { isPending, data: hasEngagementDashboard = false } = useHasLicenseModule('engagement-dashboard'); const { shouldShowUpsell, handleManageSubscription } = useUpsellActions(hasEngagementDashboard); @@ -64,7 +64,7 @@ const EngagementDashboardRoute = (): ReactElement | null => { }); }, [shouldShowUpsell, router, tab, setModal, t, handleManageSubscription]); - if (isModalOpen) { + if (isModalOpen || isPending) { return ; } diff --git a/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx b/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx index 48c5282047365..fe647fe476eee 100644 --- a/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx +++ b/apps/meteor/client/views/admin/permissions/EditRolePageWithData.tsx @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import EditRolePage from './EditRolePage'; import { useRole } from './hooks/useRole'; +import GenericError from '../../../components/GenericError'; import PageSkeleton from '../../../components/PageSkeleton'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; @@ -13,17 +14,21 @@ const EditRolePageWithData = ({ roleId }: { roleId?: IRole['_id'] }): ReactEleme const { t } = useTranslation(); const role = useRole(roleId); const context = useRouteParameter('context'); - const hasCustomRolesModule = useHasLicenseModule('custom-roles'); + const { isPending, isError, data: hasLicense } = useHasLicenseModule('custom-roles'); if (!role && context === 'edit') { return {t('error-invalid-role')}; } - if (hasCustomRolesModule === 'loading') { + if (isPending) { return ; } - return ; + if (isError) { + return ; + } + + return ; }; export default EditRolePageWithData; diff --git a/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx b/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx index f2bec4375050a..64b9e7bc92890 100644 --- a/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx +++ b/apps/meteor/client/views/admin/permissions/PermissionsContextBar.tsx @@ -14,20 +14,24 @@ const PermissionsContextBar = (): ReactElement | null => { const context = useRouteParameter('context'); const router = useRoute('admin-permissions'); const setModal = useSetModal(); - const hasCustomRolesModule = useHasLicenseModule('custom-roles') === true; + const { isPending, data: hasCustomRolesModule = false } = useHasLicenseModule('custom-roles'); const handleCloseContextualbar = useEffectEvent(() => { router.push({}); }); useEffect(() => { + if (isPending) { + return; + } + if (context !== 'new' || hasCustomRolesModule) { return; } setModal( setModal(null)} />); handleCloseContextualbar(); - }, [context, hasCustomRolesModule, handleCloseContextualbar, setModal]); + }, [isPending, context, hasCustomRolesModule, handleCloseContextualbar, setModal]); return ( (context && ( diff --git a/apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx b/apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx index 61798ef3405c6..0137f2bd25782 100644 --- a/apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx +++ b/apps/meteor/client/views/admin/workspace/UsersUploadsCard/UsersUploadsCard.tsx @@ -26,7 +26,7 @@ const UsersUploadsCard = ({ statistics }: UsersUploadsCardProps): ReactElement = router.navigate('/admin/engagement'); }); - const canViewEngagement = useHasLicenseModule('engagement-dashboard'); + const { data: canViewEngagement = false } = useHasLicenseModule('engagement-dashboard'); return ( diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx index 6053429a21340..8d173ee601d9f 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppDetails/AppDetails.tsx @@ -41,7 +41,7 @@ const AppDetails = ({ app }: AppDetailsProps) => { const appAddon = installed ? installedAddon : addon; - const workspaceHasAddon = useHasLicenseModule(appAddon); + const { data: workspaceHasAddon = false } = useHasLicenseModule(appAddon); const openExternalLink = useExternalLink(); diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx index cb7d32c1f919c..998a865457c0c 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx @@ -43,7 +43,7 @@ const AppStatus = ({ app, showStatus = true, isAppDetailsPage, installed, ...pro const isEnterprise = data?.isEnterprise ?? false; const appAddon = app.addon; - const workspaceHasAddon = useHasLicenseModule(appAddon); + const { data: workspaceHasAddon = false } = useHasLicenseModule(appAddon); const statuses = appMultiStatusProps(app, isAppDetailsPage, context || '', isEnterprise); diff --git a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx index 3ac7d8781e511..ef2e693af381d 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx @@ -59,8 +59,8 @@ export const useAppMenu = (app: App, isAppDetailsPage: boolean) => { const { data } = useIsEnterprise(); const isEnterpriseLicense = !!data?.isEnterprise; - const workspaceHasMarketplaceAddon = useHasLicenseModule(app.addon); - const workspaceHasInstalledAddon = useHasLicenseModule(app.installedAddon); + const { data: workspaceHasMarketplaceAddon = false } = useHasLicenseModule(app.addon); + const { data: workspaceHasInstalledAddon = false } = useHasLicenseModule(app.installedAddon); const [isLoading, setLoading] = useState(false); const [requestedEndUser, setRequestedEndUser] = useState(app.requestedEndUser); diff --git a/apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx b/apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx index 8cbcaa450fa13..bf0ccfc56030e 100644 --- a/apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx +++ b/apps/meteor/client/views/navigation/sidepanel/omnichannel/tabs/SidepanelOnHold.tsx @@ -14,7 +14,7 @@ const SidePanelOnHold = () => { const rooms = useSidePanelRoomsListTab('onHold'); const [unreadOnly, toggleUnreadOnly] = useUnreadOnlyToggle(); - const hasEEModule = useHasLicenseModule('livechat-enterprise'); + const { data: hasEEModule = false } = useHasLicenseModule('livechat-enterprise'); useRedirectToDefaultTab(!hasEEModule); if (!hasEEModule) { diff --git a/apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx b/apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx index 876e7623980e2..f378047a30617 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/BusinessHoursMultiple.tsx @@ -14,7 +14,7 @@ const BusinessHoursMultiple = ({ className }: { className?: ComponentProps(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const enabledField = useId(); const nameField = useId(); diff --git a/apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx b/apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx index ab4e90b42aa05..2db2bb68ddc7e 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/ContactManagerInput.tsx @@ -7,7 +7,7 @@ type ContactManagerInputProps = { }; const ContactManagerInput = ({ value: userId, onChange }: ContactManagerInputProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx b/apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx index 8ae3396002247..e298f3cb3dbc4 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/CurrentChatTags.tsx @@ -11,7 +11,7 @@ type CurrentChatTagsProps = Pick }; const CurrentChatTags = ({ value, handler, department, viewAll, ...props }: CurrentChatTagsProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx b/apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx index 161f2be252133..47989729e5b7c 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/CustomFieldsAdditionalForm.tsx @@ -23,7 +23,7 @@ const CustomFieldsAdditionalForm = ({ className }: { className?: ComponentProps< watch, formState: { errors }, } = useFormContext(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const { visibility, type } = watch(); diff --git a/apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx b/apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx index a8d541bc1f647..91fb8311c5b35 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/DepartmentBusinessHours.tsx @@ -7,7 +7,7 @@ import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; export const DepartmentBusinessHours = ({ bhId }: { bhId: string | undefined }) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const getBusinessHour = useEndpoint('GET', '/v1/livechat/business-hour'); const { data } = useQuery({ queryKey: ['/v1/livechat/business-hour', bhId], diff --git a/apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx b/apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx index 2eb518a3fa72c..ff737ed0b11bb 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/EeNumberInput.tsx @@ -4,7 +4,7 @@ import type { ComponentProps } from 'react'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; export const EeNumberInput = ({ label, ...props }: { label: string } & ComponentProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx b/apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx index 23a3d401b6c3f..cabe5cc5a1574 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/EeTextAreaInput.tsx @@ -4,7 +4,7 @@ import type { ComponentProps } from 'react'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; export const EeTextAreaInput = ({ label, ...props }: { label: string } & ComponentProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx b/apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx index d5c746821964a..7e7a303e2ff50 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/EeTextInput.tsx @@ -4,7 +4,7 @@ import type { ComponentProps } from 'react'; import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; export const EeTextInput = ({ label, ...props }: { label: string } & ComponentProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx b/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx index efac2dd2b4dca..c65c14cd8e829 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgent.tsx @@ -9,7 +9,7 @@ import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; const MaxChatsPerAgent = ({ className }: { className?: ComponentProps['className'] }) => { const { t } = useTranslation(); const { control } = useFormContext(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const maxChatsField = useId(); diff --git a/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx b/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx index 0ad30bed45bf8..17f6f753185ab 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx @@ -5,7 +5,7 @@ import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; const MaxChatsPerAgentDisplay = ({ maxNumberSimultaneousChat = 0 }) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); if (!hasLicense) { return null; diff --git a/apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx b/apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx index 5ca41e5abdc03..872d58658af0a 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/PrioritiesSelect.tsx @@ -19,7 +19,7 @@ type PrioritiesSelectProps = { export const PrioritiesSelect = ({ value = '', label, options, onChange }: PrioritiesSelectProps) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const [sorting] = useState>({}); const formattedOptions = useMemo(() => { diff --git a/apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx b/apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx index a3b406c1ca24f..17adf7998d0e1 100644 --- a/apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx +++ b/apps/meteor/client/views/omnichannel/additionalForms/SlaPoliciesSelect.tsx @@ -13,7 +13,7 @@ type SlaPoliciesSelectProps = { }; export const SlaPoliciesSelect = ({ value, label, options, onChange }: SlaPoliciesSelectProps) => { - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const optionsSelect = useMemo(() => options?.map((option) => [option._id, option.name]), [options]); const fieldId = useId(); diff --git a/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx b/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx index b56c1fb67831b..9c0c058ac47d4 100644 --- a/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx +++ b/apps/meteor/client/views/omnichannel/appearance/AppearanceFieldLabel.tsx @@ -11,7 +11,7 @@ type AppearanceFieldLabelProps = ComponentProps & { const AppearanceFieldLabel = ({ children, premium = false, ...props }: AppearanceFieldLabelProps) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const shouldDisableEnterprise = premium && !hasLicense; if (!shouldDisableEnterprise) { diff --git a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx index 17f5c9ab666d2..6ef72ddf91b10 100644 --- a/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx +++ b/apps/meteor/client/views/omnichannel/appearance/AppearanceForm.tsx @@ -23,7 +23,7 @@ import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; const AppearanceForm = () => { const { t } = useTranslation(); - const isEnterprise = useHasLicenseModule('livechat-enterprise'); + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); const { control, watch } = useFormContext(); const { Livechat_enable_message_character_limit } = watch(); diff --git a/apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx b/apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx index 74b4591eb31ec..e868f0198ed32 100644 --- a/apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx +++ b/apps/meteor/client/views/omnichannel/components/OmnichannelVerificationTag.tsx @@ -10,7 +10,7 @@ type OmnichannelVerificationTagProps = { const OmnichannelVerificationTag = ({ verified, onClick }: OmnichannelVerificationTagProps) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const isVerified = hasLicense && verified; return ( diff --git a/apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx b/apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx index 261f6df39a043..cbb0a76a5577b 100644 --- a/apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx +++ b/apps/meteor/client/views/omnichannel/components/outboundMessage/components/OutboundMessageWizard/OutboundMessageWizard.tsx @@ -43,7 +43,7 @@ const OutboundMessageWizard = ({ defaultValues = {}, onSuccess, onError }: Outbo const hasOutboundModule = useHasLicenseModule('outbound-messaging'); const hasOutboundPermission = usePermission('outbound.send-messages'); - const isLoadingModule = hasOutboundModule === 'loading' || hasOmnichannelModule === 'loading'; + const isLoadingModule = hasOutboundModule.isPending || hasOmnichannelModule.isPending; const sendOutboundMessage = useEndpointMutation('POST', '/v1/omnichannel/outbound/providers/:id/message', { keys: { id: provider?.providerId || '' }, @@ -81,13 +81,13 @@ const OutboundMessageWizard = ({ defaultValues = {}, onSuccess, onError }: Outbo return; } - if (!hasOmnichannelModule || !hasOutboundModule || !hasProviders) { + if (!hasOmnichannelModule.data || !hasOutboundModule.data || !hasProviders) { upsellModal.open(); } - }, [hasOmnichannelModule, hasOutboundModule, hasProviders, isLoadingModule, isLoadingProviders, upsellModal]); + }, [hasOmnichannelModule.data, hasOutboundModule.data, hasProviders, isLoadingModule, isLoadingProviders, upsellModal]); const handleSubmit = useEffectEvent((values: SubmitPayload) => { - if (!hasOutboundModule) { + if (!hasOutboundModule.data) { upsellModal.open(); return; } diff --git a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts index b84d3c68acefd..683f727835af9 100644 --- a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts +++ b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.spec.ts @@ -1,4 +1,5 @@ import { usePermission } from '@rocket.chat/ui-contexts'; +import type { UseQueryResult } from '@tanstack/react-query'; import { renderHook } from '@testing-library/react'; import { useOutboundMessageAccess } from './useOutboundMessageAccess'; @@ -21,6 +22,35 @@ const usePermissionMock = jest.mocked(usePermission); const useOmnichannelEnabledMock = jest.mocked(useOmnichannelEnabled); const useHasLicenseModuleMock = jest.mocked(useHasLicenseModule); +// TODO: do not mock the hook itself, mock only its dependencies +const createSuccessfulQueryResult = (data: boolean): UseQueryResult => ({ + data, + error: null, + isPending: false, + isError: false, + isLoading: false, + isLoadingError: false, + isRefetchError: false, + isSuccess: true, + isPlaceholderData: false, + isFetched: true, + isFetchedAfterMount: true, + isFetching: false, + isInitialLoading: false, + isPaused: false, + isRefetching: false, + isStale: false, + status: 'success', + dataUpdatedAt: Date.now(), + errorUpdatedAt: Date.now(), + failureCount: 0, + failureReason: null, + errorUpdateCount: 0, + refetch: () => Promise.resolve(createSuccessfulQueryResult(data)), + fetchStatus: 'idle', + promise: Promise.resolve(data), +}); + describe('useOutboundMessageAccess', () => { beforeEach(() => { jest.clearAllMocks(); @@ -28,7 +58,7 @@ describe('useOutboundMessageAccess', () => { it('should return false if omnichannel is not enabled', () => { useOmnichannelEnabledMock.mockReturnValue(false); - useHasLicenseModuleMock.mockReturnValue(true); + useHasLicenseModuleMock.mockReturnValue(createSuccessfulQueryResult(true)); usePermissionMock.mockReturnValue(true); const { result } = renderHook(() => useOutboundMessageAccess()); @@ -37,7 +67,7 @@ describe('useOutboundMessageAccess', () => { it('should return true if omnichannel module is missing (upsell)', () => { useOmnichannelEnabledMock.mockReturnValue(true); - useHasLicenseModuleMock.mockImplementation((module) => module !== 'livechat-enterprise'); + useHasLicenseModuleMock.mockImplementation((module) => createSuccessfulQueryResult(module !== 'livechat-enterprise')); usePermissionMock.mockReturnValue(true); const { result } = renderHook(() => useOutboundMessageAccess()); @@ -46,7 +76,7 @@ describe('useOutboundMessageAccess', () => { it('should return true if outbound module is missing (upsell)', () => { useOmnichannelEnabledMock.mockReturnValue(true); - useHasLicenseModuleMock.mockImplementation((module) => module !== 'outbound-messaging'); + useHasLicenseModuleMock.mockImplementation((module) => createSuccessfulQueryResult(module !== 'outbound-messaging')); usePermissionMock.mockReturnValue(true); const { result } = renderHook(() => useOutboundMessageAccess()); @@ -55,7 +85,7 @@ describe('useOutboundMessageAccess', () => { it('should return true if both modules are missing (upsell)', () => { useOmnichannelEnabledMock.mockReturnValue(true); - useHasLicenseModuleMock.mockReturnValue(false); + useHasLicenseModuleMock.mockReturnValue(createSuccessfulQueryResult(false)); usePermissionMock.mockReturnValue(true); const { result } = renderHook(() => useOutboundMessageAccess()); @@ -64,7 +94,7 @@ describe('useOutboundMessageAccess', () => { it('should return true if all conditions are met and user has permission', () => { useOmnichannelEnabledMock.mockReturnValue(true); - useHasLicenseModuleMock.mockReturnValue(true); + useHasLicenseModuleMock.mockReturnValue(createSuccessfulQueryResult(true)); usePermissionMock.mockReturnValue(true); const { result } = renderHook(() => useOutboundMessageAccess()); @@ -73,7 +103,7 @@ describe('useOutboundMessageAccess', () => { it('should return false if all conditions are met but user does not have permission', () => { useOmnichannelEnabledMock.mockReturnValue(true); - useHasLicenseModuleMock.mockReturnValue(true); + useHasLicenseModuleMock.mockReturnValue(createSuccessfulQueryResult(true)); usePermissionMock.mockReturnValue(false); const { result } = renderHook(() => useOutboundMessageAccess()); diff --git a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts index 942a103b3df39..be08df8e674b4 100644 --- a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts +++ b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundMessageAccess.ts @@ -5,8 +5,8 @@ import { useOmnichannelEnabled } from '../../../hooks/useOmnichannelEnabled'; export const useOutboundMessageAccess = (): boolean => { const isOmnichannelEnabled = useOmnichannelEnabled(); - const hasOmnichannelModule = useHasLicenseModule('livechat-enterprise') === true; - const hasOutboundModule = useHasLicenseModule('outbound-messaging') === true; + const { data: hasOmnichannelModule = false } = useHasLicenseModule('livechat-enterprise'); + const { data: hasOutboundModule = false } = useHasLicenseModule('outbound-messaging'); const hasPermission = usePermission('outbound.send-messages'); if (!isOmnichannelEnabled) { diff --git a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts index 4bca4cab26a9c..083cdd1b5d888 100644 --- a/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts +++ b/apps/meteor/client/views/omnichannel/components/outboundMessage/hooks/useOutboundProvidersList.ts @@ -19,7 +19,7 @@ const useOutboundProvidersList = (options?: U const getProviders = useEndpoint('GET', '/v1/omnichannel/outbound/providers'); const isOmnichannelEnabled = useOmnichannelEnterpriseEnabled(); - const hasOutboundModule = useHasLicenseModule('outbound-messaging'); + const { data: hasOutboundModule = false } = useHasLicenseModule('outbound-messaging'); const canSendOutboundMessages = usePermission('outbound.send-messages'); return useQuery({ diff --git a/apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx b/apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx index 95fd3c7aca44b..42e92bf2248e6 100644 --- a/apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx +++ b/apps/meteor/client/views/omnichannel/components/outboundMessage/modals/OutboundMessageUpsellModal/useOutboundMessageUpsellModal.tsx @@ -10,7 +10,7 @@ export const useOutboundMessageUpsellModal = () => { const setModal = useSetModal(); const isAdmin = useRole('admin'); const license = useLicense(); - const hasModule = useHasLicenseModule('outbound-messaging') === true; + const { data: hasModule = false } = useHasLicenseModule('outbound-messaging'); const close = useEffectEvent(() => setModal(null)); const open = useEffectEvent(() => diff --git a/apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx b/apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx index 5e10d1ed68c29..03bd0328adb7c 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/AdvancedContactModal.tsx @@ -16,7 +16,7 @@ type AdvancedContactModalProps = { const AdvancedContactModal = ({ onCancel }: AdvancedContactModalProps) => { const { t } = useTranslation(); const isAdmin = useRole('admin'); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const { shouldShowUpsell, handleManageSubscription } = useUpsellActions(hasLicense); const openExternalLink = useExternalLink(); const eventStats = useEndpoint('POST', '/v1/statistics.telemetry'); diff --git a/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx b/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx index 53a0f46bc06d6..32a73bb7fbd87 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/ContactInfo/ReviewContactModal.tsx @@ -26,7 +26,7 @@ type HandleConflictsPayload = { const ReviewContactModal = ({ contact, onCancel }: ReviewContactModalProps) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const { control, diff --git a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx index 87e6a5bae9187..c9ca41a50f64a 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/EditContactInfo.tsx @@ -72,7 +72,7 @@ const EditContactInfo = ({ contactData, onClose, onCancel }: ContactNewEditProps const { t } = useTranslation(); const setModal = useSetModal(); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const canViewCustomFields = hasAtLeastOnePermission(['view-livechat-room-customfields', 'edit-livechat-room-customfields']); const editContact = useEditContact(['current-contacts']); diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx index a647c7782d548..90a208c4e209f 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoChannels/useBlockChannel.tsx @@ -12,7 +12,7 @@ export const useBlockChannel = ({ blocked, association }: { blocked: boolean; as const { t } = useTranslation(); const setModal = useSetModal(); const dispatchToastMessage = useToastMessageDispatch(); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const queryClient = useQueryClient(); const blockContact = useEndpoint('POST', '/v1/omnichannel/contacts.block'); diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx index a2b47f938387f..6746da49ba9fb 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistory.tsx @@ -28,7 +28,7 @@ const ContactInfoHistory = ({ contact, setChatId }: ContactInfoHistoryProps) => const setModal = useSetModal(); const [storedType, setStoredType] = useLocalStorage('contact-history-type', 'all'); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const type = isFilterBlocked(hasLicense, storedType) ? 'all' : storedType; const { getSourceName } = useOmnichannelSource(); diff --git a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx index 323ad1e837840..8d10b22005fc9 100644 --- a/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx +++ b/apps/meteor/client/views/omnichannel/contactInfo/tabs/ContactInfoHistory/ContactInfoHistoryItem.tsx @@ -30,7 +30,7 @@ const ContactInfoHistoryItem = ({ source, lastMessage, verified, onClick }: Cont const getTimeFromNow = useTimeFromNow(true); const setModal = useSetModal(); const preventPropagation = usePreventPropagation(); - const hasLicense = useHasLicenseModule('contact-id-verification') as boolean; + const { data: hasLicense = false } = useHasLicenseModule('contact-id-verification'); const { getSourceName } = useOmnichannelSource(); const customClass = css` diff --git a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx index f95fb09ca5ef1..07ea1422c0738 100644 --- a/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx +++ b/apps/meteor/client/views/omnichannel/departments/EditDepartment.tsx @@ -60,7 +60,7 @@ function EditDepartment({ data, id, title, allowedToForwardData }: EditDepartmen const { department, agents = [] } = data || {}; - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const canManageUnits = usePermission('manage-livechat-units'); const initialValues = getFormInitialValues({ department, agents, allowedToForwardData }); diff --git a/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx b/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx index 3532dc9c965d5..fb687d07f39cd 100644 --- a/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx +++ b/apps/meteor/client/views/omnichannel/directory/chats/ChatsFiltersContextualBar.tsx @@ -31,7 +31,7 @@ const ChatsFiltersContextualBar = ({ onClose }: ChatsFiltersContextualBarProps) const { t } = useTranslation(); const canViewLivechatRooms = usePermission('view-livechat-rooms'); const canViewCustomFields = usePermission('view-livechat-room-customfields'); - const isEnterprise = useHasLicenseModule('livechat-enterprise'); + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); const allCustomFields = useEndpoint('GET', '/v1/livechat/custom-fields'); const { data } = useQuery({ queryKey: ['livechat/custom-fields'], queryFn: async () => allCustomFields() }); diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx index 60d8c270d5dfa..5faca4f06dfc2 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaInfo.tsx @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import { useHasLicenseModule } from '../../../../hooks/useHasLicenseModule'; export const useSlaInfo = (slaId: string) => { - const isEnterprise = useHasLicenseModule('livechat-enterprise') === true; + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); const getSLA = useEndpoint('GET', '/v1/livechat/sla/:slaId', { slaId }); return useQuery({ queryKey: ['/v1/livechat/sla/:slaId', slaId], diff --git a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx index 4c05262c7a1a9..082efef23e1e0 100644 --- a/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx +++ b/apps/meteor/client/views/omnichannel/directory/hooks/useSlaPolicies.tsx @@ -5,7 +5,7 @@ import { millisecondsToMinutes } from 'date-fns'; import { useHasLicenseModule } from '../../../../hooks/useHasLicenseModule'; export const useSlaPolicies = () => { - const isEnterprise = useHasLicenseModule('livechat-enterprise') === true; + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); const getSlaPolicies = useEndpoint('GET', '/v1/livechat/sla'); const { data: { sla } = {}, ...props } = useQuery({ queryKey: ['/v1/livechat/sla'], diff --git a/apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts b/apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts index c2de0ef534ca1..20d6f8e353921 100644 --- a/apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts +++ b/apps/meteor/client/views/omnichannel/hooks/useCannedResponsesRoomAction.ts @@ -7,7 +7,7 @@ import type { RoomToolboxActionConfig } from '../../room/contexts/RoomToolboxCon const CannedResponse = lazy(() => import('../cannedResponses/contextualBar/CannedResponse/WrapCannedResponseList')); export const useCannedResponsesRoomAction = () => { - const licensed = useHasLicenseModule('canned-responses') === true; + const { data: licensed = false } = useHasLicenseModule('canned-responses'); const enabled = useSetting('Canned_Responses_Enable', false); return useMemo((): RoomToolboxActionConfig | undefined => { diff --git a/apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx b/apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx index 3c7eb4f640368..8d88307497bea 100644 --- a/apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx +++ b/apps/meteor/client/views/omnichannel/modals/CloseChatModal.tsx @@ -75,7 +75,7 @@ const CloseChatModal = ({ department, visitorEmail, onCancel, onConfirm }: Close const userTranscriptEmail = useUserPreference('omnichannelTranscriptEmail') ?? false; const userTranscriptPDF = useUserPreference('omnichannelTranscriptPDF') ?? false; - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const transcriptPDFPermission = usePermission('request-pdf-transcript'); const transcriptEmailPermission = usePermission('send-omnichannel-chat-transcript'); diff --git a/apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx b/apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx index d1a7d06a9985b..830f625fc76fd 100644 --- a/apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx +++ b/apps/meteor/client/views/omnichannel/monitors/MonitorsPageContainer.tsx @@ -4,13 +4,13 @@ import { useHasLicenseModule } from '../../../hooks/useHasLicenseModule'; import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const MonitorsPageContainer = () => { - const license = useHasLicenseModule('livechat-enterprise'); + const { isPending, data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); - if (license === 'loading') { + if (isPending) { return ; } - if (!license) { + if (!hasLicense) { return ; } diff --git a/apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx b/apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx index c4e9650a52f4e..a05b0577d416a 100644 --- a/apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx +++ b/apps/meteor/client/views/omnichannel/reports/ReportsPage.tsx @@ -13,7 +13,7 @@ const ReportsPage = () => { const { t } = useTranslation(); const hasPermission = usePermission('view-livechat-reports'); - const isEnterprise = useHasLicenseModule('livechat-enterprise'); + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); if (!hasPermission || !isEnterprise) { return ; diff --git a/apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx b/apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx index f4537e58f9eab..4894aa6625ec1 100644 --- a/apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/actions/ActionForm.tsx @@ -40,7 +40,7 @@ export const ActionForm = ({ control, trigger, index, ...props }: SendMessageFor const actionFieldName = `actions.${index}.name` as const; const actionFieldValue = useWatch({ control, name: actionFieldName }); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const actionOptions = useMemo(() => { return [ diff --git a/apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx b/apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx index 15f724fb3dbae..34e78602a4e48 100644 --- a/apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx +++ b/apps/meteor/client/views/omnichannel/triggers/actions/ExternalServiceActionForm.tsx @@ -19,7 +19,7 @@ type SendMessageActionFormType = ComponentProps & { export const ExternalServiceActionForm = ({ control, trigger, index, ...props }: SendMessageActionFormType) => { const { t } = useTranslation(); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const timeoutFieldId = useId(); const timeoutFieldName = `actions.${index}.params.serviceTimeout` as const; diff --git a/apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx b/apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx index f121242039499..b6d52f4d55739 100644 --- a/apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx +++ b/apps/meteor/client/views/omnichannel/units/UnitsRoute.tsx @@ -6,7 +6,7 @@ import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage'; const UnitsRoute = () => { const canViewUnits = usePermission('manage-livechat-units'); - const isEnterprise = useHasLicenseModule('livechat-enterprise'); + const { data: isEnterprise = false } = useHasLicenseModule('livechat-enterprise'); if (!(isEnterprise && canViewUnits)) { return ; diff --git a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx index 67bba30d71b4f..e3c734874253e 100644 --- a/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx +++ b/apps/meteor/client/views/room/Header/Omnichannel/QuickActions/hooks/useQuickActions.tsx @@ -310,7 +310,7 @@ export const useQuickActions = (): { const canMoveQueue = !!omnichannelRouteConfig?.returnQueue && room?.u !== undefined; const canForwardGuest = usePermission('transfer-livechat-guest'); const canSendTranscriptEmail = usePermission('send-omnichannel-chat-transcript'); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const canSendTranscriptPDF = usePermission('request-pdf-transcript'); const canCloseRoom = usePermission('close-livechat-room'); const canCloseOthersRoom = usePermission('close-others-livechat-room'); diff --git a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx index 9bb3a477543f6..f315b31ce3868 100644 --- a/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx +++ b/apps/meteor/client/views/room/HeaderV2/Omnichannel/QuickActions/hooks/useQuickActions.tsx @@ -308,7 +308,7 @@ export const useQuickActions = (): { const canMoveQueue = !!omnichannelRouteConfig?.returnQueue && room?.u !== undefined; const canForwardGuest = usePermission('transfer-livechat-guest'); const canSendTranscriptEmail = usePermission('send-omnichannel-chat-transcript'); - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); const canSendTranscriptPDF = usePermission('request-pdf-transcript'); const canCloseRoom = usePermission('close-livechat-room'); const canCloseOthersRoom = usePermission('close-others-livechat-room'); diff --git a/apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx b/apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx index ec75bdd4fa79b..4c13198f9d82a 100644 --- a/apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx +++ b/apps/meteor/client/views/room/composer/ComposerFederation/ComposerFederation.tsx @@ -9,7 +9,7 @@ import { useIsFederationEnabled } from '../../../../hooks/useIsFederationEnabled const ComposerFederation = ({ subscription, children, ...props }: ComposerMessageProps): ReactElement => { const federationEnabled = useIsFederationEnabled(); - const federationModuleEnabled = useHasLicenseModule('federation') === true; + const { data: federationModuleEnabled = false } = useHasLicenseModule('federation'); if (!federationEnabled) { return ; diff --git a/apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts b/apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts index 0e3763232d837..13ec6f603c449 100644 --- a/apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts +++ b/apps/meteor/client/views/root/hooks/useLivechatEnterprise.ts @@ -14,7 +14,7 @@ const businessHours: Record = { export const useLivechatEnterprise = () => { const businessHourType = useSetting('Livechat_business_hour_type') as string; - const hasLicense = useHasLicenseModule('livechat-enterprise'); + const { data: hasLicense = false } = useHasLicenseModule('livechat-enterprise'); useEffect(() => { if (businessHourType && hasLicense) {