Delete pop up button is added for dev tools

Signed-off-by: deepthi-28 <deepthi.ajith@infosys.com>
This commit is contained in:
deepthi-28
2025-03-17 15:55:21 +05:30
parent ad988fb87f
commit ba88bfa464
3 changed files with 127 additions and 38 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-unprocessed-entities': patch
---
Added confirmation popup for delete entities in devtools
@@ -0,0 +1,64 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogTitle from '@material-ui/core/DialogTitle';
import React, { useState } from 'react';
import { assertError } from '@backstage/errors';
interface DeleteEntityDialogProps {
open: boolean;
onClose: () => any;
onConfirm: () => any;
}
export function DeleteEntityDialog(props: DeleteEntityDialogProps) {
const { open, onClose, onConfirm } = props;
const [busy, setBusy] = useState(false);
const onDelete = async () => {
setBusy(true);
try {
onConfirm();
} catch (err) {
assertError(err);
} finally {
setBusy(false);
}
};
return (
<Dialog open={open} onClose={onClose}>
<DialogTitle id="responsive-dialog-title">
Are you sure you want to delete this entity?
</DialogTitle>
<DialogActions>
<Button
variant="contained"
color="secondary"
disabled={busy}
onClick={onDelete}
>
Delete
</Button>
<Button onClick={onClose} color="primary">
Cancel
</Button>
</DialogActions>
</Dialog>
);
}
@@ -34,6 +34,7 @@ import { EntityDialog } from './EntityDialog';
import { catalogUnprocessedEntitiesApiRef } from '../api';
import useAsync from 'react-use/esm/useAsync';
import DeleteIcon from '@material-ui/icons/Delete';
import { DeleteEntityDialog } from './DeleteEntityDialog';
const useStyles = makeStyles((theme: Theme) => ({
errorBox: {
@@ -117,6 +118,9 @@ export const FailedEntities = () => {
const [, setSelectedSearchTerm] = useState<string>('');
const unprocessedEntityApi = useApi(catalogUnprocessedEntitiesApiRef);
const alertApi = useApi(alertApiRef);
const [entityID, setEntityID] = useState('');
const [entityRefVal, setEntityRefVal] = useState('');
const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
if (loading) {
return <Progress />;
@@ -125,25 +129,32 @@ export const FailedEntities = () => {
return <ErrorPanel error={error} />;
}
const handleDelete = async ({
const handleDelete = ({
entityId,
entityRef,
}: {
entityId: string;
entityRef: string;
}) => {
setEntityID(entityId);
setEntityRefVal(entityRef);
setConfirmationDialogOpen(true);
};
const cleanUpAfterRemoval = async () => {
try {
await unprocessedEntityApi.delete(entityId);
await unprocessedEntityApi.delete(entityID);
alertApi.post({
message: `Entity ${entityRef} has been deleted`,
message: `Entity ${entityRefVal} has been deleted`,
severity: 'success',
});
} catch (e) {
alertApi.post({
message: `Ran into an issue when deleting ${entityRef}. Please try again later.`,
message: `Ran into an issue when deleting ${entityRefVal}. Please try again later.`,
severity: 'error',
});
}
setConfirmationDialogOpen(false);
};
const columns: TableColumn[] = [
@@ -213,8 +224,8 @@ export const FailedEntities = () => {
return (
<IconButton
aria-label="delete"
onClick={async () =>
await handleDelete({
onClick={() =>
handleDelete({
entityId: entity_id,
entityRef: entity_ref,
})
@@ -228,37 +239,46 @@ export const FailedEntities = () => {
];
return (
<Table
options={{ pageSize: 20, search: true }}
columns={columns}
data={data?.entities ?? []}
emptyContent={
<Typography className={classes.successMessage}>
No failed entities found
</Typography>
}
onSearchChange={(searchTerm: string) => setSelectedSearchTerm(searchTerm)}
detailPanel={({ rowData }) => {
const errors = (rowData as UnprocessedEntity).errors;
return (
<>
{errors?.map((e, idx) => {
return (
<Box key={idx} className={classes.errorBox}>
<Typography className={classes.errorTitle}>
{e.name}
</Typography>
<MarkdownContent content={e.message} />
<RenderErrorContext
error={e}
rowData={rowData as UnprocessedEntity}
/>
</Box>
);
})}
</>
);
}}
/>
<>
<Table
options={{ pageSize: 20, search: true }}
columns={columns}
data={data?.entities ?? []}
emptyContent={
<Typography className={classes.successMessage}>
No failed entities found
</Typography>
}
onSearchChange={(searchTerm: string) =>
setSelectedSearchTerm(searchTerm)
}
detailPanel={({ rowData }) => {
const errors = (rowData as UnprocessedEntity).errors;
return (
<>
{errors?.map((e, idx) => {
return (
<Box key={idx} className={classes.errorBox}>
<Typography className={classes.errorTitle}>
{e.name}
</Typography>
<MarkdownContent content={e.message} />
<RenderErrorContext
error={e}
rowData={rowData as UnprocessedEntity}
/>
</Box>
);
})}
</>
);
}}
/>
<DeleteEntityDialog
open={confirmationDialogOpen}
onClose={() => setConfirmationDialogOpen(false)}
onConfirm={cleanUpAfterRemoval}
/>
</>
);
};