diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json index 2436cb0e3b7..8c00969cfcf 100644 --- a/ui/litellm-dashboard/eslint-suppressions.json +++ b/ui/litellm-dashboard/eslint-suppressions.json @@ -921,15 +921,9 @@ } }, "src/app/(dashboard)/playground/components/chat_ui/ChatUI.tsx": { - "local/no-complex-jsx-arrow": { - "count": 1 - }, "max-lines": { "count": 1 }, - "no-nested-ternary": { - "count": 6 - }, "react-hooks/set-state-in-effect": { "count": 4 } diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatUI.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatUI.tsx index def4e60e27a..bf68328599c 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatUI.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/ChatUI.tsx @@ -109,6 +109,63 @@ const MCP_SUPPORTED_ENDPOINTS = new Set([ const CUSTOM_MODEL_DEBOUNCE_WAIT_MS = 500; +interface SendDisabledOptions { + endpointType: EndpointType; + inputMessage: string; + isLoading: boolean; + selectedMCPDirectTool: string | undefined; + selectedMCPServers: readonly string[]; + uploadedAudio: File | null; + uploadedOcrFile: File | null; +} + +const getInputPlaceholder = (endpointType: EndpointType): string => { + switch (endpointType) { + case EndpointType.CHAT: + case EndpointType.EMBEDDINGS: + case EndpointType.RESPONSES: + case EndpointType.ANTHROPIC_MESSAGES: + case EndpointType.INTERACTIONS: + return "Type your message... (Shift+Enter for new line)"; + case EndpointType.A2A_AGENTS: + return "Send a message to the A2A agent..."; + case EndpointType.IMAGE_EDITS: + return "Describe how you want to edit the image..."; + case EndpointType.SPEECH: + return "Enter text to convert to speech..."; + case EndpointType.TRANSCRIPTION: + return "Optional: Add context or prompt for transcription..."; + case EndpointType.OCR: + return "Upload a document or image to run OCR"; + default: + return "Describe the image you want to generate..."; + } +}; + +const getSendDisabled = ({ + endpointType, + inputMessage, + isLoading, + selectedMCPDirectTool, + selectedMCPServers, + uploadedAudio, + uploadedOcrFile, +}: SendDisabledOptions): boolean => { + if (isLoading) { + return true; + } + if (endpointType === EndpointType.MCP) { + return !(selectedMCPServers.length === 1 && selectedMCPServers[0] !== "__all__" && selectedMCPDirectTool); + } + if (endpointType === EndpointType.TRANSCRIPTION) { + return !uploadedAudio; + } + if (endpointType === EndpointType.OCR) { + return !uploadedOcrFile; + } + return !inputMessage.trim(); +}; + const ChatUI: React.FC = ({ accessToken, token, @@ -659,6 +716,14 @@ const ChatUI: React.FC = ({ event.target.value = ""; }; + const handleAudioFileDrop = (event: React.DragEvent) => { + event.preventDefault(); + const file = event.dataTransfer.files[0]; + if (file) { + handleAudioUpload(file); + } + }; + const mcpServerOptions = useMemo((): MultiSelectOption[] => { const options: MultiSelectOption[] = []; if (endpointType !== EndpointType.MCP) { @@ -738,6 +803,14 @@ const ChatUI: React.FC = ({ event.target.value = ""; }; + const handleOcrFileDrop = (event: React.DragEvent) => { + event.preventDefault(); + const file = event.dataTransfer.files[0]; + if (file) { + handleOcrFileUpload(file); + } + }; + const handleRemoveOcrFile = () => { setUploadedOcrFile(null); revokeOcrFilePreviewUrl(); @@ -1255,34 +1328,16 @@ const ChatUI: React.FC = ({ modelEmptyText = "No models available for this endpoint"; } - const inputPlaceholder = - endpointType === EndpointType.CHAT || - endpointType === EndpointType.EMBEDDINGS || - endpointType === EndpointType.RESPONSES || - endpointType === EndpointType.ANTHROPIC_MESSAGES || - endpointType === EndpointType.INTERACTIONS - ? "Type your message... (Shift+Enter for new line)" - : endpointType === EndpointType.A2A_AGENTS - ? "Send a message to the A2A agent..." - : endpointType === EndpointType.IMAGE_EDITS - ? "Describe how you want to edit the image..." - : endpointType === EndpointType.SPEECH - ? "Enter text to convert to speech..." - : endpointType === EndpointType.TRANSCRIPTION - ? "Optional: Add context or prompt for transcription..." - : endpointType === EndpointType.OCR - ? "Upload a document or image to run OCR" - : "Describe the image you want to generate..."; - - const sendDisabled = - isLoading || - (endpointType === EndpointType.MCP - ? !(selectedMCPServers.length === 1 && selectedMCPServers[0] !== "__all__" && selectedMCPDirectTool) - : endpointType === EndpointType.TRANSCRIPTION - ? !uploadedAudio - : endpointType === EndpointType.OCR - ? !uploadedOcrFile - : !inputMessage.trim()); + const inputPlaceholder = getInputPlaceholder(endpointType as EndpointType); + const sendDisabled = getSendDisabled({ + endpointType: endpointType as EndpointType, + inputMessage, + isLoading, + selectedMCPDirectTool, + selectedMCPServers, + uploadedAudio, + uploadedOcrFile, + }); return (
@@ -1963,13 +2018,7 @@ const ChatUI: React.FC = ({