Disallow disconnecting that would damage relations

Fixes #1714
This commit is contained in:
John Firebaugh
2016-02-07 20:27:39 -08:00
parent 36a767554c
commit 8a3314e5d3
4 changed files with 63 additions and 1 deletions

View File

@@ -105,6 +105,7 @@ en:
annotation: Disconnected lines/areas.
not_connected: There aren't enough lines/areas here to disconnect.
connected_to_hidden: This can't be disconnected because it is connected to a hidden feature.
relation: This can't be disconnected because it connects members of a relation.
merge:
title: Merge
description: Merge these features.

View File

@@ -133,7 +133,8 @@
"key": "D",
"annotation": "Disconnected lines/areas.",
"not_connected": "There aren't enough lines/areas here to disconnect.",
"connected_to_hidden": "This can't be disconnected because it is connected to a hidden feature."
"connected_to_hidden": "This can't be disconnected because it is connected to a hidden feature.",
"relation": "This can't be disconnected because it connects members of a relation."
},
"merge": {
"title": "Merge",

View File

@@ -64,6 +64,27 @@ iD.actions.Disconnect = function(nodeId, newNodeId) {
var connections = action.connections(graph);
if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
return 'not_connected';
var parentWays = graph.parentWays(graph.entity(nodeId)),
seenRelationIds = {},
sharedRelation;
parentWays.forEach(function(way) {
if (wayIds && wayIds.indexOf(way.id) === -1)
return;
var relations = graph.parentRelations(way);
relations.forEach(function(relation) {
if (relation.id in seenRelationIds) {
sharedRelation = relation;
} else {
seenRelationIds[relation.id] = true;
}
});
});
if (sharedRelation)
return 'relation';
};
action.limitWays = function(_) {

View File

@@ -81,6 +81,45 @@ describe("iD.actions.Disconnect", function () {
expect(iD.actions.Disconnect('b', ['|']).disabled(graph)).not.to.be.ok;
});
it("returns 'relation' for a node connecting any two members of the same relation", function () {
// Covers restriction relations, routes, multipolygons.
// a ---- b ---- c
var graph = iD.Graph([
iD.Node({id: 'a'}),
iD.Node({id: 'b'}),
iD.Node({id: 'c'}),
iD.Way({id: 'f', nodes: ['a', 'b']}),
iD.Way({id: 't', nodes: ['b', 'c']}),
iD.Relation({id: 'r', members: [
{ id: 'f' },
{ id: 't' }
]})
]);
expect(iD.actions.Disconnect('b').disabled(graph)).to.eql('relation');
});
it("returns falsy for a node connecting two members of an unaffected relation", function () {
// a ---- b ---- c
// |
// d
var graph = iD.Graph([
iD.Node({id: 'a'}),
iD.Node({id: 'b'}),
iD.Node({id: 'c'}),
iD.Node({id: 'd'}),
iD.Way({id: 'f', nodes: ['a', 'b']}),
iD.Way({id: 't', nodes: ['b', 'c']}),
iD.Way({id: '|', nodes: ['b', 'd']}),
iD.Relation({id: 'r', members: [
{ id: 'f' },
{ id: 't' }
]})
]);
expect(iD.actions.Disconnect('b').limitWays(['|']).disabled(graph)).not.to.be.ok;
});
});
it("replaces the node with a new node in all but the first way", function () {