@@ -331,6 +331,7 @@ export const updateSeries = async (
331331
332332 const tzid = event . timezone ;
333333
334+ const oldMaster = vevents [ masterIndex ] ;
334335 const updatedMaster = makeVevent ( event , tzid , calOwnerEmail , true ) ;
335336 const newRrule = updatedMaster [ 1 ] . find ( ( [ k ] : string [ ] ) => k === "rrule" ) ;
336337 if ( ! newRrule ) {
@@ -346,67 +347,102 @@ export const updateSeries = async (
346347 finalVevents = [ updatedMaster ] ;
347348 } else {
348349 // When only properties changed, keep override instances and update their metadata
350+
351+ // Helper function to get field values from props
352+ const getFieldValues = ( props : any [ ] , fieldName : string ) => {
353+ return props . filter ( ( [ k ] ) => k . toLowerCase ( ) === fieldName . toLowerCase ( ) ) ;
354+ } ;
355+
356+ // Helper function to serialize for comparison
357+ const serialize = ( values : any [ ] ) => JSON . stringify ( values ) ;
358+
359+ // Detect which fields changed in the master
360+ const changedFields = new Map < string , any [ ] > ( ) ;
361+ const oldMasterProps = oldMaster [ 1 ] ;
362+ const newMasterProps = updatedMaster [ 1 ] ;
363+
364+ // Fields that are metadata (not time-related)
365+ const metadataFields = [
366+ "summary" ,
367+ "description" ,
368+ "location" ,
369+ "class" ,
370+ "transp" ,
371+ "attendee" ,
372+ "organizer" ,
373+ "x-openpaas-videoconference" ,
374+ ] ;
375+
376+ metadataFields . forEach ( ( fieldName ) => {
377+ const oldValues = getFieldValues ( oldMasterProps , fieldName ) ;
378+ const newValues = getFieldValues ( newMasterProps , fieldName ) ;
379+
380+ if ( serialize ( oldValues ) !== serialize ( newValues ) ) {
381+ changedFields . set ( fieldName . toLowerCase ( ) , newValues ) ;
382+ }
383+ } ) ;
384+
385+ // Check if VALARM component changed
386+ const oldMasterComponents = oldMaster [ 2 ] || [ ] ;
387+ const newMasterComponents = updatedMaster [ 2 ] || [ ] ;
388+ const oldValarm = oldMasterComponents . filter (
389+ ( [ name ] ) => name . toLowerCase ( ) === "valarm"
390+ ) ;
391+ const newValarm = newMasterComponents . filter (
392+ ( [ name ] ) => name . toLowerCase ( ) === "valarm"
393+ ) ;
394+ const valarmChanged = serialize ( oldValarm ) !== serialize ( newValarm ) ;
395+
349396 const updatedVevents = vevents . map ( ( vevent , index ) => {
350397 if ( index === masterIndex ) {
351398 return updatedMaster ;
352399 }
353400
354- const [ veventType , props ] = vevent ;
355- const updatedProps = [ ...updatedMaster [ 1 ] ] ;
356-
357- // Fields that should be updated from master (metadata)
358- const updateFields = [
359- "summary" ,
360- "description" ,
361- "location" ,
362- "class" ,
363- "transp" ,
364- "attendee" ,
365- "organizer" ,
366- "valarm" ,
367- "x-openpaas-videoconference" ,
368- ] ;
369-
370- // Start with existing exception properties
371- const newProps = [ ...props ] ;
372-
373- // Update each metadata field from the master
374- updateFields . forEach ( ( fieldName ) => {
375- const fieldNameLower = fieldName . toLowerCase ( ) ;
376-
377- // Remove old values of this field from exception
401+ const [ veventType , props , components = [ ] ] = vevent ;
402+ let newProps = [ ...props ] ;
403+
404+ // Only update fields that actually changed in the master
405+ changedFields . forEach ( ( newValues , fieldNameLower ) => {
406+ // Remove old values of this changed field from exception
378407 const filteredProps = newProps . filter (
379408 ( [ k ] ) => k . toLowerCase ( ) !== fieldNameLower
380409 ) ;
381410
382- // Get new values from updated master
383- const newValues = updatedProps . filter (
384- ( [ k ] ) => k . toLowerCase ( ) === fieldNameLower
385- ) ;
386-
387- // Replace with new values
388- newProps . length = 0 ;
389- newProps . push ( ...filteredProps , ...newValues ) ;
411+ // Add new values from updated master
412+ newProps = [ ...filteredProps , ...newValues ] ;
390413 } ) ;
391414
392- // Increment sequence number for the exception
393- const sequenceIndex = newProps . findIndex (
394- ( [ k ] ) => k . toLowerCase ( ) === "sequence"
395- ) ;
396- if ( sequenceIndex !== - 1 ) {
397- const currentSequence = parseInt ( newProps [ sequenceIndex ] [ 3 ] || "0" , 10 ) ;
398- newProps [ sequenceIndex ] = [
399- newProps [ sequenceIndex ] [ 0 ] ,
400- newProps [ sequenceIndex ] [ 1 ] ,
401- newProps [ sequenceIndex ] [ 2 ] ,
402- String ( currentSequence + 1 ) ,
403- ] ;
404- } else {
405- // Add sequence if it doesn't exist
406- newProps . push ( [ "sequence" , { } , "integer" , "1" ] ) ;
415+ // Increment sequence number if any changes were made
416+ if ( changedFields . size > 0 || valarmChanged ) {
417+ const sequenceIndex = newProps . findIndex (
418+ ( [ k ] ) => k . toLowerCase ( ) === "sequence"
419+ ) ;
420+ if ( sequenceIndex !== - 1 ) {
421+ const currentSequence = parseInt (
422+ newProps [ sequenceIndex ] [ 3 ] || "0" ,
423+ 10
424+ ) ;
425+ newProps [ sequenceIndex ] = [
426+ newProps [ sequenceIndex ] [ 0 ] ,
427+ newProps [ sequenceIndex ] [ 1 ] ,
428+ newProps [ sequenceIndex ] [ 2 ] ,
429+ String ( currentSequence + 1 ) ,
430+ ] ;
431+ } else {
432+ newProps . push ( [ "sequence" , { } , "integer" , "1" ] ) ;
433+ }
434+ }
435+
436+ // Handle VALARM component updates
437+ let updatedComponents = components ;
438+ if ( valarmChanged ) {
439+ // Remove old VALARM and add new one
440+ updatedComponents = components
441+ . filter ( ( [ name ] ) => name . toLowerCase ( ) !== "valarm" )
442+ . concat ( newValarm ) ;
407443 }
408444
409- return [ veventType , newProps ] ;
445+ return [ veventType , newProps , updatedComponents ] ;
410446 } ) ;
411447
412448 finalVevents = updatedVevents ;
0 commit comments