Skip to content

Commit da7fe32

Browse files
authored
Fix row actions on instance NICs table closing when polling (#2460)
same trick as instance disks. fix row actions on nics table closing when polling
1 parent e0d52ef commit da7fe32

File tree

1 file changed

+65
-49
lines changed

1 file changed

+65
-49
lines changed

app/pages/project/instances/instance/tabs/NetworkingTab.tsx

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
usePrefetchedApiQuery,
1919
type ExternalIp,
2020
type InstanceNetworkInterface,
21+
type InstanceState,
2122
} from '@oxide/api'
2223
import { IpGlobal24Icon, Networking24Icon } from '@oxide/design-system/icons/react'
2324

@@ -110,7 +111,15 @@ NetworkingTab.loader = async ({ params }: LoaderFunctionArgs) => {
110111
return null
111112
}
112113

113-
const colHelper = createColumnHelper<InstanceNetworkInterface>()
114+
// Bit of a hack: by putting the instance state in the row data, we can avoid
115+
// remaking the row actions callback whenever the instance state changes, which
116+
// causes the whole table to get re-rendered, which jarringly closes any open
117+
// row actions menus
118+
type NicRow = InstanceNetworkInterface & {
119+
instanceState: InstanceState
120+
}
121+
122+
const colHelper = createColumnHelper<NicRow>()
114123
const staticCols = [
115124
colHelper.accessor('name', {
116125
header: 'name',
@@ -211,56 +220,58 @@ export function NetworkingTab() {
211220
path: { instance: instanceName },
212221
query: { project },
213222
})
214-
const canUpdateNic = instanceCan.updateNic(instance)
215223

216224
const makeActions = useCallback(
217-
(nic: InstanceNetworkInterface): MenuAction[] => [
218-
{
219-
label: 'Make primary',
220-
onActivate() {
221-
editNic({
222-
path: { interface: nic.name },
223-
query: instanceSelector,
224-
body: { ...nic, primary: true },
225-
})
226-
},
227-
disabled: nic.primary
228-
? 'This network interface is already set as primary'
229-
: !canUpdateNic && (
230-
<>
231-
The instance must be {updateNicStates} to change its primary network
232-
interface
233-
</>
234-
),
235-
},
236-
{
237-
label: 'Edit',
238-
onActivate() {
239-
setEditing(nic)
240-
},
241-
disabled: !canUpdateNic && (
242-
<>
243-
The instance must be {updateNicStates} before editing a network interface&apos;s
244-
settings
245-
</>
246-
),
247-
},
248-
{
249-
label: 'Delete',
250-
onActivate: confirmDelete({
251-
doDelete: () =>
252-
deleteNic({
225+
(nic: NicRow): MenuAction[] => {
226+
const canUpdateNic = instanceCan.updateNic({ runState: nic.instanceState })
227+
return [
228+
{
229+
label: 'Make primary',
230+
onActivate() {
231+
editNic({
253232
path: { interface: nic.name },
254233
query: instanceSelector,
255-
}),
256-
label: nic.name,
257-
}),
258-
disabled: !canUpdateNic && (
259-
<>The instance must be {updateNicStates} to delete a network interface</>
260-
),
261-
},
262-
],
263-
[canUpdateNic, deleteNic, editNic, instanceSelector]
234+
body: { ...nic, primary: true },
235+
})
236+
},
237+
disabled: nic.primary
238+
? 'This network interface is already set as primary'
239+
: !canUpdateNic && (
240+
<>
241+
The instance must be {updateNicStates} to change its primary network
242+
interface
243+
</>
244+
),
245+
},
246+
{
247+
label: 'Edit',
248+
onActivate() {
249+
setEditing(nic)
250+
},
251+
disabled: !canUpdateNic && (
252+
<>
253+
The instance must be {updateNicStates} before editing a network
254+
interface&apos;s settings
255+
</>
256+
),
257+
},
258+
{
259+
label: 'Delete',
260+
onActivate: confirmDelete({
261+
doDelete: () =>
262+
deleteNic({
263+
path: { interface: nic.name },
264+
query: instanceSelector,
265+
}),
266+
label: nic.name,
267+
}),
268+
disabled: !canUpdateNic && (
269+
<>The instance must be {updateNicStates} to delete a network interface</>
270+
),
271+
},
272+
]
273+
},
274+
[deleteNic, editNic, instanceSelector]
264275
)
265276

266277
const columns = useColsWithActions(staticCols, makeActions)
@@ -269,9 +280,14 @@ export function NetworkingTab() {
269280
query: { ...instanceSelector, limit: 1000 },
270281
}).data.items
271282

283+
const nicRows = useMemo(
284+
() => nics.map((nic) => ({ ...nic, instanceState: instance.runState })),
285+
[nics, instance]
286+
)
287+
272288
const tableInstance = useReactTable({
273289
columns,
274-
data: nics || [],
290+
data: nicRows,
275291
getCoreRowModel: getCoreRowModel(),
276292
})
277293

@@ -423,7 +439,7 @@ export function NetworkingTab() {
423439
<TableTitle id="nics-label">Network interfaces</TableTitle>
424440
<CreateButton
425441
onClick={() => setCreateModalOpen(true)}
426-
disabled={!canUpdateNic}
442+
disabled={!instanceCan.updateNic(instance)}
427443
disabledReason={
428444
<>
429445
A network interface cannot be created or edited unless the instance is{' '}

0 commit comments

Comments
 (0)