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:
Connor Johnstone
2025-08-31 18:49:56 -04:00
parent ee181cf6cb
commit 5a12c0e0d0
5 changed files with 91 additions and 16 deletions

View File

@@ -9,13 +9,20 @@ pub enum DeleteAction {
DeleteSeries,
}
#[derive(Clone, PartialEq, Debug)]
pub enum EditAction {
EditThis,
EditFuture,
EditAll,
}
#[derive(Properties, PartialEq)]
pub struct EventContextMenuProps {
pub is_open: bool,
pub x: i32,
pub y: i32,
pub event: Option<VEvent>,
pub on_edit: Callback<()>,
pub on_edit: Callback<EditAction>,
pub on_delete: Callback<DeleteAction>,
pub on_close: Callback<()>,
}
@@ -38,11 +45,11 @@ pub fn event_context_menu(props: &EventContextMenuProps) -> Html {
.map(|event| event.rrule.is_some())
.unwrap_or(false);
let on_edit_click = {
let create_edit_callback = |action: EditAction| {
let on_edit = props.on_edit.clone();
let on_close = props.on_close.clone();
Callback::from(move |_: MouseEvent| {
on_edit.emit(());
on_edit.emit(action.clone());
on_close.emit(());
})
};
@@ -62,9 +69,29 @@ pub fn event_context_menu(props: &EventContextMenuProps) -> Html {
class="context-menu"
style={style}
>
<div class="context-menu-item" onclick={on_edit_click}>
{"Edit Event"}
</div>
{
if is_recurring {
html! {
<>
<div class="context-menu-item" onclick={create_edit_callback(EditAction::EditThis)}>
{"Edit This Event"}
</div>
<div class="context-menu-item" onclick={create_edit_callback(EditAction::EditFuture)}>
{"Edit This and Future Events"}
</div>
<div class="context-menu-item" onclick={create_edit_callback(EditAction::EditAll)}>
{"Edit All Events in Series"}
</div>
</>
}
} else {
html! {
<div class="context-menu-item" onclick={create_edit_callback(EditAction::EditThis)}>
{"Edit Event"}
</div>
}
}
}
{
if is_recurring {
html! {