Implement comprehensive event series editing via modal
## 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>
This commit is contained in:
@@ -2,7 +2,7 @@ use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
use gloo_storage::{LocalStorage, Storage};
|
||||
use web_sys::MouseEvent;
|
||||
use crate::components::{Sidebar, ViewMode, Theme, CreateCalendarModal, ContextMenu, EventContextMenu, CalendarContextMenu, CreateEventModal, EventCreationData, RouteHandler, EventStatus, EventClass, ReminderType, RecurrenceType, DeleteAction};
|
||||
use crate::components::{Sidebar, ViewMode, Theme, CreateCalendarModal, ContextMenu, EventContextMenu, CalendarContextMenu, CreateEventModal, EventCreationData, RouteHandler, EventStatus, EventClass, ReminderType, RecurrenceType, DeleteAction, EditAction};
|
||||
use crate::services::{CalendarService, calendar_service::UserInfo};
|
||||
use crate::models::ical::VEvent;
|
||||
use chrono::NaiveDate;
|
||||
@@ -54,6 +54,7 @@ pub fn App() -> Html {
|
||||
let calendar_context_menu_date = use_state(|| -> Option<NaiveDate> { None });
|
||||
let create_event_modal_open = use_state(|| false);
|
||||
let selected_date_for_event = use_state(|| -> Option<NaiveDate> { None });
|
||||
let event_edit_scope = use_state(|| -> Option<EditAction> { None });
|
||||
let _recurring_edit_modal_open = use_state(|| false);
|
||||
let _recurring_edit_event = use_state(|| -> Option<VEvent> { None });
|
||||
let _recurring_edit_data = use_state(|| -> Option<EventCreationData> { None });
|
||||
@@ -738,8 +739,10 @@ pub fn App() -> Html {
|
||||
let _event_context_menu_event = event_context_menu_event.clone();
|
||||
let event_context_menu_open = event_context_menu_open.clone();
|
||||
let create_event_modal_open = create_event_modal_open.clone();
|
||||
move |_| {
|
||||
// Close the context menu and open the edit modal
|
||||
let event_edit_scope = event_edit_scope.clone();
|
||||
move |edit_action: EditAction| {
|
||||
// Set the edit scope and close the context menu
|
||||
event_edit_scope.set(Some(edit_action));
|
||||
event_context_menu_open.set(false);
|
||||
create_event_modal_open.set(true);
|
||||
}
|
||||
@@ -840,13 +843,16 @@ pub fn App() -> Html {
|
||||
is_open={*create_event_modal_open}
|
||||
selected_date={(*selected_date_for_event).clone()}
|
||||
event_to_edit={(*event_context_menu_event).clone()}
|
||||
edit_scope={(*event_edit_scope).clone()}
|
||||
on_close={Callback::from({
|
||||
let create_event_modal_open = create_event_modal_open.clone();
|
||||
let event_context_menu_event = event_context_menu_event.clone();
|
||||
let event_edit_scope = event_edit_scope.clone();
|
||||
move |_| {
|
||||
create_event_modal_open.set(false);
|
||||
// Clear the event being edited
|
||||
// Clear the event being edited and edit scope
|
||||
event_context_menu_event.set(None);
|
||||
event_edit_scope.set(None);
|
||||
}
|
||||
})}
|
||||
on_create={on_event_create}
|
||||
@@ -854,10 +860,12 @@ pub fn App() -> Html {
|
||||
let auth_token = auth_token.clone();
|
||||
let create_event_modal_open = create_event_modal_open.clone();
|
||||
let event_context_menu_event = event_context_menu_event.clone();
|
||||
let event_edit_scope = event_edit_scope.clone();
|
||||
move |(original_event, updated_data): (VEvent, EventCreationData)| {
|
||||
web_sys::console::log_1(&format!("Updating event: {:?}", updated_data).into());
|
||||
web_sys::console::log_1(&format!("Updating event: {:?}, edit_scope: {:?}", updated_data, updated_data.edit_scope).into());
|
||||
create_event_modal_open.set(false);
|
||||
event_context_menu_event.set(None);
|
||||
event_edit_scope.set(None);
|
||||
|
||||
if let Some(token) = (*auth_token).clone() {
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
|
||||
Reference in New Issue
Block a user