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
This commit is contained in:
Michel Roegl-Brunner
2025-10-08 10:59:05 +02:00
committed by GitHub
parent 6a84da5e85
commit 81fbd440ce

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import '@xterm/xterm/css/xterm.css'; import '@xterm/xterm/css/xterm.css';
import { Button } from './ui/button'; import { Button } from './ui/button';
import { Play, Square, Trash2, X } from 'lucide-react'; import { Play, Square, Trash2, X } from 'lucide-react';
@@ -34,6 +34,60 @@ export function Terminal({ scriptPath, onClose, mode = 'local', server, isUpdate
const scriptName = scriptPath.split('/').pop() ?? scriptPath.split('\\').pop() ?? 'Unknown Script'; const scriptName = scriptPath.split('/').pop() ?? scriptPath.split('\\').pop() ?? 'Unknown Script';
const handleMessage = useCallback((message: TerminalMessage) => {
if (!xtermRef.current) return;
const timestamp = new Date(message.timestamp).toLocaleTimeString();
const prefix = `[${timestamp}] `;
switch (message.type) {
case 'start':
xtermRef.current.writeln(`${prefix}[START] ${message.data}`);
setIsRunning(true);
break;
case 'output':
// Write directly to terminal - xterm.js handles ANSI codes natively
xtermRef.current.write(message.data);
break;
case 'error':
// Check if this looks like ANSI terminal output (contains escape codes)
if (message.data.includes('\x1B[') || message.data.includes('\u001b[')) {
// This is likely terminal output sent to stderr, treat it as normal output
xtermRef.current.write(message.data);
} else if (message.data.includes('TERM environment variable not set')) {
// This is a common warning, treat as normal output
xtermRef.current.write(message.data);
} else if (message.data.includes('exit code') && message.data.includes('clear')) {
// This is a script error, show it with error prefix
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
} else {
// This is a real error, show it with error prefix
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
}
break;
case 'end':
// Check if this is an LXC creation script
const isLxcCreation = scriptPath.includes('ct/') ||
scriptPath.includes('create_lxc') ||
(containerId != null) ||
scriptName.includes('lxc') ||
scriptName.includes('container');
if (isLxcCreation && message.data.includes('SSH script execution finished with code: 0')) {
// Display prominent LXC creation completion message
xtermRef.current.writeln('');
xtermRef.current.writeln('#########################################');
xtermRef.current.writeln('########## LXC CREATION FINISHED ########');
xtermRef.current.writeln('#########################################');
xtermRef.current.writeln('');
} else {
xtermRef.current.writeln(`${prefix}${message.data}`);
}
setIsRunning(false);
break;
}
}, [scriptPath, containerId, scriptName]);
// Ensure we're on the client side // Ensure we're on the client side
useEffect(() => { useEffect(() => {
setIsClient(true); setIsClient(true);
@@ -206,45 +260,7 @@ export function Terminal({ scriptPath, onClose, mode = 'local', server, isUpdate
wsRef.current.close(); wsRef.current.close();
} }
}; };
}, [scriptPath, executionId, mode, server, isUpdate, containerId]); }, [scriptPath, executionId, mode, server, isUpdate, containerId, handleMessage]);
const handleMessage = (message: TerminalMessage) => {
if (!xtermRef.current) return;
const timestamp = new Date(message.timestamp).toLocaleTimeString();
const prefix = `[${timestamp}] `;
switch (message.type) {
case 'start':
xtermRef.current.writeln(`${prefix}[START] ${message.data}`);
setIsRunning(true);
break;
case 'output':
// Write directly to terminal - xterm.js handles ANSI codes natively
xtermRef.current.write(message.data);
break;
case 'error':
// Check if this looks like ANSI terminal output (contains escape codes)
if (message.data.includes('\x1B[') || message.data.includes('\u001b[')) {
// This is likely terminal output sent to stderr, treat it as normal output
xtermRef.current.write(message.data);
} else if (message.data.includes('TERM environment variable not set')) {
// This is a common warning, treat as normal output
xtermRef.current.write(message.data);
} else if (message.data.includes('exit code') && message.data.includes('clear')) {
// This is a script error, show it with error prefix
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
} else {
// This is a real error, show it with error prefix
xtermRef.current.writeln(`${prefix}[ERROR] ${message.data}`);
}
break;
case 'end':
xtermRef.current.writeln(`${prefix}[SUCCESS] ${message.data}`);
setIsRunning(false);
break;
}
};
const startScript = () => { const startScript = () => {
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) { if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {