docs: rewrite README with Azure setup guide and troubleshooting
Also improve dashboard to show 'Warte auf Status...' instead of gray bars when user is assigned but no polling result exists yet. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4e659000f7
commit
ce19dec8c1
194
README.md
194
README.md
@ -2,24 +2,24 @@
|
|||||||
|
|
||||||
Web-Anwendung zur Steuerung von WLED-Busylights basierend auf Microsoft Teams Presence-Status und AIDA-Zeiterfassung.
|
Web-Anwendung zur Steuerung von WLED-Busylights basierend auf Microsoft Teams Presence-Status und AIDA-Zeiterfassung.
|
||||||
|
|
||||||
Jedes WLED-Gerät verfügt über zwei Segmente (oben/unten), die jeweils einem Benutzer zugeordnet werden. Die Farbe des Segments wird automatisch anhand des Anwesenheitsstatus (AIDA) und des Teams-Status gesetzt.
|
Jedes WLED-Geraet verfuegt ueber zwei Segmente (oben/unten), die jeweils einem Benutzer zugeordnet werden. Die Farbe des Segments wird automatisch anhand des Anwesenheitsstatus (AIDA) und des Teams-Status gesetzt.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Dashboard** mit Echtzeit-Übersicht aller Busylights und deren aktuellem Status
|
- **Dashboard** mit Echtzeit-Uebersicht aller Busylights und deren aktuellem Status
|
||||||
- **Benutzer-Verwaltung** mit automatischem Sync aus Azure AD
|
- **Benutzer-Verwaltung** mit automatischem Sync aus Azure AD
|
||||||
- **WLED-Geräte** hinzufügen, bearbeiten und entfernen
|
- **WLED-Geraete** hinzufuegen, bearbeiten, entfernen und Live-Status pruefen (online/offline, LED-Anzahl, Firmware-Version)
|
||||||
- **Zuordnung** von Benutzern zu WLED-Segmenten per Dropdown (statt UUID-Mapping in einer Config-Datei)
|
- **Zuordnung** von Benutzern zu WLED-Segmenten per Dropdown (statt UUID-Mapping in einer Config-Datei)
|
||||||
- **Farb-Regeln** mit Color-Picker für jeden Teams-/Anwesenheitsstatus
|
- **Farb-Regeln** mit Color-Picker fuer jeden Teams-/Anwesenheitsstatus
|
||||||
- **Einstellungen** für Azure AD, Polling-Intervall und AIDA-CSV-Pfad
|
- **Einstellungen** fuer Azure AD, Polling-Intervall und AIDA-CSV-Pfad
|
||||||
- **Protokoll** der letzten Statusänderungen
|
- **Protokoll** der letzten Statusaenderungen
|
||||||
|
|
||||||
## Voraussetzungen
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Linux-Server (Debian 12+/Ubuntu 22.04+)
|
||||||
- Python 3.10+
|
- Python 3.10+
|
||||||
- Netzwerkzugriff auf die WLED-Geräte (HTTP)
|
- Netzwerkzugriff auf die WLED-Geraete (HTTP Port 80)
|
||||||
- Azure AD App-Registrierung mit folgenden Berechtigungen:
|
- Azure AD App-Registrierung (siehe unten)
|
||||||
- `User.Read`, `User.Read.All`, `Presence.Read`, `Presence.Read.All`
|
|
||||||
- Zugriff auf die AIDA-Zeiterfassungs-CSV (lokal oder per SMB-Mount)
|
- Zugriff auf die AIDA-Zeiterfassungs-CSV (lokal oder per SMB-Mount)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@ -33,40 +33,105 @@ cd /opt/busylight
|
|||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
|
|
||||||
# Abhängigkeiten installieren
|
# Abhaengigkeiten installieren
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Azure AD einrichten
|
||||||
|
|
||||||
|
### 1. App-Registrierung erstellen
|
||||||
|
|
||||||
|
1. Azure Portal oeffnen: https://portal.azure.com
|
||||||
|
2. **Azure Active Directory** -> **App-Registrierungen** -> **Neue Registrierung**
|
||||||
|
3. Einstellungen:
|
||||||
|
- **Name**: `Busylight Web` (oder beliebig)
|
||||||
|
- **Unterstuetzte Kontotypen**: Nur Konten in diesem Organisationsverzeichnis
|
||||||
|
- **Umleitungs-URI**: leer lassen
|
||||||
|
4. **Registrieren** klicken
|
||||||
|
|
||||||
|
### 2. Oeffentliche Clientflows aktivieren
|
||||||
|
|
||||||
|
1. In der erstellten App-Registrierung: **Authentifizierung** (linkes Menue)
|
||||||
|
2. Ganz unten: **Erweiterte Einstellungen**
|
||||||
|
3. **Oeffentliche Clientflows zulassen** -> **Ja**
|
||||||
|
4. **Speichern**
|
||||||
|
|
||||||
|
### 3. API-Berechtigungen setzen
|
||||||
|
|
||||||
|
1. **API-Berechtigungen** -> **Berechtigung hinzufuegen** -> **Microsoft Graph**
|
||||||
|
2. **Delegierte Berechtigungen** waehlen
|
||||||
|
3. Folgende Berechtigungen hinzufuegen:
|
||||||
|
- `User.Read`
|
||||||
|
- `User.Read.All`
|
||||||
|
- `Presence.Read`
|
||||||
|
- `Presence.Read.All`
|
||||||
|
4. **Administratorzustimmung erteilen** klicken
|
||||||
|
|
||||||
|
### 4. IDs notieren
|
||||||
|
|
||||||
|
Von der Uebersichtsseite der App-Registrierung:
|
||||||
|
- **Anwendungs-ID (Client)** -> das ist die `Client ID`
|
||||||
|
- **Verzeichnis-ID (Mandant)** -> das ist die `Tenant ID`
|
||||||
|
|
||||||
|
### 5. Credentials in Busylight eintragen
|
||||||
|
|
||||||
|
Entweder ueber das Web-Interface unter **Einstellungen**, oder per CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/busylight && source venv/bin/activate
|
||||||
|
python -c "
|
||||||
|
from database import init_db, set_setting
|
||||||
|
init_db()
|
||||||
|
set_setting('azure_client_id', 'DEINE-CLIENT-ID')
|
||||||
|
set_setting('azure_tenant_id', 'DEINE-TENANT-ID')
|
||||||
|
set_setting('azure_auth_tenant', 'DEINE-TENANT-ID')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Azure Authentifizierung durchfuehren
|
||||||
|
|
||||||
|
Die Authentifizierung erfolgt einmalig ueber den Device-Code-Flow im Terminal.
|
||||||
|
Um den Device-Code sauber angezeigt zu bekommen (ohne Azure-Debug-Logs):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/busylight && source venv/bin/activate
|
||||||
|
python -W ignore -c "
|
||||||
|
import logging
|
||||||
|
logging.getLogger('azure').setLevel(logging.WARNING)
|
||||||
|
from app import cli_auth
|
||||||
|
cli_auth()
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
Es wird ein Code angezeigt, z.B.:
|
||||||
|
|
||||||
|
```
|
||||||
|
To sign in, use a web browser to open the page https://microsoft.com/devicelogin
|
||||||
|
and enter the code LW5ZR5BFC to authenticate.
|
||||||
|
```
|
||||||
|
|
||||||
|
Diesen Code im Browser eingeben und mit einem Azure-AD-Konto anmelden.
|
||||||
|
Nach erfolgreicher Anmeldung wird das Token in der Datenbank gespeichert und automatisch erneuert.
|
||||||
|
|
||||||
## Migration von der alten config.cfg
|
## Migration von der alten config.cfg
|
||||||
|
|
||||||
Falls das System vorher mit dem alten Python-Script und `config.cfg` betrieben wurde, können alle Daten (User, Geräte, Segmente, Farben, Azure-Credentials) automatisch importiert werden:
|
Falls das System vorher mit dem alten Python-Script und `config.cfg` betrieben wurde,
|
||||||
|
koennen alle Daten (User, Geraete, Segmente, Farben) automatisch importiert werden:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# config.cfg ins Projektverzeichnis kopieren
|
# config.cfg ins Projektverzeichnis kopieren
|
||||||
cp /pfad/zur/alten/config.cfg .
|
cp /pfad/zur/alten/config.cfg .
|
||||||
|
|
||||||
# Migration ausführen
|
# Migration ausfuehren
|
||||||
python migrate.py
|
python migrate.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Die alte `config.cfg` wird danach nicht mehr benötigt.
|
Die alte `config.cfg` wird danach nicht mehr benoetigt.
|
||||||
|
|
||||||
## Azure Authentifizierung
|
|
||||||
|
|
||||||
Die Authentifizierung gegen Microsoft Graph erfolgt einmalig über den Device-Code-Flow im Terminal:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
source venv/bin/activate
|
|
||||||
python app.py --auth
|
|
||||||
```
|
|
||||||
|
|
||||||
Es wird ein Code angezeigt, der unter https://microsoft.com/devicelogin eingegeben werden muss. Nach erfolgreicher Anmeldung wird das Token in der Datenbank gespeichert und automatisch erneuert.
|
|
||||||
|
|
||||||
## AIDA-CSV auf Linux bereitstellen
|
## AIDA-CSV auf Linux bereitstellen
|
||||||
|
|
||||||
Die Zeiterfassungs-CSV liegt typischerweise auf einem Windows-Server. Für den Zugriff von Linux gibt es mehrere Möglichkeiten:
|
Die Zeiterfassungs-CSV liegt typischerweise auf einem Windows-Server.
|
||||||
|
Fuer den Zugriff von Linux empfiehlt sich ein SMB/CIFS-Mount:
|
||||||
### Option A: SMB/CIFS-Mount (empfohlen)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Paket installieren
|
# Paket installieren
|
||||||
@ -75,9 +140,6 @@ sudo apt install cifs-utils
|
|||||||
# Mount-Punkt erstellen
|
# Mount-Punkt erstellen
|
||||||
sudo mkdir -p /mnt/zeiterfassung
|
sudo mkdir -p /mnt/zeiterfassung
|
||||||
|
|
||||||
# Eintrag in /etc/fstab
|
|
||||||
# //SERVERNAME/Zeiterfassung /mnt/zeiterfassung cifs credentials=/etc/samba/creds,uid=busylight,gid=busylight,ro 0 0
|
|
||||||
|
|
||||||
# Credentials-Datei erstellen
|
# Credentials-Datei erstellen
|
||||||
sudo bash -c 'cat > /etc/samba/creds << EOF
|
sudo bash -c 'cat > /etc/samba/creds << EOF
|
||||||
username=DOMAIN\user
|
username=DOMAIN\user
|
||||||
@ -85,6 +147,9 @@ password=geheim
|
|||||||
EOF'
|
EOF'
|
||||||
sudo chmod 600 /etc/samba/creds
|
sudo chmod 600 /etc/samba/creds
|
||||||
|
|
||||||
|
# Eintrag in /etc/fstab (eine Zeile)
|
||||||
|
# //SERVERNAME/Zeiterfassung /mnt/zeiterfassung cifs credentials=/etc/samba/creds,uid=busylight,gid=busylight,ro 0 0
|
||||||
|
|
||||||
# Mounten
|
# Mounten
|
||||||
sudo mount /mnt/zeiterfassung
|
sudo mount /mnt/zeiterfassung
|
||||||
```
|
```
|
||||||
@ -94,20 +159,19 @@ In den Web-Einstellungen dann als CSV-Pfad eintragen:
|
|||||||
/mnt/zeiterfassung/Aida/profiles/aida/Transfer/Export/Status.csv
|
/mnt/zeiterfassung/Aida/profiles/aida/Transfer/Export/Status.csv
|
||||||
```
|
```
|
||||||
|
|
||||||
### Option B: Regelmäßiger Kopiervorgang
|
Alternativ: Per Cronjob die CSV regelmaessig per `scp` oder `rsync` kopieren.
|
||||||
|
|
||||||
Per Cronjob die CSV regelmäßig auf den Linux-Server kopieren (z.B. via `scp` oder `rsync`).
|
|
||||||
|
|
||||||
## Starten
|
## Starten
|
||||||
|
|
||||||
### Manuell (zum Testen)
|
### Manuell (zum Testen)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
cd /opt/busylight
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
python app.py
|
python app.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Web-Oberfläche ist dann erreichbar unter: **http://localhost:8080**
|
Die Web-Oberflaeche ist dann erreichbar unter: **http://SERVER-IP:8080**
|
||||||
|
|
||||||
### Als systemd-Service (Produktivbetrieb)
|
### Als systemd-Service (Produktivbetrieb)
|
||||||
|
|
||||||
@ -121,7 +185,7 @@ sudo cp busylight.service /etc/systemd/system/
|
|||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable --now busylight
|
sudo systemctl enable --now busylight
|
||||||
|
|
||||||
# Status prüfen
|
# Status pruefen
|
||||||
sudo systemctl status busylight
|
sudo systemctl status busylight
|
||||||
|
|
||||||
# Logs anzeigen
|
# Logs anzeigen
|
||||||
@ -132,48 +196,56 @@ sudo journalctl -u busylight -f
|
|||||||
|
|
||||||
### 1. Einstellungen konfigurieren
|
### 1. Einstellungen konfigurieren
|
||||||
|
|
||||||
Unter **Einstellungen** die Azure AD Credentials (Client ID, Client Secret, Tenant ID) und den CSV-Pfad eintragen.
|
Unter **Einstellungen** die Azure AD Credentials (Client ID, Tenant ID) und den AIDA-CSV-Pfad eintragen.
|
||||||
|
|
||||||
### 2. Benutzer synchronisieren
|
### 2. Benutzer synchronisieren
|
||||||
|
|
||||||
Unter **Benutzer** auf „Aus Azure synchronisieren" klicken. Alle Azure AD Benutzer werden importiert. Anschließend:
|
Unter **Benutzer** auf "Aus Azure synchronisieren" klicken. Alle Azure AD Benutzer werden importiert. Anschliessend:
|
||||||
- Benutzer aktivieren/deaktivieren (nur aktive Benutzer werden abgefragt)
|
- Benutzer aktivieren/deaktivieren (nur aktive Benutzer werden abgefragt)
|
||||||
- AIDA-Personalnummer zuordnen (Format: `~~00341~~`)
|
- AIDA-Personalnummer zuordnen (Format: `~~00341~~`)
|
||||||
|
|
||||||
### 3. WLED-Geräte anlegen
|
### 3. WLED-Geraete anlegen
|
||||||
|
|
||||||
Unter **WLED-Geräte** die Hostnamen/IP-Adressen der WLED-Busylights eintragen und die Anzahl der Segmente festlegen (Standard: 2).
|
Unter **WLED-Geraete** die Hostnamen/IP-Adressen der WLED-Busylights eintragen.
|
||||||
|
Die Seite zeigt automatisch den Online-Status, LED-Anzahl und Firmware-Version jedes Geraets an.
|
||||||
|
|
||||||
### 4. Zuordnungen erstellen
|
### 4. Zuordnungen erstellen
|
||||||
|
|
||||||
Unter **Zuordnungen** jeden aktiven Benutzer einem WLED-Gerät und Segment zuweisen:
|
Unter **Zuordnungen** jeden aktiven Benutzer einem WLED-Geraet und Segment zuweisen:
|
||||||
- Segment 0 = oben
|
- Segment 0 = oben
|
||||||
- Segment 1 = unten
|
- Segment 1 = unten
|
||||||
|
|
||||||
### 5. Farben anpassen
|
### 5. Farben anpassen
|
||||||
|
|
||||||
Unter **Farb-Regeln** die Farben für jeden Status per Color-Picker anpassen:
|
Unter **Farb-Regeln** die Farben fuer jeden Status per Color-Picker anpassen:
|
||||||
|
|
||||||
| Status | Beschreibung |
|
| Status | Beschreibung |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `abwesend` | Benutzer laut AIDA nicht anwesend |
|
| `abwesend` | Benutzer laut AIDA nicht anwesend |
|
||||||
| `homeoffice` | Benutzer im Homeoffice |
|
| `homeoffice` | Benutzer im Homeoffice |
|
||||||
| `teams_available` | Teams: Verfügbar |
|
| `teams_available` | Teams: Verfuegbar |
|
||||||
| `teams_busy` | Teams: Beschäftigt |
|
| `teams_busy` | Teams: Beschaeftigt |
|
||||||
| `teams_donotdisturb` | Teams: Nicht stören |
|
| `teams_donotdisturb` | Teams: Nicht stoeren |
|
||||||
| `teams_inacall` | Teams: In einem Anruf |
|
| `teams_inacall` | Teams: In einem Anruf |
|
||||||
| `teams_inameeting` | Teams: In einer Besprechung |
|
| `teams_inameeting` | Teams: In einer Besprechung |
|
||||||
| `teams_presenting` | Teams: Präsentiert |
|
| `teams_presenting` | Teams: Praesentiert |
|
||||||
| `teams_away` | Teams: Abwesend |
|
| `teams_away` | Teams: Abwesend |
|
||||||
| `teams_offline` | Teams: Offline |
|
| `teams_offline` | Teams: Offline |
|
||||||
|
| `teams_outofoffice` | Teams: Abwesend (ganztaegig) |
|
||||||
|
| `teams_inactive` | Teams: Inaktiv |
|
||||||
|
| `teams_offwork` | Teams: Nicht bei der Arbeit |
|
||||||
|
|
||||||
### 6. Dashboard
|
### 6. Dashboard
|
||||||
|
|
||||||
Das **Dashboard** zeigt alle Busylights mit dem aktuellen Status in Echtzeit an und aktualisiert sich automatisch alle 10 Sekunden.
|
Das **Dashboard** zeigt alle Busylights mit dem aktuellen Status in Echtzeit an und aktualisiert sich automatisch alle 10 Sekunden.
|
||||||
|
|
||||||
|
- Farbige Segmente = Status wurde erfolgreich abgefragt
|
||||||
|
- Graue Segmente mit "Warte auf Status..." = Zuordnung vorhanden, aber noch kein Polling-Ergebnis (z.B. AIDA-CSV nicht erreichbar)
|
||||||
|
- "Nicht zugeordnet" = kein Benutzer diesem Segment zugewiesen
|
||||||
|
|
||||||
### 7. Protokoll
|
### 7. Protokoll
|
||||||
|
|
||||||
Unter **Protokoll** werden die letzten 200 Statusänderungen mit Zeitstempel, WLED-URL und Ergebnis angezeigt.
|
Unter **Protokoll** werden die letzten 200 Statusaenderungen mit Zeitstempel, WLED-URL und Ergebnis angezeigt.
|
||||||
|
|
||||||
## Projektstruktur
|
## Projektstruktur
|
||||||
|
|
||||||
@ -183,27 +255,43 @@ busylight/
|
|||||||
├── database.py # SQLite Datenbank-Schema und Hilfsfunktionen
|
├── database.py # SQLite Datenbank-Schema und Hilfsfunktionen
|
||||||
├── graph_client.py # Microsoft Graph API Client
|
├── graph_client.py # Microsoft Graph API Client
|
||||||
├── wled_client.py # WLED HTTP API Client
|
├── wled_client.py # WLED HTTP API Client
|
||||||
├── scheduler.py # Hintergrund-Polling (AIDA + Teams → WLED)
|
├── scheduler.py # Hintergrund-Polling (AIDA + Teams -> WLED)
|
||||||
├── migrate.py # Import aus alter config.cfg
|
├── migrate.py # Import aus alter config.cfg
|
||||||
├── requirements.txt # Python-Abhängigkeiten
|
├── requirements.txt # Python-Abhaengigkeiten
|
||||||
├── busylight.service # systemd Service-Datei
|
├── busylight.service # systemd Service-Datei
|
||||||
├── static/
|
├── static/
|
||||||
│ └── style.css # CSS Styles
|
│ └── style.css # CSS Styles
|
||||||
└── templates/
|
└── templates/
|
||||||
├── base.html # Basis-Layout mit Sidebar
|
├── base.html # Basis-Layout mit Sidebar
|
||||||
├── dashboard.html # Status-Übersicht
|
├── dashboard.html # Status-Uebersicht
|
||||||
├── users.html # Benutzer-Verwaltung
|
├── users.html # Benutzer-Verwaltung
|
||||||
├── devices.html # WLED-Geräte-Verwaltung
|
├── devices.html # WLED-Geraete-Verwaltung
|
||||||
├── assignments.html # Zuordnungen User → Segment
|
├── assignments.html # Zuordnungen User -> Segment
|
||||||
├── colors.html # Farb-Regeln
|
├── colors.html # Farb-Regeln
|
||||||
├── settings.html # Einstellungen
|
├── settings.html # Einstellungen
|
||||||
└── log.html # Aktivitäts-Protokoll
|
└── log.html # Aktivitaets-Protokoll
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ports und Firewall
|
## Ports und Firewall
|
||||||
|
|
||||||
| Port | Richtung | Zweck |
|
| Port | Richtung | Zweck |
|
||||||
|------|----------|-------|
|
|------|----------|-------|
|
||||||
| 8080/tcp | Eingehend | Web-Oberfläche |
|
| 8080/tcp | Eingehend | Web-Oberflaeche |
|
||||||
| 80/tcp | Ausgehend | WLED HTTP API |
|
| 80/tcp | Ausgehend | WLED HTTP API |
|
||||||
| 443/tcp | Ausgehend | Microsoft Graph API |
|
| 443/tcp | Ausgehend | Microsoft Graph API |
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Dashboard zeigt nur graue Segmente
|
||||||
|
- AIDA-CSV-Pfad in den Einstellungen pruefen (muss auf dem Linux-Server erreichbar sein)
|
||||||
|
- Benutzer muessen aktiviert sein UND eine Personalnummer haben
|
||||||
|
- Zuordnung Benutzer -> WLED-Geraet + Segment muss vorhanden sein
|
||||||
|
|
||||||
|
### Azure Auth schlaegt fehl
|
||||||
|
- "Oeffentliche Clientflows zulassen" muss in der Azure App aktiviert sein
|
||||||
|
- Auth-Tenant muss die Tenant-ID sein (nicht "common"), wenn die App auf "Nur meine Organisation" steht
|
||||||
|
- Bei erneutem Auth: `python app.py --auth` loescht automatisch den alten Token
|
||||||
|
|
||||||
|
### WLED-Geraete offline
|
||||||
|
- Unter WLED-Geraete den Status pruefen (Wifi-Button)
|
||||||
|
- Netzwerkverbindung vom Linux-Server zu den WLED-Geraeten pruefen: `curl http://HOSTNAME/json/info`
|
||||||
|
|||||||
@ -38,11 +38,19 @@
|
|||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<small class="text-muted d-block mb-1">Segment {{ seg.index }}</small>
|
<small class="text-muted d-block mb-1">Segment {{ seg.index }}</small>
|
||||||
{% if seg.user %}
|
{% if seg.user %}
|
||||||
|
{% if seg.aida == '-' %}
|
||||||
|
<div class="segment-bar" style="background: #f0f0f0; border-color: #ccc;">
|
||||||
|
<span class="status-dot me-2" style="background: #ccc;"></span>
|
||||||
|
{{ seg.user }}
|
||||||
|
</div>
|
||||||
|
<small class="text-muted"><i class="bi bi-hourglass-split"></i> Warte auf Status...</small>
|
||||||
|
{% else %}
|
||||||
<div class="segment-bar" style="background: rgba({{ seg.r }}, {{ seg.g }}, {{ seg.b }}, 0.3); border-color: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});">
|
<div class="segment-bar" style="background: rgba({{ seg.r }}, {{ seg.g }}, {{ seg.b }}, 0.3); border-color: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});">
|
||||||
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
<span class="status-dot me-2" style="background: rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});"></span>
|
||||||
{{ seg.user }}
|
{{ seg.user }}
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted">{{ seg.aida }} / {{ seg.teams }}</small>
|
<small class="text-muted">{{ seg.aida }} / {{ seg.teams }}</small>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="segment-bar empty">
|
<div class="segment-bar empty">
|
||||||
<i class="bi bi-dash-circle me-2"></i> Nicht zugeordnet
|
<i class="bi bi-dash-circle me-2"></i> Nicht zugeordnet
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user