iobroker.eos-admin 7.9.79 → 7.9.83

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.
Files changed (593) hide show
  1. package/adminWww/assets/{Adapters-B5_jQ7DE-v79.js → Adapters-B5_jQ7DE-v82.js} +1 -1
  2. package/adminWww/assets/{CustomTab-B0wqoazH-v79.js → CustomTab-B0wqoazH-v82.js} +1 -1
  3. package/adminWww/assets/{DeviceManager-BFmQeYQ1-v79.js → DeviceManager-BFmQeYQ1-v82.js} +1 -1
  4. package/adminWww/assets/{EasyMode-B1d9Vdc4-v79.js → EasyMode-B1d9Vdc4-v82.js} +1 -1
  5. package/adminWww/assets/{Enums-DbWYxKOo-v79.js → Enums-DbWYxKOo-v82.js} +1 -1
  6. package/adminWww/assets/{Files-Cd2HOzIE-v79.js → Files-Cd2HOzIE-v82.js} +1 -1
  7. package/adminWww/assets/{Hosts-Bg8QzW5i-v79.js → Hosts-Bg8QzW5i-v82.js} +1 -1
  8. package/adminWww/assets/{Instances-YdaGnS5a-v79.js → Instances-YdaGnS5a-v82.js} +1 -1
  9. package/adminWww/assets/{Intro-DkwRiz1n-v79.js → Intro-DkwRiz1n-v82.js} +1 -1
  10. package/adminWww/assets/{Logs-CsVPSLJH-v79.js → Logs-CsVPSLJH-v82.js} +1 -1
  11. package/adminWww/assets/{Objects-DPan0bzw-v79.js → Objects-DPan0bzw-v82.js} +1 -1
  12. package/adminWww/assets/{Users-BgnBRgwU-v79.js → Users-BgnBRgwU-v82.js} +1 -1
  13. package/adminWww/assets/{bootstrap-COulQZax-v79.js → bootstrap-COulQZax-v82.js} +3 -3
  14. package/adminWww/assets/{hostInit-v79.js → hostInit-v82.js} +2 -2
  15. package/adminWww/assets/{index-CQZugZ1z-v79.js → index-CQZugZ1z-v82.js} +2 -2
  16. package/adminWww/css/nexowatt-native-shell.css +471 -0
  17. package/adminWww/index.html +10 -11
  18. package/adminWww/js/eos-assistant.js +104 -3
  19. package/adminWww/js/eos-manual-write-policy.js +1 -1
  20. package/adminWww/js/eos-native-security.js +45 -0
  21. package/adminWww/js/eos-policy-client.js +1 -1
  22. package/adminWww/js/eos-role-ui.js +1 -1
  23. package/adminWww/js/nexowatt-native-shell.js +196 -0
  24. package/adminWww/mf-manifest.json +1 -1
  25. package/adminWww/{remoteEntry-v79.js → remoteEntry-v82.js} +2 -2
  26. package/adminWww/remoteEntry.js +1 -1
  27. package/io-package.json +10 -5
  28. package/package.json +11 -5
  29. package/tools/nexowatt-clean-legacy-runtime.cjs +147 -0
  30. package/tools/nexowatt-runtime-cleanup-selftest.cjs +47 -0
  31. package/tools/nexowatt-validate-package.cjs +119 -44
  32. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v54.js +0 -1
  33. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v55.js +0 -1
  34. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v56.js +0 -1
  35. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v57.js +0 -1
  36. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v58.js +0 -1
  37. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v59.js +0 -1
  38. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v60.js +0 -1
  39. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v61.js +0 -1
  40. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v62.js +0 -1
  41. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v63.js +0 -1
  42. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v64.js +0 -1
  43. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v65.js +0 -1
  44. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v66.js +0 -1
  45. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v67.js +0 -1
  46. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v68.js +0 -1
  47. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v69.js +0 -1
  48. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v70.js +0 -1
  49. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v71.js +0 -1
  50. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v72.js +0 -1
  51. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v73.js +0 -1
  52. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v74.js +0 -1
  53. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v75.js +0 -1
  54. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v76.js +0 -1
  55. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v77.js +0 -1
  56. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v78.js +0 -1
  57. package/adminWww/assets/AdapterUpdateDialog-BMg84Hpf-v79.js +0 -2
  58. package/adminWww/assets/Adapters-B5_jQ7DE-v54.js +0 -1
  59. package/adminWww/assets/Adapters-B5_jQ7DE-v55.js +0 -1
  60. package/adminWww/assets/Adapters-B5_jQ7DE-v56.js +0 -1
  61. package/adminWww/assets/Adapters-B5_jQ7DE-v57.js +0 -1
  62. package/adminWww/assets/Adapters-B5_jQ7DE-v58.js +0 -1
  63. package/adminWww/assets/Adapters-B5_jQ7DE-v59.js +0 -1
  64. package/adminWww/assets/Adapters-B5_jQ7DE-v60.js +0 -1
  65. package/adminWww/assets/Adapters-B5_jQ7DE-v61.js +0 -1
  66. package/adminWww/assets/Adapters-B5_jQ7DE-v62.js +0 -1
  67. package/adminWww/assets/Adapters-B5_jQ7DE-v63.js +0 -1
  68. package/adminWww/assets/Adapters-B5_jQ7DE-v64.js +0 -1
  69. package/adminWww/assets/Adapters-B5_jQ7DE-v65.js +0 -1
  70. package/adminWww/assets/Adapters-B5_jQ7DE-v66.js +0 -1
  71. package/adminWww/assets/Adapters-B5_jQ7DE-v67.js +0 -1
  72. package/adminWww/assets/Adapters-B5_jQ7DE-v68.js +0 -1
  73. package/adminWww/assets/Adapters-B5_jQ7DE-v69.js +0 -1
  74. package/adminWww/assets/Adapters-B5_jQ7DE-v70.js +0 -1
  75. package/adminWww/assets/Adapters-B5_jQ7DE-v71.js +0 -1
  76. package/adminWww/assets/Adapters-B5_jQ7DE-v72.js +0 -1
  77. package/adminWww/assets/Adapters-B5_jQ7DE-v73.js +0 -1
  78. package/adminWww/assets/Adapters-B5_jQ7DE-v74.js +0 -1
  79. package/adminWww/assets/Adapters-B5_jQ7DE-v75.js +0 -1
  80. package/adminWww/assets/Adapters-B5_jQ7DE-v76.js +0 -1
  81. package/adminWww/assets/Adapters-B5_jQ7DE-v77.js +0 -1
  82. package/adminWww/assets/Adapters-B5_jQ7DE-v78.js +0 -1
  83. package/adminWww/assets/Config-hHK2UzGP-v54.js +0 -1
  84. package/adminWww/assets/Config-hHK2UzGP-v55.js +0 -1
  85. package/adminWww/assets/Config-hHK2UzGP-v56.js +0 -1
  86. package/adminWww/assets/Config-hHK2UzGP-v57.js +0 -1
  87. package/adminWww/assets/Config-hHK2UzGP-v58.js +0 -1
  88. package/adminWww/assets/Config-hHK2UzGP-v59.js +0 -1
  89. package/adminWww/assets/Config-hHK2UzGP-v60.js +0 -1
  90. package/adminWww/assets/Config-hHK2UzGP-v61.js +0 -1
  91. package/adminWww/assets/Config-hHK2UzGP-v62.js +0 -1
  92. package/adminWww/assets/Config-hHK2UzGP-v63.js +0 -1
  93. package/adminWww/assets/Config-hHK2UzGP-v64.js +0 -1
  94. package/adminWww/assets/Config-hHK2UzGP-v65.js +0 -1
  95. package/adminWww/assets/Config-hHK2UzGP-v66.js +0 -1
  96. package/adminWww/assets/Config-hHK2UzGP-v67.js +0 -1
  97. package/adminWww/assets/Config-hHK2UzGP-v68.js +0 -1
  98. package/adminWww/assets/Config-hHK2UzGP-v69.js +0 -1
  99. package/adminWww/assets/Config-hHK2UzGP-v70.js +0 -1
  100. package/adminWww/assets/Config-hHK2UzGP-v71.js +0 -1
  101. package/adminWww/assets/Config-hHK2UzGP-v72.js +0 -1
  102. package/adminWww/assets/Config-hHK2UzGP-v73.js +0 -1
  103. package/adminWww/assets/Config-hHK2UzGP-v74.js +0 -1
  104. package/adminWww/assets/Config-hHK2UzGP-v75.js +0 -1
  105. package/adminWww/assets/Config-hHK2UzGP-v76.js +0 -1
  106. package/adminWww/assets/Config-hHK2UzGP-v77.js +0 -1
  107. package/adminWww/assets/Config-hHK2UzGP-v78.js +0 -1
  108. package/adminWww/assets/Config-hHK2UzGP-v79.js +0 -1
  109. package/adminWww/assets/CustomTab-B0wqoazH-v54.js +0 -1
  110. package/adminWww/assets/CustomTab-B0wqoazH-v55.js +0 -1
  111. package/adminWww/assets/CustomTab-B0wqoazH-v56.js +0 -1
  112. package/adminWww/assets/CustomTab-B0wqoazH-v57.js +0 -1
  113. package/adminWww/assets/CustomTab-B0wqoazH-v58.js +0 -1
  114. package/adminWww/assets/CustomTab-B0wqoazH-v59.js +0 -1
  115. package/adminWww/assets/CustomTab-B0wqoazH-v60.js +0 -1
  116. package/adminWww/assets/CustomTab-B0wqoazH-v61.js +0 -1
  117. package/adminWww/assets/CustomTab-B0wqoazH-v62.js +0 -1
  118. package/adminWww/assets/CustomTab-B0wqoazH-v63.js +0 -1
  119. package/adminWww/assets/CustomTab-B0wqoazH-v64.js +0 -1
  120. package/adminWww/assets/CustomTab-B0wqoazH-v65.js +0 -1
  121. package/adminWww/assets/CustomTab-B0wqoazH-v66.js +0 -1
  122. package/adminWww/assets/CustomTab-B0wqoazH-v67.js +0 -1
  123. package/adminWww/assets/CustomTab-B0wqoazH-v68.js +0 -1
  124. package/adminWww/assets/CustomTab-B0wqoazH-v69.js +0 -1
  125. package/adminWww/assets/CustomTab-B0wqoazH-v70.js +0 -1
  126. package/adminWww/assets/CustomTab-B0wqoazH-v71.js +0 -1
  127. package/adminWww/assets/CustomTab-B0wqoazH-v72.js +0 -1
  128. package/adminWww/assets/CustomTab-B0wqoazH-v73.js +0 -1
  129. package/adminWww/assets/CustomTab-B0wqoazH-v74.js +0 -1
  130. package/adminWww/assets/CustomTab-B0wqoazH-v75.js +0 -1
  131. package/adminWww/assets/CustomTab-B0wqoazH-v76.js +0 -1
  132. package/adminWww/assets/CustomTab-B0wqoazH-v77.js +0 -1
  133. package/adminWww/assets/CustomTab-B0wqoazH-v78.js +0 -1
  134. package/adminWww/assets/DeviceManager-BFmQeYQ1-v54.js +0 -1
  135. package/adminWww/assets/DeviceManager-BFmQeYQ1-v55.js +0 -1
  136. package/adminWww/assets/DeviceManager-BFmQeYQ1-v56.js +0 -1
  137. package/adminWww/assets/DeviceManager-BFmQeYQ1-v57.js +0 -1
  138. package/adminWww/assets/DeviceManager-BFmQeYQ1-v58.js +0 -1
  139. package/adminWww/assets/DeviceManager-BFmQeYQ1-v59.js +0 -1
  140. package/adminWww/assets/DeviceManager-BFmQeYQ1-v60.js +0 -1
  141. package/adminWww/assets/DeviceManager-BFmQeYQ1-v61.js +0 -1
  142. package/adminWww/assets/DeviceManager-BFmQeYQ1-v62.js +0 -1
  143. package/adminWww/assets/DeviceManager-BFmQeYQ1-v63.js +0 -1
  144. package/adminWww/assets/DeviceManager-BFmQeYQ1-v64.js +0 -1
  145. package/adminWww/assets/DeviceManager-BFmQeYQ1-v65.js +0 -1
  146. package/adminWww/assets/DeviceManager-BFmQeYQ1-v66.js +0 -1
  147. package/adminWww/assets/DeviceManager-BFmQeYQ1-v67.js +0 -1
  148. package/adminWww/assets/DeviceManager-BFmQeYQ1-v68.js +0 -1
  149. package/adminWww/assets/DeviceManager-BFmQeYQ1-v69.js +0 -1
  150. package/adminWww/assets/DeviceManager-BFmQeYQ1-v70.js +0 -1
  151. package/adminWww/assets/DeviceManager-BFmQeYQ1-v71.js +0 -1
  152. package/adminWww/assets/DeviceManager-BFmQeYQ1-v72.js +0 -1
  153. package/adminWww/assets/DeviceManager-BFmQeYQ1-v73.js +0 -1
  154. package/adminWww/assets/DeviceManager-BFmQeYQ1-v74.js +0 -1
  155. package/adminWww/assets/DeviceManager-BFmQeYQ1-v75.js +0 -1
  156. package/adminWww/assets/DeviceManager-BFmQeYQ1-v76.js +0 -1
  157. package/adminWww/assets/DeviceManager-BFmQeYQ1-v77.js +0 -1
  158. package/adminWww/assets/DeviceManager-BFmQeYQ1-v78.js +0 -1
  159. package/adminWww/assets/EasyMode-B1d9Vdc4-v54.js +0 -1
  160. package/adminWww/assets/EasyMode-B1d9Vdc4-v55.js +0 -1
  161. package/adminWww/assets/EasyMode-B1d9Vdc4-v56.js +0 -1
  162. package/adminWww/assets/EasyMode-B1d9Vdc4-v57.js +0 -1
  163. package/adminWww/assets/EasyMode-B1d9Vdc4-v58.js +0 -1
  164. package/adminWww/assets/EasyMode-B1d9Vdc4-v59.js +0 -1
  165. package/adminWww/assets/EasyMode-B1d9Vdc4-v60.js +0 -1
  166. package/adminWww/assets/EasyMode-B1d9Vdc4-v61.js +0 -1
  167. package/adminWww/assets/EasyMode-B1d9Vdc4-v62.js +0 -1
  168. package/adminWww/assets/EasyMode-B1d9Vdc4-v63.js +0 -1
  169. package/adminWww/assets/EasyMode-B1d9Vdc4-v64.js +0 -1
  170. package/adminWww/assets/EasyMode-B1d9Vdc4-v65.js +0 -1
  171. package/adminWww/assets/EasyMode-B1d9Vdc4-v66.js +0 -1
  172. package/adminWww/assets/EasyMode-B1d9Vdc4-v67.js +0 -1
  173. package/adminWww/assets/EasyMode-B1d9Vdc4-v68.js +0 -1
  174. package/adminWww/assets/EasyMode-B1d9Vdc4-v69.js +0 -1
  175. package/adminWww/assets/EasyMode-B1d9Vdc4-v70.js +0 -1
  176. package/adminWww/assets/EasyMode-B1d9Vdc4-v71.js +0 -1
  177. package/adminWww/assets/EasyMode-B1d9Vdc4-v72.js +0 -1
  178. package/adminWww/assets/EasyMode-B1d9Vdc4-v73.js +0 -1
  179. package/adminWww/assets/EasyMode-B1d9Vdc4-v74.js +0 -1
  180. package/adminWww/assets/EasyMode-B1d9Vdc4-v75.js +0 -1
  181. package/adminWww/assets/EasyMode-B1d9Vdc4-v76.js +0 -1
  182. package/adminWww/assets/EasyMode-B1d9Vdc4-v77.js +0 -1
  183. package/adminWww/assets/EasyMode-B1d9Vdc4-v78.js +0 -1
  184. package/adminWww/assets/Enums-DbWYxKOo-v54.js +0 -1
  185. package/adminWww/assets/Enums-DbWYxKOo-v55.js +0 -1
  186. package/adminWww/assets/Enums-DbWYxKOo-v56.js +0 -1
  187. package/adminWww/assets/Enums-DbWYxKOo-v57.js +0 -1
  188. package/adminWww/assets/Enums-DbWYxKOo-v58.js +0 -1
  189. package/adminWww/assets/Enums-DbWYxKOo-v59.js +0 -1
  190. package/adminWww/assets/Enums-DbWYxKOo-v60.js +0 -1
  191. package/adminWww/assets/Enums-DbWYxKOo-v61.js +0 -1
  192. package/adminWww/assets/Enums-DbWYxKOo-v62.js +0 -1
  193. package/adminWww/assets/Enums-DbWYxKOo-v63.js +0 -1
  194. package/adminWww/assets/Enums-DbWYxKOo-v64.js +0 -1
  195. package/adminWww/assets/Enums-DbWYxKOo-v65.js +0 -1
  196. package/adminWww/assets/Enums-DbWYxKOo-v66.js +0 -1
  197. package/adminWww/assets/Enums-DbWYxKOo-v67.js +0 -1
  198. package/adminWww/assets/Enums-DbWYxKOo-v68.js +0 -1
  199. package/adminWww/assets/Enums-DbWYxKOo-v69.js +0 -1
  200. package/adminWww/assets/Enums-DbWYxKOo-v70.js +0 -1
  201. package/adminWww/assets/Enums-DbWYxKOo-v71.js +0 -1
  202. package/adminWww/assets/Enums-DbWYxKOo-v72.js +0 -1
  203. package/adminWww/assets/Enums-DbWYxKOo-v73.js +0 -1
  204. package/adminWww/assets/Enums-DbWYxKOo-v74.js +0 -1
  205. package/adminWww/assets/Enums-DbWYxKOo-v75.js +0 -1
  206. package/adminWww/assets/Enums-DbWYxKOo-v76.js +0 -1
  207. package/adminWww/assets/Enums-DbWYxKOo-v77.js +0 -1
  208. package/adminWww/assets/Enums-DbWYxKOo-v78.js +0 -1
  209. package/adminWww/assets/Fields-CX3rKuWb-v54.js +0 -1
  210. package/adminWww/assets/Fields-CX3rKuWb-v55.js +0 -1
  211. package/adminWww/assets/Fields-CX3rKuWb-v56.js +0 -1
  212. package/adminWww/assets/Fields-CX3rKuWb-v57.js +0 -1
  213. package/adminWww/assets/Fields-CX3rKuWb-v58.js +0 -1
  214. package/adminWww/assets/Fields-CX3rKuWb-v59.js +0 -1
  215. package/adminWww/assets/Fields-CX3rKuWb-v60.js +0 -1
  216. package/adminWww/assets/Fields-CX3rKuWb-v61.js +0 -1
  217. package/adminWww/assets/Fields-CX3rKuWb-v62.js +0 -1
  218. package/adminWww/assets/Fields-CX3rKuWb-v63.js +0 -1
  219. package/adminWww/assets/Fields-CX3rKuWb-v64.js +0 -1
  220. package/adminWww/assets/Fields-CX3rKuWb-v65.js +0 -1
  221. package/adminWww/assets/Fields-CX3rKuWb-v66.js +0 -1
  222. package/adminWww/assets/Fields-CX3rKuWb-v67.js +0 -1
  223. package/adminWww/assets/Fields-CX3rKuWb-v68.js +0 -1
  224. package/adminWww/assets/Fields-CX3rKuWb-v69.js +0 -1
  225. package/adminWww/assets/Fields-CX3rKuWb-v70.js +0 -1
  226. package/adminWww/assets/Fields-CX3rKuWb-v71.js +0 -1
  227. package/adminWww/assets/Fields-CX3rKuWb-v72.js +0 -1
  228. package/adminWww/assets/Fields-CX3rKuWb-v73.js +0 -1
  229. package/adminWww/assets/Fields-CX3rKuWb-v74.js +0 -1
  230. package/adminWww/assets/Fields-CX3rKuWb-v75.js +0 -1
  231. package/adminWww/assets/Fields-CX3rKuWb-v76.js +0 -1
  232. package/adminWww/assets/Fields-CX3rKuWb-v77.js +0 -1
  233. package/adminWww/assets/Fields-CX3rKuWb-v78.js +0 -1
  234. package/adminWww/assets/Fields-CX3rKuWb-v79.js +0 -1
  235. package/adminWww/assets/Files-Cd2HOzIE-v54.js +0 -1
  236. package/adminWww/assets/Files-Cd2HOzIE-v55.js +0 -1
  237. package/adminWww/assets/Files-Cd2HOzIE-v56.js +0 -1
  238. package/adminWww/assets/Files-Cd2HOzIE-v57.js +0 -1
  239. package/adminWww/assets/Files-Cd2HOzIE-v58.js +0 -1
  240. package/adminWww/assets/Files-Cd2HOzIE-v59.js +0 -1
  241. package/adminWww/assets/Files-Cd2HOzIE-v60.js +0 -1
  242. package/adminWww/assets/Files-Cd2HOzIE-v61.js +0 -1
  243. package/adminWww/assets/Files-Cd2HOzIE-v62.js +0 -1
  244. package/adminWww/assets/Files-Cd2HOzIE-v63.js +0 -1
  245. package/adminWww/assets/Files-Cd2HOzIE-v64.js +0 -1
  246. package/adminWww/assets/Files-Cd2HOzIE-v65.js +0 -1
  247. package/adminWww/assets/Files-Cd2HOzIE-v66.js +0 -1
  248. package/adminWww/assets/Files-Cd2HOzIE-v67.js +0 -1
  249. package/adminWww/assets/Files-Cd2HOzIE-v68.js +0 -1
  250. package/adminWww/assets/Files-Cd2HOzIE-v69.js +0 -1
  251. package/adminWww/assets/Files-Cd2HOzIE-v70.js +0 -1
  252. package/adminWww/assets/Files-Cd2HOzIE-v71.js +0 -1
  253. package/adminWww/assets/Files-Cd2HOzIE-v72.js +0 -1
  254. package/adminWww/assets/Files-Cd2HOzIE-v73.js +0 -1
  255. package/adminWww/assets/Files-Cd2HOzIE-v74.js +0 -1
  256. package/adminWww/assets/Files-Cd2HOzIE-v75.js +0 -1
  257. package/adminWww/assets/Files-Cd2HOzIE-v76.js +0 -1
  258. package/adminWww/assets/Files-Cd2HOzIE-v77.js +0 -1
  259. package/adminWww/assets/Files-Cd2HOzIE-v78.js +0 -1
  260. package/adminWww/assets/Hosts-Bg8QzW5i-v54.js +0 -1
  261. package/adminWww/assets/Hosts-Bg8QzW5i-v55.js +0 -1
  262. package/adminWww/assets/Hosts-Bg8QzW5i-v56.js +0 -1
  263. package/adminWww/assets/Hosts-Bg8QzW5i-v57.js +0 -1
  264. package/adminWww/assets/Hosts-Bg8QzW5i-v58.js +0 -1
  265. package/adminWww/assets/Hosts-Bg8QzW5i-v59.js +0 -1
  266. package/adminWww/assets/Hosts-Bg8QzW5i-v60.js +0 -1
  267. package/adminWww/assets/Hosts-Bg8QzW5i-v61.js +0 -1
  268. package/adminWww/assets/Hosts-Bg8QzW5i-v62.js +0 -1
  269. package/adminWww/assets/Hosts-Bg8QzW5i-v63.js +0 -1
  270. package/adminWww/assets/Hosts-Bg8QzW5i-v64.js +0 -1
  271. package/adminWww/assets/Hosts-Bg8QzW5i-v65.js +0 -1
  272. package/adminWww/assets/Hosts-Bg8QzW5i-v66.js +0 -1
  273. package/adminWww/assets/Hosts-Bg8QzW5i-v67.js +0 -1
  274. package/adminWww/assets/Hosts-Bg8QzW5i-v68.js +0 -1
  275. package/adminWww/assets/Hosts-Bg8QzW5i-v69.js +0 -1
  276. package/adminWww/assets/Hosts-Bg8QzW5i-v70.js +0 -1
  277. package/adminWww/assets/Hosts-Bg8QzW5i-v71.js +0 -1
  278. package/adminWww/assets/Hosts-Bg8QzW5i-v72.js +0 -1
  279. package/adminWww/assets/Hosts-Bg8QzW5i-v73.js +0 -1
  280. package/adminWww/assets/Hosts-Bg8QzW5i-v74.js +0 -1
  281. package/adminWww/assets/Hosts-Bg8QzW5i-v75.js +0 -1
  282. package/adminWww/assets/Hosts-Bg8QzW5i-v76.js +0 -1
  283. package/adminWww/assets/Hosts-Bg8QzW5i-v77.js +0 -1
  284. package/adminWww/assets/Hosts-Bg8QzW5i-v78.js +0 -1
  285. package/adminWww/assets/Instances-YdaGnS5a-v54.js +0 -1
  286. package/adminWww/assets/Instances-YdaGnS5a-v55.js +0 -1
  287. package/adminWww/assets/Instances-YdaGnS5a-v56.js +0 -1
  288. package/adminWww/assets/Instances-YdaGnS5a-v57.js +0 -1
  289. package/adminWww/assets/Instances-YdaGnS5a-v58.js +0 -1
  290. package/adminWww/assets/Instances-YdaGnS5a-v59.js +0 -1
  291. package/adminWww/assets/Instances-YdaGnS5a-v60.js +0 -1
  292. package/adminWww/assets/Instances-YdaGnS5a-v61.js +0 -1
  293. package/adminWww/assets/Instances-YdaGnS5a-v62.js +0 -1
  294. package/adminWww/assets/Instances-YdaGnS5a-v63.js +0 -1
  295. package/adminWww/assets/Instances-YdaGnS5a-v64.js +0 -1
  296. package/adminWww/assets/Instances-YdaGnS5a-v65.js +0 -1
  297. package/adminWww/assets/Instances-YdaGnS5a-v66.js +0 -1
  298. package/adminWww/assets/Instances-YdaGnS5a-v67.js +0 -1
  299. package/adminWww/assets/Instances-YdaGnS5a-v68.js +0 -1
  300. package/adminWww/assets/Instances-YdaGnS5a-v69.js +0 -1
  301. package/adminWww/assets/Instances-YdaGnS5a-v70.js +0 -1
  302. package/adminWww/assets/Instances-YdaGnS5a-v71.js +0 -1
  303. package/adminWww/assets/Instances-YdaGnS5a-v72.js +0 -1
  304. package/adminWww/assets/Instances-YdaGnS5a-v73.js +0 -1
  305. package/adminWww/assets/Instances-YdaGnS5a-v74.js +0 -1
  306. package/adminWww/assets/Instances-YdaGnS5a-v75.js +0 -1
  307. package/adminWww/assets/Instances-YdaGnS5a-v76.js +0 -1
  308. package/adminWww/assets/Instances-YdaGnS5a-v77.js +0 -1
  309. package/adminWww/assets/Instances-YdaGnS5a-v78.js +0 -1
  310. package/adminWww/assets/Intro-DkwRiz1n-v54.js +0 -1
  311. package/adminWww/assets/Intro-DkwRiz1n-v55.js +0 -1
  312. package/adminWww/assets/Intro-DkwRiz1n-v56.js +0 -1
  313. package/adminWww/assets/Intro-DkwRiz1n-v57.js +0 -1
  314. package/adminWww/assets/Intro-DkwRiz1n-v58.js +0 -1
  315. package/adminWww/assets/Intro-DkwRiz1n-v59.js +0 -1
  316. package/adminWww/assets/Intro-DkwRiz1n-v60.js +0 -1
  317. package/adminWww/assets/Intro-DkwRiz1n-v61.js +0 -1
  318. package/adminWww/assets/Intro-DkwRiz1n-v62.js +0 -1
  319. package/adminWww/assets/Intro-DkwRiz1n-v63.js +0 -1
  320. package/adminWww/assets/Intro-DkwRiz1n-v64.js +0 -1
  321. package/adminWww/assets/Intro-DkwRiz1n-v65.js +0 -1
  322. package/adminWww/assets/Intro-DkwRiz1n-v66.js +0 -1
  323. package/adminWww/assets/Intro-DkwRiz1n-v67.js +0 -1
  324. package/adminWww/assets/Intro-DkwRiz1n-v68.js +0 -1
  325. package/adminWww/assets/Intro-DkwRiz1n-v69.js +0 -1
  326. package/adminWww/assets/Intro-DkwRiz1n-v70.js +0 -1
  327. package/adminWww/assets/Intro-DkwRiz1n-v71.js +0 -1
  328. package/adminWww/assets/Intro-DkwRiz1n-v72.js +0 -1
  329. package/adminWww/assets/Intro-DkwRiz1n-v73.js +0 -1
  330. package/adminWww/assets/Intro-DkwRiz1n-v74.js +0 -1
  331. package/adminWww/assets/Intro-DkwRiz1n-v75.js +0 -1
  332. package/adminWww/assets/Intro-DkwRiz1n-v76.js +0 -1
  333. package/adminWww/assets/Intro-DkwRiz1n-v77.js +0 -1
  334. package/adminWww/assets/Intro-DkwRiz1n-v78.js +0 -1
  335. package/adminWww/assets/Logs-CsVPSLJH-v54.js +0 -1
  336. package/adminWww/assets/Logs-CsVPSLJH-v55.js +0 -1
  337. package/adminWww/assets/Logs-CsVPSLJH-v56.js +0 -1
  338. package/adminWww/assets/Logs-CsVPSLJH-v57.js +0 -1
  339. package/adminWww/assets/Logs-CsVPSLJH-v58.js +0 -1
  340. package/adminWww/assets/Logs-CsVPSLJH-v59.js +0 -1
  341. package/adminWww/assets/Logs-CsVPSLJH-v60.js +0 -1
  342. package/adminWww/assets/Logs-CsVPSLJH-v61.js +0 -1
  343. package/adminWww/assets/Logs-CsVPSLJH-v62.js +0 -1
  344. package/adminWww/assets/Logs-CsVPSLJH-v63.js +0 -1
  345. package/adminWww/assets/Logs-CsVPSLJH-v64.js +0 -1
  346. package/adminWww/assets/Logs-CsVPSLJH-v65.js +0 -1
  347. package/adminWww/assets/Logs-CsVPSLJH-v66.js +0 -1
  348. package/adminWww/assets/Logs-CsVPSLJH-v67.js +0 -1
  349. package/adminWww/assets/Logs-CsVPSLJH-v68.js +0 -1
  350. package/adminWww/assets/Logs-CsVPSLJH-v69.js +0 -1
  351. package/adminWww/assets/Logs-CsVPSLJH-v70.js +0 -1
  352. package/adminWww/assets/Logs-CsVPSLJH-v71.js +0 -1
  353. package/adminWww/assets/Logs-CsVPSLJH-v72.js +0 -1
  354. package/adminWww/assets/Logs-CsVPSLJH-v73.js +0 -1
  355. package/adminWww/assets/Logs-CsVPSLJH-v74.js +0 -1
  356. package/adminWww/assets/Logs-CsVPSLJH-v75.js +0 -1
  357. package/adminWww/assets/Logs-CsVPSLJH-v76.js +0 -1
  358. package/adminWww/assets/Logs-CsVPSLJH-v77.js +0 -1
  359. package/adminWww/assets/Logs-CsVPSLJH-v78.js +0 -1
  360. package/adminWww/assets/Objects-DPan0bzw-v54.js +0 -1
  361. package/adminWww/assets/Objects-DPan0bzw-v55.js +0 -1
  362. package/adminWww/assets/Objects-DPan0bzw-v56.js +0 -1
  363. package/adminWww/assets/Objects-DPan0bzw-v57.js +0 -1
  364. package/adminWww/assets/Objects-DPan0bzw-v58.js +0 -1
  365. package/adminWww/assets/Objects-DPan0bzw-v59.js +0 -1
  366. package/adminWww/assets/Objects-DPan0bzw-v60.js +0 -1
  367. package/adminWww/assets/Objects-DPan0bzw-v61.js +0 -1
  368. package/adminWww/assets/Objects-DPan0bzw-v62.js +0 -1
  369. package/adminWww/assets/Objects-DPan0bzw-v63.js +0 -1
  370. package/adminWww/assets/Objects-DPan0bzw-v64.js +0 -1
  371. package/adminWww/assets/Objects-DPan0bzw-v65.js +0 -1
  372. package/adminWww/assets/Objects-DPan0bzw-v66.js +0 -1
  373. package/adminWww/assets/Objects-DPan0bzw-v67.js +0 -1
  374. package/adminWww/assets/Objects-DPan0bzw-v68.js +0 -1
  375. package/adminWww/assets/Objects-DPan0bzw-v69.js +0 -1
  376. package/adminWww/assets/Objects-DPan0bzw-v70.js +0 -1
  377. package/adminWww/assets/Objects-DPan0bzw-v71.js +0 -1
  378. package/adminWww/assets/Objects-DPan0bzw-v72.js +0 -1
  379. package/adminWww/assets/Objects-DPan0bzw-v73.js +0 -1
  380. package/adminWww/assets/Objects-DPan0bzw-v74.js +0 -1
  381. package/adminWww/assets/Objects-DPan0bzw-v75.js +0 -1
  382. package/adminWww/assets/Objects-DPan0bzw-v76.js +0 -1
  383. package/adminWww/assets/Objects-DPan0bzw-v77.js +0 -1
  384. package/adminWww/assets/Objects-DPan0bzw-v78.js +0 -1
  385. package/adminWww/assets/Objects-DPw50Write.js +0 -878
  386. package/adminWww/assets/Objects-DPw51NoLock.js +0 -878
  387. package/adminWww/assets/Objects-DPw52Fast.js +0 -878
  388. package/adminWww/assets/Objects-DPw53Native.js +0 -878
  389. package/adminWww/assets/Users-BgnBRgwU-v54.js +0 -1
  390. package/adminWww/assets/Users-BgnBRgwU-v55.js +0 -1
  391. package/adminWww/assets/Users-BgnBRgwU-v56.js +0 -1
  392. package/adminWww/assets/Users-BgnBRgwU-v57.js +0 -1
  393. package/adminWww/assets/Users-BgnBRgwU-v58.js +0 -1
  394. package/adminWww/assets/Users-BgnBRgwU-v59.js +0 -1
  395. package/adminWww/assets/Users-BgnBRgwU-v60.js +0 -1
  396. package/adminWww/assets/Users-BgnBRgwU-v61.js +0 -1
  397. package/adminWww/assets/Users-BgnBRgwU-v62.js +0 -1
  398. package/adminWww/assets/Users-BgnBRgwU-v63.js +0 -1
  399. package/adminWww/assets/Users-BgnBRgwU-v64.js +0 -1
  400. package/adminWww/assets/Users-BgnBRgwU-v65.js +0 -1
  401. package/adminWww/assets/Users-BgnBRgwU-v66.js +0 -1
  402. package/adminWww/assets/Users-BgnBRgwU-v67.js +0 -1
  403. package/adminWww/assets/Users-BgnBRgwU-v68.js +0 -1
  404. package/adminWww/assets/Users-BgnBRgwU-v69.js +0 -1
  405. package/adminWww/assets/Users-BgnBRgwU-v70.js +0 -1
  406. package/adminWww/assets/Users-BgnBRgwU-v71.js +0 -1
  407. package/adminWww/assets/Users-BgnBRgwU-v72.js +0 -1
  408. package/adminWww/assets/Users-BgnBRgwU-v73.js +0 -1
  409. package/adminWww/assets/Users-BgnBRgwU-v74.js +0 -1
  410. package/adminWww/assets/Users-BgnBRgwU-v75.js +0 -1
  411. package/adminWww/assets/Users-BgnBRgwU-v76.js +0 -1
  412. package/adminWww/assets/Users-BgnBRgwU-v77.js +0 -1
  413. package/adminWww/assets/Users-BgnBRgwU-v78.js +0 -1
  414. package/adminWww/assets/bootstrap-COulQZax-v54.js +0 -1
  415. package/adminWww/assets/bootstrap-COulQZax-v55.js +0 -1
  416. package/adminWww/assets/bootstrap-COulQZax-v56.js +0 -1
  417. package/adminWww/assets/bootstrap-COulQZax-v57.js +0 -1
  418. package/adminWww/assets/bootstrap-COulQZax-v58.js +0 -1
  419. package/adminWww/assets/bootstrap-COulQZax-v59.js +0 -1
  420. package/adminWww/assets/bootstrap-COulQZax-v60.js +0 -1
  421. package/adminWww/assets/bootstrap-COulQZax-v61.js +0 -1
  422. package/adminWww/assets/bootstrap-COulQZax-v62.js +0 -1
  423. package/adminWww/assets/bootstrap-COulQZax-v63.js +0 -1
  424. package/adminWww/assets/bootstrap-COulQZax-v64.js +0 -1
  425. package/adminWww/assets/bootstrap-COulQZax-v65.js +0 -1
  426. package/adminWww/assets/bootstrap-COulQZax-v66.js +0 -1
  427. package/adminWww/assets/bootstrap-COulQZax-v67.js +0 -1
  428. package/adminWww/assets/bootstrap-COulQZax-v68.js +0 -1
  429. package/adminWww/assets/bootstrap-COulQZax-v69.js +0 -1
  430. package/adminWww/assets/bootstrap-COulQZax-v70.js +0 -1
  431. package/adminWww/assets/bootstrap-COulQZax-v71.js +0 -1
  432. package/adminWww/assets/bootstrap-COulQZax-v72.js +0 -1
  433. package/adminWww/assets/bootstrap-COulQZax-v73.js +0 -1
  434. package/adminWww/assets/bootstrap-COulQZax-v74.js +0 -1
  435. package/adminWww/assets/bootstrap-COulQZax-v75.js +0 -1
  436. package/adminWww/assets/bootstrap-COulQZax-v76.js +0 -1
  437. package/adminWww/assets/bootstrap-COulQZax-v77.js +0 -1
  438. package/adminWww/assets/bootstrap-COulQZax-v78.js +0 -1
  439. package/adminWww/assets/bootstrap-DPWrite50.js +0 -317
  440. package/adminWww/assets/bootstrap-DPWrite51.js +0 -317
  441. package/adminWww/assets/bootstrap-DPWrite52.js +0 -317
  442. package/adminWww/assets/bootstrap-DPWrite53.js +0 -317
  443. package/adminWww/assets/hostInit-DPWrite50.js +0 -2
  444. package/adminWww/assets/hostInit-DPWrite51.js +0 -2
  445. package/adminWww/assets/hostInit-DPWrite52.js +0 -2
  446. package/adminWww/assets/hostInit-DPWrite53.js +0 -2
  447. package/adminWww/assets/hostInit-v54.js +0 -1
  448. package/adminWww/assets/hostInit-v55.js +0 -1
  449. package/adminWww/assets/hostInit-v56.js +0 -1
  450. package/adminWww/assets/hostInit-v57.js +0 -1
  451. package/adminWww/assets/hostInit-v58.js +0 -1
  452. package/adminWww/assets/hostInit-v59.js +0 -1
  453. package/adminWww/assets/hostInit-v60.js +0 -1
  454. package/adminWww/assets/hostInit-v61.js +0 -1
  455. package/adminWww/assets/hostInit-v62.js +0 -1
  456. package/adminWww/assets/hostInit-v63.js +0 -1
  457. package/adminWww/assets/hostInit-v64.js +0 -1
  458. package/adminWww/assets/hostInit-v65.js +0 -1
  459. package/adminWww/assets/hostInit-v66.js +0 -1
  460. package/adminWww/assets/hostInit-v67.js +0 -1
  461. package/adminWww/assets/hostInit-v68.js +0 -1
  462. package/adminWww/assets/hostInit-v69.js +0 -1
  463. package/adminWww/assets/hostInit-v70.js +0 -1
  464. package/adminWww/assets/hostInit-v71.js +0 -1
  465. package/adminWww/assets/hostInit-v72.js +0 -1
  466. package/adminWww/assets/hostInit-v73.js +0 -1
  467. package/adminWww/assets/hostInit-v74.js +0 -1
  468. package/adminWww/assets/hostInit-v75.js +0 -1
  469. package/adminWww/assets/hostInit-v76.js +0 -1
  470. package/adminWww/assets/hostInit-v77.js +0 -1
  471. package/adminWww/assets/hostInit-v78.js +0 -1
  472. package/adminWww/assets/index-CQZugZ1z-v54.js +0 -1
  473. package/adminWww/assets/index-CQZugZ1z-v55.js +0 -1
  474. package/adminWww/assets/index-CQZugZ1z-v56.js +0 -1
  475. package/adminWww/assets/index-CQZugZ1z-v57.js +0 -1
  476. package/adminWww/assets/index-CQZugZ1z-v58.js +0 -1
  477. package/adminWww/assets/index-CQZugZ1z-v59.js +0 -1
  478. package/adminWww/assets/index-CQZugZ1z-v60.js +0 -1
  479. package/adminWww/assets/index-CQZugZ1z-v61.js +0 -1
  480. package/adminWww/assets/index-CQZugZ1z-v62.js +0 -1
  481. package/adminWww/assets/index-CQZugZ1z-v63.js +0 -1
  482. package/adminWww/assets/index-CQZugZ1z-v64.js +0 -1
  483. package/adminWww/assets/index-CQZugZ1z-v65.js +0 -1
  484. package/adminWww/assets/index-CQZugZ1z-v66.js +0 -1
  485. package/adminWww/assets/index-CQZugZ1z-v67.js +0 -1
  486. package/adminWww/assets/index-CQZugZ1z-v68.js +0 -1
  487. package/adminWww/assets/index-CQZugZ1z-v69.js +0 -1
  488. package/adminWww/assets/index-CQZugZ1z-v70.js +0 -1
  489. package/adminWww/assets/index-CQZugZ1z-v71.js +0 -1
  490. package/adminWww/assets/index-CQZugZ1z-v72.js +0 -1
  491. package/adminWww/assets/index-CQZugZ1z-v73.js +0 -1
  492. package/adminWww/assets/index-CQZugZ1z-v74.js +0 -1
  493. package/adminWww/assets/index-CQZugZ1z-v75.js +0 -1
  494. package/adminWww/assets/index-CQZugZ1z-v76.js +0 -1
  495. package/adminWww/assets/index-CQZugZ1z-v77.js +0 -1
  496. package/adminWww/assets/index-CQZugZ1z-v78.js +0 -1
  497. package/adminWww/assets/index-D2ymscJA-v54.js +0 -1
  498. package/adminWww/assets/index-D2ymscJA-v55.js +0 -1
  499. package/adminWww/assets/index-D2ymscJA-v56.js +0 -1
  500. package/adminWww/assets/index-D2ymscJA-v57.js +0 -1
  501. package/adminWww/assets/index-D2ymscJA-v58.js +0 -1
  502. package/adminWww/assets/index-D2ymscJA-v59.js +0 -1
  503. package/adminWww/assets/index-D2ymscJA-v60.js +0 -1
  504. package/adminWww/assets/index-D2ymscJA-v61.js +0 -1
  505. package/adminWww/assets/index-D2ymscJA-v62.js +0 -1
  506. package/adminWww/assets/index-D2ymscJA-v63.js +0 -1
  507. package/adminWww/assets/index-D2ymscJA-v64.js +0 -1
  508. package/adminWww/assets/index-D2ymscJA-v65.js +0 -1
  509. package/adminWww/assets/index-D2ymscJA-v66.js +0 -1
  510. package/adminWww/assets/index-D2ymscJA-v67.js +0 -1
  511. package/adminWww/assets/index-D2ymscJA-v68.js +0 -1
  512. package/adminWww/assets/index-D2ymscJA-v69.js +0 -1
  513. package/adminWww/assets/index-D2ymscJA-v70.js +0 -1
  514. package/adminWww/assets/index-D2ymscJA-v71.js +0 -1
  515. package/adminWww/assets/index-D2ymscJA-v72.js +0 -1
  516. package/adminWww/assets/index-D2ymscJA-v73.js +0 -1
  517. package/adminWww/assets/index-D2ymscJA-v74.js +0 -1
  518. package/adminWww/assets/index-D2ymscJA-v75.js +0 -1
  519. package/adminWww/assets/index-D2ymscJA-v76.js +0 -1
  520. package/adminWww/assets/index-D2ymscJA-v77.js +0 -1
  521. package/adminWww/assets/index-D2ymscJA-v78.js +0 -1
  522. package/adminWww/assets/index-DPAdapter50.js +0 -950
  523. package/adminWww/assets/index-DPAdapter51.js +0 -950
  524. package/adminWww/assets/index-DPAdapter52.js +0 -950
  525. package/adminWww/assets/index-DPAdapter53.js +0 -950
  526. package/adminWww/assets/index-DPWrite50.js +0 -2
  527. package/adminWww/assets/index-DPWrite51.js +0 -2
  528. package/adminWww/assets/index-DPWrite52.js +0 -2
  529. package/adminWww/assets/index-DPWrite53.js +0 -2
  530. package/adminWww/assets/sentry-B7YeoTAx-v54.js +0 -1
  531. package/adminWww/assets/sentry-B7YeoTAx-v55.js +0 -1
  532. package/adminWww/assets/sentry-B7YeoTAx-v56.js +0 -1
  533. package/adminWww/assets/sentry-B7YeoTAx-v57.js +0 -1
  534. package/adminWww/assets/sentry-B7YeoTAx-v58.js +0 -1
  535. package/adminWww/assets/sentry-B7YeoTAx-v59.js +0 -1
  536. package/adminWww/assets/sentry-B7YeoTAx-v60.js +0 -1
  537. package/adminWww/assets/sentry-B7YeoTAx-v61.js +0 -1
  538. package/adminWww/assets/sentry-B7YeoTAx-v62.js +0 -1
  539. package/adminWww/assets/sentry-B7YeoTAx-v63.js +0 -1
  540. package/adminWww/assets/sentry-B7YeoTAx-v64.js +0 -1
  541. package/adminWww/assets/sentry-B7YeoTAx-v65.js +0 -1
  542. package/adminWww/assets/sentry-B7YeoTAx-v66.js +0 -1
  543. package/adminWww/assets/sentry-B7YeoTAx-v67.js +0 -1
  544. package/adminWww/assets/sentry-B7YeoTAx-v68.js +0 -1
  545. package/adminWww/assets/sentry-B7YeoTAx-v69.js +0 -1
  546. package/adminWww/assets/sentry-B7YeoTAx-v70.js +0 -1
  547. package/adminWww/assets/sentry-B7YeoTAx-v71.js +0 -1
  548. package/adminWww/assets/sentry-B7YeoTAx-v72.js +0 -1
  549. package/adminWww/assets/sentry-B7YeoTAx-v73.js +0 -1
  550. package/adminWww/assets/sentry-B7YeoTAx-v74.js +0 -1
  551. package/adminWww/assets/sentry-B7YeoTAx-v75.js +0 -1
  552. package/adminWww/assets/sentry-B7YeoTAx-v76.js +0 -1
  553. package/adminWww/assets/sentry-B7YeoTAx-v77.js +0 -1
  554. package/adminWww/assets/sentry-B7YeoTAx-v78.js +0 -1
  555. package/adminWww/assets/sentry-B7YeoTAx-v79.js +0 -1
  556. package/adminWww/css/eos-branding.css +0 -3844
  557. package/adminWww/js/eos-branding.js +0 -1547
  558. package/adminWww/js/eos-console-quiet.js +0 -7
  559. package/adminWww/js/eos-hard-logout.js +0 -18
  560. package/adminWww/js/eos-objects-state-tools.js +0 -15
  561. package/adminWww/js/eos-performance-guard.js +0 -7
  562. package/adminWww/js/eos-runtime-fixes.js +0 -146
  563. package/adminWww/js/eos-security-ui.js +0 -347
  564. package/adminWww/remoteEntry-DPWrite50.js +0 -2
  565. package/adminWww/remoteEntry-DPWrite51.js +0 -2
  566. package/adminWww/remoteEntry-DPWrite52.js +0 -2
  567. package/adminWww/remoteEntry-DPWrite53.js +0 -2
  568. package/adminWww/remoteEntry-v54.js +0 -1
  569. package/adminWww/remoteEntry-v55.js +0 -1
  570. package/adminWww/remoteEntry-v56.js +0 -1
  571. package/adminWww/remoteEntry-v57.js +0 -1
  572. package/adminWww/remoteEntry-v58.js +0 -1
  573. package/adminWww/remoteEntry-v59.js +0 -1
  574. package/adminWww/remoteEntry-v60.js +0 -1
  575. package/adminWww/remoteEntry-v61.js +0 -1
  576. package/adminWww/remoteEntry-v62.js +0 -1
  577. package/adminWww/remoteEntry-v63.js +0 -1
  578. package/adminWww/remoteEntry-v64.js +0 -1
  579. package/adminWww/remoteEntry-v65.js +0 -1
  580. package/adminWww/remoteEntry-v66.js +0 -1
  581. package/adminWww/remoteEntry-v67.js +0 -1
  582. package/adminWww/remoteEntry-v68.js +0 -1
  583. package/adminWww/remoteEntry-v69.js +0 -1
  584. package/adminWww/remoteEntry-v70.js +0 -1
  585. package/adminWww/remoteEntry-v71.js +0 -1
  586. package/adminWww/remoteEntry-v72.js +0 -1
  587. package/adminWww/remoteEntry-v73.js +0 -1
  588. package/adminWww/remoteEntry-v74.js +0 -1
  589. package/adminWww/remoteEntry-v75.js +0 -1
  590. package/adminWww/remoteEntry-v76.js +0 -1
  591. package/adminWww/remoteEntry-v77.js +0 -1
  592. package/adminWww/remoteEntry-v78.js +0 -1
  593. /package/adminWww/assets/{index-D2ymscJA-v79.js → index-D2ymscJA-v82.js} +0 -0
@@ -1,1547 +0,0 @@
1
- (() => {
2
- 'use strict';
3
-
4
- window.NEXOWATT_EOS_UI_VERSION = 'v79-direct-control-runtime-fix';
5
-
6
- const BRAND = 'NexoWatt EOS';
7
- const EOS_MEANING = 'Energy Operation System';
8
- const BRAND_LONG = `${BRAND} - ${EOS_MEANING}`;
9
- const ASSET_BASE = (() => {
10
- const script = document.currentScript?.src || document.querySelector('script[src*="eos-branding.js"]')?.src || window.location.href;
11
- return new URL('../', script).href;
12
- })();
13
- const asset = path => new URL(path.replace(/^\.\//, ''), ASSET_BASE).href;
14
- const LOGO = asset('img/eos/nexowatt-192.png');
15
- const PNG_LOGO = asset('img/eos/nexowatt-192.png');
16
- const LOGIN_MOTTO = EOS_MEANING;
17
- const CORE_PROTECTED_ADAPTERS = ['admin', 'eos-admin', 'backitup', 'nexowatt-devices', 'nexowatt-device', 'nexowatt-dev', 'nexowatt-ui'];
18
-
19
- const TEXT_REPLACEMENTS = [
20
- [/NexoWatt\s+Energy\s+Management\s+System/gi, BRAND],
21
- [/NexoWatt\s+Energy\s+Managementsystem/gi, BRAND],
22
- [/Energy\s+Management\s+System/gi, EOS_MEANING],
23
- [/Energy\s+Managementsystem/gi, EOS_MEANING],
24
- [/ioBroker\.admin/gi, BRAND],
25
- [/ioBroker\s+admin/gi, BRAND],
26
- [/\bioBroker\b/gi, BRAND],
27
- ];
28
-
29
-
30
- const MOJIBAKE_REPLACEMENTS = new Map(Object.entries({
31
- 'dürfen': 'dürfen', 'Dürfen': 'Dürfen',
32
- 'für': 'für', 'Für': 'Für',
33
- 'müssen': 'müssen', 'Müssen': 'Müssen',
34
- 'können': 'können', 'Können': 'Können',
35
- 'möglich': 'möglich', 'Möglich': 'Möglich',
36
- 'Löschen': 'Löschen', 'löschen': 'löschen',
37
- 'schützen': 'schützen', 'Schützen': 'Schützen',
38
- 'Schützt': 'Schützt', 'schützt': 'schützt',
39
- 'Geschützte': 'Geschützte', 'geschützte': 'geschützte',
40
- 'ausgewählte': 'ausgewählte', 'Ausgewählte': 'Ausgewählte',
41
- 'ändern': 'ändern', 'Ändern': 'Ändern',
42
- 'über': 'über', 'Über': 'Über',
43
- 'Wähle': 'Wähle', 'wähle': 'wähle',
44
- 'öffnen': 'öffnen', 'Öffnen': 'Öffnen',
45
- 'schließen': 'schließen', 'Schließen': 'Schließen',
46
- 'Gerät': 'Gerät', 'gerät': 'gerät',
47
- 'Geräte': 'Geräte', 'geräte': 'geräte',
48
- 'Zugänge': 'Zugänge', 'zugänge': 'zugänge',
49
- 'ß': 'ß', 'Ä': 'Ä', 'Ö': 'Ö', 'Ü': 'Ü', 'ä': 'ä', 'ö': 'ö', 'ü': 'ü'
50
- }));
51
-
52
-
53
-
54
- const decodeMojibakeChunk = chunk => {
55
- try {
56
- const bytes = Uint8Array.from(Array.from(chunk, char => char.charCodeAt(0) & 0xff));
57
- const decoded = new TextDecoder('utf-8', { fatal: false }).decode(bytes);
58
- return decoded && decoded !== chunk ? decoded : chunk;
59
- } catch (_) {
60
- return chunk;
61
- }
62
- };
63
-
64
- const repairMojibake = value => {
65
- let text = String(value || '');
66
- // Repair common UTF-8-as-Latin1 fragments, including double-encoded strings
67
- // such as dürfen, Löschen, geschützt.
68
- for (let i = 0; i < 3 && /(?:Ã.|Â.|â.|�)/.test(text); i += 1) {
69
- const repaired = text.replace(/[\u00C2-\u00F4][\u0080-\u00BF\u00A0-\u00BF]+/g, decodeMojibakeChunk);
70
- if (repaired === text) break;
71
- text = repaired;
72
- }
73
- const hardMap = new Map(Object.entries({
74
- 'dürfen': 'dürfen', 'dürfen': 'dürfen', 'Dürfen': 'Dürfen', 'Dürfen': 'Dürfen',
75
- 'für': 'für', 'für': 'für', 'Für': 'Für', 'Für': 'Für',
76
- 'können': 'können', 'können': 'können', 'Können': 'Können', 'Können': 'Können',
77
- 'möglich': 'möglich', 'möglich': 'möglich', 'Möglich': 'Möglich', 'Möglich': 'Möglich',
78
- 'Löschen': 'Löschen', 'Löschen': 'Löschen', 'löschen': 'löschen', 'löschen': 'löschen',
79
- 'schützen': 'schützen', 'schützen': 'schützen', 'Schützen': 'Schützen', 'Schützen': 'Schützen',
80
- 'Geschützte': 'Geschützte', 'Geschützte': 'Geschützte', 'geschützte': 'geschützte', 'geschützte': 'geschützte',
81
- 'ausgewählte': 'ausgewählte', 'ausgewählte': 'ausgewählte', 'Ausgewählte': 'Ausgewählte', 'Ausgewählte': 'Ausgewählte',
82
- 'ändern': 'ändern', 'ändern': 'ändern', 'Über': 'Über', 'Über': 'Über', 'über': 'über', 'über': 'über',
83
- 'Gerät': 'Gerät', 'Gerät': 'Gerät', 'Geräte': 'Geräte', 'Geräte': 'Geräte',
84
- 'schließen': 'schließen', 'schließen': 'schließen', 'ß': 'ß', 'ß': 'ß',
85
- 'ä': 'ä', 'ä': 'ä', 'ö': 'ö', 'ö': 'ö', 'ü': 'ü', 'ü': 'ü',
86
- 'Ä': 'Ä', 'Ä': 'Ä', 'Ö': 'Ö', 'Ö': 'Ö', 'Ü': 'Ü', 'Ü': 'Ü', ' ': ' ', 'Â': ''
87
- }));
88
- for (const [from, to] of hardMap) if (text.includes(from)) text = text.split(from).join(to);
89
- return text;
90
- };
91
-
92
- const EXACT_LABELS = new Map(Object.entries({
93
- 'Admin': BRAND,
94
- 'NEXOWATT': 'NEXOWATT EOS',
95
- 'NexoWatt EMS': 'EOS Cockpit',
96
- 'Übersicht': 'Cockpit',
97
- 'Overview': 'Cockpit',
98
- 'Adapter': 'Module',
99
- 'Adapters': 'Module',
100
- 'Instanzen': 'Dienste',
101
- 'Instances': 'Dienste',
102
- 'Objekte': 'Datenpunkte',
103
- 'Objects': 'Datenpunkte',
104
- 'Kategorien': 'Struktur',
105
- 'Categories': 'Struktur',
106
- 'Protokolle': 'Systemlogs',
107
- 'Logs': 'Systemlogs',
108
- 'Benutzer': 'Zugänge & Rechte',
109
- 'Users': 'Benutzerkonten',
110
- 'Groups': 'Rollen',
111
- 'In groups': 'Zugeordnete Rollen',
112
- 'Permissions': 'Rechte',
113
- 'Permission': 'Recht',
114
- 'User parameters': 'Benutzerkonto bearbeiten',
115
- 'Group parameters': 'Rolle & Rechte bearbeiten',
116
- 'Main': 'Stammdaten',
117
- 'Hosts': 'System-Hosts',
118
- 'Files': 'Dateien',
119
- 'Backup': 'Sicherung',
120
- 'xtrem': 'Konsole',
121
- 'xterm': 'Konsole',
122
- 'ra_Logout': 'Abmelden',
123
- 'Logout': 'Abmelden',
124
- }));
125
-
126
- const currentTab = () => String(window.location.hash || '').toLowerCase();
127
- const isObjectsSurface = () => /tab-objects\b/.test(currentTab());
128
- const isLogsSurface = () => /tab-logs\b/.test(currentTab());
129
- const isHighLoadAdminSurface = () => /tab-(objects|adapter|adapters|instances|logs|host|hosts)\b/.test(currentTab());
130
- const isInsideAppPaper = node => !!node?.closest?.('#app-paper, [role="grid"], .MuiDataGrid-root, .ReactVirtualized__Grid, .eos-object-value-cell, .MuiTooltip-popper, .MuiPopover-root, .MuiPopper-root, .MuiMenu-root, [role="tooltip"]');
131
-
132
- const state = {
133
- fullPatchScheduled: false,
134
- scopePatchScheduled: false,
135
- pendingScopes: new Set(),
136
- lastFullPatch: 0,
137
- securityPolicy: {
138
- loaded: false,
139
- isAdmin: false,
140
- hideLegacyAdminForNonAdmins: true,
141
- restrictProtectedAdapterControls: true,
142
- protectedAdapters: CORE_PROTECTED_ADAPTERS,
143
- },
144
- securityFetchStarted: false,
145
- unsubscribePolicy: null,
146
- unsubscribeDom: null,
147
- assistOpen: false,
148
- };
149
-
150
- const safe = fn => {
151
- try { return fn(); } catch (e) { return undefined; }
152
- };
153
-
154
- const replaceBrand = value => {
155
- if (!value || typeof value !== 'string') return value;
156
- let next = repairMojibake(value);
157
- for (const [from, to] of MOJIBAKE_REPLACEMENTS) {
158
- if (next.includes(from)) next = next.split(from).join(to);
159
- }
160
- next = repairMojibake(next);
161
- for (const [pattern, replacement] of TEXT_REPLACEMENTS) next = next.replace(pattern, replacement);
162
- next = repairMojibake(next);
163
- const compact = next.trim();
164
- if (EXACT_LABELS.has(compact)) next = next.replace(compact, EXACT_LABELS.get(compact));
165
- return next;
166
- };
167
-
168
- const isCommandOrTechnicalOutput = el => {
169
- if (!el || !el.closest) return false;
170
- if (el.closest('textarea, pre, code, samp, kbd, .xterm, .xterm-screen, .terminal, [class*=\"Terminal\"], [class*=\"terminal\"], [class*=\"Console\"], [class*=\"console\"]')) return true;
171
- const dialog = el.closest('.MuiDialog-root, [role=\"dialog\"]');
172
- if (!dialog) return false;
173
- const text = dialog.textContent || '';
174
- return /(?:Befehl ausführen|Process exited|npm error|npm ERR|upgrade\s+eos-admin|Installing\s+iobroker\.|Installing\s+NexoWatt\s+EOS\.|NPM version|debug-0\.log)/i.test(text);
175
- };
176
-
177
- const skipElement = el => {
178
- if (!el || el.nodeType !== 1) return false;
179
- const tag = el.tagName;
180
- return tag === 'SCRIPT' || tag === 'STYLE' || tag === 'TEXTAREA' || tag === 'INPUT' || tag === 'CODE' || tag === 'PRE' || tag === 'SAMP' || tag === 'KBD' || isCommandOrTechnicalOutput(el);
181
- };
182
-
183
- const patchTextNode = node => {
184
- if (!node || node.nodeType !== Node.TEXT_NODE || !node.nodeValue) return;
185
- if (skipElement(node.parentElement)) return;
186
- const before = node.nodeValue;
187
- const after = replaceBrand(before);
188
- if (after !== before) node.nodeValue = after;
189
- };
190
-
191
- const patchTextNodes = root => safe(() => {
192
- if (!root) return;
193
- if (root.nodeType === Node.TEXT_NODE) {
194
- patchTextNode(root);
195
- return;
196
- }
197
- if (root.nodeType !== Node.ELEMENT_NODE && root.nodeType !== Node.DOCUMENT_NODE) return;
198
- if (skipElement(root)) return;
199
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
200
- acceptNode(node) {
201
- return skipElement(node.parentElement) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
202
- }
203
- });
204
- let node;
205
- while ((node = walker.nextNode())) patchTextNode(node);
206
- });
207
-
208
-
209
- const patchMojibakeTextNode = node => {
210
- if (!node || node.nodeType !== Node.TEXT_NODE || !node.nodeValue) return;
211
- if (skipElement(node.parentElement)) return;
212
- const before = node.nodeValue;
213
- const after = repairMojibake(before);
214
- if (after !== before) node.nodeValue = after;
215
- };
216
-
217
- const patchMojibakeTextNodes = root => safe(() => {
218
- if (!root) return;
219
- if (root.nodeType === Node.TEXT_NODE) {
220
- patchMojibakeTextNode(root);
221
- return;
222
- }
223
- if (root.nodeType !== Node.ELEMENT_NODE && root.nodeType !== Node.DOCUMENT_NODE) return;
224
- if (skipElement(root)) return;
225
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
226
- acceptNode(node) {
227
- return skipElement(node.parentElement) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
228
- }
229
- });
230
- let node;
231
- while ((node = walker.nextNode())) patchMojibakeTextNode(node);
232
- });
233
-
234
- const patchImage = img => {
235
- const src = img.getAttribute('src') || '';
236
- const alt = img.getAttribute('alt') || '';
237
- const inBrandArea = !!img.closest('.eos-login-card, .eos-native-drawer-header, .eos-system-brand, .eos-brand-badge');
238
- const cleanSrc = src.split(/[?#]/)[0];
239
- const isBrandLogo = /(?:^|\/)(?:admin\.svg|admin\.png|logo192\.png|logo\.svg)$/i.test(cleanSrc) || (inBrandArea && /iobroker|admin|nexowatt|eos|logo/i.test(alt));
240
- const isAdapterIcon = /adapter\/|adapters\/|custom\/|upload\/|assets\//i.test(src);
241
- const isNeutralPlaceholder = /no-image\.svg/i.test(src);
242
-
243
- // Only replace real brand surfaces. Do not stamp the NexoWatt logo onto instance/module placeholders.
244
- if ((inBrandArea || (isBrandLogo && !isAdapterIcon)) && !(!inBrandArea && isNeutralPlaceholder)) {
245
- img.setAttribute('src', LOGO);
246
- img.setAttribute('alt', BRAND);
247
- }
248
- };
249
-
250
- const patchAttributes = root => safe(() => {
251
- if (!root || (root.nodeType !== Node.ELEMENT_NODE && root.nodeType !== Node.DOCUMENT_NODE)) return;
252
- const elements = root.matches && root.matches('[title],[aria-label],[alt],[placeholder],img')
253
- ? [root]
254
- : Array.from(root.querySelectorAll ? root.querySelectorAll('[title],[aria-label],[alt],[placeholder],img') : []);
255
- for (const el of elements) {
256
- if (isHighLoadAdminSurface() && el.closest?.('.eos-object-value-cell, [role="tooltip"], .MuiTooltip-popper, .MuiPopover-root, .MuiPopper-root')) continue;
257
- ['title', 'aria-label', 'alt', 'placeholder'].forEach(attr => {
258
- if (el.hasAttribute && el.hasAttribute(attr)) {
259
- const oldValue = el.getAttribute(attr);
260
- const newValue = replaceBrand(oldValue);
261
- if (newValue !== oldValue) el.setAttribute(attr, newValue);
262
- }
263
- });
264
- if (el.tagName === 'IMG') patchImage(el);
265
- }
266
- });
267
-
268
- const forceLoginGlobals = () => {
269
- window.loginTitle = BRAND;
270
- window.loginMotto = LOGIN_MOTTO;
271
- window.loginLogo = PNG_LOGO;
272
- window.loginLink = '#';
273
- window.loginHideLogo = 'false';
274
- window.loginBackgroundColor = '#020914';
275
- window.loadingBackgroundColor = '#020914';
276
- };
277
-
278
- const routeInfo = () => {
279
- const hash = window.location.hash || '';
280
- return {
281
- users: hash.includes('tab-users'),
282
- adapters: hash.includes('tab-adapters'),
283
- instances: hash.includes('tab-instances'),
284
- objects: hash.includes('tab-objects'),
285
- logs: hash.includes('tab-logs'),
286
- hosts: hash.includes('tab-hosts') || hash.includes('tab-host'),
287
- intro: hash.includes('tab-intro') || hash === '' || hash === '#/' || hash === '#/tab-intro',
288
- };
289
- };
290
-
291
- const normalizeIdentifier = value => String(value || '')
292
- .toLowerCase()
293
- .normalize('NFD')
294
- .replace(/[\u0300-\u036f]/g, '')
295
- .replace(/^iobroker\./, '')
296
- .replace(/^system\.adapter\./, '')
297
- .replace(/\.\d+$/, '')
298
- .replace(/[^a-z0-9_.-]+/g, ' ')
299
- .trim();
300
-
301
- const adapterPattern = adapter => {
302
- const escaped = String(adapter || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
303
- return new RegExp(`(?:^|[^a-z0-9_-])${escaped}(?:$|[^a-z0-9_-])`, 'i');
304
- };
305
-
306
- const textOfElement = el => {
307
- if (!el) return '';
308
- const attrs = ['data-adapter-name', 'data-adapter', 'data-id', 'id', 'title', 'aria-label', 'alt', 'href', 'src'];
309
- const values = [el.textContent || ''];
310
- attrs.forEach(attr => {
311
- if (el.getAttribute && el.hasAttribute(attr)) values.push(el.getAttribute(attr) || '');
312
- });
313
- return values.join(' ');
314
- };
315
-
316
- const securityEndpointUrls = () => [
317
- new URL('nexowatt/security/context', ASSET_BASE).href,
318
- new URL('nexowatt/security/session', ASSET_BASE).href,
319
- new URL('eos/security/status', ASSET_BASE).href,
320
- ];
321
-
322
- const normalizeSecurityPolicy = policy => {
323
- // v47: delete protection is fixed to EOS core adapters. Dynamic policy entries
324
- // from older settings are ignored, otherwise normal Dienste can be blocked.
325
- const protectedAdapters = new Set(CORE_PROTECTED_ADAPTERS);
326
- const isAdmin = !!(policy?.isAdmin || policy?.isAdminGroup || policy?.isEosAdminGroup || policy?.isAdministrator);
327
- return {
328
- loaded: true,
329
- user: policy?.user || null,
330
- groups: Array.isArray(policy?.groups) ? policy.groups : [],
331
- isAdmin,
332
- hideLegacyAdminForNonAdmins: policy?.hideLegacyAdminForNonAdmins !== false && policy?.hideLegacyAdminFromNonAdmins !== false,
333
- restrictProtectedAdapterControls: policy?.restrictProtectedAdapterControls !== false,
334
- protectedAdapters: [...protectedAdapters].sort(),
335
- };
336
- };
337
-
338
- const applySecurityClasses = () => {
339
- const policy = state.securityPolicy;
340
- document.documentElement.classList.toggle('eos-security-loaded', !!policy.loaded);
341
- document.documentElement.classList.toggle('eos-security-admin', !!policy.isAdmin);
342
- document.documentElement.classList.toggle('eos-security-nonadmin', policy.loaded && !policy.isAdmin);
343
- };
344
-
345
- const fetchSecurityPolicy = () => {
346
- if (state.securityFetchStarted) return;
347
- state.securityFetchStarted = true;
348
- const connect = () => {
349
- const client = window.NEXOWATT_EOS_POLICY_CLIENT;
350
- if (!client) {
351
- window.setTimeout(connect, 250);
352
- return;
353
- }
354
- const apply = policy => {
355
- if (!policy || policy.role === 'unknown') return;
356
- state.securityPolicy = normalizeSecurityPolicy(policy);
357
- applySecurityClasses();
358
- scheduleFullPatch(0);
359
- };
360
- apply(client.getPolicy?.());
361
- state.unsubscribePolicy?.();
362
- state.unsubscribePolicy = client.subscribe?.(apply);
363
- void client.refresh?.();
364
- };
365
- connect();
366
- };
367
-
368
- const isAdminUser = () => !!state.securityPolicy?.isAdmin;
369
-
370
- const isLegacyAdminContainer = el => {
371
- const text = textOfElement(el);
372
- if (/\badmin\.0\b/i.test(text) || /\bsystem\.adapter\.admin\.0\b/i.test(text)) return true;
373
- const candidates = Array.from(el.querySelectorAll ? el.querySelectorAll('*') : []);
374
- candidates.push(el);
375
- return candidates.some(node => {
376
- const value = textOfElement(node).trim();
377
- return /^admin$/i.test(value) || /^iobroker\.admin$/i.test(value) || /^system\.adapter\.admin$/i.test(value);
378
- });
379
- };
380
-
381
- const containerMentionsAdapter = (container, adapter) => {
382
- if (!container || !adapter) return false;
383
- const normalized = normalizeIdentifier(adapter);
384
- if (!normalized) return false;
385
- if (normalized === 'admin') return isLegacyAdminContainer(container);
386
- const pattern = adapterPattern(normalized);
387
- if (pattern.test(textOfElement(container))) return true;
388
- return Array.from(container.querySelectorAll ? container.querySelectorAll('[title],[aria-label],[data-adapter-name],[data-adapter],[data-id]') : [])
389
- .some(el => pattern.test(textOfElement(el)));
390
- };
391
-
392
- const SECURITY_SCOPE_MAX_TEXT = 1400;
393
- const SECURITY_SCOPE_MAX_CONTROLS = 18;
394
- const isSingleSecurityScope = container => {
395
- if (!container || !container.querySelectorAll) return false;
396
- const text = textOfElement(container);
397
- if (!text || text.length > SECURITY_SCOPE_MAX_TEXT) return false;
398
- const controls = container.querySelectorAll('button,[role="button"],a,.MuiIconButton-root').length;
399
- if (controls > SECURITY_SCOPE_MAX_CONTROLS) return false;
400
- const nested = container.querySelectorAll('[role="row"],tr,.MuiDataGrid-row,.MuiListItem-root,.MuiCard-root,.MuiAccordion-root').length;
401
- return nested <= 4;
402
- };
403
-
404
- const getSecurityContainers = () => Array.from(document.querySelectorAll([
405
- '#app-paper .MuiCard-root',
406
- '#app-paper tr.MuiTableRow-root',
407
- '#app-paper tr',
408
- '#app-paper .MuiAccordion-root',
409
- '#app-paper [role="row"]',
410
- '#app-paper [role="treeitem"]',
411
- '#app-paper .MuiDataGrid-row',
412
- '#app-paper .MuiTreeItem-root',
413
- '#app-paper .MuiFormControlLabel-root',
414
- '#app-paper .MuiListItem-root',
415
- '#app-paper .MuiListItemButton-root',
416
- ].join(','))).filter(el => !el.closest('.MuiDialog-paper') && isSingleSecurityScope(el));
417
-
418
- const isDeleteControl = el => {
419
- const text = normalize(el.textContent || el.getAttribute?.('title') || el.getAttribute?.('aria-label') || '');
420
- const title = normalize(el.getAttribute?.('title') || el.closest?.('[title]')?.getAttribute('title') || '');
421
- const svg = el.querySelector?.('svg[data-testid*="Delete"], svg[data-testid*="Remove"], svg[data-testid*="Clear"]');
422
- return !!svg || /\b(delete|remove|uninstall|del|loschen|entfernen|deinstallieren)\b/.test(`${text} ${title}`);
423
- };
424
-
425
- const unlockDeleteControls = () => safe(() => {
426
- // v47: clean up classes/attributes created by older EOS delete guards. We do not
427
- // install capture listeners anymore; React handlers enforce the core protection list.
428
- document.querySelectorAll('#app-paper .eos-protected-delete-control, #app-paper .eos-security-hidden-delete, #app-paper [data-eos-delete-guard-bound="true"]').forEach(control => {
429
- control.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete');
430
- control.removeAttribute('data-eos-delete-guard-bound');
431
- control.removeAttribute('aria-disabled');
432
- control.style.display = '';
433
- control.style.pointerEvents = '';
434
- control.style.visibility = '';
435
- control.style.opacity = '';
436
- if (control.hasAttribute('disabled')) control.removeAttribute('disabled');
437
- if ('disabled' in control) control.disabled = false;
438
- });
439
- });
440
-
441
- const lockDeleteControls = container => {
442
- // v47: Intentionally no DOM click blocking. Stale capture listeners and disabled
443
- // attributes were the reason normal services could not be deleted via trash icon.
444
- unlockDeleteControls();
445
- };
446
-
447
-
448
- const releaseNotificationControls = () => safe(() => {
449
- // v38: Keep native snackbar/toast close buttons clickable without touching dialogs,
450
- // poppers, menus or adapter-owned configuration surfaces. Earlier broad selectors
451
- // changed generic dialogs and broke React click handlers.
452
- const roots = [
453
- '.MuiSnackbar-root',
454
- '.SnackbarItem-root',
455
- '.SnackbarItem-wrappedRoot',
456
- '.notistack-Snackbar',
457
- '.Toastify__toast-container',
458
- '.Toastify__toast'
459
- ].join(',');
460
- document.querySelectorAll(roots).forEach(box => {
461
- if (box.closest('.MuiDialog-root,.MuiModal-root,.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,[role="dialog"]')) return;
462
- box.classList.add('eos-notification-safe');
463
- box.style.pointerEvents = 'auto';
464
- box.querySelectorAll('button, [role="button"], a, .MuiIconButton-root').forEach(control => {
465
- control.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete');
466
- // Do not remove disabled states globally. Only restore pointer handling.
467
- control.style.pointerEvents = 'auto';
468
- control.style.visibility = '';
469
- control.style.opacity = '';
470
- });
471
- });
472
- });
473
-
474
- const ensurePopupCompatibility = () => safe(() => {
475
- // v38: All native Admin dialogs, adapter install/autocomplete poppers, menus and
476
- // adapter-owned modals must stay above EOS decorative layers and keep their React
477
- // event handlers untouched.
478
- const selectors = [
479
- '.MuiDialog-root', '.MuiModal-root', '.MuiPopover-root', '.MuiPopper-root',
480
- '.MuiMenu-root', '.MuiAutocomplete-popper'
481
- ].join(',');
482
- document.querySelectorAll(selectors).forEach(el => {
483
- const hidden = el.classList.contains('MuiModal-hidden') || el.getAttribute('aria-hidden') === 'true';
484
- if (hidden) {
485
- el.classList.remove('eos-native-popup-safe');
486
- if (el.style) {
487
- el.style.pointerEvents = '';
488
- el.style.zIndex = '';
489
- }
490
- return;
491
- }
492
- el.classList.add('eos-native-popup-safe');
493
- if (el.style) {
494
- el.style.pointerEvents = 'auto';
495
- const isFloating = el.matches('.MuiPopover-root,.MuiPopper-root,.MuiMenu-root,.MuiAutocomplete-popper');
496
- if (isFloating && !el.closest('.MuiDialog-paper')) el.style.zIndex = '6500';
497
- }
498
- });
499
- });
500
-
501
- const protectDeleteDialogs = () => {
502
- // v47: Do not disable delete confirmation dialogs in the DOM. The delete command
503
- // guard is handled in React and keeps the fixed EOS core list protected.
504
- unlockDeleteControls();
505
- };
506
-
507
- const hideSecuritySettingsForNonAdmin = () => {
508
- const securityNeedles = /(nexowatt\s+sicherheit|eos\s+security|eos\s+systemschutz|legacy\s+admin|alter\s+admin|gesch(?:u|ü)tzte\s+(system)?adapter|administratorgruppen|protected\s+adapters|admin\s+groups)/i;
509
- const markAdminOnly = el => {
510
- if (!el || isAdminUser()) return;
511
- el.dataset.eosSecurityAdminOnly = 'true';
512
- el.classList.add('eos-security-admin-only-field');
513
- el.setAttribute('aria-hidden', 'true');
514
- };
515
- if (isAdminUser()) {
516
- document.querySelectorAll('[data-eos-security-admin-only="true"], .eos-security-admin-only-field').forEach(el => {
517
- el.removeAttribute('data-eos-security-admin-only');
518
- el.classList.remove('eos-security-admin-only-field');
519
- el.removeAttribute('aria-hidden');
520
- });
521
- return;
522
- }
523
- Array.from(document.querySelectorAll('[role="tab"], .MuiTab-root, button, [role="button"]')).forEach(tab => {
524
- if (!securityNeedles.test(textOfElement(tab))) return;
525
- const inDialog = !!tab.closest('.MuiDialog-paper, [role="dialog"]');
526
- if (inDialog) markAdminOnly(tab);
527
- });
528
- Array.from(document.querySelectorAll('.MuiDialog-paper, [role="dialog"]')).forEach(dialog => {
529
- const dialogText = textOfElement(dialog);
530
- if (!securityNeedles.test(dialogText)) return;
531
- dialog.classList.add('eos-security-settings-restricted');
532
- Array.from(dialog.querySelectorAll('label, legend, h2, h3, h4, .MuiTypography-root, .MuiFormLabel-root, .MuiTab-root, [role="tab"], .MuiGrid-root, .MuiGrid2-root, .MuiFormControl-root')).forEach(el => {
533
- if (!securityNeedles.test(textOfElement(el))) return;
534
- const row = el.closest('.MuiGrid2-root, .MuiGrid-root, .MuiFormControl-root, .MuiBox-root, .MuiPaper-root, [role="tabpanel"]') || el.parentElement;
535
- if (row && row !== dialog) markAdminOnly(row);
536
- markAdminOnly(el);
537
- });
538
- if (!dialog.querySelector('.eos-security-restricted-note')) {
539
- const note = document.createElement('div');
540
- note.className = 'eos-security-restricted-note';
541
- note.innerHTML = '<strong>EOS Systemschutz</strong><span>Dieser Bereich ist nur für Administratoren sichtbar. Geschützte Adapter und der alte Admin werden zentral durch NexoWatt EOS verwaltet.</span>';
542
- const content = dialog.querySelector('.MuiDialogContent-root') || dialog;
543
- content.insertBefore(note, content.firstElementChild || null);
544
- }
545
- });
546
- };
547
-
548
- const applySecurityUiGuard = () => safe(() => {
549
- const policy = state.securityPolicy;
550
- applySecurityClasses();
551
- releaseNotificationControls();
552
- // The ObjectBrowser owns datapoint value clicks and MUI tooltips. EOS security
553
- // decoration must never scan or touch this table, otherwise the native write
554
- // dialog can lose clicks while the page is still loading.
555
- if (isHighLoadAdminSurface()) return;
556
- unlockDeleteControls();
557
- // Do not apply EOS security decoration inside native adapter configuration pages.
558
- // Adapter UIs must remain 100% functional; backend/role checks still protect EOS actions.
559
- if (isAdapterConfigSurface()) return;
560
- if (!policy.loaded) return;
561
-
562
- document.querySelectorAll('.eos-hidden-legacy-admin, .eos-protected-adapter-row').forEach(el => {
563
- el.classList.remove('eos-hidden-legacy-admin', 'eos-protected-adapter-row');
564
- el.removeAttribute('aria-hidden');
565
- });
566
-
567
- const containers = getSecurityContainers();
568
- containers.forEach(container => {
569
- if (!isSingleSecurityScope(container)) return;
570
- if (!isAdminUser() && policy.hideLegacyAdminForNonAdmins !== false && isLegacyAdminContainer(container)) {
571
- container.classList.add('eos-hidden-legacy-admin');
572
- container.setAttribute('aria-hidden', 'true');
573
- return;
574
- }
575
- if (policy.restrictProtectedAdapterControls !== false) {
576
- const protectedHit = (policy.protectedAdapters || []).some(adapter => adapter !== 'admin' && containerMentionsAdapter(container, adapter));
577
- if (protectedHit) {
578
- container.classList.add('eos-protected-adapter-row');
579
- lockDeleteControls(container);
580
- }
581
- }
582
- });
583
- protectDeleteDialogs();
584
- hideSecuritySettingsForNonAdmin();
585
- });
586
-
587
- const isLoginView = () => safe(() => {
588
- const hasApp = !!document.getElementById('app-paper');
589
- if (hasApp) return false;
590
- const urlText = `${window.location.pathname} ${window.location.search} ${window.location.hash}`.toLowerCase();
591
- const hasPassword = !!document.querySelector('#password, input[type="password"], input[name*="pass" i], input[autocomplete*="password" i]');
592
- const hasUserField = !!document.querySelector('#username, input[name="username" i], input[name*="login" i], input[name*="user" i], input[autocomplete="username"]');
593
- const hasLoginButton = Array.from(document.querySelectorAll('button')).some(button => /^(anmelden|login|sign in)$/.test(normalize(button.textContent || '')));
594
- return /(?:^|[/?#])login(?:[/?#=&]|$)/.test(urlText) || (hasPassword && (hasUserField || hasLoginButton));
595
- }) || false;
596
-
597
- const removeLogoutButton = () => document.querySelectorAll('.eos-direct-logout').forEach(button => button.remove());
598
-
599
- const sanitizeLoginHref = () => safe(() => {
600
- const url = new URL(window.location.href);
601
- const href = url.searchParams.get('href') || '';
602
- if (href && /(?:^|\/)(?:logout|login|404|404\.html)(?:[/?#]|$)|%2f(?:logout|login|404|404\.html)|undefined|null/i.test(href)) {
603
- url.searchParams.delete('href');
604
- window.history.replaceState(null, document.title, `${url.pathname}${url.search}${url.hash}`);
605
- }
606
- });
607
-
608
- const normalizeBadAddressAfterLogin = () => safe(() => {
609
- const pathname = window.location.pathname || '';
610
- const badPath = /(?:%2f%23|%252f%2523|\/login|\/logout|\/404(?:\.html)?)/i.test(pathname)
611
- || /(?:^|[?&])(?:hard|origin)=/i.test(window.location.search || '');
612
- if (!badPath) return;
613
- const clean = new URL(ASSET_BASE);
614
- clean.hash = window.location.hash && !/%23|hard=|login/i.test(window.location.hash) ? window.location.hash : '#/tab-intro';
615
- if (document.getElementById('app-paper')) {
616
- window.history.replaceState(null, document.title, `${clean.pathname}${clean.search}${clean.hash}`);
617
- } else if (/(?:%2f%23|%252f%2523)/i.test(pathname)) {
618
- window.location.replace(`${clean.pathname}${clean.search}#/tab-intro`);
619
- }
620
- });
621
-
622
- const setRouteClasses = () => {
623
- const routes = routeInfo();
624
- document.documentElement.classList.toggle('eos-route-users', routes.users);
625
- document.documentElement.classList.toggle('eos-route-adapters', routes.adapters);
626
- document.documentElement.classList.toggle('eos-route-instances', routes.instances);
627
- document.documentElement.classList.toggle('eos-route-objects', routes.objects);
628
- document.documentElement.classList.toggle('eos-objects-surface', routes.objects);
629
- document.documentElement.classList.toggle('eos-route-logs', routes.logs);
630
- document.documentElement.classList.toggle('eos-route-hosts', routes.hosts);
631
- document.documentElement.classList.toggle('eos-route-intro', routes.intro);
632
- };
633
-
634
-
635
- const isAdapterConfigSurface = () => document.documentElement.classList.contains('eos-adapter-config-surface');
636
-
637
- const markAdapterConfigSurface = () => safe(() => {
638
- const app = document.querySelector('#app-paper') || document.body;
639
- const text = textOfElement(app).slice(0, 3500);
640
- const isConfig = /Instanzeinstellungen:|Instance settings:|Gerät hinzufügen|Gerät bearbeiten|Geräteliste|Adapterkonfiguration|json exportieren|json importieren|Speichern und schließen|Save and close/i.test(text);
641
- document.documentElement.classList.toggle('eos-adapter-config-surface', !!isConfig);
642
- if (!isConfig) return;
643
-
644
- // Native adapter configuration UIs are owned by the adapter. EOS must never
645
- // block, rewrite or intercept their controls. This is critical for custom
646
- // React/HTML configuration pages such as nexowatt-devices.
647
- document.querySelectorAll('#app-paper button, #app-paper [role="button"], #app-paper a, #app-paper input, #app-paper select, #app-paper textarea, #app-paper [tabindex]').forEach(control => {
648
- if (control.closest('.eos-assist-root, #eos-assist-root, .eos-standalone-nav-toggle')) return;
649
- control.style.pointerEvents = 'auto';
650
- control.removeAttribute('aria-disabled');
651
- });
652
- document.querySelectorAll('#app-paper .eos-protected-delete-control, #app-paper .eos-security-hidden-delete, #app-paper .eos-protected-adapter-row').forEach(el => {
653
- el.classList.remove('eos-protected-delete-control', 'eos-security-hidden-delete', 'eos-protected-adapter-row');
654
- el.removeAttribute('aria-disabled');
655
- if (el.style) {
656
- el.style.pointerEvents = '';
657
- el.style.display = '';
658
- el.style.visibility = '';
659
- el.style.opacity = '';
660
- }
661
- if ('disabled' in el && !el.dataset.eosOriginalDisabled) el.disabled = false;
662
- });
663
- });
664
-
665
- const getLoginCard = () => {
666
- const input = document.querySelector('#username, input[name="username"], #password, input[type="password"]');
667
- return input ? input.closest('.MuiPaper-root, form, main > div') : null;
668
- };
669
-
670
- const patchLogin = () => safe(() => {
671
- forceLoginGlobals();
672
- sanitizeLoginHref();
673
- const hasApp = !!document.getElementById('app-paper');
674
- const card = hasApp ? null : getLoginCard();
675
- const isLogin = isLoginView();
676
- document.documentElement.classList.toggle('eos-login', isLogin);
677
- document.documentElement.classList.toggle('eos-loading', !document.body || !document.querySelector('#root > *'));
678
- if (isLogin) removeLogoutButton();
679
- if (!isLogin || !card) return;
680
- card.classList.add('eos-login-card');
681
- const titles = Array.from(card.querySelectorAll('h1,h2,h3,h4,h5,.MuiTypography-h5'));
682
- const title = titles.find(el => /management|nexowatt|admin|eos/i.test(el.textContent || '')) || titles[0];
683
- if (title && title.textContent.trim() !== BRAND) {
684
- title.textContent = BRAND;
685
- title.setAttribute('aria-label', BRAND_LONG);
686
- }
687
- const logo = card.querySelector('img');
688
- if (logo) patchImage(logo);
689
- Array.from(card.querySelectorAll('a, .MuiTypography-caption, .MuiTypography-body2')).forEach(el => {
690
- const text = (el.textContent || '').trim();
691
- if (/independent|transparent|fair|management|iobroker/i.test(text)) {
692
- el.textContent = `${BRAND} · ${EOS_MEANING}`;
693
- }
694
- });
695
- });
696
-
697
- const logout = () => {
698
- const nativeLogout = Array.from(document.querySelectorAll('a,button')).find(el => /^(abmelden|logout)$/i.test((el.textContent || '').trim()) && !el.classList.contains('eos-direct-logout'));
699
- if (nativeLogout) { nativeLogout.click(); return; }
700
- safe(() => {
701
- ['App.refreshToken', 'App.accessToken', 'App.token', 'tokens', 'iobroker.admin.token'].forEach(key => {
702
- window.localStorage && window.localStorage.removeItem(key);
703
- window.sessionStorage && window.sessionStorage.removeItem(key);
704
- });
705
- });
706
- const cleanRoot = ASSET_BASE.replace(/\/?$/, '/');
707
- window.location.assign(cleanRoot);
708
- };
709
-
710
-
711
- let hardLogoutTimer = 0;
712
- let hardLogoutPollTimer = 0;
713
- let hardLogoutInstalled = false;
714
-
715
- const clearAuthStorage = () => safe(() => {
716
- const storageKeys = [
717
- 'App.refreshToken', 'App.accessToken', 'App.token', 'tokens', 'iobroker.admin.token',
718
- 'access_token', 'refresh_token', 'oidc_id_token', 'oidc_access_token', 'oidc_refresh_token'
719
- ];
720
- storageKeys.forEach(key => {
721
- window.localStorage?.removeItem(key);
722
- window.sessionStorage?.removeItem(key);
723
- window._localStorage?.removeItem?.(key);
724
- });
725
- ['access_token', 'refresh_token', 'connect.sid', 'io', 'sid'].forEach(name => {
726
- document.cookie = `${name}=; Max-Age=0; path=/; SameSite=Lax`;
727
- document.cookie = `${name}=; Max-Age=0; path=${new URL(ASSET_BASE).pathname || '/'}; SameSite=Lax`;
728
- });
729
- });
730
-
731
- const hardLogout = () => {
732
- clearAuthStorage();
733
- const logoutUrl = new URL('logout', window.location.origin + '/');
734
- logoutUrl.searchParams.set('hard', '1');
735
- logoutUrl.searchParams.set('ts', String(Date.now()));
736
- window.location.replace(logoutUrl.href);
737
- };
738
-
739
- const scheduleHardLogoutCheck = delay => {
740
- if (hardLogoutPollTimer) window.clearTimeout(hardLogoutPollTimer);
741
- hardLogoutPollTimer = window.setTimeout(checkHardLogoutSession, Math.max(1000, delay || 15000));
742
- };
743
-
744
- async function checkHardLogoutSession() {
745
- if (isLoginView() || !document.getElementById('app-paper')) {
746
- scheduleHardLogoutCheck(10000);
747
- return;
748
- }
749
- try {
750
- const response = await fetch(new URL('session', ASSET_BASE).href, {
751
- credentials: 'same-origin',
752
- cache: 'no-store',
753
- headers: { accept: 'application/json' },
754
- });
755
- const data = await response.json().catch(() => ({}));
756
- const expireInSec = Number(data?.expireInSec);
757
- if (Number.isFinite(expireInSec) && expireInSec <= 0) {
758
- hardLogout();
759
- return;
760
- }
761
- if (Number.isFinite(expireInSec) && expireInSec > 0) {
762
- if (hardLogoutTimer) window.clearTimeout(hardLogoutTimer);
763
- hardLogoutTimer = window.setTimeout(hardLogout, Math.max(1200, expireInSec * 1000 + 500));
764
- scheduleHardLogoutCheck(Math.min(Math.max(5000, expireInSec * 500), 30000));
765
- return;
766
- }
767
- } catch (_) {
768
- // Network reconnects happen during updates/restarts. Do not log out on a transient request failure.
769
- }
770
- scheduleHardLogoutCheck(30000);
771
- }
772
-
773
- const installHardLogoutWatchdog = () => {
774
- // v36: disabled. Upstream ioBroker Admin session handling is used again so
775
- // the configured admin TTL is respected and native adapter config pages are
776
- // not interrupted by duplicate EOS timers.
777
- hardLogoutInstalled = true;
778
- };
779
-
780
- const ensureBrandBadge = toolbar => {
781
- if (!toolbar) return;
782
- document.querySelectorAll('.eos-brand-badge').forEach(existing => {
783
- if (!toolbar.contains(existing)) existing.remove();
784
- });
785
- let badge = toolbar.querySelector('.eos-brand-badge');
786
- if (!badge) {
787
- badge = document.createElement('span');
788
- badge.className = 'eos-brand-badge eos-system-brand';
789
- const firstButton = toolbar.querySelector('button');
790
- toolbar.insertBefore(badge, firstButton || toolbar.firstChild || null);
791
- }
792
- badge.classList.add('eos-system-brand');
793
- badge.innerHTML = `
794
- <span class="eos-brand-badge-mark"><img class="eos-brand-badge-logo" src="${LOGO}" alt="${BRAND}" /></span>
795
- <span class="eos-brand-badge-copy"><strong>${BRAND}</strong><small>${EOS_MEANING}</small></span>
796
- <span class="eos-brand-led"></span>
797
- `;
798
- };
799
-
800
- const ensureLogoutButton = () => {
801
- // v14: the custom EOS logout button remains disabled/removed.
802
- // The visible native logout menu item is hidden too because it caused broken redirects.
803
- removeLogoutButton();
804
- };
805
-
806
- const hideNativeLogoutNav = () => safe(() => {
807
- const candidates = Array.from(document.querySelectorAll('.MuiDrawer-paper a, .MuiDrawer-paper button, .MuiDrawer-paper li, .MuiDrawer-paper .MuiListItem-root, .MuiDrawer-paper .MuiListItemButton-root, .MuiDrawer-paper [role="button"], nav a, nav button, nav li, nav [role="button"]'));
808
- candidates.forEach(el => {
809
- const text = normalize(`${el.textContent || ''} ${el.getAttribute?.('aria-label') || ''} ${el.getAttribute?.('title') || ''}`);
810
- const href = String(el.getAttribute?.('href') || '');
811
- const isLogout = /(?:^|\b)(abmelden|logout|ra_logout)(?:\b|$)/.test(text) || /(?:^|[/?#])logout(?:[/?#]|$)/i.test(href);
812
- if (!isLogout) return;
813
- const targets = new Set([
814
- el,
815
- el.closest('.MuiListItem-root'),
816
- el.closest('li'),
817
- el.closest('.MuiListItemButton-root'),
818
- el.closest('.MuiButtonBase-root'),
819
- el.closest('a, button, [role="button"]'),
820
- ].filter(Boolean));
821
- targets.forEach(item => {
822
- item.classList.add('eos-hidden-logout', 'eos-native-logout-hidden');
823
- item.setAttribute('aria-hidden', 'true');
824
- item.setAttribute('tabindex', '-1');
825
- if (item.style) {
826
- item.style.display = 'none';
827
- item.style.visibility = 'hidden';
828
- item.style.pointerEvents = 'none';
829
- }
830
- });
831
- });
832
- });
833
-
834
- const patchDrawerHeader = drawer => safe(() => {
835
- if (!drawer) return;
836
- drawer.classList.add('eos-drawer');
837
- drawer.querySelectorAll('.eos-drawer-identity').forEach(el => el.remove());
838
-
839
- const directChildren = Array.from(drawer.children).filter(el => el.nodeType === 1);
840
- const isListLike = el => el.classList?.contains('MuiList-root') || el.querySelector?.('.MuiListItemButton-root');
841
- let header = drawer.querySelector(':scope > .eos-native-drawer-header');
842
- if (!header) {
843
- header = directChildren.find(el => !isListLike(el) && el.querySelector && el.querySelector('button') && (el.querySelector('img') || el.querySelector('.MuiAvatar-root') || el.querySelector('a')))
844
- || directChildren.find(el => !isListLike(el) && el.querySelector && (el.querySelector('button') || el.querySelector('img') || el.querySelector('.MuiAvatar-root')));
845
- }
846
- if (header) {
847
- header.classList.add('eos-native-drawer-header', 'eos-nav-toggle-shell');
848
- const toggleButton = header.querySelector('button, .MuiIconButton-root, [role="button"]');
849
- if (toggleButton && !toggleButton.dataset.eosNavCompactToggle) {
850
- toggleButton.dataset.eosNavCompactToggle = 'true';
851
- toggleButton.classList.add('eos-nav-compact-toggle');
852
- toggleButton.setAttribute('title', 'Navigation kompakt/normal umschalten');
853
- toggleButton.setAttribute('aria-label', 'Navigation kompakt/normal umschalten');
854
- const toggleCompact = event => {
855
- event.preventDefault();
856
- event.stopPropagation();
857
- if (event.stopImmediatePropagation) event.stopImmediatePropagation();
858
- const compact = !document.documentElement.classList.contains('eos-nav-compact');
859
- document.documentElement.classList.toggle('eos-nav-compact', compact);
860
- safe(() => localStorage.setItem('nexowatt:eosNavCompact', compact ? '1' : '0'));
861
- toggleButton.setAttribute('aria-pressed', compact ? 'true' : 'false');
862
- };
863
- toggleButton.addEventListener('click', toggleCompact, true);
864
- toggleButton.addEventListener('keydown', event => {
865
- if (event.key === 'Enter' || event.key === ' ') toggleCompact(event);
866
- }, true);
867
- }
868
- header.querySelectorAll('a,img,.MuiAvatar-root,.MuiAvatar-img,.eos-native-title').forEach(el => {
869
- if (!el.closest?.('button')) el.classList.add('eos-nav-toggle-decor-hidden');
870
- });
871
- const img = header.querySelector('img');
872
- if (img) patchImage(img);
873
- const avatarImg = header.querySelector('.MuiAvatar-img');
874
- if (avatarImg) patchImage(avatarImg);
875
- const logoArea = header.querySelector('a')?.parentElement || header.firstElementChild || header;
876
- if (logoArea && !logoArea.querySelector('.eos-native-title')) {
877
- const title = document.createElement('span');
878
- title.className = 'eos-native-title';
879
- title.innerHTML = `<strong>${BRAND}</strong><small>${EOS_MEANING}</small>`;
880
- const link = logoArea.querySelector('a');
881
- if (link && link.nextSibling) logoArea.insertBefore(title, link.nextSibling);
882
- else logoArea.appendChild(title);
883
- }
884
- }
885
- const list = drawer.querySelector('.MuiList-root');
886
- if (list) {
887
- list.classList.add('eos-scroll-nav');
888
- hideNativeLogoutNav();
889
- }
890
- });
891
-
892
- const patchShell = () => safe(() => {
893
- const hasApp = !!document.getElementById('app-paper');
894
- const login = isLoginView();
895
- document.documentElement.classList.toggle('eos-login', login);
896
- document.documentElement.classList.toggle('eos-app', !login && hasApp);
897
- setRouteClasses();
898
- if (login || !hasApp) {
899
- removeLogoutButton();
900
- return;
901
- }
902
- const toolbar = document.querySelector('#root > .MuiPaper-root > .MuiAppBar-root .MuiToolbar-root, header .MuiToolbar-root, .MuiAppBar-root .MuiToolbar-root');
903
- if (toolbar) {
904
- toolbar.classList.add('eos-top-toolbar');
905
- ensureBrandBadge(toolbar);
906
- }
907
- patchDrawerHeader(document.querySelector('.MuiDrawer-paper'));
908
- hideNativeLogoutNav();
909
- releaseNotificationControls();
910
- ensurePopupCompatibility();
911
- removeLogoutButton();
912
- });
913
-
914
- const ensureRightsHelper = () => safe(() => {
915
- const appPaper = document.getElementById('app-paper');
916
- if (!appPaper) return;
917
- const isUsers = routeInfo().users;
918
- const existing = appPaper.querySelector('.eos-rights-helper');
919
- if (!isUsers) {
920
- existing && existing.remove();
921
- return;
922
- }
923
- if (existing) return;
924
- const helper = document.createElement('section');
925
- helper.className = 'eos-rights-helper';
926
- helper.innerHTML = `
927
- <div class="eos-rights-helper-icon">🔐</div>
928
- <div class="eos-rights-helper-copy">
929
- <strong>Zugänge & Rechte</strong>
930
- <span>Benutzer werden Rollen zugeordnet. Wähle ein verständliches Rechteprofil und passe einzelne Rechte bei Bedarf an.</span>
931
- </div>
932
- <div class="eos-rights-helper-steps">
933
- <span>1 Benutzer</span><span>2 Rolle</span><span>3 Profil</span><span>4 Speichern</span>
934
- </div>
935
- `;
936
- appPaper.insertBefore(helper, appPaper.firstElementChild || null);
937
- });
938
-
939
- const normalize = text => String(text || '')
940
- .toLowerCase()
941
- .normalize('NFD')
942
- .replace(/[\u0300-\u036f]/g, '')
943
- .replace(/\s+/g, ' ')
944
- .trim();
945
-
946
- const permissionKey = label => {
947
- const text = normalize(label);
948
- if (/auflisten|list/.test(text)) return 'list';
949
- if (/lesen|read/.test(text)) return 'read';
950
- if (/schreiben|write/.test(text)) return 'write';
951
- if (/erstellen|create/.test(text)) return 'create';
952
- if (/loschen|delete/.test(text)) return 'delete';
953
- if (/shell|execute|ausfuhr/.test(text)) return 'execute';
954
- if (/http/.test(text)) return 'http';
955
- if (/sendto/.test(text)) return 'sendto';
956
- return '';
957
- };
958
-
959
- const sectionKey = label => {
960
- let el = label.parentElement;
961
- for (let i = 0; i < 7 && el; i += 1, el = el.parentElement) {
962
- const heading = el.querySelector && el.querySelector('h2,h3,h4,.MuiTypography-h6');
963
- if (heading && el.contains(label)) {
964
- const text = normalize(heading.textContent);
965
- if (/objekt|object/.test(text)) return 'object';
966
- if (/zustand|state/.test(text)) return 'state';
967
- if (/benutzer|user/.test(text)) return 'users';
968
- if (/datei|file/.test(text)) return 'file';
969
- if (/andere|other/.test(text)) return 'other';
970
- }
971
- }
972
- return 'unknown';
973
- };
974
-
975
- const desiredPermission = (profile, block, perm) => {
976
- if (!perm) return null;
977
- if (profile === 'enduser') profile = 'operator';
978
- if (profile === 'installer') profile = 'service';
979
- if (profile === 'admin') return true;
980
- if (profile === 'viewer') return ['object', 'state', 'file'].includes(block) && ['list', 'read'].includes(perm);
981
- if (profile === 'operator') {
982
- if (['object', 'state', 'file'].includes(block)) return ['list', 'read', 'write'].includes(perm);
983
- if (block === 'other') return perm === 'sendto';
984
- if (block === 'users') return false;
985
- }
986
- if (profile === 'service') {
987
- if (['object', 'state', 'file'].includes(block)) return ['list', 'read', 'write', 'create'].includes(perm);
988
- if (block === 'other') return ['sendto', 'execute'].includes(perm);
989
- if (block === 'users') return false;
990
- }
991
- return null;
992
- };
993
-
994
- const applyPermissionProfile = (dialog, profile) => {
995
- const labels = Array.from(dialog.querySelectorAll('label.MuiFormControlLabel-root'));
996
- labels.forEach(label => {
997
- const input = label.querySelector('input[type="checkbox"]');
998
- if (!input || input.disabled) return;
999
- const perm = permissionKey(label.textContent);
1000
- const block = sectionKey(label);
1001
- const desired = desiredPermission(profile, block, perm);
1002
- if (desired === null) return;
1003
- if (Boolean(input.checked) !== desired) input.click();
1004
- });
1005
- };
1006
-
1007
- const ensurePermissionPresets = () => safe(() => {
1008
- const dialogs = Array.from(document.querySelectorAll('.MuiDialog-paper'));
1009
- const dialog = dialogs.find(item => item.querySelectorAll('input[type="checkbox"]').length >= 8 && /rechte|permissions|berecht/i.test(item.textContent || ''));
1010
- if (!dialog || dialog.querySelector('.eos-permission-presets')) return;
1011
- const content = dialog.querySelector('.MuiDialogContent-root') || dialog;
1012
- const panel = document.createElement('section');
1013
- panel.className = 'eos-permission-presets';
1014
- panel.innerHTML = `
1015
- <div class="eos-permission-presets-title">EOS Rollen-Schnellprofile</div>
1016
- <div class="eos-permission-presets-text">NexoWatt EOS arbeitet mit drei Rollen: Admin, Installateur und Endkunde. Wähle ein Profil und passe danach bei Bedarf einzelne Rechte an.</div>
1017
- <div class="eos-permission-presets-actions">
1018
- <button type="button" data-profile="enduser">Endkunde</button>
1019
- <button type="button" data-profile="installer">Installateur</button>
1020
- <button type="button" data-profile="admin">Admin</button>
1021
- </div>
1022
- `;
1023
- panel.addEventListener('click', event => {
1024
- const button = event.target.closest('button[data-profile]');
1025
- if (!button) return;
1026
- applyPermissionProfile(dialog, button.getAttribute('data-profile'));
1027
- });
1028
- content.insertBefore(panel, content.firstElementChild || null);
1029
- });
1030
-
1031
-
1032
-
1033
-
1034
- const ensureNotificationDialogClasses = () => safe(() => {
1035
- document.querySelectorAll('.MuiDialog-root, .MuiModal-root, [role="presentation"]').forEach(root => {
1036
- const paper = root.querySelector?.('.MuiDialog-paper, [role="dialog"]');
1037
- if (!paper) return;
1038
- const txt = normalize(paper.textContent || '');
1039
- if (!/(benachrichtigungen|notifications|acknowledge|bestätigen|schließen|close)/i.test(txt) && !paper.querySelector('#notifications-dialog-close')) return;
1040
- root.classList.add('eos-notification-dialog-root');
1041
- paper.classList.add('eos-notification-dialog');
1042
- paper.querySelectorAll('button, [role="button"], a, .MuiButtonBase-root, .MuiIconButton-root').forEach(control => {
1043
- control.style.pointerEvents = 'auto';
1044
- control.style.userSelect = 'auto';
1045
- if (control.getAttribute('aria-disabled') === 'true' && /schließen|close/i.test(control.textContent || control.getAttribute('aria-label') || control.getAttribute('title') || '')) {
1046
- control.removeAttribute('aria-disabled');
1047
- }
1048
- });
1049
- });
1050
- });
1051
-
1052
- const ensureSettingsDialogClasses = () => safe(() => {
1053
- const dialogs = Array.from(document.querySelectorAll('.MuiDialog-paper, [role="dialog"]'));
1054
- dialogs.forEach(dialog => {
1055
- const title = dialog.querySelector('#base-settings-dialog-title, .dialogName');
1056
- const aria = (dialog.getAttribute('aria-labelledby') || '').toLowerCase();
1057
- const text = normalize(title?.textContent || dialog.textContent || '');
1058
- const isSettingsDialog =
1059
- aria.includes('system-settings-dialog-title') ||
1060
- aria.includes('base-settings-dialog-title') ||
1061
- /basiseinstellungen|base settings|host basis|host base settings|system repositories|standard acl|let'?s encrypt|zugangsdaten|zertifikate/.test(text);
1062
- if (!isSettingsDialog) return;
1063
- dialog.classList.add('eos-settings-dialog');
1064
- const content = dialog.querySelector('.MuiDialogContent-root');
1065
- if (content) content.classList.add('eos-settings-content');
1066
- const actions = dialog.querySelector('.MuiDialogActions-root');
1067
- if (actions) actions.classList.add('eos-settings-actions');
1068
- dialog.querySelectorAll('.leaflet-container').forEach(map => map.classList.add('eos-settings-map'));
1069
- });
1070
- });
1071
-
1072
-
1073
- const hideOfficialNexoWattRepoWarning = () => safe(() => {
1074
- const body = document.body || document.documentElement;
1075
- if (!body || !/repo|repository|nexowatt|gefahr|risk/i.test(body.textContent || '')) return;
1076
- const warningTextPattern = /(WARNUNG:\s*)?(Aktuelles Repository ist|Current repository is)\s+["“”']?nexowatt["“”']?.*(Benutzung auf eigene Gefahr|Use at own risk)?/i;
1077
- const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, {
1078
- acceptNode(node) {
1079
- const text = node.nodeValue || '';
1080
- return warningTextPattern.test(text) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
1081
- }
1082
- });
1083
- const hits = [];
1084
- let node;
1085
- while ((node = walker.nextNode())) hits.push(node);
1086
- hits.forEach(textNode => {
1087
- let target = textNode.parentElement;
1088
- const box = target && target.closest('.MuiBox-root, .MuiAlert-root, [role="alert"]');
1089
- if (box && warningTextPattern.test(box.textContent || '')) target = box;
1090
- else {
1091
- for (let i = 0; i < 5 && target && target.parentElement; i += 1) {
1092
- const txt = (target.textContent || '').trim();
1093
- if (warningTextPattern.test(txt) && txt.length < 220) break;
1094
- target = target.parentElement;
1095
- }
1096
- }
1097
- if (!target || !warningTextPattern.test(target.textContent || '')) return;
1098
- target.classList.add('eos-hidden-nexowatt-repo-warning');
1099
- target.setAttribute('aria-hidden', 'true');
1100
- target.style.display = 'none';
1101
- });
1102
- });
1103
-
1104
-
1105
-
1106
-
1107
- const patchNotifications = () => safe(() => {
1108
- // Kept for compatibility with older calls. v38 intentionally scopes this to
1109
- // snackbar/toast surfaces only; no dialogs, popovers or adapter config controls.
1110
- releaseNotificationControls();
1111
- ensurePopupCompatibility();
1112
- });
1113
-
1114
- const applyNavCompactPreference = () => safe(() => {
1115
- const compact = localStorage.getItem('nexowatt:eosNavCompact') === '1';
1116
- document.documentElement.classList.toggle('eos-nav-compact', compact);
1117
- document.querySelectorAll('.eos-nav-compact-toggle').forEach(button => {
1118
- button.setAttribute('aria-pressed', compact ? 'true' : 'false');
1119
- button.setAttribute('title', compact ? 'Navigation normal anzeigen' : 'Navigation kompakt anzeigen');
1120
- });
1121
- });
1122
-
1123
- const assistContext = () => {
1124
- const routes = routeInfo();
1125
- if (routes.adapters) return {
1126
- title: 'Module einrichten',
1127
- text: 'Wähle zuerst das passende Modul, prüfe Version und Instanzstatus und öffne dann die Konfiguration über die drei Punkte oder das Werkzeug-Symbol.',
1128
- steps: ['Modul suchen', 'Instanz anlegen', 'Verbindung testen', 'Datenpunkte prüfen']
1129
- };
1130
- if (routes.instances) return {
1131
- title: 'Dienste prüfen',
1132
- text: 'Kontrolliere Status, Port, Speicherverbrauch und Logmeldungen. Gestoppte Dienste erst nach Ursache und Abhängigkeiten prüfen.',
1133
- steps: ['Status ansehen', 'Log öffnen', 'Konfiguration prüfen', 'Dienst neu starten']
1134
- };
1135
- if (routes.users) return {
1136
- title: 'Zugänge & Rechte',
1137
- text: 'Installateure und Endkunden sollten nur die Module sehen, die sie wirklich bedienen dürfen. Geschützte EOS-Module bleiben Administratoren vorbehalten.',
1138
- steps: ['Benutzer wählen', 'Rolle zuordnen', 'Rechteprofil setzen', 'Löschschutz prüfen']
1139
- };
1140
- if (routeInfo().intro) return {
1141
- title: 'EOS Cockpit',
1142
- text: 'Beginne mit Systemstatus, Hosts und gesicherten Basisdiensten. Danach Module Schritt für Schritt freischalten.',
1143
- steps: ['System prüfen', 'Sicherung prüfen', 'Module planen', 'Rechte vergeben']
1144
- };
1145
- return {
1146
- title: 'EOS Bedienhilfe',
1147
- text: 'Ich unterstütze dich beim Einrichten, Prüfen und Absichern deiner EOS-Module.',
1148
- steps: ['Ziel beschreiben', 'Modul auswählen', 'Parameter prüfen', 'Test starten']
1149
- };
1150
- };
1151
-
1152
- const configuredAssistEndpoint = () => safe(() => {
1153
- const globalEndpoint = typeof window.NEXOWATT_EOS_ASSIST_ENDPOINT === 'string' ? window.NEXOWATT_EOS_ASSIST_ENDPOINT.trim() : '';
1154
- const storedEndpoint = localStorage.getItem('nexowatt:eosAssistEndpoint') || '';
1155
- return globalEndpoint || storedEndpoint.trim();
1156
- }) || '';
1157
-
1158
- const localAssistAnswer = query => {
1159
- const q = normalize(query);
1160
- if (!q) return 'Beschreibe kurz, was eingerichtet werden soll, zum Beispiel: Wallbox, PV, Speicher, Modbus, MQTT, Sicherung oder Benutzerrechte. EOS Assist zeigt mehrere Integrationswege und nicht nur einen einzelnen Adapter.';
1161
- if (/wallbox|evcs|lade|auto|ocpp|ladestation|charge/.test(q)) return [
1162
- 'Wallbox / Ladepunkt: Es gibt mehrere mögliche Integrationswege. Empfehlung nach Priorität prüfen:',
1163
- '1. Herstelleradapter: nutzen, wenn ein stabiler Adapter für Hersteller/Modell vorhanden ist.',
1164
- '2. Modbus TCP/RTU: bevorzugt für lokale EMS-Werte wie Leistung, Strom, Freigabe, Zählerstand und Phasen.',
1165
- '3. OCPP: passend, wenn die Wallbox als Ladepunkt-Backend angebunden werden soll oder mehrere Ladepunkte zentral verwaltet werden.',
1166
- '4. HTTP/REST oder MQTT: sinnvoll bei offenen APIs, eigener Firmware oder Gateway-Lösungen.',
1167
- '5. Datenpunkt-Mapping: Fallback, wenn Werte bereits aus einem anderen System kommen.',
1168
- 'Nächster Schritt: Hersteller, Modell, IP-Adresse und verfügbare Schnittstellen nennen. Dann kann EOS Assist den besten Weg vorschlagen.'
1169
- ].join('\n');
1170
- if (/keba|kecontact|mennekes|abl|alfen|easee|heidelberg|go-?e|openwb|zaptec|wallbe|duosida/.test(q)) return [
1171
- 'Wallbox-Hersteller erkannt. Bitte nicht automatisch nur OCPP verwenden.',
1172
- 'Prüfe zuerst: gibt es einen nativen Adapter oder eine lokale Modbus-/HTTP-Schnittstelle?',
1173
- 'OCPP ist gut für Backend-/Ladepunktverwaltung; Modbus/HTTP ist oft besser für lokale EMS-Regelung und schnelle Leistungswerte.',
1174
- 'Für EOS empfehle ich: lokale Schnittstelle für Regelung + OCPP nur, wenn Backend-Funktionen gebraucht werden.'
1175
- ].join('\n');
1176
- if (/pv|solar|wechselrichter|sun2000|fronius|kostal|sma|huawei|growatt|sungrow/.test(q)) return 'PV/Wechselrichter: Herstelleradapter oder Modbus TCP prüfen. Für EOS sind Erzeugung, Bezug, Einspeisung, Batterieladeleistung und Statusdaten wichtig. Erst Livewerte validieren, dann Optimierung aktivieren.';
1177
- if (/speicher|batterie|akku|soc/.test(q)) return 'Speicher: SoC, Lade-/Entladeleistung, Betriebsmodus und Grenzwerte prüfen. Schreibbefehle erst freigeben, wenn Lese-Datenpunkte stabil und plausibel sind.';
1178
- if (/modbus/.test(q)) return 'Modbus: IP/Port 502, Unit-ID, Registerliste, Datentyp und Byte-Reihenfolge prüfen. Erst nur lesen testen, danach Schreibrechte gezielt und mit Schutzliste freischalten.';
1179
- if (/mqtt/.test(q)) return 'MQTT: Broker, Authentifizierung, Topic-Struktur und TLS prüfen. Mit Test-Topic starten, dann produktive Topics in EOS-Datenpunkte mappen.';
1180
- if (/backup|sicherung|restore|backitup/.test(q)) return 'Sicherung: BackItUp aktiv halten, Zielpfad/Cloud-Ziel testen, Test-Backup erstellen und Restore-Ablauf dokumentieren. BackItUp bleibt Systemadapter und sollte geschützt sein.';
1181
- if (/rechte|benutzer|installateur|kunde|admin|sicherheit|security/.test(q)) return 'Rechte: Administratoren verwalten Systemschutz. Installateure dürfen konfigurieren, aber geschützte Systemadapter nicht löschen, stoppen oder kritisch ändern. Endkunden bekommen Bedien- und Leserechte.';
1182
- if (/fehler|log|offline|404|timeout|startet nicht|server/.test(q)) return 'Fehlersuche: Systemlogs filtern, betroffene Instanz prüfen, letzte Änderung identifizieren, Dienst neu starten und danach Port, WebSocket, Repository und Paketversion kontrollieren.';
1183
- return 'EOS Assist Empfehlung: Gerätetyp, Hersteller/Modell und verfügbare Schnittstellen nennen. Danach wird der beste Integrationsweg gewählt: nativer Adapter, Modbus, OCPP, HTTP/REST, MQTT oder Datenpunkt-Mapping.';
1184
- };
1185
-
1186
- const requestRemoteAssist = async query => {
1187
- const endpoint = configuredAssistEndpoint();
1188
- if (!endpoint) return '';
1189
- try {
1190
- const response = await fetch(endpoint, {
1191
- method: 'POST',
1192
- credentials: 'same-origin',
1193
- headers: { 'content-type': 'application/json' },
1194
- body: JSON.stringify({ query, route: window.location.hash || '', ui: 'nexowatt-eos-admin' }),
1195
- });
1196
- if (!response.ok) return '';
1197
- const data = await response.json().catch(() => ({}));
1198
- return String(data.answer || data.text || data.message || '').trim();
1199
- } catch { return ''; }
1200
- };
1201
-
1202
- const assistAnswer = query => localAssistAnswer(query);
1203
-
1204
- const sendAssistQuestion = async (root, query) => {
1205
- const out = root?.querySelector?.('.eos-assist-answer');
1206
- if (!out) return;
1207
- const endpoint = configuredAssistEndpoint();
1208
- if (endpoint) out.textContent = 'EOS Assist fragt die KI an ...';
1209
- const remote = endpoint ? await requestRemoteAssist(query) : '';
1210
- out.textContent = remote || localAssistAnswer(query);
1211
- };
1212
-
1213
- const ensureEosAssist = () => safe(() => {
1214
- const hasApp = !!document.getElementById('app-paper');
1215
- if (!hasApp || isLoginView()) {
1216
- document.getElementById('eos-assist-root')?.remove();
1217
- document.querySelectorAll('.eos-assist-launcher,.eos-assist-panel:not(#eos-assist-root .eos-assist-panel)').forEach(el => el.remove());
1218
- return;
1219
- }
1220
- if (isAdapterConfigSurface()) {
1221
- const existing = document.getElementById('eos-assist-root');
1222
- if (existing) existing.classList.add('eos-assist-config-hidden');
1223
- return;
1224
- }
1225
-
1226
- let root = document.getElementById('eos-assist-root');
1227
- if (!root) {
1228
- root = document.createElement('section');
1229
- root.id = 'eos-assist-root';
1230
- root.className = 'eos-assist-root';
1231
- root.innerHTML = `
1232
- <button class="eos-assist-button" type="button" aria-expanded="false">
1233
- <span class="eos-assist-dot"></span><strong>EOS Assist</strong><small>KI-Hilfe</small>
1234
- </button>
1235
- <div class="eos-assist-panel" role="dialog" aria-label="EOS Assist Einrichtungshilfe">
1236
- <div class="eos-assist-head">
1237
- <span class="eos-assist-logo"><img src="${LOGO}" alt="NexoWatt EOS" /></span>
1238
- <div><strong class="eos-assist-title"></strong><span class="eos-assist-text"></span></div>
1239
- <button type="button" class="eos-assist-close" aria-label="EOS Assist schließen">×</button>
1240
- </div>
1241
- <div class="eos-assist-steps"></div>
1242
- <div class="eos-assist-actions">
1243
- <button type="button" data-question="Wallbox einrichten: Welche Wege gibt es?">Wallbox</button>
1244
- <button type="button" data-question="Wie richte ich dieses Modul ein?">Modul einrichten</button>
1245
- <button type="button" data-question="Wie prüfe ich Fehler in den Logs?">Fehler prüfen</button>
1246
- <button type="button" data-question="Welche Rechte braucht der Installateur?">Rechte erklären</button>
1247
- <button type="button" data-question="Was muss ich vor einem Update beachten?">Update-Check</button>
1248
- </div>
1249
- <label class="eos-assist-input-label">Was möchtest du einrichten?</label>
1250
- <div class="eos-assist-input-row"><input class="eos-assist-input" placeholder="z. B. Wallbox Keba Modbus, OCPP, PV, Rechte..." /><button type="button" class="eos-assist-send">Fragen</button></div>
1251
- <div class="eos-assist-answer"></div>
1252
- <div class="eos-assist-foot">EOS Assist nutzt eine lokale Entscheidungslogik und ist für eine echte NexoWatt-KI-Anbindung vorbereitet.</div>
1253
- </div>
1254
- `;
1255
- document.body.appendChild(root);
1256
- }
1257
-
1258
- root.classList.remove('eos-assist-config-hidden');
1259
- const ctx = assistContext();
1260
- const button = root.querySelector('.eos-assist-button');
1261
- const input = root.querySelector('.eos-assist-input');
1262
- const answer = root.querySelector('.eos-assist-answer');
1263
- root.querySelector('.eos-assist-title').textContent = ctx.title;
1264
- root.querySelector('.eos-assist-text').textContent = ctx.text;
1265
- root.querySelector('.eos-assist-steps').innerHTML = ctx.steps.map(step => `<span>${step}</span>`).join('');
1266
- if (answer && !answer.textContent) answer.textContent = assistAnswer('');
1267
- root.classList.toggle('eos-assist-open', !!state.assistOpen);
1268
- button?.setAttribute('aria-expanded', state.assistOpen ? 'true' : 'false');
1269
-
1270
- if (!root.dataset.eosAssistBound) {
1271
- root.dataset.eosAssistBound = 'true';
1272
- root.addEventListener('click', event => {
1273
- const target = event.target?.closest?.('button');
1274
- if (!target || !root.contains(target)) return;
1275
- if (target.classList.contains('eos-assist-button')) {
1276
- event.preventDefault();
1277
- event.stopPropagation();
1278
- state.assistOpen = !state.assistOpen;
1279
- root.classList.toggle('eos-assist-open', state.assistOpen);
1280
- target.setAttribute('aria-expanded', state.assistOpen ? 'true' : 'false');
1281
- if (state.assistOpen) setTimeout(() => root.querySelector('.eos-assist-input')?.focus(), 50);
1282
- return;
1283
- }
1284
- if (target.classList.contains('eos-assist-close')) {
1285
- event.preventDefault();
1286
- state.assistOpen = false;
1287
- root.classList.remove('eos-assist-open');
1288
- root.querySelector('.eos-assist-button')?.setAttribute('aria-expanded', 'false');
1289
- return;
1290
- }
1291
- if (target.classList.contains('eos-assist-send')) {
1292
- event.preventDefault();
1293
- const value = root.querySelector('.eos-assist-input')?.value || '';
1294
- const out = root.querySelector('.eos-assist-answer');
1295
- sendAssistQuestion(root, value);
1296
- return;
1297
- }
1298
- if (target.hasAttribute('data-question')) {
1299
- event.preventDefault();
1300
- const question = target.getAttribute('data-question') || '';
1301
- const field = root.querySelector('.eos-assist-input');
1302
- if (field) field.value = question;
1303
- const out = root.querySelector('.eos-assist-answer');
1304
- sendAssistQuestion(root, question);
1305
- }
1306
- }, true);
1307
- root.addEventListener('keydown', event => {
1308
- if (event.key !== 'Enter' || !event.target?.classList?.contains('eos-assist-input')) return;
1309
- const out = root.querySelector('.eos-assist-answer');
1310
- sendAssistQuestion(root, event.target.value || '');
1311
- }, true);
1312
- }
1313
- });
1314
-
1315
-
1316
-
1317
- const installAssistDelegatedClick = () => safe(() => {
1318
- if (window.__NEXOWATT_EOS_ASSIST_BRANDING_CLICK__) return;
1319
- window.__NEXOWATT_EOS_ASSIST_BRANDING_CLICK__ = true;
1320
- document.addEventListener('click', event => {
1321
- const target = event.target?.closest?.('.eos-assist-button,.eos-assist-close,.eos-assist-send');
1322
- if (!target) return;
1323
- const root = document.getElementById('eos-assist-root') || target.closest('.eos-assist-root');
1324
- if (!root) return;
1325
- const input = root.querySelector('.eos-assist-input');
1326
- const answer = root.querySelector('.eos-assist-answer');
1327
- if (target.matches('.eos-assist-button')) {
1328
- event.preventDefault();
1329
- event.stopPropagation();
1330
- event.stopImmediatePropagation?.();
1331
- state.assistOpen = !root.classList.contains('eos-assist-open');
1332
- root.classList.toggle('eos-assist-open', state.assistOpen);
1333
- target.setAttribute('aria-expanded', state.assistOpen ? 'true' : 'false');
1334
- if (state.assistOpen) setTimeout(() => input?.focus(), 40);
1335
- } else if (target.matches('.eos-assist-close')) {
1336
- event.preventDefault();
1337
- event.stopPropagation();
1338
- event.stopImmediatePropagation?.();
1339
- state.assistOpen = false;
1340
- root.classList.remove('eos-assist-open');
1341
- root.querySelector('.eos-assist-button')?.setAttribute('aria-expanded', 'false');
1342
- } else if (target.matches('.eos-assist-send')) {
1343
- event.preventDefault();
1344
- event.stopPropagation();
1345
- event.stopImmediatePropagation?.();
1346
- sendAssistQuestion(root, input?.value || '');
1347
- state.assistOpen = true;
1348
- root.classList.add('eos-assist-open');
1349
- }
1350
- }, true);
1351
- });
1352
-
1353
-
1354
- const ensureStandaloneNavToggle = () => safe(() => {
1355
- const html = document.documentElement;
1356
- if (!html.classList.contains('eos-app') || html.classList.contains('eos-login')) {
1357
- document.getElementById('eos-standalone-nav-toggle')?.remove();
1358
- return;
1359
- }
1360
- let button = document.getElementById('eos-standalone-nav-toggle');
1361
- if (!button) {
1362
- button = document.createElement('button');
1363
- button.id = 'eos-standalone-nav-toggle';
1364
- button.type = 'button';
1365
- button.className = 'eos-standalone-nav-toggle';
1366
- button.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M14.8 5.4 8.2 12l6.6 6.6" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>';
1367
- const toggle = event => {
1368
- event.preventDefault();
1369
- event.stopPropagation();
1370
- event.stopImmediatePropagation?.();
1371
- const compact = !document.documentElement.classList.contains('eos-nav-compact');
1372
- document.documentElement.classList.toggle('eos-nav-compact', compact);
1373
- safe(() => localStorage.setItem('nexowatt:eosNavCompact', compact ? '1' : '0'));
1374
- button.setAttribute('aria-pressed', compact ? 'true' : 'false');
1375
- button.setAttribute('title', compact ? 'Navigation normal anzeigen' : 'Navigation kompakt anzeigen');
1376
- button.setAttribute('aria-label', compact ? 'Navigation normal anzeigen' : 'Navigation kompakt anzeigen');
1377
- };
1378
- button.addEventListener('click', toggle, true);
1379
- button.addEventListener('keydown', event => {
1380
- if (event.key === 'Enter' || event.key === ' ') toggle(event);
1381
- }, true);
1382
- document.body.appendChild(button);
1383
- }
1384
- const compact = document.documentElement.classList.contains('eos-nav-compact') || safe(() => localStorage.getItem('nexowatt:eosNavCompact') === '1');
1385
- document.documentElement.classList.toggle('eos-nav-compact', !!compact);
1386
- button.setAttribute('aria-pressed', compact ? 'true' : 'false');
1387
- button.setAttribute('title', compact ? 'Navigation normal anzeigen' : 'Navigation kompakt anzeigen');
1388
- button.setAttribute('aria-label', compact ? 'Navigation normal anzeigen' : 'Navigation kompakt anzeigen');
1389
- });
1390
-
1391
- const patchDocumentMeta = () => safe(() => {
1392
- document.title = BRAND_LONG;
1393
- const theme = document.querySelector('meta[name="theme-color"]');
1394
- if (theme) theme.setAttribute('content', '#020914');
1395
- const desc = document.querySelector('meta[name="description"]');
1396
- if (desc) desc.setAttribute('content', BRAND_LONG);
1397
- });
1398
-
1399
- const fullPatch = () => {
1400
- state.fullPatchScheduled = false;
1401
- state.lastFullPatch = Date.now();
1402
- forceLoginGlobals();
1403
- sanitizeLoginHref();
1404
- normalizeBadAddressAfterLogin();
1405
- patchDocumentMeta();
1406
- patchLogin();
1407
- patchShell();
1408
- markAdapterConfigSurface();
1409
- applyNavCompactPreference();
1410
- ensureStandaloneNavToggle();
1411
- installAssistDelegatedClick();
1412
- ensureEosAssist();
1413
- installHardLogoutWatchdog();
1414
- ensureSettingsDialogClasses();
1415
- hideNativeLogoutNav();
1416
- releaseNotificationControls();
1417
- ensurePopupCompatibility();
1418
- if (!isHighLoadAdminSurface()) {
1419
- ensureRightsHelper();
1420
- ensurePermissionPresets();
1421
- hideOfficialNexoWattRepoWarning();
1422
- applySecurityUiGuard();
1423
- }
1424
- if (isAdapterConfigSurface()) {
1425
- // Adapter-owned configuration pages must not be rebranded or structurally patched.
1426
- // We still repair broken UTF-8/mojibake text because jsonConfig labels can be
1427
- // rendered through different legacy paths. This is text-only and does not touch
1428
- // adapter controls, React state, events or attributes.
1429
- patchMojibakeTextNodes(document.getElementById('app-paper'));
1430
- ['.MuiAppBar-root', '.MuiDrawer-paper', 'nav', '.eos-brand-badge', '.eos-top-toolbar'].forEach(selector => {
1431
- document.querySelectorAll(selector).forEach(scope => {
1432
- patchTextNodes(scope);
1433
- patchAttributes(scope);
1434
- });
1435
- });
1436
- } else if (isHighLoadAdminSurface()) {
1437
- // v55: on large virtualized tables do not walk the whole app body.
1438
- // Full text scans were competing with ObjectBrowser state loading.
1439
- ['.MuiAppBar-root', '.MuiDrawer-paper', 'nav', '.eos-brand-badge', '.eos-top-toolbar', '.MuiDialog-root'].forEach(selector => {
1440
- document.querySelectorAll(selector).forEach(scope => {
1441
- patchTextNodes(scope);
1442
- patchAttributes(scope);
1443
- });
1444
- });
1445
- } else {
1446
- patchTextNodes(document.body || document.documentElement);
1447
- patchAttributes(document.body || document.documentElement);
1448
- }
1449
- };
1450
-
1451
- const scopePatch = () => {
1452
- state.scopePatchScheduled = false;
1453
- const scopes = Array.from(state.pendingScopes);
1454
- state.pendingScopes.clear();
1455
- normalizeBadAddressAfterLogin();
1456
- patchLogin();
1457
- patchShell();
1458
- markAdapterConfigSurface();
1459
- applyNavCompactPreference();
1460
- ensureStandaloneNavToggle();
1461
- installAssistDelegatedClick();
1462
- ensureEosAssist();
1463
- installHardLogoutWatchdog();
1464
- ensureSettingsDialogClasses();
1465
- ensurePopupCompatibility();
1466
- hideNativeLogoutNav();
1467
- releaseNotificationControls();
1468
- if (!isHighLoadAdminSurface()) {
1469
- ensureRightsHelper();
1470
- ensurePermissionPresets();
1471
- hideOfficialNexoWattRepoWarning();
1472
- applySecurityUiGuard();
1473
- }
1474
- const scopeLimit = isHighLoadAdminSurface() ? 10 : 40;
1475
- for (const scope of scopes.slice(0, scopeLimit)) {
1476
- if (!scope || !scope.isConnected) continue;
1477
- if (isHighLoadAdminSurface() && (scope.id === 'app-paper' || isInsideAppPaper(scope))) continue;
1478
- if (isAdapterConfigSurface() && (scope.id === 'app-paper' || scope.closest?.('#app-paper'))) {
1479
- patchMojibakeTextNodes(scope);
1480
- continue;
1481
- }
1482
- patchTextNodes(scope);
1483
- patchAttributes(scope);
1484
- }
1485
- };
1486
-
1487
- const scheduleFullPatch = delay => {
1488
- if (state.fullPatchScheduled && !delay) return;
1489
- state.fullPatchScheduled = true;
1490
- const run = () => {
1491
- if ('requestIdleCallback' in window) window.requestIdleCallback(fullPatch, { timeout: 800 });
1492
- else window.requestAnimationFrame(fullPatch);
1493
- };
1494
- if (delay) window.setTimeout(run, delay);
1495
- else run();
1496
- };
1497
-
1498
- const scheduleScopePatch = () => {
1499
- if (state.scopePatchScheduled) return;
1500
- state.scopePatchScheduled = true;
1501
- const run = () => {
1502
- if ('requestIdleCallback' in window) window.requestIdleCallback(scopePatch, { timeout: isHighLoadAdminSurface() ? 1200 : 600 });
1503
- else window.requestAnimationFrame(scopePatch);
1504
- };
1505
- if (isHighLoadAdminSurface()) window.setTimeout(run, 150);
1506
- else run();
1507
- };
1508
-
1509
- const installObserver = () => safe(() => {
1510
- if (state.unsubscribeDom) return;
1511
- const onMutations = mutations => {
1512
- for (const mutation of mutations) {
1513
- if (mutation.type !== 'childList') continue;
1514
- mutation.addedNodes.forEach(node => {
1515
- if (!node) return;
1516
- if (node.nodeType === Node.TEXT_NODE) {
1517
- if (isAdapterConfigSurface() && node.parentElement?.closest?.('#app-paper')) patchMojibakeTextNode(node);
1518
- else patchTextNode(node);
1519
- } else if (node.nodeType === Node.ELEMENT_NODE) {
1520
- if (isHighLoadAdminSurface() && isInsideAppPaper(node)) return;
1521
- state.pendingScopes.add(node);
1522
- }
1523
- });
1524
- }
1525
- if (state.pendingScopes.size) scheduleScopePatch();
1526
- };
1527
- const coordinator = window.NEXOWATT_EOS_DOM_COORDINATOR;
1528
- if (coordinator?.subscribe) state.unsubscribeDom = coordinator.subscribe(onMutations);
1529
- });
1530
-
1531
- forceLoginGlobals();
1532
- if (document.readyState === 'loading') {
1533
- document.addEventListener('DOMContentLoaded', () => {
1534
- fullPatch();
1535
- fetchSecurityPolicy();
1536
- installObserver();
1537
- [450].forEach(scheduleFullPatch);
1538
- }, { once: true });
1539
- } else {
1540
- fullPatch();
1541
- fetchSecurityPolicy();
1542
- installObserver();
1543
- [450].forEach(scheduleFullPatch);
1544
- }
1545
- window.addEventListener('load', () => scheduleFullPatch(0), { once: true });
1546
- window.addEventListener('hashchange', () => scheduleFullPatch(0));
1547
- })();