diff --git a/ui/litellm-dashboard/src/components/policies/attachment_table.test.tsx b/ui/litellm-dashboard/src/components/policies/attachment_table.test.tsx
index 4372983b71a..56a59553c09 100644
--- a/ui/litellm-dashboard/src/components/policies/attachment_table.test.tsx
+++ b/ui/litellm-dashboard/src/components/policies/attachment_table.test.tsx
@@ -111,14 +111,14 @@ describe("AttachmentTable", () => {
const attachment = makeAttachment({ attachment_id: "att-del-me1" });
const user = userEvent.setup();
renderWithProviders();
- await user.click(screen.getByRole("button", { name: /TrashIcon/i }));
+ await user.click(screen.getByRole("button", { name: /delete attachment/i }));
expect(defaultProps.onDeleteClick).toHaveBeenCalledWith("att-del-me1");
});
it("should not show the delete icon for non-admins", () => {
const attachment = makeAttachment();
renderWithProviders();
- expect(screen.queryByRole("button", { name: /TrashIcon/i })).not.toBeInTheDocument();
+ expect(screen.queryByRole("button", { name: /delete attachment/i })).not.toBeInTheDocument();
});
it("should show a truncated attachment ID in the table", () => {
diff --git a/ui/litellm-dashboard/src/components/policies/attachment_table.tsx b/ui/litellm-dashboard/src/components/policies/attachment_table.tsx
index d9de8378a8a..02a5d9fd992 100644
--- a/ui/litellm-dashboard/src/components/policies/attachment_table.tsx
+++ b/ui/litellm-dashboard/src/components/policies/attachment_table.tsx
@@ -202,12 +202,17 @@ const AttachmentTable: React.FC = ({
{isAdmin && (
- onDeleteClick(attachment.attachment_id)}
- className="cursor-pointer hover:text-red-500"
- />
+
)}
diff --git a/ui/litellm-dashboard/src/components/policies/index.tsx b/ui/litellm-dashboard/src/components/policies/index.tsx
index f47b8d78b9d..6f624698dfb 100644
--- a/ui/litellm-dashboard/src/components/policies/index.tsx
+++ b/ui/litellm-dashboard/src/components/policies/index.tsx
@@ -1,8 +1,8 @@
import React, { useState, useEffect, useCallback } from "react";
import { Button, TabGroup, TabList, Tab, TabPanels, TabPanel } from "@tremor/react";
-import { Modal, Alert } from "antd";
+import { Alert } from "antd";
import MessageManager from "@/components/molecules/message_manager";
-import { ExclamationCircleOutlined, InfoCircleOutlined } from "@ant-design/icons";
+import { InfoCircleOutlined } from "@ant-design/icons";
import { isAdminRole } from "@/utils/roles";
import PolicyTable from "./policy_table";
import PolicyInfoView from "./policy_info";
@@ -57,6 +57,9 @@ const PoliciesPanel: React.FC = ({
const [isDeleting, setIsDeleting] = useState(false);
const [policyToDelete, setPolicyToDelete] = useState(null);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+ const [attachmentToDelete, setAttachmentToDelete] = useState(null);
+ const [isAttachmentDeleteModalOpen, setIsAttachmentDeleteModalOpen] = useState(false);
+ const [isDeletingAttachment, setIsDeletingAttachment] = useState(false);
const [isGuardrailSelectionModalOpen, setIsGuardrailSelectionModalOpen] = useState(false);
const [selectedTemplate, setSelectedTemplate] = useState(null);
const [existingGuardrailNames, setExistingGuardrailNames] = useState>(new Set());
@@ -166,26 +169,34 @@ const PoliciesPanel: React.FC = ({
setPolicyToDelete(null);
};
- const handleDeleteAttachment = (attachmentId: string) => {
- Modal.confirm({
- title: "Delete Attachment",
- icon: ,
- 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);
- MessageManager.success("Attachment deleted successfully");
- fetchAttachments();
- } catch (error) {
- console.error("Error deleting attachment:", error);
- MessageManager.error("Failed to delete attachment");
- }
- },
- });
+ const handleDeleteAttachmentClick = (attachmentId: string) => {
+ const attachment = attachmentsList.find((a) => a.attachment_id === attachmentId) ?? null;
+ if (!attachment) return;
+ setAttachmentToDelete(attachment);
+ setIsAttachmentDeleteModalOpen(true);
+ };
+
+ const handleAttachmentDeleteConfirm = async () => {
+ if (!attachmentToDelete || !accessToken) return;
+
+ setIsDeletingAttachment(true);
+ try {
+ await deletePolicyAttachmentCall(accessToken, attachmentToDelete.attachment_id);
+ MessageManager.success("Attachment deleted successfully");
+ await fetchAttachments();
+ } catch (error) {
+ console.error("Error deleting attachment:", error);
+ MessageManager.error("Failed to delete attachment");
+ } finally {
+ setIsDeletingAttachment(false);
+ setIsAttachmentDeleteModalOpen(false);
+ setAttachmentToDelete(null);
+ }
+ };
+
+ const handleAttachmentDeleteCancel = () => {
+ setIsAttachmentDeleteModalOpen(false);
+ setAttachmentToDelete(null);
};
const handleAttachmentSuccess = () => {
@@ -579,11 +590,26 @@ const PoliciesPanel: React.FC = ({
+
+
setIsAddAttachmentModalVisible(false)}