Master-Event eines Serientermins liegt oft vor dem sichtbaren Bereich -
das FullCalendar-RRULE-Plugin braucht ihn trotzdem zur Expansion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CalendarShare bekommt color-Spalte. Im Kalender-Menue kann jeder
Benutzer eine eigene Anzeigefarbe fuer einen mit ihm geteilten
Kalender setzen, ohne dass sich dadurch die Farbe beim
Eigentuemer oder anderen Share-Empfaengern aendert.
* Owner: Farbe aendert den Kalender direkt (wie bisher).
* Share-Empfaenger: Farbe landet in CalendarShare.color und wird
nur fuer ihn ausgeliefert (list_calendars injiziert sie in
'color', Owner-Farbe bleibt in 'owner_color' als Referenz).
Neuer Endpoint: PUT /calendars/<id>/my-color.
UI-Hinweis: "Nur fuer deine Ansicht - <Owner> behaelt seine Farbe".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
Neuer Event-Typ 'calendar' im Broadcaster. Wird bei Event-CRUD,
Serien-Ausnahmen, Freigaben hinzufuegen/entfernen und beim
Loeschen ganzer Kalender emittiert. Empfaenger: Eigentuemer +
alle User mit CalendarShare auf dem jeweiligen Kalender.
Frontend:
CalendarView oeffnet beim Mount eine EventSource zu
/api/sync/events und reloaded Kalenderliste + Events bei jedem
'calendar'-Event (300ms debounced). Damit sehen beteiligte
Nutzer Aenderungen in praktisch Echtzeit - kein F5 mehr noetig.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sharing-Fix:
Calendar-Model hatte keine owner-Relation zu User - list_calendars
stuerzte beim Listen geteilter Kalender ab (c.owner.username ->
AttributeError). Jetzt mit explizitem foreign_keys Relationship.
Benutzer-Autocomplete:
"Kalender teilen" nutzt jetzt /users/search wie bei Dateien.
Tippt man 2+ Zeichen, erscheint ein Dropdown mit passenden
Benutzernamen. Klick uebernimmt den Namen.
Bestehende Freigaben werden im Menue angezeigt mit Muelleimer
zum Entfernen.
Privat-Flag fuer Termine:
CalendarEvent bekommt is_private-Spalte. Checkbox im Termin-
Dialog "🔒 Privat (Teilnehmer sehen nur den Zeitblock)".
Redaction greift an drei Stellen:
* GET /events: Nicht-Owner sehen summary="Privat", description
und location = null. Zeitfenster bleibt voll sichtbar.
* iCal-Export (/ical/<token>): Privat-Events werden mit
CLASS:PRIVATE ausgegeben und SUMMARY/DESCRIPTION/LOCATION
werden gestrippt.
* CalDAV: aktuell werden eh nur eigene Kalender exportiert,
also keine Redaction noetig. Kommt bei Share-Support rein.
Der Eigentuemer sieht natuerlich in seiner eigenen Ansicht alle
Details seines privaten Termins.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Klick auf einen wiederkehrenden Termin oeffnet zuerst einen Dialog:
"Nur diesen Termin" oder "Ganze Serie".
* Serie: bearbeitet den Master wie bisher
* Nur dieser: fuegt EXDATE fuer das geklickte Datum zum Master
hinzu und legt einen eigenstaendigen Ersatz-Termin mit den
bearbeiteten Daten an
Backend:
* CalendarEvent.exdates speichert Ausnahmedaten kommasepariert
* POST /events/<id>/exception fuegt EXDATE hinzu, erstellt
optional das Replacement-Event mit frischer UID
* _build_vevent schreibt jetzt EXDATE-Zeilen in die ical_data,
sodass CalDAV-Clients die Ausnahmen auch sehen werden
Frontend:
* FullCalendar rrule-Plugin bekommt die exdate-Liste und blendet
die uebersprungenen Tage aus
* Drag & Drop verschiebt weiterhin die ganze Serie (Shortcut -
fuer Einzelverschiebung Termin anklicken und bearbeiten)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Automatische E-Mail-Benachrichtigungen ueber die konfigurierte
System-Email bei folgenden Ereignissen:
- Datei/Ordner mit Benutzer geteilt -> Empfaenger wird benachrichtigt
- Share-Link heruntergeladen -> Ersteller wird benachrichtigt (mit IP)
- Kalender mit Benutzer geteilt -> Empfaenger wird benachrichtigt
- Adressbuch mit Benutzer geteilt -> Empfaenger wird benachrichtigt
- Passwort-Eintrag/-Ordner geteilt -> Empfaenger wird benachrichtigt
- Admin erstellt neuen Benutzer -> Neuer Benutzer wird benachrichtigt
Alle Benachrichtigungen sind fail-safe (try/except), damit die
eigentliche Aktion nie durch Email-Fehler blockiert wird.
Emails werden nur gesendet wenn System-SMTP konfiguriert ist UND
der Empfaenger eine Email-Adresse hat.
Neuer Service: app/services/system_mail.py mit zentralem Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>