Adam Shaw 7 роки тому
батько
коміт
ba5c365086

+ 11 - 20
plugins/rrule/main.ts

@@ -1,25 +1,26 @@
 import { RRule, rrulestr } from 'rrule'
-import { registerRecurringType, ParsedRecurring, EventInput, refineProps, DateEnv, EventDef, DateRange, Calendar, DateMarker } from 'fullcalendar'
+import { registerRecurringType, ParsedRecurring, EventInput, refineProps, DateEnv, EventDef, DateRange, DateMarker, createDuration } from 'fullcalendar'
 
 interface RRuleParsedRecurring extends ParsedRecurring {
   typeData: RRule
 }
 
+const EVENT_DEF_PROPS = {
+  rrule: null,
+  duration: createDuration
+}
+
 registerRecurringType({
 
   parse(rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv): RRuleParsedRecurring | null {
     if (rawEvent.rrule != null) {
-
-      let rrule = parseRRule(rawEvent.rrule, dateEnv)
+      let props = refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps)
+      let rrule = parseRRule(props.rrule, dateEnv)
 
       if (rrule) {
-        // put all other props (except rrule) in leftoverProps
-        // TODO: should still remove the rrule prop even if failure?
-        refineProps(rawEvent, { rrule: null }, {}, leftoverProps)
-
         return {
           isAllDay: false, // TODO!!!
-          hasEnd: true, // TODO!!!
+          duration: props.duration,
           typeData: rrule
         }
       }
@@ -28,18 +29,8 @@ registerRecurringType({
     return null
   },
 
-  // TODO: what about duration?!!
-  expand(rrule: RRule, eventDef: EventDef, framingRange: DateRange, calendar: Calendar): DateRange[] {
-    let dateEnv = calendar.dateEnv
-    let duration = calendar.defaultTimedEventDuration
-    let markers = rrule.between(framingRange.start, framingRange.end)
-
-    return markers.map(function(marker: DateMarker) {
-      return {
-        start: marker,
-        end: dateEnv.add(marker, duration)
-      }
-    })
+  expand(rrule: RRule, eventDef: EventDef, framingRange: DateRange): DateMarker[] {
+    return rrule.between(framingRange.start, framingRange.end)
   }
 
 })

+ 14 - 3
src/structs/event-store.ts

@@ -58,6 +58,7 @@ export function eventTupleToStore(tuple: EventTuple, eventStore: EventStore = cr
 }
 
 export function expandRecurring(eventStore: EventStore, framingRange: DateRange, calendar: Calendar): EventStore {
+  let dateEnv = calendar.dateEnv
   let { defs, instances } = eventStore
 
   // remove existing recurring instances
@@ -69,10 +70,20 @@ export function expandRecurring(eventStore: EventStore, framingRange: DateRange,
     let def = defs[defId]
 
     if (def.recurringDef) {
-      let ranges = expandRecurringRanges(def, framingRange, calendar)
+      let starts = expandRecurringRanges(def, framingRange, calendar.dateEnv)
+      let duration = def.recurringDef.duration
 
-      for (let range of ranges) {
-        let instance = createEventInstance(defId, range)
+      if (!duration) {
+        duration = def.isAllDay ?
+          calendar.defaultAllDayEventDuration :
+          calendar.defaultTimedEventDuration
+      }
+
+      for (let start of starts) {
+        let instance = createEventInstance(defId, {
+          start,
+          end: dateEnv.add(start, duration)
+        })
         instances[instance.instanceId] = instance
       }
     }

+ 8 - 3
src/structs/event.ts

@@ -7,6 +7,7 @@ import { DateRange } from '../datelib/date-range'
 import { startOfDay } from '../datelib/marker'
 import { parseRecurring } from './recurring-event'
 import { ConstraintInput, Constraint, normalizeConstraint } from '../validation'
+import { Duration } from '../datelib/duration'
 
 /*
 Utils for parsing event-input data. Each util parses a subset of the event-input's data.
@@ -52,7 +53,7 @@ export interface EventDef {
   groupId: string
   isAllDay: boolean
   hasEnd: boolean
-  recurringDef: { typeId: number, typeData: any } | null
+  recurringDef: { typeId: number, typeData: any, duration: Duration | null } | null
   title: string
   url: string
   startEditable: boolean | null
@@ -139,8 +140,12 @@ export function parseEvent(raw: EventInput, sourceId: string, calendar: Calendar
 
     if (recurringRes) {
       def.isAllDay = recurringRes.isAllDay
-      def.hasEnd = recurringRes.hasEnd
-      def.recurringDef = { typeId: recurringRes.typeId, typeData: recurringRes.typeData }
+      def.hasEnd = Boolean(recurringRes.duration)
+      def.recurringDef = {
+        typeId: recurringRes.typeId,
+        typeData: recurringRes.typeData,
+        duration: recurringRes.duration
+      }
     } else {
       return null // TODO: give a warning
     }

+ 14 - 27
src/structs/recurring-event-simple.ts

@@ -1,11 +1,11 @@
-import { startOfDay, addDays } from '../datelib/marker'
-import { Duration, createDuration } from '../datelib/duration'
+import { startOfDay, addDays, DateMarker } from '../datelib/marker'
+import { Duration, createDuration, subtractDurations } from '../datelib/duration'
 import { arrayToHash } from '../util/object'
 import { refineProps } from '../util/misc'
 import { registerRecurringType, ParsedRecurring } from './recurring-event'
-import Calendar from '../Calendar'
 import { EventInput, EventDef } from './event'
 import { DateRange } from '../datelib/date-range'
+import { DateEnv } from '../datelib/env'
 
 /*
 An implementation of recurring events that only supports every-day or weekly recurrences.
@@ -39,21 +39,22 @@ registerRecurringType({
 
       return {
         isAllDay: !props.startTime && !props.endTime,
-        hasEnd: Boolean(props.endTime),
-        typeData: props
+        duration: (props.startTime && props.endTime) ?
+          subtractDurations(props.endTime, props.startTime) :
+          null,
+        typeData: props // doesn't need endTime anymore but oh well
       }
     }
 
     return null
   },
 
-  expand(typeData: SimpleRecurringData, eventDef: EventDef, framingRange: DateRange, calendar: Calendar): DateRange[] {
+  expand(typeData: SimpleRecurringData, eventDef: EventDef, framingRange: DateRange, dateEnv: DateEnv): DateMarker[] {
     return expandRanges(
       typeData.daysOfWeek,
       typeData.startTime,
-      typeData.endTime,
       framingRange,
-      calendar
+      dateEnv
     )
   }
 
@@ -62,19 +63,16 @@ registerRecurringType({
 function expandRanges(
   daysOfWeek: number[] | null,
   startTime: Duration | null,
-  endTime: Duration | null,
   framingRange: DateRange,
-  calendar: Calendar
-): DateRange[] {
-  let dateEnv = calendar.dateEnv
+  dateEnv: DateEnv
+): DateMarker[] {
   let dowHash: { [num: string]: true } | null = daysOfWeek ? arrayToHash(daysOfWeek) : null
   let dayMarker = startOfDay(framingRange.start)
   let endMarker = framingRange.end
-  let instanceRanges = []
+  let instanceStarts: DateMarker[] = []
 
   while (dayMarker < endMarker) {
     let instanceStart
-    let instanceEnd
 
     // if everyday, or this particular day-of-week
     if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
@@ -85,22 +83,11 @@ function expandRanges(
         instanceStart = dayMarker
       }
 
-      if (endTime) {
-        instanceEnd = dateEnv.add(dayMarker, endTime)
-      } else {
-        instanceEnd = dateEnv.add(
-          instanceStart,
-          startTime ? // a timed event?
-            calendar.defaultTimedEventDuration :
-            calendar.defaultAllDayEventDuration
-        )
-      }
-
-      instanceRanges.push({ start: instanceStart, end: instanceEnd })
+      instanceStarts.push(instanceStart)
     }
 
     dayMarker = addDays(dayMarker, 1)
   }
 
-  return instanceRanges
+  return instanceStarts
 }

+ 7 - 6
src/structs/recurring-event.ts

@@ -1,7 +1,8 @@
-import Calendar from '../Calendar'
 import { EventInput, EventDef } from './event'
 import { DateRange } from '../datelib/date-range'
 import { DateEnv } from '../datelib/env'
+import { Duration } from '../datelib/duration'
+import { DateMarker } from '../datelib/marker'
 
 /*
 The plugin system for defining how a recurring event is expanded into individual instances.
@@ -9,13 +10,13 @@ The plugin system for defining how a recurring event is expanded into individual
 
 export interface ParsedRecurring {
   isAllDay: boolean
-  hasEnd: boolean
+  duration: Duration | null // signals hasEnd
   typeData: any
 }
 
 export interface RecurringType {
   parse: (rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv) => ParsedRecurring | null
-  expand: (typeData: any, eventDef: EventDef, framingRange: DateRange, calendar: Calendar) => DateRange[]
+  expand: (typeData: any, eventDef: EventDef, framingRange: DateRange, dateEnv: DateEnv) => DateMarker[]
 }
 
 
@@ -33,7 +34,7 @@ export function parseRecurring(eventInput: EventInput, leftovers: any, dateEnv:
     if (parsed) {
       return {
         isAllDay: parsed.isAllDay,
-        hasEnd: parsed.hasEnd,
+        duration: parsed.duration,
         typeData: parsed.typeData,
         typeId: i
       }
@@ -47,13 +48,13 @@ export function parseRecurring(eventInput: EventInput, leftovers: any, dateEnv:
 /*
 Event MUST have a recurringDef
 */
-export function expandRecurringRanges(eventDef: EventDef, framingRange: DateRange, calendar: Calendar): DateRange[] {
+export function expandRecurringRanges(eventDef: EventDef, framingRange: DateRange, dateEnv: DateEnv): DateMarker[] {
   let typeDef = recurringTypes[eventDef.recurringDef.typeId]
 
   return typeDef.expand(
     eventDef.recurringDef.typeData,
     eventDef,
     framingRange,
-    calendar
+    dateEnv
   )
 }