@@ -8,19 +8,28 @@ import {
88 Toolbar ,
99 ToolbarSpacer ,
1010} from '@ui5/webcomponents-react' ;
11- import { useApiResource } from '../../lib/api/useApiResource' ;
11+ import { useApiResource , useApiResourceMutation } from '../../lib/api/useApiResource' ;
1212import { ManagedResourcesRequest } from '../../lib/api/types/crossplane/listManagedResources' ;
1313import { formatDateAsTimeAgo } from '../../utils/i18n/timeAgo' ;
1414import IllustratedError from '../Shared/IllustratedError' ;
15- import '@ui5/webcomponents-icons/dist/sys-enter-2' ;
16- import '@ui5/webcomponents-icons/dist/sys-cancel-2' ;
1715import { resourcesInterval } from '../../lib/shared/constants' ;
1816
1917import { YamlViewButton } from '../Yaml/YamlViewButton.tsx' ;
20- import { useMemo } from 'react' ;
18+ import { useMemo , useState } from 'react' ;
2119import StatusFilter from '../Shared/StatusFilter/StatusFilter.tsx' ;
2220import { ResourceStatusCell } from '../Shared/ResourceStatusCell.tsx' ;
2321import { Resource } from '../../utils/removeManagedFieldsAndFilterData.ts' ;
22+ import { ManagedResourceItem } from '../../lib/shared/types.ts' ;
23+ import { ManagedResourceDeleteDialog } from '../Dialogs/ManagedResourceDeleteDialog.tsx' ;
24+ import { RowActionsMenu } from './ManagedResourcesActionMenu.tsx' ;
25+ import { useToast } from '../../context/ToastContext.tsx' ;
26+ import {
27+ DeleteManagedResourceType ,
28+ DeleteMCPManagedResource ,
29+ PatchResourceForForceDeletion ,
30+ PatchResourceForForceDeletionBody ,
31+ } from '../../lib/api/types/crate/deleteResource' ;
32+ import { useResourcePluralNames } from '../../hooks/useResourcePluralNames' ;
2433
2534interface CellData < T > {
2635 cell : {
@@ -46,15 +55,32 @@ type ResourceRow = {
4655
4756export function ManagedResources ( ) {
4857 const { t } = useTranslation ( ) ;
58+ const toast = useToast ( ) ;
59+ const [ pendingDeleteItem , setPendingDeleteItem ] = useState < ManagedResourceItem | null > ( null ) ;
4960
5061 const {
5162 data : managedResources ,
5263 error,
5364 isLoading,
5465 } = useApiResource ( ManagedResourcesRequest , {
55- refreshInterval : resourcesInterval , // Resources are quite expensive to fetch, so we refresh every 30 seconds
66+ refreshInterval : resourcesInterval ,
5667 } ) ;
5768
69+ const { getPluralKind, isLoading : isLoadingPluralNames , error : pluralNamesError } = useResourcePluralNames ( ) ;
70+
71+ const resourceName = pendingDeleteItem ?. metadata ?. name ?? '' ;
72+ const apiVersion = pendingDeleteItem ?. apiVersion ?? '' ;
73+ const pluralKind = pendingDeleteItem ? getPluralKind ( pendingDeleteItem . kind ) : '' ;
74+ const namespace = pendingDeleteItem ?. metadata ?. namespace ?? '' ;
75+
76+ const { trigger : deleteTrigger } = useApiResourceMutation < DeleteManagedResourceType > (
77+ DeleteMCPManagedResource ( apiVersion , pluralKind , resourceName , namespace ) ,
78+ ) ;
79+
80+ const { trigger : patchTrigger } = useApiResourceMutation < DeleteManagedResourceType > (
81+ PatchResourceForForceDeletion ( apiVersion , pluralKind , resourceName , namespace ) ,
82+ ) ;
83+
5884 const columns : AnalyticalTableColumnDefinition [ ] = useMemo (
5985 ( ) => [
6086 {
@@ -109,10 +135,24 @@ export function ManagedResources() {
109135 width : 75 ,
110136 accessor : 'yaml' ,
111137 disableFilters : true ,
112- Cell : ( cellData : CellData < ResourceRow > ) =>
113- cellData . cell . row . original ?. item ? (
138+ Cell : ( cellData : CellData < ResourceRow > ) => {
139+ return cellData . cell . row . original ?. item ? (
114140 < YamlViewButton variant = "resource" resource = { cellData . cell . row . original ?. item as Resource } />
115- ) : undefined ,
141+ ) : undefined ;
142+ } ,
143+ } ,
144+ {
145+ Header : t ( 'ManagedResources.actionColumnHeader' ) ,
146+ hAlign : 'Center' ,
147+ width : 60 ,
148+ disableFilters : true ,
149+ Cell : ( cellData : CellData < ResourceRow > ) => {
150+ const item = cellData . cell . row . original ?. item as ManagedResourceItem ;
151+
152+ return cellData . cell . row . original ?. item ? (
153+ < RowActionsMenu item = { item } onOpen = { openDeleteDialog } />
154+ ) : undefined ;
155+ } ,
116156 } ,
117157 ] ,
118158 [ t ] ,
@@ -141,11 +181,34 @@ export function ManagedResources() {
141181 } ) ,
142182 ) ?? [ ] ;
143183
184+ const openDeleteDialog = ( item : ManagedResourceItem ) => {
185+ setPendingDeleteItem ( item ) ;
186+ } ;
187+
188+ const handleDeletionConfirmed = async ( item : ManagedResourceItem , force : boolean ) => {
189+ toast . show ( t ( 'ManagedResources.deleteStarted' , { resourceName : item . metadata . name } ) ) ;
190+
191+ try {
192+ await deleteTrigger ( ) ;
193+
194+ if ( force ) {
195+ await patchTrigger ( PatchResourceForForceDeletionBody ) ;
196+ }
197+ } catch ( _ ) {
198+ // Ignore errors - will be handled by the mutation hook
199+ } finally {
200+ setPendingDeleteItem ( null ) ;
201+ }
202+ } ;
203+
204+ const combinedError = error || pluralNamesError ;
205+ const combinedLoading = isLoading || isLoadingPluralNames ;
206+
144207 return (
145208 < >
146- { error && < IllustratedError details = { error . message } /> }
209+ { combinedError && < IllustratedError details = { combinedError . message } /> }
147210
148- { ! error && (
211+ { ! combinedError && (
149212 < Panel
150213 fixed
151214 header = {
@@ -155,28 +218,36 @@ export function ManagedResources() {
155218 </ Toolbar >
156219 }
157220 >
158- < AnalyticalTable
159- columns = { columns }
160- data = { rows }
161- minRows = { 1 }
162- groupBy = { [ 'kind' ] }
163- scaleWidthMode = { AnalyticalTableScaleWidthMode . Smart }
164- loading = { isLoading }
165- filterable
166- // Prevent the table from resetting when the data changes
167- retainColumnWidth
168- reactTableOptions = { {
169- autoResetHiddenColumns : false ,
170- autoResetPage : false ,
171- autoResetExpanded : false ,
172- autoResetGroupBy : false ,
173- autoResetSelectedRows : false ,
174- autoResetSortBy : false ,
175- autoResetFilters : false ,
176- autoResetRowState : false ,
177- autoResetResize : false ,
178- } }
179- />
221+ < >
222+ < AnalyticalTable
223+ columns = { columns }
224+ data = { rows }
225+ minRows = { 1 }
226+ groupBy = { [ 'kind' ] }
227+ scaleWidthMode = { AnalyticalTableScaleWidthMode . Smart }
228+ loading = { combinedLoading }
229+ filterable
230+ retainColumnWidth
231+ reactTableOptions = { {
232+ autoResetHiddenColumns : false ,
233+ autoResetPage : false ,
234+ autoResetExpanded : false ,
235+ autoResetGroupBy : false ,
236+ autoResetSelectedRows : false ,
237+ autoResetSortBy : false ,
238+ autoResetFilters : false ,
239+ autoResetRowState : false ,
240+ autoResetResize : false ,
241+ } }
242+ />
243+
244+ < ManagedResourceDeleteDialog
245+ open = { ! ! pendingDeleteItem }
246+ item = { pendingDeleteItem }
247+ onClose = { ( ) => setPendingDeleteItem ( null ) }
248+ onDeletionConfirmed = { handleDeletionConfirmed }
249+ />
250+ </ >
180251 </ Panel >
181252 ) }
182253 </ >
0 commit comments