Root cause: loadCalDAVAccounts and loadCardDAVAccounts were defined
inside the render function but called from bindIcsEvents (outside render),
causing ReferenceError when accessing Settings page.
Changes:
- Move loadCalDAVAccounts and loadCardDAVAccounts to top-level functions
- Add user parameter to both functions (no longer in render scope)
- Update all recursive calls to pass user parameter
- Move initial load code from bindIcsEvents to render function
Fixes the "loadCalDAVAccounts is not defined" error in v0.47.0.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add support for customizable birthday reminders with preset offsets
(none, at time, 15min, 1h, 1d, 2d, 1w, 2w) and custom intervals.
Users can now configure when to be reminded of upcoming birthdays.
- Add migration 31: reminder_offset, reminder_custom_amount, reminder_custom_unit to birthdays table
- Update POST/PUT /birthdays routes to accept reminder fields
- Add getOffsetMinutes() helper in birthday service
- Update birthdayReminderAt() to calculate reminder time with offset
- Modify syncBirthdayReminder() to handle empty offset (no reminder)
- Add renderBirthdayReminderSection() UI component
- Move reminder-custom CSS from calendar.css to reminders.css
- Add protocol check to service worker (non-http protocol guard)
All translations already present in de.json.
Tests: 109 passing, 0 failing.
Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <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>
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>
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>
- Overlapping timed events in week/day views now render side-by-side using a column-layout algorithm
- Calendar events support optional file attachments (images, PDFs, documents up to 5 MB)
- Attachment images shown in event popup; other files as download links
- Birthday modal redesigned with photo/avatar side-by-side with name/date fields
- DB migration 27: adds attachment_name, attachment_mime, attachment_size, attachment_data columns to calendar_events
- Server-side MIME allowlist and size validation for attachments
- i18n: all 15 locales include new attachment keys (de properly translated)
Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace innerHTML with replaceChildren/insertAdjacentHTML in birthdays.js and calendar.js (hook compliance)
- Translate calendar attachment i18n keys to German in de.json
- Fix missing diacritical marks in pt.json attachment strings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
onSave(panel) is a setup hook, not a submit handler. Bind the form's
submit event inside it and call closeModal({ force: true }) on success.
Also add explicit submit/cancel buttons to the modal content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a pencil-icon edit button to each ICS subscription row. Clicking it
opens a modal to update name, color, and shared visibility via PATCH
/calendar/subscriptions/:id. Adds updatedToast i18n key to all 15 locales.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>