import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import ChangePasswordForm from '@/components/ChangePasswordForm'; import { Switch } from '@/components/ui/ToggleGroup'; import { useSettingsData } from '@/hooks/useSettingsData'; import { useToast } from '@/contexts/ToastContext'; import { generateRandomKey } from '@/utils/key'; const SettingsPage: React.FC = () => { const { t, i18n } = useTranslation(); const navigate = useNavigate(); const { showToast } = useToast(); const [currentLanguage, setCurrentLanguage] = useState(i18n.language); // Update current language when it changes useEffect(() => { setCurrentLanguage(i18n.language); }, [i18n.language]); const [installConfig, setInstallConfig] = useState<{ pythonIndexUrl: string; npmRegistry: string; }>({ pythonIndexUrl: '', npmRegistry: '', }); const [tempSmartRoutingConfig, setTempSmartRoutingConfig] = useState<{ dbUrl: string; openaiApiBaseUrl: string; openaiApiKey: string; openaiApiEmbeddingModel: string; }>({ dbUrl: '', openaiApiBaseUrl: '', openaiApiKey: '', openaiApiEmbeddingModel: '', }); const { routingConfig, tempRoutingConfig, setTempRoutingConfig, installConfig: savedInstallConfig, smartRoutingConfig, loading, updateRoutingConfig, updateRoutingConfigBatch, updateInstallConfig, updateSmartRoutingConfig, updateSmartRoutingConfigBatch } = useSettingsData(); // Update local installConfig when savedInstallConfig changes useEffect(() => { if (savedInstallConfig) { setInstallConfig(savedInstallConfig); } }, [savedInstallConfig]); // Update local tempSmartRoutingConfig when smartRoutingConfig changes useEffect(() => { if (smartRoutingConfig) { setTempSmartRoutingConfig({ dbUrl: smartRoutingConfig.dbUrl || '', openaiApiBaseUrl: smartRoutingConfig.openaiApiBaseUrl || '', openaiApiKey: smartRoutingConfig.openaiApiKey || '', openaiApiEmbeddingModel: smartRoutingConfig.openaiApiEmbeddingModel || '', }); } }, [smartRoutingConfig]); const [sectionsVisible, setSectionsVisible] = useState({ routingConfig: false, installConfig: false, smartRoutingConfig: false, password: false }); const toggleSection = (section: 'routingConfig' | 'installConfig' | 'smartRoutingConfig' | 'password') => { setSectionsVisible(prev => ({ ...prev, [section]: !prev[section] })); }; const handleRoutingConfigChange = async (key: 'enableGlobalRoute' | 'enableGroupNameRoute' | 'enableBearerAuth' | 'bearerAuthKey', value: boolean | string) => { // If enableBearerAuth is turned on and there's no key, generate one first if (key === 'enableBearerAuth' && value === true) { if (!tempRoutingConfig.bearerAuthKey && !routingConfig.bearerAuthKey) { const newKey = generateRandomKey(); handleBearerAuthKeyChange(newKey); // Update both enableBearerAuth and bearerAuthKey in a single call const success = await updateRoutingConfigBatch({ enableBearerAuth: true, bearerAuthKey: newKey }); if (success) { // Update tempRoutingConfig to reflect the saved values setTempRoutingConfig(prev => ({ ...prev, bearerAuthKey: newKey })); } return; } } await updateRoutingConfig(key, value); }; const handleBearerAuthKeyChange = (value: string) => { setTempRoutingConfig(prev => ({ ...prev, bearerAuthKey: value })); }; const saveBearerAuthKey = async () => { await updateRoutingConfig('bearerAuthKey', tempRoutingConfig.bearerAuthKey); }; const handleInstallConfigChange = (key: 'pythonIndexUrl' | 'npmRegistry', value: string) => { setInstallConfig({ ...installConfig, [key]: value }); }; const saveInstallConfig = async (key: 'pythonIndexUrl' | 'npmRegistry') => { await updateInstallConfig(key, installConfig[key]); }; const handleSmartRoutingConfigChange = (key: 'dbUrl' | 'openaiApiBaseUrl' | 'openaiApiKey' | 'openaiApiEmbeddingModel', value: string) => { setTempSmartRoutingConfig({ ...tempSmartRoutingConfig, [key]: value }); }; const saveSmartRoutingConfig = async (key: 'dbUrl' | 'openaiApiBaseUrl' | 'openaiApiKey' | 'openaiApiEmbeddingModel') => { await updateSmartRoutingConfig(key, tempSmartRoutingConfig[key]); }; const handleSmartRoutingEnabledChange = async (value: boolean) => { // If enabling Smart Routing, validate required fields and save any unsaved changes if (value) { const currentDbUrl = tempSmartRoutingConfig.dbUrl || smartRoutingConfig.dbUrl; const currentOpenaiApiKey = tempSmartRoutingConfig.openaiApiKey || smartRoutingConfig.openaiApiKey; if (!currentDbUrl || !currentOpenaiApiKey) { const missingFields = []; if (!currentDbUrl) missingFields.push(t('settings.dbUrl')); if (!currentOpenaiApiKey) missingFields.push(t('settings.openaiApiKey')); showToast(t('settings.smartRoutingValidationError', { fields: missingFields.join(', ') })); return; } // Prepare updates object with unsaved changes and enabled status const updates: any = { enabled: value }; // Check for unsaved changes and include them in the batch update if (tempSmartRoutingConfig.dbUrl !== smartRoutingConfig.dbUrl) { updates.dbUrl = tempSmartRoutingConfig.dbUrl; } if (tempSmartRoutingConfig.openaiApiBaseUrl !== smartRoutingConfig.openaiApiBaseUrl) { updates.openaiApiBaseUrl = tempSmartRoutingConfig.openaiApiBaseUrl; } if (tempSmartRoutingConfig.openaiApiKey !== smartRoutingConfig.openaiApiKey) { updates.openaiApiKey = tempSmartRoutingConfig.openaiApiKey; } if (tempSmartRoutingConfig.openaiApiEmbeddingModel !== smartRoutingConfig.openaiApiEmbeddingModel) { updates.openaiApiEmbeddingModel = tempSmartRoutingConfig.openaiApiEmbeddingModel; } // Save all changes in a single batch update await updateSmartRoutingConfigBatch(updates); } else { // If disabling, just update the enabled status await updateSmartRoutingConfig('enabled', value); } }; const handlePasswordChangeSuccess = () => { setTimeout(() => { navigate('/'); }, 2000); }; const handleLanguageChange = (lang: string) => { localStorage.setItem('i18nextLng', lang); window.location.reload(); }; return (
{t('settings.enableSmartRoutingDescription')}
{t('settings.enableBearerAuthDescription')}
{t('settings.bearerAuthKeyDescription')}
{t('settings.enableGlobalRouteDescription')}
{t('settings.enableGroupNameRouteDescription')}
{t('settings.pythonIndexUrlDescription')}
{t('settings.npmRegistryDescription')}