|
|
@@ -1,3 +1,7 @@
|
|
|
+/*
|
|
|
+TODO: caching. dont want to regenerate all these ranges
|
|
|
+twice if there are two events being dragged at once.
|
|
|
+*/
|
|
|
|
|
|
Calendar.prototype.isEventFootprintAllowed = function(eventFootprint) {
|
|
|
var eventDef = eventFootprint.eventInstance.eventDefinition;
|
|
|
@@ -5,6 +9,7 @@ Calendar.prototype.isEventFootprintAllowed = function(eventFootprint) {
|
|
|
var constraintVal;
|
|
|
var overlapVal;
|
|
|
|
|
|
+ // TODO: use EventDef
|
|
|
constraintVal = eventDef.constraint;
|
|
|
if (constraintVal == null) {
|
|
|
constraintVal = source.constraint;
|
|
|
@@ -13,6 +18,7 @@ Calendar.prototype.isEventFootprintAllowed = function(eventFootprint) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // TODO: use EventDef
|
|
|
overlapVal = eventDef.overlap;
|
|
|
if (overlapVal == null) {
|
|
|
overlapVal = source.overlap;
|
|
|
@@ -25,21 +31,23 @@ Calendar.prototype.isEventFootprintAllowed = function(eventFootprint) {
|
|
|
eventFootprint.componentFootprint,
|
|
|
constraintVal,
|
|
|
overlapVal,
|
|
|
- eventDef
|
|
|
+ eventFootprint.eventInstance
|
|
|
);
|
|
|
};
|
|
|
|
|
|
|
|
|
Calendar.prototype.isSelectionFootprintAllowed = function(componentFootprint) {
|
|
|
- var selectAllowFunc = this.opt('selectAllow');
|
|
|
+ var selectAllowFunc;
|
|
|
|
|
|
if (this.isFootprintAllowed(
|
|
|
componentFootprint,
|
|
|
this.opt('selectConstraint'),
|
|
|
this.opt('selectOverlap')
|
|
|
)) {
|
|
|
+ selectAllowFunc = this.opt('selectAllow');
|
|
|
+
|
|
|
if (selectAllowFunc) {
|
|
|
- return selectAllowFunc(selectAllowFunc) !== false;
|
|
|
+ return selectAllowFunc(componentFootprint.toLegacy()) !== false;
|
|
|
}
|
|
|
else {
|
|
|
return true;
|
|
|
@@ -50,64 +58,281 @@ Calendar.prototype.isSelectionFootprintAllowed = function(componentFootprint) {
|
|
|
};
|
|
|
|
|
|
|
|
|
-Calendar.prototype.isFootprintAllowed = function(componentFootprint, constraintVal, overlapVal, subjectEventDef) {
|
|
|
+Calendar.prototype.isFootprintAllowed = function(
|
|
|
+ componentFootprint,
|
|
|
+ constraintVal,
|
|
|
+ overlapVal,
|
|
|
+ subjectEventInstance
|
|
|
+) {
|
|
|
+ var constraintFootprints; // ComponentFootprint[]
|
|
|
+ var overlapEventFootprints; // EventFootprint[]
|
|
|
+
|
|
|
+ if (constraintVal != null) {
|
|
|
+ constraintFootprints = this.constraintValToFootprints(constraintVal);
|
|
|
|
|
|
- console.log('constraint', this.constraintValToFootprints(constraintVal));
|
|
|
+ if (!this.isFootprintWithinConstraints(componentFootprint, constraintFootprints)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ overlapEventFootprints = this.getOverlappingEventFootprints(componentFootprint, subjectEventInstance);
|
|
|
+
|
|
|
+ if (overlapVal === false) {
|
|
|
+ if (overlapEventFootprints.length) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (typeof overlapVal === 'function') {
|
|
|
+ if (!isOverlapsAllowedByFunc(overlapEventFootprints, overlapVal, subjectEventInstance)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (subjectEventInstance) {
|
|
|
+ if (!isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
return true;
|
|
|
};
|
|
|
|
|
|
|
|
|
+// Constraint
|
|
|
+// ------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.isFootprintWithinConstraints = function(componentFootprint, constraintFootprints) {
|
|
|
+ var i;
|
|
|
+
|
|
|
+ for (i = 0; i < constraintFootprints.length; i++) {
|
|
|
+ if (this.footprintContainsFootprint(
|
|
|
+ constraintFootprints[i],
|
|
|
+ componentFootprint
|
|
|
+ )) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
Calendar.prototype.constraintValToFootprints = function(constraintVal) {
|
|
|
+ var eventDefs;
|
|
|
+ var eventDef;
|
|
|
+ var eventInstances;
|
|
|
+ var eventRanges;
|
|
|
+ var eventFootprints;
|
|
|
|
|
|
if (constraintVal === 'businessHours') {
|
|
|
- return this.buildCurrentBusinessFootprints();
|
|
|
+
|
|
|
+ eventFootprints = this.buildCurrentBusinessFootprints();
|
|
|
+
|
|
|
+ return eventFootprintsToComponentFootprints(eventFootprints);
|
|
|
}
|
|
|
+ else if (typeof constraintVal === 'object') {
|
|
|
+
|
|
|
+ eventDef = parseEventInput(constraintVal, this);
|
|
|
+ eventInstances = this.eventDefToInstances(eventDef);
|
|
|
+ eventRanges = this.eventInstancesToEventRanges(eventInstances);
|
|
|
+ eventFootprints = this.eventRangesToEventFootprints(eventRanges);
|
|
|
|
|
|
- if (typeof constraintVal === 'object') {
|
|
|
- return this.eventInputToFootprints(constraintVal);
|
|
|
+ return eventFootprintsToComponentFootprints(eventFootprints);
|
|
|
}
|
|
|
+ else if (constraintVal != null) { // an ID
|
|
|
|
|
|
- return this.eventIdToFootprints(constraintVal);
|
|
|
+ eventDefs = this.eventDefCollection.getById(constraintVal);
|
|
|
+ eventInstances = this.eventDefsToInstances(eventDefs);
|
|
|
+ eventRanges = this.eventInstancesToEventRanges(eventInstances);
|
|
|
+ eventFootprints = this.eventRangesToEventFootprints(eventRanges);
|
|
|
+
|
|
|
+ return eventFootprintsToComponentFootprints(eventFootprints);
|
|
|
+ }
|
|
|
+
|
|
|
+ return [];
|
|
|
};
|
|
|
|
|
|
|
|
|
-Calendar.prototype.eventInputToFootprints = function(eventInput) {
|
|
|
- var activeRange = this.getView().activeRange;
|
|
|
- var eventDef;
|
|
|
- var eventInstances;
|
|
|
- var eventInstanceGroup;
|
|
|
+// Overlap
|
|
|
+// ------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.getOverlappingEventFootprints = function(componentFootprint, subjectEventInstance) {
|
|
|
+ var peerEventFootprints = this.getPeerEventFootprints(componentFootprint, subjectEventInstance);
|
|
|
+ var overlapEventFootprints = [];
|
|
|
+ var i;
|
|
|
|
|
|
- if (eventInput.start == null) {
|
|
|
- return []; // invalid
|
|
|
+ for (i = 0; i < peerEventFootprints.length; i++) {
|
|
|
+ if (this.footprintsIntersect(
|
|
|
+ componentFootprint,
|
|
|
+ peerEventFootprints[i].componentFootprint
|
|
|
+ )) {
|
|
|
+ overlapEventFootprints.push(peerEventFootprints[i]);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- eventDef = parseEventInput(eventInput, this);
|
|
|
- eventInstances = eventDef.buildInstances(activeRange.start, activeRange.end);
|
|
|
- eventInstanceGroup = new EventInstanceGroup(eventInstances);
|
|
|
+ return overlapEventFootprints;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.getPeerEventFootprints = function(componentFootprint, subjectEventInstance) {
|
|
|
+ var peerEventDefs = subjectEventInstance ?
|
|
|
+ this.getUnrelatedEventDefs(subjectEventInstance.eventDefinition) :
|
|
|
+ this.eventDefCollection.eventDefs.slice(); // all. clone
|
|
|
|
|
|
- return this.eventInstanceGroupToFootprints(eventInstanceGroup);
|
|
|
+ var peerEventInstances = this.eventDefsToInstances(peerEventDefs);
|
|
|
+ var peerEventRanges = this.eventInstancesToEventRanges(peerEventInstances);
|
|
|
+
|
|
|
+ return this.eventRangesToEventFootprints(peerEventRanges);
|
|
|
};
|
|
|
|
|
|
|
|
|
-Calendar.prototype.eventIdToFootprints = function(eventId) {
|
|
|
- var activeRange = this.getView().activeRange;
|
|
|
- var eventDefs = this.eventDefCollection.getById(eventId);
|
|
|
- var eventInstances = [];
|
|
|
- var eventInstanceGroup;
|
|
|
+Calendar.prototype.getUnrelatedEventDefs = function(subjectEventDef) {
|
|
|
+ var eventDefs = this.eventDefCollection.eventDefs;
|
|
|
+ var i, eventDef;
|
|
|
+ var unrelated = [];
|
|
|
+
|
|
|
+ for (i = 0; i < eventDefs.length; i++) {
|
|
|
+ eventDef = eventDefs[i];
|
|
|
+
|
|
|
+ if (eventDef.id !== subjectEventDef.id) {
|
|
|
+ unrelated.push(eventDef);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return unrelated;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+function isOverlapsAllowedByFunc(overlapEventFootprints, overlapFunc, subjectEventInstance) {
|
|
|
var i;
|
|
|
|
|
|
- if (!eventDefs) {
|
|
|
- return []; // invalid
|
|
|
+ for (i = 0; i < overlapEventFootprints.length; i++) {
|
|
|
+ if (!overlapFunc(
|
|
|
+ overlapEventFootprints[i].eventInstance.toLegacy(),
|
|
|
+ subjectEventInstance ? subjectEventInstance.toLegacy() : null
|
|
|
+ )) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function isOverlapEventInstancesAllowed(overlapEventFootprints, subjectEventInstance) {
|
|
|
+ var i;
|
|
|
+ var overlapEventFootprint;
|
|
|
+ var overlapEventInstance;
|
|
|
+ var overlapEventDef;
|
|
|
+ var overlapVal;
|
|
|
+
|
|
|
+ for (i = 0; i < overlapEventFootprints.length; i++) {
|
|
|
+ overlapEventFootprint = overlapEventFootprints[i];
|
|
|
+ overlapEventInstance = overlapEventFootprint.eventInstance;
|
|
|
+ overlapEventDef = overlapEventInstance.eventDefinition;
|
|
|
+
|
|
|
+ // TODO: use EventDef
|
|
|
+ overlapVal = overlapEventDef.overlap;
|
|
|
+ if (overlapVal == null) {
|
|
|
+ if (overlapEventDef.source) {
|
|
|
+ overlapVal = overlapEventDef.source.overlap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (overlapVal === false) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ else if (typeof overlapVal === 'function') {
|
|
|
+ if (!overlapVal(
|
|
|
+ subjectEventInstance.toLegacy(),
|
|
|
+ overlapEventInstance.toLegacy()
|
|
|
+ )) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Conversion: eventDefs -> eventInstances -> eventRanges -> eventFootprints -> componentFootprints
|
|
|
+// ------------------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.eventDefsToInstances = function(eventDefs) {
|
|
|
+ var eventInstances = [];
|
|
|
+ var i;
|
|
|
+
|
|
|
for (i = 0; i < eventDefs.length; i++) {
|
|
|
eventInstances.push.apply(eventInstances, // append
|
|
|
- eventDefs[i].buildInstances(activeRange.start, activeRange.end)
|
|
|
+ this.eventDefToInstances(eventDefs[i])
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- eventInstanceGroup = new EventInstanceGroup(eventInstances);
|
|
|
+ return eventInstances;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.eventDefToInstances = function(eventDef) {
|
|
|
+ var activeRange = this.getView().activeRange;
|
|
|
+
|
|
|
+ return eventDef.buildInstances(activeRange.start, activeRange.end);
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.eventInstancesToEventRanges = function(eventInstances) {
|
|
|
+ var group = new EventInstanceGroup(eventInstances);
|
|
|
+ var activeRange = this.getView().activeRange;
|
|
|
+
|
|
|
+ return group.buildEventRanges(
|
|
|
+ new UnzonedRange(activeRange.start, activeRange.end),
|
|
|
+ this // calendar
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.eventRangesToEventFootprints = function(eventRanges) {
|
|
|
+ var _this = this;
|
|
|
+
|
|
|
+ return eventRanges.map(function(eventRange) {
|
|
|
+ return _this.eventRangeToEventFootprint(eventRange);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.eventRangeToEventFootprint = function(eventRange) {
|
|
|
+ return new EventFootprint( // TODO: DRY. also in Grid.event.js
|
|
|
+ eventRange.eventInstance,
|
|
|
+ new ComponentFootprint(
|
|
|
+ eventRange.dateRange,
|
|
|
+ eventRange.eventInstance.eventDateProfile.isAllDay()
|
|
|
+ )
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+function eventFootprintsToComponentFootprints(eventFootprints) {
|
|
|
+ return eventFootprints.map(function(eventFootprint) {
|
|
|
+ return eventFootprint.componentFootprint;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// Footprint Utils
|
|
|
+// ----------------------------------------------------------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+Calendar.prototype.footprintContainsFootprint = function(outerFootprint, innerFootprint) {
|
|
|
+ // TODO: use date range utils
|
|
|
+ return innerFootprint.dateRange.startMs >= outerFootprint.dateRange.startMs &&
|
|
|
+ innerFootprint.dateRange.endMs <= outerFootprint.dateRange.endMs;
|
|
|
+};
|
|
|
+
|
|
|
|
|
|
- return this.eventInstanceGroupToFootprints(eventInstanceGroup);
|
|
|
+Calendar.prototype.footprintsIntersect = function(footprint0, footprint1) {
|
|
|
+ // TODO: use date range utils
|
|
|
+ return footprint0.dateRange.startMs < footprint1.dateRange.endMs &&
|
|
|
+ footprint0.dateRange.endMs > footprint1.dateRange.startMs;
|
|
|
};
|