Skip to content

Commit c2f611f

Browse files
authored
fix(ui): Improve Delete Dialog Behaviour when deleting child apps in the app-of-app pattern (#24802)
Signed-off-by: Atif Ali <[email protected]>
1 parent ef48aa9 commit c2f611f

File tree

2 files changed

+75
-6
lines changed

2 files changed

+75
-6
lines changed

ui/src/app/applications/components/utils.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,13 @@ i.utils-health-status-icon {
6060
transform: rotate(360deg);
6161
}
6262
}
63+
64+
.delete-dialog-icon {
65+
&.warning {
66+
color: #f4c030;
67+
}
68+
69+
&.info {
70+
color: #0DADEA;
71+
}
72+
}

ui/src/app/applications/components/utils.tsx

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,18 @@ export const SpinningIcon = ({color, qeId}: {color: string; qeId: string}) => {
8282
);
8383
};
8484

85-
export async function deleteApplication(appName: string, appNamespace: string, apis: ContextApis): Promise<boolean> {
85+
export async function deleteApplication(appName: string, appNamespace: string, apis: ContextApis, application?: appModels.Application): Promise<boolean> {
8686
let confirmed = false;
87+
88+
// Use common child application detection logic if application object is provided
89+
const isChildApp = application ? isChildApplication(application) : false;
90+
const dialogTitle = isChildApp ? 'Delete child application' : 'Delete application';
91+
const appType = isChildApp ? 'child Application' : 'Application';
92+
const confirmLabel = isChildApp ? 'child application' : 'application';
93+
94+
// Check if this is being called from resource tree context
95+
const isFromResourceTree = application !== undefined;
96+
8797
const propagationPolicies: {name: string; message: string}[] = [
8898
{
8999
name: 'Foreground',
@@ -99,18 +109,27 @@ export async function deleteApplication(appName: string, appNamespace: string, a
99109
}
100110
];
101111
await apis.popup.prompt(
102-
'Delete application',
112+
dialogTitle,
103113
api => (
104114
<div>
105115
<p>
106-
Are you sure you want to delete the <strong>Application</strong> <kbd>{appName}</kbd>?
107-
<span style={{display: 'block', marginBottom: '10px'}} />
116+
Are you sure you want to delete the <strong>{appType}</strong> <kbd>{appName}</kbd>?
117+
</p>
118+
{isFromResourceTree && (
119+
<p>
120+
<strong>
121+
<i className='fa fa-warning delete-dialog-icon warning' /> Note:
122+
</strong>{' '}
123+
You are about to delete an Application from the resource tree. This uses the same deletion behavior as the Applications list page.
124+
</p>
125+
)}
126+
<p>
108127
Deleting the application in <kbd>foreground</kbd> or <kbd>background</kbd> mode will delete all the application's managed resources, which can be{' '}
109128
<strong>dangerous</strong>. Be sure you understand the effects of deleting this resource before continuing. Consider asking someone to review the change first.
110129
</p>
111130
<div className='argo-form-row'>
112131
<FormField
113-
label={`Please type '${appName}' to confirm the deletion of the resource`}
132+
label={`Please type '${appName}' to confirm the deletion of the ${confirmLabel}`}
114133
formApi={api}
115134
field='applicationName'
116135
qeId='name-field-delete-confirmation'
@@ -452,6 +471,17 @@ export const deleteSourceAction = (app: appModels.Application, source: appModels
452471
);
453472
};
454473

474+
// Detect if a resource is an Application
475+
const isApplicationResource = (resource: ResourceTreeNode): boolean => {
476+
return resource.kind === 'Application' && resource.group === 'argoproj.io';
477+
};
478+
479+
// Detect if an application is a child application
480+
const isChildApplication = (application: appModels.Application): boolean => {
481+
const partOfLabel = application.metadata.labels?.['app.kubernetes.io/part-of'];
482+
return partOfLabel && partOfLabel.trim() !== '';
483+
};
484+
455485
export const deletePopup = async (
456486
ctx: ContextApis,
457487
resource: ResourceTreeNode,
@@ -460,6 +490,17 @@ export const deletePopup = async (
460490
childResources: appModels.ResourceNode[],
461491
appChanged?: BehaviorSubject<appModels.Application>
462492
) => {
493+
// Detect if this is an Application resource
494+
const isApplication = isApplicationResource(resource);
495+
496+
// Check if we're in a parent-child context (used for both Application and non-Application resources)
497+
const isInParentContext = isChildApplication(application);
498+
499+
// For Application resources, use the deleteApplication function with resource tree context
500+
if (isApplication) {
501+
return deleteApplication(resource.name, resource.namespace || '', ctx, application);
502+
}
503+
463504
const deleteOptions = {
464505
option: 'foreground'
465506
};
@@ -471,13 +512,31 @@ export const deletePopup = async (
471512
return deletePodAction(ctx, resource, application);
472513
}
473514

515+
// Determine dialog title and add custom messaging
516+
const dialogTitle = 'Delete resource';
517+
let customMessage: React.ReactNode = null;
518+
519+
if (isInParentContext) {
520+
customMessage = (
521+
<div>
522+
<p>
523+
<strong>
524+
<i className='fa fa-exclamation-triangle delete-dialog-icon info' /> Note:
525+
</strong>{' '}
526+
You are about to delete a resource from a parent application's resource tree.
527+
</p>
528+
</div>
529+
);
530+
}
531+
474532
return ctx.popup.prompt(
475-
'Delete resource',
533+
dialogTitle,
476534
api => (
477535
<div>
478536
<p>
479537
Are you sure you want to delete <strong>{resource.kind}</strong> <kbd>{resource.name}</kbd>?
480538
</p>
539+
{customMessage}
481540
<p>
482541
Deleting resources can be <strong>dangerous</strong>. Be sure you understand the effects of deleting this resource before continuing. Consider asking someone to
483542
review the change first.

0 commit comments

Comments
 (0)