iobroker.eos-admin 7.9.26 → 7.9.27
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/admin/jsonConfig.json5 +20 -0
- package/adminWww/css/eos-branding.css +310 -0
- package/adminWww/index.html +4 -3
- package/adminWww/js/eos-assistant.js +203 -0
- package/adminWww/js/eos-branding.js +41 -1
- package/build/lib/web.js +12 -0
- package/io-package.json +9 -2
- package/package.json +1 -1
package/admin/jsonConfig.json5
CHANGED
|
@@ -165,6 +165,26 @@
|
|
|
165
165
|
newLine: true,
|
|
166
166
|
label: 'Disable Assistent',
|
|
167
167
|
sx: 12,
|
|
168
|
+
},
|
|
169
|
+
eosAssistantEnabled: {
|
|
170
|
+
type: 'checkbox',
|
|
171
|
+
newLine: true,
|
|
172
|
+
label: 'EOS Assist anzeigen',
|
|
173
|
+
help: 'Zeigt die lokale Bedienungsassistenz für Einrichtung, Adapter, Dienste, Logs und Rechte in der EOS-Oberfläche an.',
|
|
174
|
+
xs: 12,
|
|
175
|
+
sm: 12,
|
|
176
|
+
md: 6,
|
|
177
|
+
lg: 4,
|
|
178
|
+
},
|
|
179
|
+
eosAssistantAdminOnly: {
|
|
180
|
+
type: 'checkbox',
|
|
181
|
+
label: 'EOS Assist nur für Administratoren',
|
|
182
|
+
help: 'Wenn aktiv, sehen Installateur- und Endkundenbenutzer den EOS Assist nicht.',
|
|
183
|
+
hidden: '!data.eosAssistantEnabled',
|
|
184
|
+
xs: 12,
|
|
185
|
+
sm: 12,
|
|
186
|
+
md: 6,
|
|
187
|
+
lg: 4,
|
|
168
188
|
}
|
|
169
189
|
},
|
|
170
190
|
},
|
|
@@ -2448,3 +2448,313 @@ html.eos-app .MuiAppBar-root .MuiToolbar-root img[alt*="user" i] {
|
|
|
2448
2448
|
}
|
|
2449
2449
|
}
|
|
2450
2450
|
|
|
2451
|
+
|
|
2452
|
+
/* === NexoWatt EOS v27: black logo plate + safe compact navigation =========
|
|
2453
|
+
The horizontal rail must never disappear completely. The collapse control is
|
|
2454
|
+
used as a two-stage compact toggle and gets its own non-overlapping left slot. */
|
|
2455
|
+
html.eos-app .eos-brand-badge {
|
|
2456
|
+
grid-template-columns: 78px minmax(172px, 1fr) 12px !important;
|
|
2457
|
+
min-width: 332px !important;
|
|
2458
|
+
width: 332px !important;
|
|
2459
|
+
padding-left: 6px !important;
|
|
2460
|
+
background:
|
|
2461
|
+
radial-gradient(circle at 39px 31px, rgba(0, 255, 136, 0.18), transparent 46px),
|
|
2462
|
+
linear-gradient(135deg, rgba(0, 36, 28, 0.86), rgba(2, 9, 20, 0.95) 62%, rgba(0, 0, 0, 0.82)) !important;
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
html.eos-app .eos-brand-badge-mark {
|
|
2466
|
+
width: 66px !important;
|
|
2467
|
+
height: 66px !important;
|
|
2468
|
+
min-width: 66px !important;
|
|
2469
|
+
min-height: 66px !important;
|
|
2470
|
+
transform: translateY(-2px) !important;
|
|
2471
|
+
border-radius: 23px !important;
|
|
2472
|
+
background:
|
|
2473
|
+
radial-gradient(circle at 50% 44%, rgba(0, 255, 136, 0.11), rgba(0, 13, 14, 0.86) 47%, rgba(0, 0, 0, 0.98) 100%) !important;
|
|
2474
|
+
border: 1px solid rgba(97, 255, 213, 0.70) !important;
|
|
2475
|
+
outline: 1px solid rgba(0, 0, 0, 0.82) !important;
|
|
2476
|
+
box-shadow:
|
|
2477
|
+
inset 0 0 0 1px rgba(255, 255, 255, 0.035),
|
|
2478
|
+
inset 0 0 28px rgba(0, 255, 136, 0.12),
|
|
2479
|
+
0 0 0 3px rgba(0, 0, 0, 0.42),
|
|
2480
|
+
0 0 22px rgba(0, 255, 136, 0.46),
|
|
2481
|
+
0 0 46px rgba(0, 212, 255, 0.13) !important;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
html.eos-app .eos-brand-badge-logo {
|
|
2485
|
+
width: 58px !important;
|
|
2486
|
+
height: 58px !important;
|
|
2487
|
+
min-width: 58px !important;
|
|
2488
|
+
min-height: 58px !important;
|
|
2489
|
+
transform: translateY(-1px) !important;
|
|
2490
|
+
filter:
|
|
2491
|
+
brightness(2.28)
|
|
2492
|
+
contrast(1.22)
|
|
2493
|
+
saturate(1.50)
|
|
2494
|
+
drop-shadow(0 0 1px rgba(245, 255, 252, 0.96))
|
|
2495
|
+
drop-shadow(0 0 11px rgba(0, 255, 136, 0.86))
|
|
2496
|
+
drop-shadow(0 0 23px rgba(0, 212, 255, 0.28)) !important;
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
/* Dedicated collapse/compact slot: left of the horizontal menu, no overlap with
|
|
2500
|
+
the first menu action. The native full-close action is intercepted in JS. */
|
|
2501
|
+
html.eos-app .MuiDrawer-paper,
|
|
2502
|
+
html.eos-app .eos-drawer {
|
|
2503
|
+
position: fixed !important;
|
|
2504
|
+
padding-left: 82px !important;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
html.eos-app .eos-native-drawer-header {
|
|
2508
|
+
position: absolute !important;
|
|
2509
|
+
left: 12px !important;
|
|
2510
|
+
top: 8px !important;
|
|
2511
|
+
right: auto !important;
|
|
2512
|
+
bottom: auto !important;
|
|
2513
|
+
flex: 0 0 58px !important;
|
|
2514
|
+
width: 58px !important;
|
|
2515
|
+
min-width: 58px !important;
|
|
2516
|
+
max-width: 58px !important;
|
|
2517
|
+
margin: 0 !important;
|
|
2518
|
+
z-index: 4 !important;
|
|
2519
|
+
background: linear-gradient(145deg, rgba(0, 255, 136, 0.17), rgba(0, 25, 32, 0.88)) !important;
|
|
2520
|
+
border: 1px solid rgba(0, 255, 136, 0.42) !important;
|
|
2521
|
+
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.34), inset 0 0 18px rgba(0, 255, 136, 0.10) !important;
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
html.eos-app .eos-native-drawer-header button,
|
|
2525
|
+
html.eos-app .eos-native-drawer-header .MuiIconButton-root,
|
|
2526
|
+
html.eos-app .eos-native-drawer-header [role="button"] {
|
|
2527
|
+
width: 46px !important;
|
|
2528
|
+
height: 46px !important;
|
|
2529
|
+
min-width: 46px !important;
|
|
2530
|
+
min-height: 46px !important;
|
|
2531
|
+
border-radius: 16px !important;
|
|
2532
|
+
background: rgba(0, 0, 0, 0.28) !important;
|
|
2533
|
+
border: 1px solid rgba(0, 255, 136, 0.24) !important;
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
html.eos-app .eos-native-drawer-header button::after,
|
|
2537
|
+
html.eos-app .eos-native-drawer-header .MuiIconButton-root::after,
|
|
2538
|
+
html.eos-app .eos-native-drawer-header [role="button"]::after {
|
|
2539
|
+
content: 'kompakt';
|
|
2540
|
+
position: absolute;
|
|
2541
|
+
left: 50%;
|
|
2542
|
+
bottom: -13px;
|
|
2543
|
+
transform: translateX(-50%);
|
|
2544
|
+
font-size: 7px;
|
|
2545
|
+
font-weight: 800;
|
|
2546
|
+
line-height: 1;
|
|
2547
|
+
letter-spacing: .06em;
|
|
2548
|
+
text-transform: uppercase;
|
|
2549
|
+
color: rgba(208, 255, 239, .62);
|
|
2550
|
+
pointer-events: none;
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
html.eos-nav-compact .eos-native-drawer-header button::after,
|
|
2554
|
+
html.eos-nav-compact .eos-native-drawer-header .MuiIconButton-root::after,
|
|
2555
|
+
html.eos-nav-compact .eos-native-drawer-header [role="button"]::after {
|
|
2556
|
+
content: 'menü';
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
html.eos-app .eos-scroll-nav,
|
|
2560
|
+
html.eos-app .MuiDrawer-paper .MuiList-root {
|
|
2561
|
+
margin-left: 0 !important;
|
|
2562
|
+
padding-left: 0 !important;
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
/* Stronger removal of the native logout tile in the horizontal rail. */
|
|
2566
|
+
html.eos-app .eos-hidden-logout,
|
|
2567
|
+
html.eos-app .eos-hidden-logout *,
|
|
2568
|
+
html.eos-app .MuiDrawer-paper a[href*="logout"],
|
|
2569
|
+
html.eos-app .MuiDrawer-paper button[aria-label*="logout" i],
|
|
2570
|
+
html.eos-app .MuiDrawer-paper button[aria-label*="abmelden" i] {
|
|
2571
|
+
display: none !important;
|
|
2572
|
+
visibility: hidden !important;
|
|
2573
|
+
opacity: 0 !important;
|
|
2574
|
+
pointer-events: none !important;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
/* Compact mode keeps the rail visible but reduces the menu to icon buttons. */
|
|
2578
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper,
|
|
2579
|
+
html.eos-nav-compact.eos-app .eos-drawer {
|
|
2580
|
+
height: 66px !important;
|
|
2581
|
+
min-height: 66px !important;
|
|
2582
|
+
max-height: 66px !important;
|
|
2583
|
+
padding-top: 6px !important;
|
|
2584
|
+
padding-bottom: 6px !important;
|
|
2585
|
+
padding-left: 78px !important;
|
|
2586
|
+
}
|
|
2587
|
+
|
|
2588
|
+
html.eos-nav-compact.eos-app .eos-native-drawer-header {
|
|
2589
|
+
top: 6px !important;
|
|
2590
|
+
width: 54px !important;
|
|
2591
|
+
min-width: 54px !important;
|
|
2592
|
+
max-width: 54px !important;
|
|
2593
|
+
height: 52px !important;
|
|
2594
|
+
min-height: 52px !important;
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
html.eos-nav-compact.eos-app .eos-native-drawer-header button,
|
|
2598
|
+
html.eos-nav-compact.eos-app .eos-native-drawer-header .MuiIconButton-root,
|
|
2599
|
+
html.eos-nav-compact.eos-app .eos-native-drawer-header [role="button"] {
|
|
2600
|
+
width: 42px !important;
|
|
2601
|
+
height: 42px !important;
|
|
2602
|
+
min-width: 42px !important;
|
|
2603
|
+
min-height: 42px !important;
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiListItemButton-root,
|
|
2607
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiButtonBase-root.MuiListItemButton-root {
|
|
2608
|
+
width: 54px !important;
|
|
2609
|
+
min-width: 54px !important;
|
|
2610
|
+
max-width: 54px !important;
|
|
2611
|
+
height: 50px !important;
|
|
2612
|
+
min-height: 50px !important;
|
|
2613
|
+
padding: 0 !important;
|
|
2614
|
+
justify-content: center !important;
|
|
2615
|
+
gap: 0 !important;
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiListItemIcon-root {
|
|
2619
|
+
min-width: 0 !important;
|
|
2620
|
+
margin: 0 !important;
|
|
2621
|
+
display: inline-flex !important;
|
|
2622
|
+
justify-content: center !important;
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiListItemText-root,
|
|
2626
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiListItemButton-root .MuiTypography-root,
|
|
2627
|
+
html.eos-nav-compact.eos-app .MuiDrawer-paper .MuiListItemButton-root span:not(.MuiBadge-badge) {
|
|
2628
|
+
max-width: 0 !important;
|
|
2629
|
+
width: 0 !important;
|
|
2630
|
+
min-width: 0 !important;
|
|
2631
|
+
opacity: 0 !important;
|
|
2632
|
+
overflow: hidden !important;
|
|
2633
|
+
margin: 0 !important;
|
|
2634
|
+
padding: 0 !important;
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
html.eos-nav-compact.eos-app #app-paper,
|
|
2638
|
+
html.eos-nav-compact.eos-app main,
|
|
2639
|
+
html.eos-nav-compact.eos-app .MuiContainer-root {
|
|
2640
|
+
/* content keeps its normal vertical rhythm; the rail is still present */
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
@media (max-width: 1220px) {
|
|
2644
|
+
html.eos-app .eos-brand-badge {
|
|
2645
|
+
min-width: 88px !important;
|
|
2646
|
+
width: 88px !important;
|
|
2647
|
+
padding-left: 7px !important;
|
|
2648
|
+
}
|
|
2649
|
+
html.eos-app .eos-brand-badge-mark {
|
|
2650
|
+
background: radial-gradient(circle at 50% 44%, rgba(0, 255, 136, 0.10), rgba(0, 0, 0, 0.98) 70%) !important;
|
|
2651
|
+
}
|
|
2652
|
+
html.eos-app .MuiDrawer-paper,
|
|
2653
|
+
html.eos-app .eos-drawer {
|
|
2654
|
+
padding-left: 74px !important;
|
|
2655
|
+
}
|
|
2656
|
+
html.eos-app .eos-native-drawer-header {
|
|
2657
|
+
left: 9px !important;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
/* === NexoWatt EOS v27: local setup assistant ============================== */
|
|
2662
|
+
.eos-assist-launcher {
|
|
2663
|
+
position: fixed;
|
|
2664
|
+
right: 24px;
|
|
2665
|
+
bottom: 24px;
|
|
2666
|
+
z-index: 1900;
|
|
2667
|
+
height: 54px;
|
|
2668
|
+
min-width: 54px;
|
|
2669
|
+
border: 1px solid rgba(0, 255, 136, .55);
|
|
2670
|
+
border-radius: 18px;
|
|
2671
|
+
background: linear-gradient(135deg, #00ff88, #00d4ff);
|
|
2672
|
+
color: #02101d;
|
|
2673
|
+
font-weight: 950;
|
|
2674
|
+
letter-spacing: .02em;
|
|
2675
|
+
box-shadow: 0 16px 34px rgba(0,0,0,.42), 0 0 26px rgba(0,255,136,.28);
|
|
2676
|
+
cursor: pointer;
|
|
2677
|
+
display: inline-flex;
|
|
2678
|
+
align-items: center;
|
|
2679
|
+
gap: 9px;
|
|
2680
|
+
padding: 0 16px;
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
.eos-assist-launcher span:first-child { font-size: 21px; }
|
|
2684
|
+
|
|
2685
|
+
.eos-assist-panel {
|
|
2686
|
+
position: fixed;
|
|
2687
|
+
right: 24px;
|
|
2688
|
+
bottom: 88px;
|
|
2689
|
+
z-index: 1901;
|
|
2690
|
+
width: min(430px, calc(100vw - 32px));
|
|
2691
|
+
max-height: min(720px, calc(100vh - 116px));
|
|
2692
|
+
display: none;
|
|
2693
|
+
flex-direction: column;
|
|
2694
|
+
border-radius: 24px;
|
|
2695
|
+
overflow: hidden;
|
|
2696
|
+
border: 1px solid rgba(0,255,136,.42);
|
|
2697
|
+
background:
|
|
2698
|
+
radial-gradient(circle at 18% 0%, rgba(0,255,136,.16), transparent 38%),
|
|
2699
|
+
linear-gradient(180deg, rgba(8, 30, 45, .98), rgba(2, 9, 20, .98));
|
|
2700
|
+
box-shadow: 0 26px 72px rgba(0,0,0,.58), 0 0 34px rgba(0,255,136,.14);
|
|
2701
|
+
color: var(--eos-text);
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
.eos-assist-open .eos-assist-panel { display: flex; }
|
|
2705
|
+
|
|
2706
|
+
.eos-assist-head {
|
|
2707
|
+
display: grid;
|
|
2708
|
+
grid-template-columns: 48px 1fr 40px;
|
|
2709
|
+
gap: 12px;
|
|
2710
|
+
align-items: center;
|
|
2711
|
+
padding: 16px;
|
|
2712
|
+
border-bottom: 1px solid rgba(0,255,136,.22);
|
|
2713
|
+
background: rgba(0,0,0,.22);
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
.eos-assist-logo {
|
|
2717
|
+
width: 48px;
|
|
2718
|
+
height: 48px;
|
|
2719
|
+
border-radius: 16px;
|
|
2720
|
+
display: grid;
|
|
2721
|
+
place-items: center;
|
|
2722
|
+
background: #000;
|
|
2723
|
+
border: 1px solid rgba(111,255,215,.62);
|
|
2724
|
+
box-shadow: inset 0 0 18px rgba(0,255,136,.12), 0 0 18px rgba(0,255,136,.24);
|
|
2725
|
+
}
|
|
2726
|
+
.eos-assist-logo img { width: 42px; height: 42px; object-fit: contain; filter: brightness(1.9) saturate(1.35) drop-shadow(0 0 8px rgba(0,255,136,.65)); }
|
|
2727
|
+
|
|
2728
|
+
.eos-assist-head strong { display:block; font-size: 16px; font-weight: 950; }
|
|
2729
|
+
.eos-assist-head small { display:block; margin-top: 3px; color: rgba(226,246,255,.70); font-weight: 700; letter-spacing: .03em; }
|
|
2730
|
+
.eos-assist-close { border:0; background: rgba(255,255,255,.06); color: #fff; border-radius: 14px; height: 40px; cursor:pointer; font-size:20px; }
|
|
2731
|
+
|
|
2732
|
+
.eos-assist-body { padding: 15px; overflow: auto; display:flex; flex-direction:column; gap: 12px; }
|
|
2733
|
+
.eos-assist-card { border-radius: 18px; border: 1px solid rgba(123,204,255,.16); background: rgba(3,15,26,.70); padding: 13px; }
|
|
2734
|
+
.eos-assist-card strong { color: #efffff; }
|
|
2735
|
+
.eos-assist-card p { margin: 7px 0 0; color: rgba(226,246,255,.76); line-height: 1.42; }
|
|
2736
|
+
.eos-assist-actions { display:grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
2737
|
+
.eos-assist-actions button,
|
|
2738
|
+
.eos-assist-send {
|
|
2739
|
+
border: 1px solid rgba(0,255,136,.30);
|
|
2740
|
+
background: rgba(0,255,136,.09);
|
|
2741
|
+
color: #eefcff;
|
|
2742
|
+
border-radius: 13px;
|
|
2743
|
+
min-height: 38px;
|
|
2744
|
+
font-weight: 800;
|
|
2745
|
+
cursor: pointer;
|
|
2746
|
+
}
|
|
2747
|
+
.eos-assist-actions button:hover,
|
|
2748
|
+
.eos-assist-send:hover { background: rgba(0,255,136,.16); }
|
|
2749
|
+
.eos-assist-input-row { display:grid; grid-template-columns: 1fr 84px; gap: 8px; }
|
|
2750
|
+
.eos-assist-input { min-height: 40px; border-radius: 14px; border: 1px solid rgba(123,204,255,.22); background: rgba(2,9,20,.78); color: #fff; padding: 0 12px; outline: none; }
|
|
2751
|
+
.eos-assist-answer { white-space: pre-line; font-size: 13px; line-height: 1.45; color: rgba(237,251,255,.90); }
|
|
2752
|
+
.eos-assist-answer ul { margin: 8px 0 0 18px; padding: 0; }
|
|
2753
|
+
.eos-assist-answer li { margin: 4px 0; }
|
|
2754
|
+
.eos-assist-foot { color: rgba(226,246,255,.55); font-size: 11px; padding-top: 2px; }
|
|
2755
|
+
|
|
2756
|
+
@media (max-width: 760px) {
|
|
2757
|
+
.eos-assist-launcher { right: 14px; bottom: 14px; padding: 0 12px; }
|
|
2758
|
+
.eos-assist-panel { right: 14px; bottom: 78px; }
|
|
2759
|
+
.eos-assist-actions { grid-template-columns: 1fr; }
|
|
2760
|
+
}
|
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=27" />
|
|
35
35
|
<link
|
|
36
36
|
rel="manifest"
|
|
37
37
|
href="manifest.json"
|
|
@@ -154,8 +154,9 @@
|
|
|
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=
|
|
157
|
+
<script defer src="./js/eos-branding.js?v=27"></script>
|
|
158
|
+
<script defer src="./js/eos-security-ui.js?v=27"></script>
|
|
159
|
+
<script defer src="./js/eos-assistant.js?v=27"></script>
|
|
159
160
|
</head>
|
|
160
161
|
<body>
|
|
161
162
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
window.NEXOWATT_EOS_ASSIST_VERSION = 'v27-local-setup-guide';
|
|
5
|
+
|
|
6
|
+
const ASSET_BASE = (() => {
|
|
7
|
+
const script = document.currentScript?.src || document.querySelector('script[src*="eos-assistant.js"]')?.src || window.location.href;
|
|
8
|
+
return new URL('../', script).href;
|
|
9
|
+
})();
|
|
10
|
+
const asset = path => new URL(path.replace(/^\.\//, ''), ASSET_BASE).href;
|
|
11
|
+
const LOGO = asset('img/eos/nexowatt-192.png');
|
|
12
|
+
const STORE_KEY = 'nexowatt.eos.assist.open';
|
|
13
|
+
const state = { checked: false, allowed: true };
|
|
14
|
+
|
|
15
|
+
const fetchAssistantPolicy = async () => {
|
|
16
|
+
if (state.checked) return state.allowed;
|
|
17
|
+
state.checked = true;
|
|
18
|
+
try {
|
|
19
|
+
const url = new URL('eos/security/status', ASSET_BASE).href;
|
|
20
|
+
const response = await fetch(url, { credentials: 'same-origin', cache: 'no-store' });
|
|
21
|
+
if (!response.ok) return state.allowed;
|
|
22
|
+
const json = await response.json();
|
|
23
|
+
const assistant = json.assistant || {};
|
|
24
|
+
const enabled = assistant.enabled !== false && json.eosAssistantEnabled !== false;
|
|
25
|
+
const adminOnly = assistant.adminOnly === true || json.eosAssistantAdminOnly === true;
|
|
26
|
+
const isAdmin = json.isAdmin === true || json.isAdministrator === true || json.isEosAdminGroup === true;
|
|
27
|
+
state.allowed = enabled && (!adminOnly || isAdmin);
|
|
28
|
+
} catch {
|
|
29
|
+
state.allowed = true;
|
|
30
|
+
}
|
|
31
|
+
return state.allowed;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const normalize = value => String(value || '')
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.normalize('NFD')
|
|
37
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
38
|
+
.replace(/\s+/g, ' ')
|
|
39
|
+
.trim();
|
|
40
|
+
|
|
41
|
+
const route = () => {
|
|
42
|
+
const hash = window.location.hash || '';
|
|
43
|
+
const text = normalize(document.body?.innerText || '');
|
|
44
|
+
if (hash.includes('tab-adapters') || /module|adapter/.test(text.slice(0, 4000))) return 'modules';
|
|
45
|
+
if (hash.includes('tab-instances') || /dienste|instanzen/.test(text.slice(0, 4000))) return 'services';
|
|
46
|
+
if (hash.includes('tab-logs') || /systemlogs|protokolle|log-grosse/.test(text.slice(0, 4000))) return 'logs';
|
|
47
|
+
if (hash.includes('tab-users') || /zugange & rechte|benutzer|rollen/.test(text.slice(0, 4000))) return 'rights';
|
|
48
|
+
if (hash.includes('tab-objects') || /datenpunkte|objekte/.test(text.slice(0, 4000))) return 'objects';
|
|
49
|
+
if (hash.includes('tab-hosts') || /system-hosts|hosts/.test(text.slice(0, 4000))) return 'hosts';
|
|
50
|
+
return 'overview';
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const contextTitle = () => ({
|
|
54
|
+
modules: 'Module & Adapter',
|
|
55
|
+
services: 'Dienste & Instanzen',
|
|
56
|
+
logs: 'Systemlogs',
|
|
57
|
+
rights: 'Zugänge & Rechte',
|
|
58
|
+
objects: 'Datenpunkte',
|
|
59
|
+
hosts: 'System-Hosts',
|
|
60
|
+
overview: 'EOS Cockpit',
|
|
61
|
+
}[route()] || 'EOS Cockpit');
|
|
62
|
+
|
|
63
|
+
const routeAdvice = () => ({
|
|
64
|
+
modules: 'Hier installierst und aktualisierst du Module. Prüfe vor einer Installation immer: Zweck, benötigte Instanzen, Version, Abhängigkeiten und ob das Modul zu den geschützten EOS-Komponenten gehört.',
|
|
65
|
+
services: 'Hier siehst du laufende Dienste. Wichtig sind Status, Speicherverbrauch, Log-Level und ob eine Instanz automatisch startet. Fehlerhafte Dienste zuerst öffnen, Log prüfen, dann gezielt neu starten.',
|
|
66
|
+
logs: 'Hier erkennst du die Ursache vieler Probleme. Filtere nach Quelle und Level. Wiederholte Warnungen sind meist wichtiger als einzelne Meldungen.',
|
|
67
|
+
rights: 'Hier steuerst du Rollen und Benutzer. Installateur- und Endkundenrollen sollten keine geschützten EOS-Systemmodule löschen, stoppen oder aktivieren können.',
|
|
68
|
+
objects: 'Datenpunkte sind die technische Basis. Ändere Rollen, States und Alias-Strukturen nur bewusst, weil Adapter und Visualisierungen davon abhängen.',
|
|
69
|
+
hosts: 'Hier prüfst du Systemlast, Node.js, npm, Speicher und laufende Prozesse. Bei Updateproblemen zuerst Host-Status und freien Speicher prüfen.',
|
|
70
|
+
overview: 'Das Cockpit gibt den Überblick. Starte von hier aus mit Modulen, Diensten, Logs oder Rechten, je nachdem ob du einrichten, prüfen oder absichern möchtest.',
|
|
71
|
+
}[route()] || 'Wähle einen Bereich aus, dann kann EOS Assist dir die nächsten Schritte erklären.');
|
|
72
|
+
|
|
73
|
+
const answerFor = question => {
|
|
74
|
+
const q = normalize(question);
|
|
75
|
+
const r = route();
|
|
76
|
+
if (!q) return `Aktueller Bereich: ${contextTitle()}\n\n${routeAdvice()}\n\nDu kannst z. B. fragen: „Wie richte ich Modbus ein?“, „Warum ist ein Dienst rot?“ oder „Welche Rechte braucht der Installateur?“`;
|
|
77
|
+
|
|
78
|
+
if (/modbus|wechselrichter|tcp|rs485/.test(q)) {
|
|
79
|
+
return 'Modbus-Einrichtung:\n1. Modul installieren und Instanz anlegen.\n2. IP/Port oder seriellen Adapter prüfen.\n3. Unit-ID, Registerbereich und Byte-Reihenfolge dokumentieren.\n4. Dienst starten und Systemlogs auf Timeout/CRC prüfen.\n5. Erst wenn Werte stabil laufen, Datenpunkte in EOS Cockpit verwenden.';
|
|
80
|
+
}
|
|
81
|
+
if (/shelly|relay|schalter|steckdose/.test(q)) {
|
|
82
|
+
return 'Shelly-/Schaltmodul-Einrichtung:\n1. Gerät im gleichen Netzwerk erreichbar machen.\n2. Authentifizierung im Gerät setzen, damit keine Warnung wie „not protected via restricted login“ entsteht.\n3. Adapterinstanz konfigurieren und neu starten.\n4. In Datenpunkten prüfen, ob Power, Energy und Relay-State sauber aktualisieren.';
|
|
83
|
+
}
|
|
84
|
+
if (/ev|wallbox|laden|ladepunkt|ocpp/.test(q)) {
|
|
85
|
+
return 'Ladepunkt-/EVCS-Einrichtung:\n1. OCPP/Wallbox-Modul installieren.\n2. Ladepunkt-ID, Endpoint und Authentifizierung prüfen.\n3. Dienst starten und Verbindung im Log kontrollieren.\n4. Danach Ladeleistung, Fahrzeugstatus und Freigabe-Datenpunkte mit dem EOS Energiemanagement verknüpfen.';
|
|
86
|
+
}
|
|
87
|
+
if (/backup|backitup|sicherung|restore/.test(q)) {
|
|
88
|
+
return 'Backup-Empfehlung:\n1. BackItUp bleibt ein geschütztes EOS-Systemmodul.\n2. Vor Updates immer ein Backup starten.\n3. Restore-Ziel und Speicherort prüfen.\n4. Installateur-/Endkundenrollen sollten BackItUp nicht löschen oder deaktivieren dürfen.';
|
|
89
|
+
}
|
|
90
|
+
if (/recht|rolle|benutzer|installateur|kunde|admin/.test(q)) {
|
|
91
|
+
return 'Rechte-Empfehlung:\n1. Administrator: volle Wartung und Systemschutz.\n2. Installateur: Module konfigurieren, aber geschützte Adapter nicht löschen.\n3. Endkunde: Bedienung und Ansicht, keine Systemmodule.\n4. Geschützte Adapter legt der Administrator im EOS-Sicherheitsbereich fest.';
|
|
92
|
+
}
|
|
93
|
+
if (/log|fehler|warn|error|timeout|offline/.test(q)) {
|
|
94
|
+
return 'Fehleranalyse:\n1. In Systemlogs nach Quelle und Level filtern.\n2. Wiederholte Meldungen priorisieren.\n3. Bei Timeout Netzwerk/IP/Port prüfen.\n4. Bei Auth-Warnungen Zugangsdaten im Gerät und Adapter vergleichen.\n5. Danach nur die betroffene Instanz neu starten, nicht das komplette System.';
|
|
95
|
+
}
|
|
96
|
+
if (/update|aktualisieren|npm|repository|repo/.test(q)) {
|
|
97
|
+
return 'Update-Prüfung:\n1. NexoWatt-Repository aktiv setzen.\n2. Version im Repository und npm vergleichen.\n3. Bei EOS Admin: iobroker upgrade eos-admin, danach iobroker upload eos-admin.\n4. Browser mit Strg+F5 neu laden.\n5. Vor größeren Updates Backup erstellen.';
|
|
98
|
+
}
|
|
99
|
+
if (/dienst|instanz|start|stop|neustart/.test(q)) {
|
|
100
|
+
return 'Dienst prüfen:\n1. Status ansehen: grün/läuft, rot/gestoppt, gelb/Warnung.\n2. Speicherverbrauch und Log-Level prüfen.\n3. Bei Fehlern zuerst Log öffnen.\n4. Dann Instanz neu starten.\n5. Wenn der Fehler wiederkommt, Konfiguration und Abhängigkeiten prüfen.';
|
|
101
|
+
}
|
|
102
|
+
return `Ich habe deine Frage lokal eingeordnet.\n\nBereich: ${contextTitle()}\n\nEmpfohlene nächsten Schritte:\n1. Ziel klären: installieren, konfigurieren, Fehler suchen oder absichern.\n2. Betroffenes Modul/Dienst auswählen.\n3. Logs und Status prüfen.\n4. Änderung speichern und nur die betroffene Instanz neu starten.\n\nHinweis: Diese erste EOS-Assistenz arbeitet lokal ohne Cloud. Eine echte KI-Anbindung kann später über einen NexoWatt- oder MCP-Dienst ergänzt werden.`;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const setOpen = open => {
|
|
106
|
+
document.documentElement.classList.toggle('eos-assist-open', !!open);
|
|
107
|
+
try { localStorage.setItem(STORE_KEY, open ? '1' : '0'); } catch { /* ignore */ }
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const renderAnswer = (panel, question) => {
|
|
111
|
+
const out = panel.querySelector('.eos-assist-answer');
|
|
112
|
+
if (out) out.textContent = answerFor(question);
|
|
113
|
+
const ctx = panel.querySelector('.eos-assist-context');
|
|
114
|
+
if (ctx) ctx.textContent = contextTitle();
|
|
115
|
+
const hint = panel.querySelector('.eos-assist-hint');
|
|
116
|
+
if (hint) hint.textContent = routeAdvice();
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const ensureAssistant = () => {
|
|
120
|
+
if (!document.body || document.querySelector('.eos-assist-launcher')) return;
|
|
121
|
+
if (document.documentElement.classList.contains('eos-login')) return;
|
|
122
|
+
if (!document.getElementById('app-paper')) return;
|
|
123
|
+
|
|
124
|
+
const launcher = document.createElement('button');
|
|
125
|
+
launcher.type = 'button';
|
|
126
|
+
launcher.className = 'eos-assist-launcher';
|
|
127
|
+
launcher.innerHTML = '<span>✦</span><span>EOS Assist</span>';
|
|
128
|
+
launcher.setAttribute('aria-label', 'EOS Assist öffnen');
|
|
129
|
+
|
|
130
|
+
const panel = document.createElement('aside');
|
|
131
|
+
panel.className = 'eos-assist-panel';
|
|
132
|
+
panel.setAttribute('aria-label', 'EOS Assist');
|
|
133
|
+
panel.innerHTML = `
|
|
134
|
+
<div class="eos-assist-head">
|
|
135
|
+
<span class="eos-assist-logo"><img src="${LOGO}" alt="NexoWatt EOS" /></span>
|
|
136
|
+
<span><strong>EOS Assist</strong><small><span class="eos-assist-context"></span> · geführte Einrichtung</small></span>
|
|
137
|
+
<button type="button" class="eos-assist-close" aria-label="Schließen">×</button>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="eos-assist-body">
|
|
140
|
+
<div class="eos-assist-card"><strong>Aktueller Hinweis</strong><p class="eos-assist-hint"></p></div>
|
|
141
|
+
<div class="eos-assist-actions">
|
|
142
|
+
<button type="button" data-question="Wie richte ich dieses Modul ein?">Modul einrichten</button>
|
|
143
|
+
<button type="button" data-question="Wie prüfe ich Fehler in den Logs?">Fehler prüfen</button>
|
|
144
|
+
<button type="button" data-question="Welche Rechte braucht der Installateur?">Rechte erklären</button>
|
|
145
|
+
<button type="button" data-question="Was muss ich vor einem Update beachten?">Update-Check</button>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="eos-assist-input-row">
|
|
148
|
+
<input class="eos-assist-input" type="text" placeholder="Frage eingeben, z. B. Modbus einrichten" />
|
|
149
|
+
<button type="button" class="eos-assist-send">Fragen</button>
|
|
150
|
+
</div>
|
|
151
|
+
<div class="eos-assist-card eos-assist-answer"></div>
|
|
152
|
+
<div class="eos-assist-foot">Lokale Assistenz ohne Cloud. Für echte KI-Automation kann später ein NexoWatt-Dienst angebunden werden.</div>
|
|
153
|
+
</div>
|
|
154
|
+
`;
|
|
155
|
+
|
|
156
|
+
document.body.appendChild(launcher);
|
|
157
|
+
document.body.appendChild(panel);
|
|
158
|
+
renderAnswer(panel, '');
|
|
159
|
+
|
|
160
|
+
launcher.addEventListener('click', () => setOpen(!document.documentElement.classList.contains('eos-assist-open')));
|
|
161
|
+
panel.querySelector('.eos-assist-close')?.addEventListener('click', () => setOpen(false));
|
|
162
|
+
panel.querySelector('.eos-assist-send')?.addEventListener('click', () => renderAnswer(panel, panel.querySelector('.eos-assist-input')?.value || ''));
|
|
163
|
+
panel.querySelector('.eos-assist-input')?.addEventListener('keydown', event => {
|
|
164
|
+
if (event.key === 'Enter') renderAnswer(panel, event.currentTarget.value || '');
|
|
165
|
+
});
|
|
166
|
+
panel.querySelectorAll('button[data-question]').forEach(button => {
|
|
167
|
+
button.addEventListener('click', () => {
|
|
168
|
+
const question = button.getAttribute('data-question') || '';
|
|
169
|
+
const input = panel.querySelector('.eos-assist-input');
|
|
170
|
+
if (input) input.value = question;
|
|
171
|
+
renderAnswer(panel, question);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
try { if (localStorage.getItem(STORE_KEY) === '1') setOpen(true); } catch { /* ignore */ }
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const removeOnLogin = () => {
|
|
179
|
+
if (!document.documentElement.classList.contains('eos-login')) return;
|
|
180
|
+
document.querySelectorAll('.eos-assist-launcher,.eos-assist-panel').forEach(el => el.remove());
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const run = () => {
|
|
184
|
+
removeOnLogin();
|
|
185
|
+
void fetchAssistantPolicy().then(allowed => {
|
|
186
|
+
if (!allowed) {
|
|
187
|
+
document.querySelectorAll('.eos-assist-launcher,.eos-assist-panel').forEach(el => el.remove());
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
ensureAssistant();
|
|
191
|
+
const panel = document.querySelector('.eos-assist-panel');
|
|
192
|
+
if (panel) renderAnswer(panel, panel.querySelector('.eos-assist-input')?.value || '');
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run, { once: true });
|
|
197
|
+
else run();
|
|
198
|
+
window.addEventListener('hashchange', () => setTimeout(run, 80));
|
|
199
|
+
window.addEventListener('load', () => setTimeout(run, 120), { once: true });
|
|
200
|
+
new MutationObserver(() => {
|
|
201
|
+
if (!document.querySelector('.eos-assist-launcher')) run();
|
|
202
|
+
}).observe(document.documentElement, { childList: true, subtree: true });
|
|
203
|
+
})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
window.NEXOWATT_EOS_UI_VERSION = '
|
|
4
|
+
window.NEXOWATT_EOS_UI_VERSION = 'v27-header-logo-nav-assist';
|
|
5
5
|
|
|
6
6
|
const BRAND = 'NexoWatt EOS';
|
|
7
7
|
const EOS_MEANING = 'Energy Operation System';
|
|
@@ -490,6 +490,44 @@
|
|
|
490
490
|
removeLogoutButton();
|
|
491
491
|
};
|
|
492
492
|
|
|
493
|
+
const NAV_COMPACT_KEY = 'nexowatt.eos.navCompact';
|
|
494
|
+
|
|
495
|
+
const setNavCompact = value => safe(() => {
|
|
496
|
+
const active = !!value;
|
|
497
|
+
document.documentElement.classList.toggle('eos-nav-compact', active);
|
|
498
|
+
window.localStorage && window.localStorage.setItem(NAV_COMPACT_KEY, active ? '1' : '0');
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const restoreNavCompact = () => safe(() => {
|
|
502
|
+
const saved = window.localStorage && window.localStorage.getItem(NAV_COMPACT_KEY);
|
|
503
|
+
if (saved === '1') document.documentElement.classList.add('eos-nav-compact');
|
|
504
|
+
if (saved === '0') document.documentElement.classList.remove('eos-nav-compact');
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
const bindCompactNavToggle = header => safe(() => {
|
|
508
|
+
if (!header) return;
|
|
509
|
+
restoreNavCompact();
|
|
510
|
+
const controls = Array.from(header.querySelectorAll('button, .MuiIconButton-root, [role="button"]'));
|
|
511
|
+
controls.forEach(control => {
|
|
512
|
+
if (control.dataset.eosCompactToggleBound === '1') return;
|
|
513
|
+
control.dataset.eosCompactToggleBound = '1';
|
|
514
|
+
control.setAttribute('title', 'Menü kompakt/erweitert anzeigen');
|
|
515
|
+
control.setAttribute('aria-label', 'Menü kompakt/erweitert anzeigen');
|
|
516
|
+
const toggle = event => {
|
|
517
|
+
event.preventDefault();
|
|
518
|
+
event.stopPropagation();
|
|
519
|
+
if (event.stopImmediatePropagation) event.stopImmediatePropagation();
|
|
520
|
+
setNavCompact(!document.documentElement.classList.contains('eos-nav-compact'));
|
|
521
|
+
scheduleFullPatch(0);
|
|
522
|
+
return false;
|
|
523
|
+
};
|
|
524
|
+
control.addEventListener('click', toggle, true);
|
|
525
|
+
control.addEventListener('keydown', event => {
|
|
526
|
+
if (event.key === 'Enter' || event.key === ' ') toggle(event);
|
|
527
|
+
}, true);
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
|
|
493
531
|
const hideNativeLogoutNav = () => safe(() => {
|
|
494
532
|
const candidates = Array.from(document.querySelectorAll('.MuiDrawer-paper a, .MuiDrawer-paper button, .MuiDrawer-paper .MuiListItem-root, .MuiDrawer-paper .MuiListItemButton-root, .MuiDrawer-paper [role=\"button\"]'));
|
|
495
533
|
candidates.forEach(el => {
|
|
@@ -518,6 +556,7 @@
|
|
|
518
556
|
}
|
|
519
557
|
if (header) {
|
|
520
558
|
header.classList.add('eos-native-drawer-header');
|
|
559
|
+
bindCompactNavToggle(header);
|
|
521
560
|
const img = header.querySelector('img');
|
|
522
561
|
if (img) patchImage(img);
|
|
523
562
|
const avatarImg = header.querySelector('.MuiAvatar-img');
|
|
@@ -820,6 +859,7 @@
|
|
|
820
859
|
});
|
|
821
860
|
|
|
822
861
|
forceLoginGlobals();
|
|
862
|
+
restoreNavCompact();
|
|
823
863
|
if (document.readyState === 'loading') {
|
|
824
864
|
document.addEventListener('DOMContentLoaded', () => {
|
|
825
865
|
fullPatch();
|
package/build/lib/web.js
CHANGED
|
@@ -491,6 +491,14 @@ class Web {
|
|
|
491
491
|
legacyAdminAdapter: 'admin',
|
|
492
492
|
legacyAdminInstance: 'admin.0',
|
|
493
493
|
protectedAdapters: this.getEosProtectedAdapterNames(),
|
|
494
|
+
eosAssistantEnabled: this.settings.eosAssistantEnabled !== false,
|
|
495
|
+
eosAssistantMode: this.settings.eosAssistantMode || 'local',
|
|
496
|
+
eosAssistantAdminOnly: this.settings.eosAssistantAdminOnly === true,
|
|
497
|
+
assistant: {
|
|
498
|
+
enabled: this.settings.eosAssistantEnabled !== false,
|
|
499
|
+
mode: this.settings.eosAssistantMode || 'local',
|
|
500
|
+
adminOnly: this.settings.eosAssistantAdminOnly === true,
|
|
501
|
+
},
|
|
494
502
|
});
|
|
495
503
|
}
|
|
496
504
|
|
|
@@ -721,6 +729,10 @@ class Web {
|
|
|
721
729
|
hideLegacyAdminFromNonAdmins: true,
|
|
722
730
|
restrictProtectedAdapterControls: true,
|
|
723
731
|
protectedAdapters: ['eos-admin'],
|
|
732
|
+
eosAssistantEnabled: true,
|
|
733
|
+
eosAssistantMode: 'local',
|
|
734
|
+
eosAssistantAdminOnly: false,
|
|
735
|
+
assistant: { enabled: true, mode: 'local', adminOnly: false },
|
|
724
736
|
});
|
|
725
737
|
});
|
|
726
738
|
};
|
package/io-package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "eos-admin",
|
|
4
|
-
"version": "7.9.
|
|
4
|
+
"version": "7.9.27",
|
|
5
5
|
"titleLang": {
|
|
6
6
|
"en": "NexoWatt EOS Admin",
|
|
7
7
|
"de": "NexoWatt EOS Admin",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"connectionType": "local",
|
|
19
19
|
"dataSource": "push",
|
|
20
20
|
"news": {
|
|
21
|
+
"7.9.27": {
|
|
22
|
+
"en": "Visual and usability update: logo gets a black high-contrast background, the horizontal navigation collapse control becomes a safe compact toggle, and EOS Assist adds guided setup help for modules and adapters.",
|
|
23
|
+
"de": "Optik- und Bedienupdate: Logo mit schwarzem Kontrast-Hintergrund, der Navigationspfeil schaltet nur noch eine sichere Kompaktansicht, und EOS Assist ergänzt geführte Hilfe für Module und Adapter."
|
|
24
|
+
},
|
|
21
25
|
"7.9.26": {
|
|
22
26
|
"en": "Visual polish: strengthened the NexoWatt EOS header logo and improved account-name contrast in the top bar.",
|
|
23
27
|
"de": "Optischer Feinschliff: NexoWatt-EOS-Headerlogo deutlicher sichtbar und Kontoname in der oberen Leiste kontrastreicher."
|
|
@@ -325,7 +329,10 @@
|
|
|
325
329
|
}
|
|
326
330
|
],
|
|
327
331
|
"eosAdminOnlyGroup": "system.group.administrator",
|
|
328
|
-
"eosApplyAdminOnlyAclToProtectedAdapters": true
|
|
332
|
+
"eosApplyAdminOnlyAclToProtectedAdapters": true,
|
|
333
|
+
"eosAssistantEnabled": true,
|
|
334
|
+
"eosAssistantMode": "local",
|
|
335
|
+
"eosAssistantAdminOnly": false
|
|
329
336
|
},
|
|
330
337
|
"notifications": [
|
|
331
338
|
{
|