chore(usage): add Realtime docs, improve timeframes, upsell

This commit is contained in:
Kevin Grüneberg committed 2023-06-09 12:31:18 +02:00
1 parent b7dabb368d
commit 2fc053d323
2 files changed
+199 -154

No files matched your search

@@ -243,6 +243,12 @@ export const USAGE_CATEGORIES: CategoryMeta[] = [
description:
"Count of messages going through Realtime.\nUsage example: If you do a database change and 5 clients listen to that change via Realtime, that's 5 messages. If you broadcast a message and 4 clients listen to that, that's 5 messages (1 message sent, 4 received).\nBilling is based on the total amount of messages throughout your billing period.",
chartDescription: 'The data refreshes every 24 hours.',
links: [
{
name: 'Realtime Rate Limits',
url: 'https://supabase.com/docs/guides/realtime/rate-limits',
},
],
},
{
anchor: 'realtimePeakConnection',
@@ -254,6 +260,12 @@ export const USAGE_CATEGORIES: CategoryMeta[] = [
description:
'Total number of successful connections. Connections attempts are not counted towards usage.\nBilling is based on the maximum amount of concurrent peak connections throughout your billing period.',
chartDescription: 'The data refreshes every 24 hours.',
links: [
{
name: 'Realtime Rate Limits',
url: 'https://supabase.com/docs/guides/realtime/rate-limits',
},
],
},
],
},
@@ -68,166 +68,199 @@ const UsageSection = ({
return (
<div id={attribute.anchor} key={attribute.key}>
<SectionContent section={attribute}>
<div className="space-y-2">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<p className="text-sm">{attribute.name} usage</p>
{currentBillingCycleSelected &&
usageBasedBilling === false &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<Tooltip.Root delayDuration={0}>
<Tooltip.Trigger asChild>
{!usageBasedBilling && usageRatio >= 1 ? (
<div className="flex items-center space-x-2 min-w-[115px] cursor-help">
<IconAlertTriangle
size={14}
strokeWidth={2}
className={exceededLimitStyle}
/>
<p className={`text-sm ${exceededLimitStyle}`}>Exceeded limit</p>
</div>
) : (
!usageBasedBilling &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<div className="flex items-center space-x-2 min-w-[115px] cursor-help">
<IconAlertTriangle
size={14}
strokeWidth={2}
className="text-amber-900"
/>
<p className="text-sm text-amber-900">Approaching limit</p>
</div>
)
)}
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content side="bottom">
<Tooltip.Arrow className="radix-tooltip-arrow" />
<div
className={[
'rounded bg-scale-100 py-1 px-2 leading-none shadow',
'border border-scale-200',
].join(' ')}
>
<p className="text-xs text-scale-1200">
Exceeding your plans included usage will lead to restrictions to
your project.
</p>
<p className="text-xs text-scale-1200">
Upgrade to a usage-based plan or disable the spend cap to avoid
restrictions.
</p>
</div>
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
)}
</div>
{usageMeta?.available_in_plan ? (
<>
<div className="space-y-2">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<p className="text-sm">{attribute.name} usage</p>
{currentBillingCycleSelected &&
usageBasedBilling === false &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<Tooltip.Root delayDuration={0}>
<Tooltip.Trigger asChild>
{!usageBasedBilling && usageRatio >= 1 ? (
<div className="flex items-center space-x-2 min-w-[115px] cursor-help">
<IconAlertTriangle
size={14}
strokeWidth={2}
className={exceededLimitStyle}
/>
<p className={`text-sm ${exceededLimitStyle}`}>
Exceeded limit
</p>
</div>
) : (
!usageBasedBilling &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<div className="flex items-center space-x-2 min-w-[115px] cursor-help">
<IconAlertTriangle
size={14}
strokeWidth={2}
className="text-amber-900"
/>
<p className="text-sm text-amber-900">Approaching limit</p>
</div>
)
)}
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content side="bottom">
<Tooltip.Arrow className="radix-tooltip-arrow" />
<div
className={[
'rounded bg-scale-100 py-1 px-2 leading-none shadow',
'border border-scale-200',
].join(' ')}
>
<p className="text-xs text-scale-1200">
Exceeding your plans included usage will lead to restrictions
to your project.
</p>
<p className="text-xs text-scale-1200">
Upgrade to a usage-based plan or disable the spend cap to
avoid restrictions.
</p>
</div>
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
)}
</div>
{currentBillingCycleSelected &&
!usageBasedBilling &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<Link href={upgradeUrl}>
<a className="pb-1">
<Button type="default" size="tiny">
{subscription?.plan?.id === 'free'
? 'Upgrade plan'
: 'Change spend cap'}
</Button>
</a>
</Link>
)}
</div>
{currentBillingCycleSelected && usageMeta?.limit > 0 && (
<SparkBar
type="horizontal"
barClass={clsx(
usageRatio >= 1
? usageBasedBilling
? 'bg-amber-900'
: 'bg-red-900'
: usageBasedBilling === false && usageRatio >= USAGE_APPROACHING_THRESHOLD
? 'bg-amber-900'
: 'bg-scale-1100'
)}
bgClass="bg-gray-300 dark:bg-gray-600"
value={usageMeta?.usage ?? 0}
max={usageMeta?.limit || 1}
/>
)}
<div>
<div className="flex items-center justify-between border-b py-1">
<p className="text-xs text-scale-1000">
Included in {subscription?.plan?.name.toLowerCase()} plan
</p>
<p className="text-xs">
{attribute.unit === 'bytes'
? formatBytes(usageMeta?.limit ?? 0)
: (usageMeta?.limit ?? 0).toLocaleString()}
</p>
</div>
<div className="flex items-center justify-between py-1">
<p className="text-xs text-scale-1000">
{attribute.chartPrefix || 'Used '}in period
</p>
<p className="text-xs">
{attribute.unit === 'bytes'
? formatBytes(usageMeta?.usage ?? 0)
: (usageMeta?.usage ?? 0).toLocaleString()}
</p>
</div>
{currentBillingCycleSelected && usageMeta?.limit > 0 && (
<div className="flex items-center justify-between border-t py-1">
<p className="text-xs text-scale-1000">Overage in period</p>
<p className="text-xs">
{usageExcess < 0
? attribute.unit === 'bytes'
? formatBytes(0)
: 0
: attribute.unit === 'bytes'
? formatBytes(usageExcess)
: usageExcess.toLocaleString()}
</p>
{currentBillingCycleSelected &&
!usageBasedBilling &&
usageRatio >= USAGE_APPROACHING_THRESHOLD && (
<Link href={upgradeUrl}>
<a className="pb-1">
<Button type="default" size="tiny">
{subscription?.plan?.id === 'free'
? 'Upgrade plan'
: 'Change spend cap'}
</Button>
</a>
</Link>
)}
</div>
{currentBillingCycleSelected && usageMeta?.limit > 0 && (
<SparkBar
type="horizontal"
barClass={clsx(
usageRatio >= 1
? usageBasedBilling
? 'bg-amber-900'
: 'bg-red-900'
: usageBasedBilling === false &&
usageRatio >= USAGE_APPROACHING_THRESHOLD
? 'bg-amber-900'
: 'bg-scale-1100'
)}
bgClass="bg-gray-300 dark:bg-gray-600"
value={usageMeta?.usage ?? 0}
max={usageMeta?.limit || 1}
/>
)}
<div>
<div className="flex items-center justify-between border-b py-1">
<p className="text-xs text-scale-1000">
Included in {subscription?.plan?.name.toLowerCase()} plan
</p>
{usageMeta?.limit === -1 ? (
<p className="text-xs">None</p>
) : usageMeta?.limit === 0 ? (
<p className="text-xs">Unlimited</p>
) : (
<p className="text-xs">
{attribute.unit === 'bytes'
? formatBytes(usageMeta?.limit ?? 0)
: (usageMeta?.limit ?? 0).toLocaleString()}
</p>
)}
</div>
{currentBillingCycleSelected && (
<div className="flex items-center justify-between py-1">
<p className="text-xs text-scale-1000">
{attribute.chartPrefix || 'Used '}in period
</p>
<p className="text-xs">
{attribute.unit === 'bytes'
? formatBytes(usageMeta?.usage ?? 0)
: (usageMeta?.usage ?? 0).toLocaleString()}
</p>
</div>
)}
{currentBillingCycleSelected && usageMeta?.limit > 0 && (
<div className="flex items-center justify-between border-t py-1">
<p className="text-xs text-scale-1000">Overage in period</p>
<p className="text-xs">
{(usageMeta?.limit ?? 0) === -1 || usageExcess < 0
? 0
: attribute.unit === 'bytes'
? formatBytes(usageExcess)
: usageExcess.toLocaleString()}
</p>
</div>
)}
</div>
</div>
{attribute.additionalInfo?.(subscription, usage)}
<div className="space-y-1">
<p>
{attribute.chartPrefix || ''}
{attribute.name} per day
</p>
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
<p key={`para-${idx}`} className="text-sm text-scale-1000">
{paragraph}
</p>
))}
</div>
{chartMeta[attribute.key].isLoading ? (
<div className="space-y-2">
<ShimmeringLoader />
<ShimmeringLoader className="w-3/4" />
<ShimmeringLoader className="w-1/2" />
</div>
) : chartData.length > 0 && notAllValuesZero ? (
<UsageBarChart
name={`${attribute.chartPrefix || ''}${attribute.name}`}
unit={attribute.unit}
attribute={attribute.attribute}
data={chartData}
yLeftMargin={chartMeta[attribute.key].margin}
yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)}
/>
) : (
<Panel>
<Panel.Content>
<div className="flex flex-col items-center justify-center">
<IconBarChart2 className="text-scale-1100 mb-2" />
<p className="text-sm">No data in period</p>
<p className="text-sm text-scale-1000">May take up to 24 hours to show</p>
</div>
</Panel.Content>
</Panel>
)}
</div>
</div>
{attribute.additionalInfo?.(subscription, usage)}
<div className="space-y-1">
<p>
{attribute.chartPrefix || ''}
{attribute.name} per day
</p>
{attribute.chartDescription.split('\n').map((paragraph, idx) => (
<p key={`para-${idx}`} className="text-sm text-scale-1000">
{paragraph}
</p>
))}
</div>
{chartMeta[attribute.key].isLoading ? (
<div className="space-y-2">
<ShimmeringLoader />
<ShimmeringLoader className="w-3/4" />
<ShimmeringLoader className="w-1/2" />
</div>
) : chartData.length > 0 && notAllValuesZero ? (
<UsageBarChart
name={`${attribute.chartPrefix || ''}${attribute.name}`}
unit={attribute.unit}
attribute={attribute.attribute}
data={chartData}
yLeftMargin={chartMeta[attribute.key].margin}
yFormatter={(value) => ChartYFormatterCompactNumber(value, attribute.unit)}
/>
</>
) : (
<Panel>
<Panel.Content>
<div className="flex flex-col items-center justify-center">
<IconBarChart2 className="text-scale-1100 mb-2" />
<p className="text-sm">No data in period</p>
<p className="text-sm text-scale-1000">May take up to 24 hours to show</p>
<div className="flex w-full items-center flex-col justify-center space-y-2 md:flex-row md:justify-between">
<div className="space-y-1">
<p className="text-sm">Not included in plan</p>
<div>
<p className="text-sm text-scale-1100">
You need to be on a higher plan in order to use this feature.
</p>
</div>
</div>
<Link href={`/project/${projectRef}/settings/billing/subscription`}>
<a>
<Button type="primary">Upgrade plan</Button>
</a>
</Link>
</div>
</Panel.Content>
</Panel>