Adam Shaw пре 7 година
родитељ
комит
ef132ec5da

+ 3 - 51
src/agenda/AbstractAgendaView.ts

@@ -12,16 +12,13 @@ import TimeGrid from './TimeGrid'
 import DayGrid from '../basic/DayGrid'
 import { createDuration } from '../datelib/duration'
 import { createFormatter } from '../datelib/formatting'
-import { EventStore, filterEventStoreDefs } from '../structs/event-store'
-import { EventInteractionUiState } from '../interactions/event-interaction-state'
-import reselector from '../util/reselector'
-import { hasBgRendering } from '../component/event-rendering'
 import { buildGotoAnchorHtml, getAllDayHtml } from '../component/date-rendering'
 import { diffDays } from '../datelib/marker'
 import { ComponentContext } from '../component/Component'
 import { ViewSpec } from '../structs/view-spec'
 import DateProfileGenerator from '../DateProfileGenerator'
-import { EventUiHash } from '../component/event-ui'
+import { memoizeSplitter } from '../component/event-splitting'
+import AllDaySplitter from './AllDaySplitter'
 
 const AGENDA_ALL_DAY_EVENT_LIMIT = 5
 const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
@@ -40,13 +37,7 @@ export default abstract class AgendaView extends View {
   scroller: ScrollComponent
   axisWidth: any // the width of the time axis running down the side
 
-  // reselectors
-  filterEventsForTimeGrid = reselector(filterEventsForTimeGrid)
-  filterEventsForDayGrid = reselector(filterEventsForDayGrid)
-  buildEventDragForTimeGrid = reselector(buildInteractionForTimeGrid)
-  buildEventDragForDayGrid = reselector(buildInteractionForDayGrid)
-  buildEventResizeForTimeGrid = reselector(buildInteractionForTimeGrid)
-  buildEventResizeForDayGrid = reselector(buildInteractionForDayGrid)
+  splitter = memoizeSplitter(new AllDaySplitter())
 
 
   constructor(
@@ -375,42 +366,3 @@ export default abstract class AgendaView extends View {
 }
 
 AgendaView.prototype.usesMinMaxTime = true // indicates that minTime/maxTime affects rendering
-
-
-function filterEventsForTimeGrid(eventStore: EventStore, eventUis: EventUiHash): EventStore {
-  return filterEventStoreDefs(eventStore, function(eventDef) {
-    return !eventDef.allDay || hasBgRendering(eventUis[eventDef.defId])
-  })
-}
-
-function filterEventsForDayGrid(eventStore: EventStore, eventUis: EventUiHash): EventStore {
-  return filterEventStoreDefs(eventStore, function(eventDef) {
-    return eventDef.allDay
-  })
-}
-
-function buildInteractionForTimeGrid(state: EventInteractionUiState): EventInteractionUiState {
-  if (state) {
-    return {
-      affectedEvents: state.affectedEvents,
-      mutatedEvents: filterEventsForTimeGrid(state.mutatedEvents, state.eventUis),
-      eventUis: state.eventUis,
-      isEvent: state.isEvent,
-      origSeg: state.origSeg
-    }
-  }
-  return null
-}
-
-function buildInteractionForDayGrid(state: EventInteractionUiState): EventInteractionUiState {
-  if (state) {
-    return {
-      affectedEvents: state.affectedEvents,
-      mutatedEvents: filterEventsForDayGrid(state.mutatedEvents, state.eventUis),
-      eventUis: state.eventUis,
-      isEvent: state.isEvent,
-      origSeg: state.origSeg
-    }
-  }
-  return null
-}

+ 11 - 6
src/agenda/AgendaView.ts

@@ -58,9 +58,14 @@ export default class AgendaView extends AbstractAgendaView {
   render(props: ViewProps) {
     super.render(props) // for flags for updateSize
 
+    let { splitter } = this
     let { dateProfile, dateSelection } = this.props
     let dayTable = this.buildDayTable(dateProfile, this.dateProfileGenerator)
 
+    let eventStores = splitter.splitEventStore(props.eventStore, props.eventUis)
+    let eventDrags = splitter.splitEventDrag(props.eventDrag, props.eventUis)
+    let eventResizes = splitter.splitEventResize(props.eventResize, props.eventUis)
+
     if (this.header) {
       this.header.receiveProps({
         dateProfile,
@@ -75,11 +80,11 @@ export default class AgendaView extends AbstractAgendaView {
       dayTable,
       businessHours: props.businessHours,
       dateSelection: dateSelection && !dateSelection.allDay ? dateSelection : null,
-      eventStore: this.filterEventsForTimeGrid(props.eventStore, props.eventUis),
+      eventStore: eventStores.timed,
       eventUis: props.eventUis,
       eventSelection: props.eventSelection,
-      eventDrag: this.buildEventDragForTimeGrid(props.eventDrag),
-      eventResize: this.buildEventResizeForTimeGrid(props.eventResize)
+      eventDrag: eventDrags.timed,
+      eventResize: eventResizes.timed
     })
 
     if (this.simpleDayGrid) {
@@ -88,11 +93,11 @@ export default class AgendaView extends AbstractAgendaView {
         dayTable,
         businessHours: props.businessHours,
         dateSelection: dateSelection && dateSelection.allDay ? dateSelection : null,
-        eventStore: this.filterEventsForDayGrid(props.eventStore, props.eventUis),
+        eventStore: eventStores.allDay,
         eventUis: props.eventUis,
         eventSelection: props.eventSelection,
-        eventDrag: this.buildEventDragForDayGrid(props.eventDrag),
-        eventResize: this.buildEventResizeForDayGrid(props.eventResize),
+        eventDrag: eventDrags.allDay,
+        eventResize: eventResizes.allDay,
         nextDayThreshold: this.nextDayThreshold,
         isRigid: false
       })

+ 22 - 0
src/agenda/AllDaySplitter.ts

@@ -0,0 +1,22 @@
+import { Splitter } from '../component/event-splitting'
+import { EventUi } from '../component/event-ui'
+import { hasBgRendering } from '../component/event-rendering'
+import { EventDef } from '../structs/event'
+
+export default class AllDaySplitter extends Splitter {
+
+  constructor() {
+    super([ 'allDay', 'timed' ])
+  }
+
+  getKeysForEventDef(eventDef: EventDef, eventUi: EventUi): string[] {
+    if (!eventDef.allDay) {
+      return [ 'timed' ]
+    } else if (hasBgRendering(eventUi)) {
+      return [ 'timed', 'allDay' ]
+    } else {
+      return [ 'allDay' ]
+    }
+  }
+
+}

+ 101 - 0
src/component/event-splitting.ts

@@ -0,0 +1,101 @@
+import { EventStore, createEmptyEventStore } from '../structs/event-store'
+import { EventDef } from '../structs/event'
+import { EventInteractionUiState } from '../interactions/event-interaction-state'
+import { mapHash } from '../util/object'
+import { EventUi, EventUiHash } from '../component/event-ui'
+import reselector from '../util/reselector'
+
+export function memoizeSplitter(splitter: Splitter) {
+  return {
+    splitEventStore: reselector(splitter.splitEventStore),
+    splitEventDrag: reselector(splitter.splitInteraction),
+    splitEventResize: reselector(splitter.splitInteraction)
+  }
+}
+
+export abstract class Splitter { // not just EVENT splitting (rename file?)
+
+  allKeys: string[]
+
+  constructor(allKeys: string[]) {
+    this.allKeys = allKeys
+  }
+
+  splitInteraction = (state: EventInteractionUiState | null, allEventUis: EventUiHash) => {
+    let splitStates: { [key: string]: EventInteractionUiState } = {}
+
+    for (let key in this.allKeys) {
+      splitStates[key] = null
+    }
+
+    if (state) {
+      let mutatedStores = this.splitEventStorePopulated(state.mutatedEvents, state.eventUis)
+      let affectedStores = this.splitEventStorePopulated(state.affectedEvents, allEventUis)
+      let populate = function(key) {
+        if (!splitStates[key]) {
+          splitStates[key] = {
+            affectedEvents: affectedStores[key] || createEmptyEventStore(),
+            mutatedEvents: mutatedStores[key] || createEmptyEventStore(),
+            eventUis: state.eventUis,
+            isEvent: state.isEvent,
+            origSeg: state.origSeg
+          }
+        }
+      }
+
+      for (let key in affectedStores) {
+        populate(key)
+      }
+
+      for (let key in mutatedStores) {
+        populate(key)
+      }
+    }
+
+    return splitStates
+  }
+
+  splitEventStore = (eventStore: EventStore, eventUis: EventUiHash) => {
+    let splitStores = this.splitEventStorePopulated(eventStore, eventUis)
+
+    for (let key in this.allKeys) {
+      if (!splitStores[key]) {
+        splitStores[key] = createEmptyEventStore()
+      }
+    }
+
+    return splitStores
+  }
+
+  splitEventStorePopulated(eventStore: EventStore, eventUis: EventUiHash): { [key: string]: EventStore } {
+    let { defs, instances } = eventStore
+    let keysByDefId = mapHash(eventStore.defs, (eventDef: EventDef, defId: string) => {
+      return this.getKeysForEventDef(eventDef, eventUis[defId])
+    })
+    let splitStores = {}
+
+    for (let defId in defs) {
+      for (let key of keysByDefId[defId]) {
+
+        if (!splitStores[key]) {
+          splitStores[key] = createEmptyEventStore()
+        }
+
+        splitStores[key].defs[defId] = defs[defId]
+      }
+    }
+
+    for (let instanceId in instances) {
+      let instance = instances[instanceId]
+
+      for (let key of keysByDefId[instance.defId]) {
+        splitStores[key].instances[instanceId] = instance
+      }
+    }
+
+    return splitStores
+  }
+
+  abstract getKeysForEventDef(eventDef: EventDef, eventUi: EventUi): string[]
+
+}

+ 1 - 0
src/exports.ts

@@ -65,6 +65,7 @@ export {
 export { EventStore, filterEventStoreDefs, createEmptyEventStore } from './structs/event-store'
 export { hasBgRendering } from './component/event-rendering'
 export { EventUiHash } from './component/event-ui'
+export { Splitter, memoizeSplitter } from './component/event-splitting'
 export { buildGotoAnchorHtml, getAllDayHtml, getDayClasses } from './component/date-rendering'
 
 export {