Fix external calendar creation and Outlook compatibility issues

- Fix external calendar form validation by replacing node refs with controlled state inputs
- Add multiple user-agent fallback approach for better external calendar compatibility
- Enhance HTTP client configuration with proper redirect handling and timeouts
- Add detailed error logging and Outlook-specific error detection
- Improve request headers for better calendar server compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Connor Johnstone
2025-09-11 17:58:53 -04:00
parent 927cd7d2bb
commit 91be4436a9
2 changed files with 118 additions and 31 deletions

View File

@@ -30,8 +30,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
let is_creating = use_state(|| false);
// External Calendar state
let external_name_ref = use_node_ref();
let external_url_ref = use_node_ref();
let external_name = use_state(|| String::new());
let external_url = use_state(|| String::new());
let external_selected_color = use_state(|| Some("#4285f4".to_string()));
let external_is_loading = use_state(|| false);
let external_error_message = use_state(|| None::<String>);
@@ -43,6 +43,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
let selected_color = selected_color.clone();
let create_error_message = create_error_message.clone();
let is_creating = is_creating.clone();
let external_name = external_name.clone();
let external_url = external_url.clone();
let external_is_loading = external_is_loading.clone();
let external_error_message = external_error_message.clone();
let external_selected_color = external_selected_color.clone();
@@ -56,6 +58,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
selected_color.set(None);
create_error_message.set(None);
is_creating.set(false);
external_name.set(String::new());
external_url.set(String::new());
external_is_loading.set(false);
external_error_message.set(None);
external_selected_color.set(Some("#4285f4".to_string()));
@@ -146,8 +150,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
// External Calendar handlers
let on_external_submit = {
let external_name_ref = external_name_ref.clone();
let external_url_ref = external_url_ref.clone();
let external_name = external_name.clone();
let external_url = external_url.clone();
let external_selected_color = external_selected_color.clone();
let external_is_loading = external_is_loading.clone();
let external_error_message = external_error_message.clone();
@@ -157,24 +161,28 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
Callback::from(move |e: SubmitEvent| {
e.prevent_default();
let name = external_name_ref
.cast::<HtmlInputElement>()
.map(|input| input.value())
.unwrap_or_default()
.trim()
.to_string();
let url = external_url_ref
.cast::<HtmlInputElement>()
.map(|input| input.value())
.unwrap_or_default()
.trim()
.to_string();
let name = (*external_name).trim().to_string();
let url = (*external_url).trim().to_string();
let color = (*external_selected_color).clone().unwrap_or_else(|| "#4285f4".to_string());
if name.is_empty() || url.is_empty() {
external_error_message.set(Some("Name and URL are required".to_string()));
// Debug logging to understand the issue
web_sys::console::log_1(&format!("External calendar form submission - Name: '{}', URL: '{}'", name, url).into());
if name.is_empty() {
external_error_message.set(Some("Calendar name is required".to_string()));
web_sys::console::log_1(&"Validation failed: empty name".into());
return;
}
if url.is_empty() {
external_error_message.set(Some("Calendar URL is required".to_string()));
web_sys::console::log_1(&"Validation failed: empty URL".into());
return;
}
// Basic URL validation
if !url.starts_with("http://") && !url.starts_with("https://") {
external_error_message.set(Some("Please enter a valid HTTP or HTTPS URL".to_string()));
return;
}
@@ -204,6 +212,25 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
})
};
// External input change handlers
let on_external_name_change = {
let external_name = external_name.clone();
Callback::from(move |e: Event| {
if let Some(input) = e.target_dyn_into::<HtmlInputElement>() {
external_name.set(input.value());
}
})
};
let on_external_url_change = {
let external_url = external_url.clone();
Callback::from(move |e: Event| {
if let Some(input) = e.target_dyn_into::<HtmlInputElement>() {
external_url.set(input.value());
}
})
};
if !props.is_open {
return html! {};
}
@@ -333,7 +360,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
<input
type="text"
id="external-name"
ref={external_name_ref.clone()}
value={(*external_name).clone()}
onchange={on_external_name_change}
placeholder="Enter calendar name"
disabled={*external_is_loading}
/>
@@ -344,7 +372,8 @@ pub fn calendar_management_modal(props: &CalendarManagementModalProps) -> Html {
<input
type="url"
id="external-url"
ref={external_url_ref.clone()}
value={(*external_url).clone()}
onchange={on_external_url_change}
placeholder="https://example.com/calendar.ics"
disabled={*external_is_loading}
/>