@@ -18,6 +18,7 @@ import {
18
18
useApiQueryClient ,
19
19
usePrefetchedApiQuery ,
20
20
type Disk ,
21
+ type InstanceState ,
21
22
} from '@oxide/api'
22
23
import { Storage24Icon } from '@oxide/design-system/icons/react'
23
24
@@ -60,7 +61,15 @@ StorageTab.loader = async ({ params }: LoaderFunctionArgs) => {
60
61
return null
61
62
}
62
63
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 > ( )
64
73
const staticCols = [
65
74
colHelper . accessor ( 'name' , { header : 'Disk' } ) ,
66
75
colHelper . accessor ( 'size' , Columns . size ) ,
@@ -112,7 +121,7 @@ export function StorageTab() {
112
121
const { data : instance } = usePrefetchedApiQuery ( 'instanceView' , instancePathQuery )
113
122
114
123
const makeActions = useCallback (
115
- ( disk : Disk ) : MenuAction [ ] => [
124
+ ( disk : InstanceDisk ) : MenuAction [ ] => [
116
125
{
117
126
label : 'Snapshot' ,
118
127
disabled : ! diskCan . snapshot ( disk ) && (
@@ -135,7 +144,7 @@ export function StorageTab() {
135
144
// don't bother checking disk state: assume that if it is showing up
136
145
// in this list, it can be detached
137
146
label : 'Detach' ,
138
- disabled : ! instanceCan . detachDisk ( { runState : instance . runState } ) && (
147
+ disabled : ! instanceCan . detachDisk ( { runState : disk . instanceState } ) && (
139
148
< >
140
149
Instance must be < span className = "text-default" > stopped</ span > before disk can
141
150
be detached
@@ -146,9 +155,7 @@ export function StorageTab() {
146
155
} ,
147
156
} ,
148
157
] ,
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 ]
152
159
)
153
160
154
161
const attachDisk = useApiMutation ( 'instanceDiskAttach' , {
@@ -169,9 +176,14 @@ export function StorageTab() {
169
176
170
177
const { data : disks } = usePrefetchedApiQuery ( 'instanceDiskList' , instancePathQuery )
171
178
179
+ const rows = useMemo (
180
+ ( ) => disks . items . map ( ( disk ) => ( { ...disk , instanceState : instance . runState } ) ) ,
181
+ [ disks . items , instance . runState ]
182
+ )
183
+
172
184
const table = useReactTable ( {
173
185
columns : useColsWithActions ( staticCols , makeActions ) ,
174
- data : disks . items ,
186
+ data : rows ,
175
187
getCoreRowModel : getCoreRowModel ( ) ,
176
188
} )
177
189
0 commit comments