feat(ui): per-Screen-Override in Übersichtskarte und Detailseite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c263d97cca
commit
fc94f56162
2 changed files with 92 additions and 0 deletions
|
|
@ -982,6 +982,27 @@ const manageTmpl = `<!DOCTYPE html>
|
|||
</div>
|
||||
<p id="schedule-save-ok" class="save-ok mt-2" style="font-size:.8rem">✓ Gespeichert</p>
|
||||
</div>
|
||||
<!-- Per-Screen Override (Einschalten bis) -->
|
||||
<div class="box mb-3">
|
||||
<h3 class="title is-6 mb-2">Einschalten bis (Override)</h3>
|
||||
{{if not_expired .Schedule.OverrideOnUntil}}
|
||||
<p style="font-size:.875rem;color:#059669;margin-bottom:.5rem">
|
||||
⏰ Aktiv bis {{.Schedule.OverrideOnUntil.Format "02.01.2006 15:04"}}
|
||||
</p>
|
||||
<button class="button is-small is-light" type="button"
|
||||
onclick="clearScreenOverridePage()">Override aufheben</button>
|
||||
{{else}}
|
||||
<p style="font-size:.8rem;color:#6b7280;margin-bottom:.5rem">
|
||||
Überschreibt Zeitplan und Wochenend-Sperre — Monitor bleibt bis zum angegebenen Zeitpunkt eingeschaltet.
|
||||
</p>
|
||||
<div style="display:flex;gap:.5rem;align-items:center;flex-wrap:wrap">
|
||||
<input type="datetime-local" id="screen-override-until" class="input is-small" style="width:16rem">
|
||||
<button class="button is-small is-success" type="button"
|
||||
onclick="setScreenOverridePage()">Setzen</button>
|
||||
</div>
|
||||
{{end}}
|
||||
<p id="screen-override-ok" class="save-ok mt-2" style="font-size:.8rem">✓ Gespeichert</p>
|
||||
</div>
|
||||
<!-- Upload (collapsed) -->
|
||||
<div class="box mb-3">
|
||||
<details id="upload-details">
|
||||
|
|
@ -1189,6 +1210,33 @@ function saveSchedule() {
|
|||
}).catch(function() { showToast('Netzwerkfehler', 'is-danger'); });
|
||||
}
|
||||
|
||||
function setScreenOverridePage() {
|
||||
var val = document.getElementById('screen-override-until').value;
|
||||
if (!val) { showToast('Bitte Datum und Uhrzeit angeben', 'is-warning'); return; }
|
||||
var dt = new Date(val);
|
||||
fetch('/api/v1/screens/' + SCREEN_SLUG + '/override', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-CSRF-Token': getCsrf(), 'X-Requested-With': 'fetch'},
|
||||
body: JSON.stringify({on_until: dt.toISOString()})
|
||||
}).then(function(r) {
|
||||
if (r.ok) {
|
||||
var ok = document.getElementById('screen-override-ok');
|
||||
if (ok) { ok.classList.add('show'); setTimeout(function() { ok.classList.remove('show'); }, 2000); }
|
||||
} else { showToast('Fehler beim Setzen des Overrides', 'is-danger'); }
|
||||
}).catch(function() { showToast('Netzwerkfehler', 'is-danger'); });
|
||||
}
|
||||
|
||||
function clearScreenOverridePage() {
|
||||
fetch('/api/v1/screens/' + SCREEN_SLUG + '/override', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-CSRF-Token': getCsrf(), 'X-Requested-With': 'fetch'},
|
||||
body: JSON.stringify({on_until: null})
|
||||
}).then(function(r) {
|
||||
if (r.ok) { location.reload(); }
|
||||
else { showToast('Fehler beim Aufheben des Overrides', 'is-danger'); }
|
||||
}).catch(function() { showToast('Netzwerkfehler', 'is-danger'); });
|
||||
}
|
||||
|
||||
// ─── ?msg= toast ─────────────────────────────────────────────────
|
||||
(function() {
|
||||
var msg = new URLSearchParams(window.location.search).get('msg');
|
||||
|
|
@ -1447,6 +1495,24 @@ const screenOverviewTmpl = `<!DOCTYPE html>
|
|||
<button class="button is-small is-danger is-light" type="button"
|
||||
onclick="sendDisplayCmd('{{.Screen.Slug}}','off')">Aus</button>
|
||||
</div>
|
||||
<!-- Per-Screen Override -->
|
||||
<div style="margin-top:.5rem;font-size:.8rem">
|
||||
{{if .OverrideOnUntil}}
|
||||
<span style="color:#059669">⏰ Ein bis {{.OverrideOnUntil.Format "02.01. 15:04"}}</span>
|
||||
<button class="button is-small is-light" style="padding:0 .4rem;height:1.4rem" type="button"
|
||||
onclick="clearScreenOverride('{{.Screen.Slug}}')">✕</button>
|
||||
{{else}}
|
||||
<details style="display:inline">
|
||||
<summary style="cursor:pointer;color:#6b7280">Einschalten bis…</summary>
|
||||
<div style="display:flex;gap:.3rem;align-items:center;margin-top:.3rem;flex-wrap:wrap">
|
||||
<input type="datetime-local" id="override-until-{{.Screen.Slug}}"
|
||||
class="input is-small" style="width:13rem;font-size:.75rem">
|
||||
<button class="button is-small is-success is-light" type="button"
|
||||
onclick="setScreenOverride('{{.Screen.Slug}}')">Setzen</button>
|
||||
</div>
|
||||
</details>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1575,6 +1641,29 @@ function deleteGlobalOverride() {
|
|||
if (r.ok) { location.reload(); }
|
||||
}).catch(function(){});
|
||||
}
|
||||
|
||||
function setScreenOverride(slug) {
|
||||
var val = document.getElementById('override-until-' + slug).value;
|
||||
if (!val) return;
|
||||
var dt = new Date(val);
|
||||
fetch('/api/v1/screens/' + slug + '/override', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-CSRF-Token': getCsrf(), 'X-Requested-With': 'fetch'},
|
||||
body: JSON.stringify({on_until: dt.toISOString()})
|
||||
}).then(function(r) {
|
||||
if (r.ok) { location.reload(); }
|
||||
}).catch(function(){});
|
||||
}
|
||||
|
||||
function clearScreenOverride(slug) {
|
||||
fetch('/api/v1/screens/' + slug + '/override', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json', 'X-CSRF-Token': getCsrf(), 'X-Requested-With': 'fetch'},
|
||||
body: JSON.stringify({on_until: null})
|
||||
}).then(function(r) {
|
||||
if (r.ok) { location.reload(); }
|
||||
}).catch(function(){});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
|
|
|
|||
|
|
@ -137,6 +137,9 @@ var tmplFuncs = template.FuncMap{
|
|||
}
|
||||
return t.Format("02.01.2006 15:04")
|
||||
},
|
||||
"not_expired": func(t *time.Time) bool {
|
||||
return t != nil && time.Now().Before(*t)
|
||||
},
|
||||
}
|
||||
|
||||
// HandleAdminUI renders the admin overview page (screens + users tabs).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue