From 939098b9bd63928f1a49f79d252a8bbf97fea689 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 15 Mar 2026 02:19:05 +0000 Subject: [PATCH] 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 --- .../src/components/policies/index.tsx | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/ui/litellm-dashboard/src/components/policies/index.tsx b/ui/litellm-dashboard/src/components/policies/index.tsx index bd77f3ab9b6..93a273f5f85 100644 --- a/ui/litellm-dashboard/src/components/policies/index.tsx +++ b/ui/litellm-dashboard/src/components/policies/index.tsx @@ -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 = ({ const [isDeleting, setIsDeleting] = useState(false); const [policyToDelete, setPolicyToDelete] = useState(null); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [attachmentToDelete, setAttachmentToDelete] = useState(null); + const [isDeleteAttachmentModalOpen, setIsDeleteAttachmentModalOpen] = useState(false); + const [isDeletingAttachment, setIsDeletingAttachment] = useState(false); const [isGuardrailSelectionModalOpen, setIsGuardrailSelectionModalOpen] = useState(false); const [selectedTemplate, setSelectedTemplate] = useState(null); const [existingGuardrailNames, setExistingGuardrailNames] = useState>(new Set()); @@ -165,26 +168,33 @@ 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); - 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 = ({ @@ -591,6 +601,21 @@ const PoliciesPanel: React.FC = ({ policies={policiesList} createAttachment={createPolicyAttachmentCall} /> + +