From 620ee49d4764808ce3cf0db417e83b8d0d0ca5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Sat, 3 Jun 2023 00:24:26 +0200 Subject: [PATCH] better no data handling --- .../interfaces/BillingV2/Usage/Activity.tsx | 34 ++++++--- .../interfaces/BillingV2/Usage/Bandwidth.tsx | 38 +++++++--- .../BillingV2/Usage/Infrastructure.tsx | 16 ++--- .../BillingV2/Usage/SizeAndCounts.tsx | 70 +++++++++++-------- .../interfaces/BillingV2/Usage/Usage.tsx | 20 +++--- .../interfaces/BillingV2/Usage/Usage.utils.ts | 18 ++++- 6 files changed, 124 insertions(+), 72 deletions(-) diff --git a/studio/components/interfaces/BillingV2/Usage/Activity.tsx b/studio/components/interfaces/BillingV2/Usage/Activity.tsx index 5437bdfec3e..68353e5ab38 100644 --- a/studio/components/interfaces/BillingV2/Usage/Activity.tsx +++ b/studio/components/interfaces/BillingV2/Usage/Activity.tsx @@ -2,7 +2,6 @@ import clsx from 'clsx' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import SparkBar from 'components/ui/SparkBar' import { useDailyStatsQuery } from 'data/analytics/daily-stats-query' -import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { ProjectUsageResponse, UsageMetric, @@ -16,10 +15,10 @@ import UsageBarChart from './UsageBarChart' import SectionContent from './SectionContent' import SectionHeader from './SectionHeader' import { USAGE_CATEGORIES } from './Usage.constants' -import { ChartYFormatterCompactNumber, getUpgradeUrl } from './Usage.utils' -import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' +import { ChartYFormatterCompactNumber, getUpgradeUrlFromV2Subscription } from './Usage.utils' import { DataPoint } from 'data/analytics/constants' import Panel from 'components/ui/Panel' +import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' export interface ActivityProps { projectRef: string @@ -27,8 +26,8 @@ export interface ActivityProps { const Activity = ({ projectRef }: ActivityProps) => { const { data: usage } = useProjectUsageQuery({ projectRef }) - const { data: subscription } = useProjectSubscriptionQuery({ projectRef }) - const { current_period_start, current_period_end } = subscription?.billing ?? {} + const { data: subscription } = useProjectSubscriptionV2Query({ projectRef }) + const { current_period_start, current_period_end } = subscription ?? {} const startDate = current_period_start !== undefined ? new Date(current_period_start * 1000).toISOString() @@ -53,11 +52,9 @@ const Activity = ({ projectRef }: ActivityProps) => { const categoryMeta = USAGE_CATEGORIES.find((category) => category.key === 'activity') - const upgradeUrl = getUpgradeUrl(projectRef, subscription) + const upgradeUrl = getUpgradeUrlFromV2Subscription(projectRef, subscription) - const isFreeTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.FREE - const isProTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.PRO - const usageBasedBilling = !isFreeTier && !isProTier + const usageBasedBilling = subscription?.usage_billing_enabled const exceededLimitStyle = !usageBasedBilling ? 'text-red-900' : 'text-amber-900' const { data: mauData, isLoading: isLoadingMauData } = useDailyStatsQuery({ @@ -168,6 +165,10 @@ const Activity = ({ projectRef }: ActivityProps) => { const chartData = chartMeta[attribute.key]?.data ?? [] + const notAllValuesZero = chartData.some( + (dataPoint) => Number(dataPoint[attribute.attribute]) !== 0 + ) + return (
@@ -227,7 +228,7 @@ const Activity = ({ projectRef }: ActivityProps) => {

- Included in {subscription?.tier.name.toLowerCase()} + Included in {subscription?.plan?.name.toLowerCase()} plan

{usageMeta?.limit === -1 ? (

None

@@ -270,7 +271,7 @@ const Activity = ({ projectRef }: ActivityProps) => {
- ) : ( + ) : chartData.length > 1 && notAllValuesZero ? ( { yLeftMargin={chartMeta[attribute.key].margin} yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)} /> + ) : ( + + +
+

No data

+

+ No {notAllValuesZero ? 'data' : 'usage'} in period +

+
+
+
)} ) : ( diff --git a/studio/components/interfaces/BillingV2/Usage/Bandwidth.tsx b/studio/components/interfaces/BillingV2/Usage/Bandwidth.tsx index 7470c72697e..088ea920036 100644 --- a/studio/components/interfaces/BillingV2/Usage/Bandwidth.tsx +++ b/studio/components/interfaces/BillingV2/Usage/Bandwidth.tsx @@ -3,7 +3,6 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import SparkBar from 'components/ui/SparkBar' import { DataPoint } from 'data/analytics/constants' import { useDailyStatsQuery } from 'data/analytics/daily-stats-query' -import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { ProjectUsageResponse, UsageMetric, @@ -17,8 +16,14 @@ import { Button, IconAlertTriangle } from 'ui' import SectionContent from './SectionContent' import SectionHeader from './SectionHeader' import { USAGE_CATEGORIES } from './Usage.constants' -import { ChartYFormatterCompactNumber, getUpgradeUrl } from './Usage.utils' +import { + ChartYFormatterCompactNumber, + getUpgradeUrl, + getUpgradeUrlFromV2Subscription, +} from './Usage.utils' import UsageBarChart from './UsageBarChart' +import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' +import Panel from 'components/ui/Panel' export interface BandwidthProps { projectRef: string @@ -26,8 +31,8 @@ export interface BandwidthProps { const Bandwidth = ({ projectRef }: BandwidthProps) => { const { data: usage } = useProjectUsageQuery({ projectRef }) - const { data: subscription } = useProjectSubscriptionQuery({ projectRef }) - const { current_period_start, current_period_end } = subscription?.billing ?? {} + const { data: subscription } = useProjectSubscriptionV2Query({ projectRef }) + const { current_period_start, current_period_end } = subscription ?? {} const startDate = current_period_start !== undefined ? new Date(current_period_start * 1000).toISOString() @@ -42,10 +47,8 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => { const categoryMeta = USAGE_CATEGORIES.find((category) => category.key === 'bandwidth') - const upgradeUrl = getUpgradeUrl(projectRef, subscription) - const isFreeTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.FREE - const isProTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.PRO - const usageBasedBilling = !isFreeTier && !isProTier + const upgradeUrl = getUpgradeUrlFromV2Subscription(projectRef, subscription) + const usageBasedBilling = subscription?.usage_billing_enabled const exceededLimitStyle = !usageBasedBilling ? 'text-red-900' : 'text-amber-900' const { data: dbEgressData, isLoading: isLoadingDbEgressData } = useDailyStatsQuery({ @@ -95,6 +98,10 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => { const chartData = chartMeta[attribute.key]?.data ?? [] + const notAllValuesZero = chartData.some( + (dataPoint) => Number(dataPoint[attribute.attribute]) !== 0 + ) + return (
@@ -148,7 +155,7 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {

- Included in {subscription?.tier.name.toLowerCase()} + Included in {subscription?.plan?.name.toLowerCase()} plan

{usageMeta?.limit === 0 ? 'Unlimited' : formatBytes(usageMeta?.limit ?? 0)} @@ -184,7 +191,7 @@ const Bandwidth = ({ projectRef }: BandwidthProps) => {

- ) : ( + ) : chartData.length > 1 && notAllValuesZero ? ( { yLeftMargin={chartMeta[attribute.key].margin} yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)} /> + ) : ( + + +
+

No data

+

+ No {notAllValuesZero ? 'data' : 'usage'} in period +

+
+
+
)}
diff --git a/studio/components/interfaces/BillingV2/Usage/Infrastructure.tsx b/studio/components/interfaces/BillingV2/Usage/Infrastructure.tsx index 1d7210d0d94..8ef35c0b8b0 100644 --- a/studio/components/interfaces/BillingV2/Usage/Infrastructure.tsx +++ b/studio/components/interfaces/BillingV2/Usage/Infrastructure.tsx @@ -1,7 +1,6 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { DataPoint } from 'data/analytics/constants' import { useInfraMonitoringQuery } from 'data/analytics/infra-monitoring-query' -import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import dayjs from 'dayjs' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import Link from 'next/link' @@ -9,9 +8,10 @@ import { Alert, Button } from 'ui' import SectionContent from './SectionContent' import SectionHeader from './SectionHeader' import { COMPUTE_INSTANCE_SPECS, USAGE_CATEGORIES } from './Usage.constants' -import { getUpgradeUrl } from './Usage.utils' +import { getUpgradeUrl, getUpgradeUrlFromV2Subscription } from './Usage.utils' import UsageBarChart from './UsageBarChart' import Panel from 'components/ui/Panel' +import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' export interface InfrastructureProps { projectRef: string @@ -20,8 +20,8 @@ export interface InfrastructureProps { // [Joshen] Need to update the IO budget chart to show burst mbps and duration next time const Infrastructure = ({ projectRef }: InfrastructureProps) => { - const { data: subscription } = useProjectSubscriptionQuery({ projectRef }) - const { current_period_start, current_period_end } = subscription?.billing ?? {} + const { data: subscription } = useProjectSubscriptionV2Query({ projectRef }) + const { current_period_start, current_period_end } = subscription ?? {} const startDate = current_period_start !== undefined ? new Date(current_period_start * 1000).toISOString() @@ -37,8 +37,8 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => { const categoryMeta = USAGE_CATEGORIES.find((category) => category.key === 'infra') - const upgradeUrl = getUpgradeUrl(projectRef, subscription) - const isFreeTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.FREE + const upgradeUrl = getUpgradeUrlFromV2Subscription(projectRef, subscription) + const isFreeTier = subscription?.plan?.id === 'free' const currentComputeInstance = subscription?.addons.find((addon) => addon.supabase_prod_id.includes('_instance_') ) @@ -249,9 +249,7 @@ const Infrastructure = ({ projectRef }: InfrastructureProps) => {

No data

-

- There is no data in the timeframe available -

+

There is no data in period

diff --git a/studio/components/interfaces/BillingV2/Usage/SizeAndCounts.tsx b/studio/components/interfaces/BillingV2/Usage/SizeAndCounts.tsx index 54b14e1bd94..dae39168258 100644 --- a/studio/components/interfaces/BillingV2/Usage/SizeAndCounts.tsx +++ b/studio/components/interfaces/BillingV2/Usage/SizeAndCounts.tsx @@ -2,14 +2,12 @@ import clsx from 'clsx' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import SparkBar from 'components/ui/SparkBar' import { useDailyStatsQuery } from 'data/analytics/daily-stats-query' -import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { ProjectUsageResponse, UsageMetric, useProjectUsageQuery, } from 'data/usage/project-usage-query' import dayjs from 'dayjs' -import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { formatBytes } from 'lib/helpers' import Link from 'next/link' import { Badge, Button, IconAlertTriangle, IconExternalLink } from 'ui' @@ -18,8 +16,10 @@ import UsageBarChart from './UsageBarChart' import SectionContent from './SectionContent' import SectionHeader from './SectionHeader' import { USAGE_CATEGORIES } from './Usage.constants' -import { ChartYFormatterCompactNumber, getUpgradeUrl } from './Usage.utils' +import { ChartYFormatterCompactNumber, getUpgradeUrlFromV2Subscription } from './Usage.utils' import { DataPoint } from 'data/analytics/constants' +import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' +import Panel from 'components/ui/Panel' export interface SizeAndCountsProps { projectRef: string @@ -27,8 +27,8 @@ export interface SizeAndCountsProps { const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => { const { data: usage } = useProjectUsageQuery({ projectRef }) - const { data: subscription } = useProjectSubscriptionQuery({ projectRef }) - const { current_period_start, current_period_end } = subscription?.billing ?? {} + const { data: subscription } = useProjectSubscriptionV2Query({ projectRef }) + const { current_period_start, current_period_end } = subscription ?? {} const startDate = current_period_start !== undefined ? new Date(current_period_start * 1000).toISOString() @@ -43,10 +43,8 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => { const categoryMeta = USAGE_CATEGORIES.find((category) => category.key === 'sizeCount') - const upgradeUrl = getUpgradeUrl(projectRef, subscription) - const isFreeTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.FREE - const isProTier = subscription?.tier.supabase_prod_id === PRICING_TIER_PRODUCT_IDS.PRO - const usageBasedBilling = !isFreeTier && !isProTier + const upgradeUrl = getUpgradeUrlFromV2Subscription(projectRef, subscription) + const usageBasedBilling = subscription?.usage_billing_enabled const exceededLimitStyle = !usageBasedBilling ? 'text-red-900' : 'text-amber-900' const { data: dbSizeData, isLoading: isLoadingDbSizeData } = useDailyStatsQuery({ @@ -110,6 +108,10 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => { const chartData = chartMeta[attribute.key]?.data ?? [] + const notAllValuesZero = chartData.some( + (dataPoint) => Number(dataPoint[attribute.attribute]) !== 0 + ) + return (
@@ -164,7 +166,7 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {

- Included in {subscription?.tier.name.toLowerCase()} + Included in {subscription?.plan?.name.toLowerCase()} plan

{attribute.unit === 'bytes' @@ -199,25 +201,24 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {

- {attribute.key === 'db_size' && - subscription?.tier.supabase_prod_id !== PRICING_TIER_PRODUCT_IDS.FREE && ( -
-
-

Disk size:

-

{usage?.disk_volume_size_gb} GB

- - Auto-scaling - -
- - - - - + {attribute.key === 'db_size' && subscription?.plan?.id !== 'free' && ( +
+
+

Disk size:

+

{usage?.disk_volume_size_gb} GB

+ + Auto-scaling +
- )} + + + + + +
+ )}

@@ -236,7 +237,7 @@ const SizeAndCounts = ({ projectRef }: SizeAndCountsProps) => {

- ) : ( + ) : chartData.length > 1 && notAllValuesZero ? ( { yLeftMargin={chartMeta[attribute.key].margin} yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)} /> + ) : ( + + +
+

No data

+

+ No {notAllValuesZero ? 'data' : 'usage'} in period +

+
+
+
)}
diff --git a/studio/components/interfaces/BillingV2/Usage/Usage.tsx b/studio/components/interfaces/BillingV2/Usage/Usage.tsx index d96a78e9292..45de5f1f433 100644 --- a/studio/components/interfaces/BillingV2/Usage/Usage.tsx +++ b/studio/components/interfaces/BillingV2/Usage/Usage.tsx @@ -1,11 +1,10 @@ import clsx from 'clsx' import { useParams } from 'common' -import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { useProjectUsageQuery } from 'data/usage/project-usage-query' import dayjs from 'dayjs' import Link from 'next/link' import { useRef, useState } from 'react' -import { Button, IconAlertCircle, IconCheckCircle, IconLoader, Listbox } from 'ui' +import { Button, IconAlertCircle, IconLoader, Listbox } from 'ui' import Activity from './Activity' import Bandwidth from './Bandwidth' import Infrastructure from './Infrastructure' @@ -13,7 +12,7 @@ import SizeAndCounts from './SizeAndCounts' import { USAGE_CATEGORIES, USAGE_STATUS } from './Usage.constants' import { getUsageStatus } from './Usage.utils' import { useInfraMonitoringQuery } from 'data/analytics/infra-monitoring-query' -import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' +import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' const Usage = () => { const { ref } = useParams() @@ -28,11 +27,11 @@ const Usage = () => { const activityRef = useRef(null) const { data: usage } = useProjectUsageQuery({ projectRef: ref }) - const { data: subscription, isLoading: isLoadingSubscription } = useProjectSubscriptionQuery({ + const { data: subscription, isLoading: isLoadingSubscription } = useProjectSubscriptionV2Query({ projectRef: selectedProjectRef, }) - const { current_period_start, current_period_end } = subscription?.billing ?? {} + const { current_period_start, current_period_end } = subscription ?? {} const startDate = current_period_start !== undefined ? new Date(current_period_start * 1000).toISOString() @@ -52,13 +51,10 @@ const Usage = () => { ] ?? 100 ) - const billingCycleStart = dayjs.unix(subscription?.billing?.current_period_start ?? 0).utc() - const billingCycleEnd = dayjs.unix(subscription?.billing?.current_period_end ?? 0).utc() + const billingCycleStart = dayjs.unix(subscription?.current_period_start ?? 0).utc() + const billingCycleEnd = dayjs.unix(subscription?.current_period_end ?? 0).utc() - const subscriptionTierId = subscription?.tier?.supabase_prod_id - const usageBillingEnabled = - subscriptionTierId !== PRICING_TIER_PRODUCT_IDS.FREE && - subscriptionTierId !== PRICING_TIER_PRODUCT_IDS.PRO + const usageBillingEnabled = subscription?.usage_billing_enabled const scrollTo = (id: 'infra' | 'bandwidth' | 'sizeCount' | 'activity') => { switch (id) { @@ -107,7 +103,7 @@ const Usage = () => { ) : subscription !== undefined ? (

- Project is on {subscription.tier.name} + Project is on {subscription.plan.name} plan

{billingCycleStart.format('DD MMM YYYY')} -{' '} diff --git a/studio/components/interfaces/BillingV2/Usage/Usage.utils.ts b/studio/components/interfaces/BillingV2/Usage/Usage.utils.ts index 99f6092748f..11e35b9331d 100644 --- a/studio/components/interfaces/BillingV2/Usage/Usage.utils.ts +++ b/studio/components/interfaces/BillingV2/Usage/Usage.utils.ts @@ -5,6 +5,7 @@ import { CategoryAttribute, USAGE_STATUS } from './Usage.constants' import { StripeSubscription } from 'components/interfaces/Billing' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { formatBytes } from 'lib/helpers' +import { ProjectSubscriptionResponse } from 'data/subscriptions/project-subscription-v2-query' // [Joshen] This is just for development to generate some test data for chart rendering export const generateUsageData = (attribute: string, days: number): DataPoint[] => { @@ -48,6 +49,21 @@ export const getUpgradeUrl = (projectRef: string, subscription?: StripeSubscript : `/project/${projectRef}/settings/billing/update/pro` } +export const getUpgradeUrlFromV2Subscription = ( + projectRef: string, + subscription?: ProjectSubscriptionResponse +) => { + if (!subscription) return `/project/${projectRef}/settings/billing/update` + + return subscription?.plan.id === 'enterprise' + ? `/project/${projectRef}/settings/billing/update/enterprise` + : subscription?.plan.id === 'team' + ? `/project/${projectRef}/settings/billing/update/team` + : subscription?.plan.id === 'free' + ? `/project/${projectRef}/settings/billing/update` + : `/project/${projectRef}/settings/billing/update/pro` +} + const compactNumberFormatter = new Intl.NumberFormat('en-US', { notation: 'compact', compactDisplay: 'short', @@ -58,7 +74,7 @@ export const ChartYFormatterCompactNumber = (number: number | string, unit: stri if (unit === 'bytes') { const formattedBytes = formatBytes(number, 0).replace(/\s/g, '') - + return formattedBytes === '0bytes' ? '0' : formattedBytes } else { return compactNumberFormatter.format(number)