feat(ui): Display-Buttons und Sammelschalter in Screen-Übersicht
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
68fc0bf4cf
commit
bdd99d10bd
1 changed files with 72 additions and 0 deletions
|
|
@ -1304,6 +1304,12 @@ const screenOverviewTmpl = `<!DOCTYPE html>
|
||||||
.morz-toast { position:fixed; top:1rem; right:1rem; z-index:9999; max-width:380px; border-radius:24px; box-shadow:var(--shadow-md); padding:.75rem 1.25rem; display:flex; align-items:center; gap:.75rem; font-size:.9rem; transform:translateX(120%); transition:transform .25s ease; }
|
.morz-toast { position:fixed; top:1rem; right:1rem; z-index:9999; max-width:380px; border-radius:24px; box-shadow:var(--shadow-md); padding:.75rem 1.25rem; display:flex; align-items:center; gap:.75rem; font-size:.9rem; transform:translateX(120%); transition:transform .25s ease; }
|
||||||
.morz-toast.show { transform:translateX(0); }
|
.morz-toast.show { transform:translateX(0); }
|
||||||
.morz-toast.is-success { background:#f0fdf4; color:#166534; border:1px solid #bbf7d0; }
|
.morz-toast.is-success { background:#f0fdf4; color:#166534; border:1px solid #bbf7d0; }
|
||||||
|
.display-btn-row { display:flex; gap:.4rem; margin-top:.5rem; }
|
||||||
|
.bulk-bar { background:var(--surface); border-radius:var(--radius); box-shadow:var(--shadow-sm); padding:.85rem 1rem; margin-bottom:1.25rem; display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; }
|
||||||
|
.display-state-badge { font-size:.7rem; padding:.15em .55em; border-radius:99px; font-weight:700; }
|
||||||
|
.display-state-badge.on { background:#dcfce7; color:#166534; }
|
||||||
|
.display-state-badge.off { background:#fee2e2; color:#991b1b; }
|
||||||
|
.display-state-badge.unknown { background:#f3f4f6; color:#6b7280; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -1326,6 +1332,14 @@ const screenOverviewTmpl = `<!DOCTYPE html>
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="title is-4 mb-5">Meine Bildschirme</h1>
|
<h1 class="title is-4 mb-5">Meine Bildschirme</h1>
|
||||||
|
{{if gt (len .Cards) 1}}
|
||||||
|
<div class="bulk-bar">
|
||||||
|
<span style="font-size:.875rem;font-weight:600;color:#374151">Alle Displays:</span>
|
||||||
|
<button class="button is-small is-success is-light" type="button" onclick="bulkDisplay('on')">Alle einschalten</button>
|
||||||
|
<button class="button is-small is-danger is-light" type="button" onclick="bulkDisplay('off')">Alle ausschalten</button>
|
||||||
|
<span id="bulk-result" style="font-size:.8rem;color:#6b7280"></span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="columns is-multiline">
|
<div class="columns is-multiline">
|
||||||
{{range .Cards}}
|
{{range .Cards}}
|
||||||
<div class="column is-one-third-desktop is-half-tablet">
|
<div class="column is-one-third-desktop is-half-tablet">
|
||||||
|
|
@ -1341,6 +1355,15 @@ const screenOverviewTmpl = `<!DOCTYPE html>
|
||||||
</div>
|
</div>
|
||||||
<div class="screen-card-sub">{{orientationLabel .Screen.Orientation}} · {{.Screen.Slug}}</div>
|
<div class="screen-card-sub">{{orientationLabel .Screen.Orientation}} · {{.Screen.Slug}}</div>
|
||||||
<a class="button is-primary is-fullwidth" href="/manage/{{.Screen.Slug}}">Verwalten →</a>
|
<a class="button is-primary is-fullwidth" href="/manage/{{.Screen.Slug}}">Verwalten →</a>
|
||||||
|
<div class="display-btn-row">
|
||||||
|
<span id="ds-{{.Screen.Slug}}" class="display-state-badge {{.DisplayState}}">
|
||||||
|
{{if eq .DisplayState "on"}}An{{else if eq .DisplayState "off"}}Aus{{else}}?{{end}}
|
||||||
|
</span>
|
||||||
|
<button class="button is-small is-success is-light" type="button"
|
||||||
|
onclick="sendDisplayCmd('{{.Screen.Slug}}','on')">Ein</button>
|
||||||
|
<button class="button is-small is-danger is-light" type="button"
|
||||||
|
onclick="sendDisplayCmd('{{.Screen.Slug}}','off')">Aus</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1381,6 +1404,55 @@ function injectCSRF() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (document.readyState==='loading') document.addEventListener('DOMContentLoaded',injectCSRF); else injectCSRF();
|
if (document.readyState==='loading') document.addEventListener('DOMContentLoaded',injectCSRF); else injectCSRF();
|
||||||
|
|
||||||
|
// ─── Display control ─────────────────────────────────────────────
|
||||||
|
function sendDisplayCmd(slug, state) {
|
||||||
|
fetch('/api/v1/screens/' + slug + '/display', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-Token': getCsrf(),
|
||||||
|
'X-Requested-With': 'fetch'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({state: state})
|
||||||
|
}).then(function(r) {
|
||||||
|
var badge = document.getElementById('ds-' + slug);
|
||||||
|
if (r.ok && badge) {
|
||||||
|
badge.className = 'display-state-badge ' + state;
|
||||||
|
badge.textContent = state === 'on' ? 'An' : 'Aus';
|
||||||
|
}
|
||||||
|
}).catch(function(){});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bulkDisplay(state) {
|
||||||
|
var slugs = [];
|
||||||
|
document.querySelectorAll('[id^="ds-"]').forEach(function(el) {
|
||||||
|
slugs.push(el.id.replace('ds-', ''));
|
||||||
|
});
|
||||||
|
var result = document.getElementById('bulk-result');
|
||||||
|
var done = 0;
|
||||||
|
slugs.forEach(function(slug) {
|
||||||
|
fetch('/api/v1/screens/' + slug + '/display', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-Token': getCsrf(),
|
||||||
|
'X-Requested-With': 'fetch'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({state: state})
|
||||||
|
}).then(function(r) {
|
||||||
|
if (r.ok) {
|
||||||
|
var badge = document.getElementById('ds-' + slug);
|
||||||
|
if (badge) {
|
||||||
|
badge.className = 'display-state-badge ' + state;
|
||||||
|
badge.textContent = state === 'on' ? 'An' : 'Aus';
|
||||||
|
}
|
||||||
|
done++;
|
||||||
|
if (result) result.textContent = done + '/' + slugs.length + ' geschaltet';
|
||||||
|
}
|
||||||
|
}).catch(function(){});
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>`
|
</html>`
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue