diff --git a/modules/actions/index.js b/modules/actions/index.js index acb76f3ff..6eac6bfc6 100644 --- a/modules/actions/index.js +++ b/modules/actions/index.js @@ -33,3 +33,4 @@ export { actionStraighten } from './straighten'; export { actionUnrestrictTurn } from './unrestrict_turn'; export { actionReflect } from './reflect.js'; export { actionDetachNode } from './detach_node'; +export { actionUpgradeTags } from './upgrade_tags'; diff --git a/modules/actions/upgrade_tags.js b/modules/actions/upgrade_tags.js new file mode 100644 index 000000000..38ca76675 --- /dev/null +++ b/modules/actions/upgrade_tags.js @@ -0,0 +1,35 @@ +import _clone from 'lodash-es/clone'; + +export function actionUpgradeTags(entityId, oldTags, replaceTags) { + return function(graph) { + var entity = graph.entity(entityId); + var tags = _clone(entity.tags); + var transferValue; + for (var oldTagKey in oldTags) { + if (oldTags[oldTagKey] === '*') { + transferValue = tags[oldTagKey]; + } + delete tags[oldTagKey]; + } + if (replaceTags) { + for (var replaceKey in replaceTags) { + var replaceValue = replaceTags[replaceKey]; + if (replaceValue === '*') { + if (tags[replaceKey]) { + // any value is okay and there already + // is one, so don't update it + continue; + } else { + // otherwise assume `yes` is okay + tags[replaceKey] = 'yes'; + } + } else if (replaceValue === '$1') { + tags[replaceKey] = transferValue; + } else { + tags[replaceKey] = replaceValue; + } + } + } + return graph.replace(entity.update({tags: tags})); + }; +} diff --git a/modules/validations/deprecated_tag.js b/modules/validations/deprecated_tag.js index e72677814..56dba449d 100644 --- a/modules/validations/deprecated_tag.js +++ b/modules/validations/deprecated_tag.js @@ -1,7 +1,7 @@ import _clone from 'lodash-es/clone'; import { t } from '../util/locale'; -import { actionChangeTags } from '../actions'; +import { actionUpgradeTags, actionChangeTags } from '../actions'; import { utilDisplayLabel, utilTagText } from '../util'; import { validationIssue, validationIssueFix } from '../core/validator'; @@ -48,37 +48,11 @@ export function validationDeprecatedTag() { icon: 'iD-icon-up', title: t('issues.fix.' + (isCombo ? 'upgrade_tag_combo' : 'upgrade_tag') + '.title'), onClick: function() { - var entity = this.issue.entities[0]; - var tags = _clone(entity.tags); - var replaceTags = this.issue.info.replaceTags; var oldTags = this.issue.info.oldTags; + var replaceTags = this.issue.info.replaceTags; var fixTextID = Object.keys(oldTags).length > 1 ? 'upgrade_tag_combo' : 'upgrade_tag'; - var transferValue; - for (var oldTagKey in oldTags) { - if (oldTags[oldTagKey] === '*') { - transferValue = tags[oldTagKey]; - } - delete tags[oldTagKey]; - } - for (var replaceKey in replaceTags) { - var replaceValue = replaceTags[replaceKey]; - if (replaceValue === '*') { - if (tags[replaceKey]) { - // any value is okay and there already - // is one, so don't update it - continue; - } else { - // otherwise assume `yes` is okay - tags[replaceKey] = 'yes'; - } - } else if (replaceValue === '$1') { - tags[replaceKey] = transferValue; - } else { - tags[replaceKey] = replaceValue; - } - } context.perform( - actionChangeTags(entity.id, tags), + actionUpgradeTags(this.issue.entities[0].id, oldTags, replaceTags), t('issues.fix.' + fixTextID + '.annotation') ); } diff --git a/test/index.html b/test/index.html index 66bf09be9..8ac0e0974 100644 --- a/test/index.html +++ b/test/index.html @@ -63,6 +63,7 @@ + diff --git a/test/spec/actions/upgrade_tags.js b/test/spec/actions/upgrade_tags.js new file mode 100644 index 000000000..eba80416d --- /dev/null +++ b/test/spec/actions/upgrade_tags.js @@ -0,0 +1,59 @@ +describe('iD.actionUpgradeTags', function () { + + it('upgrades a tag', function () { + var oldTags = { amenity: 'swimming_pool' }, + newTags = { leisure: 'swimming_pool' }, + entity = iD.Entity({ tags: { amenity: 'swimming_pool', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ leisure: 'swimming_pool', name: 'Foo' }); + }); + + it('upgrades a tag combination', function () { + var oldTags = { amenity: 'vending_machine', vending: 'news_papers' }, + newTags = { amenity: 'vending_machine', vending: 'newspapers' }, + entity = iD.Entity({ tags: { amenity: 'vending_machine', vending: 'news_papers', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ amenity: 'vending_machine', vending: 'newspapers', name: 'Foo' }); + }); + + it('upgrades a tag with multiple replacement tags', function () { + var oldTags = { natural: 'marsh' }, + newTags = { natural: 'wetland', wetland: 'marsh' }, + entity = iD.Entity({ tags: { natural: 'marsh', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ natural: 'wetland', wetland: 'marsh', name: 'Foo' }); + }); + + it('upgrades a tag with no replacement tags', function () { + var oldTags = { highway: 'no' }, + newTags = undefined, + entity = iD.Entity({ tags: { highway: 'no', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ name: 'Foo' }); + }); + + it('upgrades a wildcard tag and moves the value', function () { + var oldTags = { color: '*' }, + newTags = { colour: '$1' }, + entity = iD.Entity({ tags: { color: 'red', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ colour: 'red', name: 'Foo' }); + }); + + it('upgrades a tag with a wildcard replacement and adds a default value', function () { + var oldTags = { amenity: 'shop' }, + newTags = { shop: '*' }, + entity = iD.Entity({ tags: { amenity: 'shop', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ shop: 'yes', name: 'Foo' }); + }); + + it('upgrades a tag with a wildcard replacement and maintains the existing value', function () { + var oldTags = { amenity: 'shop' }, + newTags = { shop: '*' }, + entity = iD.Entity({ tags: { amenity: 'shop', shop: 'supermarket', name: 'Foo' }}), + graph = iD.actionUpgradeTags(entity.id, oldTags, newTags)(iD.coreGraph([entity])); + expect(graph.entity(entity.id).tags).to.eql({ shop: 'supermarket', name: 'Foo' }); + }); + +});