-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.tsx
More file actions
107 lines (87 loc) · 2.5 KB
/
index.tsx
File metadata and controls
107 lines (87 loc) · 2.5 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
import { useEffect, useState, useCallback } from "react";
const STREAM_URL = "http://localhost:8000/stream";
function ErrorMessage({ error, onRetry }: { error: string; onRetry: () => void }) {
return (
<div>
<p>Error: {error}</p>
<button onClick={onRetry}>Retry</button>
</div>
);
}
function LoadingMessage() {
return <p>Loading stream data...</p>;
}
function ReceivedData({ dataChunks }: { dataChunks: { timestamp: string; log: string }[] }) {
return (
<pre>
{dataChunks.map(({ timestamp, log }, index) => (
<div key={index}>
<span>[{timestamp}]</span> {log}
</div>
))}
</pre>
);
}
export default function IndexPage() {
const [dataChunks, setDataChunks] = useState<{ timestamp: string; log: string }[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchStream = useCallback(async () => {
setIsLoading(true);
setError(null);
setDataChunks([]);
try {
const response = await fetch(STREAM_URL);
if (!response.ok) {
throw new Error(`Failed to fetch stream. Status: ${response.status}`);
}
if (!response.body) {
throw new Error("Response body is null");
}
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let isCancelled = false;
while (!isCancelled) {
const { value, done } = await reader.read();
if (done) {
break;
}
const chunk = decoder.decode(value);
setDataChunks((prev) => [
...prev,
{ timestamp: new Date().toLocaleTimeString(), log: chunk },
]);
}
setIsLoading(false);
return () => {
isCancelled = true;
reader.cancel();
};
} catch (error) {
console.error("Error fetching stream:", error);
setError(error instanceof Error ? error.message : String(error));
setIsLoading(false);
}
}, []);
useEffect(() => {
const cleanup = fetchStream();
return cleanup;
}, [fetchStream]);
return (
<div>
<h1>Server Log Viewer</h1>
{error && <ErrorMessage error={error} onRetry={fetchStream} />}
<div>
<h2>Logs:</h2>
{isLoading && dataChunks.length === 0 ? (
<LoadingMessage />
) : (
<ReceivedData dataChunks={dataChunks} />
)}
</div>
<div>
<p>Total logs received: {dataChunks.length}</p>
</div>
</div>
);
}