mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-23 00:29:50 +02:00
WIP: Add choices ui for resolving conflicts
This commit is contained in:
+10
-5
@@ -312,18 +312,25 @@ en:
|
||||
title: Save
|
||||
help: "Save changes to OpenStreetMap, making them visible to other users."
|
||||
no_changes: No changes to save.
|
||||
errors: Errors occurred while trying to save
|
||||
error: Errors occurred while trying to save
|
||||
status_code: "Server returned status code {code}"
|
||||
status_gone: '{type} "{id}" {name} has already been deleted.'
|
||||
unknown_error_details: "Please ensure you are connected to the internet."
|
||||
uploading: Uploading changes to OpenStreetMap.
|
||||
unsaved_changes: You have unsaved changes
|
||||
conflicts:
|
||||
conflict:
|
||||
header: Conflicting edits detected
|
||||
message: 'Conflicting edits were made to {type} "{id}" {name}'
|
||||
keep_local: Keep Mine
|
||||
keep_remote: Keep Theirs
|
||||
restore: Restore
|
||||
leave_deleted: Leave Deleted
|
||||
delete: Leave Deleted
|
||||
annotation:
|
||||
safe: Merged remote changes from server.
|
||||
keep_local: 'Kept local version of "{id}".'
|
||||
keep_remote: 'Kept remote version of "{id}".'
|
||||
restore: 'Restored local version of "{id}".'
|
||||
delete: 'Deleted local version of "{id}".'
|
||||
try_again: Try Again
|
||||
download_changes: Download Changes
|
||||
help: |
|
||||
@@ -331,9 +338,7 @@ en:
|
||||
You can click on each item below for more details about the conflict, and choose whether to keep
|
||||
your changes or the other user's changes. Or, you can download your changes to a file.
|
||||
merge_remote_changes:
|
||||
annotation: Merged remote changes from server.
|
||||
conflict:
|
||||
general: 'Conflicting edits were made to {type} "{id}" {name}'
|
||||
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.
|
||||
|
||||
Vendored
+11
-5
@@ -386,27 +386,33 @@
|
||||
"title": "Save",
|
||||
"help": "Save changes to OpenStreetMap, making them visible to other users.",
|
||||
"no_changes": "No changes to save.",
|
||||
"errors": "Errors occurred while trying to save",
|
||||
"error": "Errors occurred while trying to save",
|
||||
"status_code": "Server returned status code {code}",
|
||||
"status_gone": "{type} \"{id}\" {name} has already been deleted.",
|
||||
"unknown_error_details": "Please ensure you are connected to the internet.",
|
||||
"uploading": "Uploading changes to OpenStreetMap.",
|
||||
"unsaved_changes": "You have unsaved changes",
|
||||
"conflicts": {
|
||||
"conflict": {
|
||||
"header": "Conflicting edits detected",
|
||||
"message": "Conflicting edits were made to {type} \"{id}\" {name}",
|
||||
"keep_local": "Keep Mine",
|
||||
"keep_remote": "Keep Theirs",
|
||||
"restore": "Restore",
|
||||
"leave_deleted": "Leave Deleted",
|
||||
"delete": "Leave Deleted",
|
||||
"annotation": {
|
||||
"safe": "Merged remote changes from server.",
|
||||
"keep_local": "Kept local version of \"{id}\".",
|
||||
"keep_remote": "Kept remote version of \"{id}\".",
|
||||
"restore": "Restored local version of \"{id}\".",
|
||||
"delete": "Deleted local version of \"{id}\"."
|
||||
},
|
||||
"try_again": "Try Again",
|
||||
"download_changes": "Download Changes",
|
||||
"help": "It looks like another OpenStreetMap user has changed some of the same map features that you changed.\nYou can click on each item below for more details about the conflict, and choose whether to keep\nyour changes or the other user's changes. Or, you can download your changes to a file.\n"
|
||||
}
|
||||
},
|
||||
"merge_remote_changes": {
|
||||
"annotation": "Merged remote changes from server.",
|
||||
"conflict": {
|
||||
"general": "Conflicting edits were made to {type} \"{id}\" {name}",
|
||||
"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.",
|
||||
|
||||
+70
-24
@@ -3,6 +3,13 @@ iD.modes.Save = function(context) {
|
||||
.on('cancel', cancel)
|
||||
.on('save', save);
|
||||
|
||||
function choice(text, actions) {
|
||||
return {
|
||||
text: text,
|
||||
action: function() { context.perform.apply(this, actions); }
|
||||
};
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
@@ -14,7 +21,8 @@ iD.modes.Save = function(context) {
|
||||
toCheck = _.pluck(history.changes().modified, 'id'),
|
||||
didMerge = false,
|
||||
conflicts = [],
|
||||
errors = [];
|
||||
errors = [],
|
||||
confirm;
|
||||
|
||||
context.container()
|
||||
.call(loading);
|
||||
@@ -39,14 +47,20 @@ iD.modes.Save = function(context) {
|
||||
if (err.status === 410) { // Status: Gone (contains no responseText)
|
||||
conflicts.push({
|
||||
id: id,
|
||||
msg: t('save.status_gone', {id: id, type: type, name: name}),
|
||||
details: [ t('save.status_code', {code: err.status}) ]
|
||||
msg: t('save.status_gone', { id: id, type: type, name: name }),
|
||||
details: [ t('save.status_code', { code: err.status }) ],
|
||||
choices: [
|
||||
choice(t('save.conflict.restore'),
|
||||
[ iD.actions.Noop() /*FIXME*/, t('save.conflict.annotation.restore', {id: id}) ]),
|
||||
choice(t('save.conflict.delete'),
|
||||
[ iD.actions.DeleteMultiple([id]), t('save.conflict.annotation.delete', {id: id}) ])
|
||||
]
|
||||
});
|
||||
} else {
|
||||
errors.push({
|
||||
id: id,
|
||||
msg: err.responseText,
|
||||
details: [ t('save.status_code', {code: err.status}) ]
|
||||
details: [ t('save.status_code', { code: err.status }) ]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,16 +69,27 @@ iD.modes.Save = function(context) {
|
||||
|
||||
var remote = altGraph.entity(id);
|
||||
if (local.version !== remote.version) {
|
||||
var action = iD.actions.MergeRemoteChanges(id, graph, altGraph),
|
||||
diff = history.perform(action);
|
||||
var merge = iD.actions.MergeRemoteChanges,
|
||||
safe = merge(id, graph, altGraph),
|
||||
diff = context.perform(safe),
|
||||
details = safe.conflicts();
|
||||
|
||||
if (diff.length()) {
|
||||
didMerge = true;
|
||||
} else {
|
||||
var forceLocal = merge(id, graph, altGraph).withOption('force_local'),
|
||||
forceRemote = merge(id, graph, altGraph).withOption('force_remote');
|
||||
|
||||
conflicts.push({
|
||||
id: id,
|
||||
msg: t('merge_remote_changes.conflict.general', {id: id, type: type, name: name}),
|
||||
details: action.conflicts()
|
||||
msg: t('save.conflict.message', { id: id, type: type, name: name }),
|
||||
details: details,
|
||||
choices: [
|
||||
choice(t('save.conflict.keep_local'),
|
||||
[ forceLocal, t('save.conflict.annotation.keep_local', {id: id}) ]),
|
||||
choice(t('save.conflict.keep_remote'),
|
||||
[ forceRemote, t('save.conflict.annotation.keep_remote', {id: id}) ])
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -78,7 +103,7 @@ iD.modes.Save = function(context) {
|
||||
|
||||
function finalize() {
|
||||
if (didMerge) { // set undo checkpoint..
|
||||
history.perform([iD.actions.Noop, t('merge_remote_changes.annotation')]);
|
||||
context.perform(iD.actions.Noop(), t('save.conflict.annotation.safe'));
|
||||
}
|
||||
|
||||
if (conflicts.length) {
|
||||
@@ -107,20 +132,19 @@ iD.modes.Save = function(context) {
|
||||
}
|
||||
|
||||
function showConflicts() {
|
||||
var confirm = iD.ui.confirm(context.container());
|
||||
|
||||
confirm = iD.ui.confirm(context.container());
|
||||
loading.close();
|
||||
|
||||
confirm
|
||||
.select('.modal-section.header')
|
||||
.append('h3')
|
||||
.text(t('save.conflicts.header'));
|
||||
.text(t('save.conflict.header'));
|
||||
|
||||
confirm
|
||||
.select('.modal-section.message-text')
|
||||
.append('div')
|
||||
.attr('class', 'conflicts-help')
|
||||
.text(t('save.conflicts.help'));
|
||||
.text(t('save.conflict.help'));
|
||||
|
||||
addItems(confirm, conflicts);
|
||||
|
||||
@@ -135,7 +159,7 @@ iD.modes.Save = function(context) {
|
||||
confirm.remove();
|
||||
save(e);
|
||||
})
|
||||
.text(t('save.conflicts.try_again'));
|
||||
.text(t('save.conflict.try_again'));
|
||||
|
||||
buttons
|
||||
.append('button')
|
||||
@@ -152,22 +176,22 @@ iD.modes.Save = function(context) {
|
||||
var diff = iD.actions.DiscardTags(history.difference()),
|
||||
changes = history.changes(diff),
|
||||
data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', changes)),
|
||||
win = window.open("data:text/xml," + encodeURIComponent(data), "_blank");
|
||||
win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
|
||||
|
||||
win.focus();
|
||||
confirm.remove();
|
||||
})
|
||||
.text(t('save.conflicts.download_changes'));
|
||||
.text(t('save.conflict.download_changes'));
|
||||
}
|
||||
|
||||
function showErrors() {
|
||||
var confirm = iD.ui.confirm(context.container());
|
||||
confirm = iD.ui.confirm(context.container());
|
||||
loading.close();
|
||||
|
||||
confirm
|
||||
.select('.modal-section.header')
|
||||
.append('h3')
|
||||
.text(t('save.errors'));
|
||||
.text(t('save.error'));
|
||||
|
||||
addItems(confirm, errors);
|
||||
confirm.okButton();
|
||||
@@ -193,25 +217,47 @@ iD.modes.Save = function(context) {
|
||||
.text(function(d) { return d.msg || t('save.unknown_error_details'); })
|
||||
.on('click', function() {
|
||||
var error = d3.select(this),
|
||||
details = d3.select(this.nextElementSibling),
|
||||
detail = d3.select(this.nextElementSibling),
|
||||
exp = error.classed('expanded');
|
||||
|
||||
details.style('display', exp ? 'none' : 'block');
|
||||
detail.style('display', exp ? 'none' : 'block');
|
||||
error.classed('expanded', !exp);
|
||||
|
||||
d3.event.preventDefault();
|
||||
});
|
||||
|
||||
enter
|
||||
var details = enter
|
||||
.append('div')
|
||||
.attr('class', 'error-detail-container')
|
||||
.style('display', 'none');
|
||||
|
||||
details
|
||||
.append('ul')
|
||||
.attr('class', 'error-detail-list')
|
||||
.style('display', 'none')
|
||||
.selectAll('li')
|
||||
.data(function(d) { return d.details; })
|
||||
.data(function(d) { return d.details || []; })
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('class', 'error-detail-item')
|
||||
.text(function(d) { return d;});
|
||||
.text(function(d) { return d; });
|
||||
|
||||
details
|
||||
.append('div')
|
||||
.attr('class', 'error-choices')
|
||||
.selectAll('a')
|
||||
.data(function(d) { return d.choices || []; })
|
||||
.enter()
|
||||
.append('a')
|
||||
.attr('class', 'error-choice')
|
||||
.text(function(d) { return d.text; })
|
||||
.on('click', function(d) {
|
||||
d.action();
|
||||
d3.event.preventDefault();
|
||||
d3.select(this.parentElement.parentElement.parentElement)
|
||||
.transition()
|
||||
.style('opacity', 0)
|
||||
.remove();
|
||||
});
|
||||
|
||||
items.exit()
|
||||
.remove();
|
||||
|
||||
Reference in New Issue
Block a user