Move locking code from input and localized up to uiField

Also adjust styles some more for wikidata tagged items
This commit is contained in:
Bryan Housel
2019-05-20 17:50:50 -04:00
parent 06bdfbfb8a
commit 69a25fd6aa
5 changed files with 70 additions and 87 deletions
+5 -3
View File
@@ -1557,11 +1557,13 @@ button.preset-favorite-button.active .icon {
}
.field-label .modified-icon,
.field-label .remove-icon {
.field-label .remove-icon,
.field-label .remove-icon-multilingual {
display: none;
}
.modified .field-label .modified-icon,
.present .field-label .remove-icon {
.modified:not(.locked) .field-label .modified-icon,
.present:not(.locked) .field-label .remove-icon,
.present:not(.locked) .field-label .remove-icon-multilingual {
display: inline-block;
}
+44 -7
View File
@@ -4,6 +4,7 @@ import { event as d3_event, select as d3_select } from 'd3-selection';
import { t } from '../util/locale';
import { textDirection } from '../util/locale';
import { svgIcon } from '../svg/icon';
import { tooltip } from '../util/tooltip';
import { uiFieldHelp } from './field_help';
import { uiFields } from './fields';
import { uiTagReference } from './tag_reference';
@@ -25,6 +26,12 @@ export function uiField(context, presetField, entity, options) {
var _state = '';
var _tags = {};
var _locked = false;
var _lockedTip = tooltip()
.title(t('inspector.lock.suggestion', { label: field.label }))
.placement('bottom');
field.keys = field.keys || [field.key];
// only create the fields that are actually being shown
@@ -77,7 +84,7 @@ export function uiField(context, presetField, entity, options) {
function revert(d) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (!entity) return false;
if (!entity || _locked) return;
var original = context.graph().base().entities[entity.id];
var t = {};
@@ -92,6 +99,7 @@ export function uiField(context, presetField, entity, options) {
function remove(d) {
d3_event.stopPropagation();
d3_event.preventDefault();
if (_locked) return;
var t = {};
d.keys.forEach(function(key) {
@@ -162,9 +170,9 @@ export function uiField(context, presetField, entity, options) {
.on('click', revert);
container
.classed('modified', isModified())
.classed('present', isPresent())
.each(function(d) {
var selection = d3_select(this);
if (!d.impl) {
createField();
}
@@ -189,12 +197,12 @@ export function uiField(context, presetField, entity, options) {
}
}
d3_select(this)
selection
.call(d.impl);
// add field help components
if (help) {
d3_select(this)
selection
.call(help.body)
.select('.field-label')
.call(help.button);
@@ -202,7 +210,7 @@ export function uiField(context, presetField, entity, options) {
// add tag reference components
if (reference) {
d3_select(this)
selection
.call(reference.body)
.select('.field-label')
.call(reference.button);
@@ -210,6 +218,29 @@ export function uiField(context, presetField, entity, options) {
d.impl.tags(_tags);
});
container
.classed('locked', _locked)
.classed('modified', isModified())
.classed('present', isPresent());
// show a tip and lock icon if the field is locked
var annotation = container.selectAll('.field-label .label-textannotation');
var icon = annotation.selectAll('.icon')
.data(_locked ? [0]: []);
icon.exit()
.remove();
icon.enter()
.append('svg')
.attr('class', 'icon')
.append('use')
.attr('xlink:href', '#fas-lock');
container.call(_locked ? _lockedTip : _lockedTip.destroy);
};
@@ -227,6 +258,13 @@ export function uiField(context, presetField, entity, options) {
};
field.locked = function(val) {
if (!arguments.length) return _locked;
_locked = val;
return field;
};
field.show = function() {
_show = true;
if (!field.impl) {
@@ -239,7 +277,6 @@ export function uiField(context, presetField, entity, options) {
}
};
// A shown field has a visible UI, a non-shown field is in the 'Add field' dropdown
field.isShown = function() {
return _show || isPresent();
+4 -37
View File
@@ -21,18 +21,11 @@ export function uiFieldText(field, context) {
var nominatim = services.geocoder;
var input = d3_select(null);
var _entity;
var _brandTip;
if (field.id === 'brand') {
_brandTip = tooltip()
.title(t('inspector.lock.suggestion', { label: field.label }))
.placement('bottom');
}
function i(selection) {
var preset = _entity && context.presets().match(_entity, context.graph());
var isSuggestion = preset && preset.suggestion && field.id === 'brand';
var isLocked = preset && preset.suggestion && field.id === 'brand';
field.locked(isLocked);
var wrap = selection.selectAll('.form-field-input-wrap')
.data([0]);
@@ -57,8 +50,8 @@ export function uiFieldText(field, context) {
.merge(input);
input
.classed('disabled', !!isSuggestion)
.attr('readonly', isSuggestion || null)
.classed('disabled', !!isLocked)
.attr('readonly', isLocked || null)
.on('input', change(true))
.on('blur', change())
.on('change', change());
@@ -99,32 +92,6 @@ export function uiFieldText(field, context) {
input.node().value = vals.join(';');
change()();
});
} else if (preset && field.id === 'brand') {
var pTag = preset.id.split('/', 2);
var pKey = pTag[0];
if (isSuggestion) {
// A "suggestion" preset (brand name)
// Put suggestion keys in `field.keys` so delete button can remove them all.
field.keys = Object.keys(preset.removeTags)
.filter(function(k) { return k !== pKey && k !== 'name'; });
}
selection.call(isSuggestion ? _brandTip : _brandTip.destroy);
// add a label annotation
var annotation = selection.selectAll('.field-label .label-textannotation');
var icon = annotation.selectAll('.icon')
.data(isSuggestion ? [0]: []);
icon.exit()
.remove();
icon.enter()
.append('svg')
.attr('class', 'icon')
.append('use')
.attr('xlink:href', '#fas-lock');
}
}
+16 -40
View File
@@ -32,10 +32,6 @@ export function uiFieldLocalized(field, context) {
var _selection = d3_select(null);
var _multilingual = [];
var _isLocked = false;
var _brandTip = tooltip()
.title(t('inspector.lock.suggestion', { label: field.label }))
.placement('bottom');
var _buttonTip = tooltip()
.title(t('translate.translate'))
.placement('left');
@@ -45,13 +41,13 @@ export function uiFieldLocalized(field, context) {
function calcLocked() {
if (!_entity) { // the original entity
_isLocked = false;
field.locked(false);
return;
}
var latest = context.hasEntity(_entity.id);
if (!latest) { // get current entity, possibly edited
_isLocked = false;
field.locked(false);
return;
}
@@ -62,8 +58,10 @@ export function uiFieldLocalized(field, context) {
var showsBrand = preset && preset.fields
.filter(function(d) { return d.id === 'brand'; }).length;
_isLocked = !!(field.id === 'name' && hasOriginalName &&
var isLocked = !!(field.id === 'name' && hasOriginalName &&
(hasWikidata || (isSuggestion && !showsBrand)));
field.locked(isLocked);
}
@@ -82,6 +80,7 @@ export function uiFieldLocalized(field, context) {
function localized(selection) {
_selection = selection;
calcLocked();
var isLocked = field.locked();
var entity = _entity && context.hasEntity(_entity.id); // get latest
var preset = entity && context.presets().match(entity, context.graph());
@@ -112,13 +111,7 @@ export function uiFieldLocalized(field, context) {
var pKey = pTag[0];
var pValue = pTag[1];
if (preset.suggestion) {
// A "suggestion" preset (brand name)
// Put suggestion keys in `field.keys` so delete button can remove them all.
field.keys = Object.keys(preset.removeTags)
.filter(function(k) { return k !== pKey; });
} else {
if (!preset.suggestion) {
// Not a suggestion preset - Add a suggestions dropdown if it makes sense to.
// This code attempts to determine if the matched preset is the
// kind of preset that even can benefit from name suggestions..
@@ -147,8 +140,8 @@ export function uiFieldLocalized(field, context) {
}
input
.classed('disabled', !!_isLocked)
.attr('readonly', _isLocked || null)
.classed('disabled', !!isLocked)
.attr('readonly', isLocked || null)
.on('input', change(true))
.on('blur', change())
.on('change', change());
@@ -165,8 +158,8 @@ export function uiFieldLocalized(field, context) {
.merge(translateButton);
translateButton
.classed('disabled', !!_isLocked)
.call(_isLocked ? _buttonTip.destroy : _buttonTip)
.classed('disabled', !!isLocked)
.call(isLocked ? _buttonTip.destroy : _buttonTip)
.on('click', addNew);
@@ -186,25 +179,8 @@ export function uiFieldLocalized(field, context) {
.call(renderMultilingual);
localizedInputs.selectAll('button, input')
.classed('disabled', !!_isLocked)
.attr('readonly', _isLocked || null);
_selection.call(_isLocked ? _brandTip : _brandTip.destroy);
// add a label annotations if locked
var annotation = selection.selectAll('.field-label .label-textannotation');
var icon = annotation.selectAll('.icon')
.data(_isLocked ? [0]: []);
icon.exit()
.remove();
icon.enter()
.append('svg')
.attr('class', 'icon')
.append('use')
.attr('xlink:href', '#fas-lock');
.classed('disabled', !!isLocked)
.attr('readonly', isLocked || null);
@@ -308,7 +284,7 @@ export function uiFieldLocalized(field, context) {
function addNew() {
d3_event.preventDefault();
if (_isLocked) return;
if (field.locked()) return;
var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
var langExists = _multilingual.find(function(datum) { return datum.lang === defaultLang; });
@@ -325,7 +301,7 @@ export function uiFieldLocalized(field, context) {
function change(onInput) {
return function() {
if (_isLocked) {
if (field.locked()) {
d3_event.preventDefault();
return;
}
@@ -432,7 +408,7 @@ export function uiFieldLocalized(field, context) {
.append('button')
.attr('class', 'remove-icon-multilingual')
.on('click', function(d){
if (_isLocked) return;
if (field.locked()) return;
d3_event.preventDefault();
var t = {};
t[key(d.lang)] = undefined;
+1
View File
@@ -5,6 +5,7 @@ describe('iD.uiFieldLocalized', function() {
context = iD.coreContext();
selection = d3.select(document.createElement('div'));
field = iD.presetField('name', { key: 'name', type: 'localized' });
field.locked = function() { return false; };
});
it('adds a blank set of fields when the + button is clicked', function() {