mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 21:48:20 +02:00
More bugfixes and style updates:
* working Previous/Next buttons * remove behaviors from save mode (users should not be moving nodes around or selecting at this point) * clear hover before hovering next object * enable save button and finished message after reviewing last conflict * store users choice in __data__.chosen.. * default choices to `keep remote version` * better message for delete conflicts * fix undelete action to check localGraph (which will have the entity) instead of context.graph() (which may not)
This commit is contained in:
@@ -2504,15 +2504,6 @@ img.wiki-image {
|
||||
padding: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.conflict-container:not(.expanded) .conflict-description:hover {
|
||||
background: #ececec;
|
||||
}
|
||||
|
||||
.conflict-container.expanded {
|
||||
padding: 10px 0;
|
||||
background: #f6f6f6;
|
||||
}
|
||||
|
||||
.conflict-detail-container {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
+3
-2
@@ -314,16 +314,17 @@ en:
|
||||
no_changes: No changes to save.
|
||||
error: Errors occurred while trying to save
|
||||
status_code: "Server returned status code {code}"
|
||||
status_gone: '{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
|
||||
conflict:
|
||||
header: Resolve conflicting edits
|
||||
count: 'Conflict {num} of {total}'
|
||||
message: '{name}'
|
||||
previous: '< Previous'
|
||||
next: 'Next >'
|
||||
keep_local: Keep mine
|
||||
keep_remote: Use theirs
|
||||
deleted: 'This object has been deleted.'
|
||||
restore: Restore
|
||||
delete: Leave Deleted
|
||||
download_changes: Download your changes.
|
||||
|
||||
Vendored
+3
-2
@@ -388,16 +388,17 @@
|
||||
"no_changes": "No changes to save.",
|
||||
"error": "Errors occurred while trying to save",
|
||||
"status_code": "Server returned status code {code}",
|
||||
"status_gone": "{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",
|
||||
"conflict": {
|
||||
"header": "Resolve conflicting edits",
|
||||
"count": "Conflict {num} of {total}",
|
||||
"message": "{name}",
|
||||
"previous": "< Previous",
|
||||
"next": "Next >",
|
||||
"keep_local": "Keep mine",
|
||||
"keep_remote": "Use theirs",
|
||||
"deleted": "This object has been deleted.",
|
||||
"restore": "Restore",
|
||||
"delete": "Leave Deleted",
|
||||
"download_changes": "Download your changes.",
|
||||
|
||||
+80
-123
@@ -36,7 +36,7 @@ iD.modes.Save = function(context) {
|
||||
|
||||
if (err) {
|
||||
if (err.status === 410) { // Status: Gone (contains no responseText)
|
||||
addDeleteConflict(id, err);
|
||||
addDeleteConflict(id);
|
||||
} else {
|
||||
errors.push({
|
||||
id: id,
|
||||
@@ -57,35 +57,34 @@ iD.modes.Save = function(context) {
|
||||
}
|
||||
|
||||
|
||||
function addDeleteConflict(id, err) {
|
||||
function addDeleteConflict(id) {
|
||||
if (deletedIds.indexOf(id) !== -1) return;
|
||||
else deletedIds.push(id);
|
||||
|
||||
function undelete(id) {
|
||||
return function(graph) {
|
||||
var entity = context.entity(id),
|
||||
target = iD.Entity(entity, { version: +entity.version + 1 });
|
||||
return graph.replace(target);
|
||||
};
|
||||
}
|
||||
|
||||
var local = context.graph().entity(id);
|
||||
var local = localGraph.entity(id);
|
||||
|
||||
conflicts.push({
|
||||
id: id,
|
||||
msg: t('save.status_gone', { name: entityName(local) }),
|
||||
details: [ t('save.status_code', { code: err.status }) ],
|
||||
name: entityName(local),
|
||||
details: [ t('save.conflict.deleted') ],
|
||||
chosen: 1,
|
||||
choices: [
|
||||
choice(id, t('save.conflict.restore'), undelete(id)),
|
||||
choice(id, t('save.conflict.restore'), undelete(local)),
|
||||
choice(id, t('save.conflict.delete'), iD.actions.DeleteMultiple([id]))
|
||||
]
|
||||
],
|
||||
});
|
||||
|
||||
function undelete(entity) {
|
||||
return function(graph) {
|
||||
var target = iD.Entity(entity, { version: +entity.version + 1 });
|
||||
return graph.replace(target);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkConflicts(id) {
|
||||
var graph = context.graph(),
|
||||
local = graph.entity(id),
|
||||
var local = localGraph.entity(id),
|
||||
remote = remoteGraph.entity(id);
|
||||
|
||||
if (local.version !== remote.version) {
|
||||
@@ -100,8 +99,9 @@ iD.modes.Save = function(context) {
|
||||
|
||||
conflicts.push({
|
||||
id: id,
|
||||
msg: t('save.conflict.message', { name: entityName(local) }),
|
||||
name: entityName(local),
|
||||
details: merge.conflicts(),
|
||||
chosen: 1,
|
||||
choices: [
|
||||
choice(id, t('save.conflict.keep_local'), forceLocal),
|
||||
choice(id, t('save.conflict.keep_remote'), forceRemote)
|
||||
@@ -113,6 +113,7 @@ iD.modes.Save = function(context) {
|
||||
|
||||
function finalize() {
|
||||
if (conflicts.length) {
|
||||
conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
|
||||
showConflicts();
|
||||
} else if (errors.length) {
|
||||
showErrors();
|
||||
@@ -125,7 +126,7 @@ iD.modes.Save = function(context) {
|
||||
if (err) {
|
||||
errors.push({
|
||||
msg: err.responseText,
|
||||
details: [ t('save.status_code', {code: err.status}) ]
|
||||
details: [ t('save.status_code', { code: err.status }) ]
|
||||
});
|
||||
showErrors();
|
||||
} else {
|
||||
@@ -183,10 +184,15 @@ iD.modes.Save = function(context) {
|
||||
|
||||
body
|
||||
.append('div')
|
||||
.attr('class', 'message-text conflicts-message-text');
|
||||
.attr('class', 'conflict-container fillL3')
|
||||
.call(showConflict, 0);
|
||||
|
||||
body
|
||||
.call(showConflict, conflicts, 0);
|
||||
.append('div')
|
||||
.attr('class', 'conflicts-done')
|
||||
.attr('opacity', 0)
|
||||
.style('display', 'none')
|
||||
.text(t('save.conflict.done'));
|
||||
|
||||
var buttons = body
|
||||
.append('div')
|
||||
@@ -194,7 +200,7 @@ iD.modes.Save = function(context) {
|
||||
|
||||
buttons
|
||||
.append('button')
|
||||
.attr('disabled', true)
|
||||
.attr('disabled', conflicts.length > 1)
|
||||
.attr('class', 'action conflicts-button col6')
|
||||
.text(t('save.title'))
|
||||
.on('click.try_again', function() {
|
||||
@@ -213,38 +219,48 @@ iD.modes.Save = function(context) {
|
||||
}
|
||||
|
||||
|
||||
function showConflict(selection, data, index) {
|
||||
function showConflict(selection, index) {
|
||||
var parent = d3.select(selection.node().parentElement);
|
||||
|
||||
// enable save button if this is the last conflict being reviewed..
|
||||
if (index === conflicts.length - 1) {
|
||||
window.setTimeout(function() {
|
||||
parent.select('.conflicts-button')
|
||||
.attr('disabled', null);
|
||||
|
||||
parent.select('.conflicts-done')
|
||||
.transition()
|
||||
.attr('opacity', 1)
|
||||
.style('display', 'block');
|
||||
}, 250);
|
||||
}
|
||||
|
||||
var item = selection
|
||||
.selectAll('.conflict-container')
|
||||
.data([data[index]]);
|
||||
.selectAll('.conflict')
|
||||
.data([conflicts[index]]);
|
||||
|
||||
var enter = item.enter()
|
||||
.append('div')
|
||||
.attr('class', 'conflict-container');
|
||||
// .classed('expanded', function(d, i) { return i === 0; })
|
||||
// .each(function(d, i) { if (i === 0) zoomToEntity(d); });
|
||||
.attr('class', 'conflict');
|
||||
|
||||
enter
|
||||
.append('h4')
|
||||
.attr('class', 'conflict-count')
|
||||
// .style('display', function(d, i) { return (i === 0) ? 'block' : 'none'; })
|
||||
.text(t('save.conflict.count', { num: index + 1, total: data.length }));
|
||||
.text(t('save.conflict.count', { num: index + 1, total: conflicts.length }));
|
||||
|
||||
enter
|
||||
.append('a')
|
||||
.attr('class', 'conflict-description')
|
||||
.attr('href', '#')
|
||||
.text(function(d) { return d.msg || t('save.unknown_error_details'); })
|
||||
.text(function(d) { return d.name; })
|
||||
.on('click', function(d) {
|
||||
zoomToEntity(d.id);
|
||||
// toggleExpanded(this.parentElement, d);
|
||||
d3.event.preventDefault();
|
||||
});
|
||||
|
||||
var details = enter
|
||||
.append('div')
|
||||
.attr('class', 'conflict-detail-container');
|
||||
// .style('display', function(d, i) { return i === 0 ? 'block' : 'none'; });
|
||||
|
||||
details
|
||||
.append('ul')
|
||||
@@ -259,92 +275,44 @@ iD.modes.Save = function(context) {
|
||||
details
|
||||
.append('div')
|
||||
.attr('class', 'conflict-choices')
|
||||
.each(addChoices);
|
||||
.call(addChoices);
|
||||
|
||||
details
|
||||
.append('div')
|
||||
.attr('class', 'conflict-nav-buttons joined cf')
|
||||
.selectAll('button')
|
||||
.data(['prev', 'next'])
|
||||
.data(['previous', 'next'])
|
||||
.enter()
|
||||
.append('button')
|
||||
.text(function(d) { return t('save.conflict.' + d); })
|
||||
.attr('class', 'conflict-nav-button action col6')
|
||||
.text(function(d) { return d; })
|
||||
.on('click', function(d) {
|
||||
.attr('disabled', function(d, i) {
|
||||
return (i === 0 && index === 0) ||
|
||||
(i === 1 && index === conflicts.length - 1) || null;
|
||||
})
|
||||
.on('click', function(d, i) {
|
||||
var container = parent.select('.conflict-container'), //d3.select(this.parentElement.parentElement.parentElement.parentElement),
|
||||
sign = (i === 0 ? -1 : 1);
|
||||
|
||||
container
|
||||
.selectAll('.conflict')
|
||||
.remove();
|
||||
|
||||
container
|
||||
.call(showConflict, index + sign);
|
||||
|
||||
d3.event.preventDefault();
|
||||
});
|
||||
|
||||
// details
|
||||
// .append('div')
|
||||
// .attr('class', 'modal-section buttons cf')
|
||||
// .append('button')
|
||||
// .attr('class', 'action col4')
|
||||
// .text(t('confirm.okay'))
|
||||
// .on('click', function(d) {
|
||||
// var container = this.parentElement.parentElement.parentElement;
|
||||
// var next = container.parentElement.firstElementChild.classList.contains('expanded') ? container.nextElementSibling : container.parentElement.firstElementChild;
|
||||
|
||||
// window.setTimeout(function() {
|
||||
// if (next) {
|
||||
// toggleExpanded(next, d);
|
||||
// } else {
|
||||
// d3.select(container.parentElement).append('div')
|
||||
// .attr('class','conflicts-done')
|
||||
// .text(t('save.conflict.done'));
|
||||
|
||||
// d3.select('.conflicts-button')
|
||||
// .attr('disabled', null);
|
||||
// }
|
||||
// }, 250);
|
||||
|
||||
// d3.select(container)
|
||||
// .transition()
|
||||
// .style('opacity', 0)
|
||||
// .remove();
|
||||
|
||||
// d3.event.preventDefault();
|
||||
// });
|
||||
|
||||
item.exit()
|
||||
.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
|
||||
enter.classed('expanded', false);
|
||||
details.style('display', 'none');
|
||||
|
||||
// Set new
|
||||
detail
|
||||
.style('opacity', exp ? 1 : 0)
|
||||
.transition()
|
||||
.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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function addChoices(datum) {
|
||||
var selection = d3.select(this)
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list');
|
||||
|
||||
function addChoices(selection) {
|
||||
var choices = selection
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list')
|
||||
.selectAll('li')
|
||||
.data(function(d) { return d.choices || []; });
|
||||
|
||||
@@ -358,9 +326,10 @@ iD.modes.Save = function(context) {
|
||||
label
|
||||
.append('input')
|
||||
.attr('type', 'radio')
|
||||
.attr('name', datum.id)
|
||||
.on('change', function(d) {
|
||||
.attr('name', function(d) { return d.id; })
|
||||
.on('change', function(d, i) {
|
||||
var ul = this.parentElement.parentElement.parentElement;
|
||||
ul.__data__.chosen = i;
|
||||
choose(ul, d);
|
||||
});
|
||||
|
||||
@@ -368,17 +337,17 @@ iD.modes.Save = function(context) {
|
||||
.append('span')
|
||||
.text(function(d) { return d.text; });
|
||||
|
||||
// choose first choice by default..
|
||||
choices
|
||||
.each(function(d, i) {
|
||||
if (i === 0) choose(this.parentElement, d);
|
||||
var ul = this.parentElement;
|
||||
if (ul.__data__.chosen === i) choose(ul, d);
|
||||
});
|
||||
}
|
||||
|
||||
function choose(el, datum) {
|
||||
function choose(ul, datum) {
|
||||
if (d3.event) d3.event.preventDefault();
|
||||
|
||||
d3.select(el)
|
||||
d3.select(ul)
|
||||
.selectAll('li')
|
||||
.classed('active', function(d) { return d === datum; })
|
||||
.selectAll('input')
|
||||
@@ -471,8 +440,10 @@ iD.modes.Save = function(context) {
|
||||
}
|
||||
|
||||
function zoomToEntity(id) {
|
||||
var entity = context.graph().hasEntity(id);
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
|
||||
var entity = context.graph().hasEntity(id);
|
||||
if (entity) {
|
||||
context.map().zoomTo(entity);
|
||||
context.surface().selectAll(
|
||||
@@ -499,27 +470,13 @@ iD.modes.Save = function(context) {
|
||||
id: 'save'
|
||||
};
|
||||
|
||||
var behaviors = [
|
||||
iD.behavior.Hover(context),
|
||||
// iD.behavior.Select(context),
|
||||
iD.behavior.Lasso(context),
|
||||
iD.modes.DragNode(context).behavior];
|
||||
|
||||
mode.enter = function() {
|
||||
behaviors.forEach(function(behavior) {
|
||||
context.install(behavior);
|
||||
});
|
||||
|
||||
context.connection().authenticate(function() {
|
||||
context.ui().sidebar.show(ui);
|
||||
});
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
behaviors.forEach(function(behavior) {
|
||||
context.uninstall(behavior);
|
||||
});
|
||||
|
||||
context.ui().sidebar.hide(ui);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user