diff --git a/apps/studio/components/layouts/ProjectLayout/index.test.tsx b/apps/studio/components/layouts/ProjectLayout/index.test.tsx index 8fb816cf310..08552fbe6e6 100644 --- a/apps/studio/components/layouts/ProjectLayout/index.test.tsx +++ b/apps/studio/components/layouts/ProjectLayout/index.test.tsx @@ -47,6 +47,12 @@ vi.mock('common', () => ({ mergeRefs: (..._refs: any[]) => (_value: unknown) => {}, + IS_PLATFORM: false, + LOCAL_STORAGE_KEYS: { + FREE_MICRO_UPGRADE_BANNER_DISMISSED: (ref: string) => + `free-micro-upgrade-banner-dismissed-${ref}`, + }, + isFeatureEnabled: () => false, })) vi.mock('framer-motion', () => ({ @@ -121,6 +127,27 @@ vi.mock('@/hooks/custom-content/useCustomContent', () => ({ useCustomContent: () => ({ appTitle: 'Supabase' }), })) +vi.mock('@/hooks/misc/useCheckEntitlements', () => ({ + useCheckEntitlements: () => ({ hasAccess: false, isLoading: false }), +})) + +vi.mock('@/hooks/misc/useLocalStorage', () => ({ + useLocalStorageQuery: () => [false, vi.fn()], +})) + +vi.mock('@/components/ui/BannerStack/BannerStackProvider', () => ({ + BANNER_ID: { FREE_MICRO_UPGRADE: 'free-micro-upgrade-banner' }, + useBannerStack: () => ({ addBanner: vi.fn(), dismissBanner: vi.fn(), banners: [] }), +})) + +vi.mock('@/components/ui/BannerStack/Banners/BannerFreeMicroUpgrade', () => ({ + BannerFreeMicroUpgrade: () => null, +})) + +vi.mock('data/usage/resource-warnings-query', () => ({ + useResourceWarningsQuery: () => ({ data: undefined }), +})) + vi.mock('@/hooks/misc/useSelectedOrganization', () => ({ useSelectedOrganizationQuery: () => ({ data: { name: 'Organization 1', slug: 'org-1' }, diff --git a/apps/studio/components/layouts/ProjectLayout/index.tsx b/apps/studio/components/layouts/ProjectLayout/index.tsx index fe87e4e12d3..170d63eeedb 100644 --- a/apps/studio/components/layouts/ProjectLayout/index.tsx +++ b/apps/studio/components/layouts/ProjectLayout/index.tsx @@ -1,4 +1,5 @@ -import { mergeRefs, useParams } from 'common' +import { LOCAL_STORAGE_KEYS, mergeRefs, useParams } from 'common' +import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { AnimatePresence, motion } from 'framer-motion' import Head from 'next/head' import { useRouter } from 'next/router' @@ -45,10 +46,8 @@ import { useCustomContent } from '@/hooks/custom-content/useCustomContent' import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements' import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' -import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { withAuth } from '@/hooks/misc/withAuth' -import { LOCAL_STORAGE_KEYS } from 'common' import { PROJECT_STATUS } from '@/lib/constants' import { buildStudioPageTitle } from '@/lib/page-title' import { getPathnameWithoutQuery } from '@/lib/pathname.utils' @@ -126,11 +125,11 @@ export const ProjectLayout = forwardRef { if (!selectedProject?.ref) return - if (isEligibleForFreeUpgrade && !isFreeMicroUpgradeBannerDismissed) { + if (showUpgradeBanner && !isFreeMicroUpgradeBannerDismissed) { addBanner({ id: BANNER_ID.FREE_MICRO_UPGRADE, isDismissed: false, @@ -192,7 +191,7 @@ export const ProjectLayout = forwardRef {
-

Free upgrade to Micro available

+

Your project is running low on resources

- Your Pro plan includes a free upgrade from Nano to Micro — double the memory at no extra - cost. + Your Nano compute is approaching its limits. Upgrade to Micro for free — it's included + in your Pro plan.

diff --git a/apps/studio/components/ui/ComputeBadgeWrapper.tsx b/apps/studio/components/ui/ComputeBadgeWrapper.tsx index 9294aa0162c..68f758615f3 100644 --- a/apps/studio/components/ui/ComputeBadgeWrapper.tsx +++ b/apps/studio/components/ui/ComputeBadgeWrapper.tsx @@ -106,30 +106,32 @@ export const ComputeBadgeWrapper = ({ const isEligibleForFreeUpgrade = !!data && data.plan.id !== 'free' && computeSize === 'nano' const isLoading = isLoadingAddons || isLoadingSubscriptions const isComputeNearExhaustion = - !!resourceWarnings?.cpu_exhaustion || !!resourceWarnings?.memory_and_swap_exhaustion - const hasUpgradeAvailable = (isFreeOnNano || isEligibleForFreeUpgrade) && isComputeNearExhaustion + !!resourceWarnings?.cpu_exhaustion || + !!resourceWarnings?.memory_and_swap_exhaustion || + !!resourceWarnings?.disk_space_exhaustion + const showUpgradeGlow = isEligibleForFreeUpgrade && isComputeNearExhaustion if (!computeSize) return null return ( setOpenState(!open)} openDelay={280}> e.stopPropagation()}> -
+
} + icon={showUpgradeGlow && } className={cn( - hasUpgradeAvailable && 'text-brand-600 border-brand-500 bg-brand/10 gap-1', + showUpgradeGlow && 'text-brand-600 border-brand-500 bg-brand/10 gap-1', badgeClassName )} /> - {hasUpgradeAvailable && ( + {showUpgradeGlow && ( )}
@@ -186,16 +188,20 @@ export const ComputeBadgeWrapper = ({

{isFreeOnNano ? 'Double your memory for free' - : isEligibleForFreeUpgrade - ? 'Free upgrade to Micro available' - : 'Unlock more compute'} + : isEligibleForFreeUpgrade && isComputeNearExhaustion + ? 'Your project is running low on resources' + : isEligibleForFreeUpgrade + ? 'Free upgrade to Micro available' + : 'Unlock more compute'}

{isFreeOnNano ? 'Upgrade to Pro and get a free Micro compute upgrade — double the memory at no extra cost.' - : isEligibleForFreeUpgrade - ? 'Your Pro plan includes a free upgrade from Nano to Micro compute.' - : 'Scale your project up to 64 cores and 256 GB RAM.'} + : isEligibleForFreeUpgrade && isComputeNearExhaustion + ? 'Your Nano compute is approaching its limits. Your Pro plan includes a free upgrade to Micro — double the memory at no extra cost.' + : isEligibleForFreeUpgrade + ? 'Your Pro plan includes a free upgrade from Nano to Micro compute.' + : 'Scale your project up to 64 cores and 256 GB RAM.'}