Spaces:
Running
Running
| import React, { useState } from "react"; | |
| import { | |
| Dialog, | |
| DialogContent, | |
| DialogDescription, | |
| DialogHeader, | |
| DialogTitle, | |
| } from "@/components/ui/dialog"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Label } from "@/components/ui/label"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Checkbox } from "@/components/ui/checkbox"; | |
| import { Separator } from "@/components/ui/separator"; | |
| import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; | |
| import { Settings, Zap, RotateCcw } from "lucide-react"; | |
| interface PreprocessingOptions { | |
| max_char: number | null; | |
| topk: number; | |
| raw: boolean; | |
| hierarchy: boolean; | |
| replace: boolean; | |
| truncate_enabled: boolean; | |
| } | |
| interface PreprocessingMethodModalProps { | |
| open: boolean; | |
| onOpenChange: (open: boolean) => void; | |
| onConfirm: (options: PreprocessingOptions) => void; | |
| onCancel: () => void; | |
| isLoading?: boolean; | |
| } | |
| export function PreprocessingMethodModal({ | |
| open, | |
| onOpenChange, | |
| onConfirm, | |
| onCancel, | |
| isLoading = false, | |
| }: PreprocessingMethodModalProps) { | |
| const [options, setOptions] = useState<PreprocessingOptions>({ | |
| max_char: 1000, | |
| topk: 10, | |
| raw: false, | |
| hierarchy: true, | |
| replace: true, | |
| truncate_enabled: false, | |
| }); | |
| const handleConfirm = () => { | |
| // Set max_char to null if truncate is disabled | |
| const processedOptions = { | |
| ...options, | |
| max_char: options.truncate_enabled ? options.max_char : null | |
| }; | |
| onConfirm(processedOptions); | |
| }; | |
| const handleReset = () => { | |
| setOptions({ | |
| max_char: 1000, | |
| topk: 10, | |
| raw: false, | |
| hierarchy: true, | |
| replace: true, | |
| truncate_enabled: false, | |
| }); | |
| }; | |
| const updateOption = <K extends keyof PreprocessingOptions>( | |
| key: K, | |
| value: PreprocessingOptions[K] | |
| ) => { | |
| setOptions(prev => ({ ...prev, [key]: value })); | |
| }; | |
| return ( | |
| <Dialog open={open} onOpenChange={onOpenChange}> | |
| <DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-y-auto"> | |
| <DialogHeader> | |
| <DialogTitle className="flex items-center gap-2"> | |
| <Settings className="h-5 w-5" /> | |
| Preprocessing Configuration | |
| </DialogTitle> | |
| <DialogDescription> | |
| Configure how traces will be processed before import. Adjust these settings to optimize trace analysis and storage. | |
| </DialogDescription> | |
| </DialogHeader> | |
| <div className="space-y-6 py-4"> | |
| <Card> | |
| <CardHeader className="pb-3"> | |
| <div className="flex items-center justify-between"> | |
| <div> | |
| <CardTitle className="text-base flex items-center gap-2"> | |
| <Settings className="h-5 w-5" /> | |
| Preprocessing Configuration | |
| </CardTitle> | |
| <CardDescription> | |
| Configure how traces will be processed before import | |
| </CardDescription> | |
| </div> | |
| {/* Keep Raw Data Toggle - Top right */} | |
| <div className="flex items-center space-x-2"> | |
| <Checkbox | |
| id="raw" | |
| checked={options.raw} | |
| onCheckedChange={(checked: boolean) => updateOption('raw', checked)} | |
| disabled={isLoading} | |
| /> | |
| <Label htmlFor="raw" className="text-sm font-medium text-muted-foreground"> | |
| Keep Raw Data | |
| </Label> | |
| </div> | |
| </div> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| {options.raw && ( | |
| <div className="p-4 bg-red-50 border border-red-200 rounded-md"> | |
| <div className="flex items-start gap-3"> | |
| <div className="flex-shrink-0"> | |
| <div className="w-5 h-5 bg-red-500 rounded-full flex items-center justify-center"> | |
| <span className="text-white text-xs font-bold">!</span> | |
| </div> | |
| </div> | |
| <div className="text-sm text-red-800"> | |
| <div className="font-semibold text-red-900 mb-2">⚠️ Raw Data Mode Warning</div> | |
| <ul className="space-y-1 text-red-700"> | |
| <li>• <strong>Large file sizes:</strong> No compression or truncation applied</li> | |
| <li>• <strong>Unnecessary noise:</strong> Metadata and debug info will reduce analysis quality</li> | |
| <li>• <strong>Agent Graph degradation:</strong> Unfiltered data may harm knowledge extraction</li> | |
| <li>• <strong>Higher processing costs:</strong> Larger files require more resources</li> | |
| </ul> | |
| <div className="mt-2 text-xs text-red-600 italic"> | |
| Recommended: Use filtering options for better analysis results | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| {/* Show processing options only when raw is false */} | |
| {!options.raw && ( | |
| <> | |
| <Separator /> | |
| {/* Compression Options */} | |
| <div className="space-y-4"> | |
| <div className="flex items-center gap-2"> | |
| <Zap className="h-4 w-4" /> | |
| <h4 className="text-sm font-medium">Compression Options</h4> | |
| </div> | |
| <div className="space-y-4 pl-6"> | |
| {/* Hierarchical Structure */} | |
| <div className="flex items-center space-x-2"> | |
| <Checkbox | |
| id="hierarchy" | |
| checked={options.hierarchy} | |
| onCheckedChange={(checked: boolean) => updateOption('hierarchy', checked)} | |
| disabled={isLoading} | |
| /> | |
| <div className="space-y-1"> | |
| <Label htmlFor="hierarchy" className="text-sm font-medium"> | |
| Hierarchical Structure | |
| </Label> | |
| <p className="text-xs text-muted-foreground"> | |
| Organize runs in parent-child hierarchy instead of flat list | |
| </p> | |
| </div> | |
| </div> | |
| {/* Extract Repeated Variables */} | |
| <div className="flex items-center space-x-2"> | |
| <Checkbox | |
| id="replace" | |
| checked={options.replace} | |
| onCheckedChange={(checked: boolean) => updateOption('replace', checked)} | |
| disabled={isLoading} | |
| /> | |
| <div className="space-y-1"> | |
| <Label htmlFor="replace" className="text-sm font-medium"> | |
| Extract Repeated Variables | |
| </Label> | |
| <p className="text-xs text-muted-foreground"> | |
| Replace repeated strings with variables to reduce file size | |
| </p> | |
| </div> | |
| </div> | |
| {/* Repeated Variables Count - only when compression is enabled */} | |
| {options.replace && ( | |
| <div className="space-y-2"> | |
| <Label htmlFor="topk" className="text-sm font-medium"> | |
| Repeated Variables Count | |
| </Label> | |
| <Input | |
| id="topk" | |
| type="number" | |
| min="1" | |
| max="50" | |
| value={options.topk} | |
| onChange={(e) => updateOption('topk', parseInt(e.target.value) || 10)} | |
| disabled={isLoading} | |
| /> | |
| <p className="text-xs text-muted-foreground"> | |
| Number of repeated strings to extract as variables for compression (1-50) | |
| </p> | |
| </div> | |
| )} | |
| {/* Enable String Truncation */} | |
| <div className="flex items-center space-x-2"> | |
| <Checkbox | |
| id="truncate_enabled" | |
| checked={options.truncate_enabled} | |
| onCheckedChange={(checked: boolean) => updateOption('truncate_enabled', checked)} | |
| disabled={isLoading} | |
| /> | |
| <div className="space-y-1"> | |
| <Label htmlFor="truncate_enabled" className="text-sm font-medium"> | |
| Enable String Truncation | |
| </Label> | |
| <p className="text-xs text-muted-foreground"> | |
| Limit the length of strings to manage file size and processing costs | |
| </p> | |
| </div> | |
| </div> | |
| {/* Maximum Characters - only when truncation is enabled */} | |
| {options.truncate_enabled && ( | |
| <div className="space-y-2"> | |
| <Label htmlFor="max_char" className="text-sm font-medium"> | |
| Maximum Characters per String | |
| </Label> | |
| <Input | |
| id="max_char" | |
| type="number" | |
| min="1000" | |
| max="10000" | |
| step="100" | |
| value={options.max_char ?? 1000} | |
| onChange={(e) => updateOption('max_char', parseInt(e.target.value) || 1000)} | |
| disabled={isLoading} | |
| /> | |
| <p className="text-xs text-muted-foreground"> | |
| Longer text will be truncated to this length to manage processing costs (1000-10000 characters) | |
| </p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </> | |
| )} | |
| </CardContent> | |
| </Card> | |
| </div> | |
| <div className="flex justify-between items-center pt-4 border-t"> | |
| <Button | |
| variant="outline" | |
| onClick={handleReset} | |
| disabled={isLoading} | |
| className="flex items-center gap-2" | |
| > | |
| <RotateCcw className="h-4 w-4" /> | |
| Reset to Defaults | |
| </Button> | |
| <div className="flex gap-3"> | |
| <Button variant="outline" onClick={onCancel} disabled={isLoading}> | |
| Cancel | |
| </Button> | |
| <Button onClick={handleConfirm} disabled={isLoading}> | |
| {isLoading ? ( | |
| <> | |
| <div className="w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin mr-2" /> | |
| Importing... | |
| </> | |
| ) : ( | |
| <> | |
| <Settings className="h-4 w-4 mr-2" /> | |
| Import with Configuration | |
| </> | |
| )} | |
| </Button> | |
| </div> | |
| </div> | |
| </DialogContent> | |
| </Dialog> | |
| ); | |
| } | |