Refactor from coreConnection to serviceOsm

(closes #3497)
This commit is contained in:
Bryan Housel
2016-10-19 01:00:20 -04:00
parent 1d03414b80
commit b5c95af3b7
8 changed files with 226 additions and 229 deletions
+3 -5
View File
@@ -1,7 +1,6 @@
import * as d3 from 'd3';
import _ from 'lodash';
import { t, addTranslation, setLocale } from '../util/locale';
import { coreConnection } from './connection';
import { coreHistory } from './history';
import { dataLocales, dataEn } from '../../data/index';
import { geoRawMercator } from '../geo/raw_mercator';
@@ -336,14 +335,13 @@ export function coreContext(root) {
/* reset (aka flush) */
context.reset = context.flush = function() {
context.debouncedSave.cancel();
connection.flush();
features.reset();
history.reset();
_.each(services, function(service) {
if (typeof service.reset === 'function') {
service.reset(context);
}
});
features.reset();
history.reset();
return context;
};
@@ -383,7 +381,7 @@ export function coreContext(root) {
ui = uiInit(context);
connection = coreConnection();
connection = services.osm;
background = rendererBackground(context);
features = rendererFeatures(context);
-1
View File
@@ -1,4 +1,3 @@
export { coreConnection } from './connection';
export { coreContext } from './context';
export { coreDifference } from './difference';
export { coreGraph } from './graph';
+3 -1
View File
@@ -18,7 +18,9 @@ export * from './lib/index';
export * from './validations/index';
/* export some legacy symbols: */
export { coreConnection as Connection } from './core/connection';
import { services } from './services/index';
var Connection = services.osm;
export { Connection };
export { coreContext as Context, setAreaKeys } from './core/context';
export { coreDifference as Difference } from './core/difference';
export { coreGraph as Graph } from './core/graph';
+2
View File
@@ -1,5 +1,6 @@
import serviceMapillary from './mapillary';
import serviceNominatim from './nominatim';
import serviceOsm from './osm';
import serviceTaginfo from './taginfo';
import serviceWikidata from './wikidata';
import serviceWikipedia from './wikipedia';
@@ -7,6 +8,7 @@ import serviceWikipedia from './wikipedia';
export var services = {
mapillary: serviceMapillary,
nominatim: serviceNominatim,
osm: serviceOsm,
taginfo: serviceTaginfo,
wikidata: serviceWikidata,
wikipedia: serviceWikipedia
@@ -10,230 +10,241 @@ import { utilRebind } from '../util/rebind';
import { utilFunctor } from '../util/index';
export function coreConnection(useHttps) {
if (typeof useHttps !== 'boolean') {
useHttps = window.location.protocol === 'https:';
var dispatch = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
useHttps = window.location.protocol === 'https:',
protocol = useHttps ? 'https:' : 'http:',
url = protocol + '//www.openstreetmap.org',
inflight = {},
loadedTiles = {},
tileZoom = 16,
oauth = osmAuth({
url: protocol + '//www.openstreetmap.org',
oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
loading: authenticating,
done: authenticated
}),
userDetails,
off;
function authenticating() {
dispatch.call('authenticating');
}
function authenticated() {
dispatch.call('authenticated');
}
function abortRequest(i) {
i.abort();
}
function getLoc(attrs) {
var lon = attrs.lon && attrs.lon.value,
lat = attrs.lat && attrs.lat.value;
return [parseFloat(lon), parseFloat(lat)];
}
function getNodes(obj) {
var elems = obj.getElementsByTagName('nd'),
nodes = new Array(elems.length);
for (var i = 0, l = elems.length; i < l; i++) {
nodes[i] = 'n' + elems[i].attributes.ref.value;
}
return nodes;
}
function getTags(obj) {
var elems = obj.getElementsByTagName('tag'),
tags = {};
for (var i = 0, l = elems.length; i < l; i++) {
var attrs = elems[i].attributes;
tags[attrs.k.value] = attrs.v.value;
}
return tags;
}
function getMembers(obj) {
var elems = obj.getElementsByTagName('member'),
members = new Array(elems.length);
for (var i = 0, l = elems.length; i < l; i++) {
var attrs = elems[i].attributes;
members[i] = {
id: attrs.type.value[0] + attrs.ref.value,
type: attrs.type.value,
role: attrs.role.value
};
}
return members;
}
function getVisible(attrs) {
return (!attrs.visible || attrs.visible.value !== 'false');
}
var parsers = {
node: function nodeData(obj) {
var attrs = obj.attributes;
return new osmNode({
id: osmEntity.id.fromOSM('node', attrs.id.value),
loc: getLoc(attrs),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
visible: getVisible(attrs)
});
},
way: function wayData(obj) {
var attrs = obj.attributes;
return new osmWay({
id: osmEntity.id.fromOSM('way', attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
nodes: getNodes(obj),
visible: getVisible(attrs)
});
},
relation: function relationData(obj) {
var attrs = obj.attributes;
return new osmRelation({
id: osmEntity.id.fromOSM('relation', attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
members: getMembers(obj),
visible: getVisible(attrs)
});
}
};
function parse(dom) {
if (!dom || !dom.childNodes) return;
var root = dom.childNodes[0],
children = root.childNodes,
entities = [];
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i],
parser = parsers[child.nodeName];
if (parser) {
entities.push(parser(child));
}
}
var dispatch = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
protocol = useHttps ? 'https:' : 'http:',
url = protocol + '//www.openstreetmap.org',
connection = {},
inflight = {},
loadedTiles = {},
tileZoom = 16,
oauth = osmAuth({
url: protocol + '//www.openstreetmap.org',
oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
loading: authenticating,
done: authenticated
}),
ndStr = 'nd',
tagStr = 'tag',
memberStr = 'member',
nodeStr = 'node',
wayStr = 'way',
relationStr = 'relation',
userDetails,
off;
return entities;
}
connection.changesetURL = function(changesetId) {
export default {
init: function() {
this.event = utilRebind(this, dispatch, 'on');
},
reset: function() {
userDetails = undefined;
_.forEach(inflight, abortRequest);
loadedTiles = {};
inflight = {};
return this;
},
changesetURL: function(changesetId) {
return url + '/changeset/' + changesetId;
};
},
connection.changesetsURL = function(center, zoom) {
changesetsURL: function(center, zoom) {
var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
return url + '/history#map=' +
Math.floor(zoom) + '/' +
center[1].toFixed(precision) + '/' +
center[0].toFixed(precision);
};
},
connection.entityURL = function(entity) {
entityURL: function(entity) {
return url + '/' + entity.type + '/' + entity.osmId();
};
},
connection.userURL = function(username) {
userURL: function(username) {
return url + '/user/' + username;
};
},
connection.loadFromURL = function(url, callback) {
loadFromURL: function(url, callback) {
function done(err, dom) {
return callback(err, parse(dom));
}
return d3.xml(url).get(done);
};
},
connection.loadEntity = function(id, callback) {
loadEntity: function(id, callback) {
var type = osmEntity.id.type(id),
osmID = osmEntity.id.toOSM(id);
connection.loadFromURL(
this.loadFromURL(
url + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
function(err, entities) {
if (callback) callback(err, {data: entities});
});
};
},
connection.loadEntityVersion = function(id, version, callback) {
loadEntityVersion: function(id, version, callback) {
var type = osmEntity.id.type(id),
osmID = osmEntity.id.toOSM(id);
connection.loadFromURL(
this.loadFromURL(
url + '/api/0.6/' + type + '/' + osmID + '/' + version,
function(err, entities) {
if (callback) callback(err, {data: entities});
});
};
},
connection.loadMultiple = function(ids, callback) {
loadMultiple: function(ids, callback) {
var that = this;
_.each(_.groupBy(_.uniq(ids), osmEntity.id.type), function(v, k) {
var type = k + 's',
osmIDs = _.map(v, osmEntity.id.toOSM);
_.each(_.chunk(osmIDs, 150), function(arr) {
connection.loadFromURL(
that.loadFromURL(
url + '/api/0.6/' + type + '?' + type + '=' + arr.join(),
function(err, entities) {
if (callback) callback(err, {data: entities});
});
});
});
};
},
function authenticating() {
dispatch.call('authenticating');
}
function authenticated() {
dispatch.call('authenticated');
}
function getLoc(attrs) {
var lon = attrs.lon && attrs.lon.value,
lat = attrs.lat && attrs.lat.value;
return [parseFloat(lon), parseFloat(lat)];
}
function getNodes(obj) {
var elems = obj.getElementsByTagName(ndStr),
nodes = new Array(elems.length);
for (var i = 0, l = elems.length; i < l; i++) {
nodes[i] = 'n' + elems[i].attributes.ref.value;
}
return nodes;
}
function getTags(obj) {
var elems = obj.getElementsByTagName(tagStr),
tags = {};
for (var i = 0, l = elems.length; i < l; i++) {
var attrs = elems[i].attributes;
tags[attrs.k.value] = attrs.v.value;
}
return tags;
}
function getMembers(obj) {
var elems = obj.getElementsByTagName(memberStr),
members = new Array(elems.length);
for (var i = 0, l = elems.length; i < l; i++) {
var attrs = elems[i].attributes;
members[i] = {
id: attrs.type.value[0] + attrs.ref.value,
type: attrs.type.value,
role: attrs.role.value
};
}
return members;
}
function getVisible(attrs) {
return (!attrs.visible || attrs.visible.value !== 'false');
}
var parsers = {
node: function nodeData(obj) {
var attrs = obj.attributes;
return new osmNode({
id: osmEntity.id.fromOSM(nodeStr, attrs.id.value),
loc: getLoc(attrs),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
visible: getVisible(attrs)
});
},
way: function wayData(obj) {
var attrs = obj.attributes;
return new osmWay({
id: osmEntity.id.fromOSM(wayStr, attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
nodes: getNodes(obj),
visible: getVisible(attrs)
});
},
relation: function relationData(obj) {
var attrs = obj.attributes;
return new osmRelation({
id: osmEntity.id.fromOSM(relationStr, attrs.id.value),
version: attrs.version.value,
user: attrs.user && attrs.user.value,
tags: getTags(obj),
members: getMembers(obj),
visible: getVisible(attrs)
});
}
};
function parse(dom) {
if (!dom || !dom.childNodes) return;
var root = dom.childNodes[0],
children = root.childNodes,
entities = [];
for (var i = 0, l = children.length; i < l; i++) {
var child = children[i],
parser = parsers[child.nodeName];
if (parser) {
entities.push(parser(child));
}
}
return entities;
}
connection.authenticated = function() {
authenticated: function() {
return oauth.authenticated();
};
},
// Generate Changeset XML. Returns a string.
connection.changesetJXON = function(tags) {
changesetJXON: function(tags) {
return {
osm: {
changeset: {
@@ -245,12 +256,12 @@ export function coreConnection(useHttps) {
}
}
};
};
},
// Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
// XML. Returns a string.
connection.osmChangeJXON = function(changeset_id, changes) {
osmChangeJXON: function(changeset_id, changes) {
function nest(x, order) {
var groups = {};
for (var i = 0; i < x.length; i++) {
@@ -278,10 +289,10 @@ export function coreConnection(useHttps) {
'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
}
};
};
},
connection.changesetTags = function(version, comment, imageryUsed) {
changesetTags: function(version, comment, imageryUsed) {
var detected = utilDetect(),
tags = {
created_by: ('iD ' + version).substr(0, 255),
@@ -295,22 +306,23 @@ export function coreConnection(useHttps) {
}
return tags;
};
},
connection.putChangeset = function(changes, version, comment, imageryUsed, callback) {
putChangeset: function(changes, version, comment, imageryUsed, callback) {
var that = this;
oauth.xhr({
method: 'PUT',
path: '/api/0.6/changeset/create',
options: { header: { 'Content-Type': 'text/xml' } },
content: JXON.stringify(connection.changesetJXON(connection.changesetTags(version, comment, imageryUsed)))
content: JXON.stringify(that.changesetJXON(that.changesetTags(version, comment, imageryUsed)))
}, function(err, changeset_id) {
if (err) return callback(err);
oauth.xhr({
method: 'POST',
path: '/api/0.6/changeset/' + changeset_id + '/upload',
options: { header: { 'Content-Type': 'text/xml' } },
content: JXON.stringify(connection.osmChangeJXON(changeset_id, changes))
content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
}, function(err) {
if (err) return callback(err);
// POST was successful, safe to call the callback.
@@ -324,10 +336,10 @@ export function coreConnection(useHttps) {
}, utilFunctor(true));
});
});
};
},
connection.userDetails = function(callback) {
userDetails: function(callback) {
if (userDetails) {
callback(undefined, userDetails);
return;
@@ -354,11 +366,11 @@ export function coreConnection(useHttps) {
}
oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
};
},
connection.userChangesets = function(callback) {
connection.userDetails(function(err, user) {
userChangesets: function(callback) {
this.userDetails(function(err, user) {
if (err) return callback(err);
function done(changesets) {
@@ -372,10 +384,10 @@ export function coreConnection(useHttps) {
.on('load', done)
.on('error', callback);
});
};
},
connection.status = function(callback) {
status: function(callback) {
function done(capabilities) {
var apiStatus = capabilities.getElementsByTagName('status');
callback(undefined, apiStatus[0].getAttribute('api'));
@@ -383,25 +395,21 @@ export function coreConnection(useHttps) {
d3.xml(url + '/api/capabilities').get()
.on('load', done)
.on('error', callback);
};
},
function abortRequest(i) {
i.abort();
}
connection.tileZoom = function(_) {
tileZoom: function(_) {
if (!arguments.length) return tileZoom;
tileZoom = _;
return connection;
};
return this;
},
connection.loadTiles = function(projection, dimensions, callback) {
loadTiles: function(projection, dimensions, callback) {
if (off) return;
var s = projection.scale() * 2 * Math.PI,
var that = this,
s = projection.scale() * 2 * Math.PI,
z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
ts = 256 * Math.pow(2, z - tileZoom),
origin = [
@@ -446,7 +454,7 @@ export function coreConnection(useHttps) {
dispatch.call('loading');
}
inflight[id] = connection.loadFromURL(bboxUrl(tile), function(err, parsed) {
inflight[id] = that.loadFromURL(bboxUrl(tile), function(err, parsed) {
loadedTiles[id] = true;
delete inflight[id];
@@ -457,60 +465,48 @@ export function coreConnection(useHttps) {
}
});
});
};
},
connection.switch = function(options) {
switch: function(options) {
url = options.url;
oauth.options(_.extend({
loading: authenticating,
done: authenticated
}, options));
dispatch.call('auth');
connection.flush();
return connection;
};
this.reset();
return this;
},
connection.toggle = function(_) {
toggle: function(_) {
off = !_;
return connection;
};
return this;
},
connection.flush = function() {
userDetails = undefined;
_.forEach(inflight, abortRequest);
loadedTiles = {};
inflight = {};
return connection;
};
connection.loadedTiles = function(_) {
loadedTiles: function(_) {
if (!arguments.length) return loadedTiles;
loadedTiles = _;
return connection;
};
return this;
},
connection.logout = function() {
logout: function() {
userDetails = undefined;
oauth.logout();
dispatch.call('auth');
return connection;
};
return this;
},
connection.authenticate = function(callback) {
authenticate: function(callback) {
userDetails = undefined;
function done(err, res) {
dispatch.call('auth');
if (callback) callback(err, res);
}
return oauth.authenticate(done);
};
return utilRebind(connection, dispatch, 'on');
}
}
};
+1 -1
View File
@@ -67,7 +67,7 @@ export function uiAccount(context) {
.attr('id', 'userLink')
.classed('hide', true);
connection.on('auth.account', function() { update(selection); });
connection.event.on('auth.account', function() { update(selection); });
update(selection);
};
}
+2 -2
View File
@@ -8,13 +8,13 @@ export function uiSpinner(context) {
.attr('src', context.imagePath('loader-black.gif'))
.style('opacity', 0);
connection
connection.event
.on('loading.spinner', function() {
img.transition()
.style('opacity', 1);
});
connection
connection.event
.on('loaded.spinner', function() {
img.transition()
.style('opacity', 0);