Commit Graph
36 Commits
Author SHA1 Message Date
Guido SchmitandClaude Opus 4.6 87ebc22d17 fix: Stufenförmige Monatsgrenze – auch waagerechte Linie unter Vormonats-Tagen
Die Trennlinie hat jetzt eine 'Stufen'-Form: unten unter den letzten
Tagen des Vormonats in derselben Zeile, dann links runter zum 1. des
neuen Monats, dann oben über die ersten Tage des neuen Monats.

So ist die Monatsgrenze visuell vollständig umrandet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-09 17:12:57 +02:00
Guido SchmitandClaude Opus 4.6 496d4e5745 fix: Monatswechsel-Markierung – Linien über Events, mehr Abstand, immer waagerecht
Vier Korrekturen:
- Linie verschwand hinter Events: Pseudo-Elemente mit z-index 4 statt
  box-shadow inset, damit Trennlinien immer über den Event-Bars liegen
- Waagerechte Linie auch bei Monatswechsel mitten in einer Zeile (vorher
  nur wenn der Monat am Zeilenanfang begann)
- "1" verschwand hinter Events: cell-day und month-marker bekommen
  z-index 3 + position relative, plus Events-Overlay wird in Zeilen mit
  Monatsmarker um ~26px nach unten geschoben
- Mehr Abstand zwischen Monatskürzel und Trennlinie (padding-top 8px,
  margin-bottom am marker positiv statt negativ)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-09 17:08:17 +02:00
Guido SchmitandClaude Opus 4.6 006c1f994c feat: Monatswechsel-Markierung in Monatsansicht
In der rolling Monatsansicht wird jetzt am Monatswechsel:
- eine dickere Trennlinie gezeichnet (links bei Wechsel mitten in Zeile,
  oben bei Zeilenstart)
- das 3-Buchstaben-Monatskürzel (z.B. JUL, AUG) groß über der "1"
  angezeigt

Beide Farben (Linie und Kürzel) sind in den Einstellungen unter
"Farben" individuell anpassbar (Default: #7090c0).

Backend: neue UserSettings-Felder month_divider_color und month_label_color
mit Migration. Frontend: applyTheme setzt entsprechende CSS-Variablen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-09 16:49:52 +02:00
Guido Schmit 23a18b0a20 fix: HA Update-Fallback auf delete+create wenn Integration nicht unterstützt
HA's Google-Calendar-Integration unterstützt kein calendar/event/update
und gibt 'not_supported: Calendar does not support event update' zurück.
In dem Fall wird jetzt automatisch der Termin gelöscht und neu erstellt
(beide Operationen werden von der Integration unterstützt). Der Termin
bekommt dabei eine neue UID, aber für den User sieht es wie ein Update aus.
2026-05-05 18:19:00 +02:00
Guido Schmit e7174770f3 fix: Ganztägig-Termine zeigen End-Datum jetzt korrekt inklusive
iCal speichert DTEND exklusiv (Tag NACH dem letzten Tag). Bisher
führte das dazu, dass ein Termin mit Ende=18.08 nur bis zum 17.08
angezeigt wurde, obwohl der User 18.08 als letzten Tag erwartete.
Fix: Im Date-Picker arbeiten wir jetzt mit inklusiven End-Daten
('endet am 18.08' = 18.08 ist letzter Tag) und konvertieren beim
Speichern auf exklusiv (DTEND=19.08). Beim Laden umgekehrt: -1 Tag
fürs Anzeigen im Picker.
Betrifft: openEditEventModal, openCopyEditModal, Save-Handler.
2026-05-05 18:16:56 +02:00
Guido Schmit c12f30cbbf feat: 'Vor dem Kopieren bearbeiten' Checkbox im Kopieren-Popup
Über der Kalenderliste im Kopieren-Menü gibt es jetzt eine Checkbox
'Vor dem Kopieren bearbeiten'. Wenn aktiviert und ein Ziel-Kalender
geklickt wird, öffnet sich der Termin-erstellen-Dialog mit allen
Daten des Quell-Termins vorausgefüllt (Titel, Datum, Ort, Beschreibung,
Farbe, Wiederholung) und dem Ziel-Kalender vorausgewählt.
2026-05-05 18:11:33 +02:00
Guido Schmit da74e8dc78 fix: Quell-Kalender wird beim Kopieren ausgeblendet
buildWritableCalendars excluded jetzt den Kalender, in dem das Event
bereits ist – so kann man nicht mehr in denselben Kalender kopieren.
2026-05-05 17:54:15 +02:00
Guido Schmit b1b08072e7 fix: Termine in unchecked Kalendern erstellen + HA-Kalender als Kopier-Ziel
- populateCalendarSelect: filtert jetzt nach !sidebar_hidden statt
  enabled. Unchecked (versteckte) Kalender bleiben so im
  Termin-erstellen-Dropdown verfügbar
- buildWritableCalendars: HA-Kalender werden als Kopier-Ziele aufgeführt
- copyEventToCalendar: routet HA-Ziele über /homeassistant/events
  Endpoint (vorher fielen sie in den CalDAV-Fallback)
2026-05-05 17:46:12 +02:00
Guido Schmit b961cf94ef fix: CalDAV-Events bekommen source-Feld – Kalenderfarbe-Patch wirkt sofort
CalDAV-Events hatten bisher kein source-Feld gesetzt. applyCalendarColor
filtert aber via ev.source !== 'caldav', sodass der Patch nie auf
CalDAV-Events angewendet wurde – die Farbe blieb sichtbar bis F5.
Jetzt wird source: 'caldav' beim Anreichern der Events gesetzt.
2026-04-29 20:27:31 +02:00
Guido Schmit dce9890bfa fix: Termin-Änderungen (Farbe, Titel, etc.) sofort ohne Reload anzeigen
Nach dem Speichern eines Termins wird das gecachte Event-Objekt
direkt in-place gepatcht und die View neu gerendert. Vorher war die
neue Farbe erst nach F5 sichtbar, weil zwar fetchAndRender(true)
aufgerufen wurde, aber der Render-Pfad das Update nicht zuverlässig
übernommen hat.
2026-04-29 20:22:34 +02:00
Guido Schmit 98870ccfb3 feat: HA-Events über WebSocket API (calendar/event/delete und update)
Manche HA-Integrationen registrieren nur den WebSocket-Handler, keinen
Service-Call. Die HA-Web-UI nutzt deshalb den WebSocket-Pfad. Calendarr
macht das jetzt auch:
- _ha_ws_call: minimaler WebSocket-Client für eine einzelne Command
- create: erst WS, dann Service-Call als Fallback
- update: nur WS (Service-Call existiert oft nicht)
- delete: nur WS (Service-Call existiert oft nicht)
Neue Dependency: websocket-client==1.8.0
2026-04-29 20:01:12 +02:00
Guido Schmit 1f010078d3 fix: HA Delete – mehrere Body-Formate ausprobieren
HA's Service-Call-Schema akzeptiert je nach Version verschiedene
Body-Shapes für entity_id. Wir probieren jetzt der Reihe nach:
1. entity_id als String
2. entity_id als Liste
3. target-Wrapper
Wenn alle fehlschlagen, klare Anweisung zum HA-Developer-Tools-Test.
2026-04-29 19:58:56 +02:00
Guido Schmit 80cde5aaee fix: HA Delete – Fallback auf REST DELETE und klarere Fehlermeldung
calendar.delete_event schlägt mit 400 fehl, wenn die HA-Integration
das Feature nicht unterstützt (z.B. Google-Calendar via HA hat nur
CREATE_EVENT, kein DELETE/UPDATE).
- Versucht erst Service-Call, dann REST DELETE als Fallback
- Bei 400 wird der User aufgeklärt, dass die Integration vermutlich
  kein Löschen unterstützt
2026-04-29 19:55:04 +02:00
Guido Schmit 0ea0a530f6 fix: HA Datetime-Format mit Timezone, leere Strings filtern, Debug-Logs
- _ha_format_dt: Parst ISO-Datetime zu datetime-Objekt, emittiert
  ohne Millisekunden, MIT Timezone-Offset. Vorher landeten Termine
  am falschen Datum, weil das Frontend UTC schickt aber wir die
  Timezone gestrippt haben → HA hat als lokale Zeit interpretiert
- Leere Strings werden nicht mehr in den Body aufgenommen (HA
  Validator könnte diese ablehnen)
- Logging in create/delete/update für besseres Debugging der HA-Calls
2026-04-29 19:50:52 +02:00
Guido Schmit 7047f55cf7 feat: HA-Termine erstellen über calendar.create_event Service
- POST /api/homeassistant/events Endpoint mit calendar.create_event
- Frontend: HA-Termine erstellen statt 'nicht unterstützt' Toast
- Datetime-Format an HA-Konvention angepasst:
  'YYYY-MM-DD HH:MM:SS' (Space-Separator, ohne Timezone)
- _ha_format_dt Helper für ISO → HA Datetime-Konvertierung
2026-04-29 19:07:02 +02:00
Guido Schmit d859e969d0 fix: HA-Event-Update Fallback auf delete+create
calendar.update_event existiert erst ab HA 2024.6. Wenn der Service
nicht verfügbar ist (400), wird stattdessen delete_event + create_event
verwendet. Funktioniert mit HA 2022.5+.
2026-04-29 18:54:33 +02:00
Guido Schmit f970276b91 fix: HA update_event – bessere Fehlermeldung mit JSON-Response-Details
Liest message-Feld aus HA JSON-Response und loggt den Request-Body
für Debugging
2026-04-29 18:52:32 +02:00
Guido Schmit 4964dcf7f3 fix: HA Service-Call Parameter-Format korrigiert
- update_event: start_date_time/end_date_time statt dtstart/dtend
- Ganztägig: start_date/end_date statt dtstart/dtend
- Datetime-Werte als ISO-String mit Timezone statt space-separated
- Bessere Fehlermeldungen: HA-Response-Body wird im Error angezeigt
2026-04-29 18:50:00 +02:00
Guido Schmit 86fa07d18c fix: HA-Events über Service-Call API statt nicht-existierender REST-Endpoints
PUT/DELETE /api/calendars/{entity_id}/{uid} existieren nicht in HA.
Stattdessen: POST /api/services/calendar/update_event und
POST /api/services/calendar/delete_event (HA 2023.x+)
2026-04-29 18:45:24 +02:00
Guido Schmit 59f53b5524 fix: HA-Event-Update URL-Encoding und Popup-Überlappung bei Lösch-Dialog
- HA Update/Delete: UID wird URL-encoded (@ → %40), Delete mit
  Fallback auf Service-Call API für ältere HA-Versionen
- Lösch-Dialog: Event-Popup wird geschlossen BEVOR der Bestätigungsdialog
  erscheint, kein Überlappen mehr
2026-04-29 18:38:43 +02:00
Guido Schmit e5265b3694 fix: HA-Events bearbeitbar, Selected≠Today Styling, Serien-Löschung
- HA-Events: Update/Delete-Endpoints via HA REST API implementiert
- HA read-only Guard entfernt, stattdessen korrekte API-Anbindung
- Selected-Day: Outline-Ring statt gefüllter Kreis (Today bleibt gefüllt)
- Serien-Löschung: RECURRENCE-ID aus CalDAV-Events erkennen, damit
  expandierte Serientermine als recurring markiert werden und der
  Lösch-Dialog Einzel-/Serienlöschung anbietet
2026-04-29 18:31:58 +02:00
Guido Schmit 3e204d3355 fix: CalDAV-Update DTSTART-Fehler und HA-Events read-only
- 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
2026-04-29 18:21:56 +02:00
Guido Schmit 1638c9f631 fix: Runde-2-Fixes – Monatsauswahl, CalDAV-Update, Lösch-Dialog, EXDATE
- Monatsansicht: selectedDate von currentDate getrennt, Klick verschiebt View nicht mehr
- Selected-Day Styling: weißer Text auf Primary-Hintergrund statt nur Textfarbe
- Kontextmenü: --bg-surface statt fehlendem --bg-card
- CalDAV Update/Delete: parent Calendar-Objekt übergeben (behebt NoneType-Fehler)
- HA-Kalender im Kalender-Selektor ergänzt
- Browser-confirm() durch styled Modal-Dialog ersetzt mit Serie/Einzeln-Option
- EXDATE-Support: einzelne Vorkommen wiederkehrender Termine löschen (lokal + CalDAV)
- Fehlende i18n-Keys für Lösch-Dialog ergänzt (DE + EN)
2026-04-29 18:13:12 +02:00
Guido Schmit 013fb3dbc2 feat: Datum-Validierung, Monatsauswahl, CalDAV-Fix, wiederkehrende Termine
- 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)
2026-04-29 17:49:03 +02:00
Guido Schmit 7f123de148 fix: Tint für mehrtägige Ganztags-Events korrekt via alldayLayout
Der bisherige multiDayAllDayEvs-Filter hatte einen Timezone-Fehler
bei der Datumsberechnung (UTC-Parsing vs. lokale Zeit in UTC+2).
Neue Lösung: das bereits korrekt arbeitende alldayLayout wird direkt
als Quelle verwendet. Items mit colEnd > colStart sind mehrtägig —
die Spaltenindizes aus dem Layout ergeben den Tint-Bereich exakt.
2026-04-08 22:24:05 +02:00
Guido Schmit a362ab21ae perf/fix: Kalender-Toggle ohne Ladescreen + Mehrfach-Tint als Verlauf
Ausblenden: Events werden sofort client-seitig aus dem Cache gefiltert
(calendar_id-Match), kein Netzwerkaufruf für die Ansicht nötig.
Einblenden: fetchAndRender(force, silent=true) überspringt showLoading(),
die aktuelle Ansicht bleibt sichtbar und wird nach dem Fetch aktualisiert.
Mehrere mehrtägige Events am selben Tag erzeugen jetzt einen vertikalen
Farbverlauf (linear-gradient) statt gestapelter Ebenen, bei denen nur
die letzte Farbe sichtbar war.
2026-04-08 22:14:08 +02:00
Guido Schmit 15c540bd25 fix: Kalender-Toggle sofort wirksam + Tint für mehrtägige Ganztags-Events
- fetchAndRender(true) beim Ein-/Ausblenden eines Kalenders erzwingt
  einen Neu-Abruf statt Cache-Treffer, damit die Änderung sofort sichtbar ist
- Tint-Berechnung in der Wochenansicht berücksichtigt jetzt auch
  mehrtägige Ganztags-Events (z.B. Urlaub), nicht nur mehrtägige
  Termin-Events — exclusive Enddaten werden dabei korrekt normalisiert
2026-04-08 21:59:41 +02:00
Guido Schmit f2da15784b fix: Wochenkalender-Filter und per-Kalender Fehlerbehandlung
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
2026-04-08 21:49:24 +02:00
Guido Schmit 62e7fa8be1 fix: Google-Token-Fehler wird sichtbar gemacht und dem User gemeldet
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.
2026-04-08 21:40:13 +02:00
Guido Schmit 3846af527a fix: Kalenderfarbe wird sofort ohne Reload aktualisiert
Statt nach Farbänderung den Cache zu invalidieren und neu zu laden,
wird calendarColor direkt in-place auf allen gecachten Events gepatcht
und dann nur renderView() aufgerufen. Kein Netzwerk-Request, sofortige
Darstellung der neuen Farbe.
2026-04-07 22:18:10 +02:00
Guido Schmit 59751349b7 perf: Sliding-window Cache — Hintergrund-Prefetch bei Cache-Randnähe
Wenn die aktuelle Ansicht weniger als 4 Wochen vom Cache-Rand entfernt
ist, werden im Hintergrund 8 weitere Wochen in diese Richtung geladen
und in den Cache gemergt. Der Cache wächst damit automatisch mit der
Navigation mit — kein sichtbarer Ladevorgang auch bei langen Sprüngen.
2026-04-07 22:09:11 +02:00
Guido Schmit bc93474f49 perf: Event cache mit ±8-Wochen-Puffer für schnelle Navigation
Beim ersten Laden wird ein Fenster von ±8 Wochen um die aktuelle
Ansicht geholt. Wochenweise Navigation trifft danach den Cache
sofort (kein Spinner, kein Netzwerk). Nach echten Datenänderungen
(Event speichern/löschen, Sync, Konto-Änderungen) wird der Cache
invalidiert und neu geladen.
2026-04-07 22:05:03 +02:00
Guido Schmit 62ac0162eb feat: Rolling 5-week month view with week-by-week scroll
Month view now shows 5 weeks starting from the week containing
currentDate (not fixed to month boundaries), enabling views like
"mid-April to mid-May". Prev/Next buttons jump 4 weeks; mouse
wheel scrolls 1 week at a time with 500ms debounce.
2026-04-07 21:58:51 +02:00
Guido Schmit 46f6765087 fix: Month scroll navigates by full month, not by week
Scrolling in month view was moving currentDate by 7 days, but the
grid always renders the complete month — so 4 scrolls were needed
before any visual change. Now each scroll step advances/retreats
by exactly one month (same as the prev/next buttons).
2026-04-07 21:51:15 +02:00
Guido Schmit e2f98520e2 fix: Month grid lines, scroll throttle, custom dark date/time picker
- Month view: Replaced day-strip+events-area with full-height column
  divs (.month-col) so borders extend the full row height and clicking
  anywhere in a day column (including below events) navigates to day view.
  Events overlay uses pointer-events:none (pass-through) while span bars
  and +N-more labels stay pointer-events:all.
- Scroll navigation: Changed wheel handler from 80ms debounce to 500ms
  leading-edge throttle — one navigation per trackpad gesture.
- Custom date/time picker (date-picker.js): Dark calendar grid with
  prev/next navigation, today/selected highlighting, and a CSS
  scroll-snap time scroller (hours 0-23, minutes 0-59) matching the
  app's primary color. Language-aware (month names, day headers via t()).
- Event modal datetime inputs replaced with hidden inputs + .dt-display
  click targets that open the custom picker. setDtValue() helper keeps
  hidden input and display label in sync.
2026-04-07 21:44:44 +02:00
Guido Schmit 94cbe4e7fb feat: Spanning event bars, wheel nav, dark datetime picker, segmented settings UI
- Month view: Multi-day events render as continuous Google Calendar-style
  spanning bars across days/weeks using a greedy lane-packing algorithm.
  Timed multi-day events no longer repeat per day.
- Mouse wheel / trackpad scrolls week-by-week in month view, day/week in
  other views (debounced, prevents default page scroll).
- datetime-local/date inputs now use color-scheme:dark so the native
  browser picker opens in dark mode; calendar icon styled to match.
- Contrast/hour-height selectors redesigned as connected segmented pill
  controls instead of individual tiles.
- Hidden calendars list gains proper padding and separator lines.
- "Google Konten" settings panel renamed "Konten" and expanded to show
  CalDAV, local calendars, iCal subscriptions, and Google accounts in
  one unified panel with sync/disconnect actions.
- New i18n keys added for accounts panel in both de and en.
2026-04-07 21:20:42 +02:00