Przeglądaj źródła

fixes to event mutation api

Adam Shaw 7 lat temu
rodzic
commit
56b3a6c734

+ 59 - 49
src/api/EventApi.ts

@@ -2,8 +2,8 @@ import Calendar from '../Calendar'
 import { EventDef, EventInstance } from '../structs/event'
 import { EventMutation } from '../structs/event-mutation'
 import { DateInput } from '../datelib/env'
-import { diffDates } from '../util/misc'
-import { subtractDurations, asRoughMs, DurationInput, createDuration } from '../datelib/duration'
+import { diffDates, computeAlignedDayRange } from '../util/misc'
+import { subtractDurations, DurationInput, createDuration } from '../datelib/duration'
 
 export default class EventApi {
 
@@ -56,52 +56,71 @@ export default class EventApi {
       if (options.maintainDuration) {
         let origDuration = diffDates(instanceRange.start, instanceRange.end, dateEnv, options.granularity)
         let newDuration = diffDates(start, instanceRange.end, dateEnv, options.granularity)
-        endDelta = subtractDurations(newDuration, origDuration)
+        endDelta = subtractDurations(origDuration, newDuration)
       }
 
-      this.mutate({
-        startDelta,
-        endDelta,
-        standardProps:
-          options.maintainDuration || !asRoughMs(startDelta) ?
-            {} :
-            { hasEnd: true } // when events will get new duration, considered to have an end
-      })
+      this.mutate({ startDelta, endDelta })
     }
   }
 
-  setEnd(endInput: DateInput, options: { granularity?: string } = {}) {
+  setEnd(endInput: DateInput | null, options: { granularity?: string } = {}) {
     let dateEnv = this.calendar.dateEnv
-    let end = dateEnv.createMarker(endInput)
+    let end
 
-    if (end && this.instance) { // TODO: warning if parsed bad
-      let endDelta = diffDates(this.instance.range.end, end, dateEnv, options.granularity)
+    if (endInput != null) {
+      end = dateEnv.createMarker(endInput)
 
-      this.mutate({
-        endDelta,
-        standardProps: { hasEnd: true }
-      })
+      if (!end) {
+        return // TODO: warning if parsed bad
+      }
+    }
+
+    if (this.instance) {
+      if (end) {
+        let endDelta = diffDates(this.instance.range.end, end, dateEnv, options.granularity)
+        this.mutate({ endDelta })
+      } else {
+        this.mutate({ standardProps: { hasEnd: false } })
+      }
     }
   }
 
-  setDates(startInput: DateInput, endInput: DateInput, options: { granularity?: string } = {}) {
+  setDates(startInput: DateInput, endInput: DateInput | null, options: { isAllDay?: boolean, granularity?: string } = {}) {
     let dateEnv = this.calendar.dateEnv
+    let standardProps = { isAllDay: options.isAllDay } as any
     let start = dateEnv.createMarker(startInput)
-    let end = dateEnv.createMarker(endInput)
+    let end
 
-    if (start && end && this.instance) { // TODO: warning if parsed bad
+    if (!start) {
+      return // TODO: warning if parsed bad
+    }
+
+    if (endInput != null) {
+      end = dateEnv.createMarker(endInput)
+
+      if (!end) { // TODO: warning if parsed bad
+        return
+      }
+    }
+
+    if (this.instance) {
       let instanceRange = this.instance.range
+
+      // when computing the diff for an event being converted to all-day,
+      // compute diff off of the all-day values the way event-mutation does.
+      if (options.isAllDay === true) {
+        instanceRange = computeAlignedDayRange(instanceRange)
+      }
+
       let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity)
-      let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity)
 
-      this.mutate({
-        startDelta,
-        endDelta,
-        standardProps:
-          asRoughMs(endDelta) ?
-            { hasEnd: true } : // any end change? mark as having an end
-            {}
-      })
+      if (end) {
+        let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity)
+        this.mutate({ startDelta, endDelta, standardProps })
+      } else {
+        standardProps.hasEnd = false
+        this.mutate({ startDelta, standardProps })
+      }
     }
   }
 
@@ -109,10 +128,7 @@ export default class EventApi {
     let delta = createDuration(deltaInput)
 
     if (delta) { // TODO: warning if parsed bad
-      this.mutate({
-        startDelta: delta,
-        standardProps: { hasEnd: true }
-      })
+      this.mutate({ startDelta: delta })
     }
   }
 
@@ -120,10 +136,7 @@ export default class EventApi {
     let delta = createDuration(deltaInput)
 
     if (delta) { // TODO: warning if parsed bad
-      this.mutate({
-        endDelta: delta,
-        standardProps: { hasEnd: true }
-      })
+      this.mutate({ endDelta: delta })
     }
   }
 
@@ -131,26 +144,23 @@ export default class EventApi {
     let delta = createDuration(deltaInput)
 
     if (delta) { // TODO: warning if parsed bad
-      this.mutate({
-        startDelta: delta,
-        endDelta: delta
-      })
+      this.mutate({ startDelta: delta, endDelta: delta })
     }
   }
 
   setIsAllDay(isAllDay: boolean, options: { maintainDuration?: boolean } = {}) {
+    let standardProps = { isAllDay } as any
     let maintainDuration = options.maintainDuration
 
     if (maintainDuration == null) {
       maintainDuration = this.calendar.opt('isAllDayMaintainDuration')
     }
 
-    this.mutate({
-      standardProps: {
-        isAllDay,
-        hasEnd: maintainDuration
-      }
-    })
+    if (this.def.isAllDay !== isAllDay) {
+      standardProps.hasEnd = maintainDuration
+    }
+
+    this.mutate({ standardProps })
   }
 
   private mutate(mutation: EventMutation) {

+ 2 - 2
src/interactions/EventDragging.ts

@@ -348,8 +348,8 @@ function computeEventMutation(hit0: Hit, hit1: Hit): EventMutation {
 
   if (dateSpan0.isAllDay !== dateSpan1.isAllDay) {
     standardProps = {
-      hasEnd: hit1.component.opt('isAllDayMaintainDuration'),
-      isAllDay: dateSpan1.isAllDay
+      isAllDay: dateSpan1.isAllDay,
+      hasEnd: hit1.component.opt('isAllDayMaintainDuration')
     }
 
     if (dateSpan1.isAllDay) {

+ 2 - 2
src/interactions/EventResizing.ts

@@ -214,11 +214,11 @@ function computeMutation(hit0: Hit, hit1: Hit, isFromStart: boolean, instanceRan
 
   if (isFromStart) {
     if (dateEnv.add(instanceRange.start, delta) > instanceRange.end) {
-      return { startDelta: delta, standardProps: { hasEnd: true } }
+      return { startDelta: delta }
     }
   } else {
     if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
-      return { endDelta: delta, standardProps: { hasEnd: true } }
+      return { endDelta: delta }
     }
   }
 

+ 42 - 3
src/structs/event-mutation.ts

@@ -1,9 +1,10 @@
-import { Duration } from '../datelib/duration'
+import { Duration, asRoughMs, durationsEqual } from '../datelib/duration'
 import { EventStore, createEmptyEventStore } from './event-store'
 import { EventDef, EventInstance } from './event'
 import { assignTo } from '../util/object'
 import Calendar from '../Calendar'
 import { computeAlignedDayRange } from '../util/misc'
+import { startOfDay } from '../datelib/marker'
 
 /*
 A data structure for how to modify an EventDef/EventInstance within an EventStore
@@ -36,11 +37,20 @@ export function applyMutationToEventStore(eventStore: EventStore, mutation: Even
 
 function applyMutationToEventDef(eventDef: EventDef, mutation: EventMutation): EventDef {
   let copy = assignTo({}, eventDef)
+  let standardProps = mutation.standardProps || {}
 
-  if (mutation.standardProps) {
-    assignTo(copy, mutation.standardProps)
+  // if hasEnd has not been specified, guess a good value based on deltas.
+  // if duration will change, there's no way the default duration will persist,
+  // and thus, we need to mark the event as having a real end
+  if (
+    standardProps.hasEnd == null &&
+    willDeltasAffectDuration(mutation.startDelta, mutation.endDelta)
+  ) {
+    standardProps.hasEnd = true
   }
 
+  assignTo(copy, standardProps)
+
   if (mutation.extendedProps) {
     copy.extendedProps = assignTo({}, copy.extendedProps, mutation.extendedProps)
   }
@@ -48,6 +58,21 @@ function applyMutationToEventDef(eventDef: EventDef, mutation: EventMutation): E
   return copy
 }
 
+function willDeltasAffectDuration(startDelta: Duration | null, endDelta: Duration | null) {
+  if (startDelta && !asRoughMs(startDelta)) { startDelta = null }
+  if (endDelta && !asRoughMs(endDelta)) { endDelta = null }
+
+  if (!startDelta && !endDelta) {
+    return false
+  }
+
+  if (Boolean(startDelta) !== Boolean(endDelta)) {
+    return true
+  }
+
+  return !durationsEqual(startDelta, endDelta)
+}
+
 function applyMutationToEventInstance(
   eventInstance: EventInstance,
   eventDef: EventDef, // must first be modified by applyMutationToEventDef
@@ -82,5 +107,19 @@ function applyMutationToEventInstance(
     }
   }
 
+  // in case event was all-day but the supplied deltas were not
+  // better util for this?
+  if (eventDef.isAllDay) {
+    copy.range = {
+      start: startOfDay(copy.range.start),
+      end: startOfDay(copy.range.end)
+    }
+  }
+
+  // handle invalid durations
+  if (copy.range.end < copy.range.start) {
+    copy.range.end = calendar.getDefaultEventEnd(eventDef.isAllDay, copy.range.start)
+  }
+
   return copy
 }