66 * Copyright Oxide Computer Company
77 */
88
9- import { useQuery } from '@tanstack/react-query'
9+ import { useQueries , useQuery } from '@tanstack/react-query'
1010import { useForm } from 'react-hook-form'
1111import { Link , useNavigate , type LoaderFunctionArgs } from 'react-router-dom'
12+ import * as R from 'remeda'
1213
1314import { Gateway16Icon } from '@oxide/design-system/icons/react'
1415
15- import { apiQueryClient , getListQFn , queryClient , usePrefetchedApiQuery } from '~/api'
16+ import {
17+ apiQueryClient ,
18+ getListQFn ,
19+ queryClient ,
20+ usePrefetchedApiQuery ,
21+ usePrefetchedQuery ,
22+ } from '~/api'
1623import { SideModalForm } from '~/components/form/SideModalForm'
1724import { getInternetGatewaySelector , useInternetGatewaySelector } from '~/hooks/use-params'
1825import { DescriptionCell } from '~/table/cells/DescriptionCell'
@@ -28,54 +35,55 @@ import { links } from '~/util/links'
2835import { pb } from '~/util/path-builder'
2936import type * as PP from '~/util/path-params'
3037
31- const RouterRow = ( {
32- project,
33- vpc,
34- gateway,
35- router,
36- } : PP . VpcInternetGateway & { router : string } ) => {
37- const matchingRoutes : JSX . Element [ ] = [ ]
38- const { data : routes } = useQuery ( routeList ( { project, vpc, router } ) . optionsFn ( ) )
39- if ( ! routes || routes . items . length < 1 ) return
40- routes . items . forEach ( ( route ) => {
41- if ( route . target . type === 'internet_gateway' && route . target . value === gateway ) {
42- matchingRoutes . push (
43- < Table . Row key = { `${ router } -${ route . name } ` } >
44- < Table . Cell className = "!bg-raise" > { router } </ Table . Cell >
45- < Table . Cell className = "bg-raise" >
46- < Link
47- to = { pb . vpcRouterRouteEdit ( {
48- project,
49- vpc,
50- router,
51- route : route . name ,
52- } ) }
53- className = "link-with-underline text-sans-md"
54- >
55- { route . name }
56- </ Link >
57- </ Table . Cell >
58- </ Table . Row >
59- )
60- }
38+ const RoutesEmpty = ( ) => (
39+ < Table . Row >
40+ < Table . Cell colSpan = { 2 } className = "bg-secondary" >
41+ No VPC router routes target this gateway.
42+ </ Table . Cell >
43+ </ Table . Row >
44+ )
45+
46+ /**
47+ * For a given gateway, return a list of [router name, RouterRoute] pairs
48+ */
49+ export function useGatewayRoutes ( { project, vpc, gateway } : PP . VpcInternetGateway ) {
50+ const { data : routers } = usePrefetchedQuery ( routerList ( { project, vpc } ) . optionsFn ( ) )
51+ const routerNames = routers . items . map ( ( r ) => r . name )
52+
53+ const routesQueries = useQueries ( {
54+ queries : routerNames . map ( ( router ) => routeList ( { project, vpc, router } ) . optionsFn ( ) ) ,
6155 } )
62- return matchingRoutes
63- }
56+ const loadedRoutesLists = routesQueries . filter ( ( q ) => ! ! q . data ) . map ( ( q ) => q . data . items )
57+
58+ // loading. should never happen because of prefetches
59+ if ( loadedRoutesLists . length < routers . items . length ) return null
6460
65- const RouterRows = ( { project , vpc , gateway } : PP . VpcInternetGateway ) => {
66- const { data : routers } = useQuery ( routerList ( { project , vpc } ) . optionsFn ( ) )
67- const matchingRoutes = routers ?. items . flatMap ( ( router ) =>
68- RouterRow ( { project , vpc , gateway , router : router . name } )
61+ return R . pipe (
62+ R . zip ( routerNames , loadedRoutesLists ) ,
63+ R . flatMap ( ( [ router , routes ] ) => routes . map ( ( route ) => [ router , route ] as const ) ) ,
64+ R . filter ( ( [ _ , r ] ) => r . target . type === 'internet_gateway' && r . target . value === gateway )
6965 )
70- return matchingRoutes ?. length ? (
71- matchingRoutes
72- ) : (
73- < Table . Row >
74- < Table . Cell colSpan = { 2 } className = "bg-secondary" >
75- No VPC routes target this gateway.
66+ }
67+
68+ function RouteRows ( { project, vpc, gateway } : PP . VpcInternetGateway ) {
69+ const matchingRoutes = useGatewayRoutes ( { project, vpc, gateway } )
70+
71+ if ( ! matchingRoutes ) return null
72+ if ( matchingRoutes . length === 0 ) return < RoutesEmpty />
73+
74+ return matchingRoutes . map ( ( [ router , route ] ) => (
75+ < Table . Row key = { route . id } >
76+ < Table . Cell className = "!bg-raise" > { router } </ Table . Cell >
77+ < Table . Cell className = "bg-raise" >
78+ < Link
79+ to = { pb . vpcRouterRouteEdit ( { project, vpc, router, route : route . name } ) }
80+ className = "link-with-underline text-sans-md"
81+ >
82+ { route . name }
83+ </ Link >
7684 </ Table . Cell >
7785 </ Table . Row >
78- )
86+ ) )
7987}
8088
8189const gatewayIpPoolList = ( { project, vpc, gateway } : PP . VpcInternetGateway ) =>
@@ -100,14 +108,13 @@ EditInternetGatewayForm.loader = async function ({ params }: LoaderFunctionArgs)
100108 } ) ,
101109 queryClient . prefetchQuery ( gatewayIpPoolList ( { project, vpc, gateway } ) . optionsFn ( ) ) ,
102110 queryClient . prefetchQuery ( gatewayIpAddressList ( { project, vpc, gateway } ) . optionsFn ( ) ) ,
103- ( await queryClient . fetchQuery ( routerList ( { project, vpc } ) . optionsFn ( ) ) ) . items . map (
104- ( router ) => {
111+ ... ( await queryClient . fetchQuery ( routerList ( { project, vpc } ) . optionsFn ( ) ) ) . items . map (
112+ ( router ) =>
105113 queryClient . prefetchQuery (
106114 routeList ( { project, vpc, router : router . name } ) . optionsFn ( )
107115 )
108- }
109116 ) ,
110- ] )
117+ ] satisfies Promise < unknown > [ ] )
111118 return null
112119}
113120
@@ -235,11 +242,13 @@ export function EditInternetGatewayForm() {
235242 </ SideModal . Heading >
236243 < Table >
237244 < Table . Header >
238- < Table . HeadCell > Router</ Table . HeadCell >
239- < Table . HeadCell > Route</ Table . HeadCell >
245+ < Table . HeaderRow >
246+ < Table . HeadCell > Router</ Table . HeadCell >
247+ < Table . HeadCell > Route</ Table . HeadCell >
248+ </ Table . HeaderRow >
240249 </ Table . Header >
241250 < Table . Body >
242- < RouterRows project = { project } vpc = { vpc } gateway = { gateway } />
251+ < RouteRows project = { project } vpc = { vpc } gateway = { gateway } />
243252 </ Table . Body >
244253 </ Table >
245254 </ div >
0 commit comments