Merkmal-Optionen vorausgefüllt und bei aktivem Merkmal änderbar, Kiosk-Felder
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
99d02d5c29
commit
3255900f3f
7 files changed
+82
-90
No files matched your search
+26
-4
@@ -7,6 +7,10 @@
|
||||
# Passwort-Felder - "type" steuert den HTML-Input-Typ und die
|
||||
# Parsing-Logik in parse_optionen_form().
|
||||
#
|
||||
# Seit 26.10.2026 (Kiosk) gibt es auch "textarea", "url" und "number", und
|
||||
# alle Felder außer Passwörtern sind mit dem aktuellen Wert vorausgefüllt
|
||||
# (templates/_merkmal_optionen.html), auch bei aktivem Merkmal änderbar.
|
||||
#
|
||||
# Passwort-Felder werden nie mit ihrem aktuellen Wert vorausgefüllt (siehe
|
||||
# Templates) und nur übernommen, wenn tatsächlich etwas eingegeben wurde -
|
||||
# ein leer gelassenes Passwort-Feld beim Bearbeiten überschreibt also
|
||||
@@ -47,19 +51,37 @@ OPTIONEN_FELDER = {
|
||||
"veyon": [
|
||||
{"key": "veyon_lehrer", "label": "Lehrergerät (Veyon Master mit Schlüssel und Raumliste)", "type": "checkbox"},
|
||||
],
|
||||
# 26.10.2026: Kiosk (platform-docs roadmap/kiosk.md, Rolle kiosk).
|
||||
"kiosk": [
|
||||
{"key": "kiosk_startseite", "label": "Startseite", "type": "url", "placeholder": "https://…"},
|
||||
{"key": "kiosk_whitelist", "label": "Whitelist: erlaubte Domains, eine je Zeile, optional mit Pfad. Subdomains sind eingeschlossen, die Domain der Startseite ist immer erlaubt.",
|
||||
"type": "textarea", "placeholder": "opac.beispiel.de\nschule.de/vertretungsplan"},
|
||||
{"key": "kiosk_frei_surfen", "label": "Frei surfen (Whitelist aus)", "type": "checkbox"},
|
||||
{"key": "kiosk_anzeigename", "label": "Name am Anmeldebildschirm (leer = „Kiosk“)", "type": "text"},
|
||||
{"key": "kiosk_leerlauf_minuten", "label": "Nach so vielen Minuten ohne Eingabe mit der Startseite neu beginnen (leer = 10, 0 = nie)", "type": "number"},
|
||||
{"key": "kiosk_ohne_leiste", "label": "Bedienleiste (Zurück, Startseite, Abmelden) ausblenden, z. B. für Anzeigetafeln", "type": "checkbox"},
|
||||
{"key": "kiosk_bildschirm_an", "label": "Bildschirm schaltet nie ab", "type": "checkbox"},
|
||||
{"key": "kiosk_autostart", "label": "Autostart: Kiosk startet ohne Anmeldung, der Anmeldebildschirm erscheint nicht mehr", "type": "checkbox"},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def parse_optionen_form(form, merkmal_key: str) -> dict:
|
||||
"""Liest die zu einem Merkmal gehörenden optionen-Felder aus einem
|
||||
FastAPI-Formular gemäß OPTIONEN_FELDER - Checkboxen werden zu bool,
|
||||
Text-/Passwort-Felder nur übernommen, wenn tatsächlich etwas eingegeben
|
||||
wurde (leer = "nicht ändern", siehe Modul-Kommentar oben)."""
|
||||
Passwort-Felder nur übernommen, wenn tatsächlich etwas eingegeben
|
||||
wurde (leer = "nicht ändern", siehe Modul-Kommentar oben), Text-Felder
|
||||
immer (sie sind vorausgefüllt)."""
|
||||
ergebnis = {}
|
||||
for feld in OPTIONEN_FELDER.get(merkmal_key, []):
|
||||
roh = form.get(f"optionen.{feld['key']}")
|
||||
if feld["type"] == "checkbox":
|
||||
ergebnis[feld["key"]] = roh == "on"
|
||||
elif roh:
|
||||
ergebnis[feld["key"]] = roh
|
||||
elif feld["type"] == "password":
|
||||
if roh:
|
||||
ergebnis[feld["key"]] = roh
|
||||
elif roh is not None:
|
||||
# Seit 26.10.2026 vorausgefüllt (_merkmal_optionen.html): leer
|
||||
# heißt hier "entfernen", nicht "beibehalten".
|
||||
ergebnis[feld["key"]] = roh.strip()
|
||||
return ergebnis
|
||||
@@ -0,0 +1,46 @@
|
||||
{# Merkmal-Optionen (ADR-0010) an OE und Gruppe, Feld-Definitionen in
|
||||
optionen_felder.py. Seit 26.10.2026 (Kiosk) vorausgefüllt und bei aktivem
|
||||
Merkmal unter "Einstellungen" änderbar; Passwörter bleiben leer
|
||||
(leer = beibehalten). #}
|
||||
{% macro optionen_felder_html(felder, werte) %}
|
||||
<div class="optionen">
|
||||
{% for feld in felder %}
|
||||
<label>
|
||||
{% if feld.type == "checkbox" %}
|
||||
<input type="checkbox" name="optionen.{{ feld.key }}" {% if werte.get(feld.key) %}checked{% endif %}>
|
||||
{{ feld.label }}
|
||||
{% elif feld.type == "textarea" %}
|
||||
{{ feld.label }}
|
||||
<textarea name="optionen.{{ feld.key }}" rows="{{ feld.rows or 4 }}" autocomplete="off"
|
||||
{% if feld.placeholder %}placeholder="{{ feld.placeholder }}"{% endif %}>{{ werte.get(feld.key) or "" }}</textarea>
|
||||
{% elif feld.type == "password" %}
|
||||
{{ feld.label }}
|
||||
<input type="password" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
{% if werte.get(feld.key) %}placeholder="(bereits gesetzt - leer lassen zum Beibehalten)"{% endif %}>
|
||||
{% else %}
|
||||
{{ feld.label }}
|
||||
<input type="{{ feld.type }}" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
value="{{ werte.get(feld.key) if werte.get(feld.key) is not none else '' }}"
|
||||
{% if feld.placeholder %}placeholder="{{ feld.placeholder }}"{% endif %}>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro merkmal_aktivieren(felder, werte, aktiv, select_url, knopf_text) %}
|
||||
{% if aktiv != true %}
|
||||
<form method="post" action="{{ select_url }}">
|
||||
{% if felder %}{{ optionen_felder_html(felder, werte or {}) }}{% endif %}
|
||||
<button type="submit">{{ knopf_text }}</button>
|
||||
</form>
|
||||
{% elif felder %}
|
||||
<details class="optionen-bearbeiten">
|
||||
<summary>Einstellungen</summary>
|
||||
<form method="post" action="{{ select_url }}">
|
||||
{{ optionen_felder_html(felder, werte or {}) }}
|
||||
<button type="submit">Einstellungen speichern</button>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
@@ -172,13 +172,13 @@ oder sie unter <a href="/struktur">Organisation › Standorte/Zwecke</a> direkt
|
||||
<h4>🧭 Standardbrowser</h4>
|
||||
<div class="ws-box">
|
||||
<form method="post" action="{{ ws_basis }}/{{ workspace_id }}/standardbrowser">
|
||||
<label>Webapps ohne Kiosk-Modus und Links aus anderen Programmen öffnen sich in
|
||||
<label>Webapps ohne eigenes Fenster und Links aus anderen Programmen öffnen sich in
|
||||
<select name="browser">
|
||||
<option value="" {% if not workspace.standardbrowser %}selected{% endif %}>keine Vorgabe (Standard der Distro)</option>
|
||||
{% for b in workspace.standardbrowser_auswahl %}<option value="{{ b.key }}" {% if b.key == workspace.standardbrowser %}selected{% endif %}>{{ b.name }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<small>Zur Wahl stehen Firefox und die Browser, die im gespeicherten Entwurf enthalten sind. Webapps mit Kiosk-Modus starten weiterhin als eigenes Chrome- bzw. Chromium-Fenster.</small>
|
||||
<small>Zur Wahl stehen Firefox und die Browser, die im gespeicherten Entwurf enthalten sind. Webapps mit eigenem Fenster starten weiterhin als eigenes Chrome- bzw. Chromium-Fenster.</small>
|
||||
<button type="submit" class="outline">Speichern</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% from "_merkmal_optionen.html" import merkmal_aktivieren with context %}
|
||||
{% block title %}Gruppe {{ gruppe.name }} — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<p><a href="/admin/kunden/{{ organization_id }}/gruppen">← Gruppen</a></p>
|
||||
@@ -30,27 +31,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if eintrag.aktiv != true %}
|
||||
<form method="post" action="/admin/kunden/{{ organization_id }}/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/select">
|
||||
{% if optionen_felder.get(eintrag.merkmal) %}
|
||||
<div class="optionen">
|
||||
{% for feld in optionen_felder[eintrag.merkmal] %}
|
||||
<label>
|
||||
{% if feld.type == "checkbox" %}
|
||||
<input type="checkbox" name="optionen.{{ feld.key }}">
|
||||
{{ feld.label }}
|
||||
{% else %}
|
||||
{{ feld.label }}
|
||||
<input type="{{ feld.type }}" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
{% if eintrag.optionen and eintrag.optionen.get(feld.key) %}placeholder="(bereits gesetzt - leer lassen zum Beibehalten)"{% endif %}>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Aktiv</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ merkmal_aktivieren(optionen_felder.get(eintrag.merkmal), eintrag.optionen, eintrag.aktiv, "/admin/kunden/" ~ organization_id ~ "/gruppen/" ~ gruppe.id ~ "/merkmale/" ~ eintrag.merkmal ~ "/select", "Aktiv") }}
|
||||
{% if eintrag.aktiv != false %}
|
||||
<form method="post" action="/admin/kunden/{{ organization_id }}/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/deselect" style="display:inline">
|
||||
<button type="submit" class="secondary">Inaktiv</button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "admin/layout.html" %}
|
||||
{% from "_merkmal_optionen.html" import merkmal_aktivieren with context %}
|
||||
{% block title %}OE-Merkmale — Tuxflotte Admin{% endblock %}
|
||||
{% block admin_content %}
|
||||
<p><a href="/admin/kunden/{{ organization_id }}">← Organisation</a></p>
|
||||
@@ -31,27 +32,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if eintrag.aktiv != true %}
|
||||
<form method="post" action="/admin/kunden/{{ organization_id }}/organisationseinheiten/{{ oe_id }}/merkmale/{{ eintrag.merkmal }}/select">
|
||||
{% if optionen_felder.get(eintrag.merkmal) %}
|
||||
<div class="optionen">
|
||||
{% for feld in optionen_felder[eintrag.merkmal] %}
|
||||
<label>
|
||||
{% if feld.type == "checkbox" %}
|
||||
<input type="checkbox" name="optionen.{{ feld.key }}">
|
||||
{{ feld.label }}
|
||||
{% else %}
|
||||
{{ feld.label }}
|
||||
<input type="{{ feld.type }}" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
{% if eintrag.optionen and eintrag.optionen.get(feld.key) %}placeholder="(bereits gesetzt - leer lassen zum Beibehalten)"{% endif %}>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Aktiv</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ merkmal_aktivieren(optionen_felder.get(eintrag.merkmal), eintrag.optionen, eintrag.aktiv, "/admin/kunden/" ~ organization_id ~ "/organisationseinheiten/" ~ oe_id ~ "/merkmale/" ~ eintrag.merkmal ~ "/select", "Aktiv") }}
|
||||
{% if eintrag.aktiv != false %}
|
||||
<form method="post" action="/admin/kunden/{{ organization_id }}/organisationseinheiten/{{ oe_id }}/merkmale/{{ eintrag.merkmal }}/deselect" style="display:inline">
|
||||
<button type="submit" class="secondary">Inaktiv</button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "_merkmal_optionen.html" import merkmal_aktivieren with context %}
|
||||
{% block title %}Gruppe {{ gruppe.name }} — Tuxflotte{% endblock %}
|
||||
{% block content %}
|
||||
<p><a href="/gruppen">← Gruppen</a></p>
|
||||
@@ -33,27 +34,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if eintrag.aktiv != true %}
|
||||
<form method="post" action="/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/select">
|
||||
{% if optionen_felder.get(eintrag.merkmal) %}
|
||||
<div class="optionen">
|
||||
{% for feld in optionen_felder[eintrag.merkmal] %}
|
||||
<label>
|
||||
{% if feld.type == "checkbox" %}
|
||||
<input type="checkbox" name="optionen.{{ feld.key }}">
|
||||
{{ feld.label }}
|
||||
{% else %}
|
||||
{{ feld.label }}
|
||||
<input type="{{ feld.type }}" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
{% if eintrag.optionen.get(feld.key) %}placeholder="(bereits gesetzt - leer lassen zum Beibehalten)"{% endif %}>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Aktiv setzen</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ merkmal_aktivieren(optionen_felder.get(eintrag.merkmal), eintrag.optionen, eintrag.aktiv, "/gruppen/" ~ gruppe.id ~ "/merkmale/" ~ eintrag.merkmal ~ "/select", "Aktiv setzen") }}
|
||||
{% if eintrag.aktiv != false %}
|
||||
<form method="post" action="/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/deselect">
|
||||
<button type="submit" class="secondary">Inaktiv setzen</button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "_merkmal_optionen.html" import merkmal_aktivieren with context %}
|
||||
{% block title %}Merkmale {{ oe.name }} — Tuxflotte{% endblock %}
|
||||
{% block content %}
|
||||
<p><a href="/struktur">← Standorte/Zwecke</a></p>
|
||||
@@ -71,27 +72,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if eintrag.aktiv != true %}
|
||||
<form method="post" action="/struktur/{{ oe.id }}/merkmale/{{ eintrag.merkmal }}/select">
|
||||
{% if optionen_felder.get(eintrag.merkmal) %}
|
||||
<div class="optionen">
|
||||
{% for feld in optionen_felder[eintrag.merkmal] %}
|
||||
<label>
|
||||
{% if feld.type == "checkbox" %}
|
||||
<input type="checkbox" name="optionen.{{ feld.key }}">
|
||||
{{ feld.label }}
|
||||
{% else %}
|
||||
{{ feld.label }}
|
||||
<input type="{{ feld.type }}" name="optionen.{{ feld.key }}" autocomplete="off"
|
||||
{% if eintrag.optionen.get(feld.key) %}placeholder="(bereits gesetzt - leer lassen zum Beibehalten)"{% endif %}>
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit">Aktiv setzen</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ merkmal_aktivieren(optionen_felder.get(eintrag.merkmal), eintrag.optionen, eintrag.aktiv, "/struktur/" ~ oe.id ~ "/merkmale/" ~ eintrag.merkmal ~ "/select", "Aktiv setzen") }}
|
||||
{% if eintrag.aktiv != false %}
|
||||
<form method="post" action="/struktur/{{ oe.id }}/merkmale/{{ eintrag.merkmal }}/deselect">
|
||||
<button type="submit" class="secondary">Inaktiv setzen</button>
|
||||
|
||||
Reference in new issue
Block a user