Grotti 2.10.0: Orca-Senden, Slice-Ordner, ED-Strom, Hygiene.
Slice-Watch mit Ordnern/Filtern, Orca-Nachbearbeitung, Cockpit-Verlauf mit ED, Zeitzone im Browser. Tasten-Grenze und README-API angeglichen, toter Code entfernt, Requirements gepinnt.
This commit is contained in:
1 parent
efd0801cd1
commit
9e22cebb81
48 files changed
+2259
-422
No files matched your search
+72
-1
@@ -61,6 +61,12 @@
|
||||
</aside>
|
||||
</div>
|
||||
<div class="desk-tools">
|
||||
<details class="desk-fold desk-tool" data-fold="verlauf" open>
|
||||
<summary class="desk-fold-sum"><svg class="ico caret"><use href="#i-down"/></svg><span class="grow">Verlauf</span><span class="tiny" data-role="verlauf-caption"></span></summary>
|
||||
<div class="desk-fold-body desk-verlauf" data-role="verlauf">
|
||||
<p class="tiny">Lade Verlauf …</p>
|
||||
</div>
|
||||
</details>
|
||||
<details class="desk-fold desk-tool" data-fold="path">
|
||||
<summary class="desk-fold-sum"><svg class="ico caret"><use href="#i-down"/></svg><span class="grow">3D-Pfad</span><span class="tiny" data-role="path-caption"></span></summary>
|
||||
<div class="desk-fold-body">
|
||||
@@ -100,6 +106,9 @@ let deskCamFails = 0;
|
||||
let deskViewerFileId = null;
|
||||
let deskSyncGen = 0;
|
||||
let deskExcludeSelected = "";
|
||||
let deskVerlaufAt = 0;
|
||||
let deskVerlaufHtml = "";
|
||||
let deskVerlaufHost = "";
|
||||
const wallPullTried = new Set();
|
||||
const toolpathCache = new Map();
|
||||
|
||||
@@ -909,6 +918,61 @@ function patchDesk(printer) {
|
||||
|
||||
// Kamera nur über Timer aktualisieren — sonst doppelter Reload + Layout-Ruckler
|
||||
syncDeskViewer(printer).catch(() => {});
|
||||
refreshDeskVerlauf(false);
|
||||
}
|
||||
|
||||
async function refreshDeskVerlauf(force) {
|
||||
if (!deskHost || deskEl.hidden) return;
|
||||
const now = Date.now();
|
||||
if (!force && deskVerlaufHost === deskHost && now - deskVerlaufAt < 20000) return;
|
||||
const host = deskHost;
|
||||
deskVerlaufAt = now;
|
||||
deskVerlaufHost = host;
|
||||
const box = deskEl.querySelector('[data-role="verlauf"]');
|
||||
const caption = deskEl.querySelector('[data-role="verlauf-caption"]');
|
||||
if (!box) return;
|
||||
try {
|
||||
const data = await api("/laeufe/aktuell?host=" + encodeURIComponent(host));
|
||||
if (deskHost !== host) return;
|
||||
const run = data.run;
|
||||
if (!run) {
|
||||
const empty = '<p class="desk-empty"><svg class="ico"><use href="#i-activity"/></svg><span>Noch kein Verlauf</span></p>';
|
||||
if (deskVerlaufHtml !== empty) {
|
||||
deskVerlaufHtml = empty;
|
||||
box.innerHTML = empty;
|
||||
}
|
||||
if (caption) caption.textContent = "";
|
||||
return;
|
||||
}
|
||||
const active = ["in_progress", "printing", "paused"].includes(run.state);
|
||||
const energy = data.energy || {};
|
||||
const kwh = energy.kwh != null
|
||||
? (Number(energy.kwh) || 0).toLocaleString("de-DE", { maximumFractionDigits: 2 }) + " kWh"
|
||||
+ (energy.source === "ed" ? " ED" : "")
|
||||
: "";
|
||||
const bits = [
|
||||
active ? "läuft" : "letzter Druck",
|
||||
formatDateRange(run.started_at, run.ended_at),
|
||||
kwh,
|
||||
].filter(Boolean);
|
||||
if (caption) caption.textContent = bits.join(" · ");
|
||||
const head = `<div class="desk-verlauf-head">
|
||||
<span class="tiny grow">${escapeHtml(jobLabel(run.filename) || "Druck")}${run.chargen_nr ? " · " + escapeHtml(run.chargen_nr) : ""}</span>
|
||||
<a class="ghost tiny-btn" href="/protokoll/${run.id}">Bericht →</a>
|
||||
</div>`;
|
||||
const html = head + tempChartHtml(data.samples || []);
|
||||
if (deskVerlaufHtml !== html) {
|
||||
deskVerlaufHtml = html;
|
||||
box.innerHTML = html;
|
||||
}
|
||||
} catch (error) {
|
||||
if (deskHost !== host) return;
|
||||
const fail = '<p class="tiny msg">' + escapeHtml(error.message || "Verlauf nicht geladen") + "</p>";
|
||||
if (deskVerlaufHtml !== fail) {
|
||||
deskVerlaufHtml = fail;
|
||||
box.innerHTML = fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function syncDeskViewer(printer) {
|
||||
@@ -1068,10 +1132,15 @@ function openDesk(host, opts) {
|
||||
const prev = deskHost;
|
||||
deskHost = host;
|
||||
setDeskVisible(true);
|
||||
if (prev !== host) destroyDeskViewer();
|
||||
if (prev !== host) {
|
||||
destroyDeskViewer();
|
||||
deskVerlaufHtml = "";
|
||||
deskVerlaufAt = 0;
|
||||
}
|
||||
const steer = deskEl.querySelector("[data-role=steer]");
|
||||
if (!same || !steer.querySelector(".steer")) setHtml(steer, steerPanelHtml(printer));
|
||||
patchDesk(printer);
|
||||
refreshDeskVerlauf(true);
|
||||
startCameraTimer();
|
||||
if (!same) {
|
||||
const back = document.getElementById("desk-back");
|
||||
@@ -1087,6 +1156,8 @@ function openDesk(host, opts) {
|
||||
function closeDesk(opts) {
|
||||
if (!deskHost && deskEl.hidden) return;
|
||||
deskHost = "";
|
||||
deskVerlaufHtml = "";
|
||||
deskVerlaufHost = "";
|
||||
stopCameraTimer();
|
||||
destroyDeskViewer();
|
||||
setDeskVisible(false);
|
||||
|
||||
Reference in new issue
Block a user