diff --git a/README.md b/README.md index 4ec237b..ba6e52b 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,187 @@ erreichbar ist und die Durchwahl als Kennung nutzt. ### Bedienung +Es gibt genau **eine** Adresse: + +``` +http://SERVER:8080/zentrale +``` + +Durchwahl eintragen, **Weiter** klicken - die Seite zeigt dann, was fuer diese Person +gerade gilt. Derselbe Weg fuehrt zum Uebernehmen und zum Freigeben, es muss sich also +niemand eine zweite, persoenliche Adresse gemerkt haben, um die Zentrale wieder +loszuwerden. + +| Lage | Angebot | +|------|---------| +| Zentrale frei | **Zentrale besetzen** | +| jemand anderes sitzt darauf | **Zentrale uebernehmen**, mit Hinweis was mit dieser Person passiert | +| man sitzt selbst darauf | **Zentrale freigeben** | +| es ist der eigene Stammplatz | kein Knopf, nur der Hinweis dass nichts zu tun ist | + +Wer gerade auf der Zentrale sitzt, steht immer oben auf der Seite - auch ohne +Durchwahl. Wartet jemand auf seine Rueckkehr, steht das ebenfalls dort. + +Jede Aktion leitet auf `/zentrale` zurueck (POST/Redirect/GET). Man landet also nie auf +einer Formular-Antwort, die beim Neuladen die Aktion wiederholen wuerde. + +Fuer QR-Codes pro Person gibt es die Kurzform `/zentrale/{durchwahl}`. Sie leitet +lediglich auf `/zentrale?durchwahl=...` um - es bleibt bei der einen Seite. + +### Verhalten + +- `callstart`: Setzt WLED auf Telefon-Farbe (Standard: Rot), aber **nur** wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice ist +- `callend`: Setzt WLED zurueck auf den Zeiterfassungs-Status. Der Teams-Status wird beim naechsten Polling-Zyklus (15s) automatisch aktualisiert +- Waehrend eines aktiven Telefonats ueberschreibt das Teams-Polling die Farbe nicht +- Die Telefon-Farbe (`phone_active`) ist unter **Farb-Regeln** konfigurierbar + +## Logo + +Unter **Einstellungen > Logo** kann ein kundenspezifisches Logo hochgeladen werden. Es +erscheint in der Seitenleiste, auf der Login-Seite und auf der Zentrale-Seite. + +- Formate: PNG, JPG, SVG, WEBP, GIF, maximal 2 MB +- Dargestellt wird eine Hoehe von etwa 40 Pixeln. Die Seitenleiste ist dunkel, ein Logo + mit heller Schrift oder transparentem Hintergrund wirkt dort am besten - die + Einstellungsseite zeigt eine Vorschau auf hellem und dunklem Grund. +- Die Datei liegt unter `static/custom/` und ist per `.gitignore` von der Versionierung + ausgenommen. **Ein `git pull` ueberschreibt das Kundenlogo nicht.** +- Mit **Zurueck zum Standardlogo** wird die Datei entfernt und wieder + `static/logo.png` aus dem Repository verwendet. + +## Zentrale (Self-Service) + +Ein Busylight im Empfangsbereich wird wechselnd besetzt. Damit die Mitarbeiter das +selbst umstellen koennen, gibt es eine eigene Seite, die **ohne Admin-Passwort** +erreichbar ist und die Durchwahl als Kennung nutzt. + +### Einrichtung + +1. Unter **Benutzer** die **Durchwahl** pro Mitarbeiter eintragen (dieselbe wie fuer den Telefon-Webhook) +2. Unter **Einstellungen > Zentrale (Self-Service)** das Busylight des Empfangs und das Segment auswaehlen +3. Die Seite `http://SERVER:8080/zentrale` an die Mitarbeiter geben + +### Bedienung + +``` +http://SERVER:8080/zentrale - Durchwahl eingeben +http://SERVER:8080/zentrale/{durchwahl} - Zustandsseite pro Person, als Lesezeichen + oder QR-Code +``` + +Die Bedienung laeuft in zwei Schritten. Auf `/zentrale` gibt man seine Durchwahl ein +und landet auf der eigenen Zustandsseite `/zentrale/{durchwahl}`. Dort steht, wer +gerade auf der Zentrale sitzt und welche Knoepfe zur Verfuegung stehen - geaendert +wird erst per Klick. + +Die Zustandsseite ist die eigentliche Adresse fuer den Alltag und als Lesezeichen +gedacht. Sie zeigt immer den echten Zustand, passt die Knoepfe daran an und ist +gefahrlos neu ladbar: + +| Lage | Angebot | +|------|---------| +| Zentrale frei | **Zentrale besetzen**, ohne Rueckfrage | +| jemand anderes sitzt darauf | **Zentrale uebernehmen** mit Rueckfrage, siehe unten | +| man sitzt selbst darauf | **Zurueck auf mein Tuerschild** | +| es ist der eigene Stammplatz | kein Knopf, nur der Hinweis dass nichts zu tun ist | + +### Verhalten + +- `callstart`: Setzt WLED auf Telefon-Farbe (Standard: Rot), aber **nur** wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice ist +- `callend`: Setzt WLED zurueck auf den Zeiterfassungs-Status. Der Teams-Status wird beim naechsten Polling-Zyklus (15s) automatisch aktualisiert +- Waehrend eines aktiven Telefonats ueberschreibt das Teams-Polling die Farbe nicht +- Die Telefon-Farbe (`phone_active`) ist unter **Farb-Regeln** konfigurierbar + +## Logo + +Unter **Einstellungen > Logo** kann ein kundenspezifisches Logo hochgeladen werden. Es +erscheint in der Seitenleiste, auf der Login-Seite und auf der Zentrale-Seite. + +- Formate: PNG, JPG, SVG, WEBP, GIF, maximal 2 MB +- Dargestellt wird eine Hoehe von etwa 40 Pixeln. Die Seitenleiste ist dunkel, ein Logo + mit heller Schrift oder transparentem Hintergrund wirkt dort am besten - die + Einstellungsseite zeigt eine Vorschau auf hellem und dunklem Grund. +- Die Datei liegt unter `static/custom/` und ist per `.gitignore` von der Versionierung + ausgenommen. **Ein `git pull` ueberschreibt das Kundenlogo nicht.** +- Mit **Zurueck zum Standardlogo** wird die Datei entfernt und wieder + `static/logo.png` aus dem Repository verwendet. + +## Zentrale (Self-Service) + +Ein Busylight im Empfangsbereich wird wechselnd besetzt. Damit die Mitarbeiter das +selbst umstellen koennen, gibt es eine eigene Seite, die **ohne Admin-Passwort** +erreichbar ist und die Durchwahl als Kennung nutzt. + +### Einrichtung + +1. Unter **Benutzer** die **Durchwahl** pro Mitarbeiter eintragen (dieselbe wie fuer den Telefon-Webhook) +2. Unter **Einstellungen > Zentrale (Self-Service)** das Busylight des Empfangs und das Segment auswaehlen +3. Die Seite `http://SERVER:8080/zentrale` an die Mitarbeiter geben + +### Bedienung + +Es gibt genau **eine** Adresse: + +``` +http://SERVER:8080/zentrale +``` + +Durchwahl eintragen, **Weiter** klicken - die Seite zeigt dann, was fuer diese Person +gerade gilt. Derselbe Weg fuehrt zum Uebernehmen und zum Freigeben, es muss sich also +niemand eine zweite, persoenliche Adresse gemerkt haben, um die Zentrale wieder +loszuwerden. + +| Lage | Angebot | +|------|---------| +| Zentrale frei | **Zentrale besetzen** | +| jemand anderes sitzt darauf | **Zentrale uebernehmen**, mit Hinweis was mit dieser Person passiert | +| man sitzt selbst darauf | **Zentrale freigeben** | +| es ist der eigene Stammplatz | kein Knopf, nur der Hinweis dass nichts zu tun ist | + +Wer gerade auf der Zentrale sitzt, steht immer oben auf der Seite - auch ohne +Durchwahl. Wartet jemand auf seine Rueckkehr, steht das ebenfalls dort. + +Jede Aktion leitet auf `/zentrale` zurueck (POST/Redirect/GET). Man landet also nie auf +einer Formular-Antwort, die beim Neuladen die Aktion wiederholen wuerde. + +Fuer QR-Codes pro Person gibt es die Kurzform `/zentrale/{durchwahl}`. Sie leitet +lediglich auf `/zentrale?durchwahl=...` um - es bleibt bei der einen Seite. + +### Verhalten + +- `callstart`: Setzt WLED auf Telefon-Farbe (Standard: Rot), aber **nur** wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice ist +- `callend`: Setzt WLED zurueck auf den Zeiterfassungs-Status. Der Teams-Status wird beim naechsten Polling-Zyklus (15s) automatisch aktualisiert +- Waehrend eines aktiven Telefonats ueberschreibt das Teams-Polling die Farbe nicht +- Die Telefon-Farbe (`phone_active`) ist unter **Farb-Regeln** konfigurierbar + +## Logo + +Unter **Einstellungen > Logo** kann ein kundenspezifisches Logo hochgeladen werden. Es +erscheint in der Seitenleiste, auf der Login-Seite und auf der Zentrale-Seite. + +- Formate: PNG, JPG, SVG, WEBP, GIF, maximal 2 MB +- Dargestellt wird eine Hoehe von etwa 40 Pixeln. Die Seitenleiste ist dunkel, ein Logo + mit heller Schrift oder transparentem Hintergrund wirkt dort am besten - die + Einstellungsseite zeigt eine Vorschau auf hellem und dunklem Grund. +- Die Datei liegt unter `static/custom/` und ist per `.gitignore` von der Versionierung + ausgenommen. **Ein `git pull` ueberschreibt das Kundenlogo nicht.** +- Mit **Zurueck zum Standardlogo** wird die Datei entfernt und wieder + `static/logo.png` aus dem Repository verwendet. + +## Zentrale (Self-Service) + +Ein Busylight im Empfangsbereich wird wechselnd besetzt. Damit die Mitarbeiter das +selbst umstellen koennen, gibt es eine eigene Seite, die **ohne Admin-Passwort** +erreichbar ist und die Durchwahl als Kennung nutzt. + +### Einrichtung + +1. Unter **Benutzer** die **Durchwahl** pro Mitarbeiter eintragen (dieselbe wie fuer den Telefon-Webhook) +2. Unter **Einstellungen > Zentrale (Self-Service)** das Busylight des Empfangs und das Segment auswaehlen +3. Die Seite `http://SERVER:8080/zentrale` an die Mitarbeiter geben + +### Bedienung + ``` http://SERVER:8080/zentrale - Durchwahl eingeben http://SERVER:8080/zentrale/{durchwahl} - Zustandsseite pro Person, als Lesezeichen @@ -387,11 +568,11 @@ busylight/ - Unter Tuerschilder den Status pruefen ("Alle jetzt pruefen") - Netzwerkverbindung pruefen: `curl http://HOSTNAME/json/info` -### Auf /zentrale fehlt der Knopf zum Zurueckgeben +### Wie gibt man die Zentrale wieder frei? -Der ist absichtlich erst auf der Zustandsseite `/zentrale/{durchwahl}` zu sehen, denn -vorher weiss die Anwendung nicht, wer zurueckgeben will. Durchwahl eingeben, **Weiter** -klicken - dann erscheint der passende Knopf. +Auf `/zentrale` die eigene Durchwahl eintragen und **Weiter** klicken - dann erscheint +**Zentrale freigeben**. Es ist derselbe Weg wie beim Uebernehmen, eine gemerkte Adresse +braucht es nicht. ### Zentrale-Seite sagt "noch nicht eingerichtet" diff --git a/app.py b/app.py index e189d2b..8823b30 100644 --- a/app.py +++ b/app.py @@ -666,51 +666,47 @@ def _zentrale_page(request, conn, target, extension="", user=None, done=None): def _zentrale_redirect(extension, done): - """Nach jeder Aktion zurueck auf die Zustandsseite (POST/Redirect/GET).""" + """Nach jeder Aktion zurueck auf /zentrale (POST/Redirect/GET). + + Es gibt absichtlich nur diese eine Adresse: wer die Zentrale freigeben will, + soll sich keine zweite URL gemerkt haben muessen. + """ ext = quote((extension or "").strip(), safe="") if not ext: return RedirectResponse(f"/zentrale?done={done}", status_code=303) - return RedirectResponse(f"/zentrale/{ext}?done={done}", status_code=303) + return RedirectResponse(f"/zentrale?durchwahl={ext}&done={done}", status_code=303) @app.get("/zentrale", response_class=HTMLResponse) async def zentrale_page(request: Request): - """Self-Service-Seite fuer den Empfangsbereich. Absichtlich ohne Admin-Login.""" - # Das Formular schickt die Durchwahl per GET - auf die Personenseite umleiten, - # damit die Adresse merkbar und neu ladbar ist. + """Self-Service-Seite fuer den Empfangsbereich. Absichtlich ohne Admin-Login. + + Die eine Adresse fuer alles: Durchwahl eintragen, und die Seite zeigt die + Knoepfe, die fuer diese Person gerade gelten - Uebernehmen oder Freigeben. + """ typed = (request.query_params.get("durchwahl") or "").strip() - if typed: - return RedirectResponse(f"/zentrale/{quote(typed, safe='')}", status_code=303) + done = request.query_params.get("done") - conn = database.get_db() - try: - return _zentrale_page(request, conn, _selfservice_target(conn), - done=request.query_params.get("done")) - finally: - conn.close() - - -@app.get("/zentrale/{extension}", response_class=HTMLResponse) -async def zentrale_page_for_extension(request: Request, extension: str): - """Zustandsseite pro Mitarbeiter. Zeigt nur an, geaendert wird per Knopf.""" conn = database.get_db() try: target = _selfservice_target(conn) - user = _user_by_extension(extension, conn) - done = request.query_params.get("done") if user else "err_unbekannt" - return _zentrale_page(request, conn, target, extension=extension, user=user, done=done) + user = _user_by_extension(typed, conn) if typed else None + if typed and not user and not done: + done = "err_unbekannt" + return _zentrale_page(request, conn, target, extension=typed, user=user, done=done) finally: conn.close() -@app.post("/api/zentrale/uebernehmen") -async def zentrale_takeover(extension: str = Form(...), confirm: str = Form("")): - """Mitarbeiter setzt sich selbst auf das Busylight der Zentrale. +@app.get("/zentrale/{extension}") +async def zentrale_page_for_extension(extension: str): + """Kurzform fuer QR-Codes. Leitet auf die eine Adresse um.""" + return RedirectResponse(f"/zentrale?durchwahl={quote(extension, safe='')}", status_code=303) - Sitzt bereits jemand anderes darauf, braucht es eine ausdrueckliche - Bestaetigung. Eine Rueckgabe zu erzwingen waere die Alternative, wuerde die - Zentrale aber sperren, sobald jemand ohne Freigabe nach Hause geht. - """ + +@app.post("/api/zentrale/uebernehmen") +async def zentrale_takeover(extension: str = Form(...)): + """Mitarbeiter setzt sich selbst auf das Busylight der Zentrale.""" conn = database.get_db() try: target = _selfservice_target(conn) @@ -721,14 +717,6 @@ async def zentrale_takeover(extension: str = Form(...), confirm: str = Form("")) if not user: return _zentrale_redirect(extension, "err_unbekannt") - if confirm != "ja": - besetzt = conn.execute(""" - SELECT 1 FROM assignments - WHERE wled_device_id = ? AND segment = ? AND user_azure_id != ? - """, (target["id"], target["segment"], user["azure_id"])).fetchone() - if besetzt: - return _zentrale_redirect(extension, "bestaetigen") - already = conn.execute(""" SELECT 1 FROM assignments WHERE user_azure_id = ? AND wled_device_id = ? AND segment = ? diff --git a/templates/zentrale.html b/templates/zentrale.html index 1d9865b..19d9894 100644 --- a/templates/zentrale.html +++ b/templates/zentrale.html @@ -70,8 +70,8 @@ {{ target.name }} (Segment {{ target.segment }})
+ Aktuell besetzt von {% if occupant %} - Aktuell besetzt von {{ occupant.display_name }} {%- if is_here %} das bist du{% endif %} @@ -80,7 +80,6 @@
Das ist der Stammplatz dieser Person.
{% endif %} {% else %} - Aktuell besetzt von niemand - die Zentrale ist frei {% endif %} {% if owner_waiting %} @@ -93,30 +92,37 @@ {% if not user %} - {# ── Schritt 1: Wer bist du? ──────────────────────────────────── #} + {# ── Eintritt: Durchwahl. Derselbe Weg fuer Uebernehmen und Freigeben. ── #}
- + - Im naechsten Schritt siehst du, was du tun kannst - es wird noch nichts geaendert. + {% if occupant %} + Damit uebernimmst du die Zentrale - oder gibst sie frei, wenn du selbst + eingetragen bist. Im naechsten Schritt siehst du, was fuer dich gilt. + {% else %} + Damit besetzt du die Zentrale. Im naechsten Schritt siehst du, was fuer + dich gilt - geaendert wird noch nichts. + {% endif %}
+ {% else %} - {# ── Schritt 2: Zustand und passende Aktionen ──────────────────── #} + {# ── Zustand dieser Person und die passenden Knoepfe ──────────────── #}
Durchwahl {{ user.phone_extension }} {{ user.display_name }}
{% if is_owner and is_here %} -
+
Die Zentrale ist dein eigener Platz und du sitzt darauf. Hier ist nichts zu tun - jemand anderes kann sie jederzeit uebernehmen, @@ -136,50 +142,17 @@
{% if home_blocker %} -
+
Achtung: dein Tuerschild ist derzeit {{ home_blocker }} zugeordnet. Die Rueckkehr wird abgelehnt, solange das so ist.
{% endif %} - {% elif done == 'bestaetigen' and occupant %} - {# Zweiter Schritt: verdraengen ist nie ein Versehen #} -
- Wirklich uebernehmen? -
- {{ occupant.display_name }} ist derzeit auf der Zentrale - eingetragen. Bitte nur uebernehmen, wenn diese Person den Empfang - tatsaechlich verlassen hat. -
- {% if occupant_is_owner %} - {{ occupant.display_name }} gehoert auf die Zentrale und kommt automatisch - zurueck, sobald du sie wieder freigibst. - {% elif occupant_has_home %} - {{ occupant.display_name }} wird dabei auf das eigene Tuerschild - zurueckgesetzt. - {% else %} - {{ occupant.display_name }} hat kein eigenes Tuerschild und gehoert damit - auf die Zentrale. Die Person wird als Stamm-Besetzer vermerkt und kommt - automatisch zurueck, sobald du wieder freigibst. - {% endif %} -
-
-
- - - -
- - Abbrechen - - {% else %}
@@ -189,16 +162,14 @@ {% if occupant and occupant_is_owner %} - {{ occupant.display_name }} sitzt darauf und gehoert dorthin. Nach einer - Uebernahme kommt sie oder er automatisch zurueck, sobald du freigibst. - Du wirst noch um Bestaetigung gebeten. + {{ occupant.display_name }} gehoert auf die Zentrale und kommt automatisch + zurueck, sobald du wieder freigibst. {% elif occupant and occupant_has_home %} - {{ occupant.display_name }} sitzt darauf und wird dabei auf das eigene - Tuerschild zurueckgesetzt. Du wirst noch um Bestaetigung gebeten. + {{ occupant.display_name }} wird dabei auf das eigene Tuerschild + zurueckgesetzt. {% elif occupant %} - {{ occupant.display_name }} sitzt darauf und gehoert auf die Zentrale, - kommt also automatisch zurueck, sobald du freigibst. - Du wirst noch um Bestaetigung gebeten. + {{ occupant.display_name }} hat kein eigenes Tuerschild und gehoert damit + auf die Zentrale - kommt also automatisch zurueck, sobald du freigibst. {% else %} Die Zentrale ist frei. {% endif %} @@ -206,11 +177,11 @@ {% if home %} -
+ + - Gemerkt: {{ home.name or home.hostname }}, Segment {{ home.segment }}. @@ -218,23 +189,29 @@ {% endif %} {% endif %} - -
- - Diese Seite als Lesezeichen: /zentrale/{{ user.phone_extension }} - -
- {% endif %} + {# ── Andere Person: dasselbe Formular, dieselbe Adresse ──────────── #} +
+ +
+ + +
+
+ +
+
{% endif %}
- © cynfo GmbH + + Zentrale-Seite neu laden + +
+ © cynfo GmbH +
+ {% endif %}