@@ -18,6 +18,7 @@ import {
1818 useApiQueryClient ,
1919 usePrefetchedApiQuery ,
2020 type Disk ,
21+ type InstanceState ,
2122} from '@oxide/api'
2223import { Storage24Icon } from '@oxide/design-system/icons/react'
2324
@@ -60,7 +61,15 @@ StorageTab.loader = async ({ params }: LoaderFunctionArgs) => {
6061 return null
6162}
6263
63- const colHelper = createColumnHelper < Disk > ( )
64+ // Bit of a hack: by putting the instance state in the row data, we can avoid
65+ // remaking the row actions callback whenever the instance state changes, which
66+ // causes the whole table to get re-rendered, which jarringly closes any open
67+ // row actions menus
68+ type InstanceDisk = Disk & {
69+ instanceState : InstanceState
70+ }
71+
72+ const colHelper = createColumnHelper < InstanceDisk > ( )
6473const staticCols = [
6574 colHelper . accessor ( 'name' , { header : 'Disk' } ) ,
6675 colHelper . accessor ( 'size' , Columns . size ) ,
@@ -112,7 +121,7 @@ export function StorageTab() {
112121 const { data : instance } = usePrefetchedApiQuery ( 'instanceView' , instancePathQuery )
113122
114123 const makeActions = useCallback (
115- ( disk : Disk ) : MenuAction [ ] => [
124+ ( disk : InstanceDisk ) : MenuAction [ ] => [
116125 {
117126 label : 'Snapshot' ,
118127 disabled : ! diskCan . snapshot ( disk ) && (
@@ -135,7 +144,7 @@ export function StorageTab() {
135144 // don't bother checking disk state: assume that if it is showing up
136145 // in this list, it can be detached
137146 label : 'Detach' ,
138- disabled : ! instanceCan . detachDisk ( { runState : instance . runState } ) && (
147+ disabled : ! instanceCan . detachDisk ( { runState : disk . instanceState } ) && (
139148 < >
140149 Instance must be < span className = "text-default" > stopped</ span > before disk can
141150 be detached
@@ -146,9 +155,7 @@ export function StorageTab() {
146155 } ,
147156 } ,
148157 ] ,
149- // important to pass instance.runState because instance is not referentially
150- // stable when we are polling when instance is in transition
151- [ detachDisk , instance . runState , instancePathQuery , createSnapshot , project ]
158+ [ detachDisk , instancePathQuery , createSnapshot , project ]
152159 )
153160
154161 const attachDisk = useApiMutation ( 'instanceDiskAttach' , {
@@ -169,9 +176,14 @@ export function StorageTab() {
169176
170177 const { data : disks } = usePrefetchedApiQuery ( 'instanceDiskList' , instancePathQuery )
171178
179+ const rows = useMemo (
180+ ( ) => disks . items . map ( ( disk ) => ( { ...disk , instanceState : instance . runState } ) ) ,
181+ [ disks . items , instance . runState ]
182+ )
183+
172184 const table = useReactTable ( {
173185 columns : useColsWithActions ( staticCols , makeActions ) ,
174- data : disks . items ,
186+ data : rows ,
175187 getCoreRowModel : getCoreRowModel ( ) ,
176188 } )
177189
0 commit comments