7
7
*/
8
8
9
9
import { createColumnHelper , getCoreRowModel , useReactTable } from '@tanstack/react-table'
10
- import { useMemo } from 'react'
10
+ import { useCallback } from 'react'
11
11
import type { LoaderFunctionArgs } from 'react-router'
12
12
13
13
import { Affinity24Icon } from '@oxide/design-system/icons/react'
14
14
15
15
import {
16
16
apiq ,
17
- getListQFn ,
18
17
queryClient ,
18
+ useApiMutation ,
19
19
usePrefetchedQuery ,
20
20
type AntiAffinityGroupMember ,
21
21
} from '~/api'
22
+ import { HL } from '~/components/HL'
22
23
import { makeCrumb } from '~/hooks/use-crumbs'
23
24
import {
24
25
getAntiAffinityGroupSelector ,
25
26
useAntiAffinityGroupSelector ,
26
27
} from '~/hooks/use-params'
28
+ import { confirmAction } from '~/stores/confirm-action'
29
+ import { addToast } from '~/stores/toast'
27
30
import { makeLinkCell } from '~/table/cells/LinkCell'
31
+ import { useColsWithActions , type MenuAction } from '~/table/columns/action-col'
28
32
import { Columns } from '~/table/columns/common'
29
33
import { Table } from '~/table/Table'
30
34
import { Badge } from '~/ui/lib/Badge'
@@ -49,7 +53,7 @@ const colHelper = createColumnHelper<AntiAffinityGroupMember>()
49
53
const antiAffinityGroupView = ( { antiAffinityGroup, project } : PP . AntiAffinityGroup ) =>
50
54
apiq ( 'antiAffinityGroupView' , { path : { antiAffinityGroup } , query : { project } } )
51
55
const memberList = ( { antiAffinityGroup, project } : PP . AntiAffinityGroup ) =>
52
- getListQFn ( 'antiAffinityGroupMemberList' , {
56
+ apiq ( 'antiAffinityGroupMemberList' , {
53
57
path : { antiAffinityGroup } ,
54
58
// member limit in DB is currently 32, so pagination isn't needed
55
59
query : { project, limit : ALL_ISH } ,
@@ -59,7 +63,7 @@ export async function clientLoader({ params }: LoaderFunctionArgs) {
59
63
const { antiAffinityGroup, project } = getAntiAffinityGroupSelector ( params )
60
64
await Promise . all ( [
61
65
queryClient . fetchQuery ( antiAffinityGroupView ( { antiAffinityGroup, project } ) ) ,
62
- queryClient . fetchQuery ( memberList ( { antiAffinityGroup, project } ) . optionsFn ( ) ) ,
66
+ queryClient . fetchQuery ( memberList ( { antiAffinityGroup, project } ) ) ,
63
67
] )
64
68
return null
65
69
}
@@ -80,19 +84,66 @@ export default function AntiAffinityPage() {
80
84
antiAffinityGroupView ( { antiAffinityGroup, project } )
81
85
)
82
86
const { id, name, description, policy, timeCreated } = group
83
- const { data : members } = usePrefetchedQuery (
84
- memberList ( { antiAffinityGroup, project } ) . optionsFn ( )
85
- )
87
+ const { data : members } = usePrefetchedQuery ( memberList ( { antiAffinityGroup, project } ) )
86
88
const membersCount = members . items . length
87
- const columns = useMemo (
88
- ( ) => [
89
+
90
+ const { mutateAsync : removeMember } = useApiMutation (
91
+ 'antiAffinityGroupMemberInstanceDelete' ,
92
+ {
93
+ onSuccess ( _data , variables ) {
94
+ queryClient . invalidateEndpoint ( 'antiAffinityGroupMemberList' )
95
+ queryClient . invalidateEndpoint ( 'antiAffinityGroupView' )
96
+ addToast ( < > Member < HL > { variables . path . instance } </ HL > removed from anti-affinity group < HL > { group . name } </ HL > </ > ) // prettier-ignore
97
+ } ,
98
+ }
99
+ )
100
+
101
+ const makeActions = useCallback (
102
+ ( antiAffinityGroupMember : AntiAffinityGroupMember ) : MenuAction [ ] => [
103
+ {
104
+ label : 'Copy instance ID' ,
105
+ onActivate ( ) {
106
+ navigator . clipboard . writeText ( antiAffinityGroupMember . value . id )
107
+ } ,
108
+ } ,
109
+ {
110
+ label : 'Remove from group' ,
111
+ onActivate ( ) {
112
+ confirmAction ( {
113
+ actionType : 'danger' ,
114
+ doAction : ( ) =>
115
+ removeMember ( {
116
+ path : {
117
+ antiAffinityGroup : antiAffinityGroup ,
118
+ instance : antiAffinityGroupMember . value . name ,
119
+ } ,
120
+ query : { project } ,
121
+ } ) ,
122
+ modalTitle : 'Remove instance from anti-affinity group' ,
123
+ modalContent : (
124
+ < p >
125
+ Are you sure you want to remove{ ' ' }
126
+ < HL > { antiAffinityGroupMember . value . name } </ HL > from the anti-affinity group{ ' ' }
127
+ < HL > { antiAffinityGroup } </ HL > ?
128
+ </ p >
129
+ ) ,
130
+ errorTitle : `Error removing ${ antiAffinityGroupMember . value . name } ` ,
131
+ } )
132
+ } ,
133
+ } ,
134
+ ] ,
135
+ [ project , removeMember , antiAffinityGroup ]
136
+ )
137
+
138
+ const columns = useColsWithActions (
139
+ [
89
140
colHelper . accessor ( 'value.name' , {
90
141
header : 'Name' ,
91
142
cell : makeLinkCell ( ( instance ) => pb . instance ( { project, instance } ) ) ,
92
143
} ) ,
93
144
colHelper . accessor ( 'value.runState' , Columns . instanceState ) ,
94
145
] ,
95
- [ project ]
146
+ makeActions
96
147
)
97
148
98
149
const table = useReactTable ( {
0 commit comments