Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions modules/presets/field.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { localizer, t } from '../core/localizer';
import { utilSafeClassName } from '../util/util';
import { utilResolveReference, utilSafeClassName } from '../util/util';


//
// `presetField` decorates a given `field` Object
// with some extra methods for searching and matching geometry
//
export function presetField(fieldID, field, allFields) {
export function presetField(fieldID, field, allFields, allPresets) {
allFields = allFields || {};
allPresets = allPresets || {};

const references = { fields: allFields, presets: allPresets };

let _this = Object.assign({}, field); // shallow copy

_this.id = fieldID;
Expand Down Expand Up @@ -53,5 +57,24 @@ export function presetField(fieldID, field, allFields) {

_this.increment = _this.type === 'number' ? (_this.increment || 1) : undefined;

/** @param {boolean} [allOptions] - see https://github.com/openstreetmap/id/commit/a35653 */
_this.options = (allOptions) => {
const referencedField = _this.resolveReference('stringsCrossReference');
let options = field.options || [];
if (referencedField !== _this) {
if (allOptions) {
options.push(...referencedField.options());
} else {
options = referencedField.options();
}
}

return options.map(option => {
const reference = utilResolveReference(option, references);
if (reference) return reference.label;
return option;
});
};

return _this;
}
2 changes: 1 addition & 1 deletion modules/presets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function presetIndex() {
let f = d.fields[fieldID];

if (f) { // add or replace
f = presetField(fieldID, f, _fields);
f = presetField(fieldID, f, _fields, _presets);
if (f.locationSet) newLocationSets.push(f);
_fields[fieldID] = f;

Expand Down
5 changes: 1 addition & 4 deletions modules/ui/fields/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export { uiFieldCheck as uiFieldOnewayCheck };

export function uiFieldCheck(field, context) {
var dispatch = d3_dispatch('change');
var options = field.options;
var options = field.options();
var values = [];
var texts = [];

Expand All @@ -34,9 +34,6 @@ export function uiFieldCheck(field, context) {


var stringsField = field.resolveReference('stringsCrossReference');
if (!options && stringsField.options) {
options = stringsField.options;
}

if (options) {
for (var i in options) {
Expand Down
10 changes: 2 additions & 8 deletions modules/ui/fields/combo.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,8 @@ export function uiFieldCombo(field, context) {

function getOptions(allOptions) {
var stringsField = field.resolveReference('stringsCrossReference');
if (!(field.options || stringsField.options)) return [];
const options = field.options(allOptions);

let options;
if (allOptions !== true) {
options = field.options || stringsField.options;
} else {
options = [].concat(field.options, stringsField.options).filter(Boolean);
}
const result = options.map(function(v) {
const labelId = getLabelId(stringsField, v);
return {
Expand Down Expand Up @@ -272,7 +266,7 @@ export function uiFieldCombo(field, context) {
d.value.toLowerCase().indexOf(_countryCode + ':') === 0);
}

const additionalOptions = (field.options || stringsField.options || [])
const additionalOptions = (field.options() || stringsField.options() || [])
.filter(v => !data.some(dv => dv.value === (_isMulti ? field.key + v : v)))
.map(v => ({ value: v }));

Expand Down
4 changes: 2 additions & 2 deletions modules/ui/fields/radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function uiFieldRadio(field, context) {
var labels = d3_select(null);
var radios = d3_select(null);
var strings = field.resolveReference('stringsCrossReference');
var radioData = (field.options || strings.options || field.keys).slice(); // shallow copy
var radioData = (field.options() || strings.options() || field.keys).slice(); // shallow copy
var typeField;
var layerField;
var _oldType = {};
Expand Down Expand Up @@ -279,7 +279,7 @@ export function uiFieldRadio(field, context) {

radios.property('checked', function(d) {
return isOptionChecked(d) &&
(field.key || field.options.filter(isOptionChecked).length === 1);
(field.key || field.options().filter(isOptionChecked).length === 1);
});

labels
Expand Down
1 change: 1 addition & 0 deletions modules/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export { utilPrefixCSSProperty } from './util';
export { utilPrefixDOMProperty } from './util';
export { utilQsString } from './util';
export { utilRebind } from './rebind';
export { utilResolveReference } from './util';
export { utilSafeClassName } from './util';
export { utilSetTransform } from './util';
export { utilSessionMutex } from './session_mutex';
Expand Down
23 changes: 23 additions & 0 deletions modules/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,3 +692,26 @@ export function utilCleanOsmString(val, maxChars) {
// trim to the number of allowed characters
return utilUnicodeCharsTruncated(val, maxChars);
}

/**
* For cross-referenced strings from id-tagging-schema:
* If the `string` contains an expression like `{group/x/y/z}`, it will
* return `allItems['group']['x/y/z']`
* @template T
* @param {string} path
* @param {{ [group: string]: { [key: string]: T } } | undefined} allItems
* @returns {T | undefined}
*/
export function utilResolveReference(path, allItems) {
const match = path.match(/^\{(.*)\}$/);
if (match) {
const [group, ...remainder] = match[1].split('/');
const value = allItems?.[group]?.[remainder.join('/')];

if (value) {
return value;
}
console.error(`Unable to resolve referenced field: ${match[1]}`); // eslint-disable-line no-console
}
return undefined;
}
18 changes: 18 additions & 0 deletions test/spec/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,22 @@ describe('iD.util', function() {
expect(iD.utilOldestID(['z', 'a', 'A', 'Z'])).to.eql('z');
});
});

describe('utilResolveReference', () => {
const allItems = {
group1: { 'a/b': 1 },
group2: { 'x': 2 },
};
it.each`
path | result
${'{group1/a/b}'} | ${1}
${'{group2/x}'} | ${2}
${'{group2/invalid}'} | ${undefined}
${'{invalid/invalid}'} | ${undefined}
${'{}'} | ${undefined}
${''} | ${undefined}
`('resolves $path to $result', ({ path, result }) => {
expect(iD.utilResolveReference(path, allItems)).toBe(result);
});
});
});