From c0e69dcf97e9786c753764c45cc66606b4dad6e7 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 9 Oct 2024 14:03:21 -0400 Subject: [PATCH 1/3] Extract IpPoolCell so we can use it in other places --- .../project/floating-ips/FloatingIpsPage.tsx | 23 +++++-------------- app/table/cells/IpPoolCell.tsx | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 app/table/cells/IpPoolCell.tsx diff --git a/app/pages/project/floating-ips/FloatingIpsPage.tsx b/app/pages/project/floating-ips/FloatingIpsPage.tsx index a8e35941ad..fc246cd182 100644 --- a/app/pages/project/floating-ips/FloatingIpsPage.tsx +++ b/app/pages/project/floating-ips/FloatingIpsPage.tsx @@ -13,7 +13,6 @@ import { Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router-dom' import { apiQueryClient, useApiMutation, - useApiQuery, useApiQueryClient, usePrefetchedApiQuery, type FloatingIp, @@ -28,8 +27,8 @@ import { getProjectSelector, useProjectSelector } from '~/hooks/use-params' import { confirmAction } from '~/stores/confirm-action' import { confirmDelete } from '~/stores/confirm-delete' import { addToast } from '~/stores/toast' -import { EmptyCell } from '~/table/cells/EmptyCell' import { InstanceLinkCell } from '~/table/cells/InstanceLinkCell' +import { IpPoolCell } from '~/table/cells/IpPoolCell' import { useColsWithActions, type MenuAction } from '~/table/columns/action-col' import { Columns } from '~/table/columns/common' import { PAGE_SIZE, useQueryTable } from '~/table/QueryTable' @@ -39,7 +38,6 @@ import { Message } from '~/ui/lib/Message' import { Modal } from '~/ui/lib/Modal' import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' import { TableActions } from '~/ui/lib/Table' -import { Tooltip } from '~/ui/lib/Tooltip' import { ALL_ISH } from '~/util/consts' import { docLinks } from '~/util/links' import { pb } from '~/util/path-builder' @@ -63,6 +61,9 @@ FloatingIpsPage.loader = async ({ params }: LoaderFunctionArgs) => { apiQueryClient.prefetchQuery('instanceList', { query: { project }, }), + // 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 apiQueryClient .fetchQuery('projectIpPoolList', { query: { limit: ALL_ISH } }) .then((pools) => { @@ -78,18 +79,6 @@ FloatingIpsPage.loader = async ({ params }: LoaderFunctionArgs) => { return null } -const IpPoolCell = ({ ipPoolId }: { ipPoolId: string }) => { - const pool = useApiQuery('projectIpPoolView', { path: { pool: ipPoolId } }).data - if (!pool) return - return pool.description ? ( - - {pool.name} - - ) : ( - <>{pool.name} - ) -} - const colHelper = createColumnHelper() const staticCols = [ colHelper.accessor('name', {}), @@ -98,12 +87,12 @@ const staticCols = [ header: 'IP address', }), colHelper.accessor('ipPoolId', { - cell: (info) => , header: 'IP pool', + cell: (info) => , }), colHelper.accessor('instanceId', { - cell: (info) => , header: 'Attached to instance', + cell: (info) => , }), ] diff --git a/app/table/cells/IpPoolCell.tsx b/app/table/cells/IpPoolCell.tsx new file mode 100644 index 0000000000..7f9148e82c --- /dev/null +++ b/app/table/cells/IpPoolCell.tsx @@ -0,0 +1,23 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { useApiQuery } from '~/api' +import { Tooltip } from '~/ui/lib/Tooltip' + +import { EmptyCell } from './EmptyCell' + +export const IpPoolCell = ({ ipPoolId }: { ipPoolId: string }) => { + const pool = useApiQuery('projectIpPoolView', { path: { pool: ipPoolId } }).data + if (!pool) return + return pool.description ? ( + + {pool.name} + + ) : ( + <>{pool.name} + ) +} From 7ab417d09961185a3682b34f8c81102473d6e3d4 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 9 Oct 2024 15:39:05 -0400 Subject: [PATCH 2/3] Tooltip returns child if no tooltip contents passed in --- app/table/cells/IpPoolCell.tsx | 5 ++--- app/ui/lib/Tooltip.tsx | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/table/cells/IpPoolCell.tsx b/app/table/cells/IpPoolCell.tsx index 7f9148e82c..bc3fc5bcfa 100644 --- a/app/table/cells/IpPoolCell.tsx +++ b/app/table/cells/IpPoolCell.tsx @@ -12,12 +12,11 @@ import { EmptyCell } from './EmptyCell' export const IpPoolCell = ({ ipPoolId }: { ipPoolId: string }) => { const pool = useApiQuery('projectIpPoolView', { path: { pool: ipPoolId } }).data - if (!pool) return - return pool.description ? ( + return pool ? ( {pool.name} ) : ( - <>{pool.name} + ) } diff --git a/app/ui/lib/Tooltip.tsx b/app/ui/lib/Tooltip.tsx index ece688b0c7..bcda6f480d 100644 --- a/app/ui/lib/Tooltip.tsx +++ b/app/ui/lib/Tooltip.tsx @@ -39,7 +39,7 @@ export interface TooltipProps { /** The target the tooltip hovers near; can not be a raw string. */ children?: ReactElement /** The text to appear on hover/focus */ - content: string | React.ReactNode + content?: string | React.ReactNode /** * `undefined` means automatic, which means the tooltip will be placed in the * best position based on the available space. When any other placement is @@ -86,6 +86,8 @@ export const Tooltip = forwardRef( const zIndex = usePopoverZIndex() + if (!content) return child + return ( <> {child} From 646ddab7f8b864623bbeb5495f134df74c08ec94 Mon Sep 17 00:00:00 2001 From: Charlie Park Date: Wed, 9 Oct 2024 15:48:03 -0400 Subject: [PATCH 3/3] early return EmptyCell when appropriate --- app/table/cells/IpPoolCell.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/table/cells/IpPoolCell.tsx b/app/table/cells/IpPoolCell.tsx index bc3fc5bcfa..f15a03fd87 100644 --- a/app/table/cells/IpPoolCell.tsx +++ b/app/table/cells/IpPoolCell.tsx @@ -12,11 +12,10 @@ import { EmptyCell } from './EmptyCell' export const IpPoolCell = ({ ipPoolId }: { ipPoolId: string }) => { const pool = useApiQuery('projectIpPoolView', { path: { pool: ipPoolId } }).data - return pool ? ( + if (!pool) return + return ( {pool.name} - ) : ( - ) }