diff --git a/data/core.yaml b/data/core.yaml index 1a14e20da..bfd36e8f5 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1442,6 +1442,8 @@ en: title: Continue drawing from end delete_feature: title: Delete this feature + ignore_issue: + title: Ignore this issue move_tags: title: Move the tags annotation: Moved tags. diff --git a/dist/locales/en.json b/dist/locales/en.json index eaede94df..fe721da02 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1793,6 +1793,9 @@ "delete_feature": { "title": "Delete this feature" }, + "ignore_issue": { + "title": "Ignore this issue" + }, "move_tags": { "title": "Move the tags", "annotation": "Moved tags." diff --git a/modules/core/validation/models.js b/modules/core/validation/models.js index 1b5ac4e71..4599a5abc 100644 --- a/modules/core/validation/models.js +++ b/modules/core/validation/models.js @@ -7,10 +7,10 @@ export function validationIssue(attrs) { this.severity = attrs.severity; // required - 'warning' or 'error' this.message = attrs.message; // required - localized string this.reference = attrs.reference; // optional - function(selection) to render reference information - this.entities = attrs.entities; // optional - array of entities involved in the issue + this.entityIds = attrs.entityIds; // optional - array of IDs of entities involved in the issue this.loc = attrs.loc; // optional - [lon, lat] to zoom in on to see the issue this.data = attrs.data; // optional - object containing extra data for the fixes - this.fixes = attrs.fixes; // optional - array of validationIssueFix objects + this.fixes = attrs.fixes || []; // optional - array of validationIssueFix objects this.hash = attrs.hash; // optional - string to further differentiate the issue this.id = generateID.apply(this); // generated - see below @@ -25,10 +25,14 @@ export function validationIssue(attrs) { parts.push(this.hash); } + if (this.subtype) { + parts.push(this.subtype); + } + // include entities this issue is for // (sort them so the id is deterministic) - if (this.entities) { - var entityKeys = this.entities.map(osmEntity.key).sort(); + if (this.entityIds) { + var entityKeys = this.entityIds.slice().sort(); parts.push.apply(parts, entityKeys); } @@ -48,9 +52,9 @@ export function validationIssue(attrs) { if (this.loc) { return _extent = geoExtent(this.loc); } - if (this.entities && this.entities.length) { - return _extent = this.entities.reduce(function(extent, entity) { - return extent.extend(entity.extent(resolver)); + if (this.entityIds && this.entityIds.length) { + return _extent = this.entityIds.reduce(function(extent, entityId) { + return extent.extend(resolver.entity(entityId).extent(resolver)); }, geoExtent()); } return null; diff --git a/modules/core/validator.js b/modules/core/validator.js index 093b04cc7..d36c34900 100644 --- a/modules/core/validator.js +++ b/modules/core/validator.js @@ -2,6 +2,8 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { coreDifference } from './difference'; import { utilArrayGroupBy, utilCallWhenIdle, utilRebind } from '../util'; +import { t } from '../util/locale'; +import { validationIssueFix } from './validation/models'; import * as Validations from '../validations/index'; @@ -12,6 +14,7 @@ export function coreValidator(context) { var _rules = {}; var _disabledRules = {}; + var _ignoredIssueIDs = {}; // issue.id -> true var _issuesByIssueID = {}; // issue.id -> issue var _issuesByEntityID = {}; // entity.id -> set(issue.id) var _validatedGraph = null; @@ -57,9 +60,10 @@ export function coreValidator(context) { // options = { // what: 'edited', // 'all' or 'edited' // where: 'visible', // 'all' or 'visible' + // includeIgnored: false // true or false // }; validator.getIssues = function(options) { - var opts = Object.assign({ what: 'all', where: 'all' }, options); + var opts = Object.assign({ what: 'all', where: 'all', includeIgnored: false }, options); var issues = Object.values(_issuesByIssueID); var changes = context.history().difference().changes(); var view = context.map().extent(); @@ -69,19 +73,21 @@ export function coreValidator(context) { // Sanity check: This issue may be for an entity that not longer exists. // If we detect this, uncache and return false so it is not incluced.. - var entities = issue.entities || []; - for (var i = 0; i < entities.length; i++) { - var entity = entities[i]; - if (!context.hasEntity(entity.id)) { - delete _issuesByEntityID[entity.id]; - delete _issuesByIssueID[issue.id]; + var entityIds = issue.entityIds || []; + for (var i = 0; i < entityIds.length; i++) { + var entityId = entityIds[i]; + if (!context.hasEntity(entityId)) { + delete _issuesByEntityID[entityId]; + delete _issuesByIssueID[entityId]; return false; } } + if (!opts.includeIgnored && _ignoredIssueIDs[issue.id]) return false; + if (opts.what === 'edited') { - var isEdited = entities.some(function(entity) { return changes[entity.id]; }); - if (entities.length && !isEdited) return false; + var isEdited = entityIds.some(function(entityId) { return changes[entityId]; }); + if (entityIds.length && !isEdited) return false; } if (opts.where === 'visible') { @@ -108,7 +114,7 @@ export function coreValidator(context) { return Array.from(issueIDs) .map(function(id) { return _issuesByIssueID[id]; }) - .filter(function(issue) { return !_disabledRules[issue.type]; }); + .filter(function(issue) { return !_disabledRules[issue.type] && !_ignoredIssueIDs[issue.id]; }); }; @@ -158,10 +164,10 @@ export function coreValidator(context) { if (issue) { // When multiple entities are involved (e.g. crossing_ways), // remove this issue from the other entity caches too.. - var entities = issue.entities || []; - entities.forEach(function(other) { - if (other.id !== entityID) { - var otherIssueIDs = _issuesByEntityID[other.id]; + var entityIds = issue.entityIds || []; + entityIds.forEach(function(other) { + if (other !== entityID) { + var otherIssueIDs = _issuesByEntityID[other]; if (otherIssueIDs) { otherIssueIDs.delete(issueID); } @@ -176,6 +182,11 @@ export function coreValidator(context) { } + function ignoreIssue(id) { + _ignoredIssueIDs[id] = true; + } + + // // Run validation on a single entity // @@ -196,6 +207,19 @@ export function coreValidator(context) { } var detected = fn(entity, context); + detected.forEach(function(issue) { + if (issue.severity === 'warning') { + var ignoreFix = new validationIssueFix({ + title: t('issues.fix.ignore_issue.title'), + icon: 'iD-icon-close', + onClick: function() { + ignoreIssue(this.issue.id); + } + }); + ignoreFix.issue = issue; + issue.fixes.push(ignoreFix); + } + }); entityIssues = entityIssues.concat(detected); ran[key] = true; return !detected.length; @@ -278,12 +302,12 @@ export function coreValidator(context) { var issues = validateEntity(entity); issues.forEach(function(issue) { - var entities = issue.entities || []; - entities.forEach(function(entity) { - if (!_issuesByEntityID[entity.id]) { - _issuesByEntityID[entity.id] = new Set(); + var entityIds = issue.entityIds || []; + entityIds.forEach(function(entityId) { + if (!_issuesByEntityID[entityId]) { + _issuesByEntityID[entityId] = new Set(); } - _issuesByEntityID[entity.id].add(issue.id); + _issuesByEntityID[entityId].add(issue.id); }); _issuesByIssueID[issue.id] = issue; }); diff --git a/modules/services/maprules.js b/modules/services/maprules.js index 4a1950228..1f7c54298 100644 --- a/modules/services/maprules.js +++ b/modules/services/maprules.js @@ -222,7 +222,7 @@ export default { type: 'maprules', severity: severity, message: selector[severity], - entities: [entity], + entityIds: [entity.id], })); } } diff --git a/modules/ui/commit.js b/modules/ui/commit.js index c5a7e01e4..a777a7994 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -123,7 +123,7 @@ export function uiCommit(context) { // add counts of warnings generated by the user's edits var warnings = context.validator() - .getIssuesBySeverity({ what: 'edited', where: 'all' }).warning; + .getIssuesBySeverity({ what: 'edited', where: 'all', includeIgnored: true }).warning; var warningsByType = utilArrayGroupBy(warnings, 'type'); for (var warningType in warningsByType) { diff --git a/modules/ui/commit_warnings.js b/modules/ui/commit_warnings.js index a335840ca..b5b59cafa 100644 --- a/modules/ui/commit_warnings.js +++ b/modules/ui/commit_warnings.js @@ -67,10 +67,10 @@ export function uiCommitWarnings(context) { items .on('mouseover', function(d) { - if (d.entities) { + if (d.entityIds) { context.surface().selectAll( utilEntityOrMemberSelector( - d.entities.map(function(e) { return e.id; }), + d.entityIds, context.graph() ) ).classed('hover', true); @@ -81,12 +81,9 @@ export function uiCommitWarnings(context) { .classed('hover', false); }) .on('click', function(d) { - if (d.entities && d.entities.length > 0) { - context.map().zoomTo(d.entities[0]); - context.enter(modeSelect( - context, - d.entities.map(function(e) { return e.id; }) - )); + if (d.entityIds && d.entityIds.length > 0) { + context.map().zoomTo(context.entity(d.entityIds[0])); + context.enter(modeSelect(context, d.entityIds)); } }); } diff --git a/modules/ui/entity_issues.js b/modules/ui/entity_issues.js index c0d493b71..25a8b31c9 100644 --- a/modules/ui/entity_issues.js +++ b/modules/ui/entity_issues.js @@ -66,16 +66,14 @@ export function uiEntityIssues(context) { .attr('class', function(d) { return 'issue severity-' + d.severity; }) .on('mouseover.highlight', function(d) { // don't hover-highlight the selected entity - var ids = d.entities - .filter(function(e) { return e.id !== _entityID; }) - .map(function(e) { return e.id; }); + var ids = d.entityIds + .filter(function(e) { return e !== _entityID; }); utilHighlightEntities(ids, true, context); }) .on('mouseout.highlight', function(d) { - var ids = d.entities - .filter(function(e) { return e.id !== _entityID; }) - .map(function(e) { return e.id; }); + var ids = d.entityIds + .filter(function(e) { return e !== _entityID; }); utilHighlightEntities(ids, false, context); }); @@ -189,7 +187,7 @@ export function uiEntityIssues(context) { }) .on('click', function(d) { if (d.onClick) { - var issueEntityIDs = d.issue.entities.map(function(e) { return e.id; }); + var issueEntityIDs = d.issue.entityIds; utilHighlightEntities(issueEntityIDs.concat(d.entityIds), false, context); d.onClick(); context.validator().validate(); diff --git a/modules/ui/issues.js b/modules/ui/issues.js index ebaea9816..a34bf51bc 100644 --- a/modules/ui/issues.js +++ b/modules/ui/issues.js @@ -90,9 +90,9 @@ export function uiIssues(context) { context.map().centerZoomEase(extent.center(), setZoom); // select the first entity - if (d.entities && d.entities.length) { + if (d.entityIds && d.entityIds.length) { window.setTimeout(function() { - var ids = d.entities.map(function(e) { return e.id; }); + var ids = d.entityIds; context.enter(modeSelect(context, [ids[0]])); utilHighlightEntities(ids, true, context); }, 250); // after ease @@ -100,12 +100,10 @@ export function uiIssues(context) { } }) .on('mouseover', function(d) { - var ids = d.entities.map(function(e) { return e.id; }); - utilHighlightEntities(ids, true, context); + utilHighlightEntities(d.entityIds, true, context); }) .on('mouseout', function(d) { - var ids = d.entities.map(function(e) { return e.id; }); - utilHighlightEntities(ids, false, context); + utilHighlightEntities(d.entityIds, false, context); }); @@ -147,7 +145,7 @@ export function uiIssues(context) { d3_event.preventDefault(); d3_event.stopPropagation(); - var issuesEntityIDs = d.issue.entities.map(function(e) { return e.id; }); + var issuesEntityIDs = d.issue.entityIds; utilHighlightEntities(issuesEntityIDs.concat(d.entityIds), false, context); context.perform.apply(context, d.autoArgs); diff --git a/modules/validations/almost_junction.js b/modules/validations/almost_junction.js index 161ec112e..8d4903700 100644 --- a/modules/validations/almost_junction.js +++ b/modules/validations/almost_junction.js @@ -47,10 +47,11 @@ export function validationAlmostJunction() { icon: 'iD-icon-abutment', title: t('issues.fix.connect_features.title'), onClick: function() { - var endNode = this.issue.entities[1]; + var endNodeId = this.issue.entityIds[1]; + var endNode = context.entity(endNodeId); var targetEdge = this.issue.data.edge; var crossLoc = this.issue.data.cross_loc; - var edgeNodes = [context.graph().entity(targetEdge[0]), context.graph().entity(targetEdge[1])]; + var edgeNodes = [context.entity(targetEdge[0]), context.entity(targetEdge[1])]; var closestNodeInfo = geoSphericalClosestNode(edgeNodes, crossLoc); var annotation = t('issues.fix.connect_almost_junction.annotation'); @@ -76,7 +77,7 @@ export function validationAlmostJunction() { icon: 'maki-barrier', title: t('issues.fix.tag_as_disconnected.title'), onClick: function() { - var nodeID = this.issue.entities[1].id; + var nodeID = this.issue.entityIds[1]; context.perform( actionChangeTags(nodeID, { noexit: 'yes' }), t('issues.fix.tag_as_disconnected.annotation') @@ -93,7 +94,7 @@ export function validationAlmostJunction() { feature2: utilDisplayLabel(edgeHighway, context) }), reference: showReference, - entities: [entity, node, edgeHighway], + entityIds: [entity.id, node.id, edgeHighway.id], loc: extendableNodeInfo.node.loc, data: { edge: extendableNodeInfo.edge, diff --git a/modules/validations/crossing_ways.js b/modules/validations/crossing_ways.js index 112108081..5e305058e 100644 --- a/modules/validations/crossing_ways.js +++ b/modules/validations/crossing_ways.js @@ -489,7 +489,9 @@ export function validationCrossingWays() { severity: 'warning', message: t('issues.crossing_ways.message', messageDict), reference: showReference, - entities: entities, + entityIds: entities.map(function(entity) { + return entity.id; + }), data: { edges: crossing.edges, connectionTags: connectionTags @@ -521,8 +523,8 @@ export function validationCrossingWays() { if (selectedIDs.length !== 1) return; var selectedID = selectedIDs[0]; - if (!this.issue.entities.some(function(entity) { - return entity.id === selectedID; + if (!this.issue.entityIds.some(function(entityId) { + return entityId === selectedID; })) return; var entity = context.hasEntity(selectedID); diff --git a/modules/validations/disconnected_way.js b/modules/validations/disconnected_way.js index 3f4e147ee..d1c2a83dc 100644 --- a/modules/validations/disconnected_way.js +++ b/modules/validations/disconnected_way.js @@ -69,7 +69,7 @@ export function validationDisconnectedWay() { title: t('issues.fix.delete_feature.title'), entityIds: [entity.id], onClick: function() { - var id = this.issue.entities[0].id; + var id = this.issue.entityIds[0]; var operation = operationDelete([id], context); if (!operation.disabled()) { operation(); @@ -83,7 +83,7 @@ export function validationDisconnectedWay() { severity: 'warning', message: t('issues.disconnected_way.highway.message', { highway: entityLabel }), reference: showReference, - entities: [entity], + entityIds: [entity.id], fixes: fixes })]; diff --git a/modules/validations/fixme_tag.js b/modules/validations/fixme_tag.js index 51f425b49..5257ccdae 100644 --- a/modules/validations/fixme_tag.js +++ b/modules/validations/fixme_tag.js @@ -25,7 +25,7 @@ export function validationFixmeTag() { severity: 'warning', message: t('issues.fixme_tag.message', { feature: utilDisplayLabel(entity, context) }), reference: showReference, - entities: [entity] + entityIds: [entity.id] })]; function showReference(selection) { diff --git a/modules/validations/generic_name.js b/modules/validations/generic_name.js index 9677429d3..9b20f423f 100644 --- a/modules/validations/generic_name.js +++ b/modules/validations/generic_name.js @@ -59,17 +59,19 @@ export function validationGenericName() { severity: 'warning', message: t('issues.generic_name.message', {feature: preset.name(), name: generic}), reference: showReference, - entities: [entity], + entityIds: [entity.id], + hash: generic, fixes: [ new validationIssueFix({ icon: 'iD-operation-delete', title: t('issues.fix.remove_generic_name.title'), onClick: function() { - var entity = this.issue.entities[0]; + var entityId = this.issue.entityIds[0]; + var entity = context.entity(entityId); var tags = Object.assign({}, entity.tags); // shallow copy delete tags.name; context.perform( - actionChangeTags(entity.id, tags), + actionChangeTags(entityId, tags), t('issues.fix.remove_generic_name.annotation') ); } diff --git a/modules/validations/impossible_oneway.js b/modules/validations/impossible_oneway.js index ae0b4f6d5..2abd4cc70 100644 --- a/modules/validations/impossible_oneway.js +++ b/modules/validations/impossible_oneway.js @@ -98,7 +98,7 @@ export function validationImpossibleOneway() { title: t('issues.fix.reverse_feature.title'), entityIds: [way.id], onClick: function() { - var id = this.issue.entities[0].id; + var id = this.issue.entityIds[0]; context.perform(actionReverse(id), t('operations.reverse.annotation')); } })); @@ -108,8 +108,8 @@ export function validationImpossibleOneway() { icon: 'iD-operation-continue' + (isFirst ? '-left' : ''), title: t('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'), onClick: function() { - var entityID = this.issue.entities[0].id; - var vertexID = this.issue.entities[1].id; + var entityID = this.issue.entityIds[0]; + var vertexID = this.issue.entityIds[1]; var way = context.entity(entityID); var vertex = context.entity(vertexID); continueDrawing(way, vertex, context); @@ -120,7 +120,7 @@ export function validationImpossibleOneway() { var placement = isFirst ? 'start' : 'end', messageID = wayType + '.', referenceID = wayType + '.'; - + if (isWaterway) { messageID += 'connected.' + placement; referenceID += 'connected'; @@ -137,7 +137,7 @@ export function validationImpossibleOneway() { feature: utilDisplayLabel(way, context) }), reference: getReference(referenceID), - entities: [way, node], + entityIds: [way.id, node.id], fixes: fixes })]; diff --git a/modules/validations/incompatible_source.js b/modules/validations/incompatible_source.js index 23916eb95..5f369c643 100644 --- a/modules/validations/incompatible_source.js +++ b/modules/validations/incompatible_source.js @@ -22,7 +22,7 @@ export function validationIncompatibleSource() { feature: utilDisplayLabel(entity, context), }), reference: getReference(invalidSource.id), - entities: [entity], + entityIds: [entity.id], fixes: [ new validationIssueFix({ title: t('issues.fix.remove_proprietary_data.title') diff --git a/modules/validations/missing_role.js b/modules/validations/missing_role.js index ec3799f51..22ed2c25e 100644 --- a/modules/validations/missing_role.js +++ b/modules/validations/missing_role.js @@ -46,10 +46,11 @@ export function validationMissingRole() { relation: utilDisplayLabel(relation, context), }), reference: showReference, - entities: [relation, way], + entityIds: [relation.id, way.id], data: { member: member }, + hash: member.index.toString(), fixes: [ makeAddRoleFix('inner', context), makeAddRoleFix('outer', context), @@ -58,7 +59,7 @@ export function validationMissingRole() { title: t('issues.fix.remove_from_relation.title'), onClick: function() { context.perform( - actionDeleteMember(this.issue.entities[0].id, this.issue.data.member.index), + actionDeleteMember(this.issue.entityIds[0], this.issue.data.member.index), t('operations.delete_member.annotation') ); } @@ -83,9 +84,9 @@ export function validationMissingRole() { title: t('issues.fix.set_as_' + role + '.title'), onClick: function() { var oldMember = this.issue.data.member; - var member = { id: this.issue.entities[1].id, type: oldMember.type, role: role }; + var member = { id: this.issue.entityIds[1], type: oldMember.type, role: role }; context.perform( - actionChangeMember(this.issue.entities[0].id, member, oldMember.index), + actionChangeMember(this.issue.entityIds[0], member, oldMember.index), t('operations.change_role.annotation') ); } diff --git a/modules/validations/missing_tag.js b/modules/validations/missing_tag.js index a498f7ec6..67b456f90 100644 --- a/modules/validations/missing_tag.js +++ b/modules/validations/missing_tag.js @@ -92,7 +92,7 @@ export function validationMissingTag() { icon: 'iD-operation-delete', title: t('issues.fix.delete_feature.title'), onClick: function() { - var id = this.issue.entities[0].id; + var id = this.issue.entityIds[0]; var operation = operationDelete([id], context); if (!operation.disabled()) { operation(); @@ -113,7 +113,7 @@ export function validationMissingTag() { severity: severity, message: t('issues.' + messageID + '.message', messageObj), reference: showReference, - entities: [entity], + entityIds: [entity.id], fixes: fixes })]; diff --git a/modules/validations/outdated_tags.js b/modules/validations/outdated_tags.js index a17156a79..87d81af33 100644 --- a/modules/validations/outdated_tags.js +++ b/modules/validations/outdated_tags.js @@ -70,7 +70,8 @@ export function validationOutdatedTags() { severity: 'warning', message: t('issues.outdated_tags.message', { feature: utilDisplayLabel(entity, context) }), reference: showReference, - entities: [entity], + entityIds: [entity.id], + hash: JSON.stringify(tagDiff), fixes: [ new validationIssueFix({ autoArgs: [doUpgrade, t('issues.fix.upgrade_tags.annotation')], @@ -143,7 +144,7 @@ export function validationOutdatedTags() { severity: 'warning', message: t('issues.old_multipolygon.message', { multipolygon: multipolygonLabel }), reference: showReference, - entities: [outerWay, multipolygon], + entityIds: [outerWay.id, multipolygon.id], fixes: [ new validationIssueFix({ autoArgs: [doUpgrade, t('issues.fix.move_tags.annotation')], diff --git a/modules/validations/private_data.js b/modules/validations/private_data.js index 53adef44c..d342ec7fa 100644 --- a/modules/validations/private_data.js +++ b/modules/validations/private_data.js @@ -65,7 +65,7 @@ export function validationPrivateData() { feature: utilDisplayLabel(entity, context), }), reference: showReference, - entities: [entity], + entityIds: [entity.id], data: { newTags: keepTags }, @@ -74,7 +74,7 @@ export function validationPrivateData() { icon: 'iD-operation-delete', title: t('issues.fix.' + fixID + '.title'), onClick: function() { - var entityID = this.issue.entities[0].id; + var entityID = this.issue.entityIds[0]; var newTags = this.issue.data.newTags; context.perform( actionChangeTags(entityID, newTags), diff --git a/modules/validations/tag_suggests_area.js b/modules/validations/tag_suggests_area.js index 1a2c380ec..77c051497 100644 --- a/modules/validations/tag_suggests_area.js +++ b/modules/validations/tag_suggests_area.js @@ -43,7 +43,7 @@ export function validationTagSuggestsArea() { // make sure this will not create a self-intersection if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) { connectEndpointsOnClick = function() { - var way = this.issue.entities[0]; + var way = context.entity(this.issue.entityIds[0]); context.perform( actionMergeNodes([way.nodes[0], way.nodes[way.nodes.length-1]], nodes[0].loc), t('issues.fix.connect_endpoints.annotation') @@ -59,11 +59,12 @@ export function validationTagSuggestsArea() { // make sure this will not create a self-intersection if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) { connectEndpointsOnClick = function() { - var way = this.issue.entities[0]; + var wayId = this.issue.entityIds[0]; + var way = context.entity(wayId); var nodeId = way.nodes[0]; var index = way.nodes.length; context.perform( - actionAddVertex(way.id, nodeId, index), + actionAddVertex(wayId, nodeId, index), t('issues.fix.connect_endpoints.annotation') ); }; @@ -80,13 +81,14 @@ export function validationTagSuggestsArea() { icon: 'iD-operation-delete', title: t('issues.fix.remove_tag.title'), onClick: function() { - var entity = this.issue.entities[0]; + var entityId = this.issue.entityIds[0]; + var entity = context.entity(entityId); var tags = Object.assign({}, entity.tags); // shallow copy for (var key in tagSuggestingArea) { delete tags[key]; } context.perform( - actionChangeTags(entity.id, tags), + actionChangeTags(entityId, tags), t('issues.fix.remove_tag.annotation') ); } @@ -98,7 +100,8 @@ export function validationTagSuggestsArea() { severity: 'warning', message: t('issues.tag_suggests_area.message', { feature: featureLabel, tag: tagText }), reference: showReference, - entities: [entity], + entityIds: [entity.id], + hash: JSON.stringify(tagSuggestingArea), fixes: fixes })]; diff --git a/modules/validations/unsquare_way.js b/modules/validations/unsquare_way.js index 324f4f216..07e3b1b8a 100644 --- a/modules/validations/unsquare_way.js +++ b/modules/validations/unsquare_way.js @@ -58,14 +58,14 @@ export function validationUnsquareWay() { context.validator().validate(); }; - return new validationIssue({ + return [new validationIssue({ type: type, severity: 'warning', message: t('issues.unsquare_way.message', { feature: utilDisplayLabel(entity, context) }), reference: showReference, - entities: [entity], + entityIds: [entity.id], fixes: [ new validationIssueFix({ icon: 'iD-operation-orthogonalize', @@ -76,7 +76,7 @@ export function validationUnsquareWay() { } }) ] - }); + })]; function showReference(selection) { selection.selectAll('.issue-reference') diff --git a/test/spec/core/validator.js b/test/spec/core/validator.js index 26b787ed0..2e40b04d1 100644 --- a/test/spec/core/validator.js +++ b/test/spec/core/validator.js @@ -36,8 +36,8 @@ describe('iD.validations.validator', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); }); diff --git a/test/spec/services/maprules.js b/test/spec/services/maprules.js index 36ee8cda4..ec01a2f9b 100644 --- a/test/spec/services/maprules.js +++ b/test/spec/services/maprules.js @@ -561,7 +561,7 @@ describe('maprules', function() { var type = Object.keys(selector).indexOf('error') ? 'error' : 'warning'; expect(issues.length).to.eql(1); - expect(issue.entities).to.eql([entity]); + expect(issue.entityIds).to.eql([entity.id]); expect(issue.message).to.eql(selector[type]); expect(type).to.eql(issue.severity); }); diff --git a/test/spec/validations/almost_junction.js b/test/spec/validations/almost_junction.js index b35342701..df7fb686e 100644 --- a/test/spec/validations/almost_junction.js +++ b/test/spec/validations/almost_junction.js @@ -148,10 +148,10 @@ describe('iD.validations.almost_junction', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('almost_junction'); - expect(issue.entities).to.have.lengthOf(3); - expect(issue.entities[0].id).to.eql('w-1'); - expect(issue.entities[1].id).to.eql('n-1'); - expect(issue.entities[2].id).to.eql('w-2'); + expect(issue.entityIds).to.have.lengthOf(3); + expect(issue.entityIds[0]).to.eql('w-1'); + expect(issue.entityIds[1]).to.eql('n-1'); + expect(issue.entityIds[2]).to.eql('w-2'); expect(issue.loc).to.have.lengthOf(2); expect(issue.loc[0]).to.eql(22.42357); @@ -177,10 +177,10 @@ describe('iD.validations.almost_junction', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('almost_junction'); - expect(issue.entities).to.have.lengthOf(3); - expect(issue.entities[0].id).to.eql('w-1'); - expect(issue.entities[1].id).to.eql('n-1'); - expect(issue.entities[2].id).to.eql('w-2'); + expect(issue.entityIds).to.have.lengthOf(3); + expect(issue.entityIds[0]).to.eql('w-1'); + expect(issue.entityIds[1]).to.eql('n-1'); + expect(issue.entityIds[2]).to.eql('w-2'); expect(issue.loc).to.have.lengthOf(2); expect(issue.loc[0]).to.eql(22.42357); diff --git a/test/spec/validations/crossing_ways.js b/test/spec/validations/crossing_ways.js index 707e8e7f2..972fc54c7 100644 --- a/test/spec/validations/crossing_ways.js +++ b/test/spec/validations/crossing_ways.js @@ -67,7 +67,7 @@ describe('iD.validations.crossing_ways', function () { function verifySingleCrossingIssue(issues) { var issue = issues[0]; expect(issue.type).to.eql('crossing_ways'); - expect(issue.entities).to.have.lengthOf(2); + expect(issue.entityIds).to.have.lengthOf(2); expect(issue.loc).to.have.lengthOf(2); expect(issue.loc[0]).to.eql(1.5); @@ -224,7 +224,7 @@ describe('iD.validations.crossing_ways', function () { expect(issues).to.have.lengthOf(4); var issue = issues[0]; expect(issue.type).to.eql('crossing_ways'); - expect(issue.entities).to.have.lengthOf(2); + expect(issue.entityIds).to.have.lengthOf(2); expect(issue.loc).to.have.lengthOf(2); expect(issue.loc[0]).to.eql(1.5); @@ -232,7 +232,7 @@ describe('iD.validations.crossing_ways', function () { issue = issues[1]; expect(issue.type).to.eql('crossing_ways'); - expect(issue.entities).to.have.lengthOf(2); + expect(issue.entityIds).to.have.lengthOf(2); expect(issue.loc).to.have.lengthOf(2); expect(issue.loc[0]).to.eql(2.5); diff --git a/test/spec/validations/disconnected_way.js b/test/spec/validations/disconnected_way.js index 59735a4da..dd6e9b224 100644 --- a/test/spec/validations/disconnected_way.js +++ b/test/spec/validations/disconnected_way.js @@ -56,8 +56,8 @@ describe('iD.validations.disconnected_way', function () { var issue = issues[0]; expect(issue.type).to.eql('disconnected_way'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags highway connected only to service area', function() { @@ -67,8 +67,8 @@ describe('iD.validations.disconnected_way', function () { var issue = issues[0]; expect(issue.type).to.eql('disconnected_way'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags disconnected highway with disconnected entrance vertex', function() { @@ -87,8 +87,8 @@ describe('iD.validations.disconnected_way', function () { var issue = issues[0]; expect(issue.type).to.eql('disconnected_way'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('ignores highways that are connected', function() { diff --git a/test/spec/validations/generic_name.js b/test/spec/validations/generic_name.js index 5d6d7e874..337c239cc 100644 --- a/test/spec/validations/generic_name.js +++ b/test/spec/validations/generic_name.js @@ -65,8 +65,8 @@ describe('iD.validations.generic_name', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('generic_name'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags feature with a name that is just a defining tag key', function() { @@ -75,8 +75,8 @@ describe('iD.validations.generic_name', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('generic_name'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags feature with a name that is just a defining tag value', function() { @@ -85,8 +85,8 @@ describe('iD.validations.generic_name', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('generic_name'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); }); diff --git a/test/spec/validations/incompatible_source.js b/test/spec/validations/incompatible_source.js index f8a3e2d90..600f91403 100644 --- a/test/spec/validations/incompatible_source.js +++ b/test/spec/validations/incompatible_source.js @@ -53,8 +53,8 @@ describe('iD.validations.incompatible_source', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('incompatible_source'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); }); diff --git a/test/spec/validations/missing_role.js b/test/spec/validations/missing_role.js index 0ed6d43b6..77a79e463 100644 --- a/test/spec/validations/missing_role.js +++ b/test/spec/validations/missing_role.js @@ -80,9 +80,9 @@ describe('iD.validations.missing_role', function () { expect(issues[0].id).to.eql(issues[1].id); var issue = issues[0]; expect(issue.type).to.eql('missing_role'); - expect(issue.entities).to.have.lengthOf(2); - expect(issue.entities[0].id).to.eql('r-1'); - expect(issue.entities[1].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(2); + expect(issue.entityIds[0]).to.eql('r-1'); + expect(issue.entityIds[1]).to.eql('w-1'); }); it('flags way with whitespace string role in multipolygon', function() { @@ -92,9 +92,9 @@ describe('iD.validations.missing_role', function () { expect(issues[0].id).to.eql(issues[1].id); var issue = issues[0]; expect(issue.type).to.eql('missing_role'); - expect(issue.entities).to.have.lengthOf(2); - expect(issue.entities[0].id).to.eql('r-1'); - expect(issue.entities[1].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(2); + expect(issue.entityIds[0]).to.eql('r-1'); + expect(issue.entityIds[1]).to.eql('w-1'); }); }); diff --git a/test/spec/validations/missing_tag.js b/test/spec/validations/missing_tag.js index 42dbb63a2..e25ec29e0 100644 --- a/test/spec/validations/missing_tag.js +++ b/test/spec/validations/missing_tag.js @@ -68,8 +68,8 @@ describe('iD.validations.missing_tag', function () { var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); expect(issue.subtype).to.eql('any'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags no descriptive tags', function() { @@ -79,8 +79,8 @@ describe('iD.validations.missing_tag', function () { var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); expect(issue.subtype).to.eql('descriptive'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags no descriptive tags on multipolygon', function() { @@ -90,8 +90,8 @@ describe('iD.validations.missing_tag', function () { var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); expect(issue.subtype).to.eql('descriptive'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('r-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('r-1'); }); it('flags no type tag on relation', function() { @@ -101,8 +101,8 @@ describe('iD.validations.missing_tag', function () { var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); expect(issue.subtype).to.eql('relation_type'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('r-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('r-1'); }); it('ignores highway with classification', function() { @@ -118,8 +118,8 @@ describe('iD.validations.missing_tag', function () { var issue = issues[0]; expect(issue.type).to.eql('missing_tag'); expect(issue.subtype).to.eql('highway_classification'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); }); diff --git a/test/spec/validations/outdated_tags.js b/test/spec/validations/outdated_tags.js index ef387f683..5c61746c8 100644 --- a/test/spec/validations/outdated_tags.js +++ b/test/spec/validations/outdated_tags.js @@ -63,8 +63,8 @@ describe('iD.validations.outdated_tags', function () { expect(issue.type).to.eql('outdated_tags'); expect(issue.subtype).to.eql('deprecated_tags'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); @@ -87,9 +87,9 @@ describe('iD.validations.outdated_tags', function () { var issue = issues[0]; expect(issue.type).to.eql('outdated_tags'); expect(issue.subtype).to.eql('old_multipolygon'); - expect(issue.entities).to.have.lengthOf(2); - expect(issue.entities[0].id).to.eql('w-1'); - expect(issue.entities[1].id).to.eql('r-1'); + expect(issue.entityIds).to.have.lengthOf(2); + expect(issue.entityIds[0]).to.eql('w-1'); + expect(issue.entityIds[1]).to.eql('r-1'); }); }); diff --git a/test/spec/validations/private_data.js b/test/spec/validations/private_data.js index 065575788..a927fc68a 100644 --- a/test/spec/validations/private_data.js +++ b/test/spec/validations/private_data.js @@ -65,8 +65,8 @@ describe('iD.validations.private_data', function () { expect(issues).to.have.lengthOf(1); var issue = issues[0]; expect(issue.type).to.eql('private_data'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); }); diff --git a/test/spec/validations/tag_suggests_area.js b/test/spec/validations/tag_suggests_area.js index 479aa99b6..20e8cdc48 100644 --- a/test/spec/validations/tag_suggests_area.js +++ b/test/spec/validations/tag_suggests_area.js @@ -88,8 +88,8 @@ describe('iD.validations.tag_suggests_area', function () { var issue = issues[0]; expect(issue.type).to.eql('tag_suggests_area'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); it('flags open way with both area and line tags', function() { @@ -99,8 +99,8 @@ describe('iD.validations.tag_suggests_area', function () { var issue = issues[0]; expect(issue.type).to.eql('tag_suggests_area'); expect(issue.severity).to.eql('warning'); - expect(issue.entities).to.have.lengthOf(1); - expect(issue.entities[0].id).to.eql('w-1'); + expect(issue.entityIds).to.have.lengthOf(1); + expect(issue.entityIds[0]).to.eql('w-1'); }); });