mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
Merge pull request #18170 from BerriAI/litellm_ui_cloudzero_delete
[Feature] UI - Cloudzero Delete Settings
This commit is contained in:
commit
cacaf54b95
3 changed files with 114 additions and 21 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { getProxyBaseUrl } from "@/components/networking";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { createQueryKeys } from "../common/queryKeysFactory";
|
||||
import { CloudZeroSettings } from "@/components/CloudZeroCostTracking/types";
|
||||
import { getProxyBaseUrl } from "@/components/networking";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { createQueryKeys } from "../common/queryKeysFactory";
|
||||
|
||||
const cloudZeroSettingsKeys = createQueryKeys("cloudZeroSettings");
|
||||
|
||||
|
|
@ -54,6 +54,11 @@ interface UpdateResponse {
|
|||
status: string;
|
||||
}
|
||||
|
||||
interface DeleteResponse {
|
||||
message: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
const updateCloudZeroSettings = async (accessToken: string, params: UpdateParams): Promise<UpdateResponse> => {
|
||||
const proxyBaseUrl = getProxyBaseUrl();
|
||||
const url = proxyBaseUrl ? `${proxyBaseUrl}/cloudzero/settings` : `/cloudzero/settings`;
|
||||
|
|
@ -98,3 +103,43 @@ export const useCloudZeroUpdateSettings = (accessToken: string) => {
|
|||
},
|
||||
});
|
||||
};
|
||||
|
||||
const deleteCloudZeroSettings = async (accessToken: string): Promise<DeleteResponse> => {
|
||||
const proxyBaseUrl = getProxyBaseUrl();
|
||||
const url = proxyBaseUrl ? `${proxyBaseUrl}/cloudzero/delete` : `/cloudzero/delete`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
const errorMessage =
|
||||
errorData?.error?.message || errorData?.message || errorData?.detail || "Failed to delete CloudZero settings";
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
export const useCloudZeroDeleteSettings = (accessToken: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<DeleteResponse, Error, void>({
|
||||
mutationFn: async () => {
|
||||
if (!accessToken) {
|
||||
throw new Error("Access token is required");
|
||||
}
|
||||
return await deleteCloudZeroSettings(accessToken);
|
||||
},
|
||||
onSuccess: () => {
|
||||
// Invalidate the settings query to refetch updated data
|
||||
queryClient.invalidateQueries({ queryKey: cloudZeroSettingsKeys.list({}) });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { CloudZeroIntegrationSettings } from "./CloudZeroIntegrationSettings";
|
||||
import { CloudZeroSettings } from "./types";
|
||||
|
||||
|
|
@ -68,4 +68,15 @@ describe("CloudZeroIntegrationSettings", () => {
|
|||
expect(screen.getByText("Connection ID")).toBeInTheDocument();
|
||||
expect(screen.getByText("Timezone")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display the correct values from settings", () => {
|
||||
render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<CloudZeroIntegrationSettings settings={mockSettings} onSettingsUpdated={vi.fn()} />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText(mockSettings.api_key_masked)).toBeInTheDocument();
|
||||
expect(screen.getByText(mockSettings.connection_id)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useCloudZeroDryRun } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroDryRun";
|
||||
import { useCloudZeroExport } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroExport";
|
||||
import { useCloudZeroDeleteSettings } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroSettings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";
|
||||
import { Alert, Button, Card, Descriptions, Divider, message, Popconfirm, Tag } from "antd";
|
||||
import { CheckCircle, Edit, Play, Trash2, Upload } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
|
@ -15,9 +17,11 @@ interface CloudZeroIntegrationSettingsProps {
|
|||
export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: CloudZeroIntegrationSettingsProps) {
|
||||
const { accessToken } = useAuthorized();
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
|
||||
const dryRunMutation = useCloudZeroDryRun(accessToken || "");
|
||||
const exportMutation = useCloudZeroExport(accessToken || "");
|
||||
const deleteMutation = useCloudZeroDeleteSettings(accessToken || "");
|
||||
|
||||
const handleDryRun = () => {
|
||||
if (!accessToken) return;
|
||||
|
|
@ -66,10 +70,27 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
setIsEditModalOpen(false);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
// Note: Delete functionality is not yet implemented in the backend API
|
||||
// This would require a DELETE endpoint at /cloudzero/settings
|
||||
message.warning("Delete functionality is not yet available. Please contact support.");
|
||||
const handleDeleteClick = () => {
|
||||
setIsDeleteModalOpen(true);
|
||||
};
|
||||
|
||||
const handleDeleteConfirm = () => {
|
||||
if (!accessToken) return;
|
||||
|
||||
deleteMutation.mutate(undefined, {
|
||||
onSuccess: () => {
|
||||
message.success("CloudZero integration deleted successfully");
|
||||
setIsDeleteModalOpen(false);
|
||||
onSettingsUpdated();
|
||||
},
|
||||
onError: (error) => {
|
||||
message.error(error?.message || "Failed to delete CloudZero integration");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteCancel = () => {
|
||||
setIsDeleteModalOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -89,19 +110,14 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
<Button icon={<Edit size={16} />} onClick={handleEdit} className="flex items-center gap-2">
|
||||
Edit
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="Delete Integration"
|
||||
description="Delete functionality is not yet available in the API. This button is disabled."
|
||||
okText="OK"
|
||||
cancelText="Cancel"
|
||||
okButtonProps={{
|
||||
danger: true,
|
||||
}}
|
||||
<Button
|
||||
danger
|
||||
icon={<Trash2 size={16} />}
|
||||
onClick={handleDeleteClick}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Button danger icon={<Trash2 size={16} />} disabled className="flex items-center gap-2">
|
||||
Delete
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
className="shadow-sm"
|
||||
|
|
@ -187,6 +203,27 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
onCancel={handleEditModalCancel}
|
||||
settings={settings}
|
||||
/>
|
||||
|
||||
<DeleteResourceModal
|
||||
isOpen={isDeleteModalOpen}
|
||||
title="Delete CloudZero Integration?"
|
||||
message="Are you sure you want to delete this CloudZero integration? All associated settings and configurations will be permanently removed."
|
||||
resourceInformationTitle="Integration Details"
|
||||
resourceInformation={[
|
||||
{
|
||||
label: "Connection ID",
|
||||
value: settings.connection_id,
|
||||
code: true,
|
||||
},
|
||||
{
|
||||
label: "Timezone",
|
||||
value: settings.timezone || "Default (UTC)",
|
||||
},
|
||||
]}
|
||||
onCancel={handleDeleteCancel}
|
||||
onOk={handleDeleteConfirm}
|
||||
confirmLoading={deleteMutation.isPending}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue