mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Finished reimplementation of merge box. Needs more tests
This commit is contained in:
committed by
David Glasser
parent
bbb127c3ca
commit
fbc787cd1d
@@ -10,9 +10,55 @@ Meteor._SessionDocumentView = function (id) {
|
||||
var self = this;
|
||||
self.id = id;
|
||||
self.existsIn = {}; // set of subId
|
||||
self.dataByKey = {}; // key-> [ {subId -> value} by precedence]
|
||||
self.dataByKey = {}; // key-> [ {subscriptionId -> value} by precedence]
|
||||
};
|
||||
|
||||
_.extend(Meteor._SessionDocumentView.prototype, {
|
||||
clearField: function (subscriptionId, key, changeCollector, clearCollector) {
|
||||
var self = this;
|
||||
var precedenceList = self.dataByKey[key];
|
||||
var old = precedenceList[0];
|
||||
var i = 0;
|
||||
_.each(precedenceList, function (precedence) {
|
||||
if (precedence.subscriptionId === subscriptionId) {
|
||||
precedenceList.splice(i, 1);
|
||||
}
|
||||
i++;
|
||||
});
|
||||
if (_.isEmpty(precedenceList)) {
|
||||
delete self.dataByKey[key];
|
||||
clearCollector.push(key);
|
||||
} else if (old.value !== precedenceList[0].value) {
|
||||
changeCollector[key] = precedenceList[0].value;
|
||||
}
|
||||
},
|
||||
|
||||
changeField: function (subscriptionId, key, value, changeCollector) {
|
||||
var self = this;
|
||||
var precedenceList = self.dataByKey[key];
|
||||
if (!precedenceList) {
|
||||
self.dataByKey[key] = [{subscriptionId: subscriptionId, value: value}];
|
||||
changeCollector[key] = value;
|
||||
return;
|
||||
}
|
||||
var elt = _.find(precedenceList, function (precedence) {
|
||||
return precedence.subscriptionId === subscriptionId;
|
||||
});
|
||||
|
||||
if (elt) {
|
||||
if (elt === precedenceList[0] && !_.isEqual(value, elt.value)) {
|
||||
// this subscription is changing the value of this field.
|
||||
changeCollector[key] = value;
|
||||
}
|
||||
elt.value = value;
|
||||
} else {
|
||||
// this subscription is newly caring about this field
|
||||
precedenceList.push({subscriptionId: subscriptionId, value: value});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Meteor._SessionCollectionView = function (collectionName, sessionCallbacks) {
|
||||
var self = this;
|
||||
self.collectionName = collectionName;
|
||||
@@ -21,28 +67,68 @@ Meteor._SessionCollectionView = function (collectionName, sessionCallbacks) {
|
||||
};
|
||||
|
||||
_.extend(Meteor._SessionCollectionView.prototype, {
|
||||
|
||||
added: function (subscriptionId, doc) {
|
||||
var self = this;
|
||||
var docView = self.documents[doc._id];
|
||||
if (docView) {
|
||||
// somebody else knew about this doc; reconicle. The effective order of
|
||||
// precedence here is that the first subscription to say anything about a
|
||||
// key determines its value.
|
||||
var newPairs = {};
|
||||
if (_.has(docView.existsIn, subscriptionId)) {
|
||||
throw new Error("Duplicate add for " + doc._id);
|
||||
}
|
||||
docView.existsIn[subscriptionId] = true;
|
||||
//XXX: Deal with fields here.
|
||||
_.each(doc, function (value, key) {
|
||||
var dataAssertionList = docView.dataByKey[key];
|
||||
if (dataAssertionList) {
|
||||
// just assume that we're not already in the assertion list yet,
|
||||
// but we could check this.
|
||||
} else {
|
||||
// nobody has taken responsibility for this key yet
|
||||
dataAssertionList = [];
|
||||
self.dataByKey[key] = dataAssertionList;
|
||||
newPairs[key] = value;
|
||||
}
|
||||
// add our assertion
|
||||
var assertion = {subscriptionId: subscriptionId, value: value};
|
||||
dataAssertionList.push(assertion);
|
||||
});
|
||||
if (!_.isEmpty(newPairs))
|
||||
self.callbacks.changed(self.collectionName, doc._id, newPairs, []);
|
||||
} else {
|
||||
docView = new Meteor._SessionDocumentView(doc._id);
|
||||
self.documents[doc._id] = docView;
|
||||
docView.existsIn[subscriptionId] = true;
|
||||
//XXX: Deal with fields here
|
||||
_.each(doc, function (value, key) {
|
||||
docView.dataByKey[key] = [{subscriptionId: subscriptionId, value: value}];
|
||||
});
|
||||
// since nobody else knew about this doc, we can just call added.
|
||||
self.callbacks.added(self.collectionName, doc);
|
||||
}
|
||||
},
|
||||
|
||||
changed: function (subscriptionId, id, changed, cleared) {
|
||||
var self = this;
|
||||
var changedResult = {};
|
||||
var clearedResult = [];
|
||||
var docView = self.documents[id];
|
||||
if (!docView)
|
||||
throw new Error("Could not find element with id " + id + "to change");
|
||||
_.each(changed, function (value, key) {
|
||||
docView.changeField(subscriptionId, key, value, changedResult);
|
||||
});
|
||||
_.each(cleared, function (clearKey) {
|
||||
docView.clearField(subscriptionId, clearKey, changedResult, clearedResult);
|
||||
});
|
||||
if (!_.isEmpty(changed) || !_.isEmpty(cleared))
|
||||
self.callbacks.changed(self.collectionName, id, changedResult, clearedResult);
|
||||
},
|
||||
|
||||
removed: function (subscriptionId, ids) {
|
||||
var self = this;
|
||||
var removedIds = [];
|
||||
_.each(ids, function (id) {
|
||||
var docView = self.documents[id];
|
||||
if (!docView) {
|
||||
@@ -50,12 +136,23 @@ _.extend(Meteor._SessionCollectionView.prototype, {
|
||||
}
|
||||
delete docView.existsIn[subscriptionId];
|
||||
if (_.isEmpty(docView.existsIn)) {
|
||||
//XXX: Stop splitting it up
|
||||
self.callbacks.removed(self.collectionName, [id]);
|
||||
// it is gone from everyone
|
||||
removedIds.push(id);
|
||||
delete self.documents[id];
|
||||
} else {
|
||||
//XXX: DO STUFF
|
||||
var changed = {};
|
||||
var cleared = [];
|
||||
// remove this subscription from every precedence list
|
||||
// and record the changes
|
||||
_.each(docView.dataByKey, function (precedenceList, key) {
|
||||
docView.clearField(subscriptionId, key, changed, cleared);
|
||||
});
|
||||
if (!_.isEmpty(changed) || !_.isEmpty(cleared))
|
||||
self.callbacks.changed(self.collectionName, id, changed, cleared);
|
||||
}
|
||||
});
|
||||
if (!_.isEmpty(removedIds))
|
||||
self.callbacks.removed(self.collectionName, removedIds);
|
||||
}
|
||||
});
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -27,7 +27,7 @@ var newView = function(test) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
Tinytest.add('livedata - sessionview - basic', function (test) {
|
||||
Tinytest.add('livedata - sessionview - exists reveal', function (test) {
|
||||
var v = newView(test);
|
||||
|
||||
v.added("A", {_id: "A1"});
|
||||
@@ -44,3 +44,58 @@ Tinytest.add('livedata - sessionview - basic', function (test) {
|
||||
v.expectResult({fun: 'removed', ids: ["A1"]});
|
||||
v.expectNoResult();
|
||||
});
|
||||
|
||||
Tinytest.add('livedata - sessionview - field reveal', function (test) {
|
||||
var v = newView(test);
|
||||
|
||||
v.added("A", {_id: "A1", foo: "bar"});
|
||||
v.expectResult({fun: 'added', doc: {_id: "A1", foo: "bar"}});
|
||||
v.expectNoResult();
|
||||
|
||||
v.added("B", {_id: "A1", foo: "baz"});
|
||||
v.removed("A", ["A1"]);
|
||||
v.expectResult({fun: 'changed', id: "A1", changed: {foo: "baz"}, cleared: []});
|
||||
v.expectNoResult();
|
||||
// Somewhere in here we must have changed foo to baz. Legal either on the
|
||||
// added or on the removed, but only once.
|
||||
|
||||
v.removed("B", ["A1"]);
|
||||
v.expectResult({fun: 'removed', ids: ["A1"]});
|
||||
v.expectNoResult();
|
||||
});
|
||||
|
||||
Tinytest.add('livedata - sessionview - field change', function (test) {
|
||||
var v = newView(test);
|
||||
|
||||
v.added("A", {_id: "A1", foo: "bar"});
|
||||
v.expectResult({fun: 'added', doc: {_id: "A1", foo: "bar"}});
|
||||
v.expectNoResult();
|
||||
|
||||
v.changed("A", "A1", {foo: "baz"}, []);
|
||||
v.expectResult({fun: 'changed', id: "A1", changed: {foo: "baz"}, cleared: []});
|
||||
v.expectNoResult();
|
||||
|
||||
v.removed("A", ["A1"]);
|
||||
v.expectResult({fun: 'removed', ids: ["A1"]});
|
||||
v.expectNoResult();
|
||||
});
|
||||
|
||||
Tinytest.add('livedata - sessionview - field change reveal', function (test) {
|
||||
var v = newView(test);
|
||||
|
||||
v.added("A", {_id: "A1", foo: "bar"});
|
||||
v.expectResult({fun: 'added', doc: {_id: "A1", foo: "bar"}});
|
||||
v.expectNoResult();
|
||||
|
||||
|
||||
v.added("B", {_id: "A1", foo: "baz"});
|
||||
v.changed("A", "A1", {}, ["foo"]);
|
||||
v.expectResult({fun: 'changed', id: "A1", changed: {foo: "baz"}, cleared: []});
|
||||
v.expectNoResult();
|
||||
|
||||
v.removed("A", ["A1"]);
|
||||
v.expectNoResult();
|
||||
v.removed("B", ["A1"]);
|
||||
v.expectResult({fun: 'removed', ids: ["A1"]});
|
||||
v.expectNoResult();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user