From 0cbff57dc9ac12d54c33e043f40416168496b3dd Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 7 Feb 2018 19:04:28 -0500 Subject: [PATCH] Cycle through `only_` turn restriction states (re: #2622) --- modules/actions/restrict_turn.js | 11 +++-------- modules/actions/unrestrict_turn.js | 8 ++++---- modules/osm/intersection.js | 2 +- modules/ui/fields/restrictions.js | 23 +++++++++++++++++----- test/spec/actions/unrestrict_turn.js | 29 +++++++++++++--------------- test/spec/osm/intersection.js | 6 +++--- 6 files changed, 42 insertions(+), 37 deletions(-) diff --git a/modules/actions/restrict_turn.js b/modules/actions/restrict_turn.js index df45ece81..60284c381 100644 --- a/modules/actions/restrict_turn.js +++ b/modules/actions/restrict_turn.js @@ -27,7 +27,7 @@ import { // Normally, this will be undefined and the relation will automatically // be assigned a new ID. // -export function actionRestrictTurn(turn, projection, restrictionId) { +export function actionRestrictTurn(turn, projection, restrictionID) { return function(graph) { var fromWay = graph.entity(turn.from.way); @@ -49,15 +49,10 @@ export function actionRestrictTurn(turn, projection, restrictionId) { members.push({ id: toWay.id, type: 'way', role: 'to' }); return graph.replace(osmRelation({ - id: restrictionId, + id: restrictionID, tags: { type: 'restriction', - restriction: turn.restriction || - osmInferRestriction( - graph, - turn.from, - turn.to, - projection) + restriction: turn.restriction || osmInferRestriction(graph, turn.from, turn.to, projection) }, members: members })); diff --git a/modules/actions/unrestrict_turn.js b/modules/actions/unrestrict_turn.js index 3e0a794c5..4210b3a7b 100644 --- a/modules/actions/unrestrict_turn.js +++ b/modules/actions/unrestrict_turn.js @@ -8,19 +8,19 @@ import { actionDeleteRelation } from './delete_relation'; // from: { node: , way: }, // via: { node: }, // to: { node: , way: }, -// restriction: +// restrictionID: // } // -// In the simple case, `restriction` is a reference to a `no_*` restriction +// In the simple case, `restrictionID` is a reference to a `no_*` restriction // on the turn itself. In this case, it is simply deleted. // -// The more complex case is where `restriction` references an `only_*` +// The more complex case is where `restrictionID` references an `only_*` // restriction on a different turn in the same intersection. In that case, // that restriction is also deleted, but at the same time restrictions on // the turns other than the first two are created. // export function actionUnrestrictTurn(turn) { return function(graph) { - return actionDeleteRelation(turn.restriction)(graph); + return actionDeleteRelation(turn.restrictionID)(graph); }; } diff --git a/modules/osm/intersection.js b/modules/osm/intersection.js index 7b97f9af0..236fa9c5f 100644 --- a/modules/osm/intersection.js +++ b/modules/osm/intersection.js @@ -471,7 +471,7 @@ export function osmIntersection(graph, startVertexId) { var turn = pathToTurn(currPath); if (turn) { if (matchedRestriction) { - turn.restriction = matchedRestriction.id; + turn.restrictionID = matchedRestriction.id; turn.only = matchedRestriction.only; turn.direct = matchedRestriction.direct; turn.indirect = matchedRestriction.indirect; diff --git a/modules/ui/fields/restrictions.js b/modules/ui/fields/restrictions.js index 81df760e8..8ea0b5b95 100644 --- a/modules/ui/fields/restrictions.js +++ b/modules/ui/fields/restrictions.js @@ -1,3 +1,5 @@ +import _cloneDeep from 'lodash-es/cloneDeep'; + import { dispatch as d3_dispatch } from 'd3-dispatch'; import { @@ -206,7 +208,18 @@ export function uiFieldRestrictions(field, context) { } else if (datum instanceof osmTurn) { var actions; - if (datum.restriction) { + datum.restriction = osmInferRestriction(vgraph, datum.from, datum.to, projection); + + if (datum.restrictionID && !datum.only) { // cycle thru the `only_` state + var datumOnly = _cloneDeep(datum); + datumOnly.only = true; + datumOnly.restriction = datumOnly.restriction.replace(/^no\_/, 'only_'); + actions = _intersection.actions.concat([ + actionUnrestrictTurn(datum, projection), + actionRestrictTurn(datumOnly, projection), + t('operations.restriction.annotation.create') + ]); + } else if (datum.restrictionID) { actions = _intersection.actions.concat([ actionUnrestrictTurn(datum, projection), t('operations.restriction.annotation.delete') @@ -250,14 +263,14 @@ export function uiFieldRestrictions(field, context) { .classed('related', true); var turnType = { - 'no_left_turn': 'Left Turns', - 'no_right_turn': 'Right Turns', - 'no_u_turn': 'U-Turns', + 'no_left_turn': 'Left Turn', + 'no_right_turn': 'Right Turn', + 'no_u_turn': 'U-Turn', 'no_straight_on': 'Continuing' }[osmInferRestriction(vgraph, datum.from, datum.to, projection)]; var restrictType = 'IS'; - if (datum.restriction) { + if (datum.restrictionID) { if (datum.only) { restrictType = 'IS ONLY'; } if (datum.direct) { restrictType = 'IS NOT'; } if (datum.indirect) { restrictType = 'IS NOT '; } diff --git a/test/spec/actions/unrestrict_turn.js b/test/spec/actions/unrestrict_turn.js index 991439da8..9ab094c6e 100644 --- a/test/spec/actions/unrestrict_turn.js +++ b/test/spec/actions/unrestrict_turn.js @@ -1,24 +1,21 @@ describe('iD.actionUnrestrictTurn', function() { it('removes a restriction from a restricted turn', function() { // u====*--->w - var graph = iD.Graph([ - iD.Node({id: 'u'}), - iD.Node({id: '*'}), - iD.Node({id: 'w'}), - iD.Way({id: '=', nodes: ['u', '*'], tags: {highway: 'residential'}}), - iD.Way({id: '-', nodes: ['*', 'w'], tags: {highway: 'residential'}}), - iD.Relation({id: 'r', tags: {type: 'restriction'}, members: [ - {id: '=', role: 'from', type: 'way'}, - {id: '-', role: 'to', type: 'way'}, - {id: '*', role: 'via', type: 'node'} - ]}) - ]), - action = iD.actionUnrestrictTurn({ - restriction: 'r' - }); + var graph = iD.coreGraph([ + iD.osmNode({ id: 'u' }), + iD.osmNode({ id: '*' }), + iD.osmNode({ id: 'w' }), + iD.osmWay({ id: '=', nodes: ['u', '*'], tags: { highway: 'residential' } }), + iD.osmWay({ id: '-', nodes: ['*', 'w'], tags: { highway: 'residential' } }), + iD.osmRelation({ id: 'r', tags: { type: 'restriction' }, members: [ + { id: '=', role: 'from', type: 'way' }, + { id: '-', role: 'to', type: 'way' }, + { id: '*', role: 'via', type: 'node' } + ]}) + ]); + var action = iD.actionUnrestrictTurn({ restrictionID: 'r' }); graph = action(graph); - expect(graph.hasEntity('r')).to.be.undefined; }); }); diff --git a/test/spec/osm/intersection.js b/test/spec/osm/intersection.js index a0a3818e4..e27772754 100644 --- a/test/spec/osm/intersection.js +++ b/test/spec/osm/intersection.js @@ -338,7 +338,7 @@ describe('iD.osmIntersection', function() { expect(turns[1]).to.be.an.instanceOf(iD.osmTurn); expect(turns[1].key).to.eql('=,*,-'); expect(turns[1].u).to.be.not.ok; - expect(turns[1].restriction).to.eql('r'); + expect(turns[1].restrictionID).to.eql('r'); expect(turns[1].direct).to.be.true; expect(turns[1].indirect).to.be.not.ok; expect(turns[1].only).to.be.not.ok; @@ -372,7 +372,7 @@ describe('iD.osmIntersection', function() { expect(turns[1]).to.be.an.instanceOf(iD.osmTurn); expect(turns[1].key).to.eql('=,*,~'); - expect(turns[1].restriction).to.eql('r'); + expect(turns[1].restrictionID).to.eql('r'); expect(turns[1].u).to.be.not.ok; expect(turns[1].direct).to.be.not.ok; expect(turns[1].indirect).to.be.true; @@ -380,7 +380,7 @@ describe('iD.osmIntersection', function() { expect(turns[2]).to.be.an.instanceOf(iD.osmTurn); expect(turns[2].key).to.eql('=,*,-'); - expect(turns[2].restriction).to.eql('r'); + expect(turns[2].restrictionID).to.eql('r'); expect(turns[2].u).to.be.not.ok; expect(turns[2].direct).to.be.not.ok; expect(turns[2].indirect).to.be.not.ok;