Skip to content

Commit 81fbd44

Browse files
feat: Add prominent LXC creation completion message (#73)
* feat: Add prominent LXC creation completion message - Enhanced Terminal component to detect LXC creation scripts - Display prominent block message when LXC creation finishes successfully - Detection based on script path (ct/), container ID, and script name patterns - Maintains backward compatibility for non-LXC scripts - Shows 'LXC CREATION FINISHED' block instead of standard completion message * Delete scripts/ct/debian.sh * Delete scripts/install/debian-install.sh * Fix linting errors in Terminal.tsx - Add handleMessage to useEffect dependency array - Move handleMessage function before useEffect and wrap with useCallback - Replace logical OR with proper null check for containerId - Fix React hooks exhaustive-deps warning - Fix TypeScript prefer-nullish-coalescing error * Remove duplicate handleMessage function - Clean up merge conflict resolution that left duplicate function - Keep only the properly memoized useCallback version - Fix code duplication issue
1 parent 6a84da5 commit 81fbd44

File tree

1 file changed

+56
-40
lines changed

1 file changed

+56
-40
lines changed

src/app/_components/Terminal.tsx

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { useEffect, useRef, useState } from 'react';
3+
import { useCallback, useEffect, useRef, useState } from 'react';
44
import '@xterm/xterm/css/xterm.css';
55
import { Button } from './ui/button';
66
import { Play, Square, Trash2, X } from 'lucide-react';
@@ -34,6 +34,60 @@ export function Terminal({ scriptPath, onClose, mode = 'local', server, isUpdate
3434

3535
const scriptName = scriptPath.split('/').pop() ?? scriptPath.split('\\').pop() ?? 'Unknown Script';
3636

37+
const handleMessage = useCallback((message: TerminalMessage) => {
38+
if (!xtermRef.current) return;
39+
40+
const timestamp = new Date(message.timestamp).toLocaleTimeString();
41+
const prefix = `[${timestamp}] `;
42+
43+
switch (message.type) {
44+
case 'start':
45+
xtermRef.current.writeln(`${prefix}[START] ${message.data}`);
46+
setIsRunning(true);
47+
break;
48+
case 'output':
49+
// Write directly to terminal - xterm.js handles ANSI codes natively
50+
xtermRef.current.write(message.data);
51+
break;
52+
case 'error':
53+
// Check if this looks like ANSI terminal output (contains escape codes)
54+
if (message.data.includes('\x1B[') || message.data.includes('\u001b[')) {
55+
// This is likely terminal output sent to stderr, treat it as normal output
56+
xtermRef.current.write(message.data);
57+
} else if (message.data.includes('TERM environment variable not set')) {
58+
// This is a common warning, treat as normal output
59+
xtermRef.current.write(message.data);
60+
} else if (message.data.includes('exit code') && message.data.includes('clear')) {
61+
// This is a script error, show it with error prefix
62+
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
63+
} else {
64+
// This is a real error, show it with error prefix
65+
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
66+
}
67+
break;
68+
case 'end':
69+
// Check if this is an LXC creation script
70+
const isLxcCreation = scriptPath.includes('ct/') ||
71+
scriptPath.includes('create_lxc') ||
72+
(containerId != null) ||
73+
scriptName.includes('lxc') ||
74+
scriptName.includes('container');
75+
76+
if (isLxcCreation && message.data.includes('SSH script execution finished with code: 0')) {
77+
// Display prominent LXC creation completion message
78+
xtermRef.current.writeln('');
79+
xtermRef.current.writeln('#########################################');
80+
xtermRef.current.writeln('########## LXC CREATION FINISHED ########');
81+
xtermRef.current.writeln('#########################################');
82+
xtermRef.current.writeln('');
83+
} else {
84+
xtermRef.current.writeln(`${prefix}${message.data}`);
85+
}
86+
setIsRunning(false);
87+
break;
88+
}
89+
}, [scriptPath, containerId, scriptName]);
90+
3791
// Ensure we're on the client side
3892
useEffect(() => {
3993
setIsClient(true);
@@ -206,45 +260,7 @@ export function Terminal({ scriptPath, onClose, mode = 'local', server, isUpdate
206260
wsRef.current.close();
207261
}
208262
};
209-
}, [scriptPath, executionId, mode, server, isUpdate, containerId]);
210-
211-
const handleMessage = (message: TerminalMessage) => {
212-
if (!xtermRef.current) return;
213-
214-
const timestamp = new Date(message.timestamp).toLocaleTimeString();
215-
const prefix = `[${timestamp}] `;
216-
217-
switch (message.type) {
218-
case 'start':
219-
xtermRef.current.writeln(`${prefix}[START] ${message.data}`);
220-
setIsRunning(true);
221-
break;
222-
case 'output':
223-
// Write directly to terminal - xterm.js handles ANSI codes natively
224-
xtermRef.current.write(message.data);
225-
break;
226-
case 'error':
227-
// Check if this looks like ANSI terminal output (contains escape codes)
228-
if (message.data.includes('\x1B[') || message.data.includes('\u001b[')) {
229-
// This is likely terminal output sent to stderr, treat it as normal output
230-
xtermRef.current.write(message.data);
231-
} else if (message.data.includes('TERM environment variable not set')) {
232-
// This is a common warning, treat as normal output
233-
xtermRef.current.write(message.data);
234-
} else if (message.data.includes('exit code') && message.data.includes('clear')) {
235-
// This is a script error, show it with error prefix
236-
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
237-
} else {
238-
// This is a real error, show it with error prefix
239-
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
240-
}
241-
break;
242-
case 'end':
243-
xtermRef.current.writeln(`${prefix}[SUCCESS] ${message.data}`);
244-
setIsRunning(false);
245-
break;
246-
}
247-
};
263+
}, [scriptPath, executionId, mode, server, isUpdate, containerId, handleMessage]);
248264

249265
const startScript = () => {
250266
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {

0 commit comments

Comments
 (0)