Grotti 2.5.1: Druckbericht, Statistik, Spulenakte und Protokoll-Fixes.
This commit is contained in:
1 parent
b277ca48aa
commit
efd0801cd1
30 files changed
+3393
-178
No files matched your search
@@ -9,7 +9,7 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='brand/favicon-32.png') }}">
|
||||
<link rel="icon" type="image/png" sizes="512x512" href="{{ url_for('static', filename='brand/favicon.png') }}">
|
||||
<link rel="apple-touch-icon" href="{{ url_for('static', filename='brand/apple-touch-icon.png') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='grotti.css') }}?v=41">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='grotti.css') }}?v=45">
|
||||
<script>
|
||||
(function () {
|
||||
try {
|
||||
@@ -100,7 +100,8 @@
|
||||
<a href="/kameras" class="{{ 'on' if page == 'kameras' else '' }}" title="Kameras"><svg class="ico"><use href="#i-camera"/></svg><span>Kameras</span></a>
|
||||
<a href="/aktivitaet" class="{{ 'on' if page == 'aktivitaet' else '' }} nav-desk" title="Aktivität"><svg class="ico"><use href="#i-activity"/></svg><span>Aktivität</span></a>
|
||||
<a href="/warteschlange" class="{{ 'on' if page == 'warteschlange' else '' }}" title="Warteschlange"><svg class="ico"><use href="#i-queue"/></svg><span>Warteschlange</span></a>
|
||||
<a href="/protokoll" class="{{ 'on' if page == 'protokoll' else '' }} nav-desk" title="Protokoll"><svg class="ico"><use href="#i-list"/></svg><span>Protokoll</span></a>
|
||||
<a href="/protokoll" class="{{ 'on' if page == 'protokoll' or page == 'bericht' else '' }} nav-desk" title="Protokoll"><svg class="ico"><use href="#i-list"/></svg><span>Protokoll</span></a>
|
||||
<a href="/statistik" class="{{ 'on' if page == 'statistik' else '' }} nav-desk" title="Statistik"><svg class="ico"><use href="#i-activity"/></svg><span>Statistik</span></a>
|
||||
<a href="/material" class="{{ 'on' if page == 'material' else '' }} nav-desk" title="Material"><svg class="ico"><use href="#i-spool"/></svg><span>Material</span></a>
|
||||
<a href="/projekte" class="{{ 'on' if page == 'projekte' else '' }} nav-desk" title="Projekte"><svg class="ico"><use href="#i-folder"/></svg><span>Projekte</span></a>
|
||||
</nav>
|
||||
@@ -289,6 +290,31 @@ function directItemHtml(p) {
|
||||
}
|
||||
|
||||
let queueCache = [];
|
||||
const lastLiveFilename = Object.create(null);
|
||||
|
||||
function setListHtml(el, html) {
|
||||
if (!el) return;
|
||||
if (el._html === html) return;
|
||||
el._html = html;
|
||||
el.innerHTML = html;
|
||||
}
|
||||
|
||||
function stickyLiveFilename(host, filename, state) {
|
||||
const next = filename || "";
|
||||
if (next) {
|
||||
lastLiveFilename[host] = next;
|
||||
return next;
|
||||
}
|
||||
const prev = lastLiveFilename[host] || "";
|
||||
if (prev && ["printing", "paused", "heating", "complete"].includes(String(state || "").toLowerCase())) {
|
||||
return prev;
|
||||
}
|
||||
if (!["printing", "paused", "heating"].includes(String(state || "").toLowerCase())) {
|
||||
delete lastLiveFilename[host];
|
||||
}
|
||||
return prev && ["complete"].includes(String(state || "").toLowerCase()) ? prev : "";
|
||||
}
|
||||
|
||||
async function refreshPrintQueue() {
|
||||
let jobs;
|
||||
let active = [];
|
||||
@@ -298,7 +324,10 @@ async function refreshPrintQueue() {
|
||||
queueCache = jobs || [];
|
||||
const running = queueCache.filter((job) => job.status === "running");
|
||||
const queuedHosts = new Set(running.map((job) => job.host));
|
||||
const direct = (active || []).filter((p) => !queuedHosts.has(p.host));
|
||||
const direct = (active || []).filter((p) => !queuedHosts.has(p.host)).map((p) => ({
|
||||
...p,
|
||||
filename: stickyLiveFilename(p.host, p.filename, p.state),
|
||||
}));
|
||||
const waiting = queueCache.filter((job) => job.status === "waiting");
|
||||
const errors = queueCache
|
||||
.filter((job) => job.status === "error")
|
||||
@@ -308,15 +337,21 @@ async function refreshPrintQueue() {
|
||||
const runBox = document.getElementById("run-box");
|
||||
runBox.hidden = !(running.length || direct.length);
|
||||
document.getElementById("run-count").textContent = running.length + direct.length;
|
||||
document.getElementById("run-list").innerHTML = running.map(runItemHtml).join("") + direct.map(directItemHtml).join("");
|
||||
setListHtml(
|
||||
document.getElementById("run-list"),
|
||||
running.map(runItemHtml).join("") + direct.map(directItemHtml).join(""),
|
||||
);
|
||||
|
||||
const waitList = document.getElementById("wait-list");
|
||||
document.getElementById("wait-count").textContent = waiting.length;
|
||||
document.getElementById("wait-count").className = "count" + (errors.length ? " bad" : waiting.length ? " hot" : "");
|
||||
document.getElementById("wait-empty").hidden = !!(waiting.length || errors.length);
|
||||
document.getElementById("wait-box").classList.toggle("is-empty", !(waiting.length || errors.length));
|
||||
waitList.innerHTML = errors.map((job) => waitItemHtml(job, 0, 1)).join("")
|
||||
+ waiting.map((job, i) => waitItemHtml(job, i, waiting.length)).join("");
|
||||
setListHtml(
|
||||
waitList,
|
||||
errors.map((job) => waitItemHtml(job, 0, 1)).join("")
|
||||
+ waiting.map((job, i) => waitItemHtml(job, i, waiting.length)).join(""),
|
||||
);
|
||||
|
||||
const panel = document.getElementById("live-panel");
|
||||
panel.querySelectorAll("[data-cancel-q]").forEach((btn) => {
|
||||
|
||||
Reference in new issue
Block a user