From 0867221a3c56e4008053124bf7d8c09759ac1798 Mon Sep 17 00:00:00 2001 From: Christian Mueller Date: Fri, 21 Aug 2026 09:08:08 +0000 Subject: [PATCH] fix: Zentrale-Seite zeigt den Zustand und den Weg zurueck Zwei Handhabungsprobleme, die zusammengehoeren. Auf /zentrale gab es ueberhaupt keinen Knopf zum Zurueckgeben - den fand man nur ueber den Direktlink, den man nach einer Uebernahme in der Hand hatte. Wer stattdessen /zentrale aufrief, konnte nur weiter uebernehmen und sah nicht, dass erst zurueckgesetzt werden muss. Ausserdem rendern die POST-Endpunkte ihr Ergebnis direkt. Man blieb also auf /api/zentrale/uebernehmen stehen: eine Adresse, die beim Neuladen die Aktion wiederholt und den Zustand nicht widerspiegelt. Neu: - Zwei Schritte. /zentrale fragt nur die Durchwahl ab und leitet auf /zentrale/{durchwahl} um. Diese Zustandsseite ist die Adresse fuer den Alltag, als Lesezeichen oder QR-Code, und ist gefahrlos neu ladbar. - Die Knoepfe richten sich nach der Lage: frei -> besetzen, fremd besetzt -> uebernehmen samt Hinweis was mit dieser Person passiert, selbst besetzt -> zurueck auf mein Tuerschild, eigener Stammplatz -> kein Knopf, nur der Hinweis dass nichts zu tun ist. - Alle Aktionen antworten mit POST/Redirect/GET auf die Zustandsseite und uebergeben nur einen kurzen Code fuer die Bestaetigung. Die Einzelheiten - wer sitzt drauf, wer wartet, wer blockiert den Heimatplatz - leitet die Seite bei jedem Aufruf frisch aus dem echten Zustand ab. - Die allgemeine Seite nennt den aktuellen Besetzer und, falls vorhanden, wer bei einer Freigabe automatisch zurueckkommt. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 32 ++++- app.py | 224 +++++++++++++++-------------- templates/zentrale.html | 303 +++++++++++++++++++++++++--------------- 3 files changed, 329 insertions(+), 230 deletions(-) diff --git a/README.md b/README.md index 85ec481..623ccb3 100644 --- a/README.md +++ b/README.md @@ -205,12 +205,30 @@ erreichbar ist und die Durchwahl als Kennung nutzt. ### Bedienung ``` -http://SERVER:8080/zentrale - Durchwahl eingeben und Zentrale uebernehmen -http://SERVER:8080/zentrale/{durchwahl} - Direktlink pro Person, z.B. als QR-Code +http://SERVER:8080/zentrale - Durchwahl eingeben +http://SERVER:8080/zentrale/{durchwahl} - Zustandsseite pro Person, als Lesezeichen + oder QR-Code ``` -Der Direktlink zeigt nur den Stand an und aendert nichts - das Umstellen passiert -erst per Knopfdruck. +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** | +| jemand anderes sitzt darauf | **Zentrale uebernehmen**, mit Hinweis was mit dieser Person passiert | +| man sitzt selbst darauf | **Zurueck auf mein Tuerschild** | +| es ist der eigene Stammplatz | kein Knopf, nur der Hinweis dass nichts zu tun ist | + +Jede Aktion leitet auf diese Seite zurueck (POST/Redirect/GET). Man landet also nie +auf einer Formular-Antwort, die beim Neuladen die Aktion wiederholen wuerde, und sieht +nach jedem Klick den neuen Zustand samt Bestaetigung. ### Verhalten @@ -353,6 +371,12 @@ busylight/ - Unter Tuerschilder den Status pruefen ("Alle jetzt pruefen") - Netzwerkverbindung pruefen: `curl http://HOSTNAME/json/info` +### Auf /zentrale fehlt der Knopf zum Zurueckgeben + +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. + ### Zentrale-Seite sagt "noch nicht eingerichtet" Unter **Einstellungen > Zentrale (Self-Service)** ist kein Busylight ausgewaehlt. diff --git a/app.py b/app.py index 3728f46..54790fa 100644 --- a/app.py +++ b/app.py @@ -10,6 +10,7 @@ import shutil import sys from contextlib import asynccontextmanager from datetime import datetime +from urllib.parse import quote from fastapi import FastAPI, Request, Form, UploadFile, File, BackgroundTasks from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse, JSONResponse @@ -559,43 +560,6 @@ def _user_by_extension(extension, conn): """, (ext,)).fetchone() -def _zentrale_view(request, conn, target, extension="", user=None, error=None, message=None): - """Kontext fuer die Self-Service-Seite zusammenbauen.""" - occupant = None - if target: - occupant = conn.execute(""" - SELECT u.display_name - FROM assignments a JOIN users u ON u.azure_id = a.user_azure_id - WHERE a.wled_device_id = ? AND a.segment = ? - """, (target["id"], target["segment"])).fetchone() - - home = None - is_here = False - if user: - home = conn.execute(""" - SELECT h.segment, d.name, d.hostname - FROM home_assignments h JOIN wled_devices d ON d.id = h.wled_device_id - WHERE h.user_azure_id = ? - """, (user["azure_id"],)).fetchone() - if target: - is_here = conn.execute(""" - SELECT 1 FROM assignments - WHERE user_azure_id = ? AND wled_device_id = ? AND segment = ? - """, (user["azure_id"], target["id"], target["segment"])).fetchone() is not None - - return templates.TemplateResponse(request, "zentrale.html", { - "page": "zentrale", - "target": target, - "occupant": occupant["display_name"] if occupant else None, - "extension": extension, - "user": user, - "home": home, - "is_here": is_here, - "error": error, - "message": message, - }) - - def _zentrale_owner_row(conn, target): """Heimateintrag, der auf das Zentral-Segment zeigt - der Stamm-Besetzer.""" if not target: @@ -634,45 +598,122 @@ def _restore_zentrale_owner(conn, target): return owner +def _zentrale_state(conn, target, user): + """Alles, was die Self-Service-Seite ueber die aktuelle Lage wissen muss. + + Wird bei jedem GET frisch berechnet. Die Aktionen leiten deshalb nach dem + Absenden auf /zentrale/{durchwahl} um: die Seite zeigt dann den echten + Zustand und nicht das Ergebnis eines abgeschickten Formulars. + """ + st = { + "occupant": None, "is_here": False, "home": None, + "home_blocker": None, "is_owner": False, "owner_waiting": None, + "occupant_is_owner": False, + } + if not target: + return st + + st["occupant"] = conn.execute(""" + SELECT u.azure_id, u.display_name + FROM assignments a JOIN users u ON u.azure_id = a.user_azure_id + WHERE a.wled_device_id = ? AND a.segment = ? + """, (target["id"], target["segment"])).fetchone() + + owner = _zentrale_owner_row(conn, target) + if owner and (not st["occupant"] or owner["user_azure_id"] != st["occupant"]["azure_id"]): + st["owner_waiting"] = owner["display_name"] + + # Sitzt der aktuelle Besetzer auf seinem Stammplatz? Dann kommt er nach einer + # Uebernahme von allein zurueck - das gehoert auf den Knopf geschrieben. + if st["occupant"]: + st["occupant_is_owner"] = conn.execute(""" + SELECT 1 FROM home_assignments + WHERE user_azure_id = ? AND wled_device_id = ? AND segment = ? + """, (st["occupant"]["azure_id"], target["id"], target["segment"])).fetchone() is not None + + if not user: + return st + + st["is_here"] = bool(st["occupant"] and st["occupant"]["azure_id"] == user["azure_id"]) + + st["home"] = conn.execute(""" + SELECT h.wled_device_id, h.segment, d.name, d.hostname + FROM home_assignments h JOIN wled_devices d ON d.id = h.wled_device_id + WHERE h.user_azure_id = ? + """, (user["azure_id"],)).fetchone() + + if st["home"]: + st["is_owner"] = (st["home"]["wled_device_id"], st["home"]["segment"]) \ + == (target["id"], target["segment"]) + if not st["is_owner"]: + blocker = conn.execute(""" + SELECT u.display_name FROM assignments a JOIN users u ON u.azure_id = a.user_azure_id + WHERE a.wled_device_id = ? AND a.segment = ? AND a.user_azure_id != ? + """, (st["home"]["wled_device_id"], st["home"]["segment"], user["azure_id"])).fetchone() + st["home_blocker"] = blocker["display_name"] if blocker else None + return st + + +def _zentrale_page(request, conn, target, extension="", user=None, done=None): + """Self-Service-Seite rendern.""" + st = _zentrale_state(conn, target, user) + return templates.TemplateResponse(request, "zentrale.html", { + "page": "zentrale", "target": target, "extension": extension, + "user": user, "done": done, **st, + }) + + +def _zentrale_redirect(extension, done): + """Nach jeder Aktion zurueck auf die Zustandsseite (POST/Redirect/GET).""" + 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) + + @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. + typed = (request.query_params.get("durchwahl") or "").strip() + if typed: + return RedirectResponse(f"/zentrale/{quote(typed, safe='')}", status_code=303) + conn = database.get_db() try: - return _zentrale_view(request, conn, _selfservice_target(conn)) + 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): - """Direktlink pro Mitarbeiter (z.B. als QR-Code). Zeigt nur an, aendert nichts.""" + """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) - error = None if user else f"Durchwahl {extension} ist keinem aktiven Benutzer zugeordnet." - return _zentrale_view(request, conn, target, extension=extension, user=user, error=error) + done = request.query_params.get("done") if user else "err_unbekannt" + return _zentrale_page(request, conn, target, extension=extension, user=user, done=done) finally: conn.close() -@app.post("/api/zentrale/uebernehmen", response_class=HTMLResponse) -async def zentrale_takeover(request: Request, extension: str = Form(...)): +@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) if not target: - return _zentrale_view(request, conn, target, extension=extension, - error="Die Zentrale ist noch nicht eingerichtet. Bitte den Administrator informieren.") + return _zentrale_redirect(extension, "err_nicht_eingerichtet") user = _user_by_extension(extension, conn) if not user: - return _zentrale_view(request, conn, target, extension=extension, - error=f"Durchwahl {extension} ist keinem aktiven Benutzer zugeordnet.") + return _zentrale_redirect(extension, "err_unbekannt") - # Sitzt der Benutzer schon dort? Dann nur das Licht nachziehen. already = conn.execute(""" SELECT 1 FROM assignments WHERE user_azure_id = ? AND wled_device_id = ? AND segment = ? @@ -680,8 +721,7 @@ async def zentrale_takeover(request: Request, extension: str = Form(...)): if already: scheduler.push_user_light(user["azure_id"], user["display_name"], target["hostname"], target["segment"], conn) - return _zentrale_view(request, conn, target, extension=extension, user=user, - message=f"{user['display_name']} ist bereits auf der Zentrale eingetragen.") + return _zentrale_redirect(extension, "bereits") # Bisheriger Platz des Benutzers wird als Heimat-Tuerschild gemerkt own = conn.execute(""" @@ -715,8 +755,6 @@ async def zentrale_takeover(request: Request, extension: str = Form(...)): # er erst selbst "zurueck" klicken, bevor die Uebernahme fuer ihn stimmt - und # bis dahin haette er gar kein Licht. pred_back = None - pred_blocked = None - pred_waiting = False if predecessor and predecessor["azure_id"] != user["azure_id"]: pred_home = conn.execute(""" SELECT h.wled_device_id, h.segment, d.hostname, d.name @@ -731,15 +769,13 @@ async def zentrale_takeover(request: Request, extension: str = Form(...)): # Sein Stammplatz IST die Zentrale, die jetzt der Nachfolger hat. # Der Heimateintrag bleibt stehen, damit er zurueckkommt, sobald # die Zentrale wieder frei wird. - pred_waiting = True + pass elif pred_home: taken = conn.execute(""" - SELECT u.display_name FROM assignments a JOIN users u ON u.azure_id = a.user_azure_id - WHERE a.wled_device_id = ? AND a.segment = ? + SELECT 1 FROM assignments + WHERE wled_device_id = ? AND segment = ? """, (pred_home["wled_device_id"], pred_home["segment"])).fetchone() - if taken: - pred_blocked = taken["display_name"] - else: + if not taken: conn.execute(""" INSERT INTO assignments (user_azure_id, wled_device_id, segment) VALUES (?, ?, ?) """, (predecessor["azure_id"], pred_home["wled_device_id"], pred_home["segment"])) @@ -758,7 +794,6 @@ async def zentrale_takeover(request: Request, extension: str = Form(...)): INSERT OR REPLACE INTO home_assignments (user_azure_id, wled_device_id, segment) VALUES (?, ?, ?) """, (predecessor["azure_id"], target["id"], target["segment"])) - pred_waiting = True conn.commit() @@ -777,44 +812,23 @@ async def zentrale_takeover(request: Request, extension: str = Form(...)): scheduler.push_user_light(predecessor["azure_id"], predecessor["display_name"], pred_back["hostname"], pred_back["segment"], conn) - logger.info("Zentrale uebernommen von %s (Durchwahl %s), Vorgaenger: %s (%s)", + logger.info("Zentrale uebernommen von %s (Durchwahl %s), Vorgaenger: %s", user["display_name"], extension, - predecessor["display_name"] if predecessor else "-", - "zurueck auf eigenem Tuerschild" if pred_back - else f"Tuerschild belegt von {pred_blocked}" if pred_blocked - else "wartet auf die Zentrale" if pred_waiting - else "kein Tuerschild gemerkt") - - msg = f"{user['display_name']} sitzt jetzt auf der Zentrale ({target['name']})." - if own: - msg += f" Das eigene Tuerschild ({own['name'] or own['hostname']}) ist bis zur Rueckkehr ausgeschaltet." - if pred_back: - msg += (f" {predecessor['display_name']} wurde auf das eigene Tuerschild " - f"({pred_back['name'] or pred_back['hostname']}) zurueckgesetzt.") - elif pred_blocked: - msg += (f" {predecessor['display_name']} konnte nicht zurueckgesetzt werden, " - f"weil das eigene Tuerschild inzwischen {pred_blocked} zugeordnet ist.") - elif pred_waiting: - msg += (f" {predecessor['display_name']} gehoert auf die Zentrale und kommt automatisch " - "zurueck, sobald sie wieder freigegeben wird.") - elif predecessor and predecessor["azure_id"] != user["azure_id"]: - msg += (f" Fuer {predecessor['display_name']} war kein eigenes Tuerschild gemerkt, " - "er ist jetzt ohne Zuordnung.") - return _zentrale_view(request, conn, target, extension=extension, user=user, message=msg) + predecessor["display_name"] if predecessor else "-") + return _zentrale_redirect(extension, "uebernommen") finally: conn.close() -@app.post("/api/zentrale/verlassen", response_class=HTMLResponse) -async def zentrale_release(request: Request, extension: str = Form(...)): +@app.post("/api/zentrale/verlassen") +async def zentrale_release(extension: str = Form(...)): """Mitarbeiter verlaesst die Zentrale und geht auf sein Heimat-Tuerschild zurueck.""" conn = database.get_db() try: target = _selfservice_target(conn) user = _user_by_extension(extension, conn) if not user: - return _zentrale_view(request, conn, target, extension=extension, - error=f"Durchwahl {extension} ist keinem aktiven Benutzer zugeordnet.") + return _zentrale_redirect(extension, "err_unbekannt") was_here = bool(target) and conn.execute(""" SELECT 1 FROM assignments @@ -829,8 +843,7 @@ async def zentrale_release(request: Request, extension: str = Form(...)): if not home: if not was_here: - return _zentrale_view(request, conn, target, extension=extension, user=user, - error="Es ist kein Heimat-Tuerschild gespeichert und du sitzt nicht auf der Zentrale.") + return _zentrale_redirect(extension, "err_nichts_zu_tun") # Nur von der Zentrale abmelden, es gibt keinen Platz zum Zurueckgehen conn.execute("DELETE FROM assignments WHERE user_azure_id = ?", (user["azure_id"],)) returning = _restore_zentrale_owner(conn, target) @@ -840,35 +853,21 @@ async def zentrale_release(request: Request, extension: str = Form(...)): target["hostname"], target["segment"], conn) else: scheduler.clear_segment(target["hostname"], target["segment"], conn) - logger.info("Zentrale verlassen von %s (kein Heimat-Tuerschild), zurueck auf der Zentrale: %s", + logger.info("Zentrale verlassen von %s (kein Heimat-Tuerschild), zurueck: %s", user["display_name"], returning["display_name"] if returning else "-") - msg = f"{user['display_name']} ist von der Zentrale abgemeldet. Ein eigenes Tuerschild war nicht gespeichert." - if returning: - msg += f" {returning['display_name']} sitzt wieder auf der Zentrale." - return _zentrale_view(request, conn, target, extension=extension, user=user, message=msg) + return _zentrale_redirect(extension, "abgemeldet") - # Der Stamm-Besetzer der Zentrale hat keinen anderen Platz, auf den er - # zurueckgehen koennte - sein Heimatplatz IST die Zentrale. + # Der Stamm-Besetzer hat keinen anderen Platz - sein Heimatplatz IST die Zentrale if target and (home["wled_device_id"], home["segment"]) == (target["id"], target["segment"]): - if was_here: - return _zentrale_view(request, conn, target, extension=extension, user=user, - message=("Die Zentrale ist dein eigener Platz - du sitzt schon dort. " - "Es gibt nichts zurueckzusetzen.")) - return _zentrale_view(request, conn, target, extension=extension, user=user, - error=("Die Zentrale ist dein eigener Platz, aktuell hat sie jemand anderes. " - "Mit \"Zentrale uebernehmen\" holst du sie zurueck.")) + return _zentrale_redirect(extension, "stammplatz_hier" if was_here else "err_stammplatz_fremd") # Ist der Heimatplatz inzwischen von jemand anderem belegt? blocker = conn.execute(""" - SELECT u.display_name - FROM assignments a JOIN users u ON u.azure_id = a.user_azure_id - WHERE a.wled_device_id = ? AND a.segment = ? AND a.user_azure_id != ? + SELECT 1 FROM assignments + WHERE wled_device_id = ? AND segment = ? AND user_azure_id != ? """, (home["wled_device_id"], home["segment"], user["azure_id"])).fetchone() if blocker: - return _zentrale_view(request, conn, target, extension=extension, user=user, - error=(f"Das eigene Tuerschild ({home['name'] or home['hostname']}, Segment {home['segment']}) " - f"ist inzwischen {blocker['display_name']} zugeordnet. " - "Bitte den Administrator ansprechen - es wurde nichts geaendert.")) + return _zentrale_redirect(extension, "err_heimat_belegt") conn.execute("DELETE FROM assignments WHERE user_azure_id = ?", (user["azure_id"],)) conn.execute(""" @@ -892,12 +891,7 @@ async def zentrale_release(request: Request, extension: str = Form(...)): logger.info("Zentrale verlassen von %s, zurueck auf %s Segment %s; Zentrale nun: %s", user["display_name"], home["hostname"], home["segment"], returning["display_name"] if returning else "frei") - - msg = (f"{user['display_name']} ist zurueck auf dem eigenen Tuerschild " - f"({home['name'] or home['hostname']}, Segment {home['segment']}).") - if returning: - msg += f" {returning['display_name']} sitzt wieder auf der Zentrale." - return _zentrale_view(request, conn, target, extension=extension, user=user, message=msg) + return _zentrale_redirect(extension, "zurueck") finally: conn.close() diff --git a/templates/zentrale.html b/templates/zentrale.html index bebf7e4..46b10d2 100644 --- a/templates/zentrale.html +++ b/templates/zentrale.html @@ -8,118 +8,199 @@ -
-
-
-
-
-
- Logo -
Zentrale besetzen
-
+
+
+
+
+
- {% if message %} -
- {{ message }} -
- {% endif %} - - {% if error %} -
- {{ error }} -
- {% endif %} - - {% if not target %} -
- - - Die Zentrale ist noch nicht eingerichtet. Unter - Einstellungen > Zentrale muss ein Busylight - und ein Segment ausgewaehlt werden. - -
- {% else %} - -
-
-
- Busylight der Zentrale - {{ target.name }} - (Segment {{ target.segment }}) -
-
-
- Aktuell besetzt von - {% if occupant %} - {{ occupant }} - {% else %} - niemand - {% endif %} -
- - {% if user %} -
- Durchwahl {{ user.phone_extension }} - {{ user.display_name }} -
- - {% if is_here %} -
- Du sitzt derzeit auf der Zentrale. -
- {% endif %} - -
- - -
- -
- - -
- - {% if home %} -
- - Gemerktes Tuerschild: {{ home.name or home.hostname }} (Segment {{ home.segment }}) - -
- {% endif %} - - - {% else %} -
-
- - - - Damit wird die eigene Person auf das Busylight der Zentrale gesetzt. - -
- -
- {% endif %} - {% endif %} - -
- © cynfo GmbH -
-
-
-
-
+
+ Logo +
Zentrale besetzen
+ + {# ── Rueckmeldung der letzten Aktion ───────────────────────────────── #} + {% if done == 'uebernommen' %} +
+ Du sitzt jetzt auf der Zentrale.
+ {% elif done == 'bereits' %} +
+ Du warst schon auf der Zentrale eingetragen. Das Licht wurde neu gesetzt.
+ {% elif done == 'zurueck' %} +
+ Zurueck auf dem eigenen Tuerschild.
+ {% elif done == 'abgemeldet' %} +
+ Von der Zentrale abgemeldet.
+ {% elif done == 'stammplatz_hier' %} +
+ Die Zentrale ist dein eigener Platz - es gibt nichts zurueckzusetzen.
+ {% elif done == 'err_unbekannt' %} +
+ Die Durchwahl {{ extension }} ist keinem aktiven Benutzer zugeordnet.
+ {% elif done == 'err_nicht_eingerichtet' %} +
+ Die Zentrale ist noch nicht eingerichtet.
+ {% elif done == 'err_heimat_belegt' %} +
+ Dein eigenes Tuerschild ist inzwischen + {%- if home_blocker %} {{ home_blocker }}{% else %} jemand anderem{% endif %} zugeordnet. + Es wurde nichts geaendert - bitte den Administrator ansprechen.
+ {% elif done == 'err_nichts_zu_tun' %} +
+ Du sitzt nicht auf der Zentrale und es ist kein eigenes Tuerschild gemerkt.
+ {% elif done == 'err_stammplatz_fremd' %} +
+ Die Zentrale ist dein eigener Platz, aktuell hat sie jemand anderes. + Mit "Zentrale uebernehmen" holst du sie zurueck.
+ {% endif %} + + {% if not target %} +
+ + Die Zentrale ist noch nicht eingerichtet. Unter + Einstellungen > Zentrale muss ein Busylight und ein + Segment ausgewaehlt werden. +
+ {% else %} + + {# ── Zustand der Zentrale, immer sichtbar ──────────────────────────── #} +
+ Busylight der Zentrale + {{ target.name }} + (Segment {{ target.segment }}) +
+ {% if occupant %} + Aktuell besetzt von + + {{ occupant.display_name }} + {%- if is_here %} das bist du{% endif %} + + {% if occupant_is_owner %} +
Das ist der Stammplatz dieser Person.
+ {% endif %} + {% else %} + Aktuell besetzt von + niemand - die Zentrale ist frei + {% endif %} + {% if owner_waiting %} +
+ + {{ owner_waiting }} gehoert auf die Zentrale und kommt automatisch zurueck, + sobald sie freigegeben wird. +
+ {% endif %} +
+ + {% if not user %} + {# ── Schritt 1: Wer bist du? ──────────────────────────────────── #} +
+
+ + + + Im naechsten Schritt siehst du, was du tun kannst - es wird noch nichts geaendert. + +
+ +
+ {% else %} + {# ── Schritt 2: Zustand und passende Aktionen ──────────────────── #} +
+ 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, + danach kommst du automatisch zurueck. +
+ + {% elif is_here %} +
+ + Du sitzt aktuell auf der Zentrale. + {% if home %} + Dein eigenes Tuerschild ({{ home.name or home.hostname }}, Segment {{ home.segment }}) + ist bis zur Rueckkehr ausgeschaltet. + {% endif %} + +
+
+ + +
+ {% if home_blocker %} +
+ + Achtung: dein Tuerschild ist derzeit {{ home_blocker }} zugeordnet. + Die Rueckkehr wird abgelehnt, solange das so ist. +
+ {% endif %} + + {% else %} +
+ + + + {% if occupant and occupant_is_owner %} + {{ occupant.display_name }} gehoert auf die Zentrale und kommt automatisch + zurueck, sobald du sie wieder freigibst. + {% elif occupant %} + {{ occupant.display_name }} wird dabei auf das eigene Tuerschild zurueckgesetzt. + {% else %} + Die Zentrale ist frei. + {% endif %} + +
+ + {% if home %} +
+ + + + Gemerkt: {{ home.name or home.hostname }}, Segment {{ home.segment }}. + +
+ {% endif %} + {% endif %} + + +
+ + Diese Seite als Lesezeichen: /zentrale/{{ user.phone_extension }} + +
+ {% endif %} + {% endif %} + +
+ © cynfo GmbH +
+ +
+
+
+
+