diff --git a/app/components/ExternalIps.tsx b/app/components/ExternalIps.tsx index eb9e03693..918d77706 100644 --- a/app/components/ExternalIps.tsx +++ b/app/components/ExternalIps.tsx @@ -6,11 +6,15 @@ * Copyright Oxide Computer Company */ +import { Link } from 'react-router-dom' + import { useApiQuery } from '@oxide/api' import { EmptyCell, SkeletonCell } from '~/table/cells/EmptyCell' import { CopyableIp } from '~/ui/lib/CopyableIp' +import { Slash } from '~/ui/lib/Slash' import { intersperse } from '~/util/array' +import { pb } from '~/util/path-builder' import type * as PP from '~/util/path-params' export function ExternalIps({ project, instance }: PP.Instance) { @@ -22,12 +26,29 @@ export function ExternalIps({ project, instance }: PP.Instance) { const ips = data?.items if (!ips || ips.length === 0) return + // create a copy of ips so we don't mutate the original; move ephemeral ip to the end + const orderedIps = [...ips].sort((a) => (a.kind === 'ephemeral' ? 1 : -1)) + const ipsToShow = orderedIps.slice(0, 2) + const overflowCount = orderedIps.length - ipsToShow.length + + // create a list of CopyableIp components + const links = ipsToShow.map((eip) => ) + + // if there are more than 2 ips, add a link to the instance networking page + if (overflowCount > 0) { + links.push( + + +{overflowCount} + + ) + } + return ( -
- {intersperse( - ips.map((eip) => ), - / - )} +
+ {intersperse(links, )}
) } diff --git a/test/e2e/instance-networking.e2e.ts b/test/e2e/instance-networking.e2e.ts index f74b1b91b..53f840d4e 100644 --- a/test/e2e/instance-networking.e2e.ts +++ b/test/e2e/instance-networking.e2e.ts @@ -122,6 +122,8 @@ test('Instance networking tab — floating IPs', async ({ page }) => { await expectRowVisible(externalIpTable, { ip: '123.4.56.0', Kind: 'ephemeral' }) await expectRowVisible(externalIpTable, { ip: '123.4.56.5', Kind: 'floating' }) + await expect(page.getByText('external IPs123.4.56.5/123.4.56.0')).toBeVisible() + // Attach a new external IP await attachFloatingIpButton.click() await expectVisible(page, ['role=heading[name="Attach floating IP"]']) @@ -143,9 +145,14 @@ test('Instance networking tab — floating IPs', async ({ page }) => { // Verify that the "Attach floating IP" button is disabled, since there shouldn't be any more IPs to attach await expect(attachFloatingIpButton).toBeDisabled() + // Verify that the External IPs table row has a +1 in it + await expect(page.getByText('external IPs123.4.56.5/123.4.56.4/+1')).toBeVisible() + // Detach one of the external IPs await clickRowAction(page, 'cola-float', 'Detach') await page.getByRole('button', { name: 'Confirm' }).click() + await expect(page.getByText('external IPs123.4.56.5/123.4.56.4/+1')).toBeHidden() + await expect(page.getByText('external IPs123.4.56.4/123.4.56.0')).toBeVisible() // Since we detached it, we don't expect to see the row any longer await expect(externalIpTable.getByRole('cell', { name: 'cola-float' })).toBeHidden()