Replace terminal with xterm.js

parent 67392682
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<link rel="icon" href="/logos/favicon.ico" type="image/x-icon"> <link rel="icon" href="/logos/favicon.ico" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css">
<style> <style>
.navbar-brand { .navbar-brand {
font-weight: bold; font-weight: bold;
...@@ -138,6 +139,7 @@ ...@@ -138,6 +139,7 @@
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
<script> <script>
function copyToClipboard(text) { function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(function() { navigator.clipboard.writeText(text).then(function() {
......
...@@ -21,13 +21,7 @@ ...@@ -21,13 +21,7 @@
</div> </div>
</div> </div>
<div class="card-body p-0"> <div class="card-body p-0">
<div id="terminal" class="terminal-container"> <div id="terminal" class="terminal-container"></div>
<div id="output"></div>
<div class="input-group">
<span class="text-success me-2">$</span>
<input type="text" id="commandInput" class="terminal-input" placeholder="Type your command..." disabled>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -36,16 +30,12 @@ ...@@ -36,16 +30,12 @@
{% block scripts %} {% block scripts %}
<script> <script>
let ws = null; let term = null;
let connected = false; let connected = false;
let commandBuffer = '';
document.getElementById('connectBtn').addEventListener('click', connect); document.getElementById('connectBtn').addEventListener('click', connect);
document.getElementById('disconnectBtn').addEventListener('click', disconnect); document.getElementById('disconnectBtn').addEventListener('click', disconnect);
document.getElementById('commandInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendCommand();
}
});
function connect() { function connect() {
const username = document.getElementById('sshUsername').value; const username = document.getElementById('sshUsername').value;
...@@ -54,73 +44,85 @@ function connect() { ...@@ -54,73 +44,85 @@ function connect() {
return; return;
} }
// Initialize xterm
if (!term) {
term = new Terminal();
term.open(document.getElementById('terminal'));
term.write('Connecting to ' + username + '@{{ client_id }}...\r\n');
}
// For demo purposes, we'll simulate the connection // For demo purposes, we'll simulate the connection
// In a real implementation, this would use WebSocket to communicate with wsssh
connected = true; connected = true;
document.getElementById('connectBtn').disabled = true; document.getElementById('connectBtn').disabled = true;
document.getElementById('disconnectBtn').disabled = false; document.getElementById('disconnectBtn').disabled = false;
document.getElementById('commandInput').disabled = false;
document.getElementById('sshUsername').disabled = true; document.getElementById('sshUsername').disabled = true;
appendOutput(`Connecting to ${username}@{{ client_id }}...`);
setTimeout(() => { setTimeout(() => {
appendOutput(`Connected successfully!`); term.write('Connected successfully!\r\n');
appendOutput(`Welcome to {{ client_id }}`); term.write('Welcome to {{ client_id }}\r\n');
appendOutput(`$ `); term.write('$ ');
}, 1000); }, 1000);
// Handle input
term.onData(data => {
if (!connected) return;
if (data === '\r' || data === '\n') {
// Enter pressed, process command
processCommand(commandBuffer.trim());
commandBuffer = '';
} else if (data === '\x7f' || data === '\b') { // Backspace
if (commandBuffer.length > 0) {
commandBuffer = commandBuffer.slice(0, -1);
term.write('\b \b');
}
} else {
commandBuffer += data;
term.write(data);
}
});
} }
function disconnect() { function disconnect() {
connected = false; connected = false;
document.getElementById('connectBtn').disabled = false; document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true; document.getElementById('disconnectBtn').disabled = true;
document.getElementById('commandInput').disabled = true;
document.getElementById('sshUsername').disabled = false; document.getElementById('sshUsername').disabled = false;
commandBuffer = '';
appendOutput('Disconnected.'); if (term) {
term.write('\r\nDisconnected.\r\n');
}
} }
function sendCommand() { function processCommand(command) {
if (!connected) return; if (!connected || !term) return;
const input = document.getElementById('commandInput');
const command = input.value.trim();
if (!command) return;
appendOutput(`$ ${command}`); term.write('\r\n');
// Simulate command execution // Simulate command execution
setTimeout(() => { setTimeout(() => {
if (command === 'ls') { if (command === 'ls') {
appendOutput(`Desktop Documents Downloads Music Pictures Videos`); term.write('Desktop Documents Downloads Music Pictures Videos\r\n');
} else if (command === 'pwd') { } else if (command === 'pwd') {
appendOutput(`/home/${document.getElementById('sshUsername').value}`); term.write('/home/' + document.getElementById('sshUsername').value + '\r\n');
} else if (command === 'whoami') { } else if (command === 'whoami') {
appendOutput(document.getElementById('sshUsername').value); term.write(document.getElementById('sshUsername').value + '\r\n');
} else if (command === 'exit' || command === 'logout') { } else if (command === 'exit' || command === 'logout') {
disconnect(); disconnect();
return; return;
} else if (command === '') {
// Empty command
} else { } else {
appendOutput(`Command not found: ${command}`); term.write('Command not found: ' + command + '\r\n');
} }
appendOutput(`$ `); term.write('$ ');
}, 500); }, 500);
input.value = '';
}
function appendOutput(text) {
const output = document.getElementById('output');
const line = document.createElement('div');
line.textContent = text;
output.appendChild(line);
output.scrollTop = output.scrollHeight;
} }
// Focus on command input when connected // Focus on terminal when connected
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', function(e) {
if (connected && e.target.tagName !== 'INPUT') { if (connected && term) {
document.getElementById('commandInput').focus(); term.focus();
} }
}); });
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment