iobroker.eos-admin 7.9.37 → 7.9.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/adminWww/assets/index-D2ymscJA.js +1 -1
- package/adminWww/css/eos-branding.css +126 -69
- package/adminWww/index.html +5 -4
- package/adminWww/js/eos-branding.js +47 -49
- package/adminWww/js/eos-objects-state-tools.js +167 -0
- package/adminWww/js/eos-runtime-fixes.js +7 -7
- package/adminWww/js/eos-security-ui.js +11 -8
- package/io-package.json +911 -903
- package/package.json +143 -143
- package/tools/nexowatt-validate-package.cjs +1 -1
|
@@ -3321,7 +3321,7 @@ html.eos-app #eos-assist-root {
|
|
|
3321
3321
|
}
|
|
3322
3322
|
|
|
3323
3323
|
|
|
3324
|
-
/* === NexoWatt EOS
|
|
3324
|
+
/* === NexoWatt EOS v38: native adapter configuration safe mode =============
|
|
3325
3325
|
Custom adapter configuration pages (React/HTML/jsonConfig) must be fully
|
|
3326
3326
|
controlled by the adapter itself. EOS shell decoration is disabled inside the
|
|
3327
3327
|
content area so buttons such as "Gerät hinzufügen" and "Gerät bearbeiten" stay
|
|
@@ -3372,100 +3372,157 @@ html.eos-app.eos-adapter-config-surface #app-paper .eos-protected-adapter-row {
|
|
|
3372
3372
|
pointer-events: auto !important;
|
|
3373
3373
|
}
|
|
3374
3374
|
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3375
|
+
|
|
3376
|
+
/* === NexoWatt EOS v38: native popup/dialog compatibility ==================
|
|
3377
|
+
EOS decoration must never block native Admin dialogs, adapter install search,
|
|
3378
|
+
autocomplete poppers, menus or adapter-owned configuration dialogs. */
|
|
3379
|
+
html.eos-app .MuiDialog-root,
|
|
3380
|
+
html.eos-app .MuiModal-root,
|
|
3381
|
+
html.eos-app .MuiPopover-root,
|
|
3382
|
+
html.eos-app .MuiPopper-root,
|
|
3383
|
+
html.eos-app .MuiMenu-root,
|
|
3384
|
+
html.eos-app .MuiAutocomplete-popper,
|
|
3385
|
+
html.eos-app [role="dialog"],
|
|
3386
|
+
html.eos-app [role="listbox"],
|
|
3387
|
+
html.eos-app [role="menu"] {
|
|
3388
|
+
pointer-events: auto !important;
|
|
3389
|
+
}
|
|
3390
|
+
html.eos-app .MuiDialog-paper,
|
|
3391
|
+
html.eos-app .MuiPaper-root[role="dialog"],
|
|
3392
|
+
html.eos-app .MuiPopover-paper,
|
|
3393
|
+
html.eos-app .MuiMenu-paper,
|
|
3394
|
+
html.eos-app .MuiAutocomplete-paper,
|
|
3395
|
+
html.eos-app .MuiAutocomplete-listbox,
|
|
3396
|
+
html.eos-app .MuiList-root[role="listbox"] {
|
|
3397
|
+
pointer-events: auto !important;
|
|
3398
|
+
user-select: auto !important;
|
|
3399
|
+
}
|
|
3400
|
+
html.eos-app .MuiAutocomplete-popper,
|
|
3401
|
+
html.eos-app .MuiPopper-root,
|
|
3402
|
+
html.eos-app .MuiPopover-root,
|
|
3403
|
+
html.eos-app .MuiMenu-root {
|
|
3404
|
+
z-index: 6500 !important;
|
|
3405
|
+
}
|
|
3406
|
+
html.eos-app .MuiDialog-root button,
|
|
3407
|
+
html.eos-app .MuiDialog-root [role="button"],
|
|
3408
|
+
html.eos-app .MuiDialog-root a,
|
|
3409
|
+
html.eos-app .MuiModal-root button,
|
|
3410
|
+
html.eos-app .MuiModal-root [role="button"],
|
|
3411
|
+
html.eos-app .MuiModal-root a,
|
|
3412
|
+
html.eos-app .MuiPopover-root button,
|
|
3413
|
+
html.eos-app .MuiPopover-root [role="button"],
|
|
3414
|
+
html.eos-app .MuiPopover-root a,
|
|
3415
|
+
html.eos-app .MuiPopper-root button,
|
|
3416
|
+
html.eos-app .MuiPopper-root [role="button"],
|
|
3417
|
+
html.eos-app .MuiPopper-root a,
|
|
3418
|
+
html.eos-app .MuiMenu-root button,
|
|
3419
|
+
html.eos-app .MuiMenu-root [role="button"],
|
|
3420
|
+
html.eos-app .MuiMenu-root a,
|
|
3421
|
+
html.eos-app [role="listbox"] [role="option"],
|
|
3422
|
+
html.eos-app .MuiAutocomplete-option {
|
|
3423
|
+
pointer-events: auto !important;
|
|
3424
|
+
visibility: visible !important;
|
|
3425
|
+
}
|
|
3426
|
+
|
|
3427
|
+
/* v38: snackbars/toasts are clickable, but generic dialogs are not modified. */
|
|
3378
3428
|
html.eos-app .MuiSnackbar-root,
|
|
3379
3429
|
html.eos-app .SnackbarItem-root,
|
|
3380
3430
|
html.eos-app .SnackbarItem-wrappedRoot,
|
|
3381
3431
|
html.eos-app .notistack-Snackbar,
|
|
3382
3432
|
html.eos-app .Toastify__toast-container,
|
|
3383
|
-
html.eos-app .Toastify__toast
|
|
3384
|
-
html.eos-app [role="alert"],
|
|
3385
|
-
html.eos-app .MuiAlert-root {
|
|
3433
|
+
html.eos-app .Toastify__toast {
|
|
3386
3434
|
pointer-events: auto !important;
|
|
3387
3435
|
z-index: 5200 !important;
|
|
3388
3436
|
}
|
|
3389
3437
|
html.eos-app .MuiSnackbar-root button,
|
|
3390
3438
|
html.eos-app .SnackbarItem-root button,
|
|
3391
3439
|
html.eos-app .notistack-Snackbar button,
|
|
3392
|
-
html.eos-app .Toastify__toast button
|
|
3393
|
-
html.eos-app .MuiAlert-root button,
|
|
3394
|
-
html.eos-app [role="alert"] button,
|
|
3395
|
-
html.eos-app button[aria-label="close"],
|
|
3396
|
-
html.eos-app button[aria-label="Close"],
|
|
3397
|
-
html.eos-app button[title="Schließen"],
|
|
3398
|
-
html.eos-app button[title="Close"] {
|
|
3440
|
+
html.eos-app .Toastify__toast button {
|
|
3399
3441
|
pointer-events: auto !important;
|
|
3400
|
-
opacity: 1 !important;
|
|
3401
3442
|
visibility: visible !important;
|
|
3402
|
-
|
|
3443
|
+
opacity: 1 !important;
|
|
3403
3444
|
}
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
html.eos-app .
|
|
3407
|
-
html.eos-app
|
|
3445
|
+
|
|
3446
|
+
/* v38: never allow decorative EOS layers to sit above native modals/popups. */
|
|
3447
|
+
html.eos-app .eos-top-toolbar::before,
|
|
3448
|
+
html.eos-app .eos-top-toolbar::after,
|
|
3449
|
+
html.eos-app .eos-brand-badge::before,
|
|
3450
|
+
html.eos-app .eos-brand-badge::after,
|
|
3451
|
+
html.eos-app .eos-panel::before,
|
|
3452
|
+
html.eos-app .eos-panel::after {
|
|
3408
3453
|
pointer-events: none !important;
|
|
3409
3454
|
}
|
|
3410
3455
|
|
|
3411
|
-
/* v37: BackItUp-safe mode. EOS keeps delete/stop controls protected in the UI,
|
|
3412
|
-
but does not force adapter-object ACLs for runtime adapters by default. */
|
|
3413
|
-
html.eos-app .eos-backitup-safe-note { color: rgba(226,245,255,.78); }
|
|
3414
3456
|
|
|
3415
|
-
/*
|
|
3416
|
-
html.eos-app .
|
|
3417
|
-
html.eos-
|
|
3418
|
-
html.eos-app .MuiSnackbarContent-root,
|
|
3419
|
-
html.eos-app [role="alert"],
|
|
3420
|
-
html.eos-app .Toastify__toast,
|
|
3421
|
-
html.eos-app .notistack-Snackbar,
|
|
3422
|
-
html.eos-app .eos-notification-safe {
|
|
3457
|
+
/* === NexoWatt EOS v39: Objects/datapoints native state writing compatibility === */
|
|
3458
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell,
|
|
3459
|
+
html.eos-objects-surface .eos-object-value-cell {
|
|
3423
3460
|
pointer-events: auto !important;
|
|
3424
|
-
|
|
3461
|
+
min-height: 30px !important;
|
|
3462
|
+
border-radius: 8px !important;
|
|
3463
|
+
transition: background .12s ease, box-shadow .12s ease, outline-color .12s ease;
|
|
3425
3464
|
}
|
|
3426
|
-
html.eos-app .
|
|
3427
|
-
html.eos-
|
|
3428
|
-
|
|
3429
|
-
html.eos-app [role="alert"] button,
|
|
3430
|
-
html.eos-app .Toastify__toast button,
|
|
3431
|
-
html.eos-app .notistack-Snackbar button,
|
|
3432
|
-
html.eos-app .eos-notification-safe button,
|
|
3433
|
-
html.eos-app .eos-notification-safe [role="button"],
|
|
3434
|
-
html.eos-app .eos-notification-safe a,
|
|
3435
|
-
html.eos-app .eos-notification-safe .MuiIconButton-root {
|
|
3436
|
-
pointer-events: auto !important;
|
|
3437
|
-
visibility: visible !important;
|
|
3438
|
-
opacity: 1 !important;
|
|
3465
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell.eos-object-value-writable,
|
|
3466
|
+
html.eos-objects-surface .eos-object-value-cell.eos-object-value-writable {
|
|
3467
|
+
cursor: pointer !important;
|
|
3439
3468
|
}
|
|
3440
|
-
html.eos-app
|
|
3441
|
-
html.eos-
|
|
3442
|
-
|
|
3469
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell.eos-object-value-writable:hover,
|
|
3470
|
+
html.eos-objects-surface .eos-object-value-cell.eos-object-value-writable:hover,
|
|
3471
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell.eos-object-value-hover,
|
|
3472
|
+
html.eos-objects-surface .eos-object-value-cell.eos-object-value-hover {
|
|
3473
|
+
background: rgba(0, 255, 136, .14) !important;
|
|
3474
|
+
box-shadow: inset 0 0 0 1px rgba(0, 255, 136, .32), 0 0 12px rgba(0, 255, 136, .10) !important;
|
|
3475
|
+
}
|
|
3476
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell .admin-button,
|
|
3477
|
+
html.eos-objects-surface .eos-object-value-cell .admin-button,
|
|
3478
|
+
html.eos-app.eos-objects-surface .eos-object-value-cell button,
|
|
3479
|
+
html.eos-objects-surface .eos-object-value-cell button {
|
|
3443
3480
|
pointer-events: auto !important;
|
|
3481
|
+
cursor: pointer !important;
|
|
3444
3482
|
}
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
html.eos-app
|
|
3449
|
-
html.eos-app
|
|
3450
|
-
html.eos-app
|
|
3483
|
+
html.eos-app.eos-objects-surface .MuiDialog-root,
|
|
3484
|
+
html.eos-app.eos-objects-surface .MuiModal-root,
|
|
3485
|
+
html.eos-app.eos-objects-surface .MuiPopover-root,
|
|
3486
|
+
html.eos-app.eos-objects-surface .MuiPopper-root,
|
|
3487
|
+
html.eos-app.eos-objects-surface [role="dialog"],
|
|
3488
|
+
html.eos-app.eos-objects-surface [role="listbox"],
|
|
3489
|
+
html.eos-app.eos-objects-surface [role="menu"],
|
|
3490
|
+
html.eos-objects-surface .MuiDialog-root,
|
|
3491
|
+
html.eos-objects-surface .MuiModal-root,
|
|
3492
|
+
html.eos-objects-surface .MuiPopover-root,
|
|
3493
|
+
html.eos-objects-surface .MuiPopper-root,
|
|
3494
|
+
html.eos-objects-surface [role="dialog"],
|
|
3495
|
+
html.eos-objects-surface [role="listbox"],
|
|
3496
|
+
html.eos-objects-surface [role="menu"] {
|
|
3451
3497
|
pointer-events: auto !important;
|
|
3452
|
-
z-index: 4300 !important;
|
|
3453
3498
|
}
|
|
3454
|
-
html.eos-app
|
|
3455
|
-
html.eos-app .MuiDialog-
|
|
3499
|
+
html.eos-app.eos-objects-surface .MuiDialog-root button,
|
|
3500
|
+
html.eos-app.eos-objects-surface .MuiDialog-root [role="button"],
|
|
3501
|
+
html.eos-app.eos-objects-surface .MuiDialog-root input,
|
|
3502
|
+
html.eos-app.eos-objects-surface .MuiDialog-root textarea,
|
|
3503
|
+
html.eos-app.eos-objects-surface .MuiDialog-root select,
|
|
3504
|
+
html.eos-app.eos-objects-surface .MuiMenuItem-root,
|
|
3505
|
+
html.eos-app.eos-objects-surface .MuiAutocomplete-option,
|
|
3506
|
+
html.eos-objects-surface .MuiDialog-root button,
|
|
3507
|
+
html.eos-objects-surface .MuiDialog-root [role="button"],
|
|
3508
|
+
html.eos-objects-surface .MuiDialog-root input,
|
|
3509
|
+
html.eos-objects-surface .MuiDialog-root textarea,
|
|
3510
|
+
html.eos-objects-surface .MuiDialog-root select,
|
|
3511
|
+
html.eos-objects-surface .MuiMenuItem-root,
|
|
3512
|
+
html.eos-objects-surface .MuiAutocomplete-option {
|
|
3456
3513
|
pointer-events: auto !important;
|
|
3457
|
-
z-index: 4301 !important;
|
|
3458
3514
|
}
|
|
3459
|
-
html.eos-app
|
|
3460
|
-
html.eos-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
pointer-events: auto !important;
|
|
3464
|
-
visibility: visible !important;
|
|
3515
|
+
html.eos-app.eos-objects-surface .MuiTooltip-popper,
|
|
3516
|
+
html.eos-objects-surface .MuiTooltip-popper {
|
|
3517
|
+
z-index: 9000 !important;
|
|
3518
|
+
pointer-events: none !important;
|
|
3465
3519
|
}
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
html.eos-app
|
|
3469
|
-
html.eos-
|
|
3470
|
-
|
|
3520
|
+
/* Do not let EOS floating help cover the right action column of the object table. */
|
|
3521
|
+
html.eos-app.eos-objects-surface .eos-assist-root,
|
|
3522
|
+
html.eos-app.eos-objects-surface #eos-assist-root,
|
|
3523
|
+
html.eos-objects-surface .eos-assist-root,
|
|
3524
|
+
html.eos-objects-surface #eos-assist-root {
|
|
3525
|
+
right: 150px !important;
|
|
3526
|
+
bottom: 26px !important;
|
|
3527
|
+
z-index: 1200 !important;
|
|
3471
3528
|
}
|
package/adminWww/index.html
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
rel="stylesheet"
|
|
32
32
|
href="css/leaflet.css"
|
|
33
33
|
/>
|
|
34
|
-
<link rel="stylesheet" href="./css/eos-branding.css?v=
|
|
34
|
+
<link rel="stylesheet" href="./css/eos-branding.css?v=39" />
|
|
35
35
|
<link
|
|
36
36
|
rel="manifest"
|
|
37
37
|
href="manifest.json"
|
|
@@ -154,9 +154,10 @@
|
|
|
154
154
|
<script type="module" crossorigin src="./assets/index-CQZugZ1z.js"></script>
|
|
155
155
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
|
|
156
156
|
<link rel="modulepreload" crossorigin href="./assets/iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js">
|
|
157
|
-
<script defer src="./js/eos-branding.js?v=
|
|
158
|
-
<script defer src="./js/eos-security-ui.js?v=
|
|
159
|
-
<script defer src="./js/eos-assistant.js?v=
|
|
157
|
+
<script defer src="./js/eos-branding.js?v=39"></script>
|
|
158
|
+
<script defer src="./js/eos-security-ui.js?v=39"></script>
|
|
159
|
+
<script defer src="./js/eos-assistant.js?v=39"></script>
|
|
160
|
+
<script defer src="./js/eos-objects-state-tools.js?v=39"></script>
|
|
160
161
|
</head>
|
|
161
162
|
<body>
|
|
162
163
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
window.NEXOWATT_EOS_UI_VERSION = '
|
|
4
|
+
window.NEXOWATT_EOS_UI_VERSION = 'v39-object-state-tools';
|
|
5
5
|
|
|
6
6
|
const BRAND = 'NexoWatt EOS';
|
|
7
7
|
const EOS_MEANING = 'Energy Operation System';
|
|
@@ -405,24 +405,50 @@
|
|
|
405
405
|
|
|
406
406
|
|
|
407
407
|
const releaseNotificationControls = () => safe(() => {
|
|
408
|
-
//
|
|
409
|
-
//
|
|
410
|
-
|
|
408
|
+
// v38: Keep native snackbar/toast close buttons clickable without touching dialogs,
|
|
409
|
+
// poppers, menus or adapter-owned configuration surfaces. Earlier broad selectors
|
|
410
|
+
// changed generic dialogs and broke React click handlers.
|
|
411
|
+
const roots = [
|
|
412
|
+
'.MuiSnackbar-root',
|
|
413
|
+
'.SnackbarItem-root',
|
|
414
|
+
'.SnackbarItem-wrappedRoot',
|
|
415
|
+
'.notistack-Snackbar',
|
|
416
|
+
'.Toastify__toast-container',
|
|
417
|
+
'.Toastify__toast'
|
|
418
|
+
].join(',');
|
|
419
|
+
document.querySelectorAll(roots).forEach(box => {
|
|
420
|
+
if (box.closest('.MuiDialog-root,.MuiModal-root,.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,[role="dialog"]')) return;
|
|
411
421
|
box.classList.add('eos-notification-safe');
|
|
412
422
|
box.style.pointerEvents = 'auto';
|
|
413
|
-
box.querySelectorAll('button, [role="button"], a, .MuiIconButton-root
|
|
423
|
+
box.querySelectorAll('button, [role="button"], a, .MuiIconButton-root').forEach(control => {
|
|
414
424
|
control.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete');
|
|
415
|
-
|
|
416
|
-
control.removeAttribute('aria-disabled');
|
|
417
|
-
if ('disabled' in control) control.disabled = false;
|
|
425
|
+
// Do not remove disabled states globally. Only restore pointer handling.
|
|
418
426
|
control.style.pointerEvents = 'auto';
|
|
419
|
-
control.style.display = '';
|
|
420
427
|
control.style.visibility = '';
|
|
421
428
|
control.style.opacity = '';
|
|
422
429
|
});
|
|
423
430
|
});
|
|
424
431
|
});
|
|
425
432
|
|
|
433
|
+
const ensurePopupCompatibility = () => safe(() => {
|
|
434
|
+
// v38: All native Admin dialogs, adapter install/autocomplete poppers, menus and
|
|
435
|
+
// adapter-owned modals must stay above EOS decorative layers and keep their React
|
|
436
|
+
// event handlers untouched.
|
|
437
|
+
const selectors = [
|
|
438
|
+
'.MuiDialog-root', '.MuiModal-root', '.MuiPopover-root', '.MuiPopper-root',
|
|
439
|
+
'.MuiMenu-root', '.MuiAutocomplete-popper', '.MuiAutocomplete-listbox',
|
|
440
|
+
'[role="dialog"]', '[role="listbox"]', '[role="menu"]'
|
|
441
|
+
].join(',');
|
|
442
|
+
document.querySelectorAll(selectors).forEach(el => {
|
|
443
|
+
el.classList.add('eos-native-popup-safe');
|
|
444
|
+
if (el.style) {
|
|
445
|
+
el.style.pointerEvents = 'auto';
|
|
446
|
+
const isFloating = el.matches('.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,.MuiAutocomplete-popper,[role="listbox"],[role="menu"]');
|
|
447
|
+
if (isFloating && !el.closest('.MuiDialog-paper')) el.style.zIndex = '6500';
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
426
452
|
const protectDeleteDialogs = () => {
|
|
427
453
|
if (isAdminUser() || state.securityPolicy.restrictProtectedAdapterControls === false) return;
|
|
428
454
|
const protectedAdapters = state.securityPolicy.protectedAdapters || [];
|
|
@@ -836,7 +862,8 @@
|
|
|
836
862
|
}
|
|
837
863
|
patchDrawerHeader(document.querySelector('.MuiDrawer-paper'));
|
|
838
864
|
hideNativeLogoutNav();
|
|
839
|
-
|
|
865
|
+
releaseNotificationControls();
|
|
866
|
+
ensurePopupCompatibility();
|
|
840
867
|
removeLogoutButton();
|
|
841
868
|
});
|
|
842
869
|
|
|
@@ -1033,23 +1060,10 @@
|
|
|
1033
1060
|
|
|
1034
1061
|
|
|
1035
1062
|
const patchNotifications = () => safe(() => {
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
document.querySelectorAll(selectors.join(',')).forEach(node => {
|
|
1041
|
-
node.classList.add('eos-notification-surface');
|
|
1042
|
-
if (node.style) {
|
|
1043
|
-
node.style.pointerEvents = 'auto';
|
|
1044
|
-
if (!node.closest('.MuiDialog-root')) node.style.zIndex = '5200';
|
|
1045
|
-
}
|
|
1046
|
-
node.querySelectorAll('button,[role="button"],a').forEach(control => {
|
|
1047
|
-
control.classList.add('eos-notification-action');
|
|
1048
|
-
control.style.pointerEvents = 'auto';
|
|
1049
|
-
control.style.visibility = 'visible';
|
|
1050
|
-
control.style.opacity = '1';
|
|
1051
|
-
});
|
|
1052
|
-
});
|
|
1063
|
+
// Kept for compatibility with older calls. v38 intentionally scopes this to
|
|
1064
|
+
// snackbar/toast surfaces only; no dialogs, popovers or adapter config controls.
|
|
1065
|
+
releaseNotificationControls();
|
|
1066
|
+
ensurePopupCompatibility();
|
|
1053
1067
|
});
|
|
1054
1068
|
|
|
1055
1069
|
const applyNavCompactPreference = () => safe(() => {
|
|
@@ -1355,10 +1369,11 @@
|
|
|
1355
1369
|
ensureRightsHelper();
|
|
1356
1370
|
ensurePermissionPresets();
|
|
1357
1371
|
ensureSettingsDialogClasses();
|
|
1358
|
-
|
|
1372
|
+
ensurePopupCompatibility();
|
|
1359
1373
|
hideNativeLogoutNav();
|
|
1360
1374
|
hideOfficialNexoWattRepoWarning();
|
|
1361
|
-
|
|
1375
|
+
releaseNotificationControls();
|
|
1376
|
+
ensurePopupCompatibility();
|
|
1362
1377
|
applySecurityUiGuard();
|
|
1363
1378
|
if (isAdapterConfigSurface()) {
|
|
1364
1379
|
// Adapter-owned configuration pages must not be rebranded or structurally patched.
|
|
@@ -1394,10 +1409,11 @@
|
|
|
1394
1409
|
ensureRightsHelper();
|
|
1395
1410
|
ensurePermissionPresets();
|
|
1396
1411
|
ensureSettingsDialogClasses();
|
|
1397
|
-
|
|
1412
|
+
ensurePopupCompatibility();
|
|
1398
1413
|
hideNativeLogoutNav();
|
|
1399
1414
|
hideOfficialNexoWattRepoWarning();
|
|
1400
|
-
|
|
1415
|
+
releaseNotificationControls();
|
|
1416
|
+
ensurePopupCompatibility();
|
|
1401
1417
|
applySecurityUiGuard();
|
|
1402
1418
|
for (const scope of scopes.slice(0, 80)) {
|
|
1403
1419
|
if (!scope || !scope.isConnected) continue;
|
|
@@ -1474,21 +1490,3 @@
|
|
|
1474
1490
|
window.addEventListener('load', () => scheduleFullPatch(0), { once: true });
|
|
1475
1491
|
window.addEventListener('hashchange', () => scheduleFullPatch(0));
|
|
1476
1492
|
})();
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
// v37 eos notification close compatibility: never let EOS overlays block native notification dialogs.
|
|
1480
|
-
(() => {
|
|
1481
|
-
const normalize = value => String(value || '').replace(/\s+/g, ' ').trim();
|
|
1482
|
-
document.addEventListener('click', event => {
|
|
1483
|
-
const target = event.target?.closest?.('button, [role="button"], a, .MuiButtonBase-root, .MuiIconButton-root');
|
|
1484
|
-
if (!target) return;
|
|
1485
|
-
const dialog = target.closest?.('.eos-notification-dialog, .MuiDialog-paper, [role="dialog"]');
|
|
1486
|
-
if (!dialog || !/benachrichtigungen|notifications|acknowledge|bestätigen|schließen|close/i.test(dialog.textContent || '')) return;
|
|
1487
|
-
const label = normalize(`${target.textContent || ''} ${target.getAttribute?.('aria-label') || ''} ${target.getAttribute?.('title') || ''}`);
|
|
1488
|
-
if (/schließen|close|bestätigen|acknowledge/i.test(label)) {
|
|
1489
|
-
target.style.pointerEvents = 'auto';
|
|
1490
|
-
// Do not prevent React handlers; only stop EOS-specific bubbling side effects.
|
|
1491
|
-
event.stopPropagation();
|
|
1492
|
-
}
|
|
1493
|
-
}, true);
|
|
1494
|
-
})();
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
window.NEXOWATT_EOS_OBJECTS_STATE_TOOLS_VERSION = 'v39-object-state-tools';
|
|
5
|
+
|
|
6
|
+
const ACTIVE_CLASS = 'eos-objects-surface';
|
|
7
|
+
const safe = fn => { try { return fn(); } catch (e) { return undefined; } };
|
|
8
|
+
|
|
9
|
+
const isObjectsRoute = () => {
|
|
10
|
+
const hash = String(window.location.hash || '');
|
|
11
|
+
if (/#tab-objects/.test(hash)) return true;
|
|
12
|
+
const url = String(window.location.href || '');
|
|
13
|
+
if (/[?&]tab=objects/.test(url)) return true;
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const setSurfaceState = () => {
|
|
18
|
+
const active = isObjectsRoute();
|
|
19
|
+
document.documentElement.classList.toggle(ACTIVE_CLASS, active);
|
|
20
|
+
document.body?.classList.toggle(ACTIVE_CLASS, active);
|
|
21
|
+
return active;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const interactiveSelector = [
|
|
25
|
+
'button',
|
|
26
|
+
'[role="button"]',
|
|
27
|
+
'a[href]',
|
|
28
|
+
'input',
|
|
29
|
+
'select',
|
|
30
|
+
'textarea',
|
|
31
|
+
'.MuiButton-root',
|
|
32
|
+
'.MuiIconButton-root',
|
|
33
|
+
'.MuiCheckbox-root',
|
|
34
|
+
'.MuiSwitch-root',
|
|
35
|
+
'.MuiSwitch-switchBase',
|
|
36
|
+
'.MuiMenuItem-root',
|
|
37
|
+
'.MuiAutocomplete-option',
|
|
38
|
+
'.MuiSelect-select',
|
|
39
|
+
'.admin-button',
|
|
40
|
+
'.copyButton'
|
|
41
|
+
].join(',');
|
|
42
|
+
|
|
43
|
+
const nativeLayerSelector = [
|
|
44
|
+
'.MuiDialog-root',
|
|
45
|
+
'.MuiModal-root',
|
|
46
|
+
'.MuiPopover-root',
|
|
47
|
+
'.MuiPopper-root',
|
|
48
|
+
'.MuiTooltip-popper',
|
|
49
|
+
'[role="dialog"]',
|
|
50
|
+
'[role="listbox"]',
|
|
51
|
+
'[role="menu"]',
|
|
52
|
+
'[role="tooltip"]'
|
|
53
|
+
].join(',');
|
|
54
|
+
|
|
55
|
+
const releaseNativeControls = root => safe(() => {
|
|
56
|
+
if (!setSurfaceState()) return;
|
|
57
|
+
const base = root && root.nodeType ? root : document;
|
|
58
|
+
const nodes = [];
|
|
59
|
+
if (base.nodeType === Node.ELEMENT_NODE && base.matches?.(interactiveSelector)) nodes.push(base);
|
|
60
|
+
nodes.push(...Array.from(base.querySelectorAll?.(interactiveSelector) || []));
|
|
61
|
+
nodes.forEach(el => {
|
|
62
|
+
if (!el || el.closest?.('#eos-assist-root,.eos-assist-root')) return;
|
|
63
|
+
el.classList?.remove('eos-security-hidden-delete', 'eos-protected-delete-control', 'eos-disabled-by-security');
|
|
64
|
+
el.removeAttribute?.('data-eos-security-blocked');
|
|
65
|
+
el.removeAttribute?.('aria-disabled');
|
|
66
|
+
el.style.pointerEvents = 'auto';
|
|
67
|
+
if (el.style.visibility === 'hidden') el.style.visibility = 'visible';
|
|
68
|
+
if (el.style.display === 'none' && !el.classList?.contains('eos-native-logout-hidden')) el.style.display = '';
|
|
69
|
+
});
|
|
70
|
+
const layers = [];
|
|
71
|
+
if (base.nodeType === Node.ELEMENT_NODE && base.matches?.(nativeLayerSelector)) layers.push(base);
|
|
72
|
+
layers.push(...Array.from(base.querySelectorAll?.(nativeLayerSelector) || []));
|
|
73
|
+
layers.forEach(el => {
|
|
74
|
+
if (!el) return;
|
|
75
|
+
el.style.pointerEvents = 'auto';
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const formatAge = ts => {
|
|
80
|
+
const n = Number(ts);
|
|
81
|
+
if (!Number.isFinite(n) || n <= 0) return 'unbekannt';
|
|
82
|
+
try { return new Date(n).toLocaleString(); } catch { return String(n); }
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const annotateValueCells = root => safe(() => {
|
|
86
|
+
if (!setSurfaceState()) return;
|
|
87
|
+
const base = root && root.nodeType ? root : document;
|
|
88
|
+
const cells = [];
|
|
89
|
+
if (base.nodeType === Node.ELEMENT_NODE && base.matches?.('.eos-object-value-cell')) cells.push(base);
|
|
90
|
+
cells.push(...Array.from(base.querySelectorAll?.('.eos-object-value-cell') || []));
|
|
91
|
+
cells.forEach(cell => {
|
|
92
|
+
const id = cell.getAttribute('data-eos-object-value-cell') || '';
|
|
93
|
+
const writable = cell.getAttribute('data-eos-object-writable') === '1';
|
|
94
|
+
const visibleValue = (cell.textContent || '').trim().replace(/\s+/g, ' ') || '(leer)';
|
|
95
|
+
cell.style.pointerEvents = 'auto';
|
|
96
|
+
cell.style.cursor = writable ? 'pointer' : 'default';
|
|
97
|
+
cell.classList.toggle('eos-object-value-writable', writable);
|
|
98
|
+
cell.classList.toggle('eos-object-value-readonly', !writable);
|
|
99
|
+
cell.setAttribute('data-eos-current-visible-value', visibleValue);
|
|
100
|
+
const hint = writable
|
|
101
|
+
? 'Klicken: Wert schreiben / Button sofort testen'
|
|
102
|
+
: 'Nur lesbarer Wert';
|
|
103
|
+
cell.setAttribute('title', [
|
|
104
|
+
id ? `ID: ${id}` : null,
|
|
105
|
+
`Aktueller Wert: ${visibleValue}`,
|
|
106
|
+
`Status: ${writable ? 'beschreibbar' : 'nur lesbar'}`,
|
|
107
|
+
`Letzte Anzeige-Aktualisierung: ${formatAge(Date.now())}`,
|
|
108
|
+
hint,
|
|
109
|
+
'Zusätzliche Statusdetails zeigt der native EOS/ioBroker-Hover an.'
|
|
110
|
+
].filter(Boolean).join('\n'));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const handlePointerAssist = event => {
|
|
115
|
+
if (!setSurfaceState()) return;
|
|
116
|
+
const cell = event.target?.closest?.('.eos-object-value-cell');
|
|
117
|
+
if (!cell) return;
|
|
118
|
+
if (cell.getAttribute('data-eos-object-writable') === '1') {
|
|
119
|
+
cell.classList.add('eos-object-value-hover');
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const handlePointerLeave = event => {
|
|
123
|
+
const cell = event.target?.closest?.('.eos-object-value-cell');
|
|
124
|
+
cell?.classList.remove('eos-object-value-hover');
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const run = root => {
|
|
128
|
+
if (!setSurfaceState()) return;
|
|
129
|
+
releaseNativeControls(root);
|
|
130
|
+
annotateValueCells(root);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
window.addEventListener('hashchange', () => setTimeout(() => run(document), 30));
|
|
134
|
+
window.addEventListener('popstate', () => setTimeout(() => run(document), 30));
|
|
135
|
+
document.addEventListener('mouseover', handlePointerAssist, true);
|
|
136
|
+
document.addEventListener('mouseout', handlePointerLeave, true);
|
|
137
|
+
document.addEventListener('click', event => {
|
|
138
|
+
if (!setSurfaceState()) return;
|
|
139
|
+
const nativeInteractive = event.target?.closest?.(interactiveSelector + ',' + nativeLayerSelector + ',.eos-object-value-cell');
|
|
140
|
+
if (nativeInteractive) {
|
|
141
|
+
// Intentionally do not stop propagation. This keeps the native ObjectBrowser write dialog and button states working.
|
|
142
|
+
releaseNativeControls(nativeInteractive);
|
|
143
|
+
}
|
|
144
|
+
}, false);
|
|
145
|
+
|
|
146
|
+
const observer = new MutationObserver(records => {
|
|
147
|
+
if (!setSurfaceState()) return;
|
|
148
|
+
let roots = [];
|
|
149
|
+
for (const rec of records) {
|
|
150
|
+
rec.addedNodes?.forEach(node => {
|
|
151
|
+
if (node.nodeType === Node.ELEMENT_NODE) roots.push(node);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (!roots.length) roots = [document];
|
|
155
|
+
window.requestAnimationFrame?.(() => roots.forEach(run)) || roots.forEach(run);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const start = () => {
|
|
159
|
+
setSurfaceState();
|
|
160
|
+
run(document);
|
|
161
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
162
|
+
window.setInterval(() => run(document), 2500);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start, { once: true });
|
|
166
|
+
else start();
|
|
167
|
+
})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
window.NEXOWATT_EOS_RUNTIME_FIXES_VERSION = '
|
|
4
|
+
window.NEXOWATT_EOS_RUNTIME_FIXES_VERSION = 'v39-object-state-tools';
|
|
5
5
|
|
|
6
6
|
const MOJIBAKE_MAP = new Map(Object.entries({
|
|
7
7
|
'dürfen': 'dürfen', 'Dürfen': 'Dürfen',
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
|
|
79
79
|
const isNotificationSurface = el => !!el?.closest?.([
|
|
80
80
|
'.MuiSnackbar-root',
|
|
81
|
-
'.
|
|
82
|
-
'
|
|
83
|
-
'
|
|
81
|
+
'.SnackbarItem-root',
|
|
82
|
+
'.SnackbarItem-wrappedRoot',
|
|
83
|
+
'.notistack-Snackbar',
|
|
84
84
|
'.Toastify__toast',
|
|
85
85
|
'.eos-notification-safe'
|
|
86
86
|
].join(','));
|
|
@@ -107,9 +107,9 @@
|
|
|
107
107
|
const base = root && root.nodeType ? root : document;
|
|
108
108
|
const surfaces = Array.from(base.querySelectorAll?.([
|
|
109
109
|
'.MuiSnackbar-root',
|
|
110
|
-
'.
|
|
111
|
-
'
|
|
112
|
-
'
|
|
110
|
+
'.SnackbarItem-root',
|
|
111
|
+
'.SnackbarItem-wrappedRoot',
|
|
112
|
+
'.notistack-Snackbar',
|
|
113
113
|
'.Toastify__toast'
|
|
114
114
|
].join(',')) || []);
|
|
115
115
|
if (base.nodeType === Node.ELEMENT_NODE && isNotificationSurface(base)) surfaces.push(base);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const VERSION = '
|
|
4
|
+
const VERSION = 'v39-object-state-tools';
|
|
5
5
|
const LEGACY_ADMIN = 'admin';
|
|
6
6
|
const LEGACY_ADMIN_INSTANCE = 'admin.0';
|
|
7
7
|
const ASSET_BASE = (() => {
|
|
@@ -246,18 +246,19 @@
|
|
|
246
246
|
const isAdapterConfigSurface = () => document.documentElement.classList.contains('eos-adapter-config-surface') || /Instanzeinstellungen:|Instance settings:|Geräteliste|Gerät hinzufügen|Gerät bearbeiten/i.test(document.body?.textContent || '');
|
|
247
247
|
|
|
248
248
|
const releaseNotificationControls = () => {
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
|
|
249
|
+
// v38: security UI must not modify generic dialogs or adapter popups.
|
|
250
|
+
// Only snackbar/toast surfaces are normalized for clickability.
|
|
251
|
+
const roots = [
|
|
252
|
+
'.MuiSnackbar-root', '.SnackbarItem-root', '.SnackbarItem-wrappedRoot',
|
|
253
|
+
'.notistack-Snackbar', '.Toastify__toast-container', '.Toastify__toast'
|
|
254
|
+
].join(',');
|
|
255
|
+
document.querySelectorAll(roots).forEach(box => {
|
|
256
|
+
if (box.closest('.MuiDialog-root,.MuiModal-root,.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,[role="dialog"]')) return;
|
|
252
257
|
box.classList.add('eos-notification-safe');
|
|
253
258
|
box.style.pointerEvents = 'auto';
|
|
254
259
|
box.querySelectorAll('button, [role="button"], a, .MuiIconButton-root').forEach(control => {
|
|
255
260
|
control.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete');
|
|
256
|
-
control.removeAttribute('disabled');
|
|
257
|
-
control.removeAttribute('aria-disabled');
|
|
258
|
-
if ('disabled' in control) control.disabled = false;
|
|
259
261
|
control.style.pointerEvents = 'auto';
|
|
260
|
-
control.style.display = '';
|
|
261
262
|
control.style.visibility = '';
|
|
262
263
|
});
|
|
263
264
|
});
|
|
@@ -301,6 +302,8 @@
|
|
|
301
302
|
document.addEventListener('click', event => {
|
|
302
303
|
const target = event.target?.closest?.('button,[role="button"],a,[role="menuitem"],.MuiMenuItem-root');
|
|
303
304
|
if (!target || isAdminUser() || isAdapterConfigSurface()) return;
|
|
305
|
+
// Native Admin dialogs, install/autocomplete poppers and adapter-owned menus must stay untouched.
|
|
306
|
+
if (target.closest?.('.MuiDialog-root,.MuiModal-root,.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,.MuiAutocomplete-popper,[role="dialog"],[role="listbox"],[role="menu"]')) return;
|
|
304
307
|
const label = normalizeFlat(`${target.textContent || ''} ${target.getAttribute?.('title') || ''} ${target.getAttribute?.('aria-label') || ''}`);
|
|
305
308
|
if (/loschen|delete|remove|deinstall|uninstall/.test(label)) {
|
|
306
309
|
target.classList.add('eos-security-hidden-delete');
|