Robot.json auf WebPage
This commit is contained in:
@@ -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 =
|
||||||
|
`<span class="json-key">${key}</span>` +
|
||||||
|
`<span class="json-val">${JSON.stringify(value)}</span>`;
|
||||||
|
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();
|
updateStatus();
|
||||||
updatePosition();
|
updatePosition();
|
||||||
|
updateRobotJson();
|
||||||
|
updateRobotHistory();
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
updateStatus();
|
updateStatus();
|
||||||
updatePosition();
|
updatePosition();
|
||||||
|
if (robotJsonActive === 'current') updateRobotJson();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
setInterval(updateRobotHistory, 30000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelectorAll('.section').forEach(sec => {
|
document.querySelectorAll('.section').forEach(sec => {
|
||||||
|
|||||||
@@ -66,6 +66,16 @@
|
|||||||
<h2>Ping Messages</h2>
|
<h2>Ping Messages</h2>
|
||||||
<ul id="pingList"></ul>
|
<ul id="pingList"></ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="robotJson" class="section" data-id="robotjson">
|
||||||
|
<h2>Robot.json <span id="robotJsonLabel"></span></h2>
|
||||||
|
<div id="robotJsonTree"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="robotHistory" class="section half" data-id="robothistory">
|
||||||
|
<h2>Robot.json History</h2>
|
||||||
|
<ul id="robotHistoryList"></ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
|
|||||||
@@ -163,4 +163,97 @@ h1 {
|
|||||||
.state-grid span:first-child {
|
.state-grid span:first-child {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
font-weight: bold;
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user