From eec6ced561ba905fd31e16ecca7045b53fa9a723 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 11 Sep 2024 17:39:25 -0700 Subject: [PATCH 1/8] Extract common fields and refactor --- ...shared.tsx => vpc-router-route-common.tsx} | 49 +++++++++++- app/forms/vpc-router-route-create.tsx | 51 +++--------- app/forms/vpc-router-route-edit.tsx | 77 +++++-------------- app/pages/project/vpcs/RouterPage.tsx | 2 +- .../vpcs/VpcPage/tabs/VpcRoutersTab.tsx | 2 +- 5 files changed, 83 insertions(+), 98 deletions(-) rename app/forms/{vpc-router-route/shared.tsx => vpc-router-route-common.tsx} (62%) diff --git a/app/forms/vpc-router-route/shared.tsx b/app/forms/vpc-router-route-common.tsx similarity index 62% rename from app/forms/vpc-router-route/shared.tsx rename to app/forms/vpc-router-route-common.tsx index ce528052f..04435fada 100644 --- a/app/forms/vpc-router-route/shared.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -6,7 +6,21 @@ * Copyright Oxide Computer Company */ -import type { RouteDestination, RouteTarget } from '~/api' +import type { Control } from 'react-hook-form' + +import type { + RouteDestination, + RouterRouteCreate, + RouterRouteUpdate, + RouteTarget, +} from '~/api' +import { DescriptionField } from '~/components/form/fields/DescriptionField' +import { ListboxField } from '~/components/form/fields/ListboxField' +import { NameField } from '~/components/form/fields/NameField' +import { TextField } from '~/components/form/fields/TextField' +import { Message } from '~/ui/lib/Message' + +export type RouteFormValues = RouterRouteCreate | Required // VPCs can not be specified as a destination in custom routers // https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L363 @@ -74,3 +88,36 @@ export const targetValueDescription = (targetType: RouteTarget['type']) => targetType === 'internet_gateway' ? routeFormMessage.internetGatewayTargetValue : undefined + +type RouteFormFieldsProps = { + control: Control + targetType: RouteTarget['type'] + isDisabled?: boolean +} +export const RouteFormFields = ({ + control, + targetType, + isDisabled, +}: RouteFormFieldsProps) => { + return ( + <> + {isDisabled && ( + + )} + + + + + + {targetType !== 'drop' && ( + + )} + + ) +} diff --git a/app/forms/vpc-router-route-create.tsx b/app/forms/vpc-router-route-create.tsx index 597c82ced..fdd5609b1 100644 --- a/app/forms/vpc-router-route-create.tsx +++ b/app/forms/vpc-router-route-create.tsx @@ -5,22 +5,19 @@ * * Copyright Oxide Computer Company */ +import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { useNavigate } from 'react-router-dom' -import { useApiMutation, useApiQueryClient, type RouterRouteCreate } from '@oxide/api' +import { useApiMutation, useApiQueryClient } from '@oxide/api' -import { DescriptionField } from '~/components/form/fields/DescriptionField' -import { ListboxField } from '~/components/form/fields/ListboxField' -import { NameField } from '~/components/form/fields/NameField' -import { TextField } from '~/components/form/fields/TextField' import { SideModalForm } from '~/components/form/SideModalForm' -import { fields, targetValueDescription } from '~/forms/vpc-router-route/shared' +import { RouteFormFields, type RouteFormValues } from '~/forms/vpc-router-route-common' import { useVpcRouterSelector } from '~/hooks/use-params' import { addToast } from '~/stores/toast' import { pb } from '~/util/path-builder' -const defaultValues: RouterRouteCreate = { +const defaultValues: RouteFormValues = { name: '', description: '', destination: { type: 'ip', value: '' }, @@ -32,27 +29,28 @@ export function CreateRouterRouteSideModalForm() { const routerSelector = useVpcRouterSelector() const navigate = useNavigate() - const onDismiss = () => { - navigate(pb.vpcRouter(routerSelector)) - } - const createRouterRoute = useApiMutation('vpcRouterRouteCreate', { onSuccess() { queryClient.invalidateQueries('vpcRouterRouteList') addToast({ content: 'Your route has been created' }) - onDismiss() + navigate(pb.vpcRouter(routerSelector)) }, }) const form = useForm({ defaultValues }) const targetType = form.watch('target.type') + useEffect(() => { + // when targetType is 'internet_gateway', we set it to `outbound` + form.setValue('target.value', targetType === 'internet_gateway' ? 'outbound' : '') + }, [form, targetType]) + return ( navigate(pb.vpcRouter(routerSelector))} onSubmit={({ name, description, destination, target }) => createRouterRoute.mutate({ query: routerSelector, @@ -68,32 +66,7 @@ export function CreateRouterRouteSideModalForm() { loading={createRouterRoute.isPending} submitError={createRouterRoute.error} > - - - - - { - // 'outbound' is only valid option when targetType is 'internet_gateway' - if (value === 'internet_gateway') { - form.setValue('target.value', 'outbound') - } - if (value === 'drop') { - form.setValue('target.value', '') - } - }} - /> - {targetType !== 'drop' && ( - - )} + ) } diff --git a/app/forms/vpc-router-route-edit.tsx b/app/forms/vpc-router-route-edit.tsx index bfe52466b..5c99cfc86 100644 --- a/app/forms/vpc-router-route-edit.tsx +++ b/app/forms/vpc-router-route-edit.tsx @@ -5,6 +5,7 @@ * * Copyright Oxide Computer Company */ +import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { useNavigate, type LoaderFunctionArgs } from 'react-router-dom' import * as R from 'remeda' @@ -14,84 +15,70 @@ import { useApiMutation, useApiQueryClient, usePrefetchedApiQuery, - type RouterRouteUpdate, } from '@oxide/api' -import { DescriptionField } from '~/components/form/fields/DescriptionField' -import { ListboxField } from '~/components/form/fields/ListboxField' -import { NameField } from '~/components/form/fields/NameField' -import { TextField } from '~/components/form/fields/TextField' import { SideModalForm } from '~/components/form/SideModalForm' import { - fields, + RouteFormFields, routeFormMessage, - targetValueDescription, -} from '~/forms/vpc-router-route/shared' + type RouteFormValues, +} from '~/forms/vpc-router-route-common' import { getVpcRouterRouteSelector, useVpcRouterRouteSelector } from '~/hooks/use-params' import { addToast } from '~/stores/toast' -import { Message } from '~/ui/lib/Message' import { pb } from '~/util/path-builder' EditRouterRouteSideModalForm.loader = async ({ params }: LoaderFunctionArgs) => { - const { project, vpc, router, route } = getVpcRouterRouteSelector(params) + const { route, ...routerSelector } = getVpcRouterRouteSelector(params) await apiQueryClient.prefetchQuery('vpcRouterRouteView', { path: { route }, - query: { project, vpc, router }, + query: routerSelector, }) return null } export function EditRouterRouteSideModalForm() { const queryClient = useApiQueryClient() - const routeSelector = useVpcRouterRouteSelector() - const { project, vpc, router: routerName, route: routeName } = routeSelector + const { route: routeName, ...routerSelector } = useVpcRouterRouteSelector() const navigate = useNavigate() const { data: route } = usePrefetchedApiQuery('vpcRouterRouteView', { path: { route: routeName }, - query: { project, vpc, router: routerName }, + query: routerSelector, }) - const defaultValues: RouterRouteUpdate = R.pick(route, [ + const defaultValues: RouteFormValues = R.pick(route, [ 'name', 'description', 'target', 'destination', ]) - const onDismiss = () => { - navigate(pb.vpcRouter({ project, vpc, router: routerName })) - } - const updateRouterRoute = useApiMutation('vpcRouterRouteUpdate', { onSuccess() { queryClient.invalidateQueries('vpcRouterRouteList') addToast({ content: 'Your route has been updated' }) - onDismiss() + navigate(pb.vpcRouter(routerSelector)) }, }) const form = useForm({ defaultValues }) const targetType = form.watch('target.type') + const isDisabled = route?.kind === 'vpc_subnet' - let isDisabled = false - let disabledReason = '' - - // Can simplify this if there aren't other disabling reasons - if (route?.kind === 'vpc_subnet') { - isDisabled = true - disabledReason = routeFormMessage.vpcSubnetNotModifiable - } + useEffect(() => { + // when targetType is 'internet_gateway', we set it to `outbound` + form.setValue('target.value', targetType === 'internet_gateway' ? 'outbound' : '') + }, [form, targetType]) return ( navigate(pb.vpcRouter(routerSelector))} onSubmit={({ name, description, destination, target }) => updateRouterRoute.mutate({ - query: { project, vpc, router: routerName }, path: { route: routeName }, + query: routerSelector, body: { name, description, @@ -103,35 +90,13 @@ export function EditRouterRouteSideModalForm() { } loading={updateRouterRoute.isPending} submitError={updateRouterRoute.error} + submitDisabled={isDisabled ? routeFormMessage.vpcSubnetNotModifiable : undefined} > - {isDisabled && } - - - - - { - // 'outbound' is only valid option when targetType is 'internet_gateway' - if (value === 'internet_gateway') { - form.setValue('target.value', 'outbound') - } - if (value === 'drop') { - form.setValue('target.value', '') - } - }} + targetType={targetType} + isDisabled={isDisabled} /> - {targetType !== 'drop' && ( - - )} ) } diff --git a/app/pages/project/vpcs/RouterPage.tsx b/app/pages/project/vpcs/RouterPage.tsx index ca5c7cd8f..b91ae862a 100644 --- a/app/pages/project/vpcs/RouterPage.tsx +++ b/app/pages/project/vpcs/RouterPage.tsx @@ -23,7 +23,7 @@ import { import { DocsPopover } from '~/components/DocsPopover' import { HL } from '~/components/HL' import { MoreActionsMenu } from '~/components/MoreActionsMenu' -import { routeFormMessage } from '~/forms/vpc-router-route/shared' +import { routeFormMessage } from '~/forms/vpc-router-route-common' import { getVpcRouterSelector, useVpcRouterSelector } from '~/hooks/use-params' import { confirmAction } from '~/stores/confirm-action' import { addToast } from '~/stores/toast' diff --git a/app/pages/project/vpcs/VpcPage/tabs/VpcRoutersTab.tsx b/app/pages/project/vpcs/VpcPage/tabs/VpcRoutersTab.tsx index b030c764f..361d7a492 100644 --- a/app/pages/project/vpcs/VpcPage/tabs/VpcRoutersTab.tsx +++ b/app/pages/project/vpcs/VpcPage/tabs/VpcRoutersTab.tsx @@ -11,7 +11,7 @@ import { Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router-dom' import { apiQueryClient, useApiMutation, type VpcRouter } from '@oxide/api' -import { routeFormMessage } from '~/forms/vpc-router-route/shared' +import { routeFormMessage } from '~/forms/vpc-router-route-common' import { getVpcSelector, useVpcSelector } from '~/hooks/use-params' import { confirmDelete } from '~/stores/confirm-delete' import { addToast } from '~/stores/toast' From 6fcce469eeb554cb8067b45fe6bcce92154e5bf0 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 11 Sep 2024 17:48:06 -0700 Subject: [PATCH 2/8] Clarify comment --- app/forms/vpc-router-route-common.tsx | 44 +++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/app/forms/vpc-router-route-common.tsx b/app/forms/vpc-router-route-common.tsx index 04435fada..38a8c304a 100644 --- a/app/forms/vpc-router-route-common.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -98,26 +98,24 @@ export const RouteFormFields = ({ control, targetType, isDisabled, -}: RouteFormFieldsProps) => { - return ( - <> - {isDisabled && ( - - )} - - - - - - {targetType !== 'drop' && ( - - )} - - ) -} +}: RouteFormFieldsProps) => ( + <> + {isDisabled && ( + + )} + + + + + + {targetType !== 'drop' && ( + + )} + +) From ddc10cfa58245019a5a6d9e1eb18db36b202e48f Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 11 Sep 2024 18:26:15 -0700 Subject: [PATCH 3/8] Update useEffect to include value --- app/forms/vpc-router-route-edit.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/forms/vpc-router-route-edit.tsx b/app/forms/vpc-router-route-edit.tsx index 5c99cfc86..714398f16 100644 --- a/app/forms/vpc-router-route-edit.tsx +++ b/app/forms/vpc-router-route-edit.tsx @@ -62,12 +62,15 @@ export function EditRouterRouteSideModalForm() { const form = useForm({ defaultValues }) const targetType = form.watch('target.type') + const targetValue = form.watch('target.value') const isDisabled = route?.kind === 'vpc_subnet' - useEffect(() => { // when targetType is 'internet_gateway', we set it to `outbound` - form.setValue('target.value', targetType === 'internet_gateway' ? 'outbound' : '') - }, [form, targetType]) + form.setValue( + 'target.value', + targetType === 'internet_gateway' ? 'outbound' : targetValue + ) + }, [form, targetType, targetValue]) return ( Date: Thu, 12 Sep 2024 08:41:03 -0700 Subject: [PATCH 4/8] Inline props and remove unnecessary consts --- app/forms/vpc-router-route-common.tsx | 112 +++++++++++--------------- 1 file changed, 47 insertions(+), 65 deletions(-) diff --git a/app/forms/vpc-router-route-common.tsx b/app/forms/vpc-router-route-common.tsx index 38a8c304a..88a20bcdd 100644 --- a/app/forms/vpc-router-route-common.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -8,12 +8,7 @@ import type { Control } from 'react-hook-form' -import type { - RouteDestination, - RouterRouteCreate, - RouterRouteUpdate, - RouteTarget, -} from '~/api' +import type { RouterRouteCreate, RouterRouteUpdate, RouteTarget } from '~/api' import { DescriptionField } from '~/components/form/fields/DescriptionField' import { ListboxField } from '~/components/form/fields/ListboxField' import { NameField } from '~/components/form/fields/NameField' @@ -22,55 +17,6 @@ import { Message } from '~/ui/lib/Message' export type RouteFormValues = RouterRouteCreate | Required -// VPCs can not be specified as a destination in custom routers -// https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L363 -const destTypes: Record, string> = { - ip: 'IP', - ip_net: 'IP network', - subnet: 'Subnet', -} - -// Subnets and VPCs cannot be used as a target in custom routers -// https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L362-L368 -const targetTypes: Record, string> = { - ip: 'IP', - instance: 'Instance', - internet_gateway: 'Internet gateway', - drop: 'Drop', -} - -const toItems = (mapping: Record) => - Object.entries(mapping).map(([value, label]) => ({ value, label })) - -export const fields = { - destType: { - name: 'destination.type' as const, - items: toItems(destTypes), - label: 'Destination type', - placeholder: 'Select a destination type', - required: true, - }, - destValue: { - name: 'destination.value' as const, - label: 'Destination value', - placeholder: 'Enter a destination value', - required: true, - }, - targetType: { - name: 'target.type' as const, - items: toItems(targetTypes), - label: 'Target type', - placeholder: 'Select a target type', - required: true, - }, - targetValue: { - name: 'target.value' as const, - label: 'Target value', - placeholder: 'Enter a target value', - required: true, - }, -} - export const routeFormMessage = { vpcSubnetNotModifiable: 'Routes of type VPC Subnet within the system router are not modifiable', @@ -84,11 +30,6 @@ export const routeFormMessage = { noDeletingSystemRouters: 'System routers cannot be deleted', } -export const targetValueDescription = (targetType: RouteTarget['type']) => - targetType === 'internet_gateway' - ? routeFormMessage.internetGatewayTargetValue - : undefined - type RouteFormFieldsProps = { control: Control targetType: RouteTarget['type'] @@ -105,16 +46,57 @@ export const RouteFormFields = ({ )} - - - + + + {targetType !== 'drop' && ( )} From 00c02dbe47d5e627aa8c730ac8dc3734a5e1f9a1 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 12 Sep 2024 09:34:54 -0700 Subject: [PATCH 5/8] Pass form to move more shared code into common component --- app/forms/vpc-router-route-common.tsx | 134 +++++++++++++------------- app/forms/vpc-router-route-create.tsx | 26 ++--- app/forms/vpc-router-route-edit.tsx | 21 +--- 3 files changed, 80 insertions(+), 101 deletions(-) diff --git a/app/forms/vpc-router-route-common.tsx b/app/forms/vpc-router-route-common.tsx index 88a20bcdd..be9017ebc 100644 --- a/app/forms/vpc-router-route-common.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -6,9 +6,9 @@ * Copyright Oxide Computer Company */ -import type { Control } from 'react-hook-form' +import type { UseFormReturn } from 'react-hook-form' -import type { RouterRouteCreate, RouterRouteUpdate, RouteTarget } from '~/api' +import type { RouterRouteCreate, RouterRouteUpdate } from '~/api' import { DescriptionField } from '~/components/form/fields/DescriptionField' import { ListboxField } from '~/components/form/fields/ListboxField' import { NameField } from '~/components/form/fields/NameField' @@ -31,73 +31,75 @@ export const routeFormMessage = { } type RouteFormFieldsProps = { - control: Control - targetType: RouteTarget['type'] + form: UseFormReturn isDisabled?: boolean } -export const RouteFormFields = ({ - control, - targetType, - isDisabled, -}: RouteFormFieldsProps) => ( - <> - {isDisabled && ( - - )} - - - - - - {targetType !== 'drop' && ( +export const RouteFormFields = ({ form, isDisabled }: RouteFormFieldsProps) => { + const { control } = form + const targetType = form.watch('target.type') + return ( + <> + {isDisabled && ( + + )} + + + - )} - -) + { + form.setValue('target.value', value === 'internet_gateway' ? 'outbound' : '') + }} + disabled={isDisabled} + /> + {targetType !== 'drop' && ( + + )} + + ) +} diff --git a/app/forms/vpc-router-route-create.tsx b/app/forms/vpc-router-route-create.tsx index fdd5609b1..d7cc0177b 100644 --- a/app/forms/vpc-router-route-create.tsx +++ b/app/forms/vpc-router-route-create.tsx @@ -5,7 +5,6 @@ * * Copyright Oxide Computer Company */ -import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { useNavigate } from 'react-router-dom' @@ -17,18 +16,19 @@ import { useVpcRouterSelector } from '~/hooks/use-params' import { addToast } from '~/stores/toast' import { pb } from '~/util/path-builder' -const defaultValues: RouteFormValues = { - name: '', - description: '', - destination: { type: 'ip', value: '' }, - target: { type: 'ip', value: '' }, -} - export function CreateRouterRouteSideModalForm() { const queryClient = useApiQueryClient() const routerSelector = useVpcRouterSelector() const navigate = useNavigate() + const defaultValues: RouteFormValues = { + name: '', + description: '', + destination: { type: 'ip', value: '' }, + target: { type: 'ip', value: '' }, + } + const form = useForm({ defaultValues }) + const createRouterRoute = useApiMutation('vpcRouterRouteCreate', { onSuccess() { queryClient.invalidateQueries('vpcRouterRouteList') @@ -37,14 +37,6 @@ export function CreateRouterRouteSideModalForm() { }, }) - const form = useForm({ defaultValues }) - const targetType = form.watch('target.type') - - useEffect(() => { - // when targetType is 'internet_gateway', we set it to `outbound` - form.setValue('target.value', targetType === 'internet_gateway' ? 'outbound' : '') - }, [form, targetType]) - return ( - + ) } diff --git a/app/forms/vpc-router-route-edit.tsx b/app/forms/vpc-router-route-edit.tsx index 714398f16..0399a02d4 100644 --- a/app/forms/vpc-router-route-edit.tsx +++ b/app/forms/vpc-router-route-edit.tsx @@ -5,7 +5,6 @@ * * Copyright Oxide Computer Company */ -import { useEffect } from 'react' import { useForm } from 'react-hook-form' import { useNavigate, type LoaderFunctionArgs } from 'react-router-dom' import * as R from 'remeda' @@ -51,6 +50,8 @@ export function EditRouterRouteSideModalForm() { 'target', 'destination', ]) + const form = useForm({ defaultValues }) + const isDisabled = route?.kind === 'vpc_subnet' const updateRouterRoute = useApiMutation('vpcRouterRouteUpdate', { onSuccess() { @@ -60,18 +61,6 @@ export function EditRouterRouteSideModalForm() { }, }) - const form = useForm({ defaultValues }) - const targetType = form.watch('target.type') - const targetValue = form.watch('target.value') - const isDisabled = route?.kind === 'vpc_subnet' - useEffect(() => { - // when targetType is 'internet_gateway', we set it to `outbound` - form.setValue( - 'target.value', - targetType === 'internet_gateway' ? 'outbound' : targetValue - ) - }, [form, targetType, targetValue]) - return ( - + ) } From 398d58ce5e3dc0303d3c6f020179e2accf712656 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 12 Sep 2024 15:53:18 -0700 Subject: [PATCH 6/8] Reintroduce typechecking against API for destination types and target types --- app/forms/vpc-router-route-common.tsx | 44 +++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/app/forms/vpc-router-route-common.tsx b/app/forms/vpc-router-route-common.tsx index be9017ebc..e63cdaa86 100644 --- a/app/forms/vpc-router-route-common.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -8,7 +8,12 @@ import type { UseFormReturn } from 'react-hook-form' -import type { RouterRouteCreate, RouterRouteUpdate } from '~/api' +import type { + RouteDestination, + RouterRouteCreate, + RouterRouteUpdate, + RouteTarget, +} from '~/api' import { DescriptionField } from '~/components/form/fields/DescriptionField' import { ListboxField } from '~/components/form/fields/ListboxField' import { NameField } from '~/components/form/fields/NameField' @@ -30,6 +35,26 @@ export const routeFormMessage = { noDeletingSystemRouters: 'System routers cannot be deleted', } +// VPCs can not be specified as a destination in custom routers +// https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L363 +const destTypes: Record, string> = { + ip: 'IP', + ip_net: 'IP network', + subnet: 'Subnet', +} + +// Subnets and VPCs cannot be used as a target in custom routers +// https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L362-L368 +const targetTypes: Record, string> = { + ip: 'IP', + instance: 'Instance', + internet_gateway: 'Internet gateway', + drop: 'Drop', +} + +const toItems = (mapping: Record) => + Object.entries(mapping).map(([value, label]) => ({ value, label })) + type RouteFormFieldsProps = { form: UseFormReturn isDisabled?: boolean @@ -48,13 +73,7 @@ export const RouteFormFields = ({ form, isDisabled }: RouteFormFieldsProps) => { name="destination.type" label="Destination type" control={control} - items={[ - // VPCs can not be specified as a destination in custom routers - // https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L363 - { value: 'ip', label: 'IP' }, - { value: 'ip_net', label: 'IP network' }, - { value: 'subnet', label: 'Subnet' }, - ]} + items={toItems(destTypes)} placeholder="Select a destination type" required disabled={isDisabled} @@ -71,14 +90,7 @@ export const RouteFormFields = ({ form, isDisabled }: RouteFormFieldsProps) => { name="target.type" label="Target type" control={control} - items={[ - // Subnets and VPCs cannot be used as a target in custom routers - // https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L362-L368 - { value: 'ip', label: 'IP' }, - { value: 'instance', label: 'Instance' }, - { value: 'internet_gateway', label: 'Internet gateway' }, - { value: 'drop', label: 'Drop' }, - ]} + items={toItems(targetTypes)} placeholder="Select a target type" required onChange={(value) => { From d89087d3b3e7eaff897f073516b05734a9d321ea Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 12 Sep 2024 16:32:31 -0700 Subject: [PATCH 7/8] typo --- app/forms/vpc-router-route-common.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/forms/vpc-router-route-common.tsx b/app/forms/vpc-router-route-common.tsx index e63cdaa86..069ae60f0 100644 --- a/app/forms/vpc-router-route-common.tsx +++ b/app/forms/vpc-router-route-common.tsx @@ -35,7 +35,7 @@ export const routeFormMessage = { noDeletingSystemRouters: 'System routers cannot be deleted', } -// VPCs can not be specified as a destination in custom routers +// VPCs cannot be specified as a destination in custom routers // https://github.com/oxidecomputer/omicron/blob/4f27433d1bca57eb02073a4ea1cd14557f70b8c7/nexus/src/app/vpc_router.rs#L363 const destTypes: Record, string> = { ip: 'IP', From 9d1acd1586ca51b3414960354d6a20856a11a6a7 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Mon, 16 Sep 2024 09:00:54 -0700 Subject: [PATCH 8/8] Move default values const out of component --- app/forms/vpc-router-route-create.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/forms/vpc-router-route-create.tsx b/app/forms/vpc-router-route-create.tsx index d7cc0177b..d8c0d0769 100644 --- a/app/forms/vpc-router-route-create.tsx +++ b/app/forms/vpc-router-route-create.tsx @@ -16,17 +16,18 @@ import { useVpcRouterSelector } from '~/hooks/use-params' import { addToast } from '~/stores/toast' import { pb } from '~/util/path-builder' +const defaultValues: RouteFormValues = { + name: '', + description: '', + destination: { type: 'ip', value: '' }, + target: { type: 'ip', value: '' }, +} + export function CreateRouterRouteSideModalForm() { const queryClient = useApiQueryClient() const routerSelector = useVpcRouterSelector() const navigate = useNavigate() - const defaultValues: RouteFormValues = { - name: '', - description: '', - destination: { type: 'ip', value: '' }, - target: { type: 'ip', value: '' }, - } const form = useForm({ defaultValues }) const createRouterRoute = useApiMutation('vpcRouterRouteCreate', {