-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathpage.tsx
More file actions
146 lines (136 loc) · 6.21 KB
/
Copy pathpage.tsx
File metadata and controls
146 lines (136 loc) · 6.21 KB
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
140
141
142
143
144
145
146
'use client';
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
import '@/styles/global.css';
import CommonLayout from '../commonLayout';
import { useSession } from '@/hooks/sessionHook';
// Dynamically import react-json-view to avoid SSR issues
const ReactJson = dynamic(() => import('react-json-view'), { ssr: false });
function App() {
const [files, setFiles] = useState([]);
const [showOverlay, setShowOverlay] = useState(false);
const [jsonContent, setJsonContent] = useState({});
const [loading, setLoading] = useState(false);
const { sessionId } = useSession();
useEffect(() => {
const fetchFiles = async () => {
try {
const response = await fetch('/api/s3list', {
headers: {
'X-Session-Id': sessionId || ''
}
});
const data = await response.json();
setFiles(data.files || []);
} catch (error) {
console.error('Error fetching files:', error);
}
};
fetchFiles();
}, []);
const handleFileClick = async (file: any) => {
try {
setLoading(true);
const response = await fetch(`/api/s3view?key=${encodeURIComponent(file.key)}`, {
headers: {
'X-Session-Id': sessionId || ''
}
});
if (!response.ok) {
throw new Error('Failed to fetch file');
}
const ndJsonData = await response.text();
const jsonData = ndJsonData
.split('\n')
.filter((line) => line.trim())
.map((line) => JSON.parse(line));
setJsonContent(jsonData);
setShowOverlay(true);
} catch (error) {
console.error('Error fetching JSON:', error);
} finally {
setLoading(false);
}
};
return (
<CommonLayout
title="Monocle Traces"
navLink={{ text: "Back to Chat", href: "/" }}
>
<div className="bg-white rounded-lg shadow-sm">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-gray-50">
<tr>
<th scope="col" className="w-[60%] px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
File Name
</th>
<th scope="col" className="w-[40%] px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Last Modified
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{files.map((file: any, index) => (
<tr
key={index}
className="hover:bg-gray-50 cursor-pointer transition-colors"
>
<td
className="px-6 py-4 text-sm font-medium text-gray-900"
onClick={() => handleFileClick(file)}
>
{file.key}
</td>
<td className="px-6 py-4 text-sm text-gray-500">
{new Date(file.lastModified).toLocaleDateString(undefined, {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
{' '}
{new Date(file.lastModified).toLocaleTimeString(undefined, {
hour: '2-digit',
minute: '2-digit'
})}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* JSON Viewer Overlay */}
{showOverlay && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-6 z-50">
<div className="bg-white rounded-lg shadow-xl w-11/12 h-5/6 max-w-7xl mx-auto overflow-hidden">
<div className="p-4 border-b border-gray-200 flex justify-between items-center">
<h2 className="text-lg font-semibold text-gray-800">NDJSON Viewer</h2>
<button
onClick={() => setShowOverlay(false)}
className="p-2 hover:bg-gray-100 rounded-full transition-colors"
>
<span className="text-xl">✕</span>
</button>
</div>
<div className="p-6 h-[calc(100%-4rem)] overflow-auto">
{loading ? (
<div className="flex items-center justify-center h-full">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
</div>
) : (
<ReactJson
src={jsonContent}
style={{ backgroundColor: 'transparent' }}
enableClipboard={false}
displayDataTypes={false}
/>
)}
</div>
</div>
</div>
)}
</CommonLayout>
);
}
export default App;