diff --git a/data/core.yaml b/data/core.yaml
index fbca6f1ab..8a1b75f3c 100644
--- a/data/core.yaml
+++ b/data/core.yaml
@@ -320,6 +320,7 @@ en:
unsaved_changes: You have unsaved changes
conflict:
header: Resolve conflicting edits
+ count: '{num} of {total}'
message: '{name}'
keep_local: Keep mine
keep_remote: Use theirs
@@ -339,10 +340,10 @@ en:
your changes or the other user's changes.
merge_remote_changes:
conflict:
- location: Location was changed both locally and remotely.
- nodelist: Nodes were changed both locally and remotely.
- memberlist: Relation members were changed both locally and remotely.
- tags: 'Tag "{tag}" was changed to "{local}" locally and "{remote}" remotely.'
+ location: 'This object was moved by both you and {user}.'
+ nodelist: 'Nodes were changed by both you and {user}.'
+ memberlist: 'Relation members were changed by both you and {user}.'
+ tags: 'You changed the {tag} tag to "{local}" and {user} changed it to "{remote}".'
success:
edited_osm: "Edited OSM!"
just_edited: "You just edited OpenStreetMap!"
diff --git a/dist/locales/en.json b/dist/locales/en.json
index eb4313811..53c851af1 100644
--- a/dist/locales/en.json
+++ b/dist/locales/en.json
@@ -394,6 +394,7 @@
"unsaved_changes": "You have unsaved changes",
"conflict": {
"header": "Resolve conflicting edits",
+ "count": "{num} of {total}",
"message": "{name}",
"keep_local": "Keep mine",
"keep_remote": "Use theirs",
@@ -413,10 +414,10 @@
},
"merge_remote_changes": {
"conflict": {
- "location": "Location was changed both locally and remotely.",
- "nodelist": "Nodes were changed both locally and remotely.",
- "memberlist": "Relation members were changed both locally and remotely.",
- "tags": "Tag \"{tag}\" was changed to \"{local}\" locally and \"{remote}\" remotely."
+ "location": "This object was moved by both you and {user}.",
+ "nodelist": "Nodes were changed by both you and {user}.",
+ "memberlist": "Relation members were changed by both you and {user}.",
+ "tags": "You changed the {tag} tag to \"{local}\" and {user} changed it to \"{remote}\"."
}
},
"success": {
diff --git a/js/id/actions/merge_remote_changes.js b/js/id/actions/merge_remote_changes.js
index c81a69ad6..0592ed04e 100644
--- a/js/id/actions/merge_remote_changes.js
+++ b/js/id/actions/merge_remote_changes.js
@@ -1,10 +1,13 @@
-iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph) {
+iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph, formatUser) {
var base = localGraph.base().entities[id],
local = localGraph.entity(id),
remote = remoteGraph.entity(id),
option = 'safe', // 'safe', 'force_local', 'force_remote'
conflicts = [];
+ function user(d) {
+ return _.isFunction(formatUser) ? formatUser(d) : d;
+ }
function mergeLocation(target) {
if (!target) return;
@@ -21,7 +24,7 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph) {
return target.update({loc: remote.loc});
}
- conflicts.push(t('merge_remote_changes.conflict.location'));
+ conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
return; // fail merge
}
@@ -54,7 +57,7 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph) {
} else if (_.isEqual(c.o, c.b)) { // only changed locally
nodes.push.apply(nodes, c.a);
} else { // changed both locally and remotely
- conflicts.push(t('merge_remote_changes.conflict.nodelist'));
+ conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
return; // fail merge..
}
}
@@ -73,7 +76,7 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph) {
return target.update({members: remote.members});
}
- conflicts.push(t('merge_remote_changes.conflict.memberlist'));
+ conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
return; // fail merge
}
@@ -101,7 +104,7 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph) {
if (remote.tags[k] !== base.tags[k]) { // tag modified remotely..
if (target.tags[k] && target.tags[k] !== remote.tags[k]) {
conflicts.push(t('merge_remote_changes.conflict.tags',
- { tag: k, local: target.tags[k], remote: remote.tags[k] }));
+ { tag: k, local: target.tags[k], remote: remote.tags[k], user: user(remote.user) }));
fail = true;
} else {
tags[k] = remote.tags[k];
diff --git a/js/id/core/connection.js b/js/id/core/connection.js
index e98627e55..12923ab69 100644
--- a/js/id/core/connection.js
+++ b/js/id/core/connection.js
@@ -217,28 +217,29 @@ iD.Connection = function() {
};
connection.putChangeset = function(changes, comment, imageryUsed, callback) {
- oauth.xhr({
- method: 'PUT',
- path: '/api/0.6/changeset/create',
- options: { header: { 'Content-Type': 'text/xml' } },
- content: JXON.stringify(connection.changesetJXON(connection.changesetTags(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))
- }, function(err) {
- if (err) return callback(err);
- oauth.xhr({
- method: 'PUT',
- path: '/api/0.6/changeset/' + changeset_id + '/close'
- }, function(err) {
- callback(err, changeset_id);
- });
- });
- });
+ callback({ responseText: 'save disabled', status: 0 });
+ // oauth.xhr({
+ // method: 'PUT',
+ // path: '/api/0.6/changeset/create',
+ // options: { header: { 'Content-Type': 'text/xml' } },
+ // content: JXON.stringify(connection.changesetJXON(connection.changesetTags(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))
+ // }, function(err) {
+ // if (err) return callback(err);
+ // oauth.xhr({
+ // method: 'PUT',
+ // path: '/api/0.6/changeset/' + changeset_id + '/close'
+ // }, function(err) {
+ // callback(err, changeset_id);
+ // });
+ // });
+ // });
};
var userDetails;
diff --git a/js/id/modes/save.js b/js/id/modes/save.js
index fe4672fa3..949213bda 100644
--- a/js/id/modes/save.js
+++ b/js/id/modes/save.js
@@ -25,6 +25,10 @@ iD.modes.Save = function(context) {
context.enter(iD.modes.Browse(context));
}
+ function formatUser(d) {
+ return '' + d + '';
+ }
+
function save(e) {
var loading = iD.ui.Loading(context).message(t('save.uploading')).blocking(true),
history = context.history(),
@@ -87,16 +91,16 @@ iD.modes.Save = function(context) {
var remote = altGraph.entity(id);
if (local.version !== remote.version) {
- var merge = iD.actions.MergeRemoteChanges,
- safe = merge(id, graph, altGraph),
- diff = context.perform(safe),
- details = safe.conflicts();
+ var action = iD.actions.MergeRemoteChanges,
+ merge = action(id, graph, altGraph, formatUser),
+ diff = context.perform(merge),
+ details = merge.conflicts();
if (diff.length()) {
didMerge = true;
} else {
- var forceLocal = merge(id, graph, altGraph).withOption('force_local'),
- forceRemote = merge(id, graph, altGraph).withOption('force_remote');
+ var forceLocal = action(id, graph, altGraph, formatUser).withOption('force_local'),
+ forceRemote = action(id, graph, altGraph, formatUser).withOption('force_remote');
conflicts.push({
id: id,
@@ -249,6 +253,15 @@ iD.modes.Save = function(context) {
if (i === 0) zoomToEntity(d);
});
+ enter
+ .append('h4')
+ .style('display', function(d, i) {
+ return (i === 0) ? 'block': 'none';
+ })
+ .text(function(d, i) {
+ return t('save.conflict.count', { num: i+1, total: data.length });
+ });
+
enter
.append('a')
.attr('class', 'conflict-description')
@@ -274,7 +287,7 @@ iD.modes.Save = function(context) {
.enter()
.append('li')
.attr('class', 'conflict-detail-item')
- .text(function(d) { return d; });
+ .html(function(d) { return d; });
details
.append('div')
@@ -314,9 +327,9 @@ iD.modes.Save = function(context) {
.remove();
function toggleExpanded(el, d) {
-
var error = d3.select(el),
detail = d3.select(el.getElementsByTagName('div')[0]),
+ count = d3.select(el.getElementsByTagName('h4')[0]),
exp = error.classed('expanded');
// Clear old expanded
@@ -330,6 +343,12 @@ iD.modes.Save = function(context) {
.style('opacity', exp ? 0 : 1)
.style('display', exp ? 'none' : 'block');
+ count
+ .style('opacity', exp ? 1 : 0)
+ .transition()
+ .style('opacity', exp ? 0 : 1)
+ .style('display', exp ? 'none' : 'block');
+
zoomToEntity(d);
error.classed('expanded', !exp);