diff --git a/.changeset/brown-pants-press.md b/.changeset/brown-pants-press.md new file mode 100644 index 000000000000..54e3c140a489 --- /dev/null +++ b/.changeset/brown-pants-press.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": major +"@rocket.chat/i18n": major +--- + +feat: New tooltips to reflect changes in private apps diff --git a/apps/meteor/client/components/GenericResourceUsage/GenericResourceUsage.tsx b/apps/meteor/client/components/GenericResourceUsage/GenericResourceUsage.tsx index c226139b9489..8a5b5539c2cd 100644 --- a/apps/meteor/client/components/GenericResourceUsage/GenericResourceUsage.tsx +++ b/apps/meteor/client/components/GenericResourceUsage/GenericResourceUsage.tsx @@ -10,6 +10,7 @@ const GenericResourceUsage = ({ threshold = 80, variant = percentage < threshold ? 'success' : 'danger', subTitle, + tooltip, ...props }: { title: string; @@ -19,9 +20,20 @@ const GenericResourceUsage = ({ percentage: number; threshold?: number; variant?: 'warning' | 'danger' | 'success'; + tooltip?: string; }) => { return ( - + {title} {subTitle && {subTitle}} diff --git a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard.tsx b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard.tsx index 4bce3653838e..645151ded52a 100644 --- a/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard.tsx +++ b/apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard.tsx @@ -20,7 +20,7 @@ const AppsUsageCard = ({ privateAppsLimit, marketplaceAppsLimit }: AppsUsageCard const marketplaceAppsPercentage = Math.round((marketplaceAppsEnabled / marketplaceAppsLimitCount) * 100); const privateAppsEnabled = privateAppsLimit?.value || 0; - const privateAppsLimitCount = privateAppsLimit?.max || 3; + const privateAppsLimitCount = privateAppsLimit?.max || 0; const privateAppsPercentage = Math.round((privateAppsEnabled / privateAppsLimitCount) * 100); const card: CardProps = { @@ -43,6 +43,11 @@ const AppsUsageCard = ({ privateAppsLimit, marketplaceAppsLimit }: AppsUsageCard }), }; + const privateAppsDisabled = privateAppsLimitCount === 0; + const privateAppsTitle = privateAppsDisabled ? t('Private_apps_premium_message') : undefined; + const privateAppsVariant = privateAppsDisabled || (privateAppsPercentage || 0) >= 80 ? 'danger' : 'success'; + const privateAppsFontColor = privateAppsDisabled || (privateAppsPercentage || 0) >= 80 ? 'font-danger' : 'status-font-on-success'; + if (!privateAppsLimit || !marketplaceAppsLimit) { return ( @@ -63,15 +68,15 @@ const AppsUsageCard = ({ privateAppsLimit, marketplaceAppsLimit }: AppsUsageCard = 80 ? 'danger' : 'success'} /> - +
{t('Private_apps')}
- = 80 ? 'font-danger' : 'status-font-on-success'}> + {privateAppsEnabled} / {privateAppsLimitCount} - = 80 ? 'danger' : 'success'} /> +
); diff --git a/apps/meteor/client/views/marketplace/components/EnabledAppsCount.tsx b/apps/meteor/client/views/marketplace/components/EnabledAppsCount.tsx index 46e8bd64b55c..5ec240f99a8d 100644 --- a/apps/meteor/client/views/marketplace/components/EnabledAppsCount.tsx +++ b/apps/meteor/client/views/marketplace/components/EnabledAppsCount.tsx @@ -10,12 +10,14 @@ const EnabledAppsCount = ({ limit, enabled, context, + tooltip, }: { variant: 'warning' | 'danger' | 'success'; percentage: number; limit: number; enabled: number; context: 'private' | 'explore' | 'installed' | 'premium' | 'requested'; + tooltip?: string; }): ReactElement | null => { const { t } = useTranslation(); @@ -27,6 +29,7 @@ const EnabledAppsCount = ({ percentage={percentage} threshold={80} variant={variant} + tooltip={tooltip} /> ); }; diff --git a/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts b/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts index b23c19a2df40..ec4347a8caee 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts +++ b/apps/meteor/client/views/marketplace/hooks/useAppsCountQuery.ts @@ -1,14 +1,15 @@ import { useEndpoint } from '@rocket.chat/ui-contexts'; import { useQueryClient, useQuery } from '@tanstack/react-query'; import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; type Variant = 'success' | 'warning' | 'danger'; const getProgressBarValues = (numberOfEnabledApps: number, enabledAppsLimit: number): { variant: Variant; percentage: number } => ({ variant: 'success', ...(numberOfEnabledApps + 1 === enabledAppsLimit && { variant: 'warning' }), - ...(numberOfEnabledApps >= enabledAppsLimit && { variant: 'danger' }), - percentage: Math.round((numberOfEnabledApps / enabledAppsLimit) * 100), + ...((enabledAppsLimit === 0 || numberOfEnabledApps >= enabledAppsLimit) && { variant: 'danger' }), + percentage: Math.round(enabledAppsLimit === 0 ? 100 : (numberOfEnabledApps / enabledAppsLimit) * 100), }); export type MarketplaceRouteContext = 'private' | 'explore' | 'installed' | 'premium' | 'requested' | 'details'; @@ -19,6 +20,7 @@ export function isMarketplaceRouteContext(context: string): context is Marketpla export const useAppsCountQuery = (context: MarketplaceRouteContext) => { const getAppsCount = useEndpoint('GET', '/apps/count'); + const { t } = useTranslation(); return useQuery( ['apps/count', context], @@ -28,10 +30,12 @@ export const useAppsCountQuery = (context: MarketplaceRouteContext) => { const numberOfEnabledApps = context === 'private' ? data.totalPrivateEnabled : data.totalMarketplaceEnabled; const enabledAppsLimit = context === 'private' ? data.maxPrivateApps : data.maxMarketplaceApps; const hasUnlimitedApps = enabledAppsLimit === -1; + const tooltip = context === 'private' && enabledAppsLimit === 0 ? t('Private_apps_premium_message') : undefined; return { hasUnlimitedApps, enabled: numberOfEnabledApps, limit: enabledAppsLimit, + tooltip, ...getProgressBarValues(numberOfEnabledApps, enabledAppsLimit), }; }, diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index fa0d674383c0..cee5bfe4ed47 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -559,6 +559,7 @@ "Apps_Count_Enabled_other": "{{count}} apps enabled", "Private_Apps_Count_Enabled_one": "{{count}} private app enabled", "Private_Apps_Count_Enabled_other": "{{count}} private apps enabled", + "Private_apps_premium_message": "Private apps can only be enabled in premium plans", "Private_apps_upgrade_empty_state_title": "Upgrade to unlock private apps", "Private_apps_upgrade_empty_state_description": "Tailor Rocket.Chat according to your needs with private apps.", "Apps_Count_Enabled_tooltip": "Community workspaces can enable up to {{number}} {{context}} apps",