- caldav_client: del+add statt direkter Zuweisung bei VEVENT-Properties
(behebt "DTSTART MUST appear exactly once" Validierungsfehler)
- HA-Events als read-only behandeln (kein Bearbeiten/Löschen im Popup)
- [object Object] Toast behoben: HA-Events fallen nicht mehr in CalDAV-Pfad
- End-Datum passt sich automatisch an wenn Start geändert wird (Duration bleibt erhalten)
- Erstellen-Button nutzt den aktuell angesehenen Tag statt immer heute
- Monatsansicht: Einzelklick = Tag auswählen, Doppelklick = Tagesansicht, Rechtsklick = Kontextmenü
- CalDAV URL-Matching robuster (Normalisierung, Path-Fallback, calendar_id Parameter)
- iCal-Abo-Termine sind nicht mehr bearbeitbar (Read-Only-Schutz)
- Wiederkehrende Termine mit RRULE-Support (täglich/wöchentlich/monatlich/jährlich/benutzerdefiniert)
Home Assistant unterstützt keinen Password-Grant — deshalb kam immer
"Ungültige Anmeldedaten", egal was eingegeben wurde. Jetzt wird der
Nutzer nach demselben Muster wie bei Google zur HA-Login-Seite
weitergeleitet, meldet sich dort an und kommt zurück zu Calendarr.
Änderungen:
- Neuer POST /api/homeassistant/auth-url und GET /callback Endpoint
- Account speichert client_id für spätere Token-Refreshes
- Modal: "Benutzername/Passwort" → "Mit Home Assistant anmelden"
- Frontend behandelt ?ha_connected=1 / ?ha_error=... nach Rückkehr
- Version v1 → v2
- Backend gibt 400 statt 401 bei falschen HA-Credentials zurück, damit
der globale api.js-Logout-Handler nicht ausgelöst wird
- Null-Guard im JS nach api.post verhindert den "calendars of null"-Crash
- Radio-Buttons für Anmeldemethode nicht mehr in form-group, damit
input[type=radio] kein width:100% bekommt und sauber nebeneinander liegt
Ergänzt die HA-Integration um Password-Grant OAuth2: Nutzer können sich
nun wahlweise mit einem Long-Lived Token oder mit Benutzername/Passwort
anmelden. Access Tokens werden automatisch per Refresh-Token erneuert.
- Neue Integration: Home Assistant als Kalenderquelle via REST-API
(GET /api/calendars + GET /api/calendars/{entity_id})
- Authentifizierung per Long-Lived Access Token
- Neues Modal zum Verbinden (Name, URL, Token) mit Fehlerbehandlung
- Kalender einzeln aktivierbar/deaktivierbar, Farbe änderbar
- Ausgeblendete HA-Kalender in Einstellungen wiederherstellbar
- Sync- und Trennen-Buttons in den Einstellungen
- Bugfix: CalDAV- und Google-Kalender mit sidebar_hidden=true
liefern nun keine Events mehr im Kalender
Der Wochenkalender von Google hat locale-spezifische IDs
(z.B. de.german#weeknum@...) die nicht im alten exakten Set-Filter
gefangen wurden. Dadurch wurde er in die DB gespeichert und
verursachte beim Event-Abruf einen API-Fehler.
Da der try/except die gesamte Kalender-Schleife umschloss, wurden
bei einem einzigen fehlerhaften Kalender alle anderen Events ebenfalls
verloren — Ursache für keine Termine trotz korrektem Token.
- _is_system_calendar(): prüft jetzt auch 'weeknum' als Substring
- _sync_google_calendars(): bereinigt bereits gespeicherte System-Kalender
- get_google_events(): try/except ist jetzt pro Kalender, nicht global
Wenn der Access-Token eines Google-Accounts abläuft und der Refresh
fehlschlägt, wurde die leere Terminliste bisher still zurückgegeben
(kein Log, keine UI-Meldung). Jetzt wird der Fehler geloggt, an den
Aufrufer weitergegeben und als Toast-Meldung im Frontend angezeigt
("Token abgelaufen – bitte Konto trennen und neu verbinden").
Das Events-Endpoint gibt nun {events, errors} statt ein reines Array
zurück; das Frontend extrahiert die Events entsprechend.
- caldav_client: client.event() → caldav.Event() mit resource.load() für update/delete (DAVClient hat keine event()-Methode)
- Popup: Copy-Menü wird beim Öffnen eines neuen Events immer zurückgesetzt
- copyEventToCalendar: start/end via new Date().toISOString() normalisiert → verhindert 2h-Verschiebung bei Terminen ohne Timezone-Info
- #weekNum@group.v.calendar.google.com (Kalenderwochen) wird beim Google-
Sync, in der Kalenderliste und beim Event-Abruf übersprungen
- layoutEvents: fehlende `end`-Variable im zweiten Pass ergänzt; ohne sie
war die Bedingung immer false, sodass Spaltenanzahl überlappender Termine
falsch berechnet wurde und Termine sich visuell überdeckten
- Login: Benutzername wird case-insensitiv verglichen (func.lower auf beiden Seiten)
- Benutzer anlegen: Username wird immer lowercase gespeichert
- Einstellungen: Panels "Darstellung", "Ansicht & Raster" und "Ausgeblendete Kalender" zu einem einzigen Panel zusammengeführt
- App-Icon: Emoji 📅 durch plattformunabhängiges Inline-SVG ersetzt
- Copyright: white-space:nowrap + damit Zeile nie umbricht
- Einstellungen von Modal-Popup auf Vollbild-Seite mit Seitennavigation umgestellt
- Schriftkontrast (4 Stufen) und Linienkontrast (4 Stufen) pro Benutzer gespeichert
- Stundenhöhe (40/60/80/100px) in Wochen-/Tagesansicht per Einstellung steuerbar
- Kalenderwoche in Monats- und Wochenansicht grösser dargestellt
- CSS-Variable --hour-h für dynamische Zeitraster-Höhe in week.js und app.css
- Backend: neue Felder text_contrast, line_contrast, hour_height in UserSettings
- sidebar_hidden-Spalte zu calendars und google_calendars hinzugefügt
- Ausblenden-Button persistiert jetzt server-seitig (cross-device)
- Einblenden in Einstellungen schreibt sidebar_hidden=false zurück
- Sidebar: overflow-x hidden verhindert dass lange Namen den Button rausschieben
- GoogleCalendar-Modell hinzugefügt (pro Account, mit enabled/color/name)
- Kalender werden nach OAuth automatisch synchronisiert
- Sidebar zeigt individuelle Google-Kalender mit Checkbox, Farbpunkt und Ausblenden-Button
- Einstellungen: Google-Konten-Bereich mit Sync- und Trennen-Button
- Ausgeblendete Kalender-Liste zeigt auch Google-Kalender
- Event-Erstellung/Bearbeitung/Löschung nutzt GoogleCalendar-ID statt Account-ID
- Google OAuth2 Flow: Admin konfiguriert Client-ID/Secret, User verbindet per Klick
- Google Calendar API v3: Events lesen, erstellen, bearbeiten, löschen
- GoogleAccount Model + google_router mit Token-Refresh
- Google-Events in Event-Pipeline integriert
- Frontend: Google Kalender in Sidebar, Dropdown, Event-CRUD-Routing
- CalDAV-Kalender: Ausblenden statt ganzes Konto löschen, Einblenden in Einstellungen
- Ausgeblendete Kalender Sektion in Einstellungen
Neue Features:
- Lokale Kalender erstellen mit vollem Event-CRUD (in SQLite gespeichert)
- iCal-URLs abonnieren mit Auto-Refresh und lokalem Caching
- iCal-Events sind editierbar/löschbar (Änderungen als lokale Overrides)
- Sidebar zeigt alle 3 Kalendertypen mit Farbe, Umbenennen, Löschen
- Dropdown "Kalender hinzufügen" mit 3 Optionen (Lokal, CalDAV, iCal)
Backend: models.py (4 neue Tabellen), local_router.py, ical_router.py
Frontend: Neue Modals, erweiterte Sidebar, Source-basiertes Event-Routing