From 22ee90664cc0231ae78b1a38c2ebeab09008c984 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Wed, 4 Mar 2026 12:34:46 +0545 Subject: [PATCH] feat: enhance Ollama URL handling in TextProvider and PresentonMode components, adding custom URL options and improving user experience --- .../(dashboard)/settings/TextProvider.tsx | 90 +++++++++++---- .../components/OnBoarding/PresentonMode.tsx | 105 +++++++++++++----- servers/nextjs/utils/providerConstants.ts | 7 ++ 3 files changed, 153 insertions(+), 49 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx index c9d1743b..bf9ccf8c 100644 --- a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx +++ b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx @@ -5,7 +5,7 @@ import { Switch } from '@/components/ui/switch'; import { cn } from '@/lib/utils'; import { LLMConfig } from '@/types/llm_config'; import { LLM_PROVIDERS } from '@/utils/providerConstants'; -import { Check, ChevronsUpDown, Loader2, Eye, EyeOff, ChevronUp } from 'lucide-react'; +import { Check, Loader2, Eye, EyeOff, ChevronUp } from 'lucide-react'; import React, { useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'sonner'; @@ -68,6 +68,7 @@ const TextProvider = ({ const currentApiKey = currentApiKeyField ? ((llmConfig as Record)[currentApiKeyField] as string || '') : ''; const currentCustomUrl = llmConfig.CUSTOM_LLM_URL || ''; const currentOllamaUrl = llmConfig.OLLAMA_URL || ''; + const useCustomOllamaUrl = !!llmConfig.USE_CUSTOM_URL; const modelLabel = selectedProviderMeta?.label || selectedProvider; useEffect(() => { @@ -304,28 +305,71 @@ const TextProvider = ({
- -
- onApiKeyChange(selectedProvider, e.target.value)} - className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" - placeholder={selectedProvider === 'ollama' ? 'http://localhost:11434' : `Enter your ${llmConfig.LLM} API key`} - /> - {selectedProvider !== 'ollama' && ( - - )} -
+ {selectedProvider === 'ollama' ? ( + <> + {!useCustomOllamaUrl ? ( + + ) : ( + <> + +
+ onApiKeyChange(selectedProvider, e.target.value)} + className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + placeholder="http://localhost:11434" + /> +
+ + + )} + + ) : ( + <> + +
+ onApiKeyChange(selectedProvider, e.target.value)} + className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + placeholder={`Enter your ${llmConfig.LLM} API key`} + /> + +
+ + )} {selectedProvider === 'custom' && ( )[currentApiKeyField] as string || '') : ''; const currentModel = currentModelField ? ((llmConfig as Record)[currentModelField] as string || '') : ''; + const currentOllamaUrl = llmConfig.OLLAMA_URL || ''; + const useCustomOllamaUrl = !!llmConfig.USE_CUSTOM_URL; const fetchAvailableModels = async () => { if (llmConfig.LLM === 'openai' && !currentApiKey) return; @@ -309,6 +311,11 @@ const PresentonMode = ({ currentStep, setStep }: { currentStep: number, setStep: return 0; }, [downloadingModel?.downloaded, downloadingModel?.size]); + useEffect(() => { + if (llmConfig.LLM === 'ollama' && !modelsChecked && !modelsLoading) { + fetchAvailableModels(); + } + }, [llmConfig.LLM, modelsChecked, modelsLoading]); return (
@@ -414,31 +421,77 @@ const PresentonMode = ({ currentStep, setStep }: { currentStep: number, setStep:
- -
- setLlmConfig(prev => ({ - ...prev, - [currentApiKeyField]: e.target.value - }))} - className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" - placeholder={llmConfig.LLM === 'ollama' ? 'http://localhost:11434' : `Enter your ${llmConfig.LLM} API key`} - /> - {llmConfig.LLM !== 'ollama' && ( - - )} -
+ {llmConfig.LLM === 'ollama' ? ( + <> + {!useCustomOllamaUrl ? ( + + ) : ( + <> + +
+ setLlmConfig(prev => ({ + ...prev, + OLLAMA_URL: e.target.value + }))} + className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + placeholder="http://localhost:11434" + /> +
+ + + )} + + ) : ( + <> + +
+ setLlmConfig(prev => ({ + ...prev, + [currentApiKeyField]: e.target.value + }))} + className="w-full px-2 py-3 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + placeholder={`Enter your ${llmConfig.LLM} API key`} + /> + +
+ + )} {llmConfig.LLM === 'custom' && ( setLlmConfig(prev => ({ ...prev, DISABLE_IMAGE_GENERATION: !checked diff --git a/servers/nextjs/utils/providerConstants.ts b/servers/nextjs/utils/providerConstants.ts index c4b9e98b..1b1756ed 100644 --- a/servers/nextjs/utils/providerConstants.ts +++ b/servers/nextjs/utils/providerConstants.ts @@ -23,6 +23,7 @@ export interface LLMProviderOption { model_value?: string; model_label?: string; url?: string; + icon?: string; } export const IMAGE_PROVIDERS: Record = { @@ -97,33 +98,39 @@ export const LLM_PROVIDERS: Record = { label: "OpenAI", description: "OpenAI's latest text generation model", url: "https://api.openai.com/v1", + icon: "/icons/openai.png", }, google: { value: "google", label: "Google", description: "Google's primary text generation model", url: "https://api.google.com/v1", + icon: "/icons/google.png", }, anthropic: { value: "anthropic", label: "Anthropic", description: "Anthropic's Claude models", url: "https://api.anthropic.com/v1", + icon: "/icons/anthropic.png", }, ollama: { value: "ollama", label: "Ollama", description: "Ollama's primary text generation model", + icon: "/icons/ollama.png", }, custom: { value: "custom", label: "Custom", description: "Custom LLM", + icon: "/icons/custom.png", }, codex: { value: "codex", label: "ChatGPT", description: "ChatGPT Plus/Pro via OAuth", + icon: "/icons/chatgpt.png", }, };