Bladeren bron

fix up how we do business hour rendering

Adam Shaw 7 jaren geleden
bovenliggende
commit
8a523990fc

+ 0 - 19
src/Calendar.ts

@@ -13,7 +13,6 @@ import ViewSpecManager from './ViewSpecManager'
 import View from './View'
 import View from './View'
 import Theme from './theme/Theme'
 import Theme from './theme/Theme'
 import UnzonedRange from './models/UnzonedRange'
 import UnzonedRange from './models/UnzonedRange'
-import BusinessHourGenerator from './models/BusinessHourGenerator'
 import { getThemeSystemClass } from './theme/ThemeRegistry'
 import { getThemeSystemClass } from './theme/ThemeRegistry'
 import { RangeInput, OptionsInput, EventObjectInput, EventSourceInput } from './types/input-types'
 import { RangeInput, OptionsInput, EventObjectInput, EventSourceInput } from './types/input-types'
 import { getLocale } from './datelib/locale'
 import { getLocale } from './datelib/locale'
@@ -50,7 +49,6 @@ export default class Calendar {
   theme: Theme
   theme: Theme
   optionsManager: OptionsManager
   optionsManager: OptionsManager
   viewSpecManager: ViewSpecManager
   viewSpecManager: ViewSpecManager
-  businessHourGenerator: BusinessHourGenerator
 
 
   defaultAllDayEventDuration: Duration
   defaultAllDayEventDuration: Duration
   defaultTimedEventDuration: Duration
   defaultTimedEventDuration: Duration
@@ -416,16 +414,6 @@ export default class Calendar {
       }
       }
     })
     })
 
 
-    this.optionsManager.watch('settingBusinessHourGenerator', [ '?businessHours' ], (deps) => {
-      this.businessHourGenerator = new BusinessHourGenerator(deps.businessHours, this)
-
-      if (this.view) {
-        this.view.set('businessHourGenerator', this.businessHourGenerator)
-      }
-    }, () => {
-      this.businessHourGenerator = null
-    })
-
     // called immediately, and upon option change.
     // called immediately, and upon option change.
     // HACK: locale often affects isRTL, so we explicitly listen to that too.
     // HACK: locale often affects isRTL, so we explicitly listen to that too.
     this.optionsManager.watch('applyingDirClasses', [ '?isRTL', '?locale' ], (opts) => {
     this.optionsManager.watch('applyingDirClasses', [ '?isRTL', '?locale' ], (opts) => {
@@ -469,7 +457,6 @@ export default class Calendar {
 
 
     // removes theme-related root className
     // removes theme-related root className
     this.optionsManager.unwatch('settingTheme')
     this.optionsManager.unwatch('settingTheme')
-    this.optionsManager.unwatch('settingBusinessHourGenerator')
 
 
     if (this.removeNavLinkListener) {
     if (this.removeNavLinkListener) {
       this.removeNavLinkListener()
       this.removeNavLinkListener()
@@ -563,12 +550,6 @@ export default class Calendar {
     }
     }
 
 
     if (this.view) {
     if (this.view) {
-
-      // prevent unnecessary change firing
-      if (this.view.get('businessHourGenerator') !== this.businessHourGenerator) {
-        this.view.set('businessHourGenerator', this.businessHourGenerator)
-      }
-
       this.view.setDate(this.currentDate)
       this.view.setDate(this.currentDate)
 
 
       if (newView) {
       if (newView) {

+ 2 - 1
src/OptionsManager.ts

@@ -42,7 +42,8 @@ export default class OptionsManager extends Model {
       } else if (optionName === 'defaultDate') {
       } else if (optionName === 'defaultDate') {
         return // can't change date this way. use gotoDate instead
         return // can't change date this way. use gotoDate instead
       } else if (optionName === 'businessHours') {
       } else if (optionName === 'businessHours') {
-        return // this model already reacts to this
+        this._calendar.view.flash('displayingBusinessHours')
+        return
       } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(optionName)) {
       } else if (/^(event|select)(Overlap|Constraint|Allow)$/.test(optionName)) {
         return // doesn't affect rendering. only interactions.
         return // doesn't affect rendering. only interactions.
       } else if (optionName === 'timezone') {
       } else if (optionName === 'timezone') {

+ 4 - 4
src/View.ts

@@ -365,9 +365,9 @@ export default abstract class View extends InteractiveDateComponent {
   // -----------------------------------------------------------------------------------------------------------------
   // -----------------------------------------------------------------------------------------------------------------
 
 
 
 
-  requestBusinessHoursRender(businessHourGenerator) {
+  requestBusinessHoursRender() {
     this.requestRender(() => {
     this.requestRender(() => {
-      this.renderBusinessHours(businessHourGenerator)
+      this.renderBusinessHours(this.opt('businessHours'))
     }, 'businessHours', 'init')
     }, 'businessHours', 'init')
   }
   }
 
 
@@ -844,8 +844,8 @@ View.watch('displayingDates', [ 'isInDom', 'dateProfile' ], function(deps) {
 })
 })
 
 
 
 
-View.watch('displayingBusinessHours', [ 'displayingDates', 'businessHourGenerator' ], function(deps) {
-  this.requestBusinessHoursRender(deps.businessHourGenerator)
+View.watch('displayingBusinessHours', [ 'displayingDates' ], function() {
+  this.requestBusinessHoursRender()
 }, function() {
 }, function() {
   this.requestBusinessHoursUnrender()
   this.requestBusinessHoursUnrender()
 })
 })

+ 16 - 10
src/component/DateComponent.ts

@@ -10,6 +10,7 @@ import { Selection } from '../reducers/selection'
 import UnzonedRange from '../models/UnzonedRange'
 import UnzonedRange from '../models/UnzonedRange'
 import { Seg } from '../reducers/seg'
 import { Seg } from '../reducers/seg'
 import { EventDef, EventInstance, parseDef, createInstance } from '../reducers/event-store'
 import { EventDef, EventInstance, parseDef, createInstance } from '../reducers/event-store'
+import { BusinessHourDef, buildBusinessHourEventRenderRanges } from '../reducers/business-hours'
 
 
 
 
 export default abstract class DateComponent extends Component {
 export default abstract class DateComponent extends Component {
@@ -183,9 +184,18 @@ export default abstract class DateComponent extends Component {
   // ---------------------------------------------------------------------------------------------------------------
   // ---------------------------------------------------------------------------------------------------------------
 
 
 
 
-  renderBusinessHours(businessHourGenerator) {
+  renderBusinessHours(businessHoursDef: BusinessHourDef) {
     if (this.businessHourRenderer) {
     if (this.businessHourRenderer) {
-      this.businessHourRenderer.render(businessHourGenerator)
+      this.businessHourRenderer.renderSegs(
+        this.eventRangesToSegs(
+          buildBusinessHourEventRenderRanges(
+            businessHoursDef,
+            this.hasAllDayBusinessHours,
+            this.dateProfile.activeUnzonedRange,
+            this._getCalendar()
+          )
+        )
+      )
     }
     }
 
 
     this.callChildren('renderBusinessHours', arguments)
     this.callChildren('renderBusinessHours', arguments)
@@ -458,15 +468,11 @@ export default abstract class DateComponent extends Component {
   // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
   // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data)
   renderHighlightSegs(segs) {
   renderHighlightSegs(segs) {
     if (this.fillRenderer) {
     if (this.fillRenderer) {
-      this.fillRenderer.renderSegs(
-        'highlight',
-        segs,
-        {
-          getClasses() {
-            return [ 'fc-highlight' ]
-          }
+      this.fillRenderer.renderSegs('highlight', segs, {
+        getClasses() {
+          return [ 'fc-highlight' ]
         }
         }
-      )
+      })
     }
     }
   }
   }
 
 

+ 1 - 1
src/component/renderers/BusinessHourRenderer.ts

@@ -16,7 +16,7 @@ export default class BusinessHourRenderer {
     if (this.fillRenderer) {
     if (this.fillRenderer) {
       this.fillRenderer.renderSegs('businessHours', segs, {
       this.fillRenderer.renderSegs('businessHours', segs, {
         getClasses(seg) {
         getClasses(seg) {
-          return [ 'fc-nonbusiness', 'fc-bgevent' ]
+          return [ 'fc-bgevent' ].concat(seg.eventRange.eventDef.className)
         }
         }
       })
       })
     }
     }

+ 0 - 1
src/exports.ts

@@ -75,7 +75,6 @@ export { default as EmitterMixin, EmitterInterface } from './common/EmitterMixin
 export { default as ListenerMixin, ListenerInterface } from './common/ListenerMixin'
 export { default as ListenerMixin, ListenerInterface } from './common/ListenerMixin'
 export { default as Model } from './common/Model'
 export { default as Model } from './common/Model'
 export { default as UnzonedRange } from './models/UnzonedRange'
 export { default as UnzonedRange } from './models/UnzonedRange'
-export { default as BusinessHourGenerator } from './models/BusinessHourGenerator'
 export { defineThemeSystem } from './theme/ThemeRegistry'
 export { defineThemeSystem } from './theme/ThemeRegistry'
 export { default as Class } from './common/Class'
 export { default as Class } from './common/Class'
 export { default as Mixin } from './common/Mixin'
 export { default as Mixin } from './common/Mixin'

+ 0 - 88
src/models/BusinessHourGenerator.ts

@@ -1,88 +0,0 @@
-import { assignTo } from '../util/object'
-import { eventDefsToEventInstances } from '../models/event/util'
-import EventInstanceGroup from './event/EventInstanceGroup'
-import RecurringEventDef from './event/RecurringEventDef'
-import EventSource from './event-source/EventSource'
-
-
-let BUSINESS_HOUR_EVENT_DEFAULTS = {
-  start: '09:00',
-  end: '17:00',
-  dow: [ 1, 2, 3, 4, 5 ], // monday - friday
-  rendering: 'inverse-background'
-  // classNames are defined in businessHoursSegClasses
-}
-
-
-export default class BusinessHourGenerator {
-
-  rawComplexDef: any
-  calendar: any // for anonymous EventSource
-
-
-  constructor(rawComplexDef, calendar) {
-    this.rawComplexDef = rawComplexDef
-    this.calendar = calendar
-  }
-
-
-  buildEventInstanceGroup(isAllDay, unzonedRange) {
-    let eventDefs = this.buildEventDefs(isAllDay)
-    let eventInstanceGroup
-
-    if (eventDefs.length) {
-      eventInstanceGroup = new EventInstanceGroup(
-        eventDefsToEventInstances(eventDefs, unzonedRange)
-      )
-
-      // so that inverse-background rendering can happen even when no eventRanges in view
-      eventInstanceGroup.explicitEventDef = eventDefs[0]
-
-      return eventInstanceGroup
-    }
-  }
-
-
-  buildEventDefs(isAllDay) {
-    let rawComplexDef = this.rawComplexDef
-    let rawDefs = []
-    let requireDow = false
-    let i
-    let defs = []
-
-    if (rawComplexDef === true) {
-      rawDefs = [ {} ] // will get BUSINESS_HOUR_EVENT_DEFAULTS verbatim
-    } else if (Array.isArray(rawComplexDef)) {
-      rawDefs = rawComplexDef
-      requireDow = true // every sub-definition NEEDS a day-of-week
-    } else if (typeof rawComplexDef === 'object' && rawComplexDef) { // non-null object
-      rawDefs = [ rawComplexDef ]
-    }
-
-    for (i = 0; i < rawDefs.length; i++) {
-      if (!requireDow || rawDefs[i].dow) {
-        defs.push(
-          this.buildEventDef(isAllDay, rawDefs[i])
-        )
-      }
-    }
-
-    return defs
-  }
-
-
-  buildEventDef(isAllDay, rawDef) {
-    let fullRawDef = assignTo({}, BUSINESS_HOUR_EVENT_DEFAULTS, rawDef)
-
-    if (isAllDay) {
-      fullRawDef.start = null
-      fullRawDef.end = null
-    }
-
-    return RecurringEventDef.parse(
-      fullRawDef,
-      new EventSource(this.calendar) // dummy source
-    )
-  }
-
-}

+ 87 - 0
src/reducers/business-hours.ts

@@ -0,0 +1,87 @@
+import Calendar from '../Calendar'
+import { EventRenderRange, sliceEventRanges } from '../reducers/event-rendering'
+import UnzonedRange from '../models/UnzonedRange'
+import { EventInput } from './event-store'
+import { assignTo } from '../util/object'
+import { expandRecurring } from './recurring-events'
+import { parseDef, createInstance } from './event-store'
+
+export type BusinessHourDef = true | EventInput | EventInput[] // TODO: rename to plural?
+
+const BUSINESS_HOUR_EVENT_DEFAULTS = {
+  startTime: '09:00',
+  endTime: '17:00',
+  daysOfWeek: [ 1, 2, 3, 4, 5 ], // monday - friday
+  rendering: 'inverse-background',
+  groupId: 'business-hours', // for inverse-rendering
+  className: 'fc-nonbusiness'
+}
+
+
+export function buildBusinessHourEventRenderRanges(
+  input: BusinessHourDef,
+  isAllDay: boolean,
+  framingRange: UnzonedRange,
+  calendar: Calendar
+): EventRenderRange[] {
+  let eventRanges = buildBusinessHourEventRanges(input, isAllDay, framingRange, calendar)
+
+  return sliceEventRanges(eventRanges, framingRange)
+}
+
+
+export function buildBusinessHourEventRanges(
+  input: BusinessHourDef,
+  isAllDay: boolean,
+  framingRange: UnzonedRange,
+  calendar: Calendar
+): EventRenderRange[] {
+  let eventInputs = refineEventInputs(input, isAllDay)
+  let eventRanges: EventRenderRange[] = []
+
+  for (let eventInput of eventInputs) {
+    let dateInfo = expandRecurring(eventInput, framingRange, calendar)
+    let def = parseDef(eventInput, null, isAllDay, true)
+
+    for (let range of dateInfo.ranges) {
+      let instance = createInstance(def.defId, range)
+
+      eventRanges.push({
+        eventDef: def,
+        eventInstance: instance,
+        range
+      })
+    }
+  }
+
+  return eventRanges
+}
+
+
+function refineEventInputs(input: BusinessHourDef, isAllDay: boolean): EventInput[] {
+  let rawDefs: EventInput[]
+
+  if (input === true) {
+    rawDefs = [ {} ] // will get BUSINESS_HOUR_EVENT_DEFAULTS verbatim
+  } else if (Array.isArray(input)) {
+    // if specifying an array, every sub-definition NEEDS a day-of-week
+    rawDefs = input.filter(function(rawDef) {
+      return rawDef.daysOfWeek
+    })
+  } else if (typeof input === 'object' && input) { // non-null object
+    rawDefs = [ input ]
+  }
+
+  rawDefs = rawDefs.map(function(rawDef) {
+    rawDef = assignTo({}, BUSINESS_HOUR_EVENT_DEFAULTS, rawDef)
+
+    if (isAllDay) {
+      rawDef.startTime = null
+      rawDef.endTime = null
+    }
+
+    return rawDef
+  })
+
+  return rawDefs
+}