@@ -18,6 +18,7 @@ import {
1818 usePrefetchedApiQuery ,
1919 type ExternalIp ,
2020 type InstanceNetworkInterface ,
21+ type InstanceState ,
2122} from '@oxide/api'
2223import { 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 > ( )
114123const 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'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'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