import React, { useState, useEffect } from 'react'; import { X, Calendar, Clock, FolderInput, ArrowRight } from 'lucide-react'; import { useLanguage } from '../contexts/LanguageContext'; import { ModelConfig, ModelType, IndexingConfig } from '../types'; import { modelConfigService } from '../services/modelConfigService'; import { importService } from '../services/importService'; import { useToast } from '../contexts/ToastContext'; import IndexingModalWithMode from './IndexingModalWithMode'; interface ImportFolderDrawerProps { isOpen: boolean; onClose: () => void; authToken: string; initialGroupId?: string; // If provided, locks target to this group initialGroupName?: string; onImportSuccess?: () => void; } export const ImportFolderDrawer: React.FC = ({ isOpen, onClose, authToken, initialGroupId, initialGroupName, onImportSuccess }) => { const { t } = useLanguage(); const { showError, showSuccess } = useToast(); // Form State const [sourcePath, setSourcePath] = useState(''); const [targetName, setTargetName] = useState(''); const [executionType, setExecutionType] = useState<'immediate' | 'scheduled'>('immediate'); const [scheduledTime, setScheduledTime] = useState(''); // Indexing Config State const [isIndexingConfigOpen, setIsIndexingConfigOpen] = useState(false); // Data State const [models, setModels] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (isOpen) { // Reset form setSourcePath(''); setTargetName(initialGroupName || ''); setExecutionType('immediate'); setScheduledTime(''); setIsIndexingConfigOpen(false); // Fetch models modelConfigService.getAll(authToken).then(res => { setModels(res.filter(m => m.type === ModelType.EMBEDDING)); }); } }, [isOpen, authToken, initialGroupName]); // Auto-fill target name from path if not locked to a group const handlePathChange = (e: React.ChangeEvent) => { const val = e.target.value; setSourcePath(val); if (!initialGroupId && val) { // Extract last folder name (Windows or Unix style) const parts = val.split(/[\\/]/).filter(p => p); if (parts.length > 0) { setTargetName(parts[parts.length - 1]); } } }; const handleNext = async () => { if (!sourcePath) { showError(t('fillSourcePath')); return; } if (!initialGroupId && !targetName) { showError(t('fillTargetName')); return; } if (executionType === 'scheduled' && !scheduledTime) { showError(t('selectExecTime')); return; } // Open indexing config modal setIsIndexingConfigOpen(true); }; const handleConfirmConfig = async (config: IndexingConfig) => { setIsLoading(true); try { await importService.create(authToken, { sourcePath, targetGroupId: initialGroupId || undefined, targetGroupName: initialGroupId ? undefined : targetName, embeddingModelId: config.embeddingModelId, scheduledAt: executionType === 'scheduled' ? new Date(scheduledTime).toISOString() : undefined, chunkSize: config.chunkSize, chunkOverlap: config.chunkOverlap, mode: config.mode }); showSuccess(executionType === 'immediate' ? t('importTaskStarted') : t('importTaskScheduled')); onImportSuccess?.(); onClose(); } catch (error: any) { showError(t('submitFailed', error.message)); } finally { setIsLoading(false); setIsIndexingConfigOpen(false); } }; if (!isOpen) return null; return ( <>
{/* Header */}

{t('importFolderTitle')}

{/* Body */}
{t('importFolderTip')}
{/* Source Path */}
{/* Target Group */}
setTargetName(e.target.value)} disabled={!!initialGroupId} // Readonly if locking to group placeholder={t('placeholderNewGroup')} className={`w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none ${initialGroupId ? 'bg-slate-50 text-slate-500' : ''}`} /> {initialGroupId &&

{t('importToCurrentGroup')}

}
{/* Execution Type */}
{/* Schedule Time Picker */} {executionType === 'scheduled' && (
setScheduledTime(e.target.value)} min={new Date().toISOString().slice(0, 16)} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none" />
)}
{/* Footer */}
{/* Indexing Config Modal */} setIsIndexingConfigOpen(false)} files={[]} // Empty array for folder import mode embeddingModels={models} defaultEmbeddingId={models.length > 0 ? models[0].id : ''} onConfirm={handleConfirmConfig} isReconfiguring={false} /> ); };