Return entities from iD.Connection via callbacks

(instead of dispatching `load` event to merge them into `history`)

This is cleaner becuase now `context` doesn't need to keep an
`altGraph` state used only for Conflict Resolution.

The conflict resolution code calls the `iD.Connection` methods directly,
and other places in the code call `loadEntity` and `loadTiles` wrappers
that merge the entities into the main history.
This commit is contained in:
Bryan Housel
2015-01-08 14:44:58 -05:00
parent 0e35a6b35b
commit ed4929273d
8 changed files with 66 additions and 79 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ iD.behavior.Hash = function(context) {
if (location.hash) {
var q = iD.util.stringQs(location.hash.substring(1));
if (q.id) context.loadEntity(q.id.split(',')[0], !q.map);
if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
if (q.comment) context.storage('comment', q.comment);
hashchange();
if (q.map) hash.hadHash = true;
+4 -6
View File
@@ -1,6 +1,5 @@
iD.Connection = function() {
var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'load', 'loaded'),
var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
url = 'http://www.openstreetmap.org',
connection = {},
inflight = {},
@@ -55,8 +54,7 @@ iD.Connection = function() {
connection.loadFromURL(
url + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
function(err, entities) {
event.load(err, {data: entities});
if (callback) callback(err, entities && _.find(entities, function(e) { return e.id === id; }));
if (callback) callback(err, {data: entities});
});
};
@@ -292,7 +290,7 @@ iD.Connection = function() {
return connection;
};
connection.loadTiles = function(projection, dimensions) {
connection.loadTiles = function(projection, dimensions, callback) {
if (off) return;
@@ -345,7 +343,7 @@ iD.Connection = function() {
loadedTiles[id] = true;
delete inflight[id];
event.load(err, _.extend({data: parsed}, tile));
if (callback) callback(err, _.extend({data: parsed}, tile));
if (_.isEmpty(inflight)) {
event.loaded();
+46 -45
View File
@@ -47,23 +47,12 @@ window.iD = function () {
ui = iD.ui(context),
connection = iD.Connection(),
locale = iD.detect().locale,
localePath,
altGraph;
localePath;
if (locale && iD.data.locales.indexOf(locale) === -1) {
locale = locale.split('-')[0];
}
connection.on('load.context', function loadContext(err, result) {
if (!err) {
if (altGraph) {
_.each(result.data, function(entity) { altGraph.replace(entity); });
} else {
history.merge(result.data, result.extent);
}
}
});
context.preauth = function(options) {
connection.switch(options);
return context;
@@ -93,18 +82,56 @@ window.iD = function () {
context.connection = function() { return connection; };
context.history = function() { return history; };
/* Connection */
function entitiesLoaded(err, result) {
if (!err) history.merge(result.data, result.extent);
}
context.loadTiles = function(projection, dimensions, callback) {
function done(err, result) {
entitiesLoaded(err, result);
if (callback) callback(err, result);
}
connection.loadTiles(projection, dimensions, done);
};
context.loadEntity = function(id, callback) {
function done(err, result) {
entitiesLoaded(err, result);
if (callback) callback(err, result);
}
connection.loadEntity(id, done);
};
context.zoomToEntity = function(id, zoomTo) {
if (zoomTo !== false) {
this.loadEntity(id, function(err, result) {
if (err) return;
var entity = _.find(result.data, function(e) { return e.id === id; });
if (entity) { map.zoomTo(entity); }
});
}
map.on('drawn.zoomToEntity', function() {
if (!context.hasEntity(id)) return;
map.on('drawn.zoomToEntity', null);
context.on('enter.zoomToEntity', null);
context.enter(iD.modes.Select(context, [id]));
});
context.on('enter.zoomToEntity', function() {
if (mode.id !== 'browse') {
map.on('drawn.zoomToEntity', null);
context.on('enter.zoomToEntity', null);
}
});
};
/* History */
context.graph = history.graph;
context.changes = history.changes;
context.intersects = history.intersects;
context.altGraph = function(_) {
if (!arguments.length) return altGraph;
altGraph = _;
return context;
};
var inIntro = false;
context.inIntro = function(_) {
@@ -120,7 +147,6 @@ window.iD = function () {
};
context.flush = function() {
altGraph = undefined;
connection.flush();
features.reset();
history.reset();
@@ -185,31 +211,6 @@ window.iD = function () {
}
};
context.loadEntity = function(id, zoomTo) {
if (zoomTo !== false) {
connection.loadEntity(id, function(error, entity) {
if (entity) {
map.zoomTo(entity);
}
});
}
map.on('drawn.loadEntity', function() {
if (!context.hasEntity(id)) return;
map.on('drawn.loadEntity', null);
context.on('enter.loadEntity', null);
context.enter(iD.modes.Select(context, [id]));
});
context.on('enter.loadEntity', function() {
if (mode.id !== 'browse') {
map.on('drawn.loadEntity', null);
context.on('enter.loadEntity', null);
}
});
};
/* Behaviors */
context.install = function(behavior) {
context.surface().call(behavior);
+6 -8
View File
@@ -10,6 +10,7 @@ iD.modes.Save = function(context) {
function save(e) {
var loading = iD.ui.Loading(context).message(t('save.uploading')).blocking(true),
history = context.history(),
altGraph = iD.Graph(history.base(), true),
toCheck = _.pluck(history.changes().modified, 'id'),
didMerge = false,
errors = [];
@@ -19,14 +20,13 @@ iD.modes.Save = function(context) {
if (toCheck.length) {
// Reload modified entities into an alternate graph and check for conflicts..
context.altGraph(iD.Graph(history.base(), true));
_.each(toCheck, check);
} else {
finalize();
}
function check(id) {
context.connection().loadEntity(id, function(err) {
context.connection().loadEntity(id, function(err, result) {
var graph = context.graph(),
local = graph.entity(id),
type = iD.util.displayType(id),
@@ -44,11 +44,11 @@ iD.modes.Save = function(context) {
msg: rtext,
details: [ t('save.status_code', {code: err.status}) ]
});
}
else {
var altGraph = context.altGraph(),
remote = altGraph.entity(id);
} else {
_.each(result.data, function(entity) { altGraph.replace(entity); });
var remote = altGraph.entity(id);
if (local.version !== remote.version) {
var action = iD.actions.MergeRemoteChanges(id, graph, altGraph),
diff = history.perform(action);
@@ -101,8 +101,6 @@ iD.modes.Save = function(context) {
function showErrors() {
var confirm = iD.ui.confirm(context.container());
context.altGraph(undefined);
loading.close();
confirm
+1 -1
View File
@@ -211,7 +211,7 @@ iD.Map = function(context) {
}
if (map.editable()) {
context.connection().loadTiles(projection, dimensions);
context.loadTiles(projection, dimensions);
drawVector(difference, extent);
} else {
editOff();
+1 -1
View File
@@ -55,7 +55,7 @@ iD.ui.Contributors = function(context) {
return function(selection) {
update(selection);
context.connection().on('load.contributors', function() {
context.connection().on('loaded.contributors', function() {
update(selection);
});
+1 -1
View File
@@ -223,7 +223,7 @@ iD.ui.FeatureList = function(context) {
else if (d.entity) {
context.enter(iD.modes.Select(context, [d.entity.id]));
} else {
context.loadEntity(d.id);
context.zoomToEntity(d.id);
}
}
+6 -16
View File
@@ -90,9 +90,10 @@ describe('iD.Connection', function () {
});
it('loads a node', function(done) {
c.loadEntity('n1', function(error, entity) {
var id = 'n1';
c.loadEntity(id, function(err, result) {
var entity = _.find(result.data, function(e) { return e.id === id; });
expect(entity).to.be.an.instanceOf(iD.Node);
expect(entity.id).to.eql('n1');
done();
});
@@ -102,9 +103,10 @@ describe('iD.Connection', function () {
});
it('loads a way', function(done) {
c.loadEntity('w1', function(error, entity) {
var id = 'w1';
c.loadEntity(id, function(err, result) {
var entity = _.find(result.data, function(e) { return e.id === id; });
expect(entity).to.be.an.instanceOf(iD.Way);
expect(entity.id).to.eql('w1');
done();
});
@@ -112,18 +114,6 @@ describe('iD.Connection', function () {
[200, { "Content-Type": "text/xml" }, wayXML]);
server.respond();
});
it('emits a load event', function(done) {
c.loadEntity('n1');
c.on('load', function(error, result) {
expect(result.data[0]).to.be.an.instanceOf(iD.Node);
done();
});
server.respondWith("GET", "http://www.openstreetmap.org/api/0.6/node/1",
[200, { "Content-Type": "text/xml" }, nodeXML]);
server.respond();
});
});
describe('#osmChangeJXON', function() {