File size: 4,568 Bytes
94bebf8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { Upload, FileText, AlertCircle } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from './ui/Card';
import { Button } from './ui/Button';

export default function NotebookParser() {
  const [file, setFile] = useState(null);
  const [parsing, setParsing] = useState(false);
  const [results, setResults] = useState([]);
  const [error, setError] = useState(null);

  const onDrop = (acceptedFiles) => {
    const notebookFile = acceptedFiles.find(f => f.name.endsWith('.ipynb'));
    if (notebookFile) {
      setFile(notebookFile);
      setError(null);
    } else {
      setError('Please upload a valid .ipynb file');
    }
  };

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: { 'application/json': ['.ipynb'] },
    maxFiles: 1,
  });

  const parseNotebook = async () => {
    if (!file) return;
    
    setParsing(true);
    const formData = new FormData();
    formData.append('file', file);

    try {
      const response = await fetch('/api/parse-notebook', {
        method: 'POST',
        body: formData,
      });
      
      if (!response.ok) throw new Error('Parse failed');
      
      const data = await response.json();
      setResults(data.parameters || []);
    } catch (err) {
      setError(err.message);
    } finally {
      setParsing(false);
    }
  };

  return (
    <div className="space-y-6">
      <h2 className="text-3xl font-bold text-gray-800">Notebook Parser</h2>
      
      <Card>
        <CardHeader>
          <CardTitle>Upload Jupyter Notebook</CardTitle>
        </CardHeader>
        <CardContent>
          <div
            {...getRootProps()}
            className={`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${
              isDragActive ? 'border-primary-500 bg-primary-50' : 'border-gray-300'
            }`}
          >
            <input {...getInputProps()} />
            <Upload className="w-12 h-12 mx-auto mb-4 text-gray-400" />
            <p className="text-lg">Drag & drop your .ipynb file here</p>
            <p className="text-sm text-gray-500 mt-2">or click to browse</p>
          </div>

          {file && (
            <div className="mt-4 flex items-center">
              <FileText className="w-5 h-5 mr-2 text-primary-500" />
              <span>{file.name}</span>
            </div>
          )}

          {error && (
            <div className="mt-4 flex items-center text-red-500">
              <AlertCircle className="w-5 h-5 mr-2" />
              <span>{error}</span>
            </div>
          )}

          <Button
            onClick={parseNotebook}
            disabled={!file || parsing}
            className="mt-6 w-full"
          >
            {parsing ? 'Parsing...' : 'Parse Notebook'}
          </Button>
        </CardContent>
      </Card>

      {results.length > 0 && (
        <Card>
          <CardHeader>
            <CardTitle>Extracted Parameters</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="overflow-x-auto">
              <table className="w-full">
                <thead>
                  <tr className="border-b">
                    <th className="text-left py-2">Parameter</th>
                    <th className="text-left py-2">Value</th>
                    <th className="text-left py-2">Confidence</th>
                    <th className="text-left py-2">Source</th>
                  </tr>
                </thead>
                <tbody>
                  {results.map((param, idx) => (
                    <tr key={idx} className="border-b">
                      <td className="py-2 font-mono">{param.param}</td>
                      <td className="py-2">{JSON.stringify(param.value)}</td>
                      <td className="py-2">
                        <div className="progress-container">
                          <div
                            className="progress-bar"
                            style={{ width: `${param.confidence * 100}%` }}
                          />
                        </div>
                        <span className="text-sm">{(param.confidence * 100).toFixed(1)}%</span>
                      </td>
                      <td className="py-2 text-sm text-gray-600">{param.source}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}