This commit is contained in:
ChK
2026-04-04 18:31:31 +02:00
parent 1456f73682
commit bca05ba77c
6 changed files with 255 additions and 84 deletions

122
public/app.js Executable file → Normal file
View File

@@ -1,50 +1,72 @@
document.addEventListener('DOMContentLoaded', function() {
function updateStatus() {
fetch('/api/status')
.then(response => response.json())
.then(data => {
// WebClients
const clientsUl = document.getElementById('clients');
clientsUl.innerHTML = '';
data.clients.forEach(client => {
const li = document.createElement('li');
li.textContent = client;
clientsUl.appendChild(li);
});
// Sender
const sendersUl = document.getElementById('senderList');
sendersUl.innerHTML = '';
data.senders.forEach(sender => {
const li = document.createElement('li');
li.textContent = `${sender.name}: ${sender.status}`;
sendersUl.appendChild(li);
});
// Letzte Commands
const commandsUl = document.getElementById('commandList');
commandsUl.innerHTML = '';
data.lastCommands.forEach(cmd => {
const li = document.createElement('li');
li.textContent = cmd;
commandsUl.appendChild(li);
});
// Letzte Pings
const pingsUl = document.getElementById('pingList');
pingsUl.innerHTML = '';
data.lastPings.forEach(ping => {
const li = document.createElement('li');
li.textContent = ping;
pingsUl.appendChild(li);
});
})
.catch(error => console.error('Error fetching status:', error));
}
// Initial load
updateStatus();
// Update every 5 seconds
setInterval(updateStatus, 5000);
});
document.addEventListener('DOMContentLoaded', function() {
function updateStatus() {
fetch('/api/status')
.then(response => response.json())
.then(data => {
// WebClients
const clientsUl = document.getElementById('clients');
clientsUl.innerHTML = '';
data.clients.forEach(client => {
const li = document.createElement('li');
li.textContent = client;
clientsUl.appendChild(li);
});
// Sender
const sendersUl = document.getElementById('senderList');
sendersUl.innerHTML = '';
data.senders.forEach(sender => {
const li = document.createElement('li');
li.textContent = `${sender.name}: ${sender.status}`;
li.classList.add(sender.status.toLowerCase());
sendersUl.appendChild(li);
});
// Letzte Commands
const commandsUl = document.getElementById('commandList');
commandsUl.innerHTML = '';
data.lastCommands.forEach(cmd => {
const li = document.createElement('li');
li.textContent = cmd;
commandsUl.appendChild(li);
});
// Letzte Pings
const pingsUl = document.getElementById('pingList');
pingsUl.innerHTML = '';
data.lastPings.forEach(ping => {
const li = document.createElement('li');
li.textContent = ping;
pingsUl.appendChild(li);
});
})
.catch(error => console.error('Error fetching status:', error));
}
// Initial load
updateStatus();
// Update every 5 seconds
setInterval(updateStatus, 5000);
});
document.querySelectorAll('.section').forEach(sec => {
const id = sec.dataset.id;
const saved = localStorage.getItem('section_' + id);
if (saved === 'collapsed') sec.classList.add('collapsed');
sec.querySelector('h2').addEventListener('click', () => {
sec.classList.toggle('collapsed');
localStorage.setItem(
'section_' + id,
sec.classList.contains('collapsed') ? 'collapsed' : 'open'
);
});
});
/* Initial-Zustand
['clients','pings'].forEach(id => {
if (!localStorage.getItem('section_' + id))
localStorage.setItem('section_' + id, 'collapsed');
});
*/

69
public/index.html Executable file → Normal file
View File

@@ -1,35 +1,36 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Robot Driver Info</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #333; }
.section { margin-bottom: 20px; border: 1px solid #ccc; padding: 10px; }
ul { list-style-type: none; padding: 0; }
li { padding: 5px 0; }
</style>
</head>
<body>
<h1>Robot Driver Status</h1>
<div id="status" class="section">
<h2>Verbundene WebClients</h2>
<ul id="clients"></ul>
</div>
<div id="senders" class="section">
<h2>Verbundene FluidNC-Controller</h2>
<ul id="senderList"></ul>
</div>
<div id="commands" class="section">
<h2>Letzte Commands</h2>
<ul id="commandList"></ul>
</div>
<div id="pings" class="section">
<h2>Letzte Ping Nachrichten</h2>
<ul id="pingList"></ul>
</div>
<script src="app.js"></script>
</body>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Robot Driver Info</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Robot Driver Status</h1>
<div class="sections">
<div id="status" class="section" data-id="clients">
<h2>Verbundene WebClients</h2>
<ul id="clients"></ul>
</div>
<div id="senders" class="section" data-id="senders">
<h2>Verbundene FluidNC-Controller</h2>
<ul id="senderList"></ul>
</div>
<div id="commands" class="section" data-id="commands">
<h2>Letzte Commands</h2>
<ul id="commandList"></ul>
</div>
<div id="pings" class="section" data-id="pings">
<h2>Letzte Ping Nachrichten</h2>
<ul id="pingList"></ul>
</div>
</div>
<script src="app.js"></script>
</body>
</html>

109
public/style.css Normal file
View File

@@ -0,0 +1,109 @@
:root {
--bg: #0b1c2d;
--panel: #132c44;
--border: #1e3b58;
--text: #e0e6ed;
--accent: #6fb3ff;
}
* {
box-sizing: border-box;
}
html, body {
min-height: 100%;
}
body {
font-family: Arial, sans-serif;
margin: 16px;
background: linear-gradient(
to bottom,
#ffffff -20%,
var(--bg) 110%
);
color: var(--text);
font-size: 14px;
}
h1 {
margin-bottom: 16px;
font-size: 20px;
color: var(--accent);
}
/* Grid: mind. 500px pro Spalte, beliebig viele */
.sections {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
gap: 10px;
}
/* Section Card */
.section {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 22px 20px;
}
/* Header = Klickfläche */
.section h2 {
margin: 0;
font-size: 15px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
color: var(--accent);
}
/* Pfeil */
.section h2::after {
content: "▼";
font-size: 12px;
transition: transform 0.2s ease;
}
.section.collapsed h2::after {
transform: rotate(-90deg);
}
/* Inhalt */
.section ul {
margin: 10px 0 0;
padding: 0;
list-style: none;
}
.section.collapsed ul {
display: none;
}
.section li {
padding: 4px 0;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
/* FluidNC Status Icons */
.section#senders li {
position: relative;
padding-left: 22px;
}
.section#senders li::before {
position: absolute;
left: 0;
top: 2px;
font-size: 14px;
}
/* ✅ CONNECTED */
.section#senders li.connected::before {
content: "🟢";
}
/* ❌ DISCONNECTED */
.section#senders li.disconnected::before {
content: "⛔";
}