iobroker.mywebui 1.37.33 → 1.37.34

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "mywebui",
4
- "version": "1.37.33",
4
+ "version": "1.37.34",
5
5
  "titleLang": {
6
6
  "en": "mywebui",
7
7
  "de": "mywebui",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.mywebui",
3
- "version": "1.37.33",
3
+ "version": "1.37.34",
4
4
  "description": "ioBroker mywebui - Custom edited mywebui by gokturk413",
5
5
  "type": "module",
6
6
  "main": "dist/backend/main.js",
@@ -403,43 +403,52 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
403
403
  const designItem = selectedItems[0];
404
404
  const element = designItem.element;
405
405
 
406
- // Read existing visible binding from bind-visible: attribute
407
- const existingBindingAttr = element.getAttribute('bind-visible:');
406
+ // Read existing binding from bind-prop:hidden attribute
407
+ const bindAttr = element.getAttribute('bind-prop:hidden');
408
408
  let existingBinding = null;
409
- if (existingBindingAttr != null) {
410
- const parsed = bindingsHelper.parseBinding(element, 'bind-visible:', existingBindingAttr, 'visible', 'bind-visible:');
409
+ if (bindAttr != null) {
410
+ const parsed = bindingsHelper.parseBinding(element, 'bind-prop:hidden', bindAttr, 'property', 'bind-prop:');
411
411
  if (parsed) existingBinding = parsed[1];
412
412
  }
413
413
 
414
+ // Read group access control config from data attributes
415
+ const dataConfig = {
416
+ enabled: element.getAttribute('data-visibility-enabled') === 'true',
417
+ groups: element.getAttribute('data-visibility-groups')?.split(',').filter(g => g) || [],
418
+ action: element.getAttribute('data-visibility-action') || 'hide'
419
+ };
420
+
414
421
  content.innerHTML = '';
415
422
 
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;';
423
+ // --- BINDING ROW ---
424
+ const bindRow = document.createElement('div');
425
+ bindRow.style.cssText = 'display:flex;align-items:center;gap:6px;padding:4px 0;margin-bottom:10px;padding-bottom:10px;border-bottom:1px solid #ddd;';
419
426
 
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);
427
+ const bindLabel = document.createElement('span');
428
+ bindLabel.textContent = 'Visibility';
429
+ bindLabel.style.cssText = 'font-size:12px;font-weight:600;flex:1;';
430
+ bindRow.appendChild(bindLabel);
424
431
 
425
432
  if (existingBinding) {
426
- const statusSpan = document.createElement('span');
427
433
  const sig = existingBinding.signal || (existingBinding.expression ? 'expr' : '?');
434
+ const statusSpan = document.createElement('span');
428
435
  statusSpan.textContent = sig;
429
436
  statusSpan.title = JSON.stringify(existingBinding);
430
437
  statusSpan.style.cssText = 'font-size:10px;color:#555;max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
431
- row.appendChild(statusSpan);
438
+ bindRow.appendChild(statusSpan);
432
439
  }
433
440
 
434
441
  const bindBtn = document.createElement('button');
435
442
  bindBtn.textContent = '□';
436
443
  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;';
444
+ bindBtn.style.cssText = existingBinding
445
+ ? 'width:20px;height:20px;padding:0;font-size:13px;line-height:1;border:1px solid #888;background:#ff0;cursor:pointer;flex-shrink:0;'
446
+ : 'width:20px;height:20px;padding:0;font-size:13px;line-height:1;border:1px solid #888;background:#f0f0f0;cursor:pointer;flex-shrink:0;';
438
447
  bindBtn.onclick = () => {
439
- const property = { name: 'hidden', propertyType: 'visible' };
440
- serviceContainer.config.openBindingsEditor(property, [designItem], existingBinding, 'visible');
448
+ const property = { name: 'hidden', propertyType: 'propertyAndAttribute' };
449
+ serviceContainer.config.openBindingsEditor(property, [designItem], existingBinding, 'property');
441
450
  };
442
- row.appendChild(bindBtn);
451
+ bindRow.appendChild(bindBtn);
443
452
 
444
453
  if (existingBinding) {
445
454
  const clearBtn = document.createElement('button');
@@ -447,13 +456,94 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
447
456
  clearBtn.title = 'Remove binding';
448
457
  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
458
  clearBtn.onclick = () => {
450
- designItem.removeAttribute('bind-visible:');
459
+ designItem.removeAttribute('bind-prop:hidden');
451
460
  this._updateVisibilityPanel();
452
461
  };
453
- row.appendChild(clearBtn);
462
+ bindRow.appendChild(clearBtn);
454
463
  }
455
464
 
456
- content.appendChild(row);
465
+ content.appendChild(bindRow);
466
+
467
+ // --- GROUP ACCESS CONTROL ---
468
+ const updateGroupConfig = (key, value) => {
469
+ dataConfig[key] = value;
470
+ if (key === 'enabled') {
471
+ if (value) designItem.setAttribute('data-visibility-enabled', 'true');
472
+ else designItem.removeAttribute('data-visibility-enabled');
473
+ } else if (key === 'groups') {
474
+ if (value && value.length > 0) designItem.setAttribute('data-visibility-groups', value.join(','));
475
+ else designItem.removeAttribute('data-visibility-groups');
476
+ } else if (key === 'action') {
477
+ if (value) designItem.setAttribute('data-visibility-action', value);
478
+ else designItem.removeAttribute('data-visibility-action');
479
+ }
480
+ };
481
+
482
+ // Enable checkbox
483
+ const enableDiv = document.createElement('div');
484
+ enableDiv.style.cssText = 'margin-bottom:10px;';
485
+ const enableLabel = document.createElement('label');
486
+ enableLabel.style.cssText = 'display:flex;align-items:center;gap:5px;cursor:pointer;font-size:12px;';
487
+ const enableCheck = document.createElement('input');
488
+ enableCheck.type = 'checkbox';
489
+ enableCheck.checked = dataConfig.enabled || false;
490
+ enableCheck.onchange = () => updateGroupConfig('enabled', enableCheck.checked);
491
+ enableLabel.appendChild(enableCheck);
492
+ enableLabel.appendChild(document.createTextNode('Enable Group Visibility Control'));
493
+ enableDiv.appendChild(enableLabel);
494
+ content.appendChild(enableDiv);
495
+
496
+ // Groups
497
+ const groupsDiv = document.createElement('div');
498
+ groupsDiv.style.cssText = 'margin-bottom:10px;';
499
+ const groupsLabel = document.createElement('label');
500
+ groupsLabel.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
501
+ groupsLabel.textContent = 'Only for groups:';
502
+ groupsDiv.appendChild(groupsLabel);
503
+
504
+ const groupsList = document.createElement('div');
505
+ groupsList.style.cssText = 'max-height:100px;overflow-y:auto;border:1px solid #ccc;padding:6px;background:#fff;border-radius:3px;';
506
+
507
+ const userGroups = await iobrokerHandler.getUserGroups();
508
+ const selectedGroups = dataConfig.groups || [];
509
+
510
+ userGroups.forEach(group => {
511
+ const groupLabel = document.createElement('label');
512
+ groupLabel.style.cssText = 'display:flex;align-items:center;gap:5px;font-size:11px;padding:3px;cursor:pointer;';
513
+ const groupCheck = document.createElement('input');
514
+ groupCheck.type = 'checkbox';
515
+ groupCheck.checked = selectedGroups.includes(group.id);
516
+ groupCheck.onchange = () => {
517
+ let groups = [...dataConfig.groups];
518
+ if (groupCheck.checked) {
519
+ if (!groups.includes(group.id)) groups.push(group.id);
520
+ } else {
521
+ groups = groups.filter(g => g !== group.id);
522
+ }
523
+ updateGroupConfig('groups', groups);
524
+ };
525
+ groupLabel.appendChild(groupCheck);
526
+ groupLabel.appendChild(document.createTextNode(group.name));
527
+ groupsList.appendChild(groupLabel);
528
+ });
529
+
530
+ groupsDiv.appendChild(groupsList);
531
+ content.appendChild(groupsDiv);
532
+
533
+ // Action
534
+ const actionDiv = document.createElement('div');
535
+ actionDiv.style.cssText = 'margin-bottom:5px;';
536
+ const actionLabel = document.createElement('label');
537
+ actionLabel.style.cssText = 'font-size:11px;font-weight:600;display:block;margin-bottom:3px;color:#555;';
538
+ actionLabel.textContent = 'If user not in group:';
539
+ const actionSelect = document.createElement('select');
540
+ actionSelect.style.cssText = 'width:100%;padding:6px;font-size:12px;border:1px solid #ccc;border-radius:3px;';
541
+ actionSelect.innerHTML = '<option value="hide">hide</option><option value="disable">disable</option>';
542
+ actionSelect.value = dataConfig.action || 'hide';
543
+ actionSelect.onchange = () => updateGroupConfig('action', actionSelect.value);
544
+ actionDiv.appendChild(actionLabel);
545
+ actionDiv.appendChild(actionSelect);
546
+ content.appendChild(actionDiv);
457
547
  }
458
548
  /* Move to a Dock Spawn Helper */
459
549
  activateDockById(name) {