From 1328624a353943bcad8dee0683ce6b85a071159c Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Mon, 17 Nov 2025 16:46:31 -0800 Subject: [PATCH 1/5] Fetch and prefill VPC list in NIC forms --- app/forms/instance-create.tsx | 2 ++ app/forms/network-interface-create.tsx | 26 ++++++++++++++----- app/pages/project/instances/NetworkingTab.tsx | 2 ++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/forms/instance-create.tsx b/app/forms/instance-create.tsx index 6246a655e..44fa2328f 100644 --- a/app/forms/instance-create.tsx +++ b/app/forms/instance-create.tsx @@ -170,6 +170,8 @@ export async function clientLoader({ params }: LoaderFunctionArgs) { queryClient.prefetchQuery( q(api.floatingIpList, { query: { project, limit: ALL_ISH } }) ), + // Fetch VPCs for custom NIC form + queryClient.prefetchQuery(q(api.vpcList, { query: { project, limit: ALL_ISH } })), ]) return null } diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index b4fc54b74..0ab0e257d 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -5,12 +5,17 @@ * * Copyright Oxide Computer Company */ -import { useQuery } from '@tanstack/react-query' -import { useMemo } from 'react' +import { useEffect, useMemo } from 'react' import { useForm } from 'react-hook-form' import type { SetNonNullable, SetRequired } from 'type-fest' -import { api, q, type ApiError, type InstanceNetworkInterfaceCreate } from '@oxide/api' +import { + api, + q, + usePrefetchedQuery, + type ApiError, + type InstanceNetworkInterfaceCreate, +} from '@oxide/api' import { DescriptionField } from '~/components/form/fields/DescriptionField' import { ListboxField } from '~/components/form/fields/ListboxField' @@ -20,6 +25,7 @@ import { TextField } from '~/components/form/fields/TextField' import { SideModalForm } from '~/components/form/SideModalForm' import { useProjectSelector } from '~/hooks/use-params' import { FormDivider } from '~/ui/lib/Divider' +import { ALL_ISH } from '~/util/consts' const defaultValues: SetRequired, 'ip'> = { name: '', @@ -47,12 +53,20 @@ export function CreateNetworkInterfaceForm({ submitError = null, }: CreateNetworkInterfaceFormProps) { const projectSelector = useProjectSelector() - - const { data: vpcsData } = useQuery(q(api.vpcList, { query: projectSelector })) - const vpcs = useMemo(() => vpcsData?.items || [], [vpcsData]) + const { data: vpcsData } = usePrefetchedQuery( + q(api.vpcList, { query: { ...projectSelector, limit: ALL_ISH } }) + ) + const vpcs = useMemo(() => vpcsData.items, [vpcsData]) const form = useForm({ defaultValues }) + // prefill form with first VPC + useEffect(() => { + if (vpcs.length > 0 && !form.getValues('vpcName')) { + form.setValue('vpcName', vpcs[0].name) + } + }, [vpcs, form]) + return ( Date: Mon, 17 Nov 2025 17:18:14 -0800 Subject: [PATCH 2/5] use prefetched data in defaultValues --- app/forms/network-interface-create.tsx | 34 +++++++++----------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index 0ab0e257d..93038857a 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -5,9 +5,7 @@ * * Copyright Oxide Computer Company */ -import { useEffect, useMemo } from 'react' import { useForm } from 'react-hook-form' -import type { SetNonNullable, SetRequired } from 'type-fest' import { api, @@ -27,14 +25,6 @@ import { useProjectSelector } from '~/hooks/use-params' import { FormDivider } from '~/ui/lib/Divider' import { ALL_ISH } from '~/util/consts' -const defaultValues: SetRequired, 'ip'> = { - name: '', - description: '', - ip: '', - subnetName: '', - vpcName: '', -} - type CreateNetworkInterfaceFormProps = { onDismiss: () => void onSubmit: (values: InstanceNetworkInterfaceCreate) => void @@ -53,20 +43,18 @@ export function CreateNetworkInterfaceForm({ submitError = null, }: CreateNetworkInterfaceFormProps) { const projectSelector = useProjectSelector() - const { data: vpcsData } = usePrefetchedQuery( - q(api.vpcList, { query: { ...projectSelector, limit: ALL_ISH } }) - ) - const vpcs = useMemo(() => vpcsData.items, [vpcsData]) - + const { + data: { items: vpcs }, + } = usePrefetchedQuery(q(api.vpcList, { query: { ...projectSelector, limit: ALL_ISH } })) + const defaultValues = { + name: '', + description: '', + ip: '', + subnetName: '', + // Preselect first VPC + vpcName: vpcs.length > 0 ? vpcs[0].name : '', + } const form = useForm({ defaultValues }) - - // prefill form with first VPC - useEffect(() => { - if (vpcs.length > 0 && !form.getValues('vpcName')) { - form.setValue('vpcName', vpcs[0].name) - } - }, [vpcs, form]) - return ( Date: Mon, 17 Nov 2025 17:20:10 -0800 Subject: [PATCH 3/5] remove comment --- app/forms/network-interface-create.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index 93038857a..e4292d68d 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -51,7 +51,6 @@ export function CreateNetworkInterfaceForm({ description: '', ip: '', subnetName: '', - // Preselect first VPC vpcName: vpcs.length > 0 ? vpcs[0].name : '', } const form = useForm({ defaultValues }) From d3be9327271ac35d13d27bd3d86711005f08ed66 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Mon, 17 Nov 2025 17:34:32 -0800 Subject: [PATCH 4/5] add required type Co-authored-by: David Crespo --- app/forms/network-interface-create.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index e4292d68d..ac1876e6b 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -46,7 +46,7 @@ export function CreateNetworkInterfaceForm({ const { data: { items: vpcs }, } = usePrefetchedQuery(q(api.vpcList, { query: { ...projectSelector, limit: ALL_ISH } })) - const defaultValues = { + const defaultValues: SetRequired, 'ip'> = { name: '', description: '', ip: '', From d57d243bfddc535c1ed86a3cdfde8b52c6eb0ea5 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Mon, 17 Nov 2025 17:35:26 -0800 Subject: [PATCH 5/5] fix imports --- app/forms/network-interface-create.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index ac1876e6b..14b62ee2e 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -6,6 +6,7 @@ * Copyright Oxide Computer Company */ import { useForm } from 'react-hook-form' +import type { SetNonNullable, SetRequired } from 'type-fest' import { api,