iobroker.mywebui 1.37.32 → 1.37.33
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
|
@@ -388,231 +388,72 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
|
|
|
388
388
|
|
|
389
389
|
async _updateVisibilityPanel() {
|
|
390
390
|
const visibilityDock = this._getDomElement('visibilityDock');
|
|
391
|
-
if (!visibilityDock)
|
|
392
|
-
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
|
|
391
|
+
if (!visibilityDock) return;
|
|
392
|
+
|
|
396
393
|
const content = visibilityDock.querySelector('#visibility-panel-content');
|
|
397
|
-
if (!content)
|
|
398
|
-
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Use _selectedItems instead of selectedElements
|
|
394
|
+
if (!content) return;
|
|
395
|
+
|
|
403
396
|
const selectedItems = this.propertyGrid.propertyGrid._selectedItems;
|
|
404
|
-
|
|
405
|
-
console.log('🔍 [Visibility] Update called, selected:', selectedItems?.length || 0);
|
|
406
|
-
|
|
397
|
+
|
|
407
398
|
if (!selectedItems || selectedItems.length !== 1) {
|
|
408
399
|
content.innerHTML = '<p style="color:#999;font-style:italic;">Select an element to configure visibility...</p>';
|
|
409
|
-
console.log('👁️ [Visibility] No selection');
|
|
410
400
|
return;
|
|
411
401
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
let
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
groups: element.getAttribute('data-visibility-groups')?.split(',').filter(g => g) || []
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
const updateConfig = (key, value) => {
|
|
428
|
-
config[key] = value;
|
|
429
|
-
|
|
430
|
-
// Use DesignItem's setAttribute to properly persist in HTML
|
|
431
|
-
const designItem = selectedItems[0];
|
|
432
|
-
|
|
433
|
-
designItem.setAttribute('data-visibility-enabled', config.enabled ? 'true' : 'false');
|
|
434
|
-
if (config.objectId) {
|
|
435
|
-
designItem.setAttribute('data-visibility-signal', config.objectId);
|
|
436
|
-
} else {
|
|
437
|
-
designItem.removeAttribute('data-visibility-signal');
|
|
438
|
-
}
|
|
439
|
-
if (config.condition) {
|
|
440
|
-
designItem.setAttribute('data-visibility-condition', config.condition);
|
|
441
|
-
}
|
|
442
|
-
if (config.conditionValue) {
|
|
443
|
-
designItem.setAttribute('data-visibility-value', config.conditionValue);
|
|
444
|
-
}
|
|
445
|
-
if (config.action) {
|
|
446
|
-
designItem.setAttribute('data-visibility-action', config.action);
|
|
447
|
-
}
|
|
448
|
-
if (config.groups && config.groups.length > 0) {
|
|
449
|
-
designItem.setAttribute('data-visibility-groups', config.groups.join(','));
|
|
450
|
-
} else {
|
|
451
|
-
designItem.removeAttribute('data-visibility-groups');
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
console.log('🔒 [Visibility] Config updated via DesignItem:', config);
|
|
455
|
-
};
|
|
456
|
-
|
|
402
|
+
|
|
403
|
+
const designItem = selectedItems[0];
|
|
404
|
+
const element = designItem.element;
|
|
405
|
+
|
|
406
|
+
// Read existing visible binding from bind-visible: attribute
|
|
407
|
+
const existingBindingAttr = element.getAttribute('bind-visible:');
|
|
408
|
+
let existingBinding = null;
|
|
409
|
+
if (existingBindingAttr != null) {
|
|
410
|
+
const parsed = bindingsHelper.parseBinding(element, 'bind-visible:', existingBindingAttr, 'visible', 'bind-visible:');
|
|
411
|
+
if (parsed) existingBinding = parsed[1];
|
|
412
|
+
}
|
|
413
|
+
|
|
457
414
|
content.innerHTML = '';
|
|
458
|
-
|
|
459
|
-
//
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const condSelect = document.createElement('select');
|
|
485
|
-
condSelect.style.cssText = 'width:100%;padding:6px;font-size:12px;border:1px solid #ccc;border-radius:3px;';
|
|
486
|
-
condSelect.innerHTML = '<option>==</option><option>!=</option><option>></option><option><</option><option>>=</option><option><=</option>';
|
|
487
|
-
condSelect.value = config.condition || '==';
|
|
488
|
-
condSelect.onchange = () => updateConfig('condition', condSelect.value);
|
|
489
|
-
condDiv.appendChild(condLabel);
|
|
490
|
-
condDiv.appendChild(condSelect);
|
|
491
|
-
content.appendChild(condDiv);
|
|
492
|
-
|
|
493
|
-
// Value for condition
|
|
494
|
-
content.appendChild(this._createField('Value for condition:', 'text', config.conditionValue || '', '1',
|
|
495
|
-
(val) => updateConfig('conditionValue', val)));
|
|
496
|
-
|
|
497
|
-
// User Groups
|
|
498
|
-
const groupsDiv = document.createElement('div');
|
|
499
|
-
groupsDiv.style.cssText = 'margin-bottom:10px;';
|
|
500
|
-
const groupsLabel = document.createElement('label');
|
|
501
|
-
groupsLabel.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
|
|
502
|
-
groupsLabel.textContent = 'Only for groups:';
|
|
503
|
-
groupsDiv.appendChild(groupsLabel);
|
|
504
|
-
|
|
505
|
-
const groupsList = document.createElement('div');
|
|
506
|
-
groupsList.style.cssText = 'max-height:100px;overflow-y:auto;border:1px solid #ccc;padding:6px;background:#fff;border-radius:3px;';
|
|
507
|
-
|
|
508
|
-
const userGroups = await iobrokerHandler.getUserGroups();
|
|
509
|
-
const selectedGroups = config.groups || [];
|
|
510
|
-
|
|
511
|
-
userGroups.forEach(group => {
|
|
512
|
-
const groupLabel = document.createElement('label');
|
|
513
|
-
groupLabel.style.cssText = 'display:flex;align-items:center;gap:5px;font-size:11px;padding:3px;cursor:pointer;';
|
|
514
|
-
const groupCheck = document.createElement('input');
|
|
515
|
-
groupCheck.type = 'checkbox';
|
|
516
|
-
groupCheck.checked = selectedGroups.includes(group.id);
|
|
517
|
-
groupCheck.onchange = () => {
|
|
518
|
-
let groups = config.groups || [];
|
|
519
|
-
if (groupCheck.checked) {
|
|
520
|
-
if (!groups.includes(group.id)) groups.push(group.id);
|
|
521
|
-
} else {
|
|
522
|
-
groups = groups.filter(g => g !== group.id);
|
|
523
|
-
}
|
|
524
|
-
updateConfig('groups', groups);
|
|
525
|
-
};
|
|
526
|
-
groupLabel.appendChild(groupCheck);
|
|
527
|
-
groupLabel.appendChild(document.createTextNode(group.name));
|
|
528
|
-
groupsList.appendChild(groupLabel);
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
groupsDiv.appendChild(groupsList);
|
|
532
|
-
content.appendChild(groupsDiv);
|
|
533
|
-
|
|
534
|
-
// Action
|
|
535
|
-
const actionDiv = document.createElement('div');
|
|
536
|
-
actionDiv.style.cssText = 'margin-bottom:5px;';
|
|
537
|
-
const actionLabel = document.createElement('label');
|
|
538
|
-
actionLabel.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
|
|
539
|
-
actionLabel.textContent = 'If user not in group:';
|
|
540
|
-
const actionSelect = document.createElement('select');
|
|
541
|
-
actionSelect.style.cssText = 'width:100%;padding:6px;font-size:12px;border:1px solid #ccc;border-radius:3px;';
|
|
542
|
-
actionSelect.innerHTML = '<option value="hide">hide</option><option value="disable">disable</option>';
|
|
543
|
-
actionSelect.value = config.action || 'hide';
|
|
544
|
-
actionSelect.onchange = () => updateConfig('action', actionSelect.value);
|
|
545
|
-
actionDiv.appendChild(actionLabel);
|
|
546
|
-
actionDiv.appendChild(actionSelect);
|
|
547
|
-
content.appendChild(actionDiv);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
_createField(label, type, value, placeholder, onChange) {
|
|
551
|
-
const div = document.createElement('div');
|
|
552
|
-
div.style.cssText = 'margin-bottom:10px;';
|
|
553
|
-
const labelEl = document.createElement('label');
|
|
554
|
-
labelEl.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
|
|
555
|
-
labelEl.textContent = label;
|
|
556
|
-
const input = document.createElement('input');
|
|
557
|
-
input.type = type;
|
|
558
|
-
input.value = value;
|
|
559
|
-
input.placeholder = placeholder;
|
|
560
|
-
input.style.cssText = 'width:100%;padding:6px;font-size:12px;border:1px solid #ccc;border-radius:3px;';
|
|
561
|
-
input.oninput = () => onChange(input.value);
|
|
562
|
-
div.appendChild(labelEl);
|
|
563
|
-
div.appendChild(input);
|
|
564
|
-
return div;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
_createFieldWithButton(label, type, value, placeholder, onChange) {
|
|
568
|
-
const div = document.createElement('div');
|
|
569
|
-
div.style.cssText = 'margin-bottom:10px;';
|
|
570
|
-
const labelEl = document.createElement('label');
|
|
571
|
-
labelEl.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
|
|
572
|
-
labelEl.textContent = label;
|
|
573
|
-
|
|
574
|
-
// Container for input + button
|
|
575
|
-
const inputContainer = document.createElement('div');
|
|
576
|
-
inputContainer.style.cssText = 'display:flex;gap:5px;';
|
|
577
|
-
|
|
578
|
-
const input = document.createElement('input');
|
|
579
|
-
input.type = type;
|
|
580
|
-
input.value = value;
|
|
581
|
-
input.placeholder = placeholder;
|
|
582
|
-
input.style.cssText = 'flex:1;padding:6px;font-size:12px;border:1px solid #ccc;border-radius:3px;';
|
|
583
|
-
input.oninput = () => onChange(input.value);
|
|
584
|
-
|
|
585
|
-
// IOB Button
|
|
586
|
-
const btn = document.createElement('button');
|
|
587
|
-
btn.textContent = 'IOB';
|
|
588
|
-
btn.title = 'ioBroker object selector';
|
|
589
|
-
btn.style.cssText = 'padding:6px 12px;font-size:11px;font-weight:bold;background:#2196f3;color:#fff;border:none;border-radius:3px;cursor:pointer;white-space:nowrap;';
|
|
590
|
-
btn.onmouseover = () => btn.style.background = '#1976d2';
|
|
591
|
-
btn.onmouseout = () => btn.style.background = '#2196f3';
|
|
592
|
-
btn.onclick = async () => {
|
|
593
|
-
try {
|
|
594
|
-
const res = await openSelectIdDialog({
|
|
595
|
-
host: window.iobrokerHost,
|
|
596
|
-
port: window.iobrokerPort,
|
|
597
|
-
protocol: window.location.protocol,
|
|
598
|
-
language: 'en',
|
|
599
|
-
selected: input.value,
|
|
600
|
-
allowAll: true
|
|
601
|
-
});
|
|
602
|
-
if (res) {
|
|
603
|
-
input.value = res;
|
|
604
|
-
onChange(res);
|
|
605
|
-
}
|
|
606
|
-
} catch (err) {
|
|
607
|
-
console.error('❌ [Visibility] Object selector error:', err);
|
|
608
|
-
}
|
|
415
|
+
|
|
416
|
+
// Property row: label + current signal + bind button + clear button
|
|
417
|
+
const row = document.createElement('div');
|
|
418
|
+
row.style.cssText = 'display:flex;align-items:center;gap:6px;padding:4px 0;';
|
|
419
|
+
|
|
420
|
+
const label = document.createElement('span');
|
|
421
|
+
label.textContent = 'Visibility';
|
|
422
|
+
label.style.cssText = 'font-size:12px;font-weight:600;flex:1;';
|
|
423
|
+
row.appendChild(label);
|
|
424
|
+
|
|
425
|
+
if (existingBinding) {
|
|
426
|
+
const statusSpan = document.createElement('span');
|
|
427
|
+
const sig = existingBinding.signal || (existingBinding.expression ? 'expr' : '?');
|
|
428
|
+
statusSpan.textContent = sig;
|
|
429
|
+
statusSpan.title = JSON.stringify(existingBinding);
|
|
430
|
+
statusSpan.style.cssText = 'font-size:10px;color:#555;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
|
|
431
|
+
row.appendChild(statusSpan);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const bindBtn = document.createElement('button');
|
|
435
|
+
bindBtn.textContent = '□';
|
|
436
|
+
bindBtn.title = 'Open binding editor';
|
|
437
|
+
bindBtn.style.cssText = 'width:20px;height:20px;padding:0;font-size:13px;line-height:1;border:1px solid #888;background:#f0f0f0;cursor:pointer;flex-shrink:0;';
|
|
438
|
+
bindBtn.onclick = () => {
|
|
439
|
+
const property = { name: 'hidden', propertyType: 'visible' };
|
|
440
|
+
serviceContainer.config.openBindingsEditor(property, [designItem], existingBinding, 'visible');
|
|
609
441
|
};
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
442
|
+
row.appendChild(bindBtn);
|
|
443
|
+
|
|
444
|
+
if (existingBinding) {
|
|
445
|
+
const clearBtn = document.createElement('button');
|
|
446
|
+
clearBtn.textContent = '✕';
|
|
447
|
+
clearBtn.title = 'Remove binding';
|
|
448
|
+
clearBtn.style.cssText = 'width:20px;height:20px;padding:0;font-size:11px;line-height:1;border:1px solid #c66;background:#fee;cursor:pointer;color:#c00;flex-shrink:0;';
|
|
449
|
+
clearBtn.onclick = () => {
|
|
450
|
+
designItem.removeAttribute('bind-visible:');
|
|
451
|
+
this._updateVisibilityPanel();
|
|
452
|
+
};
|
|
453
|
+
row.appendChild(clearBtn);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
content.appendChild(row);
|
|
616
457
|
}
|
|
617
458
|
/* Move to a Dock Spawn Helper */
|
|
618
459
|
activateDockById(name) {
|