From da6f5523d73447d60e2b1b6dd43d403b59778f23 Mon Sep 17 00:00:00 2001 From: chk <79915315+ChKendel@users.noreply.github.com> Date: Fri, 12 Jun 2026 05:40:40 +0200 Subject: [PATCH] Robot.json auf WebPage --- public/app.js | 86 +++++++++++++++++++++++++++++++++++++++++++ public/index.html | 10 +++++ public/style.css | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) diff --git a/public/app.js b/public/app.js index 5e63a6a..2dcade8 100644 --- a/public/app.js +++ b/public/app.js @@ -86,14 +86,100 @@ document.addEventListener('DOMContentLoaded', function() { } + // ── Robot.json + History ───────────────────────────────────────────────── + + let robotJsonActive = 'current'; + + function renderJsonTree(data, container) { + container.innerHTML = ''; + const tree = document.createElement('div'); + tree.className = 'json-tree'; + for (const [key, value] of Object.entries(data)) { + if (value !== null && typeof value === 'object' && !Array.isArray(value)) { + const details = document.createElement('details'); + const summary = document.createElement('summary'); + summary.textContent = key; + details.appendChild(summary); + const pre = document.createElement('pre'); + pre.textContent = JSON.stringify(value, null, 2); + details.appendChild(pre); + tree.appendChild(details); + } else { + const row = document.createElement('div'); + row.className = 'json-scalar'; + row.innerHTML = + `${key}` + + `${JSON.stringify(value)}`; + tree.appendChild(row); + } + } + container.appendChild(tree); + } + + function updateRobotJson() { + const url = robotJsonActive === 'current' + ? '/api/robot' + : `/api/robot/history/${robotJsonActive}`; + fetch(url) + .then(res => res.ok ? res.json() : Promise.reject(res.status)) + .then(data => { + document.getElementById('robotJsonLabel').textContent = + robotJsonActive === 'current' ? '(aktuell)' : `(${robotJsonActive})`; + renderJsonTree(data, document.getElementById('robotJsonTree')); + }) + .catch(err => { + document.getElementById('robotJsonTree').textContent = `Fehler: ${err}`; + }); + } + + function setHistoryActive(ts) { + robotJsonActive = ts; + updateRobotJson(); + document.querySelectorAll('#robotHistoryList li').forEach(l => { + l.classList.toggle('rh-active', l.dataset.ts === ts); + }); + } + + function updateRobotHistory() { + fetch('/api/robot/history') + .then(res => res.json()) + .then(({ history }) => { + const ul = document.getElementById('robotHistoryList'); + ul.innerHTML = ''; + + const liCurrent = document.createElement('li'); + liCurrent.textContent = 'robot.json (aktuell)'; + liCurrent.dataset.ts = 'current'; + if (robotJsonActive === 'current') liCurrent.classList.add('rh-active'); + liCurrent.addEventListener('click', () => setHistoryActive('current')); + ul.appendChild(liCurrent); + + history.forEach(entry => { + const ts = entry.filename.slice(6, -5); // robot_YYYYMMDD_HHmmss.json → YYYYMMDD_HHmmss + const li = document.createElement('li'); + li.textContent = entry.filename; + li.dataset.ts = ts; + if (robotJsonActive === ts) li.classList.add('rh-active'); + li.addEventListener('click', () => setHistoryActive(ts)); + ul.appendChild(li); + }); + }) + .catch(err => console.error('Error fetching robot history:', err)); + } + updateStatus(); updatePosition(); + updateRobotJson(); + updateRobotHistory(); setInterval(() => { updateStatus(); updatePosition(); + if (robotJsonActive === 'current') updateRobotJson(); }, 1000); + setInterval(updateRobotHistory, 30000); + }); document.querySelectorAll('.section').forEach(sec => { diff --git a/public/index.html b/public/index.html index 5f0d0cb..6f7e044 100644 --- a/public/index.html +++ b/public/index.html @@ -66,6 +66,16 @@

Ping Messages

+ +
+

Robot.json

+
+
+ +
+

Robot.json History

+ +
diff --git a/public/style.css b/public/style.css index 4547fb3..248852c 100644 --- a/public/style.css +++ b/public/style.css @@ -163,4 +163,97 @@ h1 { .state-grid span:first-child { color: var(--accent); font-weight: bold; +} + +/* ── Robot.json Tree ─────────────────────────────────────────────────────── */ + +#robotJsonLabel { + font-size: 11px; + font-weight: normal; + opacity: 0.6; + margin-left: 6px; +} + +.section.collapsed #robotJsonTree { + display: none; +} + +.json-tree { + margin-top: 10px; +} + +.json-tree details { + border-bottom: 1px solid rgba(255,255,255,0.05); +} + +.json-tree details > summary { + cursor: pointer; + color: var(--accent); + font-weight: bold; + padding: 5px 0; + list-style: none; + display: flex; + align-items: center; + gap: 6px; +} + +.json-tree details > summary::before { + content: "▶"; + font-size: 10px; + display: inline-block; + transition: transform 0.15s ease; +} + +.json-tree details[open] > summary::before { + transform: rotate(90deg); +} + +.json-tree details > pre { + margin: 2px 0 6px 16px; + font-size: 11px; + white-space: pre-wrap; + word-break: break-all; + color: var(--text); + opacity: 0.8; + line-height: 1.5; +} + +.json-tree .json-scalar { + display: flex; + justify-content: space-between; + padding: 4px 0; + border-bottom: 1px solid rgba(255,255,255,0.05); + font-size: 13px; +} + +.json-tree .json-scalar .json-key { + color: var(--accent); + font-weight: bold; +} + +.json-tree .json-scalar .json-val { + opacity: 0.85; +} + +/* ── Robot.json History ──────────────────────────────────────────────────── */ + +#robotHistoryList li { + cursor: pointer; + font-size: 13px; + font-family: monospace; + transition: color 0.1s; +} + +#robotHistoryList li:hover { + color: #7ec8e3; +} + +#robotHistoryList li.rh-active { + color: #7ec8e3; + font-weight: bold; +} + +#robotHistoryList li.rh-active::before { + content: "▶ "; + font-size: 10px; } \ No newline at end of file