Backend fixes:
- Fix "this event only" EXDATE handling - ensure proper timezone conversion for exception dates
- Remove debug logging for cleaner production output
Frontend fixes:
- Add EXDATE timezone conversion in convert_utc_to_local function
- Fix event duplication when viewing weeks across month boundaries with deduplication logic
- Update CSS theme colors for context menus, recurrence options, and recurring edit modals
These changes ensure RFC 5545 compliance for recurring event exceptions and improve the user experience across different themes and calendar views.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove unused AlarmStorage module and all references
- Remove unused imports (AlarmAction, AlarmTrigger, VAlarm from backend)
- Remove unused ReminderType enum from event form types
- Remove unused methods from AlarmScheduler and NotificationManager
- Fix unnecessary mut on NotificationOptions
- Simplify alarm system initialization in app.rs
- Remove unused variable assignments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove emoji debug logs from event deduplication process
- Remove verbose RRULE consolidation logging
- Remove "found X events with title Y" spam logs
- Keep essential functionality intact
- Maintain clean production server logs
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major Features:
- Replace single ReminderType enum with Vec<VAlarm> throughout stack
- Add comprehensive alarm management UI with AlarmList and AddAlarmModal components
- Support relative (15min before, 2hrs after) and absolute (specific date/time) triggers
- Display reminder icons in both month and week calendar views
- RFC 5545 compliant VALARM implementation using calendar-models library
Frontend Changes:
- Create AlarmList component for displaying configured reminders
- Create AddAlarmModal with full alarm configuration (trigger, timing, description)
- Update RemindersTab to use new alarm management interface
- Replace old ReminderType dropdown with modern multi-alarm system
- Add reminder icons to event displays in month/week views
- Fix event title ellipsis behavior in week view with proper CSS constraints
Backend Changes:
- Update all request/response models to use Vec<VAlarm> instead of String
- Remove EventReminder conversion logic, pass VAlarms directly through
- Maintain RFC 5545 compliance for CalDAV server compatibility
UI/UX Improvements:
- Improved basic details tab layout (calendar/repeat side-by-side, All Day checkbox repositioned)
- Simplified reminder system to single notification type for user clarity
- Font Awesome icons throughout instead of emojis for consistency
- Clean modal styling with proper button padding and hover states
- Removed non-standard custom message fields for maximum CalDAV compatibility
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Root cause: Both frontend and backend were adding a day for all-day events:
- Frontend: Converts inclusive UI dates (9/22-9/25) to exclusive (9/22-9/26)
- Backend: Was incorrectly adding another day (9/22-9/27) causing display issues
Fixed by:
- Remove duplicate day addition in backend handlers (events.rs, series.rs)
- Keep frontend conversion for proper RFC 5545 compliance
- Add reverse conversion when loading events for editing
- Maintain user-friendly inclusive dates in UI while storing exclusive dates
Now properly handles: UI 9/22-9/25 ↔ Storage 9/22-9/26 (exclusive per spec)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add special handling for date-only format (%Y%m%d) in parse_datetime_with_tz
- Convert NaiveDate to midnight NaiveDateTime for all-day events
- Reorder all-day detection to occur before datetime parsing
- All-day events now properly display in calendar views
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add new context menu callback for singleton events to avoid series pipeline
- Implement complete RRULE construction with INTERVAL, COUNT, and UNTIL parameters
- Update frontend service methods to pass recurrence parameters correctly
- Add missing recurrence fields to backend UpdateEventRequest model
- Fix parameter ordering in frontend method calls
- Ensure singleton→series conversion uses single event pipeline initially
This resolves issues where converting singleton events to recurring series
would not respect recurrence interval (every N days), count (N occurrences),
or until date parameters.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Refactor VEvent to use NaiveDateTime for all date/time fields (dtstart, dtend, created, etc.)
- Add separate timezone ID fields (_tzid) for proper RFC 5545 compliance
- Update all handlers and services to work with naive local times
- Fix external calendar event conversion to handle new model structure
- Remove UTC conversions from frontend - backend now handles timezone conversion
- Update series operations to work with local time throughout the system
- Maintain compatibility with existing CalDAV servers and RFC 5545 specification
This major refactor simplifies timezone handling by treating all event times as local
until the final CalDAV conversion step, eliminating multiple conversion points that
caused timing inconsistencies.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix double timezone conversion in drag-and-drop that caused 4-hour time shifts
- Frontend now sends local times instead of UTC to backend for proper conversion
- Add missing timezone parameter to update_series method to fix recurring event updates
- Update both event modal and drag-and-drop paths to include timezone information
- Maintain RFC 5545 compliance with proper timezone conversion in backend
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Backend: Enhance CalDAV discovery to require at least one valid 207 response
- Backend: Fail authentication if no valid CalDAV endpoints are found
- Frontend: Add token verification on app startup to validate stored tokens
- Frontend: Clear invalid tokens when login fails or token verification fails
- Frontend: Prevent users with invalid tokens from accessing calendar page
This resolves the issue where invalid servers (like google.com) were incorrectly
accepted as valid CalDAV servers, and ensures proper authentication flow.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add UID-based deduplication to prefer recurring events over single events with same UID
- Implement RRULE-generated instance detection to filter duplicate occurrences
- Add title normalization for case-insensitive matching and consolidation
- Fix external calendar refresh button with proper error handling and loading states
- Update context menu for external events to show only "View Event Details" option
- Add comprehensive multi-pass deduplication: UID → title consolidation → RRULE filtering
This resolves issues where Outlook calendars showed duplicate events with same UID
but different RRULE states (e.g., "Dragster Stand Up" appearing both as recurring
and single events).
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The root cause was that drag operations sent naive local time to the backend,
which the backend interpreted using the SERVER's local timezone rather than
the USER's timezone. This caused different behavior between development and
production servers in different timezones.
**Frontend Changes:**
- Convert naive datetime from drag operations to UTC before sending to backend
- Use client-side Local timezone to properly convert user's intended times
- Handle DST transition edge cases with fallback logic
**Backend Changes:**
- Update parse_event_datetime to treat incoming times as UTC (no server timezone conversion)
- Update series handlers to expect UTC times from frontend
- Remove server-side Local timezone dependency for event parsing
**Result:**
- Consistent behavior across all server environments regardless of server timezone
- Drag operations now correctly preserve user's intended local times
- Fixes "4 hours too early" issue in production drag-and-drop operations
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhanced CalDAV datetime parsing to match the full timezone capabilities
of external calendar parsing, now supporting:
- Standard IANA timezone identifiers (America/Denver, Europe/London, etc.)
- Mozilla/Thunderbird timezone format (/mozilla.org/20070129_1/Europe/London)
- Windows timezone names (60+ global mappings from "Mountain Standard Time" to IANA)
- Timezone abbreviations (EST, PST, MST, CST)
- Timezone offset parsing (20231225T120000-0500, 2023-12-25T12:00:00-05:00)
- ISO datetime formats with UTC and offset notation
- Comprehensive global timezone coverage (North America, Europe, Asia, Australia, Africa, South America)
This ensures consistent timezone handling across both CalDAV client events
and external calendar imports, providing robust support for international users.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Events created in external CalDAV clients (like AgendaV) with timezone information
were showing incorrect times due to improper timezone handling. Fixed by:
- Enhanced datetime parser to extract TZID parameters from iCal properties
- Added proper timezone conversion from source timezone to UTC using chrono-tz
- Preserved full property strings with parameters during parsing
- Maintained backward compatibility with existing UTC format events
This resolves the issue where events created at 9 AM Mountain Time were
displaying as 5 AM instead of the correct 11 AM Eastern Time.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Google Calendar ICS files use UTC datetime format ending with 'Z' (e.g., 20250817T140000Z)
which was failing to parse with DateTime::parse_from_str. Fixed by detecting 'Z' suffix,
parsing as naive datetime, and converting to UTC with and_utc().
Also cleaned up debug logging and unused variable warnings.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements server-side database caching with 5-minute refresh intervals to
dramatically improve external calendar performance while keeping data fresh.
Backend changes:
- New external_calendar_cache table with ICS data storage
- Smart cache logic: serves from cache if < 5min old, fetches fresh otherwise
- Cache repository methods for get/update/clear operations
- Migration script for cache table creation
Frontend changes:
- 5-minute auto-refresh interval for background updates
- Manual refresh button (🔄) for each external calendar
- Last updated timestamps showing when each calendar was refreshed
- Centralized refresh function with proper cleanup on logout
Performance improvements:
- Initial load: instant from cache vs slow external HTTP requests
- Background updates: fresh data without user waiting
- Reduced external API calls: only when cache is stale
- Scalable: handles multiple external calendars efficiently
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Users can now toggle visibility of CalDAV calendars using checkboxes in
the sidebar, matching the behavior of external calendars. Events from
hidden calendars are automatically filtered out of the calendar view.
Changes:
- Add is_visible field to CalendarInfo (frontend & backend)
- Add visibility checkboxes to CalDAV calendar list items
- Implement real-time event filtering based on calendar visibility
- Add CSS styling matching external calendar checkboxes
- Default new calendars to visible state
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive Windows timezone support for global external calendars
- Map Windows timezone names (e.g. "Mountain Standard Time") to IANA zones (e.g. "America/Denver")
- Support 60+ timezone mappings across North America, Europe, Asia, Asia Pacific, Africa, South America
- Add chrono-tz dependency for proper timezone handling
- Fix external calendar event colors by setting calendar_path for color lookup
- Add visual distinction for external calendar events with dashed borders and calendar emoji
- Update timezone parsing to extract TZID parameters from iCalendar DTSTART/DTEND properties
- Pass external calendar data through component hierarchy for color matching
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Database: Add external_calendars table with user relationships and CRUD operations
- Backend: Implement REST API endpoints for external calendar management and ICS fetching
- Frontend: Add external calendar modal, sidebar section with visibility toggles
- Calendar integration: Merge external events with regular events in unified view
- ICS parsing: Support multiple datetime formats, recurring events, and timezone handling
- Authentication: Integrate with existing JWT token system for user-specific calendars
- UI: Visual distinction with 📅 indicator and separate management section
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Backend: Store all-day events at noon UTC instead of midnight to avoid timezone boundary issues
- Backend: Remove local timezone conversion for all-day events in series handler
- Frontend: Skip timezone conversion when extracting dates from all-day events for display
- Frontend: Extract dates directly from UTC for all-day events in event_spans_date function
The issue was that timezone conversion of UTC midnight could shift dates backward in western timezones.
Now all-day events use noon UTC storage and pure date extraction without timezone conversion.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Backend now updates RRULE when recurrence_count or recurrence_end_date parameters are provided
- Fixed update_entire_series() to modify COUNT/UNTIL instead of preserving original RRULE
- Added comprehensive RRULE parsing functions to extract existing frequency, interval, count, until, and BYDAY components
- Fixed frontend parameter mapping to pass recurrence parameters through update_series calls
- Resolves issue where changing recurring event from 5 to 7 occurrences kept original COUNT=5
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Events were appearing 4 hours earlier than selected time due to incorrect
timezone handling in backend. The issue was treating frontend local time
as if it was already in UTC.
- Fix parse_event_datetime() in events.rs to properly convert local time to UTC
- Fix all datetime conversions in series.rs to use Local timezone conversion
- Replace Utc.from_utc_datetime() with proper Local.from_local_datetime()
- Add timezone conversion using with_timezone(&Utc) for accurate UTC storage
Now when user selects 5:00 AM, it correctly stores as UTC equivalent
and displays back at 5:00 AM local time.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add database migration for last_used_calendar field in user preferences
- Update backend models and handlers to support last_used_calendar persistence
- Modify frontend preferences service with update_last_used_calendar() method
- Implement automatic saving of selected calendar on event creation
- Add localStorage fallback for offline usage and immediate UI response
- Update create event modal to default to last used calendar for new events
- Clean up unused imports from event form components
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Set all_day flag properly when creating VEvent in series handler
- Improve all-day event detection using VALUE=DATE parameter
- Add RFC-5545 compliance for exclusive end dates (backend adds 1 day)
- Fix end date display in event modal (frontend subtracts 1 day for display)
- Fix recurring all-day event expansion to maintain proper end date pattern
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously filtered events by start date only, which excluded recurring
events that started in previous months/years but have instances in the
current month.
New logic:
- Non-recurring events: filter by exact month match (unchanged)
- Recurring events: include if they could have instances in requested month
- Check event start date is before/during month
- Parse RRULE UNTIL date to exclude expired recurring events
- Let frontend handle proper RRULE expansion
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Backend fixes:
- Fix all-day event creation validation error
- Allow same start/end date for all-day events (single-day events)
- Maintain strict validation for timed events (end must be after start)
Frontend improvements:
- Move all-day events from time grid to day headers
- Add dedicated all-day events container that stacks vertically
- Filter all-day events out of main time-based events area
- Add proper CSS styling for all-day event display and interaction
- Maintain event click handling and color themes
All-day events now appear in the correct location at the top of each
day column and properly stack when multiple events exist.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit adds a complete style system alongside the existing theme system, allowing users to switch between different UI styles while maintaining theme color variations.
**Core Features:**
- Style enum (Default, Google Calendar) separate from Theme enum
- Hot-swappable stylesheets with dynamic loading
- Style preference persistence (localStorage + database)
- Style picker UI in sidebar below theme picker
**Frontend Implementation:**
- Add Style enum to sidebar.rs with value/display methods
- Implement dynamic stylesheet loading in app.rs
- Add style picker dropdown with proper styling
- Handle style state management and persistence
- Add web-sys features for HtmlLinkElement support
**Backend Integration:**
- Add calendar_style column to user_preferences table
- Update all database operations (insert/update/select)
- Extend API models for style preference
- Add migration for existing users
**Google Calendar Style:**
- Clean Material Design-inspired interface
- White sidebar with proper contrast
- Enhanced calendar grid with subtle shadows
- Improved event styling with hover effects
- Google Sans typography throughout
- Professional color scheme and spacing
**Technical Details:**
- Trunk asset management for stylesheet copying
- High CSS specificity to override theme styles
- Modular CSS architecture for easy extensibility
- Comprehensive text contrast fixes
- Enhanced calendar cells and navigation
Users can now choose between the original gradient design (Default) and a clean Google Calendar-inspired interface (Google Calendar), with full preference persistence across sessions.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added SQLite database for session management and user preferences storage,
allowing users to have consistent settings across different sessions and devices.
Backend changes:
- Added SQLite database with users, sessions, and preferences tables
- Implemented session-based authentication alongside JWT tokens
- Created preference storage/retrieval API endpoints
- Database migrations for schema setup
- Session validation and cleanup functionality
Frontend changes:
- Added "Remember server" and "Remember username" checkboxes to login
- Created preferences service for syncing settings with backend
- Updated auth flow to handle session tokens and preferences
- Store remembered values in LocalStorage (not database) for convenience
Key features:
- User preferences persist across sessions and devices
- CalDAV passwords never stored, only passed through
- Sessions expire after 24 hours
- Remember checkboxes only affect local browser storage
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Moved event fetching logic from CalendarView to Calendar component to properly
use the visible date range instead of hardcoded current month. The Calendar
component already tracks the current visible date through navigation, so events
now load correctly for August and other months when navigating.
Changes:
- Calendar component now manages its own events state and fetching
- Event fetching responds to current_date changes from navigation
- CalendarView simplified to just render Calendar component
- Fixed cargo fmt/clippy formatting across codebase
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Removed Obsolete Environment Variables:
- `CALDAV_SERVER_URL` - provided by user login
- `CALDAV_USERNAME` - provided by user login
- `CALDAV_PASSWORD` - provided by user login
- `CALDAV_TASKS_PATH` - not used in any features
## Kept with Intelligent Discovery:
- `CALDAV_CALENDAR_PATH` - optional override, defaults to smart discovery
## Changes:
### Backend
- Remove `CalDAVConfig::from_env()` method (not used in main app)
- Add `CalDAVConfig::new()` constructor with credentials
- Remove `tasks_path` field from CalDAVConfig
- Update auth service to use new constructor
- Update tests to use hardcoded test values instead of env vars
- Update debug tools to use test credentials
### Frontend
- Remove unused `config.rs` file entirely (frontend uses backend API)
## Current Authentication Flow:
1. User provides CalDAV credentials via login API
2. Backend creates CalDAVConfig dynamically from login request
3. Backend tests authentication via calendar discovery
4. Optional `CALDAV_CALENDAR_PATH` env var can override discovery
5. No environment variables required for normal operation
This simplifies deployment - users only need to provide CalDAV
credentials through the web interface, no server-side configuration required.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Frontend Changes:
- Add EditAction enum (EditThis, EditFuture, EditAll) to event context menu
- Update context menu to show 3 edit options for recurring events
- Enhance EventCreationData with edit_scope and changed_fields tracking
- Update app component to handle EditAction types and pass to modal
- Add field change tracking infrastructure to CreateEventModal
## Backend Changes:
- Add changed_fields parameter to UpdateEventSeriesRequest for optimization
- Existing series endpoint already supports the three update types:
- "this_only" - creates exception with EXDATE
- "this_and_future" - creates new series with UNTIL on original
- "all_in_series" - updates existing series in-place
## Implementation Details:
- Event context menu shows single edit option for non-recurring events
- Recurring events get three options: "Edit This Event", "Edit This and Future Events", "Edit All Events in Series"
- Modal tracks which fields user actually changed for efficient updates
- Backend series endpoint already has the logic for all three update scenarios
- Full RFC 5545 compliance with proper EXDATE and UNTIL handling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed unused functions and variables identified after RRULE parameter fix:
- Remove unused build_series_rrule function from backend series handler
- Remove unused RecurrenceType::from_rrule and helper functions from frontend
- Prefix unused state variables with underscores to suppress warnings
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Clean up extensive console logging that was added during RRULE debugging.
Removed debug logs from:
- Frontend RRULE generation in create event modal
- Frontend RRULE parsing in calendar service
- Weekly/monthly/yearly occurrence generation functions
- Backend RRULE processing in events and series handlers
The core functionality remains unchanged - this is purely a cleanup
of temporary debugging output that is no longer needed.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit fixes a critical bug where INTERVAL and COUNT parameters
were being stripped from recurring events during backend processing.
Frontend was correctly generating complete RRULE strings like:
FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,FR;COUNT=6
But backend was ignoring the complete RRULE and rebuilding from scratch,
resulting in simplified RRULEs like:
FREQ=WEEKLY;BYDAY=TU,FR (missing INTERVAL and COUNT)
Changes:
- Modified both events and series handlers to detect complete RRULE strings
- Added logic to use frontend RRULE directly when it starts with "FREQ="
- Maintained backwards compatibility with simple recurrence types
- Added comprehensive debug logging for RRULE generation
- Fixed weekly BYDAY occurrence counting to respect COUNT parameter
- Enhanced frontend RRULE generation with detailed logging
This ensures all RFC 5545 RRULE parameters are preserved from
frontend creation through CalDAV storage and retrieval.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Aligns update_entire_series with the same metadata preservation approach
used in this_only and this_and_future update methods.
## Key Changes:
1. **Clone-and-Modify Pattern**:
- Clone existing event to preserve all metadata (organizer, attendees, etc.)
- Only modify specific properties that need to change
- Maintains consistency with other update methods
2. **Smart Field Handling**:
- Preserve original values when request fields are empty
- Only overwrite when new values are explicitly provided
- Same selective update logic as other scopes
3. **RRULE Preservation**:
- Keep existing recurrence pattern unchanged for simple updates
- Suitable for drag operations that just change start/end times
- Avoids breaking complex RRULE patterns unnecessarily
4. **Proper Timestamp Management**:
- Update dtstamp and last_modified to current time
- Preserve original created timestamp for event history
- Consistent timestamp handling across all update types
## Benefits:
- All three update scopes now follow the same metadata preservation pattern
- Simple time changes (drag operations) work without side effects
- Complex event properties maintained across all modification types
- Better RFC 5545 compliance through proper event structure preservation
## Removed:
- Complex RRULE regeneration logic (build_series_rrule function now unused)
- Manual field-by-field assignment replaced with selective clone modification
This ensures consistent behavior whether users modify single occurrences,
future events, or entire series - all maintain original event metadata.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolves multiple issues with single occurrence modification to implement
correct CalDAV/RFC 5545 exception patterns:
## Key Fixes:
1. **Eliminate Double Updates**:
- Removed redundant client.update_event() call from update_single_occurrence
- Main handler now performs single CalDAV update, preventing conflicts
2. **Preserve Event Metadata**:
- Changed from creating new event to cloning existing event
- Maintains organizer, attendees, categories, and all original properties
- Only modifies necessary fields (times, title, recurrence rules)
3. **Fix UID Conflicts**:
- Generate unique UID for exception event (exception-{uuid})
- Prevents CalDAV from treating exception as update to original series
- Original series keeps its UID, exception gets separate identity
4. **Correct Date/Time Handling**:
- Use occurrence_date for both this_only and this_and_future scopes
- Exception event now gets dragged date/time instead of original series date
- Properly reflects user's drag operation in the exception event
## Implementation Details:
- Exception event clones original with unique UID and RECURRENCE-ID
- Original series gets EXDATE to exclude the modified occurrence
- Main handler performs single atomic CalDAV update
- Smart field preservation (keeps original values when request is empty)
## Result:
Single occurrence modifications now work correctly with proper RFC 5545
EXDATE + exception event pattern, maintaining all event metadata while
reflecting user modifications at the correct date/time.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit resolves the "Failed to fetch" errors when updating recurring
event series through drag operations by implementing proper request
sequencing and fixing time parameter handling.
Key fixes:
- Eliminate HTTP request cancellation by sequencing operations properly
- Add global mutex to prevent CalDAV HTTP race conditions
- Implement complete RFC 5545-compliant series splitting for "this_and_future"
- Fix frontend to pass dragged times instead of original times
- Add comprehensive error handling and request timing logs
- Backend now handles both UPDATE (add UNTIL) and CREATE (new series) in single request
Technical changes:
- Frontend: Remove concurrent CREATE request, pass dragged times to backend
- Backend: Implement full this_and_future logic with sequential operations
- CalDAV: Add mutex serialization and detailed error tracking
- Series: Create new series with occurrence date + dragged times
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit resolves the 404 error when dragging/updating non-recurring events.
The issue was in the regular event update handler where it was generating fake
event hrefs based on the UID (format: "{uid}.ics") instead of using the actual
href returned by the CalDAV server during event fetching.
Changes:
- Use event.href from the stored event data instead of generating fake hrefs
- Add comprehensive debug logging to track event updates
- Fallback to generated href only when the stored href is missing
Debug logging added:
- "🔍 Found event {uid} with href: {href}" - shows which href is being used
- "📝 Updating event {uid} at calendar_path: {path}, event_href: {href}" - tracks update parameters
- "✅ Successfully updated event {uid}" - confirms successful CalDAV updates
This matches the fix previously applied to the deletion functionality and ensures
that CalDAV PUT requests target the correct resource URLs.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit resolves multiple issues with event deletion:
Backend fixes:
- Fix CalDAV URL construction for DELETE requests (missing slash separator)
- Improve event lookup by href with exact matching and fallback to UID extraction
- Add support for both RFC3339 and simple YYYY-MM-DD date formats in occurrence parsing
- Implement proper logic to distinguish recurring vs non-recurring events in delete_this action
- For non-recurring events: delete entire event from CalDAV server
- For recurring events: add EXDATE to exclude specific occurrences
- Add comprehensive debug logging for troubleshooting deletion issues
Frontend fixes:
- Update callback signatures to support series endpoint parameters (7-parameter tuples)
- Add update_series method to CalendarService for series-specific operations
- Route single occurrence modifications through series endpoint with proper scoping
- Fix all component prop definitions to use new callback signature
- Update all emit calls to pass correct number of parameters
The deletion process now works correctly:
- Single events are completely removed from the calendar
- Recurring event occurrences are properly excluded via EXDATE
- Debug logging helps identify and resolve CalDAV communication issues
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Extended update callback signature to include update_scope and occurrence_date parameters
- Modified app.rs to detect when series endpoint should be used vs regular endpoint
- Updated calendar_service to automatically set occurrence_date for "this_only" updates
- Modified all callback emit calls throughout frontend to include new parameters
- Week_view now properly calls series endpoint with "this_only" scope for single occurrence edits
This ensures that single occurrence modifications (RecurringEditAction::ThisEvent)
now go through the proper series endpoint which will:
- Add EXDATE to the original recurring series
- Create exception event with RECURRENCE-ID
- Show proper debug logging in backend
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- When dragging recurring events, preserve original series start date
- Only update time components, not date, to prevent series from shifting days
- For timed events: use original date with new start/end times from drag
- For all-day events: preserve original date and duration pattern
- Added debug logging to track date preservation behavior
- Maintains event duration for both timed and all-day recurring events
Fixes issue where dragging a recurring event would change the date
for all occurrences instead of just updating the time.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>