+
+
{% for node in nodes %}
-
-
-
-
- {{ node.ip }}
-
-
-
-
- {{ node.os }}
- {{ node.arch }}
-
-
-
-
- {{ node.status }}
-
-
+
+
+
+ {{ node.ip }}
+
+
+
+ {{ node.os }}
+ {{ node.arch }}
+
+
+
+ {{ node.status }}
+
+
+
{% endfor %}
-
+
@@ -254,7 +182,7 @@
-
Warte auf Aufgaben...
+
Warte auf Daten...
@@ -272,13 +200,13 @@
@@ -288,7 +216,7 @@
let currentSettings = {};
let termDataDisposable = null;
- // 1. CHAT LOGIK
+ // CHAT
function initChat(chatWs) {
const input = document.getElementById('user-input');
window.sendMessage = function() {
@@ -297,56 +225,20 @@
chatWs.send(msg);
appendChat("Du", msg, "text-slate-400 font-bold");
input.value = '';
- input.focus();
};
- input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); sendMessage(); } });
+ input.addEventListener('keydown', (e) => { if (e.key === 'Enter') sendMessage(); });
}
- // 2. MODAL LOGIK
window.addNode = () => document.getElementById('add-node-modal').classList.remove('hidden');
window.closeAddNode = () => document.getElementById('add-node-modal').classList.add('hidden');
- // 3. ERWEITERTER REFRESH (Aktualisiert OS & Arch)
- window.refreshNodeStatus = async function(nodeId) {
- const badge = document.getElementById(`badge-${nodeId}`);
- const led = document.getElementById(`led-${nodeId}`);
- const osEl = document.getElementById(`os-${nodeId}`);
- const archEl = document.getElementById(`arch-${nodeId}`);
- const card = document.getElementById(`node-card-${nodeId}`);
-
- badge.textContent = "PRÜFE...";
- card.style.opacity = "0.7";
-
- try {
- const response = await fetch(`/refresh_status/${nodeId}`);
- const data = await response.json();
-
- badge.textContent = data.status;
- osEl.textContent = data.os;
- archEl.textContent = data.arch;
-
- if (data.status.includes("Aktiv")) {
- led.className = "h-2 w-2 rounded-full bg-blue-500 shadow-[0_0_8px_#3b82f6]";
- } else if (data.status === "Offline") {
- led.className = "h-2 w-2 rounded-full bg-red-500 shadow-[0_0_8px_#ef4444]";
- } else {
- led.className = "h-2 w-2 rounded-full bg-yellow-500";
- }
- } catch (e) {
- badge.textContent = "FEHLER";
- led.className = "h-2 w-2 rounded-full bg-red-500";
- } finally {
- card.style.opacity = "1";
- }
- };
-
- // 4. SETTINGS & MODEL LOGIK
+ // AI SETTINGS
async function loadSettings() {
try {
const res = await fetch('/api/settings');
currentSettings = await res.json();
document.getElementById('ai-provider').value = currentSettings.provider;
- document.getElementById('ollama-url').value = currentSettings.ollama_base_url || "http://127.0.0.1:11434/v1";
+ document.getElementById('ollama-url').value = currentSettings.ollama_base_url || "";
updateModelDropdown(true);
} catch (e) {}
}
@@ -361,77 +253,63 @@
modelSelect.innerHTML = '
';
try {
- // URL Parameter nur aufbauen, wenn nötig
let queryUrl = `/api/models?provider=${provider}`;
- if (provider === "ollama") {
- queryUrl += `&url=${encodeURIComponent(ollamaUrl)}`;
- }
-
+ if (provider === "ollama" && ollamaUrl) queryUrl += `&url=${encodeURIComponent(ollamaUrl)}`;
+
const res = await fetch(queryUrl);
const data = await res.json();
modelSelect.innerHTML = '';
- if (data.models && data.models.length > 0) {
+ if (data.models) {
data.models.forEach(m => {
const opt = document.createElement('option');
opt.value = opt.textContent = m;
modelSelect.appendChild(opt);
});
-
- // Korrektur: In deiner main.py ist ein Tippfehler bei "mvidia_model" (mit m)
- // Prüfe das in deiner settings API oder korrigiere es hier:
const savedModel = currentSettings[`${provider}_model`] || (provider === 'nvidia' ? currentSettings['nvidia_model'] : null);
if (isInitialLoad && savedModel) modelSelect.value = savedModel;
}
- } catch (e) {
- modelSelect.innerHTML = '
';
- }
+ } catch (e) { modelSelect.innerHTML = '
'; }
}
async function saveSettings() {
const provider = document.getElementById('ai-provider').value;
const model = document.getElementById('ai-model').value;
const ollama_base_url = document.getElementById('ollama-url').value;
- const statusEl = document.getElementById('settings-status');
try {
await fetch('/api/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ provider, model, ollama_base_url })
});
- statusEl.textContent = "✅ Gespeichert";
- setTimeout(() => statusEl.textContent = "", 2000);
- } catch (e) { statusEl.textContent = "❌ Fehler"; }
+ document.getElementById('settings-status').textContent = "✅";
+ setTimeout(() => document.getElementById('settings-status').textContent = "", 2000);
+ } catch (e) {}
}
- // 5. INITIALISIERUNG
+ // INIT EVERYTHING
document.addEventListener('DOMContentLoaded', function() {
- var grid = GridStack.init({
- cellHeight: 80,
- margin: 10,
- float: true,
- handle: '.widget-header',
- resizable: { handles: 'all' },
- alwaysShowResizeHandle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
+ const grid = GridStack.init({
+ cellHeight: 80, margin: 10, handle: '.widget-header', resizable: { handles: 'all' }
});
const savedLayout = localStorage.getItem('pi-orch-layout-v2');
- if (savedLayout) { try { grid.load(JSON.parse(savedLayout)); } catch(e){} }
- grid.on('resizestop dragstop', () => {
- localStorage.setItem('pi-orch-layout-v2', JSON.stringify(grid.save(false)));
- });
+ if (savedLayout) try { grid.load(JSON.parse(savedLayout)); } catch(e){}
+ grid.on('resizestop dragstop', () => localStorage.setItem('pi-orch-layout-v2', JSON.stringify(grid.save(false))));
const term = new Terminal({ theme: { background: '#000' }, fontSize: 13, convertEol: true });
const fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
term.open(document.getElementById('terminal'));
-
+ setTimeout(() => fitAddon.fit(), 200);
+
const logWs = new WebSocket(`ws://${location.host}/ws/install_logs`);
logWs.onmessage = (ev) => {
const div = document.createElement('div');
div.textContent = `> ${ev.data}`;
- document.getElementById('install-log').appendChild(div);
- document.getElementById('install-log').scrollTop = document.getElementById('install-log').scrollHeight;
+ const logBox = document.getElementById('install-log');
+ logBox.appendChild(div);
+ logBox.scrollTop = logBox.scrollHeight;
};
const chatWs = new WebSocket(`ws://${location.host}/ws/chat`);