fix(ui): replace Modal.confirm with DeleteResourceModal for attachment delete

antd v5 static methods (Modal.confirm) fail to render DOM elements when
they cannot access the React context/theme provider. The modal object is
returned successfully but no UI is created, causing the delete action to
silently do nothing.

Replace with the DeleteResourceModal component (already used for policy
deletion) which renders as a proper React component within the app tree,
ensuring it has access to the antd ConfigProvider context.

Also swap the Tremor Icon for TableIconActionButton in the attachment
table actions column, matching the pattern used in other table components.

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
This commit is contained in:
Cursor Agent 2026-03-15 02:19:05 +00:00
parent 60f98a05e7
commit 939098b9bd
No known key found for this signature in database

View file

@ -1,7 +1,7 @@
import React, { useState, useEffect, useCallback } from "react";
import { Button, TabGroup, TabList, Tab, TabPanels, TabPanel } from "@tremor/react";
import { Modal, message, Alert } from "antd";
import { ExclamationCircleOutlined, InfoCircleOutlined } from "@ant-design/icons";
import { message, Alert } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { isAdminRole } from "@/utils/roles";
import PolicyTable from "./policy_table";
import PolicyInfoView from "./policy_info";
@ -56,6 +56,9 @@ const PoliciesPanel: React.FC<PoliciesPanelProps> = ({
const [isDeleting, setIsDeleting] = useState(false);
const [policyToDelete, setPolicyToDelete] = useState<Policy | null>(null);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [attachmentToDelete, setAttachmentToDelete] = useState<PolicyAttachment | null>(null);
const [isDeleteAttachmentModalOpen, setIsDeleteAttachmentModalOpen] = useState(false);
const [isDeletingAttachment, setIsDeletingAttachment] = useState(false);
const [isGuardrailSelectionModalOpen, setIsGuardrailSelectionModalOpen] = useState(false);
const [selectedTemplate, setSelectedTemplate] = useState<any>(null);
const [existingGuardrailNames, setExistingGuardrailNames] = useState<Set<string>>(new Set());
@ -165,26 +168,33 @@ const PoliciesPanel: React.FC<PoliciesPanelProps> = ({
setPolicyToDelete(null);
};
const handleDeleteAttachment = (attachmentId: string) => {
Modal.confirm({
title: "Delete Attachment",
icon: <ExclamationCircleOutlined />,
content: "Are you sure you want to delete this attachment? This action cannot be undone.",
okText: "Delete",
okType: "danger",
cancelText: "Cancel",
onOk: async () => {
if (!accessToken) return;
try {
await deletePolicyAttachmentCall(accessToken, attachmentId);
message.success("Attachment deleted successfully");
fetchAttachments();
} catch (error) {
console.error("Error deleting attachment:", error);
message.error("Failed to delete attachment");
}
},
});
const handleDeleteAttachmentClick = (attachmentId: string) => {
const attachment = attachmentsList.find((a) => a.attachment_id === attachmentId) || null;
setAttachmentToDelete(attachment);
setIsDeleteAttachmentModalOpen(true);
};
const handleDeleteAttachmentConfirm = async () => {
if (!attachmentToDelete || !accessToken) return;
setIsDeletingAttachment(true);
try {
await deletePolicyAttachmentCall(accessToken, attachmentToDelete.attachment_id);
message.success("Attachment deleted successfully");
await fetchAttachments();
} catch (error) {
console.error("Error deleting attachment:", error);
message.error("Failed to delete attachment");
} finally {
setIsDeletingAttachment(false);
setIsDeleteAttachmentModalOpen(false);
setAttachmentToDelete(null);
}
};
const handleDeleteAttachmentCancel = () => {
setIsDeleteAttachmentModalOpen(false);
setAttachmentToDelete(null);
};
const handleAttachmentSuccess = () => {
@ -578,7 +588,7 @@ const PoliciesPanel: React.FC<PoliciesPanelProps> = ({
<AttachmentTable
attachments={attachmentsList}
isLoading={isAttachmentsLoading}
onDeleteClick={handleDeleteAttachment}
onDeleteClick={handleDeleteAttachmentClick}
isAdmin={isAdmin}
accessToken={accessToken}
/>
@ -591,6 +601,21 @@ const PoliciesPanel: React.FC<PoliciesPanelProps> = ({
policies={policiesList}
createAttachment={createPolicyAttachmentCall}
/>
<DeleteResourceModal
isOpen={isDeleteAttachmentModalOpen}
title="Delete Attachment"
message="Are you sure you want to delete this attachment? This action cannot be undone."
resourceInformationTitle="Attachment Information"
resourceInformation={[
{ label: "Attachment ID", value: attachmentToDelete?.attachment_id, code: true },
{ label: "Policy", value: attachmentToDelete?.policy_name },
{ label: "Scope", value: attachmentToDelete?.scope || "-" },
]}
onCancel={handleDeleteAttachmentCancel}
onOk={handleDeleteAttachmentConfirm}
confirmLoading={isDeletingAttachment}
/>
</TabPanel>
<TabPanel>