Files
PiDoBot/templates/index.html

177 lines
7.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Pi-Orchestrator AI Control Center</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.1.0/css/xterm.css" />
<script src="https://cdn.jsdelivr.net/npm/xterm@5.1.0/lib/xterm.js"></script>
<style>
/* Custom scrollbar für den Matrix-Look */
#install-log::-webkit-scrollbar { width: 5px; }
#install-log::-webkit-scrollbar-thumb { background: #22c55e; }
</style>
</head>
<body class="bg-gray-900 text-white h-screen flex flex-col overflow-hidden">
<div class="flex flex-1 overflow-hidden">
<div class="w-64 border-r border-gray-700 p-4 flex flex-col bg-gray-800">
<h2 class="text-xl font-bold mb-4 flex items-center">
<span class="mr-2">📍</span> Nodes
</h2>
<div id="node-list" class="flex-1 overflow-y-auto space-y-2">
{% for node in nodes %}
<div class="p-3 bg-gray-700 rounded-lg border border-gray-600 relative group">
<form action="/remove_node/{{ node.id }}" method="post" class="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity">
<button type="submit" class="text-red-500 hover:text-red-400 font-bold text-xs bg-gray-900 rounded-full w-5 h-5 flex items-center justify-center">×</button>
</form>
<div class="font-bold text-blue-400">{{ node.name }}</div>
<div class="text-xs text-gray-400">{{ node.ip }}</div>
<div class="text-[10px] uppercase mt-1 text-green-500 font-mono">{{ node.status }}</div>
<button onclick="openTerminal('{{ node.ip }}')" class="mt-2 text-[10px] bg-gray-600 hover:bg-gray-500 px-2 py-1 rounded w-full">Terminal öffnen</button>
</div>
{% endfor %}
</div>
<button onclick="addNode()" class="mt-4 w-full bg-blue-600 hover:bg-blue-700 p-2 rounded font-bold transition-colors">
+ Node hinzufügen
</button>
</div>
<div class="flex-1 flex flex-col bg-gray-900">
<div id="chat-window" class="flex-1 p-6 overflow-y-auto space-y-4">
<div class="bg-gray-800 p-3 rounded-lg w-fit border border-gray-700">
<span class="text-blue-400 font-bold">Bot:</span> Willkommen im Cluster-Management. Ich bin bereit für deine Befehle.
</div>
</div>
<div class="p-4 border-t border-gray-700 bg-gray-800 flex gap-2">
<input id="user-input" type="text"
class="flex-1 bg-gray-700 p-3 rounded-lg outline-none border border-gray-600 focus:border-blue-500"
placeholder="Frag die KI (z.B. 'Werfe Nginx auf Pi-1 ab')">
<button onclick="sendMessage()" class="bg-green-600 hover:bg-green-700 px-6 rounded-lg font-bold transition-colors">
Senden
</button>
</div>
</div>
</div>
<div class="h-1/3 border-t-2 border-blue-900 bg-black flex">
<div class="w-1/2 flex flex-col border-r border-gray-800">
<div class="bg-gray-800 px-3 py-1 text-[10px] font-bold text-gray-400 uppercase tracking-widest">Setup Logs</div>
<div id="install-log" class="flex-1 p-3 text-xs font-mono overflow-y-auto text-green-500">
<div>> System bereit. Warte auf Node-Aktionen...</div>
</div>
</div>
<div class="w-1/2 flex flex-col">
<div class="bg-gray-800 px-3 py-1 text-[10px] font-bold text-gray-400 uppercase tracking-widest">Active Terminal</div>
<div id="terminal" class="flex-1 p-1"></div>
</div>
</div>
<script>
// --- Xterm.js Setup ---
const term = new Terminal({
theme: { background: '#000000', foreground: '#ffffff' },
cursorBlink: true,
fontSize: 12,
fontFamily: 'Courier New'
});
term.open(document.getElementById('terminal'));
term.write('System initialisiert. Terminal bereit.\r\n');
// --- WebSocket Chat ---
const ws = new WebSocket(`ws://${location.host}/ws/chat`);
const chatWindow = document.getElementById('chat-window');
ws.onmessage = (event) => {
appendMessage('Bot', event.data, 'bg-blue-900 border-blue-700');
};
function sendMessage() {
const input = document.getElementById('user-input');
if (!input.value) return;
ws.send(input.value);
appendMessage('Du', input.value, 'bg-gray-700 border-gray-600 self-end ml-auto');
input.value = '';
}
function appendMessage(sender, text, classes) {
const msg = document.createElement('div');
msg.className = `${classes} p-3 rounded-lg w-fit max-w-[80%] border`;
msg.innerHTML = `<span class="font-bold">${sender}:</span> ${text}`;
chatWindow.appendChild(msg);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
// --- WebSocket Installation Logs ---
const logWs = new WebSocket(`ws://${location.host}/ws/install_logs`);
logWs.onmessage = (event) => {
const logDiv = document.getElementById('install-log');
const entry = document.createElement('div');
entry.className = "mb-1";
entry.innerText = `> ${event.data}`;
logDiv.appendChild(entry);
logDiv.scrollTop = logDiv.scrollHeight;
};
// --- Node Funktionen ---
async function addNode() {
const name = prompt("Name des Pi (z.B. Pi-Server-1):");
const ip = prompt("IP Adresse:");
const user = prompt("SSH Nutzername (meist 'pi' oder dein Name):", "pi");
const password = prompt("Initiales SSH Passwort (wird nur einmalig für Key-Copy benötigt):");
if (name && ip && user && password) {
const formData = new FormData();
formData.append('name', name);
formData.append('ip', ip);
formData.append('user', user);
formData.append('password', password);
await fetch('/add_node', {
method: 'POST',
body: formData
});
location.reload();
}
}
let activeTermWs = null;
function openTerminal(ip) {
if (activeTermWs) activeTermWs.close();
term.clear();
term.write(`\r\n>>> Verbinde mit ${ip}...\r\n`);
activeTermWs = new WebSocket(`ws://${location.host}/ws/terminal/${ip}`);
activeTermWs.onmessage = (event) => {
term.write(event.data);
};
activeTermWs.onclose = () => {
term.write('\r\n[Verbindung geschlossen]\r\n');
};
// Tastatureingaben vom Browser an den Server schicken
term.onData(data => {
if (activeTermWs && activeTermWs.readyState === WebSocket.OPEN) {
activeTermWs.send(data);
}
});
}
// Enter-Taste zum Senden
document.getElementById('user-input').addEventListener('keypress', function (e) {
if (e.key === 'Enter') sendMessage();
});
</script>
</body>
</html>