Add validation warning for generic names

(closes #5590)
This commit is contained in:
Bryan Housel
2019-01-08 02:15:28 -05:00
parent 528cbb29e1
commit 5f20218f1f
13 changed files with 80 additions and 20 deletions
+2
View File
@@ -629,6 +629,8 @@ en:
validations:
disconnected_highway: Disconnected highway
disconnected_highway_tooltip: "Roads should be connected to other roads or building entrances."
generic_name: Possible generic name
generic_name_tooltip: 'This feature seems to have a generic name "{name}". Please only use the name field to record the official name of a feature.'
old_multipolygon: Multipolygon tags on outer way
old_multipolygon_tooltip: "This style of multipolygon is deprecated. Please assign the tags to the parent multipolygon instead of the outer way."
untagged_point: Untagged point
+2 -2
View File
@@ -191,7 +191,7 @@
"amenity/vending_machine/excrement_bags": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "fee", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["excrement bags", "poop", "dog", "animal"], "tags": {"amenity": "vending_machine", "vending": "excrement_bags"}, "reference": {"key": "vending", "value": "excrement_bags"}, "name": "Excrement Bag Vending Machine"},
"amenity/vending_machine/feminine_hygiene": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["condom", "tampon", "pad", "woman", "women", "menstrual hygiene products", "personal care"], "tags": {"amenity": "vending_machine", "vending": "feminine_hygiene"}, "reference": {"key": "vending", "value": "feminine_hygiene"}, "name": "Feminine Hygiene Vending Machine"},
"amenity/vending_machine/food": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["food"], "tags": {"amenity": "vending_machine", "vending": "food"}, "reference": {"key": "vending", "value": "food"}, "name": "Food Vending Machine"},
"amenity/vending_machine/fuel": {"icon": "maki-fuel", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["petrol", "fuel", "gasoline", "propane", "diesel", "lng", "cng", "biodiesel"], "tags": {"amenity": "vending_machine", "vending": "fuel"}, "reference": {"key": "vending", "value": "fuel"}, "name": "Gas Pump"},
"amenity/vending_machine/fuel": {"icon": "maki-fuel", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["petrol", "fuel", "gasoline", "propane", "diesel", "lng", "cng", "biodiesel"], "tags": {"amenity": "vending_machine", "vending": "fuel"}, "reference": {"key": "vending", "value": "fuel"}, "name": "Gas Pump", "matchScore": 0.5},
"amenity/vending_machine/ice_cream": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["chocolate", "ice cream", "frozen", "popsicle", "vanilla"], "tags": {"amenity": "vending_machine", "vending": "ice_cream"}, "reference": {"key": "vending", "value": "ice_cream"}, "name": "Ice Cream Vending Machine"},
"amenity/vending_machine/newspapers": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "fee", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["newspaper"], "tags": {"amenity": "vending_machine", "vending": "newspapers"}, "reference": {"key": "vending", "value": "newspapers"}, "name": "Newspaper Vending Machine"},
"amenity/vending_machine/parcel_pickup_dropoff": {"icon": "temaki-vending_machine", "fields": ["vending", "operator", "payment_multi", "currency_multi"], "geometry": ["point"], "terms": ["mail", "parcel", "pickup"], "tags": {"amenity": "vending_machine", "vending": "parcel_pickup;parcel_mail_in"}, "reference": {"key": "vending", "value": "parcel_pickup;parcel_mail_in"}, "name": "Parcel Pickup/Dropoff Locker"},
@@ -889,7 +889,7 @@
"shop/fishing": {"icon": "maki-shop", "fields": ["name", "operator", "address", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "tags": {"shop": "fishing"}, "name": "Fishing Shop"},
"shop/florist": {"icon": "maki-florist", "fields": ["name", "operator", "address", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "terms": ["flower"], "tags": {"shop": "florist"}, "name": "Florist"},
"shop/frame": {"icon": "maki-shop", "fields": ["name", "operator", "address", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "tags": {"shop": "frame"}, "terms": ["art*", "paint*", "photo*", "frame"], "name": "Framing Shop"},
"shop/fuel": {"icon": "maki-shop", "fields": ["name", "operator", "address", "fuel_multi", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "tags": {"shop": "fuel"}, "name": "Fuel Shop"},
"shop/fuel": {"icon": "maki-shop", "fields": ["name", "operator", "address", "fuel_multi", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "tags": {"shop": "fuel"}, "name": "Fuel Shop", "matchScore": 0.5},
"shop/funeral_directors": {"icon": "maki-cemetery", "fields": ["name", "operator", "address", "building_area", "religion", "denomination"], "geometry": ["point", "area"], "terms": ["undertaker", "memorial home"], "tags": {"shop": "funeral_directors"}, "name": "Funeral Home"},
"shop/furniture": {"icon": "fas-couch", "fields": ["name", "operator", "address", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "terms": ["chair", "sofa", "table"], "tags": {"shop": "furniture"}, "name": "Furniture Store"},
"shop/garden_centre": {"icon": "maki-garden-centre", "fields": ["name", "operator", "address", "building_area", "opening_hours", "payment_multi"], "geometry": ["point", "area"], "terms": ["landscape", "mulch", "shrub", "tree"], "tags": {"shop": "garden_centre"}, "name": "Garden Center"},
@@ -27,5 +27,6 @@
"key": "vending",
"value": "fuel"
},
"name": "Gas Pump"
"name": "Gas Pump",
"matchScore": 0.5
}
+2 -1
View File
@@ -16,5 +16,6 @@
"tags": {
"shop": "fuel"
},
"name": "Fuel Shop"
"name": "Fuel Shop",
"matchScore": 0.5
}
+2
View File
@@ -767,6 +767,8 @@
"validations": {
"disconnected_highway": "Disconnected highway",
"disconnected_highway_tooltip": "Roads should be connected to other roads or building entrances.",
"generic_name": "Possible generic name",
"generic_name_tooltip": "This feature seems to have a generic name \"{name}\". Please only use the name field to record the official name of a feature.",
"old_multipolygon": "Multipolygon tags on outer way",
"old_multipolygon_tooltip": "This style of multipolygon is deprecated. Please assign the tags to the parent multipolygon instead of the outer way.",
"untagged_point": "Untagged point",
+4 -1
View File
@@ -25,7 +25,10 @@ export function uiCommitWarnings(context) {
}, {});
_forEach(validations, function(instances, type) {
instances = _uniqBy(instances, function(val) { return val.id + '_' + val.message.replace(/\s+/g,''); });
instances = _uniqBy(instances, function(val) {
return val.entity || (val.id + '_' + val.message.replace(/\s+/g,''));
});
var section = type + '-section';
var instanceItem = type + '-item';
+2 -2
View File
@@ -9,8 +9,8 @@ export function validationDeprecatedTag() {
var validation = function(changes) {
var warnings = [];
for (var i = 0; i < changes.created.length; i++) {
var change = changes.created[i],
deprecatedTags = change.deprecatedTags();
var change = changes.created[i];
var deprecatedTags = change.deprecatedTags();
if (!_isEmpty(deprecatedTags)) {
var tags = utilTagText({ tags: deprecatedTags });
+47
View File
@@ -0,0 +1,47 @@
import { t } from '../util/locale';
import { discardNames } from '../../node_modules/name-suggestion-index/config/filters.json';
export function validationGenericName() {
function isGenericName(entity) {
var name = entity.tags.name;
if (!name) return false;
if (entity.tags.amenity === name ||
entity.tags.leisure === name ||
entity.tags.shop === name ||
entity.tags.man_made === name ||
entity.tags.tourism === name) {
return name;
}
for (var i = 0; i < discardNames.length; i++) {
var re = new RegExp(discardNames[i], 'i');
if (re.test(name)) {
return name;
}
}
return false;
}
return function validation(changes) {
var warnings = [];
for (var i = 0; i < changes.created.length; i++) {
var change = changes.created[i];
var generic = isGenericName(change);
if (generic) {
warnings.push({
id: 'generic_name',
message: t('validations.generic_name'),
tooltip: t('validations.generic_name_tooltip', { name: generic }),
entity: change
});
}
}
return warnings;
};
}
+1
View File
@@ -1,5 +1,6 @@
export { validationDeprecatedTag } from './deprecated_tag';
export { validationDisconnectedHighway } from './disconnected_highway';
export { validationGenericName } from './generic_name.js';
export { validationManyDeletions } from './many_deletions';
export { validationMapCSSChecks } from './mapcss_checks';
export { validationMissingTag } from './missing_tag';
+7 -6
View File
@@ -6,19 +6,20 @@ export function validationManyDeletions() {
var validation = function(changes, graph) {
var warnings = [];
var nodes=0, ways=0, areas=0, relations=0;
var nodes = 0, ways = 0, areas = 0, relations = 0;
changes.deleted.forEach(function(c) {
if (c.type === 'node') {nodes++;}
else if (c.type === 'way' && c.geometry(graph) === 'line') {ways++;}
else if (c.type === 'way' && c.geometry(graph) === 'area') {areas++;}
else if (c.type === 'relation') {relations++;}
if (c.type === 'node') { nodes++; }
else if (c.type === 'way' && c.geometry(graph) === 'line') { ways++; }
else if (c.type === 'way' && c.geometry(graph) === 'area') { areas++; }
else if (c.type === 'relation') { relations++; }
});
if (changes.deleted.length > threshold) {
warnings.push({
id: 'many_deletions',
message: t('validations.many_deletions',
{ n: changes.deleted.length, p: nodes, l: ways, a:areas, r: relations })
{ n: changes.deleted.length, p: nodes, l: ways, a:areas, r: relations }
)
});
}
+2
View File
@@ -21,5 +21,7 @@ export function validationMapCSSChecks() {
return warnings;
};
return validation;
}
+4 -4
View File
@@ -11,12 +11,12 @@ export function validationMissingTag() {
}
var validation = function(changes, graph) {
var types = ['point', 'line', 'area', 'relation'],
warnings = [];
var types = ['point', 'line', 'area', 'relation'];
var warnings = [];
for (var i = 0; i < changes.created.length; i++) {
var change = changes.created[i],
geometry = change.geometry(graph);
var change = changes.created[i];
var geometry = change.geometry(graph);
if (types.indexOf(geometry) !== -1 && !hasTags(change, graph)) {
warnings.push({
+3 -3
View File
@@ -27,9 +27,9 @@ export function validationTagSuggestsArea() {
var validation = function(changes, graph) {
var warnings = [];
for (var i = 0; i < changes.created.length; i++) {
var change = changes.created[i],
geometry = change.geometry(graph),
suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
var change = changes.created[i];
var geometry = change.geometry(graph);
var suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
if (suggestion) {
warnings.push({