Skip to content

Commit

Permalink
when recur event parsing, change how allDay parses. fixes #4576
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Apr 2, 2019
1 parent 2b20a46 commit f27c39f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 46 deletions.
18 changes: 4 additions & 14 deletions src/core/structs/recurring-event-simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Duration, createDuration, subtractDurations } from '../datelib/duration
import { arrayToHash } from '../util/object'
import { refineProps } from '../util/misc'
import { RecurringType, ParsedRecurring } from './recurring-event'
import { EventInput, EventDef } from './event'
import { EventInput } from './event'
import { DateRange, intersectRanges } from '../datelib/date-range'
import { DateEnv } from '../datelib/env'
import { createPlugin } from '../plugin-system'
Expand All @@ -26,7 +26,7 @@ interface SimpleParsedRecurring extends ParsedRecurring {

let recurring: RecurringType = {

parse(rawEvent: EventInput, allDayDefault: boolean | null, leftoverProps: any, dateEnv: DateEnv): SimpleParsedRecurring | null {
parse(rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv): SimpleParsedRecurring | null {
let createMarker = dateEnv.createMarker.bind(dateEnv)
let processors = {
daysOfWeek: null,
Expand All @@ -46,19 +46,9 @@ let recurring: RecurringType = {
}
}

let allDay

if (props.startTime || props.endTime) {
allDay = false
} else if (allDayDefault != null) {
allDay = allDayDefault
} else {
allDay = true
}

if (anyValid) {
return {
allDay,
allDayGuess: Boolean(!props.startTime && !props.endTime),
duration: (props.startTime && props.endTime) ?
subtractDurations(props.endTime, props.startTime) :
null,
Expand All @@ -69,7 +59,7 @@ let recurring: RecurringType = {
return null
},

expand(typeData: SimpleRecurringData, eventDef: EventDef, framingRange: DateRange, dateEnv: DateEnv): DateMarker[] {
expand(typeData: SimpleRecurringData, framingRange: DateRange, dateEnv: DateEnv): DateMarker[] {
let clippedFramingRange = intersectRanges(
framingRange,
{ start: typeData.startRecur, end: typeData.endRecur }
Expand Down
36 changes: 25 additions & 11 deletions src/core/structs/recurring-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,24 @@ import { DateRange } from '../datelib/date-range'
import { DateEnv } from '../datelib/env'
import { Duration } from '../datelib/duration'
import { DateMarker, startOfDay } from '../datelib/marker'
import { __assign } from 'tslib'

/*
The plugin system for defining how a recurring event is expanded into individual instances.
*/

export interface ParsedRecurring {
allDay: boolean // last fallback to be used
duration: Duration | null // signals hasEnd
typeData: any
allDayGuess: boolean | null
duration: Duration | null // signals hasEnd
}

export interface RecurringType {
parse: (rawEvent: EventInput, allDayDefault: boolean | null, leftoverProps: any, dateEnv: DateEnv) => ParsedRecurring | null
expand: (typeData: any, eventDef: EventDef, framingRange: DateRange, dateEnv: DateEnv) => DateMarker[]
parse: (rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv) => ParsedRecurring | null
expand: (typeData: any, framingRange: DateRange, dateEnv: DateEnv) => DateMarker[]
}


/*
KNOWN BUG: will populate lefovers only up until a recurring type works
*/
export function parseRecurring(
eventInput: EventInput,
allDayDefault: boolean | null,
Expand All @@ -31,15 +29,32 @@ export function parseRecurring(
leftovers: any
) {
for (let i = 0; i < recurringTypes.length; i++) {
let parsed = recurringTypes[i].parse(eventInput, allDayDefault, leftovers, dateEnv) as ParsedRecurring
let localLeftovers = {} as any
let parsed = recurringTypes[i].parse(eventInput, localLeftovers, dateEnv) as ParsedRecurring

if (parsed) {
return { // more efficient way to do this?
allDay: parsed.allDay,

let allDay = localLeftovers.allDay
delete localLeftovers.allDay // remove from leftovers
if (allDay == null) {
allDay = allDayDefault
if (allDay == null) {
allDay = parsed.allDayGuess
if (allDay == null) {
allDay = false
}
}
}

__assign(leftovers, localLeftovers)

return {
allDay,
duration: parsed.duration,
typeData: parsed.typeData,
typeId: i
}

}
}

Expand All @@ -59,7 +74,6 @@ export function expandRecurringRanges(
let typeDef = recurringTypes[eventDef.recurringDef.typeId]
let markers = typeDef.expand(
eventDef.recurringDef.typeData,
eventDef,
framingRange,
dateEnv
)
Expand Down
36 changes: 15 additions & 21 deletions src/rrule/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
EventInput,
refineProps,
DateEnv,
EventDef,
DateRange,
DateMarker,
createDuration,
Expand All @@ -23,24 +22,24 @@ const EVENT_DEF_PROPS = {

let recurring: RecurringType = {

parse(rawEvent: EventInput, allDayDefault: boolean | null, leftoverProps: any, dateEnv: DateEnv): RRuleParsedRecurring | null {
parse(rawEvent: EventInput, leftoverProps: any, dateEnv: DateEnv): RRuleParsedRecurring | null {
if (rawEvent.rrule != null) {
let props = refineProps(rawEvent, EVENT_DEF_PROPS, {}, leftoverProps)
let parsed = parseRRule(props.rrule, allDayDefault, dateEnv)
let parsed = parseRRule(props.rrule, dateEnv)

if (parsed) {
return {
allDay: parsed.allDay,
duration: props.duration,
typeData: parsed.rrule
typeData: parsed.rrule,
allDayGuess: parsed.allDayGuess,
duration: props.duration
}
}
}

return null
},

expand(rrule: RRule, eventDef: EventDef, framingRange: DateRange): DateMarker[] {
expand(rrule: RRule, framingRange: DateRange): DateMarker[] {
// we WANT an inclusive start and in exclusive end, but the js rrule lib will only do either BOTH
// inclusive or BOTH exclusive, which is stupid: https://github.com/jakubroztocil/rrule/issues/84
// Workaround: make inclusive, which will generate extra occurences, and then trim.
Expand All @@ -56,24 +55,22 @@ export default createPlugin({
recurringTypes: [ recurring ]
})

function parseRRule(input, allDayDefault: boolean | null, dateEnv: DateEnv) {
function parseRRule(input, dateEnv: DateEnv) {
let allDayGuess = null
let rrule

if (typeof input === 'string') {
return {
rrule: rrulestr(input),
allDay: false
}
rrule = rrulestr(input)

} else if (typeof input === 'object' && input) { // non-null object
let refined = { ...input } // copy
let allDay = allDayDefault

if (typeof refined.dtstart === 'string') {
let dtstartMeta = dateEnv.createMarkerMeta(refined.dtstart)

if (dtstartMeta) {
refined.dtstart = dtstartMeta.marker
allDay = dtstartMeta.isTimeUnspecified
allDayGuess = dtstartMeta.isTimeUnspecified
} else {
delete refined.dtstart
}
Expand All @@ -97,14 +94,11 @@ function parseRRule(input, allDayDefault: boolean | null, dateEnv: DateEnv) {
refined.byweekday = convertConstants(refined.byweekday) // the plural version
}

if (allDay == null) { // if not specific event after allDayDefault
allDay = true
}
rrule = new RRule(refined)
}

return {
rrule: new RRule(refined),
allDay
}
if (rrule) {
return { rrule, allDayGuess }
}

return null
Expand Down
15 changes: 15 additions & 0 deletions tests/automated/datelib/rrule.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ describe('rrule plugin', function() {
expect(events[4].start).toEqualDate('2018-10-02T13:00:00Z')
})

it('respects allDay when an rrule string', function() {
initCalendar({
events: [
{
allDay: true,
rrule: 'DTSTART:20180904T130000\nRRULE:FREQ=WEEKLY'
}
]
})
let events = getSortedEvents()
expect(events[0].start).toEqualDate('2018-09-04') // should round down
expect(events[0].allDay).toBe(true)
expect(events[0].extendedProps).toEqual({}) // didnt accumulate allDay or rrule props
})

it('expands events when given an rrule object', function() {
initCalendar({
events: [
Expand Down

0 comments on commit f27c39f

Please sign in to comment.