import { DateRange } from '../datelib/date-range' ; import { EventStore } from '../structs/event-store' ; import { EventUiHash } from '../component/event-ui' ; import { sliceEventStore , EventRenderRange } from '../component/event-rendering' ; import { DateProfile } from '../DateProfileGenerator' ; import { Seg , EventSegUiInteractionState } from '../component/DateComponent' ; import { DateSpan , fabricateEventRange } from '../structs/date-span' ; import { EventInteractionState } from '../interactions/event-interaction-state' ; import { Duration } from '../datelib/duration' ; import { memoize } from '../util/memoize' ; import { DateMarker , addMs , addDays } from '../datelib/marker' ; import { CalendarContext } from '../CalendarContext' ; import { expandRecurring } from '../structs/recurring-event' ; export interface SliceableProps { dateSelection : DateSpan ; businessHours : EventStore ; eventStore : EventStore ; eventDrag : EventInteractionState | null ; eventResize : EventInteractionState | null ; eventSelection : string ; eventUiBases : EventUiHash ; } export interface SlicedProps < SegType extends Seg > { dateSelectionSegs : SegType [ ] ; businessHourSegs : SegType [ ] ; fgEventSegs : SegType [ ] ; bgEventSegs : SegType [ ] ; eventDrag : EventSegUiInteractionState | null ; eventResize : EventSegUiInteractionState | null ; eventSelection : string ; } export abstract class Slicer < SegType extends Seg , ExtraArgs extends any [ ] = [ ] > { private sliceBusinessHours = memoize ( this . _sliceBusinessHours ) ; private sliceDateSelection = memoize ( this . _sliceDateSpan ) ; private sliceEventStore = memoize ( this . _sliceEventStore ) ; private sliceEventDrag = memoize ( this . _sliceInteraction ) ; private sliceEventResize = memoize ( this . _sliceInteraction ) ; abstract sliceRange ( dateRange , ... extraArgs ) ; protected forceDayIfListItem = false ; sliceProps ( props , dateProfile , nextDayThreshold , context , ... extraArgs ) { let { eventUiBases } = props ; let eventSegs = this . sliceEventStore ( props . eventStore , eventUiBases , dateProfile , nextDayThreshold , ... extraArgs ) ; return { dateSelectionSegs : this . sliceDateSelection ( props . dateSelection , eventUiBases , context , ... extraArgs ) , businessHourSegs : this . sliceBusinessHours ( props . businessHours , dateProfile , nextDayThreshold , context , ... extraArgs ) , fgEventSegs : eventSegs . fg , bgEventSegs : eventSegs . bg , eventDrag : this . sliceEventDrag ( props . eventDrag , eventUiBases , dateProfile , nextDayThreshold , ... extraArgs ) , eventResize : this . sliceEventResize ( props . eventResize , eventUiBases , dateProfile , nextDayThreshold , ... extraArgs ) , eventSelection : props . eventSelection , } ; } sliceNowDate ( date , context , ... extraArgs ) { return this . _sliceDateSpan ( { range : { start : date , end : addMs ( date , 1 ) } , allDay : false } , { } , context , ... extraArgs ) ; } private _sliceBusinessHours ( businessHours , dateProfile , nextDayThreshold , context , ... extraArgs ) { if ( ! businessHours ) { return [ ] ; } return this . _sliceEventStore ( expandRecurring ( businessHours , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , context ) , { } , dateProfile , nextDayThreshold , ... extraArgs ) . bg ; } private _sliceEventStore ( eventStore , eventUiBases , dateProfile , nextDayThreshold , ... extraArgs ) { if ( eventStore ) { let rangeRes = sliceEventStore ( eventStore , eventUiBases , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , nextDayThreshold ) ; return { bg : this . sliceEventRanges ( rangeRes . bg , extraArgs ) , fg : this . sliceEventRanges ( rangeRes . fg , extraArgs ) , } ; } return { bg : [ ] , fg : [ ] } ; } private _sliceInteraction ( interaction , eventUiBases , dateProfile , nextDayThreshold , ... extraArgs ) { if ( ! interaction ) { return null ; } let rangeRes = sliceEventStore ( interaction . mutatedEvents , eventUiBases , computeActiveRange ( dateProfile , Boolean ( nextDayThreshold ) ) , nextDayThreshold ) ; return { segs : this . sliceEventRanges ( rangeRes . fg , extraArgs ) , affectedInstances : interaction . affectedEvents . instances , isEvent : interaction . isEvent , } ; } private _sliceDateSpan ( dateSpan , eventUiBases , context , ... extraArgs ) { if ( ! dateSpan ) { return [ ] ; } let eventRange = fabricateEventRange ( dateSpan , eventUiBases , context ) ; let segs = this . sliceRange ( dateSpan . range , ... extraArgs ) ; for ( let seg of segs ) { seg . eventRange = eventRange ; } return segs ; } private sliceEventRanges ( eventRanges , extraArgs ) { let segs = [ ] ; for ( let eventRange of eventRanges ) { segs . push ( ... this . sliceEventRange ( eventRange , extraArgs ) ) ; } return segs ; } private sliceEventRange ( eventRange , extraArgs ) { let dateRange = eventRange . range ; if ( this . forceDayIfListItem && eventRange . ui . display === 'list-item' ) { dateRange = { start : dateRange . start , end : addDays ( dateRange . start , 1 ) , } ; } let segs = this . sliceRange ( dateRange , ... extraArgs ) ; for ( let seg of segs ) { seg . eventRange = eventRange ; seg . isStart = eventRange . isStart && seg . isStart ; seg . isEnd = eventRange . isEnd && seg . isEnd ; } return segs ; } } function computeActiveRange ( dateProfile , isComponentAllDay ) { let range = dateProfile . activeRange ; if ( isComponentAllDay ) { return range ; } return { start : addMs ( range . start , dateProfile . slotMinTime . milliseconds ) , end : addMs ( range . end , dateProfile . slotMaxTime . milliseconds - 864e5 ) , } ; }