mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 23:14:47 +02:00
Rework presets.js file - WIP to fix resolving field inheritance
This commit is contained in:
+97
-100
@@ -8,101 +8,42 @@ import { utilSafeClassName } from '../util/util';
|
||||
// `presetPreset` decorates a given `preset` Object
|
||||
// with some extra methods for searching and matching geometry
|
||||
//
|
||||
export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
export function presetPreset(presetID, preset, allFields, addable, rawPresets) {
|
||||
let _this = Object.assign({}, preset); // shallow copy
|
||||
let _addable = addable || false;
|
||||
|
||||
_this.id = presetID;
|
||||
|
||||
// for use in classes, element ids, css selectors
|
||||
_this.safeid = utilSafeClassName(presetID);
|
||||
_this.safeid = utilSafeClassName(presetID); // for use in css classes, selectors, element ids
|
||||
|
||||
_this.parentPresetID = () => {
|
||||
const endIndex = _this.id.lastIndexOf('/');
|
||||
if (endIndex < 0) return null;
|
||||
return _this.id.substring(0, endIndex);
|
||||
};
|
||||
_this.originalTerms = (_this.terms || []).join();
|
||||
|
||||
_this.originalName = _this.name || '';
|
||||
|
||||
// For a preset without fields, use the fields of the parent _this.
|
||||
// Replace {preset} placeholders with the fields of the specified presets.
|
||||
function resolveFieldInheritance() {
|
||||
_this.originalScore = _this.matchScore || 1;
|
||||
|
||||
// Skip `fields` for the keys which define the _this.
|
||||
// These are usually `typeCombo` fields like `shop=*`
|
||||
function shouldInheritFieldWithID(fieldID) {
|
||||
const f = fields[fieldID];
|
||||
if (f.key) {
|
||||
if (_this.tags[f.key] !== undefined &&
|
||||
// inherit anyway if multiple values are allowed or just a checkbox
|
||||
f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'check'
|
||||
) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
_this.originalReference = _this.reference || {};
|
||||
|
||||
// returns an array of field IDs to inherit from the given presetID, if found
|
||||
function inheritedFieldIDs(presetID, prop) {
|
||||
if (!presetID) return null;
|
||||
_this.fields = (_this.fields || []).map(f => allFields[f]);
|
||||
|
||||
const inheritPreset = rawPresets[presetID];
|
||||
if (!inheritPreset) return null;
|
||||
|
||||
let inheritFieldIDs = inheritPreset[prop] || [];
|
||||
if (prop === 'fields') {
|
||||
inheritFieldIDs = inheritFieldIDs.filter(shouldInheritFieldWithID);
|
||||
}
|
||||
|
||||
return inheritFieldIDs;
|
||||
}
|
||||
|
||||
|
||||
['fields', 'moreFields'].forEach(prop => {
|
||||
let fieldIDs = [];
|
||||
if (preset[prop] && preset[prop].length) { // fields were defined
|
||||
preset[prop].forEach(fieldID => {
|
||||
const match = fieldID.match(/\{(.*)\}/);
|
||||
if (match !== null) { // presetID wrapped in braces {}
|
||||
const inheritIDs = inheritedFieldIDs(match[1], prop);
|
||||
if (inheritIDs !== null) {
|
||||
fieldIDs = fieldIDs.concat(inheritIDs);
|
||||
} else {
|
||||
/* eslint-disable no-console */
|
||||
console.log(`Cannot resolve presetID ${match[0]} found in ${_this.id} ${prop}`);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
} else {
|
||||
fieldIDs.push(fieldID); // no braces - just a normal field
|
||||
}
|
||||
});
|
||||
|
||||
} else { // no fields defined, so use the parent's if possible
|
||||
fieldIDs = inheritedFieldIDs(_this.parentPresetID(), prop);
|
||||
}
|
||||
fieldIDs = utilArrayUniq(fieldIDs);
|
||||
preset[prop] = fieldIDs;
|
||||
rawPresets[_this.id][prop] = fieldIDs;
|
||||
});
|
||||
}
|
||||
_this.moreFields = (_this.moreFields || []).map(f => allFields[f]);
|
||||
|
||||
if (rawPresets) {
|
||||
resolveFieldInheritance();
|
||||
}
|
||||
|
||||
_this.fields = (_this.fields || []).map(getFields);
|
||||
_this.moreFields = (_this.moreFields || []).map(getFields);
|
||||
_this.tags = _this.tags || {};
|
||||
|
||||
_this.addTags = _this.addTags || _this.tags;
|
||||
|
||||
_this.removeTags = _this.removeTags || _this.addTags;
|
||||
|
||||
_this.geometry = (_this.geometry || []);
|
||||
|
||||
function getFields(f) {
|
||||
return fields[f];
|
||||
}
|
||||
|
||||
|
||||
_this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0;
|
||||
|
||||
_this.matchAllGeometry = (geoms) => geoms.every(_this.matchGeometry);
|
||||
|
||||
_this.originalScore = _this.matchScore || 1;
|
||||
|
||||
_this.matchScore = (entityTags) => {
|
||||
const tags = _this.tags;
|
||||
let seen = {};
|
||||
@@ -140,9 +81,6 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
};
|
||||
|
||||
|
||||
_this.originalName = _this.name || '';
|
||||
|
||||
|
||||
_this.name = () => {
|
||||
if (_this.suggestion) {
|
||||
let path = presetID.split('/');
|
||||
@@ -154,27 +92,23 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
};
|
||||
|
||||
|
||||
_this.originalTerms = (_this.terms || []).join();
|
||||
|
||||
_this.terms = () => _this.t('terms', { 'default': _this.originalTerms })
|
||||
.toLowerCase().trim().split(/\s*,+\s*/);
|
||||
|
||||
|
||||
_this.isFallback = () => {
|
||||
const tagCount = Object.keys(_this.tags).length;
|
||||
return tagCount === 0 || (tagCount === 1 && _this.tags.hasOwnProperty('area'));
|
||||
};
|
||||
|
||||
|
||||
addable = addable || false;
|
||||
|
||||
_this.addable = function(val) {
|
||||
if (!arguments.length) return addable;
|
||||
addable = val;
|
||||
return addable;
|
||||
if (!arguments.length) return _addable;
|
||||
_addable = val;
|
||||
return _this;
|
||||
};
|
||||
|
||||
|
||||
const _reference = _this.reference || {};
|
||||
_this.reference = (geom) => {
|
||||
// Lookup documentation on Wikidata...
|
||||
const qid = _this.tags.wikidata || _this.tags['brand:wikidata'] || _this.tags['operator:wikidata'];
|
||||
@@ -183,8 +117,8 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
}
|
||||
|
||||
// Lookup documentation on OSM Wikibase...
|
||||
let key = _reference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
|
||||
let value = _reference.value || _this.tags[key];
|
||||
let key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
|
||||
let value = _this.originalReference.value || _this.tags[key];
|
||||
|
||||
if (geom === 'relation' && key === 'type') {
|
||||
if (value in _this.tags) {
|
||||
@@ -203,16 +137,15 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
};
|
||||
|
||||
|
||||
_this.removeTags = _this.removeTags || _this.addTags || _this.tags || {};
|
||||
|
||||
_this.unsetTags = (tags, geometry) => {
|
||||
_this.unsetTags = (tags, geometry, skipFieldDefaults) => {
|
||||
tags = utilObjectOmit(tags, Object.keys(_this.removeTags));
|
||||
|
||||
for (let f in _this.fields) {
|
||||
const field = _this.fields[f];
|
||||
if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
|
||||
delete tags[field.key];
|
||||
}
|
||||
if (geometry && !skipFieldDefaults) {
|
||||
_this.fields.forEach(field => {
|
||||
if (field.matchGeometry(geometry) && field.key && field.default === tags[field.key]) {
|
||||
delete tags[field.key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
delete tags.area;
|
||||
@@ -220,8 +153,6 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
};
|
||||
|
||||
|
||||
_this.addTags = _this.addTags || _this.tags || {};
|
||||
|
||||
_this.setTags = (tags, geometry, skipFieldDefaults) => {
|
||||
const addTags = _this.addTags;
|
||||
tags = Object.assign({}, tags); // shallow copy
|
||||
@@ -255,18 +186,84 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geometry && !skipFieldDefaults) {
|
||||
for (let f in _this.fields) {
|
||||
const field = _this.fields[f];
|
||||
_this.fields.forEach(field => {
|
||||
if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
|
||||
tags[field.key] = field.default;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return tags;
|
||||
};
|
||||
|
||||
|
||||
// For a preset without fields, use the fields of the parent preset.
|
||||
// Replace {preset} placeholders with the fields of the specified presets.
|
||||
function resolveFieldInheritance() {
|
||||
|
||||
['fields', 'moreFields'].forEach(prop => {
|
||||
let fieldIDs = [];
|
||||
if (preset[prop] && preset[prop].length) { // fields were defined
|
||||
preset[prop].forEach(fieldID => {
|
||||
const match = fieldID.match(/\{(.*)\}/);
|
||||
if (match !== null) { // presetID wrapped in braces {}
|
||||
const inheritIDs = inheritedFieldIDs(match[1], prop);
|
||||
if (inheritIDs !== null) {
|
||||
fieldIDs = fieldIDs.concat(inheritIDs);
|
||||
} else {
|
||||
/* eslint-disable no-console */
|
||||
console.log(`Cannot resolve presetID ${match[0]} found in ${_this.id} ${prop}`);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
} else {
|
||||
fieldIDs.push(fieldID); // no braces - just a normal field
|
||||
}
|
||||
});
|
||||
|
||||
} else { // no fields defined, so use the parent's if possible
|
||||
const endIndex = _this.id.lastIndexOf('/');
|
||||
const parentID = endIndex && _this.id.substring(0, endIndex);
|
||||
if (parentID) {
|
||||
fieldIDs = inheritedFieldIDs(parentID, prop);
|
||||
}
|
||||
}
|
||||
|
||||
fieldIDs = utilArrayUniq(fieldIDs);
|
||||
preset[prop] = fieldIDs;
|
||||
rawPresets[_this.id][prop] = fieldIDs;
|
||||
});
|
||||
|
||||
// Skip `fields` for the keys which define the _this.
|
||||
// These are usually `typeCombo` fields like `shop=*`
|
||||
function shouldInheritFieldWithID(fieldID) {
|
||||
const f = allFields[fieldID];
|
||||
if (f.key) {
|
||||
if (_this.tags[f.key] !== undefined &&
|
||||
// inherit anyway if multiple values are allowed or just a checkbox
|
||||
f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'check'
|
||||
) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns an array of field IDs to inherit from the given presetID, if found
|
||||
function inheritedFieldIDs(presetID, prop) {
|
||||
if (!presetID) return null;
|
||||
|
||||
const inheritPreset = rawPresets[presetID];
|
||||
if (!inheritPreset) return null;
|
||||
|
||||
let inheritFieldIDs = inheritPreset[prop] || [];
|
||||
if (prop === 'fields') {
|
||||
inheritFieldIDs = inheritFieldIDs.filter(shouldInheritFieldWithID);
|
||||
}
|
||||
|
||||
return inheritFieldIDs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user