make sure editing multi selection doesn't corrupt tags

because the common tag vs. left/right tag situation can be different for different entities in the multiselection, the approach to merge/split/update the tags needs to be made on a per entity basis

this introduces a new way to specify tag changes: a callback function which is called for each to be modified entity
This commit is contained in:
Martin Raifer
2022-12-09 19:01:17 +01:00
parent 08ae8a3fac
commit 4c222fde0a
2 changed files with 30 additions and 37 deletions
+13 -8
View File
@@ -163,14 +163,19 @@ export function uiEntityEditor(context) {
var tags = Object.assign({}, entity.tags); // shallow copy
for (var k in changed) {
if (!k) continue;
var v = changed[k];
if (typeof v === 'object') {
// a "key only" tag change
tags[k] = tags[v.oldKey];
} else if (v !== undefined || tags.hasOwnProperty(k)) {
tags[k] = v;
if (typeof changed === 'function') {
// a complex callback tag change
tags = changed(tags);
} else {
for (var k in changed) {
if (!k) continue;
var v = changed[k];
if (typeof v === 'object') {
// a "key only" tag change
tags[k] = tags[v.oldKey];
} else if (v !== undefined || tags.hasOwnProperty(k)) {
tags[k] = v;
}
}
}
+17 -29
View File
@@ -79,35 +79,23 @@ export function uiFieldDirectionalCombo(field, context) {
function change(key, newValue) {
const commonKey = field.keys[0];
// don't override multiple values with blank string
if (!newValue && (Array.isArray(_tags[commonKey]) || Array.isArray(_tags[key]))) return;
if (newValue === 'none' || newValue === '') { newValue = undefined; }
const otherKey = key === field.keys[1] ? field.keys[2] : field.keys[1];
let otherValue = typeof _tags[commonKey] === 'string' ? _tags[commonKey] : _tags[otherKey];
if (otherValue && Array.isArray(otherValue)) {
// we must always have an explicit value for comparison
otherValue = otherValue[0];
}
if (otherValue === 'none' || otherValue === '') { otherValue = undefined; }
var tag = {};
// If the left and right tags match, use the common tag to tag both sides the same way
if (newValue === otherValue) {
tag[commonKey] = newValue;
tag[key] = undefined;
tag[otherKey] = undefined;
} else {
// Always set both left and right as changing one can affect the other
tag[commonKey] = undefined;
tag[key] = newValue;
tag[otherKey] = otherValue;
}
dispatch.call('change', this, tag);
dispatch.call('change', this, tags => {
const otherValue = tags[otherKey] || tags[commonKey];
if (newValue === otherValue) {
// both tags match, use the common tag to tag both sides the same way
tags[commonKey] = newValue;
delete tags[key];
delete tags[otherKey];
} else {
// Always set both left and right as changing one can affect the other
tags[key] = newValue;
delete tags[commonKey];
tags[otherKey] = otherValue;
}
return tags;
});
}
@@ -117,8 +105,8 @@ export function uiFieldDirectionalCombo(field, context) {
const commonKey = field.keys[0];
for (let key in _combos) {
const uniqueValues = [... new Set([]
.concat(tags[commonKey])
.concat(tags[key])
.concat(_tags[commonKey])
.concat(_tags[key])
.filter(Boolean))];
_combos[key].tags({ [key]: uniqueValues.length > 1 ? uniqueValues : uniqueValues[0] });
}