Checklisten-Häkchen in Dashboards speichern (localStorage)
Beim Ausliefern von /dashboards/*.html wird ein Skript injiziert, das den Zustand der Checklisten-Checkboxen im localStorage speichert (Key = Label-Text, pro Dashboard-URL) und beim Laden wiederherstellt, inkl. update()-Aufruf für Zähler/Progress-Bar und 'Liste zurücksetzen'-Button. Funktioniert in allen bestehenden und künftigen Dashboards; Marker verhindert Doppel-Injektion, path.basename verhindert Traversal.
This commit is contained in:
1 parent
ab4f8e8570
commit
12f01b86d6
1 file changed
+70
@@ -1,6 +1,7 @@
|
||||
const path = require('path');
|
||||
const http = require('http');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const express = require('express');
|
||||
const webpush = require('web-push');
|
||||
|
||||
@@ -416,6 +417,75 @@ function sendPush(session, result) {
|
||||
// Statische Dateien & Dashboard-Dateien
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Wird in jedes ausgelieferte Dashboard-HTML injiziert: speichert den Zustand
|
||||
// der Checklisten-Häkchen im localStorage und stellt ihn beim Laden wieder her
|
||||
// (inkl. „Liste zurücksetzen"-Button). Key = Label-Text der Checkbox, damit
|
||||
// der Stand auch bei Layout-Änderungen stabil bleibt.
|
||||
const CHECKLIST_SCRIPT = `<script>
|
||||
(function () {
|
||||
var KEY = 'rc-checks:' + location.pathname;
|
||||
var boxes = document.querySelectorAll('input[type=checkbox]');
|
||||
if (!boxes.length) return;
|
||||
var saved = {};
|
||||
try { saved = JSON.parse(localStorage.getItem(KEY) || '{}'); } catch (e) {}
|
||||
|
||||
function labelFor(box, i) {
|
||||
var li = box.closest('li');
|
||||
var t = li ? li.querySelector('.check-text') : null;
|
||||
var text = (t || li || {}).textContent || '';
|
||||
return text.trim() || 'item-' + i;
|
||||
}
|
||||
|
||||
boxes.forEach(function (box, i) {
|
||||
var k = labelFor(box, i);
|
||||
if (saved[k] !== undefined) box.checked = !!saved[k];
|
||||
box.addEventListener('change', function () {
|
||||
saved[k] = box.checked;
|
||||
try { localStorage.setItem(KEY, JSON.stringify(saved)); } catch (e) {}
|
||||
});
|
||||
});
|
||||
|
||||
function refresh() {
|
||||
if (typeof update === 'function') update();
|
||||
}
|
||||
|
||||
// „Liste zurücksetzen"-Button am Anfang der ersten Checklisten-Section
|
||||
var firstBox = boxes[0];
|
||||
var section = firstBox.closest('section') || firstBox.closest('div') || document.body;
|
||||
var btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.textContent = '↺ Liste zurücksetzen';
|
||||
btn.style.cssText =
|
||||
'margin:0 0 12px;padding:6px 14px;font-size:12px;font-weight:600;border-radius:8px;' +
|
||||
'border:1px solid rgba(100,116,139,.4);background:transparent;color:inherit;cursor:pointer;';
|
||||
btn.addEventListener('click', function () {
|
||||
if (!confirm('Alle Häkchen dieser Liste zurücksetzen?')) return;
|
||||
try { localStorage.removeItem(KEY); } catch (e) {}
|
||||
saved = {};
|
||||
boxes.forEach(function (b) { b.checked = false; });
|
||||
refresh();
|
||||
});
|
||||
section.insertBefore(btn, section.firstChild);
|
||||
|
||||
refresh();
|
||||
})();
|
||||
</script>`;
|
||||
|
||||
const CHECKLIST_MARKER = 'rc-checks';
|
||||
|
||||
app.get('/dashboards/:name.html', (req, res, next) => {
|
||||
const name = path.basename(req.params.name);
|
||||
const file = path.join(__dirname, 'dashboards', `${name}.html`);
|
||||
fs.readFile(file, 'utf8', (err, html) => {
|
||||
if (err) return next();
|
||||
if (!html.includes(CHECKLIST_MARKER)) {
|
||||
html = html.replace(/<\/body>/i, `${CHECKLIST_SCRIPT}\n</body>`);
|
||||
}
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.type('html').send(html);
|
||||
});
|
||||
});
|
||||
|
||||
app.use(
|
||||
'/dashboards',
|
||||
express.static(path.join(__dirname, 'dashboards'), {
|
||||
|
||||
Reference in new issue
Block a user