Fix recurring event RRULE INTERVAL and COUNT parameter loss

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>
This commit is contained in:
Connor Johnstone
2025-08-31 00:28:41 -04:00
parent d0aa6fda08
commit c599598390
4 changed files with 509 additions and 58 deletions

View File

@@ -306,9 +306,11 @@ mod rrule_tests {
data.yearly_by_month = vec![false, false, true, false, true, false, false, false, false, false, false, false]; // March, May
let rrule = data.build_rrule();
println!("YEARLY RRULE: {}", rrule);
assert!(rrule.contains("FREQ=YEARLY"));
assert!(rrule.contains("BYMONTH=3,5"));
}
}
#[derive(Clone, PartialEq, Debug)]
@@ -385,6 +387,8 @@ impl EventCreationData {
return String::new();
}
web_sys::console::log_1(&format!("🔧 Building RRULE with interval: {}, count: {:?}", self.recurrence_interval, self.recurrence_count).into());
let mut parts = Vec::new();
// Add frequency (required)
@@ -399,6 +403,9 @@ impl EventCreationData {
// Add interval if not 1
if self.recurrence_interval > 1 {
parts.push(format!("INTERVAL={}", self.recurrence_interval));
web_sys::console::log_1(&format!(" Added INTERVAL={}", self.recurrence_interval).into());
} else {
web_sys::console::log_1(&format!("⏭️ Skipped INTERVAL (value is {})", self.recurrence_interval).into());
}
// Add frequency-specific rules
@@ -458,11 +465,17 @@ impl EventCreationData {
if let Some(until_date) = self.recurrence_until {
// Format as UNTIL=YYYYMMDDTHHMMSSZ
parts.push(format!("UNTIL={}T000000Z", until_date.format("%Y%m%d")));
web_sys::console::log_1(&format!(" Added UNTIL={}", until_date).into());
} else if let Some(count) = self.recurrence_count {
parts.push(format!("COUNT={}", count));
web_sys::console::log_1(&format!(" Added COUNT={}", count).into());
} else {
web_sys::console::log_1(&format!("⏭️ No COUNT or UNTIL specified").into());
}
parts.join(";")
let rrule = parts.join(";");
web_sys::console::log_1(&format!("🎯 Final RRULE: {}", rrule).into());
rrule
}
pub fn to_create_event_params(&self) -> (String, String, String, String, String, String, String, bool, String, String, Option<u8>, String, String, String, String, String, Vec<bool>, Option<String>) {