From 659eaaff58ebe3c85a13a7ca1685c54dce84c0a5 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Fri, 18 Oct 2024 17:47:48 +0800 Subject: [PATCH] add instances --- .../DiskManagement/DiskManagementForm.tsx | 139 +++++++++++++++++- .../ui/src/components/radio-group-card.tsx | 8 +- 2 files changed, 140 insertions(+), 7 deletions(-) diff --git a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx index 4e10795b673..2fc90559ec0 100644 --- a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx +++ b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx @@ -1,9 +1,9 @@ import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { AnimatePresence, motion } from 'framer-motion' -import { HelpCircle, InfoIcon, RotateCcw } from 'lucide-react' +import { CpuIcon, HelpCircle, InfoIcon, Microchip, RotateCcw } from 'lucide-react' import Link from 'next/link' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' @@ -69,6 +69,10 @@ import { } from './DiskManagementReadReplicas' import { DiskManagementReviewAndSubmitDialog } from './DiskManagementReviewAndSubmitDialog' import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query' +import { ProjectAddonVariantMeta } from 'data/subscriptions/types' +import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' +import { ComputeBadge } from 'ui-patterns' +import { components } from 'api-types' export function DiskManagementForm() { const { project } = useProjectContext() @@ -88,6 +92,7 @@ export function DiskManagementForm() { /** * Queries for form data */ + const { data: databases, isLoading: isReadReplicasLoading, @@ -151,12 +156,67 @@ export function DiskManagementForm() { orgSlug: org?.slug, }) + /** + * Handle compute instances + */ + const availableAddons = useMemo(() => { + return addons?.available_addons ?? [] + }, [addons]) + + const hasMicroOptionFromApi = useMemo(() => { + return ( + availableAddons.find((addon) => addon.type === 'compute_instance')?.variants ?? [] + ).some((variant) => variant.identifier === 'ci_micro') + }, [availableAddons]) + + const availableOptions = useMemo(() => { + const computeOptions = + availableAddons + .find((addon) => addon.type === 'compute_instance') + ?.variants.filter((option) => { + if (!project?.cloud_provider) { + return true + } + + const meta = option.meta as ProjectAddonVariantMeta + + return ( + !meta.supported_cloud_providers || + meta.supported_cloud_providers.includes(project.cloud_provider) + ) + }) ?? [] + + // Backwards comp until API is deployed + // if (!hasMicroOptionFromApi) { + // // Unshift to push to start of array + // computeOptions.unshift({ + // identifier: 'ci_micro', + // name: 'Micro', + // price_description: '$0.01344/hour (~$10/month)', + // price: 0.01344, + // price_interval: 'hourly', + // price_type: 'usage', + // // @ts-ignore API types it as Record + // meta: { + // cpu_cores: INSTANCE_MICRO_SPECS.cpu_cores, + // cpu_dedicated: INSTANCE_MICRO_SPECS.cpu_dedicated, + // memory_gb: INSTANCE_MICRO_SPECS.memory_gb, + // baseline_disk_io_mbs: INSTANCE_MICRO_SPECS.baseline_disk_io_mbs, + // max_disk_io_mbs: INSTANCE_MICRO_SPECS.max_disk_io_mbs, + // connections_direct: INSTANCE_MICRO_SPECS.connections_direct, + // connections_pooler: INSTANCE_MICRO_SPECS.connections_pooler, + // } as ProjectAddonVariantMeta, + // }) + // } + + return computeOptions + }, [availableAddons, hasMicroOptionFromApi]) + /** * Handle default values */ // @ts-ignore [Joshen TODO] check whats happening here const { type, iops, throughput_mbps, size_gb } = data?.attributes ?? { size_gb: 0 } - const defaultValues = { storageType: type ?? 'gp3', provisionedIOPS: iops, @@ -364,6 +424,79 @@ export function DiskManagementForm() { />
+ + {availableOptions.map((compute) => { + const cpuArchitecture = getCloudProviderArchitecture(project?.cloud_provider) + + return ( + +
+ +
+ + {/* Price needs to be exact here */}${compute.price} + + + {' '} + / {compute.price_interval === 'monthly' ? 'month' : 'hour'} + +
+
+ {/* */} +
+
+
+ + {compute.meta?.memory_gb ?? 0} GB memory +
+
+ + + {compute.meta?.cpu_cores ?? 0}-core {cpuArchitecture} CPU + +
+
+ {/*
+ {compute.meta?.cpu_dedicated ? 'Dedicated' : 'Shared'} +
*/} + + {/*
+
+ + ${compute.price} + + + {' '} + / {compute.price_interval === 'monthly' ? 'month' : 'hour'} + +
+
*/} +
+ + } + >
+ ) + })} +
{/* */}