mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-12 16:52:50 +00:00
Update to id-tagging-schema v3.0.0
Add UI for translatable combo fields
This commit is contained in:
@@ -1601,6 +1601,13 @@ a.hide-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-field-input-combo input.raw-value {
|
||||
font-family: monospace;
|
||||
}
|
||||
.form-field-input-combo input.known-value {
|
||||
color: #7092ff;
|
||||
}
|
||||
|
||||
.form-field-input-multicombo ul.chiplist {
|
||||
padding: 5px 8px 5px 8px;
|
||||
background: #fff;
|
||||
@@ -1628,6 +1635,7 @@ a.hide-toggle {
|
||||
background-color: #eff2f7;
|
||||
border: 1px solid #ccd5e3;
|
||||
max-width: 100%;
|
||||
color: #7092ff;
|
||||
}
|
||||
.ideditor[dir='ltr'] .form-field-input-multicombo li.chip {
|
||||
padding: 2px 0px 2px 5px;
|
||||
@@ -1643,6 +1651,10 @@ a.hide-toggle {
|
||||
z-index: 3000;
|
||||
cursor: grabbing;
|
||||
}
|
||||
.form-field-input-multicombo li.chip.raw-value {
|
||||
font-family: monospace;
|
||||
color: #333;
|
||||
}
|
||||
.form-field-input-multicombo li.mixed {
|
||||
border-color: #eff2f7;
|
||||
color: #888;
|
||||
@@ -2226,6 +2238,11 @@ div.combobox {
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
.combobox .combobox-option.raw-option {
|
||||
font-family: monospace;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
/* Field Help
|
||||
------------------------------------------------------- */
|
||||
|
||||
@@ -12,8 +12,8 @@ export function coreFileFetcher() {
|
||||
let _inflight = {};
|
||||
let _fileMap = {
|
||||
'address_formats': 'data/address_formats.min.json',
|
||||
'deprecated': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/deprecated.min.json',
|
||||
'discarded': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/discarded.min.json',
|
||||
'deprecated': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/deprecated.min.json',
|
||||
'discarded': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/discarded.min.json',
|
||||
'imagery': 'data/imagery.min.json',
|
||||
'intro_graph': 'data/intro_graph.min.json',
|
||||
'keepRight': 'data/keepRight.min.json',
|
||||
@@ -23,10 +23,10 @@ export function coreFileFetcher() {
|
||||
'nsi_filters': 'https://cdn.jsdelivr.net/npm/name-suggestion-index@4/dist/filters.min.json',
|
||||
'oci_features': 'https://cdn.jsdelivr.net/npm/osm-community-index@2/dist/features.min.json',
|
||||
'oci_resources': 'https://cdn.jsdelivr.net/npm/osm-community-index@2/dist/resources.min.json',
|
||||
'preset_categories': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/preset_categories.min.json',
|
||||
'preset_defaults': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/preset_defaults.min.json',
|
||||
'preset_fields': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/fields.min.json',
|
||||
'preset_presets': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/presets.min.json',
|
||||
'preset_categories': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_categories.min.json',
|
||||
'preset_defaults': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_defaults.min.json',
|
||||
'preset_fields': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/fields.min.json',
|
||||
'preset_presets': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/presets.min.json',
|
||||
'phone_formats': 'data/phone_formats.min.json',
|
||||
'qa_data': 'data/qa_data.min.json',
|
||||
'shortcuts': 'data/shortcuts.min.json',
|
||||
|
||||
@@ -90,7 +90,7 @@ export function coreLocalizer() {
|
||||
|
||||
const localeDirs = {
|
||||
general: 'locales',
|
||||
tagging: 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/translations'
|
||||
tagging: 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/translations'
|
||||
};
|
||||
|
||||
let fileMap = fileFetcher.fileMap();
|
||||
@@ -338,6 +338,10 @@ export function coreLocalizer() {
|
||||
};
|
||||
};
|
||||
|
||||
localizer.hasTextForStringId = function(stringId) {
|
||||
return !!localizer.tInfo(stringId, { default: 'nothing found'}).locale;
|
||||
};
|
||||
|
||||
// Returns only the localized text, discarding the locale info
|
||||
localizer.t = function(stringId, replacements, locale) {
|
||||
return localizer.tInfo(stringId, replacements, locale).text;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { t } from '../core/localizer';
|
||||
import { localizer, t } from '../core/localizer';
|
||||
import { utilSafeClassName } from '../util/util';
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export function presetField(fieldID, field) {
|
||||
|
||||
_this.t = (scope, options) => t(`_tagging.presets.fields.${fieldID}.${scope}`, options);
|
||||
_this.t.html = (scope, options) => t.html(`_tagging.presets.fields.${fieldID}.${scope}`, options);
|
||||
_this.hasTextForStringId = (scope) => localizer.hasTextForStringId(`_tagging.presets.fields.${fieldID}.${scope}`);
|
||||
|
||||
_this.title = () => _this.overrideLabel || _this.t('label', { 'default': fieldID });
|
||||
_this.label = () => _this.overrideLabel || _this.t.html('label', { 'default': fieldID });
|
||||
|
||||
@@ -380,7 +380,9 @@ export function uiCombobox(context, klass) {
|
||||
// enter/update
|
||||
options.enter()
|
||||
.append('a')
|
||||
.attr('class', 'combobox-option')
|
||||
.attr('class', function(d) {
|
||||
return 'combobox-option ' + (d.klass || '');
|
||||
})
|
||||
.attr('title', function(d) { return d.title; })
|
||||
.html(function(d) { return d.display || d.value; })
|
||||
.on('mouseenter', _mouseEnterHandler)
|
||||
|
||||
@@ -274,7 +274,7 @@ export function uiFieldAddress(field, context) {
|
||||
}
|
||||
if (_countryCode) {
|
||||
var localkey = subfield.id + '!' + _countryCode;
|
||||
var tkey = addrField.strings.placeholders[localkey] ? localkey : subfield.id;
|
||||
var tkey = addrField.hasTextForStringId('placeholders.' + localkey) ? localkey : subfield.id;
|
||||
return addrField.t('placeholders.' + tkey);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ export { uiFieldCheck as uiFieldOnewayCheck };
|
||||
|
||||
export function uiFieldCheck(field, context) {
|
||||
var dispatch = d3_dispatch('change');
|
||||
var options = field.strings && field.strings.options;
|
||||
var options = field.options;
|
||||
var values = [];
|
||||
var texts = [];
|
||||
|
||||
@@ -33,9 +33,10 @@ export function uiFieldCheck(field, context) {
|
||||
|
||||
|
||||
if (options) {
|
||||
for (var k in options) {
|
||||
values.push(k === 'undefined' ? undefined : k);
|
||||
texts.push(field.t.html('options.' + k, { 'default': options[k] }));
|
||||
for (var i in options) {
|
||||
var v = options[i];
|
||||
values.push(v === 'undefined' ? undefined : v);
|
||||
texts.push(field.t.html('options.' + v, { 'default': v }));
|
||||
}
|
||||
} else {
|
||||
values = [undefined, 'yes'];
|
||||
|
||||
@@ -24,8 +24,9 @@ export function uiFieldCombo(field, context) {
|
||||
var _isMulti = (field.type === 'multiCombo' || field.type === 'manyCombo');
|
||||
var _isNetwork = (field.type === 'networkCombo');
|
||||
var _isSemi = (field.type === 'semiCombo');
|
||||
var _optstrings = field.strings && field.strings.options;
|
||||
var _optarray = field.options;
|
||||
var _showTagInfoSuggestions = field.type !== 'manyCombo' && field.autoSuggestions !== false;
|
||||
var _allowCustomValues = field.type !== 'manyCombo' && field.customValues !== false;
|
||||
var _snake_case = (field.snake_case || (field.snake_case === undefined));
|
||||
var _combobox = uiCombobox(context, 'combo-' + field.safeid)
|
||||
.caseSensitive(field.caseSensitive)
|
||||
@@ -57,10 +58,6 @@ export function uiFieldCombo(field, context) {
|
||||
return s.replace(/\s+/g, '_');
|
||||
}
|
||||
|
||||
function unsnake(s) {
|
||||
return s.replace(/_+/g, ' ');
|
||||
}
|
||||
|
||||
function clean(s) {
|
||||
return s.split(';')
|
||||
.map(function(s) { return s.trim(); })
|
||||
@@ -73,14 +70,10 @@ export function uiFieldCombo(field, context) {
|
||||
function tagValue(dval) {
|
||||
dval = clean(dval || '');
|
||||
|
||||
if (_optstrings) {
|
||||
var found = _comboData.find(function(o) {
|
||||
return o.key && clean(o.value) === dval;
|
||||
});
|
||||
if (found) {
|
||||
return found.key;
|
||||
}
|
||||
}
|
||||
var found = _comboData.find(function(o) {
|
||||
return o.key && clean(o.value) === dval;
|
||||
});
|
||||
if (found) return found.key;
|
||||
|
||||
if (field.type === 'typeCombo' && !dval) {
|
||||
return 'yes';
|
||||
@@ -95,20 +88,15 @@ export function uiFieldCombo(field, context) {
|
||||
function displayValue(tval) {
|
||||
tval = tval || '';
|
||||
|
||||
if (_optstrings) {
|
||||
var found = _comboData.find(function(o) {
|
||||
return o.key === tval && o.value;
|
||||
});
|
||||
if (found) {
|
||||
return found.value;
|
||||
}
|
||||
if (field.hasTextForStringId('options.' + tval)) {
|
||||
return field.t('options.' + tval, { default: tval });
|
||||
}
|
||||
|
||||
if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return _snake_case ? unsnake(tval) : tval;
|
||||
return tval;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,46 +115,33 @@ export function uiFieldCombo(field, context) {
|
||||
|
||||
|
||||
function initCombo(selection, attachTo) {
|
||||
if (_optstrings) {
|
||||
if (!_allowCustomValues) {
|
||||
selection.attr('readonly', 'readonly');
|
||||
selection.call(_combobox, attachTo);
|
||||
setStaticValues(setPlaceholder);
|
||||
}
|
||||
|
||||
} else if (_optarray) {
|
||||
selection.call(_combobox, attachTo);
|
||||
setStaticValues(setPlaceholder);
|
||||
|
||||
} else if (services.taginfo) {
|
||||
if (_showTagInfoSuggestions && services.taginfo) {
|
||||
selection.call(_combobox.fetcher(setTaginfoValues), attachTo);
|
||||
setTaginfoValues('', setPlaceholder);
|
||||
|
||||
} else {
|
||||
selection.call(_combobox, attachTo);
|
||||
setStaticValues(setPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setStaticValues(callback) {
|
||||
if (!(_optstrings || _optarray)) return;
|
||||
if (!_optarray) return;
|
||||
|
||||
if (_optstrings) {
|
||||
_comboData = Object.keys(_optstrings).map(function(k) {
|
||||
var v = field.t('options.' + k, { 'default': _optstrings[k] });
|
||||
return {
|
||||
key: k,
|
||||
value: v,
|
||||
title: v,
|
||||
display: field.t.html('options.' + k, { 'default': _optstrings[k] })
|
||||
};
|
||||
});
|
||||
|
||||
} else if (_optarray) {
|
||||
_comboData = _optarray.map(function(k) {
|
||||
var v = _snake_case ? unsnake(k) : k;
|
||||
return {
|
||||
key: k,
|
||||
value: v,
|
||||
title: v
|
||||
};
|
||||
});
|
||||
}
|
||||
_comboData = _optarray.map(function(v) {
|
||||
return {
|
||||
key: v,
|
||||
value: field.t('options.' + v, { default: v }),
|
||||
title: v,
|
||||
display: field.t.html('options.' + v, { default: v }),
|
||||
klass: field.hasTextForStringId('options.' + v) ? '' : 'raw-option'
|
||||
};
|
||||
});
|
||||
|
||||
_combobox.data(objectDifference(_comboData, _multiData));
|
||||
if (callback) callback(_comboData);
|
||||
@@ -225,11 +200,13 @@ export function uiFieldCombo(field, context) {
|
||||
_comboData = data.map(function(d) {
|
||||
var k = d.value;
|
||||
if (_isMulti) k = k.replace(field.key, '');
|
||||
var v = _snake_case ? unsnake(k) : k;
|
||||
var label = field.t('options.' + k, { default: k });
|
||||
return {
|
||||
key: k,
|
||||
value: v,
|
||||
title: _isMulti ? v : d.title
|
||||
value: label,
|
||||
display: field.t.html('options.' + k, { default: k }),
|
||||
title: d.title || label,
|
||||
klass: field.hasTextForStringId('options.' + k) ? '' : 'raw-option'
|
||||
};
|
||||
});
|
||||
|
||||
@@ -507,9 +484,9 @@ export function uiFieldCombo(field, context) {
|
||||
_combobox.data(available);
|
||||
|
||||
// Hide 'Add' button if this field uses fixed set of
|
||||
// translateable _optstrings and they're all currently used,
|
||||
// options and they're all currently used,
|
||||
// or if the field is already at its character limit
|
||||
var hideAdd = (_optstrings && !available.length) || maxLength <= 0;
|
||||
var hideAdd = (!_allowCustomValues && !available.length) || maxLength <= 0;
|
||||
_container.selectAll('.chiplist .input-wrap')
|
||||
.style('display', hideAdd ? 'none' : null);
|
||||
|
||||
@@ -530,6 +507,11 @@ export function uiFieldCombo(field, context) {
|
||||
|
||||
chips = chips.merge(enter)
|
||||
.order()
|
||||
.classed('raw-value', function(d) {
|
||||
var k = d.key;
|
||||
if (_isMulti) k = k.replace(field.key, '');
|
||||
return !field.hasTextForStringId('options.' + k);
|
||||
})
|
||||
.classed('draggable', allowDragAndDrop)
|
||||
.classed('mixed', function(d) {
|
||||
return d.isMixed;
|
||||
@@ -558,7 +540,14 @@ export function uiFieldCombo(field, context) {
|
||||
return displayValue(val);
|
||||
}).filter(Boolean);
|
||||
|
||||
var showsValue = !isMixed && tags[field.key] && !(field.type === 'typeCombo' && tags[field.key] === 'yes');
|
||||
var isRawValue = showsValue && !field.hasTextForStringId('options.' + tags[field.key]);
|
||||
var isKnownValue = showsValue && !isRawValue;
|
||||
|
||||
utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : '')
|
||||
.classed('raw-value', isRawValue)
|
||||
.classed('known-value', isKnownValue)
|
||||
.attr('readonly', (!_allowCustomValues || isKnownValue) ? 'readonly' : undefined)
|
||||
.attr('title', isMixed ? mixedValues.join('\n') : undefined)
|
||||
.attr('placeholder', isMixed ? t('inspector.multiple_values') : _staticPlaceholder || '')
|
||||
.classed('mixed', isMixed);
|
||||
|
||||
@@ -115,7 +115,7 @@ export function uiFieldCycleway(field, context) {
|
||||
|
||||
|
||||
cycleway.options = function() {
|
||||
return Object.keys(field.strings.options).map(function(option) {
|
||||
return field.options.map(function(option) {
|
||||
return {
|
||||
title: field.t('options.' + option + '.description'),
|
||||
value: option
|
||||
|
||||
@@ -65,6 +65,7 @@ export var uiFields = {
|
||||
lanes: uiFieldLanes,
|
||||
localized: uiFieldLocalized,
|
||||
roadspeed: uiFieldRoadspeed,
|
||||
roadheight: uiFieldText,
|
||||
manyCombo: uiFieldManyCombo,
|
||||
multiCombo: uiFieldMultiCombo,
|
||||
networkCombo: uiFieldNetworkCombo,
|
||||
|
||||
@@ -53,7 +53,7 @@ export function uiFieldText(field, context) {
|
||||
|
||||
input = input.enter()
|
||||
.append('input')
|
||||
.attr('type', field.type === 'identifier' ? 'text' : field.type)
|
||||
.attr('type', field.type === 'identifier' || field.type === 'roadheight' ? 'text' : field.type)
|
||||
.attr('id', field.domId)
|
||||
.classed(field.type, true)
|
||||
.call(utilNoAuto)
|
||||
|
||||
@@ -16,7 +16,7 @@ export function uiFieldRadio(field, context) {
|
||||
var wrap = d3_select(null);
|
||||
var labels = d3_select(null);
|
||||
var radios = d3_select(null);
|
||||
var radioData = (field.options || (field.strings && field.strings.options && Object.keys(field.strings.options)) || field.keys).slice(); // shallow copy
|
||||
var radioData = (field.options || field.keys).slice(); // shallow copy
|
||||
var typeField;
|
||||
var layerField;
|
||||
var _oldType = {};
|
||||
|
||||
@@ -89,9 +89,9 @@ function buildData() {
|
||||
minifyJSON('data/territory_languages.json', 'dist/data/territory_languages.min.json'),
|
||||
Promise.all([
|
||||
// Fetch the icons that are needed by the expected tagging schema version
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/presets.min.json'),
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/preset_categories.min.json'),
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@2/dist/fields.min.json'),
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/presets.min.json'),
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_categories.min.json'),
|
||||
fetch('https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/fields.min.json'),
|
||||
// WARNING: we fetch the bleeding edge data too to make sure we're always hosting the
|
||||
// latest icons, but note that the format could break at any time
|
||||
fetch('https://raw.githubusercontent.com/openstreetmap/id-tagging-schema/main/dist/presets.min.json'),
|
||||
|
||||
Reference in New Issue
Block a user