Replaces single Apple CalDAV with generic multi-account CalDAV integration.
Features:
- Multiple CalDAV accounts (iCloud, Nextcloud, Radicale, Baikal)
- Per-account calendar selection via checkboxes
- Bidirectional sync (CalDAV ↔ Oikos)
- Optional outbound target selection per event
- Migration of existing Apple CalDAV data
Technical:
- New tables: caldav_accounts, caldav_calendar_selection
- New service: server/services/caldav-sync.js
- New API routes: /calendar/caldav/*
- Enhanced UI in Settings and Calendar event modal
- 7 new tests, all passing
Closes#90
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add CalDAV accounts card to Settings page with:
* List of configured accounts showing URL and last sync
* Expandable calendar list with enable/disable checkboxes
* Sync Now, Refresh Calendars, and Delete actions per account
* Add Account modal with name, URL, username, password fields
- Add CalDAV target selector to event modal:
* Dropdown showing local and all enabled CalDAV calendars
* Grouped by account using optgroups
* Pre-selects current target when editing events
* Includes target_caldav_account_id and target_caldav_calendar_url in save
- Add CalDAV component styles to settings.css:
* Account cards with header, meta, and action sections
* Expandable calendar details with checkboxes and color dots
* Empty state for no accounts
- Add missing i18n keys for calendar enable/disable, refresh, delete confirm
- Load CalDAV targets async when modal opens
- Admin-only access to account management
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add getCalendars() and updateCalendarSelection() to caldav-sync.js
- Add sync() function for bidirectional CalDAV synchronization
- Add getStatus() to report on all accounts and enabled calendars
- Add 8 new API routes to calendar.js for CalDAV account and calendar management
- All routes require admin role for security
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add createAccount, updateAccount, deleteAccount functions with validation, error handling, and logging. Implements Task 3 from the CalDAV multi-account spec.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove buildICS, escapeICS, unescapeICS imports - these will be
needed in Task 5 (Sync Functions), not in Task 2. Keep only the
4 functions specified in the Task 2 spec: parseICS, formatICSDate,
tzLocalToUTC, applyDuration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- caldav_accounts table for account credentials
- caldav_calendar_selection table for calendar selection
- Migrate Apple CalDAV data to caldav tables
- Add target_caldav_* columns to calendar_events
- Update external_source CHECK to include 'caldav'
- Update external_calendars.source CHECK to include 'caldav'
- Enhance migration runner to support function-based migrations
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Resolve sv.json conflict: take Swedish subcategory translations from
main and loan keys from PR branch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The PR changed dmy from dots to slashes, breaking existing users.
Revert dmy to dots (backward compat), add dmy_slash for DD/MM/YYYY.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Translates remaining English strings in sv.json and fills missing keys
(calendar/notes colors, emptyHint texts, shortcuts, navLabelOverdue,
photoOptional) across all 14 locale files.
Co-Authored-By: Andreas Olsson <olsson82@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Translates remaining English strings in sv.json (attachment, API tokens,
budget categories, backup, onboarding, offline banner).
Also adds missing keys (calendar/notes color names, emptyHint texts,
shortcut labels, tasks.navLabelOverdue, birthdays.photoOptional) to all
13 other locale files so every language is now complete against de.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also translate server error message to English and remove stale
comment from calendar.js catch block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes fixed:
- dashboard.css: remove `overflow: visible` from the "Admin Dashboard Layout"
block that overrode the earlier `overflow: clip`, letting child content escape
the dashboard container and cause layout overflow
- layout.css: replace `overflow-x: clip` with `overflow-x: hidden` on
.app-content so layout overflow is properly contained at the scroll
container level (clip only clips painting, not layout)
Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>