mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
[Feat] Add CredentialDeleteModal component and integrate with CredentialsPanel (#13550)
* [Feat] Add CredentialDeleteModal component and integrate with CredentialsPanel * Implement CredentialDeleteModal for confirming credential deletions. * Update CredentialsPanel to manage delete modal state and handle credential deletion. * Ensure user confirmation before deleting credentials to prevent accidental removals. * Update CredentialDeleteModal to use smart quotes for credential name in confirmation message * Enhance CredentialDeleteModal with confirmation input and validation * Added input field for user to confirm credential deletion by typing the credential name. * Updated modal behavior to handle confirmation and cancellation actions. * Removed unnecessary state management in CredentialsPanel for delete modal visibility. * Fix HTML entity for apostrophe in CredentialDeleteModal confirmation message
This commit is contained in:
parent
1249385a99
commit
e51c15705c
2 changed files with 120 additions and 1 deletions
|
|
@ -0,0 +1,99 @@
|
|||
import React, { useState } from "react";
|
||||
import { Modal } from "antd";
|
||||
import { Button as TremorButton } from "@tremor/react";
|
||||
import { ExclamationIcon } from "@heroicons/react/outline";
|
||||
|
||||
interface CredentialDeleteModalProps {
|
||||
isVisible: boolean;
|
||||
onCancel: () => void;
|
||||
onConfirm: () => void;
|
||||
credentialName: string;
|
||||
}
|
||||
|
||||
const CredentialDeleteModal: React.FC<CredentialDeleteModalProps> = ({
|
||||
isVisible,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
credentialName,
|
||||
}) => {
|
||||
const [deleteConfirmInput, setDeleteConfirmInput] = useState("");
|
||||
const isValid = deleteConfirmInput === credentialName;
|
||||
|
||||
const handleCancel = () => {
|
||||
setDeleteConfirmInput("");
|
||||
onCancel();
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (isValid) {
|
||||
setDeleteConfirmInput("");
|
||||
onConfirm();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={
|
||||
<div className="flex items-center">
|
||||
<ExclamationIcon className="h-6 w-6 text-red-600 mr-2" />
|
||||
Delete Credential
|
||||
</div>
|
||||
}
|
||||
open={isVisible}
|
||||
footer={null}
|
||||
onCancel={handleCancel}
|
||||
closable={true}
|
||||
destroyOnClose={true}
|
||||
maskClosable={false}
|
||||
>
|
||||
<div className="mt-4">
|
||||
<div className="flex items-start gap-3 p-4 bg-red-50 border border-red-100 rounded-md mb-5">
|
||||
<div className="text-red-500 mt-0.5">
|
||||
<ExclamationIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-base font-medium text-red-600">
|
||||
This action cannot be undone and may break existing integrations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-5">
|
||||
<label className="block text-base font-medium text-gray-700 mb-2">
|
||||
{`Type `}
|
||||
<span className="underline italic">'{credentialName}'</span>
|
||||
{` to confirm deletion:`}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={deleteConfirmInput}
|
||||
onChange={(e) => setDeleteConfirmInput(e.target.value)}
|
||||
placeholder="Enter credential name exactly"
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-base"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-2">
|
||||
<TremorButton
|
||||
onClick={handleCancel}
|
||||
variant="secondary"
|
||||
className="mr-2"
|
||||
>
|
||||
Cancel
|
||||
</TremorButton>
|
||||
<TremorButton
|
||||
onClick={handleConfirm}
|
||||
color="red"
|
||||
className="focus:ring-red-500"
|
||||
disabled={!isValid}
|
||||
>
|
||||
Delete Credential
|
||||
</TremorButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default CredentialDeleteModal;
|
||||
|
|
@ -23,6 +23,7 @@ import { UploadProps } from "antd/es/upload";
|
|||
import { PlusIcon } from "@heroicons/react/solid";
|
||||
import { credentialListCall, credentialCreateCall, credentialDeleteCall, credentialUpdateCall, CredentialItem, CredentialsResponse } from "@/components/networking"; // Assume this is your networking function
|
||||
import AddCredentialsTab from "./add_credentials_tab";
|
||||
import CredentialDeleteModal from "./CredentialDeleteModal";
|
||||
import { Form, message } from "antd";
|
||||
interface CredentialsPanelProps {
|
||||
accessToken: string | null;
|
||||
|
|
@ -37,6 +38,7 @@ const CredentialsPanel: React.FC<CredentialsPanelProps> = ({ accessToken, upload
|
|||
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
||||
const [isUpdateModalOpen, setIsUpdateModalOpen] = useState(false);
|
||||
const [selectedCredential, setSelectedCredential] = useState<CredentialItem | null>(null);
|
||||
const [credentialToDelete, setCredentialToDelete] = useState<string | null>(null);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const restrictedFields = ['credential_name', 'custom_llm_provider'];
|
||||
|
|
@ -119,9 +121,18 @@ const CredentialsPanel: React.FC<CredentialsPanelProps> = ({ accessToken, upload
|
|||
}
|
||||
const response = await credentialDeleteCall(accessToken, credentialName);
|
||||
message.success('Credential deleted successfully');
|
||||
setCredentialToDelete(null);
|
||||
fetchCredentials(accessToken);
|
||||
};
|
||||
|
||||
const openDeleteModal = (credentialName: string) => {
|
||||
setCredentialToDelete(credentialName);
|
||||
};
|
||||
|
||||
const closeDeleteModal = () => {
|
||||
setCredentialToDelete(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full mx-auto flex-auto overflow-y-auto m-8 p-2">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
|
|
@ -168,7 +179,7 @@ const CredentialsPanel: React.FC<CredentialsPanelProps> = ({ accessToken, upload
|
|||
icon={TrashIcon}
|
||||
variant="light"
|
||||
size="sm"
|
||||
onClick={() => handleDeleteCredential(credential.credential_name)}
|
||||
onClick={() => openDeleteModal(credential.credential_name)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
@ -208,6 +219,15 @@ const CredentialsPanel: React.FC<CredentialsPanelProps> = ({ accessToken, upload
|
|||
addOrEdit="edit"
|
||||
/>
|
||||
)}
|
||||
|
||||
{credentialToDelete && (
|
||||
<CredentialDeleteModal
|
||||
isVisible={true}
|
||||
onCancel={closeDeleteModal}
|
||||
onConfirm={() => handleDeleteCredential(credentialToDelete)}
|
||||
credentialName={credentialToDelete}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue