DiskSizeConfiguration.tsx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { PermissionAction } from '@supabase/shared-types/out/constants'
  2. import { useParams } from 'common'
  3. import { ExternalLink, Info } from 'lucide-react'
  4. import Link from 'next/link'
  5. import { SetStateAction } from 'react'
  6. import { toast } from 'sonner'
  7. import { Alert, AlertDescription, AlertTitle, Button, InfoIcon } from 'ui'
  8. import {
  9. PageSection,
  10. PageSectionContent,
  11. PageSectionMeta,
  12. PageSectionSummary,
  13. PageSectionTitle,
  14. } from 'ui-patterns'
  15. import { Markdown } from '@/components/interfaces/Markdown'
  16. import DiskSizeConfigurationModal from '@/components/interfaces/Settings/Database/DiskSizeConfigurationModal'
  17. import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
  18. import { DocsButton } from '@/components/ui/DocsButton'
  19. import Panel from '@/components/ui/Panel'
  20. import { useProjectDiskResizeMutation } from '@/data/config/project-disk-resize-mutation'
  21. import { useDatabaseSizeQuery } from '@/data/database/database-size-query'
  22. import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
  23. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  24. import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
  25. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  26. import {
  27. useIsAwsNimbusCloudProvider,
  28. useSelectedProjectQuery,
  29. } from '@/hooks/misc/useSelectedProject'
  30. import { useUrlState } from '@/hooks/ui/useUrlState'
  31. import { DOCS_URL } from '@/lib/constants'
  32. import { formatBytes } from '@/lib/helpers'
  33. export interface DiskSizeConfigurationProps {
  34. disabled?: boolean
  35. }
  36. export const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfigurationProps) => {
  37. const { ref: projectRef } = useParams()
  38. const { data: project } = useSelectedProjectQuery()
  39. const { data: organization } = useSelectedOrganizationQuery()
  40. const isAwsNimbus = useIsAwsNimbusCloudProvider()
  41. const { reportsAll } = useIsFeatureEnabled(['reports:all'])
  42. const [{ show_increase_disk_size_modal }, setUrlParams] = useUrlState()
  43. const showIncreaseDiskSizeModal = show_increase_disk_size_modal === 'true'
  44. const setShowIncreaseDiskSizeModal = (value: SetStateAction<boolean>) => {
  45. const show = typeof value === 'function' ? value(showIncreaseDiskSizeModal) : value
  46. setUrlParams({ show_increase_disk_size_modal: show ? 'true' : undefined })
  47. }
  48. const { can: canUpdateDiskSizeConfig } = useAsyncCheckPermissions(
  49. PermissionAction.UPDATE,
  50. 'projects',
  51. {
  52. resource: {
  53. project_id: project?.id,
  54. },
  55. }
  56. )
  57. const { isPending: isUpdatingDiskSize } = useProjectDiskResizeMutation({
  58. onSuccess: (_, variables) => {
  59. toast.success(`Successfully updated disk size to ${variables.volumeSize} GB`)
  60. setShowIncreaseDiskSizeModal(false)
  61. },
  62. })
  63. const { hasAccess: hasAccessToDiskSizeConfig } = useCheckEntitlements(
  64. 'instances.disk_modifications'
  65. )
  66. const currentDiskSize = project?.volumeSizeGb ?? 0
  67. const { data } = useDatabaseSizeQuery({
  68. projectRef: project?.ref,
  69. connectionString: project?.connectionString,
  70. })
  71. const databaseSizeBytesUsed = data ?? 0
  72. return (
  73. <>
  74. <PageSection id="disk-management">
  75. <PageSectionMeta>
  76. <PageSectionSummary>
  77. <PageSectionTitle>Disk Management</PageSectionTitle>
  78. </PageSectionSummary>
  79. <DocsButton href={`${DOCS_URL}/guides/platform/database-size#disk-management`} />
  80. </PageSectionMeta>
  81. <PageSectionContent>
  82. {organization?.usage_billing_enabled === true ? (
  83. <div className="flex flex-col gap-3">
  84. <Panel className="m-0!">
  85. <Panel.Content>
  86. <div>
  87. <div>
  88. {currentDiskSize && (
  89. <span className="text-foreground-light flex gap-2 items-baseline">
  90. <h4 className="text-foreground">Current Disk Storage</h4>
  91. </span>
  92. )}
  93. <div className="grid grid-cols-2 items-center">
  94. <p className="text-sm text-lighter max-w-lg">
  95. Briven employs auto-scaling storage and allows for manual disk size
  96. adjustments when necessary
  97. </p>
  98. {!isAwsNimbus && (
  99. <ButtonTooltip
  100. type="default"
  101. className="w-min ml-auto"
  102. disabled={!canUpdateDiskSizeConfig || disabled}
  103. onClick={() => setShowIncreaseDiskSizeModal(true)}
  104. tooltip={{
  105. content: {
  106. side: 'bottom',
  107. text: !canUpdateDiskSizeConfig
  108. ? 'You need additional permissions to increase the disk size'
  109. : undefined,
  110. },
  111. }}
  112. >
  113. Increase disk size
  114. </ButtonTooltip>
  115. )}
  116. </div>
  117. <div className="grid grid-cols-12 gap-2 mt-12 items-start">
  118. <div className="col-span-4 grid grid-cols-2 gap-x-12 gap-y-4 items-start">
  119. <div className="grid gap-2 col-span-1">
  120. <h5>Space used</h5>
  121. <span className="text-lg">
  122. {formatBytes(databaseSizeBytesUsed, 2, 'GB')}
  123. </span>
  124. </div>
  125. <div className="grid gap-2 col-span-1">
  126. <h5>Total size</h5>
  127. <span className="text-lg">{currentDiskSize} GB</span>
  128. </div>
  129. {reportsAll && (
  130. <div className="col-span-2 mt-4">
  131. <Button asChild type="default" iconRight={<ExternalLink size={14} />}>
  132. <Link
  133. href={`/project/${projectRef}/reports/database#database-size-report`}
  134. >
  135. View detailed summary
  136. </Link>
  137. </Button>
  138. </div>
  139. )}
  140. </div>
  141. <div className="col-span-8">
  142. <Alert>
  143. <Info size={16} />
  144. <AlertTitle>Importing a lot of data?</AlertTitle>
  145. <AlertDescription>
  146. <Markdown
  147. className="max-w-full"
  148. content={`
  149. We auto-scale your disk as you need more storage, but can only do this once every 4 hours.
  150. If you upload more than 1.5x the current size of your storage, your database will go
  151. into read-only mode. If you know how big your database is going to be, you can
  152. manually increase the size here.
  153. Read more about [disk management](${DOCS_URL}/guides/platform/database-size#disk-management) and how to [free up storage space](${DOCS_URL}/guides/platform/database-size#vacuum-operations).
  154. `}
  155. />
  156. </AlertDescription>
  157. </Alert>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </Panel.Content>
  163. </Panel>
  164. </div>
  165. ) : (
  166. <Alert>
  167. <InfoIcon />
  168. <AlertTitle>
  169. {hasAccessToDiskSizeConfig === false
  170. ? 'Disk size configuration is not available for projects on the Free Plan'
  171. : 'Disk size configuration is only available when the spend cap has been disabled'}
  172. </AlertTitle>
  173. <AlertDescription>
  174. {hasAccessToDiskSizeConfig === false ? (
  175. <p>
  176. If you are intending to use more than 500MB of disk space, then you will need to
  177. upgrade to at least the Pro Plan.
  178. </p>
  179. ) : (
  180. <p>
  181. If you are intending to use more than 8GB of disk space, then you will need to
  182. disable your spend cap.
  183. </p>
  184. )}
  185. <Button asChild type="default" className="mt-3">
  186. <Link
  187. href={`/org/${organization?.slug}/billing?panel=${
  188. hasAccessToDiskSizeConfig === false ? 'subscriptionPlan' : 'costControl'
  189. }`}
  190. target="_blank"
  191. >
  192. {hasAccessToDiskSizeConfig === false
  193. ? 'Upgrade subscription'
  194. : 'Disable spend cap'}
  195. </Link>
  196. </Button>
  197. </AlertDescription>
  198. </Alert>
  199. )}
  200. </PageSectionContent>
  201. </PageSection>
  202. <DiskSizeConfigurationModal
  203. visible={showIncreaseDiskSizeModal}
  204. loading={isUpdatingDiskSize}
  205. hideModal={setShowIncreaseDiskSizeModal}
  206. />
  207. </>
  208. )
  209. }