Add a validator fix option to tag as not: a matched item

(re: #6577)
This commit is contained in:
Bryan Housel
2021-08-06 10:58:59 -04:00
parent c8aedcbb79
commit 52e8555a8f
4 changed files with 57 additions and 12 deletions

View File

@@ -1941,6 +1941,9 @@ en:
tag_as_disconnected:
title: Tag as disconnected
annotation: Tagged very close features as disconnected.
tag_as_not:
title: "Tag as <strong>not:</strong> {name}"
annotation: "Added not: tag"
tag_as_unsquare:
title: Tag as physically unsquare
annotation: Tagged a way as having unsquare corners.

File diff suppressed because one or more lines are too long

View File

@@ -393,7 +393,11 @@ function gatherTuples(tryKVs, tryNames) {
// `tags`: `Object` containing the feature's OSM tags
// `loc`: Location where this feature exists, as a [lon, lat]
// Returns
// `Object`: The tags the the feature should have, or `null` if no changes needed
// `Object` containing the result, or `null` if no changes needed:
// {
// 'newTags': `Object` - The tags the the feature should have
// 'matched': `Object` - The matched item
// }
//
function _upgradeTags(tags, loc) {
let newTags = Object.assign({}, tags); // shallow copy
@@ -430,7 +434,9 @@ function _upgradeTags(tags, loc) {
// Gather key/value tag pairs to try to match
const tryKVs = gatherKVs(tags);
if (!tryKVs.primary.size && !tryKVs.alternate.size) return changed ? newTags : null;
if (!tryKVs.primary.size && !tryKVs.alternate.size) {
return changed ? { newTags: newTags, matched: null } : null;
}
// Gather namelike tag values to try to match
const tryNames = gatherNames(tags);
@@ -440,7 +446,9 @@ function _upgradeTags(tags, loc) {
const foundQID = _nsi.qids.get(tags.wikidata) || _nsi.qids.get(tags.wikipedia);
if (foundQID) tryNames.primary.add(foundQID); // matcher will recognize the Wikidata QID as name too
if (!tryNames.primary.size && !tryNames.alternate.size) return changed ? newTags : null;
if (!tryNames.primary.size && !tryNames.alternate.size) {
return changed ? { newTags: newTags, matched: null } : null;
}
// Order the [key,value,name] tuples - test primary before alternate
const tuples = gatherTuples(tryKVs, tryNames);
@@ -481,6 +489,7 @@ function _upgradeTags(tags, loc) {
if (!item) continue;
// At this point we have matched a canonical item and can suggest tag upgrades..
item = JSON.parse(JSON.stringify(item)); // deep copy
const tkv = item.tkv;
const parts = tkv.split('/', 3); // tkv = "tree/key/value"
const k = parts[1];
@@ -565,10 +574,10 @@ function _upgradeTags(tags, loc) {
}
}
return newTags;
return { newTags: newTags, matched: item };
}
return changed ? newTags : null;
return changed ? { newTags: newTags, matched: null } : null;
}
@@ -668,7 +677,11 @@ export default {
// `tags`: `Object` containing the feature's OSM tags
// `loc`: Location where this feature exists, as a [lon, lat]
// Returns
// `Object`: The tags the the feature should have, or `null` if no change
// `Object` containing the result, or `null` if no changes needed:
// {
// 'newTags': `Object` - The tags the the feature should have
// 'matched': `Object` - The matched item
// }
//
upgradeTags: (tags, loc) => _upgradeTags(tags, loc),

View File

@@ -66,13 +66,14 @@ export function validationOutdatedTags() {
// Attempt to match a canonical record in the name-suggestion-index.
const nsi = services.nsi;
let waitingForNsi = false;
let nsiResult;
if (nsi) {
waitingForNsi = (nsi.status() === 'loading');
if (!waitingForNsi) {
const loc = entity.extent(graph).center();
const result = nsi.upgradeTags(newTags, loc);
if (result) {
newTags = result;
nsiResult = nsi.upgradeTags(newTags, loc);
if (nsiResult) {
newTags = nsiResult.newTags;
subtype = 'noncanonical_brand';
}
}
@@ -88,7 +89,7 @@ export function validationOutdatedTags() {
const isOnlyAddingTags = tagDiff.every(d => d.type === '+');
let prefix = '';
if (subtype === 'noncanonical_brand') {
if (nsiResult) {
prefix = 'noncanonical_brand.';
} else if (subtype === 'deprecated_tags' && isOnlyAddingTags) {
subtype = 'incomplete_tags';
@@ -107,7 +108,7 @@ export function validationOutdatedTags() {
entityIds: [entity.id],
hash: utilHashcode(JSON.stringify(tagDiff)),
dynamicFixes: () => {
return [
let fixes = [
new validationIssueFix({
autoArgs: autoArgs,
title: t.html('issues.fix.upgrade_tags.title'),
@@ -116,6 +117,19 @@ export function validationOutdatedTags() {
}
})
];
if (nsiResult && nsiResult.matched) {
fixes.push(
new validationIssueFix({
title: t.html('issues.fix.tag_as_not.title', { name: nsiResult.matched.displayName }),
onClick: (context) => {
context.perform(addNotTag, t('issues.fix.tag_as_not.annotation'));
}
})
);
}
return fixes;
}
}));
return issues;
@@ -138,6 +152,21 @@ export function validationOutdatedTags() {
}
function addNotTag(graph) {
const currEntity = graph.hasEntity(entity.id);
if (!currEntity) return graph;
const item = nsiResult && nsiResult.matched;
if (!item) return graph;
let newTags = Object.assign({}, currEntity.tags); // shallow copy
const k = `not:${item.mainTag}`;
newTags[k] = item.tags[item.mainTag];
return actionChangeTags(currEntity.id, newTags)(graph);
}
function showMessage(context) {
const currEntity = context.hasEntity(entity.id);
if (!currEntity) return '';