55 *
66 * Copyright Oxide Computer Company
77 */
8+ import { createColumnHelper } from '@tanstack/react-table'
9+ import { useCallback } from 'react'
810import { Link , Outlet , type LoaderFunctionArgs } from 'react-router-dom'
911
1012import {
@@ -21,10 +23,11 @@ import { DiskStatusBadge } from '~/components/StatusBadge'
2123import { getProjectSelector , useProjectSelector , useToast } from '~/hooks'
2224import { confirmDelete } from '~/stores/confirm-delete'
2325import { DateCell } from '~/table/cells/DateCell'
26+ import { defaultCell } from '~/table/cells/DefaultCell'
2427import { InstanceLinkCell } from '~/table/cells/InstanceLinkCell'
2528import { SizeCell } from '~/table/cells/SizeCell'
26- import type { MenuAction } from '~/table/columns/action-col'
27- import { useQueryTable } from '~/table/QueryTable '
29+ import { useColsWithActions , type MenuAction } from '~/table/columns/action-col'
30+ import { useQueryTable2 } from '~/table/QueryTable2 '
2831import { buttonStyle } from '~/ui/lib/Button'
2932import { EmptyMessage } from '~/ui/lib/EmptyMessage'
3033import { PageHeader , PageTitle } from '~/ui/lib/PageHeader'
@@ -68,10 +71,31 @@ DisksPage.loader = async ({ params }: LoaderFunctionArgs) => {
6871 return null
6972}
7073
74+ const colHelper = createColumnHelper < Disk > ( )
75+
76+ const staticCols = [
77+ colHelper . accessor ( 'name' , { cell : defaultCell } ) ,
78+ // sneaky: rather than looking at particular states, just look at
79+ // whether it has an instance field
80+ colHelper . accessor ( ( disk ) => ( 'instance' in disk . state ? disk . state . instance : null ) , {
81+ header : 'Attached to' ,
82+ cell : ( props ) => < InstanceLinkCell value = { props . getValue ( ) } /> ,
83+ } ) ,
84+ colHelper . accessor ( 'size' , { cell : ( props ) => < SizeCell value = { props . getValue ( ) } /> } ) ,
85+ colHelper . accessor ( 'state.state' , {
86+ header : 'Status' ,
87+ cell : ( props ) => < DiskStatusBadge status = { props . getValue ( ) } /> ,
88+ } ) ,
89+ colHelper . accessor ( 'timeCreated' , {
90+ header : 'Created' ,
91+ cell : ( props ) => < DateCell value = { props . getValue ( ) } /> ,
92+ } ) ,
93+ ]
94+
7195export function DisksPage ( ) {
7296 const queryClient = useApiQueryClient ( )
73- const projectSelector = useProjectSelector ( )
74- const { Table, Column } = useQueryTable ( 'diskList' , { query : projectSelector } )
97+ const { project } = useProjectSelector ( )
98+ const { Table } = useQueryTable2 ( 'diskList' , { query : { project } } )
7599 const addToast = useToast ( )
76100
77101 const deleteDisk = useApiMutation ( 'diskDelete' , {
@@ -94,72 +118,59 @@ export function DisksPage() {
94118 } ,
95119 } )
96120
97- const makeActions = ( disk : Disk ) : MenuAction [ ] => [
98- {
99- label : 'Snapshot' ,
100- onActivate ( ) {
101- addToast ( { title : `Creating snapshot of disk '${ disk . name } '` } )
102- createSnapshot . mutate ( {
103- query : projectSelector ,
104- body : {
105- name : genName ( disk . name ) ,
106- disk : disk . name ,
107- description : '' ,
108- } ,
109- } )
121+ const makeActions = useCallback (
122+ ( disk : Disk ) : MenuAction [ ] => [
123+ {
124+ label : 'Snapshot' ,
125+ onActivate ( ) {
126+ addToast ( { title : `Creating snapshot of disk '${ disk . name } '` } )
127+ createSnapshot . mutate ( {
128+ query : { project } ,
129+ body : {
130+ name : genName ( disk . name ) ,
131+ disk : disk . name ,
132+ description : '' ,
133+ } ,
134+ } )
135+ } ,
136+ disabled : ! diskCan . snapshot ( disk ) && (
137+ < >
138+ Only disks in state { fancifyStates ( diskCan . snapshot . states ) } can be snapshotted
139+ </ >
140+ ) ,
110141 } ,
111- disabled : ! diskCan . snapshot ( disk ) && (
112- < > Only disks in state { fancifyStates ( diskCan . snapshot . states ) } can be snapshotted </ >
113- ) ,
114- } ,
115- {
116- label : 'Delete' ,
117- onActivate : confirmDelete ( {
118- doDelete : ( ) =>
119- deleteDisk . mutateAsync ( { path : { disk : disk . name } , query : projectSelector } ) ,
120- label : disk . name ,
121- } ) ,
122- disabled :
123- ! diskCan . delete ( disk ) &&
124- ( disk . state . state === 'attached' ? (
125- 'Disk must be detached before it can be deleted'
126- ) : (
127- < > Only disks in state { fancifyStates ( diskCan . delete . states ) } can be deleted </ >
128- ) ) ,
129- } ,
130- ]
142+ {
143+ label : 'Delete' ,
144+ onActivate : confirmDelete ( {
145+ doDelete : ( ) =>
146+ deleteDisk . mutateAsync ( { path : { disk : disk . name } , query : { project } } ) ,
147+ label : disk . name ,
148+ } ) ,
149+ disabled :
150+ ! diskCan . delete ( disk ) &&
151+ ( disk . state . state === 'attached' ? (
152+ 'Disk must be detached before it can be deleted'
153+ ) : (
154+ < > Only disks in state { fancifyStates ( diskCan . delete . states ) } can be deleted </ >
155+ ) ) ,
156+ } ,
157+ ] ,
158+ [ addToast , createSnapshot , deleteDisk , project ]
159+ )
160+
161+ const columns = useColsWithActions ( staticCols , makeActions )
131162
132163 return (
133164 < >
134165 < PageHeader >
135166 < PageTitle icon = { < Storage24Icon /> } > Disks</ PageTitle >
136167 </ PageHeader >
137168 < TableActions >
138- < Link to = { pb . disksNew ( projectSelector ) } className = { buttonStyle ( { size : 'sm' } ) } >
169+ < Link to = { pb . disksNew ( { project } ) } className = { buttonStyle ( { size : 'sm' } ) } >
139170 New Disk
140171 </ Link >
141172 </ TableActions >
142- < Table emptyState = { < EmptyState /> } makeActions = { makeActions } >
143- < Column accessor = "name" />
144- { /* TODO: show info about the instance it's attached to */ }
145- < Column
146- id = "attached-to"
147- header = "Attached To"
148- accessor = { ( disk ) =>
149- // sneaky: rather than looking at particular states, just look at
150- // whether it has an instance field
151- 'instance' in disk . state ? disk . state . instance : null
152- }
153- cell = { InstanceLinkCell }
154- />
155- < Column header = "Size" accessor = "size" cell = { SizeCell } />
156- < Column
157- id = "status"
158- accessor = { ( row ) => row . state . state }
159- cell = { ( { value } ) => < DiskStatusBadge status = { value } /> }
160- />
161- < Column header = "Created" accessor = "timeCreated" cell = { DateCell } />
162- </ Table >
173+ < Table emptyState = { < EmptyState /> } columns = { columns } />
163174 < Outlet />
164175 </ >
165176 )
0 commit comments