From 5c2ff2810f2be400d61e0291cf855f9c7b83c57a Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 14:55:05 -0800 Subject: [PATCH 1/7] Add minitable to top of floating-ip-edit --- app/forms/floating-ip-edit.tsx | 55 +++++++++++++++++-- .../project/floating-ips/FloatingIpsPage.tsx | 4 +- app/table/cells/InstanceLinkCell.tsx | 4 +- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/app/forms/floating-ip-edit.tsx b/app/forms/floating-ip-edit.tsx index 17469321e8..f3aef54fe0 100644 --- a/app/forms/floating-ip-edit.tsx +++ b/app/forms/floating-ip-edit.tsx @@ -6,9 +6,16 @@ * Copyright Oxide Computer Company */ import { useForm } from 'react-hook-form' -import { useNavigate, type LoaderFunctionArgs } from 'react-router-dom' +import { Link, useNavigate, type LoaderFunctionArgs } from 'react-router-dom' -import { apiq, queryClient, useApiMutation, usePrefetchedApiQuery } from '@oxide/api' +import { + apiq, + getListQFn, + queryClient, + useApiMutation, + usePrefetchedApiQuery, + usePrefetchedQuery, +} from '@oxide/api' import { DescriptionField } from '~/components/form/fields/DescriptionField' import { NameField } from '~/components/form/fields/NameField' @@ -16,15 +23,25 @@ import { SideModalForm } from '~/components/form/SideModalForm' import { HL } from '~/components/HL' import { getFloatingIpSelector, useFloatingIpSelector } from '~/hooks/use-params' import { addToast } from '~/stores/toast' +import { EmptyCell } from '~/table/cells/EmptyCell' +import { IpPoolCell } from '~/table/cells/IpPoolCell' +import { CopyableIp } from '~/ui/lib/CopyableIp' +import { PropertiesTable } from '~/ui/lib/PropertiesTable' +import { ALL_ISH } from '~/util/consts' import type * as PP from '~/util/path-params' import { pb } from 'app/util/path-builder' const floatingIpView = ({ project, floatingIp }: PP.FloatingIp) => apiq('floatingIpView', { path: { floatingIp }, query: { project } }) +const instanceList = (project: string) => + getListQFn('instanceList', { query: { project, limit: ALL_ISH } }) EditFloatingIpSideModalForm.loader = async ({ params }: LoaderFunctionArgs) => { const selector = getFloatingIpSelector(params) - await queryClient.prefetchQuery(floatingIpView(selector)) + await Promise.all([ + queryClient.fetchQuery(floatingIpView(selector)), + queryClient.fetchQuery(instanceList(selector.project).optionsFn()), + ]) return null } @@ -39,6 +56,12 @@ export function EditFloatingIpSideModalForm() { path: { floatingIp: floatingIpSelector.floatingIp }, query: { project: floatingIpSelector.project }, }) + const { name, description, ip, ipPoolId, instanceId } = floatingIp + + const { data: instances } = usePrefetchedQuery( + instanceList(floatingIpSelector.project).optionsFn() + ) + const instanceName = instances.items.find((i) => i.id === instanceId)?.name const editFloatingIp = useApiMutation('floatingIpUpdate', { onSuccess(_floatingIp) { @@ -48,8 +71,7 @@ export function EditFloatingIpSideModalForm() { }, }) - const form = useForm({ defaultValues: floatingIp }) - + const form = useForm({ defaultValues: { name, description } }) return ( + + + + + + + + + {instanceName ? ( + + {instanceName} + + ) : ( + + )} + + diff --git a/app/pages/project/floating-ips/FloatingIpsPage.tsx b/app/pages/project/floating-ips/FloatingIpsPage.tsx index 39053df5ef..b6ce6e9e4a 100644 --- a/app/pages/project/floating-ips/FloatingIpsPage.tsx +++ b/app/pages/project/floating-ips/FloatingIpsPage.tsx @@ -61,8 +61,8 @@ const instanceList = (project: string) => FloatingIpsPage.loader = async ({ params }: LoaderFunctionArgs) => { const { project } = getProjectSelector(params) await Promise.all([ - queryClient.prefetchQuery(fipList(project).optionsFn()), - queryClient.prefetchQuery(instanceList(project).optionsFn()), + queryClient.fetchQuery(fipList(project).optionsFn()), + queryClient.fetchQuery(instanceList(project).optionsFn()), // fetch IP Pools and preload into RQ cache so fetches by ID in // IpPoolCell can be mostly instant yet gracefully fall back to // fetching individually if we don't fetch them all here diff --git a/app/table/cells/InstanceLinkCell.tsx b/app/table/cells/InstanceLinkCell.tsx index b2fbe019ca..ed706e7365 100644 --- a/app/table/cells/InstanceLinkCell.tsx +++ b/app/table/cells/InstanceLinkCell.tsx @@ -11,7 +11,7 @@ import { useApiQuery } from '@oxide/api' import { useProjectSelector } from '~/hooks/use-params' import { pb } from '~/util/path-builder' -import { SkeletonCell } from './EmptyCell' +import { EmptyCell, SkeletonCell } from './EmptyCell' import { LinkCell } from './LinkCell' export const InstanceLinkCell = ({ instanceId }: { instanceId?: string }) => { @@ -23,7 +23,7 @@ export const InstanceLinkCell = ({ instanceId }: { instanceId?: string }) => { ) // has to be after the hooks because hooks can't be executed conditionally - if (!instanceId) return null + if (!instanceId) return if (!instance) return return ( From 311e67d693f333baa9cdced6c371d29466936cfd Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 14:58:37 -0800 Subject: [PATCH 2/7] small simplification to reduce changes in PR --- app/forms/floating-ip-edit.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/forms/floating-ip-edit.tsx b/app/forms/floating-ip-edit.tsx index f3aef54fe0..4515bec12f 100644 --- a/app/forms/floating-ip-edit.tsx +++ b/app/forms/floating-ip-edit.tsx @@ -56,12 +56,11 @@ export function EditFloatingIpSideModalForm() { path: { floatingIp: floatingIpSelector.floatingIp }, query: { project: floatingIpSelector.project }, }) - const { name, description, ip, ipPoolId, instanceId } = floatingIp const { data: instances } = usePrefetchedQuery( instanceList(floatingIpSelector.project).optionsFn() ) - const instanceName = instances.items.find((i) => i.id === instanceId)?.name + const instanceName = instances.items.find((i) => i.id === floatingIp.instanceId)?.name const editFloatingIp = useApiMutation('floatingIpUpdate', { onSuccess(_floatingIp) { @@ -71,7 +70,7 @@ export function EditFloatingIpSideModalForm() { }, }) - const form = useForm({ defaultValues: { name, description } }) + const form = useForm({ defaultValues: floatingIp }) return ( - + - + {instanceName ? ( From 4d90b7989579d87fa45ea9e70a97729c806d5e80 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 15:15:45 -0800 Subject: [PATCH 3/7] Test update for EmptyCell in place of an empty cell --- test/e2e/disks.e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/disks.e2e.ts b/test/e2e/disks.e2e.ts index e735f7dad6..85fd6d35c1 100644 --- a/test/e2e/disks.e2e.ts +++ b/test/e2e/disks.e2e.ts @@ -29,7 +29,7 @@ test('List disks and snapshot', async ({ page }) => { state: 'attached', }) await expectRowVisible(table, { - 'Attached to': '', + 'Attached to': '—', name: 'disk-3', size: '6 GiB', state: 'detached', From f9ff4bc4052bbc1872bc74f42d34630fe2e73d71 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 15:30:36 -0800 Subject: [PATCH 4/7] move from usePrefetchedApiQuery to usePrefetchedQuery --- app/forms/floating-ip-edit.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/forms/floating-ip-edit.tsx b/app/forms/floating-ip-edit.tsx index 4515bec12f..45de6143ff 100644 --- a/app/forms/floating-ip-edit.tsx +++ b/app/forms/floating-ip-edit.tsx @@ -13,7 +13,6 @@ import { getListQFn, queryClient, useApiMutation, - usePrefetchedApiQuery, usePrefetchedQuery, } from '@oxide/api' @@ -52,11 +51,7 @@ export function EditFloatingIpSideModalForm() { const onDismiss = () => navigate(pb.floatingIps({ project: floatingIpSelector.project })) - const { data: floatingIp } = usePrefetchedApiQuery('floatingIpView', { - path: { floatingIp: floatingIpSelector.floatingIp }, - query: { project: floatingIpSelector.project }, - }) - + const { data: floatingIp } = usePrefetchedQuery(floatingIpView(floatingIpSelector)) const { data: instances } = usePrefetchedQuery( instanceList(floatingIpSelector.project).optionsFn() ) From a40237ff9b3846e6bd3353d4a3371a6794c000b4 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 15:38:14 -0800 Subject: [PATCH 5/7] Oops; added other relevant data: id, dates --- app/forms/floating-ip-edit.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/forms/floating-ip-edit.tsx b/app/forms/floating-ip-edit.tsx index 45de6143ff..71d3670e77 100644 --- a/app/forms/floating-ip-edit.tsx +++ b/app/forms/floating-ip-edit.tsx @@ -25,7 +25,9 @@ import { addToast } from '~/stores/toast' import { EmptyCell } from '~/table/cells/EmptyCell' import { IpPoolCell } from '~/table/cells/IpPoolCell' import { CopyableIp } from '~/ui/lib/CopyableIp' +import { DateTime } from '~/ui/lib/DateTime' import { PropertiesTable } from '~/ui/lib/PropertiesTable' +import { Truncate } from '~/ui/lib/Truncate' import { ALL_ISH } from '~/util/consts' import type * as PP from '~/util/path-params' import { pb } from 'app/util/path-builder' @@ -83,6 +85,15 @@ export function EditFloatingIpSideModalForm() { submitError={editFloatingIp.error} > + + + + + + + + + From c2406cdda264f7abe99f1f93883c51faef5b5b26 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 18 Dec 2024 15:48:19 -0800 Subject: [PATCH 6/7] remove unrelated EmptyCell change --- app/table/cells/InstanceLinkCell.tsx | 4 ++-- test/e2e/disks.e2e.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/table/cells/InstanceLinkCell.tsx b/app/table/cells/InstanceLinkCell.tsx index ed706e7365..b2fbe019ca 100644 --- a/app/table/cells/InstanceLinkCell.tsx +++ b/app/table/cells/InstanceLinkCell.tsx @@ -11,7 +11,7 @@ import { useApiQuery } from '@oxide/api' import { useProjectSelector } from '~/hooks/use-params' import { pb } from '~/util/path-builder' -import { EmptyCell, SkeletonCell } from './EmptyCell' +import { SkeletonCell } from './EmptyCell' import { LinkCell } from './LinkCell' export const InstanceLinkCell = ({ instanceId }: { instanceId?: string }) => { @@ -23,7 +23,7 @@ export const InstanceLinkCell = ({ instanceId }: { instanceId?: string }) => { ) // has to be after the hooks because hooks can't be executed conditionally - if (!instanceId) return + if (!instanceId) return null if (!instance) return return ( diff --git a/test/e2e/disks.e2e.ts b/test/e2e/disks.e2e.ts index 85fd6d35c1..e735f7dad6 100644 --- a/test/e2e/disks.e2e.ts +++ b/test/e2e/disks.e2e.ts @@ -29,7 +29,7 @@ test('List disks and snapshot', async ({ page }) => { state: 'attached', }) await expectRowVisible(table, { - 'Attached to': '—', + 'Attached to': '', name: 'disk-3', size: '6 GiB', state: 'detached', From d5b167ea6f7adb205bd9b3aef3df8775cf1da2d8 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Thu, 19 Dec 2024 10:23:01 -0800 Subject: [PATCH 7/7] Incorporate new PropertesTable rows --- app/forms/floating-ip-edit.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/app/forms/floating-ip-edit.tsx b/app/forms/floating-ip-edit.tsx index 71d3670e77..259c8b6f80 100644 --- a/app/forms/floating-ip-edit.tsx +++ b/app/forms/floating-ip-edit.tsx @@ -25,9 +25,7 @@ import { addToast } from '~/stores/toast' import { EmptyCell } from '~/table/cells/EmptyCell' import { IpPoolCell } from '~/table/cells/IpPoolCell' import { CopyableIp } from '~/ui/lib/CopyableIp' -import { DateTime } from '~/ui/lib/DateTime' import { PropertiesTable } from '~/ui/lib/PropertiesTable' -import { Truncate } from '~/ui/lib/Truncate' import { ALL_ISH } from '~/util/consts' import type * as PP from '~/util/path-params' import { pb } from 'app/util/path-builder' @@ -85,15 +83,9 @@ export function EditFloatingIpSideModalForm() { submitError={editFloatingIp.error} > - - - - - - - - - + + +