diff --git a/data/core.yaml b/data/core.yaml index ce0ab7d32d..bce4b03c3f 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -2542,6 +2542,8 @@ en: terms: copyleft, copyright source: label: Source + source_multiple: + label: Source {index} presets: type/chronology: name: Chronology diff --git a/modules/presets/field.js b/modules/presets/field.js index 7f9215a15d..02a1ae0d60 100644 --- a/modules/presets/field.js +++ b/modules/presets/field.js @@ -10,6 +10,12 @@ export function presetField(fieldID, field, allFields) { allFields = allFields || {}; let _this = Object.assign({}, field); // shallow copy + // This handles fields that are composed of a base key and an index, like 'source:1' + let localizerFieldID = fieldID; + if (field.baseKey && field.index){ + localizerFieldID = field.baseKey + '_multiple'; + } + _this.id = fieldID; // for use in classes, element ids, css selectors @@ -21,14 +27,14 @@ export function presetField(fieldID, field, allFields) { return !_this.geometry || geometries.every(geom => _this.geometry.indexOf(geom) !== -1); }; - _this.t = (scope, options) => t(localizer.coalesceStringIds([`custom_presets.fields.${fieldID}.${scope}`, - `_tagging.presets.fields.${fieldID}.${scope}`]), options); - _this.t.html = (scope, options) => t.html(localizer.coalesceStringIds([`custom_presets.fields.${fieldID}.${scope}`, - `_tagging.presets.fields.${fieldID}.${scope}`]), options); - _this.t.append = (scope, options) => t.append(localizer.coalesceStringIds([`custom_presets.fields.${fieldID}.${scope}`, - `_tagging.presets.fields.${fieldID}.${scope}`]), options); - _this.hasTextForStringId = (scope) => localizer.hasTextForStringId(`custom_presets.fields.${fieldID}.${scope}`) || - localizer.hasTextForStringId(`_tagging.presets.fields.${fieldID}.${scope}`); + _this.t = (scope, options) => t(localizer.coalesceStringIds([`custom_presets.fields.${localizerFieldID}.${scope}`, + `_tagging.presets.fields.${localizerFieldID}.${scope}`]), options); + _this.t.html = (scope, options) => t.html(localizer.coalesceStringIds([`custom_presets.fields.${localizerFieldID}.${scope}`, + `_tagging.presets.fields.${localizerFieldID}.${scope}`]), options); + _this.t.append = (scope, options) => t.append(localizer.coalesceStringIds([`custom_presets.fields.${localizerFieldID}.${scope}`, + `_tagging.presets.fields.${localizerFieldID}.${scope}`]), options); + _this.hasTextForStringId = (scope) => localizer.hasTextForStringId(`custom_presets.fields.${localizerFieldID}.${scope}`) || + localizer.hasTextForStringId(`_tagging.presets.fields.${localizerFieldID}.${scope}`); _this.resolveReference = which => { const referenceRegex = /^\{(.*)\}$/; @@ -43,10 +49,10 @@ export function presetField(fieldID, field, allFields) { return _this; }; - _this.title = () => _this.overrideLabel || _this.resolveReference('label').t('label', { 'default': fieldID }); + _this.title = () => _this.overrideLabel || _this.resolveReference('label').t('label', { 'default': fieldID, 'index': field.index }); _this.label = () => _this.overrideLabel ? selection => selection.text(_this.overrideLabel) : - _this.resolveReference('label').t.append('label', { 'default': fieldID }); + _this.resolveReference('label').t.append('label', { 'default': fieldID, 'index': field.index }); _this.placeholder = () => _this.resolveReference('placeholder').t('placeholder', { 'default': '' }); diff --git a/modules/presets/index.js b/modules/presets/index.js index 6462a591b2..7c4689faa9 100644 --- a/modules/presets/index.js +++ b/modules/presets/index.js @@ -60,6 +60,24 @@ function addHistoricalFields(fields) { fields.source.type = 'source'; fields.source.source = false; fields.source.keys = ['source', 'source:url', 'source:name', 'source:date']; + + for (let i = 1; i < 4; i++){ + let id = 'source:' + i.toString(); + let previousId = 'source' + ((i-1) > 0 ? ':' + (i-1).toString() : ''); + fields[id] = { + ...fields.source, + key: id, + keys: [id, id + ':url', id + ':name', id + ':date'], + // baseKey and index will be used to create a localized label for this field + baseKey: 'source', + index: i, + prerequisiteTag: { + keys: [ + previousId, + previousId + ':url', + previousId + ':name', + previousId + ':date']}}; + } } fields.license = { diff --git a/modules/ui/field.js b/modules/ui/field.js index be11fba3c2..c8e821a45f 100644 --- a/modules/ui/field.js +++ b/modules/ui/field.js @@ -216,6 +216,10 @@ export function uiField(context, presetField, entityIDs, options) { referenceKey = referenceKey.replace(/:$/, ''); } + if (d.type === 'source') { // lookup key without the trailing ':' + referenceKey = referenceKey.split(':')[0]; + } + var referenceOptions = d.reference || { key: referenceKey, value: _tags[referenceKey] @@ -350,6 +354,12 @@ export function uiField(context, presetField, entityIDs, options) { if (!entityIDs.every(function(entityID) { var entity = context.graph().entity(entityID); + if (prerequisiteTag.keys) { + // Return true if any key in prerequisiteTag.keys is present, return false otherwise + // If prerequisiteTag.keys is present, prerequisiteTag.key will be ignored + const inEntityTags = (e) => e in entity.tags; + return prerequisiteTag.keys.some(inEntityTags); + } if (prerequisiteTag.key) { var value = entity.tags[prerequisiteTag.key]; if (!value) return false; diff --git a/modules/ui/fields/sources.js b/modules/ui/fields/sources.js index f7e4a77074..0b0988975b 100644 --- a/modules/ui/fields/sources.js +++ b/modules/ui/fields/sources.js @@ -11,7 +11,7 @@ export function uiFieldSources(field, context) { let _selection = d3_select(null); let _pendingChange; - const mainKey = 'source'; + const mainKey = field.key; const sourceHeader = mainKey + ':'; // Pre-selected subkeys to show @@ -130,5 +130,10 @@ export function uiFieldSources(field, context) { _selection.call(sources); }; + sources.focus = function() { + var node = _selection.selectAll('input').node(); + if (node) node.focus(); + }; + return utilRebind(sources, dispatch, 'on'); } diff --git a/modules/ui/sections/preset_fields.js b/modules/ui/sections/preset_fields.js index e39dd8e07c..4cce6cbb77 100644 --- a/modules/ui/sections/preset_fields.js +++ b/modules/ui/sections/preset_fields.js @@ -78,8 +78,17 @@ export function uiSectionPresetFields(context) { } }); + let optionalCoreKeys = ['source:1', 'source:2', 'source:3']; + optionalCoreKeys.forEach(key => { + let field = presetsManager.field(key); + if (field && !_fieldsArr.includes(field)) { + _fieldsArr.push(uiField(context, field, _entityIDs, { show: false })); + } + }); + + sharedFields.forEach(function(field) { - if (!coreKeys.includes(field.id) && field.matchAllGeometry(geometries)) { + if (!coreKeys.includes(field.id) && !optionalCoreKeys.includes(field.id) && field.matchAllGeometry(geometries)) { _fieldsArr.push( uiField(context, field, _entityIDs) ); @@ -101,6 +110,7 @@ export function uiSectionPresetFields(context) { additionalFields.forEach(function(field) { if (sharedFields.indexOf(field) === -1 && !coreKeys.includes(field.id) && + !optionalCoreKeys.includes(field.id) && field.matchAllGeometry(geometries)) { _fieldsArr.push( uiField(context, field, _entityIDs, { show: false })