diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index 2cfb4a1f4c7..7012eddb850 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -54,6 +54,7 @@ "src/components/agents/agent_table.tsx", "src/components/view_users/columns.tsx", "src/components/Projects/ProjectsPage.tsx", + "src/components/pass_through_settings.tsx", "src/components/permissions/VectorStorePermissions.tsx", "src/components/permissions/AgentPermissions.tsx", "src/components/permissions/MCPServerPermissions.tsx", diff --git a/ui/litellm-dashboard/src/components/pass_through_settings.tsx b/ui/litellm-dashboard/src/components/pass_through_settings.tsx index d60caa54667..4590429cc42 100644 --- a/ui/litellm-dashboard/src/components/pass_through_settings.tsx +++ b/ui/litellm-dashboard/src/components/pass_through_settings.tsx @@ -1,36 +1,42 @@ import React, { useState, useEffect } from "react"; -import { Text, Button, Icon, Title } from "@tremor/react"; -import { deletePassThroughEndpointsCall, getPassThroughEndpointsCall } from "./networking"; -import { Badge, Tooltip } from "antd"; -import { PencilAltIcon, TrashIcon, InformationCircleIcon } from "@heroicons/react/outline"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { + deletePassThroughEndpointsCall, + getPassThroughEndpointsCall, +} from "./networking"; +import { Eye, EyeOff, Info, Pencil, Trash2 } from "lucide-react"; import AddPassThroughEndpoint from "./add_pass_through"; import PassThroughInfoView from "./pass_through_info"; import { DataTable } from "./view_logs/table"; import { ColumnDef } from "@tanstack/react-table"; -import { Eye, EyeOff } from "lucide-react"; import NotificationsManager from "./molecules/notifications_manager"; interface GeneralSettingsPageProps { accessToken: string | null; userRole: string | null; userID: string | null; + // eslint-disable-next-line @typescript-eslint/no-explicit-any modelData: any; premiumUser?: boolean; } -interface routingStrategyArgs { - ttl?: number; - lowest_latency_buffer?: number; -} - -interface nestedFieldItem { - field_name: string; - field_type: string; - field_value: any; - field_description: string; - stored_in_db: boolean | null; -} - export interface passThroughItem { id?: string; path: string; @@ -40,7 +46,10 @@ export interface passThroughItem { cost_per_request?: number; auth?: boolean; methods?: string[]; - guardrails?: Record; + guardrails?: Record< + string, + { request_fields?: string[]; response_fields?: string[] } | null + >; default_query_params?: Record; } @@ -51,17 +60,36 @@ const PasswordField: React.FC<{ value: object }> = ({ value }) => { return (
- {showPassword ? headerString : "••••••••"} -
); }; -const PassThroughSettings: React.FC = ({ accessToken, userRole, userID, modelData, premiumUser }) => { +const PassThroughSettings: React.FC = ({ + accessToken, + userRole, + userID, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + modelData, + premiumUser, +}) => { const [generalSettings, setGeneralSettings] = useState([]); - const [selectedEndpointId, setSelectedEndpointId] = useState(null); + const [selectedEndpointId, setSelectedEndpointId] = useState( + null, + ); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [endpointToDelete, setEndpointToDelete] = useState(null); @@ -70,23 +98,21 @@ const PassThroughSettings: React.FC = ({ accessToken, return; } getPassThroughEndpointsCall(accessToken).then((data) => { - let general_settings = data["endpoints"]; + const general_settings = data["endpoints"]; setGeneralSettings(general_settings); }); }, [accessToken, userRole, userID]); const handleEndpointUpdated = () => { - // Refresh the endpoints list when an endpoint is updated if (accessToken) { getPassThroughEndpointsCall(accessToken).then((data) => { - let general_settings = data["endpoints"]; + const general_settings = data["endpoints"]; setGeneralSettings(general_settings); }); } }; const handleDelete = async (endpointId: string) => { - // Set the endpoint to delete and open the confirmation modal setEndpointToDelete(endpointId); setIsDeleteModalOpen(true); }; @@ -99,45 +125,53 @@ const PassThroughSettings: React.FC = ({ accessToken, try { await deletePassThroughEndpointsCall(accessToken, endpointToDelete); - const updatedSettings = generalSettings.filter((setting) => setting.id !== endpointToDelete); + const updatedSettings = generalSettings.filter( + (setting) => setting.id !== endpointToDelete, + ); setGeneralSettings(updatedSettings); NotificationsManager.success("Endpoint deleted successfully."); } catch (error) { console.error("Error deleting the endpoint:", error); - NotificationsManager.fromBackend("Error deleting the endpoint: " + error); + NotificationsManager.fromBackend( + "Error deleting the endpoint: " + error, + ); } - // Close the confirmation modal and reset the endpointToDelete setIsDeleteModalOpen(false); setEndpointToDelete(null); }; const cancelDelete = () => { - // Close the confirmation modal and reset the endpointToDelete setIsDeleteModalOpen(false); setEndpointToDelete(null); }; - const handleResetField = (endpointId: string, idx: number) => { - // Use handleDelete instead of direct deletion + const handleResetField = (endpointId: string) => { handleDelete(endpointId); }; - // Define columns for the DataTable const columns: ColumnDef[] = [ { header: "ID", accessorKey: "id", - cell: (info: any) => ( - -
info.row.original.id && setSelectedEndpointId(info.row.original.id)} - > - {info.row.original.id} -
-
+ cell: (info) => ( + + + +
+ info.row.original.id && + setSelectedEndpointId(info.row.original.id) + } + > + {info.row.original.id} +
+
+ {info.row.original.id} +
+
), }, { @@ -147,27 +181,43 @@ const PassThroughSettings: React.FC = ({ accessToken, { header: "Target", accessorKey: "target", - cell: (info: any) => {info.getValue()}, + cell: (info) => ( + {info.getValue() as string} + ), }, { header: () => (
Methods - - - + + + + + + + HTTP methods supported by this endpoint + + +
), accessorKey: "methods", - cell: (info: any) => { - const methods = info.getValue(); + cell: (info) => { + const methods = info.getValue() as string[] | undefined; if (!methods || methods.length === 0) { - return ALL; + return ( + + ALL + + ); } return (
{methods.map((method: string) => ( - + {method} ))} @@ -179,36 +229,63 @@ const PassThroughSettings: React.FC = ({ accessToken, header: () => (
Authentication - - - + + + + + + + LiteLLM Virtual Key required to call endpoint + + +
), accessorKey: "auth", - cell: (info: any) => {info.getValue() ? "Yes" : "No"}, + cell: (info) => ( + + {info.getValue() ? "Yes" : "No"} + + ), }, { header: "Headers", accessorKey: "headers", - cell: (info: any) => , + cell: (info) => , }, { header: "Actions", id: "actions", cell: ({ row }) => (
- row.original.id && setSelectedEndpointId(row.original.id)} + +
), }, @@ -218,12 +295,10 @@ const PassThroughSettings: React.FC = ({ accessToken, return null; } - // If a specific endpoint is selected, show the info view if (selectedEndpointId) { - // Find the endpoint by ID to get the endpoint data for the info view - console.log("selectedEndpointId", selectedEndpointId); - console.log("generalSettings", generalSettings); - const selectedEndpoint = generalSettings.find((endpoint) => endpoint.id === selectedEndpointId); + const selectedEndpoint = generalSettings.find( + (endpoint) => endpoint.id === selectedEndpointId, + ); if (!selectedEndpoint) { return
Endpoint not found
; @@ -244,8 +319,10 @@ const PassThroughSettings: React.FC = ({ accessToken, return (
- Pass Through Endpoints - Configure and manage your pass-through endpoints +

Pass Through Endpoints

+

+ Configure and manage your pass-through endpoints +

= ({ accessToken, noDataMessage="No pass-through endpoints configured" /> - {isDeleteModalOpen && ( -
-
- - - {/* Modal Panel */} - - - {/* Confirmation Modal Content */} -
-
-
-
-

Delete Pass-Through Endpoint

-
-

- Are you sure you want to delete this pass-through endpoint? This action cannot be undone. -

-
-
-
-
-
- - -
-
-
-
- )} + (!o ? cancelDelete() : undefined)} + > + + + Delete Pass-Through Endpoint + + Are you sure you want to delete this pass-through endpoint? This + action cannot be undone. + + + + Cancel + + Delete + + + +
); };