iobroker.mywebui 1.37.37 → 1.37.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/io-package.json
CHANGED
package/package.json
CHANGED
|
@@ -404,9 +404,31 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
404
404
|
const designItem = selectedItems[0];
|
|
405
405
|
const element = designItem.element;
|
|
406
406
|
|
|
407
|
-
// Read existing signal from data-visibility-signal (
|
|
408
|
-
const
|
|
409
|
-
|
|
407
|
+
// Read existing signal from data-visibility-signal (may be plain signal string or JSON with signal+expression+historic+converter)
|
|
408
|
+
const existingSignalAttr = element.getAttribute('data-visibility-signal') || null;
|
|
409
|
+
let existingSignal = existingSignalAttr;
|
|
410
|
+
let existingBinding = null;
|
|
411
|
+
if (existingSignalAttr) {
|
|
412
|
+
if (existingSignalAttr.startsWith('{')) {
|
|
413
|
+
try {
|
|
414
|
+
const parsed = JSON.parse(existingSignalAttr);
|
|
415
|
+
existingSignal = parsed.signal || existingSignalAttr;
|
|
416
|
+
// BindingsEditor expects bindableObjectNames array, not signal string
|
|
417
|
+
existingBinding = {
|
|
418
|
+
bindableObjectNames: parsed.signal ? [parsed.signal] : [],
|
|
419
|
+
expression: parsed.expression || '',
|
|
420
|
+
historic: parsed.historic || null,
|
|
421
|
+
converter: parsed.converter || null,
|
|
422
|
+
invert: parsed.invert || false,
|
|
423
|
+
target: 'property'
|
|
424
|
+
};
|
|
425
|
+
} catch (e) {
|
|
426
|
+
existingBinding = { bindableObjectNames: [existingSignalAttr], target: 'property' };
|
|
427
|
+
}
|
|
428
|
+
} else {
|
|
429
|
+
existingBinding = { bindableObjectNames: [existingSignalAttr], target: 'property' };
|
|
430
|
+
}
|
|
431
|
+
}
|
|
410
432
|
|
|
411
433
|
// Read group access control config from data attributes
|
|
412
434
|
const dataConfig = {
|
|
@@ -436,11 +458,23 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
436
458
|
dlg.close();
|
|
437
459
|
const signal = dynEdt.objectNames;
|
|
438
460
|
if (signal) {
|
|
439
|
-
|
|
461
|
+
const bnd = { signal };
|
|
462
|
+
if (dynEdt.expression) bnd.expression = dynEdt.expression;
|
|
463
|
+
if (dynEdt.historic) bnd.historic = dynEdt.historic;
|
|
464
|
+
if (dynEdt.invert) bnd.invert = true;
|
|
465
|
+
// converters: array of {key,value} objects → plain object, or named converter string
|
|
466
|
+
if (dynEdt.converters && dynEdt.converters.length > 0) {
|
|
467
|
+
bnd.converter = {};
|
|
468
|
+
for (const c of dynEdt.converters) bnd.converter[c.key] = c.value;
|
|
469
|
+
} else if (dynEdt.convertersString) {
|
|
470
|
+
bnd.converter = dynEdt.convertersString;
|
|
471
|
+
}
|
|
472
|
+
const needsJson = bnd.expression || bnd.historic || bnd.converter || bnd.invert;
|
|
473
|
+
designItem.setAttribute('data-visibility-signal', needsJson ? JSON.stringify(bnd) : signal);
|
|
440
474
|
} else {
|
|
441
475
|
designItem.removeAttribute('data-visibility-signal');
|
|
442
476
|
}
|
|
443
|
-
designItem.removeAttribute('bind-prop:hidden');
|
|
477
|
+
designItem.removeAttribute('bind-prop:hidden');
|
|
444
478
|
this._updateVisibilityPanel();
|
|
445
479
|
});
|
|
446
480
|
};
|
|
@@ -449,13 +483,11 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
449
483
|
const bindRow = document.createElement('div');
|
|
450
484
|
bindRow.style.cssText = 'display:flex;align-items:center;gap:6px;padding:4px 0;margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid #ddd;';
|
|
451
485
|
|
|
452
|
-
//
|
|
453
|
-
const bindBtn = document.createElement('
|
|
454
|
-
bindBtn.
|
|
455
|
-
bindBtn.
|
|
456
|
-
|
|
457
|
-
? 'width:16px;height:16px;padding:0;font-size:11px;line-height:1;border:1px solid #888;background:#ffd700;cursor:pointer;flex-shrink:0;'
|
|
458
|
-
: 'width:16px;height:16px;padding:0;font-size:11px;line-height:1;border:1px solid #888;background:#f0f0f0;cursor:pointer;flex-shrink:0;';
|
|
486
|
+
// Bind indicator — styled exactly like PropertyGridPropertyList's isSetElement
|
|
487
|
+
const bindBtn = document.createElement('div');
|
|
488
|
+
bindBtn.title = existingSignal ? 'Visibility: ' + existingSignal + ' (click / right-click)' : 'Click to bind visibility signal';
|
|
489
|
+
bindBtn.style.cssText = 'width:11px;height:11px;border:1px solid #596c7a;cursor:pointer;flex-shrink:0;box-sizing:border-box;'
|
|
490
|
+
+ (existingSignal ? 'background:orange;' : 'background:transparent;');
|
|
459
491
|
|
|
460
492
|
bindBtn.onclick = openVisibilityBindingEditor;
|
|
461
493
|
|
|
@@ -44,11 +44,36 @@ class VisibilityService {
|
|
|
44
44
|
|
|
45
45
|
// Step 2: Signal/state check (if objectId configured)
|
|
46
46
|
if (visibilityConfig.objectId) {
|
|
47
|
+
// objectId may be a plain signal string or JSON like {"signal":"...","expression":"...","converter":{...},"historic":{...}}
|
|
48
|
+
let signalId = visibilityConfig.objectId;
|
|
49
|
+
let expression = null;
|
|
50
|
+
let converter = null;
|
|
51
|
+
if (typeof signalId === 'string' && signalId.startsWith('{')) {
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(signalId);
|
|
54
|
+
signalId = parsed.signal || signalId;
|
|
55
|
+
expression = parsed.expression || null;
|
|
56
|
+
converter = parsed.converter || null;
|
|
57
|
+
} catch (e) { /* keep raw */ }
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
let stateVal = currentStateVal;
|
|
48
61
|
if (stateVal === undefined) {
|
|
49
|
-
const state = await iobrokerHandler.connection.getState(
|
|
62
|
+
const state = await iobrokerHandler.connection.getState(signalId);
|
|
50
63
|
stateVal = state?.val;
|
|
51
64
|
}
|
|
65
|
+
|
|
66
|
+
// Evaluate expression if present
|
|
67
|
+
if (expression) {
|
|
68
|
+
try { stateVal = new Function('__0', expression)(stateVal); } catch (e) { console.warn('[Visibility] Expression error:', e); }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Apply converter if present (object map like {"true":"1","false":"0"} or inverse)
|
|
72
|
+
if (converter && typeof converter === 'object') {
|
|
73
|
+
const key = String(stateVal);
|
|
74
|
+
if (key in converter) stateVal = converter[key];
|
|
75
|
+
}
|
|
76
|
+
|
|
52
77
|
// Truthy state value → apply action
|
|
53
78
|
const isActive = stateVal !== null && stateVal !== undefined && stateVal !== false && stateVal !== 0 && stateVal !== '';
|
|
54
79
|
this.#applyResult(element, isActive
|
|
@@ -75,7 +100,11 @@ class VisibilityService {
|
|
|
75
100
|
await this.#checkAndApply(element, visibilityConfig, undefined);
|
|
76
101
|
|
|
77
102
|
if (visibilityConfig.objectId) {
|
|
78
|
-
|
|
103
|
+
let signalId = visibilityConfig.objectId;
|
|
104
|
+
if (typeof signalId === 'string' && signalId.startsWith('{')) {
|
|
105
|
+
try { signalId = JSON.parse(signalId).signal || signalId; } catch (e) { /* keep raw */ }
|
|
106
|
+
}
|
|
107
|
+
await iobrokerHandler.subscribeState(signalId, (_id, state) => {
|
|
79
108
|
this.#checkAndApply(element, visibilityConfig, state?.val);
|
|
80
109
|
});
|
|
81
110
|
}
|