Skip to content

Commit 6a005a0

Browse files
authored
Instances table: remove hostname, normal row height, split CPU/RAM (#2389)
* remove hostname column from instances table * split cpu and ram into separate cols, make rows normal height * add test, remove modified column from sled instances
1 parent 2f83a1f commit 6a005a0

File tree

6 files changed

+62
-26
lines changed

6 files changed

+62
-26
lines changed

app/components/TimeAgo.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,8 @@ export const TimeAgo = ({
2626
</div>
2727
)
2828
return (
29-
<span className="mt-0.5">
30-
<Tooltip content={content} placement={placement}>
31-
<span className="text-sans-sm text-tertiary">{timeAgoAbbr(datetime)}</span>
32-
</Tooltip>
33-
</span>
29+
<Tooltip content={content} placement={placement}>
30+
<span className="text-sans-sm text-tertiary">{timeAgoAbbr(datetime)}</span>
31+
</Tooltip>
3432
)
3533
}

app/pages/project/instances/InstancesPage.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Copyright Oxide Computer Company
77
*/
88
import { createColumnHelper } from '@tanstack/react-table'
9+
import { filesize } from 'filesize'
910
import { useMemo } from 'react'
1011
import { useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
1112

@@ -20,7 +21,6 @@ import { Instances16Icon, Instances24Icon } from '@oxide/design-system/icons/rea
2021
import { DocsPopover } from '~/components/DocsPopover'
2122
import { RefreshButton } from '~/components/RefreshButton'
2223
import { getProjectSelector, useProjectSelector, useQuickActions } from '~/hooks'
23-
import { InstanceResourceCell } from '~/table/cells/InstanceResourceCell'
2424
import { InstanceStatusCell } from '~/table/cells/InstanceStatusCell'
2525
import { makeLinkCell } from '~/table/cells/LinkCell'
2626
import { getActionsCol } from '~/table/columns/action-col'
@@ -99,21 +99,32 @@ export function InstancesPage() {
9999
colHelper.accessor('name', {
100100
cell: makeLinkCell((instance) => pb.instance({ project, instance })),
101101
}),
102-
colHelper.accessor((i) => ({ ncpus: i.ncpus, memory: i.memory }), {
103-
header: 'CPU, RAM',
104-
cell: (info) => <InstanceResourceCell value={info.getValue()} />,
102+
colHelper.accessor('ncpus', {
103+
header: 'CPU',
104+
cell: (info) => (
105+
<>
106+
{info.getValue()} <span className="ml-1 text-quaternary">vCPU</span>
107+
</>
108+
),
109+
}),
110+
colHelper.accessor('memory', {
111+
header: 'Memory',
112+
cell: (info) => {
113+
const memory = filesize(info.getValue(), { output: 'object', base: 2 })
114+
return (
115+
<>
116+
{memory.value} <span className="ml-1 text-quaternary">{memory.unit}</span>
117+
</>
118+
)
119+
},
105120
}),
106121
colHelper.accessor(
107-
(i) => ({
108-
runState: i.runState,
109-
timeRunStateUpdated: i.timeRunStateUpdated,
110-
}),
122+
(i) => ({ runState: i.runState, timeRunStateUpdated: i.timeRunStateUpdated }),
111123
{
112124
header: 'status',
113125
cell: (info) => <InstanceStatusCell value={info.getValue()} />,
114126
}
115127
),
116-
colHelper.accessor('hostname', {}),
117128
colHelper.accessor('timeCreated', Columns.timeCreated),
118129
getActionsCol(makeActions),
119130
],
@@ -137,7 +148,7 @@ export function InstancesPage() {
137148
<RefreshButton onClick={refetchInstances} />
138149
<CreateLink to={pb.instancesNew({ project })}>New Instance</CreateLink>
139150
</TableActions>
140-
<Table columns={columns} emptyState={<EmptyState />} rowHeight="large" />
151+
<Table columns={columns} emptyState={<EmptyState />} />
141152
</>
142153
)
143154
}

app/pages/system/inventory/sled/SledInstancesTab.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,17 @@ const staticCols = [
5656
)
5757
},
5858
}),
59+
// we don't show run state last update time like on project instances because
60+
// it's not in this response
5961
colHelper.accessor('state', {
6062
header: 'status',
61-
cell: (info) => <InstanceStatusBadge key="run-state" status={info.getValue()} />,
63+
cell: (info) => <InstanceStatusBadge status={info.getValue()} />,
6264
}),
6365
colHelper.accessor((i) => R.pick(i, ['memory', 'ncpus']), {
6466
header: 'specs',
6567
cell: (info) => <InstanceResourceCell value={info.getValue()} />,
6668
}),
6769
colHelper.accessor('timeCreated', Columns.timeCreated),
68-
colHelper.accessor('timeModified', Columns.timeModified),
6970
]
7071

7172
export function SledInstancesTab() {

app/table/cells/InstanceStatusCell.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ type Props = { value: Pick<Instance, 'runState' | 'timeRunStateUpdated'> }
1414

1515
export const InstanceStatusCell = ({ value }: Props) => {
1616
return (
17-
<div className="flex flex-col">
18-
<InstanceStatusBadge key="run-state" status={value.runState} />
17+
<div className="flex items-center gap-1.5">
18+
<InstanceStatusBadge status={value.runState} />
1919
<TimeAgo tooltipText="Run state updated" datetime={value.timeRunStateUpdated} />
2020
</div>
2121
)

mock-api/instance.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
*/
88
import type { Instance } from '@oxide/api'
99

10+
import { GiB } from '~/util/units'
11+
1012
import type { Json } from './json-type'
1113
import { project } from './project'
1214

1315
export const instance: Json<Instance> = {
1416
id: '935499b3-fd96-432a-9c21-83a3dc1eece4',
1517
name: 'db1',
16-
ncpus: 7,
17-
memory: 1024 * 1024 * 256,
18+
ncpus: 2,
19+
memory: 4 * GiB,
1820
description: 'an instance',
1921
hostname: 'oxide.com',
2022
project_id: project.id,
@@ -27,8 +29,8 @@ export const instance: Json<Instance> = {
2729
const failedInstance: Json<Instance> = {
2830
id: 'b5946edc-5bed-4597-88ab-9a8beb9d32a4',
2931
name: 'you-fail',
30-
ncpus: 7,
31-
memory: 1024 * 1024 * 256,
32+
ncpus: 4,
33+
memory: 6 * GiB,
3234
description: 'a failed instance',
3335
hostname: 'oxide.com',
3436
project_id: project.id,
@@ -41,8 +43,8 @@ const failedInstance: Json<Instance> = {
4143
const startingInstance: Json<Instance> = {
4244
id: '16737f54-1f76-4c96-8b7c-9d24971c1d62',
4345
name: 'not-there-yet',
44-
ncpus: 7,
45-
memory: 1024 * 1024 * 256,
46+
ncpus: 2,
47+
memory: 8 * GiB,
4648
description: 'a starting instance',
4749
hostname: 'oxide.com',
4850
project_id: project.id,

test/e2e/instance.e2e.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { expect, refreshInstance, sleep, test } from './utils'
8+
import { expect, expectRowVisible, refreshInstance, sleep, test } from './utils'
99

1010
test('can delete a failed instance', async ({ page }) => {
1111
await page.goto('/projects/mock-project/instances')
@@ -78,3 +78,27 @@ test('delete from instance detail', async ({ page }) => {
7878
await expect(page.getByRole('cell', { name: 'db1' })).toBeVisible()
7979
await expect(page.getByRole('cell', { name: 'you-fail' })).toBeHidden()
8080
})
81+
82+
test('instance table', async ({ page }) => {
83+
await page.goto('/projects/mock-project/instances')
84+
85+
const table = page.getByRole('table')
86+
await expectRowVisible(table, {
87+
name: 'db1',
88+
CPU: '2 vCPU',
89+
Memory: '4 GiB',
90+
status: expect.stringMatching(/^running\d+s$/),
91+
})
92+
await expectRowVisible(table, {
93+
name: 'you-fail',
94+
CPU: '4 vCPU',
95+
Memory: '6 GiB',
96+
status: expect.stringMatching(/^failed\d+s$/),
97+
})
98+
await expectRowVisible(table, {
99+
name: 'not-there-yet',
100+
CPU: '2 vCPU',
101+
Memory: '8 GiB',
102+
status: expect.stringMatching(/^starting\d+s$/),
103+
})
104+
})

0 commit comments

Comments
 (0)