Restore provider selection, model selection, and context/glossary in file uploader
This commit is contained in:
parent
dfd45d9f07
commit
721b18dbbd
@ -2,15 +2,16 @@
|
||||
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import { Upload, FileText, FileSpreadsheet, Presentation, X, Download, Loader2, Cpu, AlertTriangle } from "lucide-react";
|
||||
import { Upload, FileText, FileSpreadsheet, Presentation, X, Download, Loader2, Cpu, AlertTriangle, Brain } from "lucide-react";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Progress } from "@/components/ui/progress";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useTranslationStore } from "@/lib/store";
|
||||
import { useTranslationStore, openaiModels, openrouterModels } from "@/lib/store";
|
||||
import { translateDocument, languages, providers, extractTextsFromDocument, reconstructDocument, TranslatedText } from "@/lib/api";
|
||||
import { useWebLLM } from "@/lib/webllm";
|
||||
import { cn } from "@/lib/utils";
|
||||
@ -323,7 +324,7 @@ export function FileUploader() {
|
||||
<CardHeader>
|
||||
<CardTitle className="text-white">Translation Options</CardTitle>
|
||||
<CardDescription>
|
||||
Select your target language and start translating
|
||||
Configure your translation settings
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
@ -351,6 +352,133 @@ export function FileUploader() {
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* Provider Selection */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="provider" className="text-zinc-300">Translation Provider</Label>
|
||||
<Select value={provider} onValueChange={(v) => setProvider(v as ProviderType)}>
|
||||
<SelectTrigger id="provider" className="bg-zinc-800 border-zinc-700 text-white">
|
||||
<SelectValue placeholder="Select provider" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-zinc-800 border-zinc-700">
|
||||
{providers.map((p) => (
|
||||
<SelectItem
|
||||
key={p.id}
|
||||
value={p.id}
|
||||
className="text-white hover:bg-zinc-700"
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<span>{p.icon}</span>
|
||||
<span>{p.name}</span>
|
||||
</span>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* OpenAI Model Selection */}
|
||||
{provider === "openai" && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="openai-model" className="text-zinc-300">OpenAI Model</Label>
|
||||
<Select
|
||||
value={settings.openaiModel}
|
||||
onValueChange={(v) => useTranslationStore.getState().updateSettings({ openaiModel: v })}
|
||||
>
|
||||
<SelectTrigger id="openai-model" className="bg-zinc-800 border-zinc-700 text-white">
|
||||
<SelectValue placeholder="Select model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-zinc-800 border-zinc-700">
|
||||
{openaiModels.map((m) => (
|
||||
<SelectItem
|
||||
key={m.id}
|
||||
value={m.id}
|
||||
className="text-white hover:bg-zinc-700"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span>{m.name}</span>
|
||||
<span className="text-xs text-zinc-500">{m.description}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{!settings.openaiApiKey && (
|
||||
<p className="text-xs text-amber-400">⚠️ API key required in Settings</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* OpenRouter Model Selection */}
|
||||
{provider === "openrouter" && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="openrouter-model" className="text-zinc-300">OpenRouter Model</Label>
|
||||
<Select
|
||||
value={settings.openrouterModel}
|
||||
onValueChange={(v) => useTranslationStore.getState().updateSettings({ openrouterModel: v })}
|
||||
>
|
||||
<SelectTrigger id="openrouter-model" className="bg-zinc-800 border-zinc-700 text-white">
|
||||
<SelectValue placeholder="Select model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-zinc-800 border-zinc-700">
|
||||
{openrouterModels.map((m) => (
|
||||
<SelectItem
|
||||
key={m.id}
|
||||
value={m.id}
|
||||
className="text-white hover:bg-zinc-700"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span>{m.name}</span>
|
||||
<span className="text-xs text-zinc-500">{m.description}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{!settings.openrouterApiKey && (
|
||||
<p className="text-xs text-amber-400">⚠️ API key required in Settings</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Context Section - Only for LLM providers */}
|
||||
{(provider === "openai" || provider === "openrouter" || provider === "ollama") && (
|
||||
<div className="space-y-4 p-4 bg-zinc-800/50 rounded-lg border border-zinc-700">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-zinc-300 flex items-center gap-2">
|
||||
<Brain className="h-4 w-4 text-teal-400" />
|
||||
Translation Context
|
||||
</Label>
|
||||
<Badge variant="outline" className="border-teal-500/50 text-teal-400 text-xs">
|
||||
LLM Only
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* System Prompt */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="system-prompt" className="text-zinc-400 text-sm">Instructions for the AI</Label>
|
||||
<Textarea
|
||||
id="system-prompt"
|
||||
value={settings.systemPrompt}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => useTranslationStore.getState().updateSettings({ systemPrompt: e.target.value })}
|
||||
placeholder="E.g., You are translating technical HVAC documentation. Keep unit measurements unchanged. Use formal language..."
|
||||
className="bg-zinc-900 border-zinc-700 text-white placeholder:text-zinc-600 min-h-[80px] text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Glossary */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="glossary" className="text-zinc-400 text-sm">Glossary (term=translation, one per line)</Label>
|
||||
<Textarea
|
||||
id="glossary"
|
||||
value={settings.glossary}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => useTranslationStore.getState().updateSettings({ glossary: e.target.value })}
|
||||
placeholder="compressor=compresseur evaporator=évaporateur condenser=condenseur"
|
||||
className="bg-zinc-900 border-zinc-700 text-white placeholder:text-zinc-600 min-h-[80px] text-sm font-mono"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Translate Button */}
|
||||
<Button
|
||||
onClick={handleTranslate}
|
||||
|
||||
@ -10,6 +10,8 @@ import {
|
||||
LogIn,
|
||||
Crown,
|
||||
LogOut,
|
||||
Settings,
|
||||
BookOpen,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
Tooltip,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user