hadinicknam commited on
Commit
2dc2fbc
·
1 Parent(s): 37fc5db

Option to download the output Node content

Browse files
frontend/src/OutputNode.css CHANGED
@@ -76,3 +76,38 @@
76
  border-radius: 3px;
77
  background: rgba(0,0,0,0.1);
78
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  border-radius: 3px;
77
  background: rgba(0,0,0,0.1);
78
  }
79
+ /* Add these styles to your existing OutputNode.css file */
80
+
81
+ .download-button {
82
+ background-color: #1a73e8;
83
+ color: white;
84
+ border: none;
85
+ border-radius: 4px;
86
+ padding: 6px 12px;
87
+ margin-top: 10px;
88
+ cursor: pointer;
89
+ font-size: 12px;
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ transition: background-color 0.2s;
94
+ }
95
+
96
+ .download-button:hover {
97
+ background-color: #0d5bdd;
98
+ }
99
+
100
+ .download-button:disabled {
101
+ background-color: #cccccc;
102
+ cursor: not-allowed;
103
+ }
104
+
105
+ .download-button svg {
106
+ margin-right: 5px;
107
+ }
108
+
109
+ .output-actions {
110
+ display: flex;
111
+ justify-content: flex-end;
112
+ padding: 0 15px 10px 15px;
113
+ }
frontend/src/OutputNode.js CHANGED
@@ -8,6 +8,85 @@ const OutputNode = ({ data, isConnectable }) => {
8
  // Log the props received by the component for debugging
9
  console.log(`[OutputNode: ${label}] Received data:`, data);
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  const renderContent = () => {
12
  // Use a more robust check for the existence of a result.
13
  // Checks for null, undefined. Allows 0, false, and empty strings to be displayed.
@@ -87,6 +166,15 @@ const OutputNode = ({ data, isConnectable }) => {
87
  }
88
  };
89
 
 
 
 
 
 
 
 
 
 
90
  return (
91
  <div className={`output-node ${data.status || ''}`}>
92
  <Handle
@@ -100,6 +188,18 @@ const OutputNode = ({ data, isConnectable }) => {
100
  {data.status && <span className="node-status">{data.status}</span>}
101
  </div>
102
  {renderContent()}
 
 
 
 
 
 
 
 
 
 
 
 
103
  <Handle
104
  type="source"
105
  position={Position.Right}
@@ -110,4 +210,4 @@ const OutputNode = ({ data, isConnectable }) => {
110
  );
111
  };
112
 
113
- export default OutputNode;
 
8
  // Log the props received by the component for debugging
9
  console.log(`[OutputNode: ${label}] Received data:`, data);
10
 
11
+ // Function to download the output content
12
+ const downloadOutput = () => {
13
+ if (!result) return;
14
+
15
+ let filename = `${label || 'output'}-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}`;
16
+ let blob, url, content;
17
+
18
+ switch (connectedType) {
19
+ case 'textbox':
20
+ case 'markdown':
21
+ case 'json':
22
+ // For text/JSON content
23
+ content = typeof result === 'object' ? JSON.stringify(result, null, 2) : String(result);
24
+ blob = new Blob([content], { type: 'text/plain' });
25
+ filename = `${filename}.txt`;
26
+ break;
27
+
28
+ case 'image':
29
+ // For image content - handle if it's a URL
30
+ let imageUrl = '';
31
+ if (typeof result === 'string') {
32
+ imageUrl = result;
33
+ } else if (Array.isArray(result) && typeof result[0] === 'string') {
34
+ imageUrl = result[0];
35
+ } else if (typeof result === 'object' && result !== null && result.url) {
36
+ imageUrl = result.url;
37
+ }
38
+
39
+ if (imageUrl) {
40
+ // For a URL, open in a new tab for direct download
41
+ window.open(imageUrl, '_blank');
42
+ return;
43
+ }
44
+ return; // Can't download if no URL
45
+
46
+ case 'audio':
47
+ case 'video':
48
+ case 'file':
49
+ // For file content - handle if it's a URL
50
+ let fileUrl = '';
51
+ if (typeof result === 'string') {
52
+ fileUrl = result;
53
+ } else if (Array.isArray(result) && typeof result[0] === 'string') {
54
+ fileUrl = result[0];
55
+ } else if (typeof result === 'object' && result !== null && result.url) {
56
+ fileUrl = result.url;
57
+ }
58
+
59
+ if (fileUrl) {
60
+ // For a URL, open in a new tab for direct download
61
+ window.open(fileUrl, '_blank');
62
+ return;
63
+ }
64
+ return; // Can't download if no URL
65
+
66
+ default:
67
+ // Default case - try to stringify any content
68
+ content = typeof result === 'object' ? JSON.stringify(result, null, 2) : String(result);
69
+ blob = new Blob([content], { type: 'text/plain' });
70
+ filename = `${filename}.txt`;
71
+ }
72
+
73
+ // Create download link and trigger it
74
+ if (blob) {
75
+ url = URL.createObjectURL(blob);
76
+ const a = document.createElement('a');
77
+ a.href = url;
78
+ a.download = filename;
79
+ document.body.appendChild(a);
80
+ a.click();
81
+
82
+ // Clean up
83
+ setTimeout(() => {
84
+ document.body.removeChild(a);
85
+ URL.revokeObjectURL(url);
86
+ }, 100);
87
+ }
88
+ };
89
+
90
  const renderContent = () => {
91
  // Use a more robust check for the existence of a result.
92
  // Checks for null, undefined. Allows 0, false, and empty strings to be displayed.
 
166
  }
167
  };
168
 
169
+ // Download button icon (simple SVG)
170
+ const DownloadIcon = () => (
171
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
172
+ <path d="M12 16L12 8" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
173
+ <path d="M9 13L12 16L15 13" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
174
+ <path d="M3 20H21" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
175
+ </svg>
176
+ );
177
+
178
  return (
179
  <div className={`output-node ${data.status || ''}`}>
180
  <Handle
 
188
  {data.status && <span className="node-status">{data.status}</span>}
189
  </div>
190
  {renderContent()}
191
+ {/* Only show download button when there's a result */}
192
+ {result !== null && result !== undefined && (
193
+ <div className="output-actions">
194
+ <button
195
+ className="download-button"
196
+ onClick={downloadOutput}
197
+ title="Download this output"
198
+ >
199
+ <DownloadIcon /> Download
200
+ </button>
201
+ </div>
202
+ )}
203
  <Handle
204
  type="source"
205
  position={Position.Right}
 
210
  );
211
  };
212
 
213
+ export default OutputNode;