From fb25a440179780fabf2ccb9c017f5fcbd6e407cf Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Tue, 12 Mar 2019 17:08:20 -0400 Subject: [PATCH] Generalize deprecated_tags validation to outdated_tags validation Add check for missing addTags go outdated_tags validation (close #6043, close #6042) --- data/core.yaml | 22 ++--- dist/locales/en.json | 29 ++---- modules/validations/deprecated_tag.js | 88 ------------------- modules/validations/index.js | 2 +- modules/validations/outdated_tags.js | 71 +++++++++++++++ test/index.html | 2 +- .../{deprecated_tag.js => outdated_tags.js} | 6 +- 7 files changed, 89 insertions(+), 131 deletions(-) delete mode 100644 modules/validations/deprecated_tag.js create mode 100644 modules/validations/outdated_tags.js rename test/spec/validations/{deprecated_tag.js => outdated_tags.js} (89%) diff --git a/data/core.yaml b/data/core.yaml index 954249d4d..cfc287768 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1244,13 +1244,6 @@ en: tip: "Crossing indoor features should use different levels." indoor-indoor_connectable: tip: "Crossing indoor features should be connected or use different levels." - deprecated_tag: - title: Deprecated Tags - single: - message: '{feature} has the outdated tag "{tag}"' - combination: - message: '{feature} has an outdated tag combination: {tags}' - tip: "Some tags become deprecated over time and should be replaced." disconnected_way: title: Disconnected Ways highway: @@ -1285,6 +1278,10 @@ en: title: Misplaced Multipolygon Tags message: "{multipolygon} has misplaced tags" tip: "Multipolygons should be tagged on their relation, not their outer way." + outdated_tags: + title: Outdated Tags + message: '{feature} has outdated tags' + tip: "Some tags change over time and should be updated." tag_suggests_area: title: Lines Tagged as Areas message: '{feature} should be a closed area based on the tag "{tag}"' @@ -1308,10 +1305,6 @@ en: move_tags: title: Move the tags annotation: Moved tags. - remove_deprecated_tag: - annotation: Removed an old tag. - remove_deprecated_tag_combo: - annotation: Removed an old tag combination. remove_from_relation: title: Remove from relation remove_generic_name: @@ -1333,12 +1326,9 @@ en: tag_as_disconnected: title: Tag as disconnected annotation: Tagged very close features as disconnected. - upgrade_tag: - title: Upgrade the tag - annotation: Upgraded an old tag. - upgrade_tag_combo: + upgrade_tags: title: Upgrade the tags - annotation: Upgraded an old tag combination. + annotation: Upgraded old tags. use_bridge_or_tunnel: title: Use a bridge or tunnel use_different_layers: diff --git a/dist/locales/en.json b/dist/locales/en.json index 7fc779472..4fc36816f 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1523,16 +1523,6 @@ "tip": "Crossing indoor features should be connected or use different levels." } }, - "deprecated_tag": { - "title": "Deprecated Tags", - "single": { - "message": "{feature} has the outdated tag \"{tag}\"" - }, - "combination": { - "message": "{feature} has an outdated tag combination: {tags}" - }, - "tip": "Some tags become deprecated over time and should be replaced." - }, "disconnected_way": { "title": "Disconnected Ways", "highway": { @@ -1580,6 +1570,11 @@ "message": "{multipolygon} has misplaced tags", "tip": "Multipolygons should be tagged on their relation, not their outer way." }, + "outdated_tags": { + "title": "Outdated Tags", + "message": "{feature} has outdated tags", + "tip": "Some tags change over time and should be updated." + }, "tag_suggests_area": { "title": "Lines Tagged as Areas", "message": "{feature} should be a closed area based on the tag \"{tag}\"", @@ -1612,12 +1607,6 @@ "title": "Move the tags", "annotation": "Moved tags." }, - "remove_deprecated_tag": { - "annotation": "Removed an old tag." - }, - "remove_deprecated_tag_combo": { - "annotation": "Removed an old tag combination." - }, "remove_from_relation": { "title": "Remove from relation" }, @@ -1648,13 +1637,9 @@ "title": "Tag as disconnected", "annotation": "Tagged very close features as disconnected." }, - "upgrade_tag": { - "title": "Upgrade the tag", - "annotation": "Upgraded an old tag." - }, - "upgrade_tag_combo": { + "upgrade_tags": { "title": "Upgrade the tags", - "annotation": "Upgraded an old tag combination." + "annotation": "Upgraded old tags." }, "use_bridge_or_tunnel": { "title": "Use a bridge or tunnel" diff --git a/modules/validations/deprecated_tag.js b/modules/validations/deprecated_tag.js deleted file mode 100644 index 56dba449d..000000000 --- a/modules/validations/deprecated_tag.js +++ /dev/null @@ -1,88 +0,0 @@ -import _clone from 'lodash-es/clone'; - -import { t } from '../util/locale'; -import { actionUpgradeTags, actionChangeTags } from '../actions'; -import { utilDisplayLabel, utilTagText } from '../util'; -import { validationIssue, validationIssueFix } from '../core/validator'; - -export function validationDeprecatedTag() { - var type = 'deprecated_tag'; - - - var validation = function(entity, context) { - var issues = []; - var deprecatedTagsArray = entity.deprecatedTags(); - if (deprecatedTagsArray.length > 0) { - for (var deprecatedTagIndex in deprecatedTagsArray) { - var deprecatedTags = deprecatedTagsArray[deprecatedTagIndex]; - var labelTags = _clone(deprecatedTags.old); - for (var key in labelTags) { - if (labelTags[key] === '*') { - // show the user the actual tag, like color=red instead of color=* - labelTags[key] = entity.tags[key]; - } - } - var tagsLabel = utilTagText({ tags: labelTags }); - var featureLabel = utilDisplayLabel(entity, context); - var isCombo = Object.keys(deprecatedTags.old).length > 1; - var messageObj = { feature: featureLabel }; - if (isCombo) { - messageObj.tags = tagsLabel; - } else { - messageObj.tag = tagsLabel; - } - var tagMessageID = isCombo ? 'combination' : 'single'; - issues.push(new validationIssue({ - type: type, - severity: 'warning', - message: t('issues.deprecated_tag.' + tagMessageID + '.message', messageObj), - tooltip: t('issues.deprecated_tag.tip'), - entities: [entity], - hash: tagsLabel, - info: { - oldTags: deprecatedTags.old, - replaceTags: deprecatedTags.replace - }, - fixes: [ - new validationIssueFix({ - icon: 'iD-icon-up', - title: t('issues.fix.' + (isCombo ? 'upgrade_tag_combo' : 'upgrade_tag') + '.title'), - onClick: function() { - var oldTags = this.issue.info.oldTags; - var replaceTags = this.issue.info.replaceTags; - var fixTextID = Object.keys(oldTags).length > 1 ? 'upgrade_tag_combo' : 'upgrade_tag'; - context.perform( - actionUpgradeTags(this.issue.entities[0].id, oldTags, replaceTags), - t('issues.fix.' + fixTextID + '.annotation') - ); - } - }), - new validationIssueFix({ - icon: 'iD-operation-delete', - title: t('issues.fix.' + (isCombo ? 'remove_tags' : 'remove_tag') + '.title'), - onClick: function() { - var entity = this.issue.entities[0]; - var tags = _clone(entity.tags); - var oldTags = this.issue.info.oldTags; - for (var key in oldTags) { - delete tags[key]; - } - var fixTextID = Object.keys(oldTags).length > 1 ? 'remove_deprecated_tag_combo' : 'remove_deprecated_tag'; - context.perform( - actionChangeTags(entity.id, tags), - t('issues.fix.' + fixTextID + '.annotation') - ); - } - }) - ] - })); - } - } - - return issues; - }; - - validation.type = type; - - return validation; -} diff --git a/modules/validations/index.js b/modules/validations/index.js index 3a4a48e2a..693107db0 100644 --- a/modules/validations/index.js +++ b/modules/validations/index.js @@ -1,6 +1,5 @@ export { validationAlmostJunction } from './almost_junction'; export { validationCrossingWays } from './crossing_ways'; -export { validationDeprecatedTag } from './deprecated_tag'; export { validationDisconnectedWay } from './disconnected_way'; export { validationGenericName } from './generic_name'; export { validationManyDeletions } from './many_deletions'; @@ -8,4 +7,5 @@ export { validationMaprules } from './maprules'; export { validationMissingRole } from './missing_role'; export { validationMissingTag } from './missing_tag'; export { validationOldMultipolygon } from './old_multipolygon'; +export { validationOutdatedTags } from './outdated_tags'; export { validationTagSuggestsArea } from './tag_suggests_area'; diff --git a/modules/validations/outdated_tags.js b/modules/validations/outdated_tags.js new file mode 100644 index 000000000..4fc8326eb --- /dev/null +++ b/modules/validations/outdated_tags.js @@ -0,0 +1,71 @@ +import _clone from 'lodash-es/clone'; + +import { t } from '../util/locale'; +import { actionUpgradeTags, actionChangeTags } from '../actions'; +import { utilDisplayLabel } from '../util'; +import { validationIssue, validationIssueFix } from '../core/validator'; + +export function validationOutdatedTags() { + var type = 'outdated_tags'; + + + var validation = function(entity, context) { + + var deprecatedTagsArray = entity.deprecatedTags(); + + var preset = context.presets().match(entity, context.graph()); + var missingRecommendedTags = {}; + if (!preset.isFallback() && preset.tags !== preset.addTags) { + missingRecommendedTags = Object.keys(preset.addTags).reduce(function(obj, key) { + if (!entity.tags[key]) { + obj[key] = preset.addTags[key]; + } + return obj; + }, {}); + } + + if (deprecatedTagsArray.length === 0 && + Object.keys(missingRecommendedTags).length === 0) return []; + + return [new validationIssue({ + type: type, + severity: 'warning', + message: t('issues.outdated_tags.message', { feature: utilDisplayLabel(entity, context) }), + tooltip: t('issues.outdated_tags.tip'), + entities: [entity], + info: { + deprecatedTagsArray: deprecatedTagsArray, + missingRecommendedTags: missingRecommendedTags + }, + fixes: [ + new validationIssueFix({ + icon: 'iD-icon-up', + title: t('issues.fix.upgrade_tags.title'), + onClick: function() { + var deprecatedTagsArray = this.issue.info.deprecatedTagsArray; + var missingRecommendedTags = this.issue.info.missingRecommendedTags; + var entityID = this.issue.entities[0].id; + context.perform( + function(graph) { + deprecatedTagsArray.forEach(function(deprecatedTags) { + graph = actionUpgradeTags(entityID, deprecatedTags.old, deprecatedTags.replace)(graph); + }); + var tags = _clone(graph.entity(entityID).tags); + for (var key in missingRecommendedTags) { + tags[key] = missingRecommendedTags[key]; + } + graph = actionChangeTags(entityID, tags)(graph); + return graph; + }, + t('issues.fix.upgrade_tags.annotation') + ); + } + }) + ] + })]; + }; + + validation.type = type; + + return validation; +} diff --git a/test/index.html b/test/index.html index 98d454dc3..783216903 100644 --- a/test/index.html +++ b/test/index.html @@ -148,11 +148,11 @@ - + diff --git a/test/spec/validations/deprecated_tag.js b/test/spec/validations/outdated_tags.js similarity index 89% rename from test/spec/validations/deprecated_tag.js rename to test/spec/validations/outdated_tags.js index cd98818f5..3c78f6da9 100644 --- a/test/spec/validations/deprecated_tag.js +++ b/test/spec/validations/outdated_tags.js @@ -1,4 +1,4 @@ -describe('iD.validations.deprecated_tag', function () { +describe('iD.validations.outdated_tags', function () { var context; beforeEach(function() { @@ -18,7 +18,7 @@ describe('iD.validations.deprecated_tag', function () { } function validate() { - var validator = iD.validationDeprecatedTag(); + var validator = iD.validationOutdatedTags(); var changes = context.history().changes(); var entities = changes.modified.concat(changes.created); var issues = []; @@ -44,7 +44,7 @@ describe('iD.validations.deprecated_tag', function () { var issues = validate(); expect(issues).to.have.lengthOf(1); var issue = issues[0]; - expect(issue.type).to.eql('deprecated_tag'); + expect(issue.type).to.eql('outdated_tags'); expect(issue.severity).to.eql('warning'); expect(issue.entities).to.have.lengthOf(1); expect(issue.entities[0].id).to.eql('w-1');