DatabaseSizeUsage.tsx160 lines · main
1import Link from 'next/link'
2import { useMemo } from 'react'
3import { Alert, AlertDescription, AlertTitle, Button, CriticalIcon } from 'ui'
4import { InfoTooltip } from 'ui-patterns/info-tooltip'
5
6import { SectionContent } from '../SectionContent'
7import { CategoryAttribute } from '../Usage.constants'
8import Panel from '@/components/ui/Panel'
9import { PricingMetric } from '@/data/analytics/org-daily-stats-query'
10import type { OrgSubscription } from '@/data/subscriptions/types'
11import { OrgUsageResponse } from '@/data/usage/org-usage-query'
12import { formatBytes } from '@/lib/helpers'
13
14export interface DatabaseSizeUsageProps {
15 slug: string
16 projectRef?: string | null
17 attribute: CategoryAttribute
18 subscription?: OrgSubscription
19 usage?: OrgUsageResponse
20
21 currentBillingCycleSelected: boolean
22}
23
24const DatabaseSizeUsage = ({
25 attribute,
26 subscription,
27 usage,
28 currentBillingCycleSelected,
29}: DatabaseSizeUsageProps) => {
30 const databaseSizeUsage = useMemo(
31 () => usage?.usages.find((it) => it.metric === PricingMetric.DATABASE_SIZE),
32 [usage]
33 )
34
35 const hasProjectsExceedingDatabaseSize = useMemo(() => {
36 return databaseSizeUsage?.project_allocations.some((it) => it.usage > 0.5 * 1e9)
37 }, [databaseSizeUsage])
38
39 return (
40 <div id={attribute.anchor} className="scroll-my-12">
41 <SectionContent section={attribute}>
42 <div className="space-y-4">
43 {currentBillingCycleSelected && hasProjectsExceedingDatabaseSize && (
44 <Alert variant="warning">
45 <CriticalIcon />
46 <AlertTitle>Projects exceeding quota</AlertTitle>
47 <AlertDescription>
48 You have projects that are exceeding 0.5 GB of database size. Reduce the database
49 size or upgrade to a paid plan.
50 </AlertDescription>
51 </Alert>
52 )}
53
54 <div>
55 <div className="flex items-center justify-between">
56 <div className="flex items-center space-x-4">
57 <p className="text-sm">{attribute.name} usage</p>
58 </div>
59 </div>
60
61 {subscription?.plan.id !== 'platform' && (
62 <>
63 <div className="flex items-center justify-between border-b py-1">
64 <p className="text-xs text-foreground-light">
65 Included in {subscription?.plan?.name} Plan
66 </p>
67 <p className="text-xs">0.5 GB per project</p>
68 </div>
69
70 <div className="flex items-center justify-between">
71 <p className="text-xs text-foreground-light">Max database size</p>
72 <p className="text-xs">
73 {databaseSizeUsage?.usage
74 ? formatBytes(databaseSizeUsage?.usage_original)
75 : '-'}
76 </p>
77 </div>
78 </>
79 )}
80 </div>
81
82 {currentBillingCycleSelected && subscription?.plan.id !== 'platform' ? (
83 <div className="space-y-4">
84 <div className="space-y-1">
85 <p className="text-sm">Current database size per project</p>
86 </div>
87
88 {databaseSizeUsage?.project_allocations.length === 0 && (
89 <Panel>
90 <Panel.Content>
91 <div className="flex flex-col items-center justify-center">
92 <p className="text-sm">No active projects</p>
93 <p className="text-sm text-foreground-light">
94 You don't have any active projects in this organization.
95 </p>
96 </div>
97 </Panel.Content>
98 </Panel>
99 )}
100
101 {databaseSizeUsage?.project_allocations.map((project, idx) => {
102 return (
103 <div
104 key={`usage-project-${project.ref}`}
105 className={
106 idx !== databaseSizeUsage.project_allocations.length - 1
107 ? 'border-b pb-2'
108 : ''
109 }
110 >
111 <div className="flex justify-between">
112 <span className="text-foreground-light flex items-center gap-2">
113 {project.name}
114 </span>
115 <Button asChild type="default" size={'tiny'}>
116 <Link
117 href={`/project/${project.ref}/observability/database#database-size-report`}
118 >
119 Manage Database Size
120 </Link>
121 </Button>
122 </div>
123 <div className="flex flex-col gap-2">
124 <div className="flex items-center h-6 gap-3">
125 <span className="text-foreground-light text-sm font-mono flex items-center gap-2">
126 <span className="text-foreground font-semibold font-mono mt-[-2px]">
127 {formatBytes(project.usage)}
128 </span>{' '}
129 Database Size
130 </span>
131 <InfoTooltip side="top">
132 <p>
133 {formatBytes(project.usage)} GB database size as reported by Postgres.
134 </p>
135 </InfoTooltip>
136 </div>
137 </div>
138 </div>
139 )
140 })}
141 </div>
142 ) : (
143 <Panel>
144 <Panel.Content>
145 <div className="flex flex-col items-center justify-center">
146 <p className="text-sm">Data not available</p>
147 <p className="text-sm text-foreground-light">
148 Switch to current billing cycle to see current database size per project.
149 </p>
150 </div>
151 </Panel.Content>
152 </Panel>
153 )}
154 </div>
155 </SectionContent>
156 </div>
157 )
158}
159
160export default DatabaseSizeUsage