Browse Source

event mutation foundation

Adam Shaw 8 years ago
parent
commit
31e8f07337

+ 2 - 0
src.json

@@ -46,6 +46,8 @@
     "models/UnzonedRange.js",
     "models/EventRange.js",
     "models/EventDateProfile.js",
+    "models/EventDateMutation.js",
+    "models/EventMutation.js",
     "models/EventInstance.js",
     "models/EventDefinition.js",
     "models/SingleEventDefinition.js",

+ 29 - 1
src/EventManager.js

@@ -45,6 +45,7 @@ function EventManager() { // assumed to be a calendar
 	var pendingSourceCnt = 0; // outstanding fetch requests, max one per source
 	var cache = []; // holds events that have already been expanded
 	var eventDefCollection = new EventDefinitionCollection(t);
+	t.eventDefCollection = eventDefCollection;
 
 
 	$.each(
@@ -589,6 +590,16 @@ function EventManager() { // assumed to be a calendar
 			}
 
 			mutateEvent(event, getMiscEventProps(event)); // will handle start/end/allDay normalization
+
+			var eventDef = eventDefCollection.getById(event._id);
+			var eventInstance = eventDef.buildInstances()[0];
+			var eventMutation = EventMutation.createFromRawProps(
+				eventInstance,
+				event, // raw props
+				null, // largeUnit -- who uses it?
+				t // calendar
+			);
+			eventMutation.mutateSingleEventDefinition(eventDef);
 		}
 
 		reportEventChange(); // reports event modifications (so we can redraw)
@@ -1146,8 +1157,25 @@ function EventManager() { // assumed to be a calendar
 
 
 // returns an undo function
+// newProps will only have start/end
 Calendar.prototype.mutateSeg = function(seg, newProps) {
-	return this.mutateEvent(seg.event, newProps);
+
+	var eventDef = this.eventDefCollection.getById(seg.event._id)[0];
+	var eventInstance = eventDef.buildInstances()[0];
+	var newEventDateProfile = new EventDateProfile(
+		this.moment(newProps.start),
+		newProps.end ? this.moment(newProps.end) : null
+	);
+	var eventDateMutation = EventDateMutation.createFromDiff(
+		eventInstance.eventDateProfile,
+		newEventDateProfile
+	);
+	eventDateMutation.mutateSingleEventDefinition( // returns an undo function
+		eventDef,
+		this.getIsAmbigTimezone()
+	);
+
+	return this.mutateEvent(seg.event, newProps); // what about largeUnit? who uses that?
 };
 
 

+ 118 - 0
src/models/EventDateMutation.js

@@ -0,0 +1,118 @@
+
+var EventDateMutation = Class.extend({
+
+	clearEnd: false,
+	forceTimed: false,
+	forceAllDay: false,
+	startDelta: null,
+	durationDelta: null,
+
+
+	mutateSingleEventDefinition: function(eventDef, isAmbigTimezone) {
+		var origStart = eventDef.start;
+		var origEnd = eventDef.end;
+		var start = origStart.clone();
+		var end = origEnd ? origEnd.clone() : null;
+
+		if (this.clearEnd) {
+			end = null;
+		}
+
+		if (this.forceTimed) {
+
+			if (!start.hasTime()) {
+				start.time(0);
+			}
+
+			if (end && !end.hasTime()) {
+				end.time(0);
+			}
+		}
+		else if (this.forceAllDay) {
+
+			if (start.hasTime()) {
+				start.stripTime();
+			}
+
+			if (end && end.hasTime()) {
+				end.stripTime();
+			}
+		}
+
+		if (this.startDelta) {
+
+			start.add(this.startDelta);
+
+			if (end) {
+				end.add(this.startDelta);
+			}
+		}
+
+		if (this.durationDelta) {
+
+			if (end) {
+				end.add(this.durationDelta);
+			}
+		}
+
+		if (isAmbigTimezone) {
+
+			if (start.hasTime() && this.startDelta) {
+				start.stripZone();
+			}
+
+			if (end && end.hasTime() && (this.startDelta || this.endDelta)) {
+				end.stripZone();
+			}
+		}
+
+		eventDef.start = start;
+		eventDef.end = end;
+
+		return function() {
+			eventDef.start = origStart;
+			eventDef.end = origEnd;
+		};
+	}
+
+});
+
+
+EventDateMutation.createFromDiff = function(profile1, profile2, largeUnit) {
+	var clearEnd = profile1.end && !profile2.end;
+	var forceTimed = profile1.isAllDay() && !profile2.isAllDay();
+	var forceAllDay = !profile1.isAllDay() && profile2.isAllDay();
+	var startDelta;
+	var endDelta;
+	var durationDelta;
+	var mutation;
+
+	// diffs the dates in the appropriate way, returning a duration
+	function diffDates(date1, date0) { // date1 - date0
+		if (largeUnit) {
+			return diffByUnit(date1, date0, largeUnit);
+		}
+		else if (profile2.isAllDay()) {
+			return diffDay(date1, date0);
+		}
+		else {
+			return diffDayTime(date1, date0);
+		}
+	}
+
+	startDelta = diffDates(profile2.start, profile1.start);
+
+	if (profile2.end) {
+		endDelta = diffDates(profile2.end, profile1.getEnd());
+		durationDelta = endDelta.subtract(startDelta);
+	}
+
+	mutation = new EventDateMutation();
+	mutation.clearEnd = clearEnd;
+	mutation.forceTimed = forceTimed;
+	mutation.forceAllDay = forceAllDay;
+	mutation.startDelta = startDelta;
+	mutation.endDelta = endDelta;
+
+	return mutation;
+}

+ 11 - 9
src/models/EventDateProfile.js

@@ -13,18 +13,20 @@ var EventDateProfile = Class.extend({
 		return !(this.start.hasTime() || (this.end && this.end.hasTime()));
 	},
 
+	getEnd: function(calendar) {
+		return this.end ?
+			this.end.clone() :
+			// derive the end from the start and allDay. compute allDay if necessary
+			calendar.getDefaultEventEnd(
+				this.isAllDay(),
+				this.start
+			);
+	},
+
 	// calendar object needed to compute missing end dates
 	buildRange: function(calendar) {
 		var startMs = this.start.clone().stripZone().valueOf();
-		var endMs = (
-				this.end ?
-					this.end.clone() :
-					// derive the end from the start and allDay. compute allDay if necessary
-					calendar.getDefaultEventEnd(
-						this.isAllDay(),
-						this.start
-					)
-			).stripZone().valueOf();
+		var endMs = this.getEnd(calendar).stripZone().valueOf();
 
 		return new UnzonedRange(startMs, endMs);
 	}

+ 4 - 0
src/models/EventDefinitionCollection.js

@@ -28,6 +28,10 @@ var EventDefinitionCollection = Class.extend({
 			.push(eventDef);
 	},
 
+	getById: function(id) {
+		return this.eventDefsById[id];
+	},
+
 	clear: function() {
 		this.eventDefs = [];
 		this.eventDefsById = {};

+ 59 - 0
src/models/EventMutation.js

@@ -0,0 +1,59 @@
+
+var EventMutation = Class.extend({
+
+	newTitle: null,
+	newRendering: null,
+	additionalMiscProps: null,
+	dateMutation: null,
+
+
+	// will not provide an undo function
+	mutateSingleEventDefinition: function(eventDef, isAmbigTimezone) {
+		eventDef.title = this.newTitle;
+		eventDef.rendering = this.newRendering;
+		$.extend(eventDef.miscProps, this.additionalMiscProps || {});
+
+		this.dateMutation.mutateSingleEventDefinition(
+			eventDef,
+			isAmbigTimezone
+		);
+	}
+
+});
+
+
+EventMutation.createFromRawProps = function(eventInstance, newRawProps, largeUnit, calendar) {
+	var newTitle = newRawProps.title;
+	var newRendering = newRawProps.rendering;
+	var additionalMiscProps = {};
+	var propName;
+	var newEventDateProfile;
+	var dateMutation;
+	var eventMutation;
+
+	for (propName in newRawProps) {
+		if (!eventInstance.eventDefinition.isStandardProp(propName)) {
+			additionalMiscProps[propName] = newRawProps[propName];
+		}
+	}
+
+	newEventDateProfile = new EventDateProfile(
+		calendar.moment(newRawProps.start),
+		newRawProps.end ? calendar.moment(newRawProps.end) : null
+	);
+
+	dateMutation = EventDateMutation.createFromDiff(
+		eventInstance.eventDateProfile,
+		newEventDateProfile,
+		largeUnit
+	);
+
+	eventMutation = new EventMutation();
+	eventMutation.newTitle = newTitle;
+	eventMutation.newRendering = newRendering;
+	eventMutation.additionalMiscProps = additionalMiscProps;
+	eventMutation.dateMutation = dateMutation;
+
+	return eventMutation;
+};
+