forked from LangGraph-GUI/LangGraph-GUI-reactflow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRunWindow.js
150 lines (129 loc) · 5.42 KB
/
RunWindow.js
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
147
148
149
150
import React, { useState, useEffect, useRef } from 'react';
import SERVER_URL from '../config';
import { useGraphManager } from './GraphManager';
import { convertFlowToJson } from './JsonUtils';
import ConfigManager from '../ConfigManager';
function RunWindow({ onClose }) {
const [responseMessage, setResponseMessage] = useState('');
const [isRunning, setIsRunning] = useState(false);
const { username, llmModel, apiKey } = ConfigManager.getSettings();
const { nodes, nodeIdCounter } = useGraphManager();
const isPollingRef = useRef(false)
const saveGraphData = async () => {
try {
const flowData = convertFlowToJson(nodes, nodeIdCounter);
const response = await fetch(`${SERVER_URL}/save-graph/${encodeURIComponent(username)}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(flowData),
});
if (!response.ok) {
throw new Error('Failed to save graph data on the server.');
}
console.log('Graph data successfully saved to server.\n');
setResponseMessage(prev => prev + '\nGraph data successfully saved to server.\n');
} catch (error) {
console.error('Error saving graph data:', error);
setResponseMessage(prev => prev + '\nError saving graph data: ' + error.message);
throw error;
}
};
const handleRun = async () => {
if (isRunning) return;
setIsRunning(true)
setResponseMessage('');
try {
await saveGraphData();
console.log("Attempting to send request to Flask server...");
const response = await fetch(`${SERVER_URL}/run/${encodeURIComponent(username)}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: username,
llm_model: llmModel,
api_key: apiKey,
}),
});
if (!response.body) {
throw new Error('ReadableStream not yet supported in this browser.');
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let done = false;
while (!done) {
const { value, done: streamDone } = await reader.read();
done = streamDone;
if (value) {
const chunk = decoder.decode(value, { stream: !done });
console.log("Received chunk:", chunk);
try{
const parsed = JSON.parse(chunk.replace("data: ", "").trim());
if (parsed.status){
setIsRunning(false)
}
}catch(e){
}
setResponseMessage(prev => prev + chunk);
}
}
} catch (error) {
console.error('Error:', error);
setResponseMessage(prev => prev + '\nError: ' + error.message);
alert('Error: ' + error.message);
setIsRunning(false);
} finally {
if(isPollingRef.current){
setIsRunning(false);
}
}
};
useEffect(() => {
isPollingRef.current = true;
const checkStatus = async () => {
try {
const response = await fetch(`${SERVER_URL}/status/${encodeURIComponent(username)}`, {
method: 'GET',
});
const status = await response.json();
setIsRunning(status.running);
} catch (error) {
console.error('Error checking status:', error);
}
};
const interval = setInterval(checkStatus, 2000);
return () => {
isPollingRef.current = false;
clearInterval(interval);
};
}, []);
const handleLeave = async () => {
onClose();
};
return (
<div className="fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 flex justify-center items-center z-1000">
<div className="bg-white p-5 rounded shadow-md w-4/5 h-4/5 flex flex-col">
<h2 className="text-lg font-bold mb-4">Run Script</h2>
<div className="flex mb-4">
<button
className={`bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mr-2 ${isRunning ? 'bg-gray-400 hover:bg-gray-400 cursor-not-allowed' : ''}`}
onClick={handleRun}
disabled={isRunning}
>
Run
</button>
<button
className={`bg-orange-500 hover:bg-orange-700 text-white font-bold py-2 px-4 rounded mr-2 ${isRunning ? 'bg-gray-400 hover:bg-gray-400 cursor-not-allowed' : ''}`}
onClick={handleLeave}
disabled={isRunning}
>
Leave
</button>
</div>
<div className="flex-1 overflow-y-auto bg-gray-100 p-2 rounded mt-4">
<pre className="text-left">{responseMessage}</pre>
</div>
</div>
</div>
);
}
export default RunWindow;