Просмотр исходного кода

change how event drag-n-drop mutation is done

Adam Shaw 7 лет назад
Родитель
Сommit
5958abce8a
3 измененных файлов с 118 добавлено и 112 удалено
  1. 24 19
      src/component/DateComponent.ts
  2. 36 13
      src/interactions/EventDragging.ts
  3. 58 80
      src/reducers/event-mutation.ts

+ 24 - 19
src/component/DateComponent.ts

@@ -978,25 +978,8 @@ export default abstract class DateComponent extends Component {
 
   // Returns the date range of the full days the given range visually appears to occupy.
   // Returns a plain object with start/end, NOT an UnzonedRange!
-  computeDayRange(unzonedRange): { start: DateMarker, end: DateMarker } {
-    let startDay: DateMarker = startOfDay(unzonedRange.start) // the beginning of the day the range starts
-    let end: DateMarker = unzonedRange.end
-    let endDay: DateMarker = startOfDay(end)
-    let endTimeMS: number = end.valueOf() - endDay.valueOf() // # of milliseconds into `endDay`
-
-    // If the end time is actually inclusively part of the next day and is equal to or
-    // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
-    // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
-    if (endTimeMS && endTimeMS >= asRoughMs(this.nextDayThreshold)) {
-      endDay = addDays(endDay, 1)
-    }
-
-    // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
-    if (endDay <= startDay) {
-      endDay = addDays(startDay, 1)
-    }
-
-    return { start: startDay, end: endDay } // TODO: eventually use UnzonedRange?
+  computeDayRange(unzonedRange): UnzonedRange {
+    return computeDayRange(unzonedRange, this.nextDayThreshold)
   }
 
 
@@ -1022,3 +1005,25 @@ export default abstract class DateComponent extends Component {
   }
 
 }
+
+
+function computeDayRange(unzonedRange: UnzonedRange, nextDayThreshold: Duration): UnzonedRange {
+  let startDay: DateMarker = startOfDay(unzonedRange.start) // the beginning of the day the range starts
+  let end: DateMarker = unzonedRange.end
+  let endDay: DateMarker = startOfDay(end)
+  let endTimeMS: number = end.valueOf() - endDay.valueOf() // # of milliseconds into `endDay`
+
+  // If the end time is actually inclusively part of the next day and is equal to or
+  // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
+  // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
+  if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
+    endDay = addDays(endDay, 1)
+  }
+
+  // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
+  if (endDay <= startDay) {
+    endDay = addDays(startDay, 1)
+  }
+
+  return new UnzonedRange(startDay, endDay)
+}

+ 36 - 13
src/interactions/EventDragging.ts

@@ -1,8 +1,9 @@
 import { default as DateComponent, Seg } from '../component/DateComponent'
 import { PointerDragEvent } from '../dnd/PointerDragListener'
-import HitDragListener, { isHitsEqual } from '../dnd/HitDragListener'
-import { createMutation, EventMutation, computeEventDisplacement } from '../reducers/event-mutation'
+import HitDragListener, { isHitsEqual, Hit } from '../dnd/HitDragListener'
+import { EventMutation, computeEventDisplacement, diffDates } from '../reducers/event-mutation'
 import { GlobalContext } from '../common/GlobalContext'
+import { startOfDay } from '../datelib/marker'
 
 export default class EventDragging {
 
@@ -87,17 +88,7 @@ export default class EventDragging {
   onHitOver = (hit, ev) => {
     let { initialHit } = this.hitListener
 
-    this.mutation = createMutation(
-      initialHit.range,
-      initialHit.isAllDay,
-      hit.range,
-      hit.isAllDay,
-      this.draggingSeg.eventRange.eventDef.hasEnd,
-      hit.component === initialHit.component ?
-        hit.component.largeUnit :
-        null,
-      hit.component.getDateEnv()
-    )
+    this.mutation = computeEventMutation(initialHit, hit)
 
     let calendar = hit.component.getCalendar()
     let displacement = computeEventDisplacement(
@@ -175,3 +166,35 @@ export default class EventDragging {
   }
 
 }
+
+function computeEventMutation(hit0: Hit, hit1: Hit): EventMutation {
+  let date0 = hit0.range.start
+  let date1 = hit1.range.start
+  let standardProps = null
+
+  if (hit0.isAllDay !== hit1.isAllDay) {
+    standardProps = {
+      hasEnd: false, // TODO: make this a setting
+      isAllDay: hit1.isAllDay
+    }
+
+    if (hit1.isAllDay) {
+      // means date1 is already start-of-day,
+      // but date0 needs to be converted
+      date0 = startOfDay(date0)
+    }
+  }
+
+  let dateDelta = diffDates(
+    date0, date1,
+    hit0.component.getDateEnv(),
+    hit0.component === hit1.component ?
+      hit0.component.largeUnit :
+      null
+  )
+
+  return {
+    dateDelta,
+    standardProps
+  }
+}

+ 58 - 80
src/reducers/event-mutation.ts

@@ -1,67 +1,19 @@
 import UnzonedRange from '../models/UnzonedRange'
-import { DateEnv } from '../datelib/env'
-import { diffDayAndTime } from '../datelib/marker'
+import { diffDayAndTime, diffDays, startOfDay, addDays } from '../datelib/marker'
 import { Duration, createDuration } from '../datelib/duration'
 import { EventStore, EventDef, EventInstance } from './event-store'
 import { assignTo } from '../util/object'
 import Calendar from '../Calendar'
 
 export interface EventMutation {
-  startDelta?: Duration
+  dateDelta?: Duration
   endDelta?: Duration
-  standardProps: object // for the def
-  extendedProps: object // for the def
-}
-
-// Creating
-
-export function createMutation(
-  range0: UnzonedRange,
-  isAllDay0: boolean,
-  range1: UnzonedRange,
-  isAllDay1: boolean,
-  hasEnd: boolean,
-  largeUnit: string,
-  dateEnv: DateEnv
-): EventMutation {
-  let startDelta: Duration = null
-  let endDelta: Duration = null
-  let standardProps = {} as any
-
-  // subtracts the dates in the appropriate way, returning a duration
-  function diffDates(date0, date1) {
-    if (largeUnit === 'year') {
-      return createDuration(dateEnv.diffWholeYears(date0, date1), 'year')
-    } else if (largeUnit === 'month') {
-      return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month')
-    } else {
-      return diffDayAndTime(date0, date1) // returns a duration
-    }
-  }
-
-  startDelta = diffDates(range0.start, range1.start)
-  endDelta = diffDates(range0.end, range1.end)
-
-  if (isAllDay0 !== isAllDay1) {
-    standardProps.isAllDay = isAllDay1
-
-    if (hasEnd) {
-      standardProps.hasEnd = false
-    }
-  }
-
-  return {
-    startDelta,
-    endDelta,
-    standardProps: standardProps,
-    extendedProps: {}
-  }
+  standardProps?: any // for the def
+  extendedProps?: any // for the def
 }
 
 export function computeEventDisplacement(eventStore: EventStore, instanceId: string, mutation: EventMutation, calendar: Calendar): EventStore {
   let newStore = { defs: {}, instances: {} } // TODO: better name
-
-  const dateEnv = calendar.dateEnv
   let eventInstance = eventStore.instances[instanceId]
   let eventDef = eventStore.defs[eventInstance.defId]
 
@@ -78,12 +30,13 @@ export function computeEventDisplacement(eventStore: EventStore, instanceId: str
 
     for (let instanceId in eventStore.instances) {
       let instance = eventStore.instances[instanceId]
+      let def = newStore.defs[instance.defId] // the already-modified version
 
       if (
         instance === eventInstance ||
         matchGroupId && matchGroupId === eventStore.defs[instance.defId].groupId
       ) {
-        newStore.instances[instanceId] = applyMutationToInstance(instance, mutation, dateEnv)
+        newStore.instances[instanceId] = applyMutationToInstance(instance, def, mutation, calendar)
       }
     }
   }
@@ -103,41 +56,66 @@ export function applyMutation(eventStore: EventStore, instanceId: string, mutati
 }
 
 function applyMutationToDef(eventDef: EventDef, mutation: EventMutation) {
+  let copy = assignTo({}, eventDef)
 
-  if (mutation.standardProps != null || mutation.extendedProps != null) {
-    eventDef = assignTo({}, eventDef)
-
-    if (mutation.standardProps != null) {
-      assignTo(eventDef, mutation.standardProps)
-    }
+  if (mutation.standardProps) {
+    assignTo(copy, mutation.standardProps)
+  }
 
-    if (mutation.extendedProps != null) {
-      eventDef.extendedProps = assignTo({}, eventDef.extendedProps, mutation.extendedProps)
-    }
+  if (mutation.extendedProps) {
+    copy.extendedProps = assignTo({}, copy.extendedProps, mutation.extendedProps)
   }
 
-  return eventDef
+  return copy
 }
 
-function applyMutationToInstance(eventInstance: EventInstance, mutation: EventMutation, dateEnv: DateEnv) {
-
-  if (mutation.startDelta || mutation.endDelta) {
-    eventInstance = assignTo({}, eventInstance)
+function applyMutationToInstance(
+  eventInstance: EventInstance,
+  eventDef: EventDef, // after already having been modified
+  mutation: EventMutation,
+  calendar: Calendar
+) {
+  let dateEnv = calendar.dateEnv
+  let forceIsAllDay = mutation.standardProps && mutation.standardProps.isAllDay === true
+  let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false
+  let copy = assignTo({}, eventInstance)
+
+  if (forceIsAllDay) {
+    // TODO: make a util for this?
+    let dayCnt = Math.floor(diffDays(copy.range.start, copy.range.end)) || 1
+    let start = startOfDay(copy.range.start)
+    let end = addDays(start, dayCnt)
+    copy.range = new UnzonedRange(start, end)
+  }
 
-    if (mutation.startDelta) {
-      eventInstance.range = new UnzonedRange(
-        dateEnv.add(eventInstance.range.start, mutation.startDelta),
-        eventInstance.range.end
-      )
-    }
+  if (mutation.dateDelta) {
+    copy.range = new UnzonedRange(
+      dateEnv.add(copy.range.start, mutation.dateDelta),
+      dateEnv.add(copy.range.end, mutation.dateDelta)
+    )
+  }
 
-    if (mutation.endDelta) {
-      eventInstance.range = new UnzonedRange(
-        eventInstance.range.start,
-        dateEnv.add(eventInstance.range.end, mutation.endDelta),
-      )
-    }
+  if (clearEnd) {
+    copy.range = new UnzonedRange(
+      copy.range.start,
+      calendar.getDefaultEventEnd(eventDef.isAllDay, copy.range.start)
+    )
+  } else if (mutation.endDelta) {
+    copy.range = new UnzonedRange(
+      copy.range.end,
+      dateEnv.add(copy.range.end, mutation.endDelta),
+    )
   }
 
-  return eventInstance
+  return copy
+}
+
+export function diffDates(date0, date1, dateEnv, largeUnit) {
+  if (largeUnit === 'year') {
+    return createDuration(dateEnv.diffWholeYears(date0, date1), 'year')
+  } else if (largeUnit === 'month') {
+    return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month')
+  } else {
+    return diffDayAndTime(date0, date1) // returns a duration
+  }
 }