@iobroker/gui-components 8.0.1

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 (368) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1450 -0
  3. package/build/AdminConnection.d.ts +1 -0
  4. package/build/AdminConnection.js +2 -0
  5. package/build/AdminConnection.js.map +1 -0
  6. package/build/Components/404.d.ts +4 -0
  7. package/build/Components/404.js +97 -0
  8. package/build/Components/404.js.map +1 -0
  9. package/build/Components/ColorPicker.d.ts +86 -0
  10. package/build/Components/ColorPicker.js +222 -0
  11. package/build/Components/ColorPicker.js.map +1 -0
  12. package/build/Components/ComplexCron.d.ts +40 -0
  13. package/build/Components/ComplexCron.js +401 -0
  14. package/build/Components/ComplexCron.js.map +1 -0
  15. package/build/Components/CopyToClipboard.d.ts +14 -0
  16. package/build/Components/CopyToClipboard.js +160 -0
  17. package/build/Components/CopyToClipboard.js.map +1 -0
  18. package/build/Components/CustomModal.d.ts +26 -0
  19. package/build/Components/CustomModal.js +62 -0
  20. package/build/Components/CustomModal.js.map +1 -0
  21. package/build/Components/DeviceType/DeviceTypeIcon.d.ts +29 -0
  22. package/build/Components/DeviceType/DeviceTypeIcon.js +108 -0
  23. package/build/Components/DeviceType/DeviceTypeIcon.js.map +1 -0
  24. package/build/Components/DeviceType/DeviceTypeOptions.d.ts +2 -0
  25. package/build/Components/DeviceType/DeviceTypeOptions.js +69 -0
  26. package/build/Components/DeviceType/DeviceTypeOptions.js.map +1 -0
  27. package/build/Components/DeviceType/DeviceTypeSelector.d.ts +20 -0
  28. package/build/Components/DeviceType/DeviceTypeSelector.js +83 -0
  29. package/build/Components/DeviceType/DeviceTypeSelector.js.map +1 -0
  30. package/build/Components/DeviceType/deviceTypeTranslations.d.ts +1 -0
  31. package/build/Components/DeviceType/deviceTypeTranslations.js +30 -0
  32. package/build/Components/DeviceType/deviceTypeTranslations.js.map +1 -0
  33. package/build/Components/DeviceType/i18n/de.json +46 -0
  34. package/build/Components/DeviceType/i18n/en.json +46 -0
  35. package/build/Components/DeviceType/i18n/fr.json +46 -0
  36. package/build/Components/DeviceType/i18n/it.json +46 -0
  37. package/build/Components/DeviceType/i18n/nl.json +46 -0
  38. package/build/Components/DeviceType/i18n/pl.json +46 -0
  39. package/build/Components/DeviceType/i18n/pt.json +46 -0
  40. package/build/Components/DeviceType/i18n/ru.json +46 -0
  41. package/build/Components/DeviceType/i18n/uk.json +46 -0
  42. package/build/Components/DeviceType/i18n/zh-cn.json +46 -0
  43. package/build/Components/DeviceType/icons/Cleaner.d.ts +3 -0
  44. package/build/Components/DeviceType/icons/Cleaner.js +14 -0
  45. package/build/Components/DeviceType/icons/Cleaner.js.map +1 -0
  46. package/build/Components/DeviceType/icons/DoorClosed.d.ts +3 -0
  47. package/build/Components/DeviceType/icons/DoorClosed.js +7 -0
  48. package/build/Components/DeviceType/icons/DoorClosed.js.map +1 -0
  49. package/build/Components/DeviceType/icons/DoorOpened.d.ts +3 -0
  50. package/build/Components/DeviceType/icons/DoorOpened.js +7 -0
  51. package/build/Components/DeviceType/icons/DoorOpened.js.map +1 -0
  52. package/build/Components/DeviceType/icons/FireOff.d.ts +3 -0
  53. package/build/Components/DeviceType/icons/FireOff.js +8 -0
  54. package/build/Components/DeviceType/icons/FireOff.js.map +1 -0
  55. package/build/Components/DeviceType/icons/FireOn.d.ts +3 -0
  56. package/build/Components/DeviceType/icons/FireOn.js +14 -0
  57. package/build/Components/DeviceType/icons/FireOn.js.map +1 -0
  58. package/build/Components/DeviceType/icons/FloodOff.d.ts +3 -0
  59. package/build/Components/DeviceType/icons/FloodOff.js +11 -0
  60. package/build/Components/DeviceType/icons/FloodOff.js.map +1 -0
  61. package/build/Components/DeviceType/icons/FloodOn.d.ts +3 -0
  62. package/build/Components/DeviceType/icons/FloodOn.js +18 -0
  63. package/build/Components/DeviceType/icons/FloodOn.js.map +1 -0
  64. package/build/Components/DeviceType/icons/Gate.d.ts +3 -0
  65. package/build/Components/DeviceType/icons/Gate.js +8 -0
  66. package/build/Components/DeviceType/icons/Gate.js.map +1 -0
  67. package/build/Components/DeviceType/icons/HeatValve.d.ts +3 -0
  68. package/build/Components/DeviceType/icons/HeatValve.js +6 -0
  69. package/build/Components/DeviceType/icons/HeatValve.js.map +1 -0
  70. package/build/Components/DeviceType/icons/Home.d.ts +3 -0
  71. package/build/Components/DeviceType/icons/Home.js +6 -0
  72. package/build/Components/DeviceType/icons/Home.js.map +1 -0
  73. package/build/Components/DeviceType/icons/Humidity.d.ts +3 -0
  74. package/build/Components/DeviceType/icons/Humidity.js +8 -0
  75. package/build/Components/DeviceType/icons/Humidity.js.map +1 -0
  76. package/build/Components/DeviceType/icons/IconHome.d.ts +5 -0
  77. package/build/Components/DeviceType/icons/IconHome.js +21 -0
  78. package/build/Components/DeviceType/icons/IconHome.js.map +1 -0
  79. package/build/Components/DeviceType/icons/Jalousie.d.ts +3 -0
  80. package/build/Components/DeviceType/icons/Jalousie.js +7 -0
  81. package/build/Components/DeviceType/icons/Jalousie.js.map +1 -0
  82. package/build/Components/DeviceType/icons/Material.d.ts +3 -0
  83. package/build/Components/DeviceType/icons/Material.js +8 -0
  84. package/build/Components/DeviceType/icons/Material.js.map +1 -0
  85. package/build/Components/DeviceType/icons/MotionOff.d.ts +3 -0
  86. package/build/Components/DeviceType/icons/MotionOff.js +11 -0
  87. package/build/Components/DeviceType/icons/MotionOff.js.map +1 -0
  88. package/build/Components/DeviceType/icons/MotionOn.d.ts +3 -0
  89. package/build/Components/DeviceType/icons/MotionOn.js +7 -0
  90. package/build/Components/DeviceType/icons/MotionOn.js.map +1 -0
  91. package/build/Components/DeviceType/icons/PushButton.d.ts +3 -0
  92. package/build/Components/DeviceType/icons/PushButton.js +9 -0
  93. package/build/Components/DeviceType/icons/PushButton.js.map +1 -0
  94. package/build/Components/DeviceType/icons/RGB.d.ts +3 -0
  95. package/build/Components/DeviceType/icons/RGB.js +43 -0
  96. package/build/Components/DeviceType/icons/RGB.js.map +1 -0
  97. package/build/Components/DeviceType/icons/RepairExpert.d.ts +3 -0
  98. package/build/Components/DeviceType/icons/RepairExpert.js +6 -0
  99. package/build/Components/DeviceType/icons/RepairExpert.js.map +1 -0
  100. package/build/Components/DeviceType/icons/Socket.d.ts +3 -0
  101. package/build/Components/DeviceType/icons/Socket.js +8 -0
  102. package/build/Components/DeviceType/icons/Socket.js.map +1 -0
  103. package/build/Components/DeviceType/icons/Thermometer.d.ts +3 -0
  104. package/build/Components/DeviceType/icons/Thermometer.js +7 -0
  105. package/build/Components/DeviceType/icons/Thermometer.js.map +1 -0
  106. package/build/Components/DeviceType/icons/ThermometerSimple.d.ts +3 -0
  107. package/build/Components/DeviceType/icons/ThermometerSimple.js +8 -0
  108. package/build/Components/DeviceType/icons/ThermometerSimple.js.map +1 -0
  109. package/build/Components/DeviceType/icons/Thermostat.d.ts +3 -0
  110. package/build/Components/DeviceType/icons/Thermostat.js +9 -0
  111. package/build/Components/DeviceType/icons/Thermostat.js.map +1 -0
  112. package/build/Components/DeviceType/icons/Valve.d.ts +3 -0
  113. package/build/Components/DeviceType/icons/Valve.js +7 -0
  114. package/build/Components/DeviceType/icons/Valve.js.map +1 -0
  115. package/build/Components/DeviceType/icons/WindowClosed.d.ts +3 -0
  116. package/build/Components/DeviceType/icons/WindowClosed.js +8 -0
  117. package/build/Components/DeviceType/icons/WindowClosed.js.map +1 -0
  118. package/build/Components/DeviceType/icons/WindowOpened.d.ts +3 -0
  119. package/build/Components/DeviceType/icons/WindowOpened.js +9 -0
  120. package/build/Components/DeviceType/icons/WindowOpened.js.map +1 -0
  121. package/build/Components/DeviceType/icons/WindowTilted.d.ts +3 -0
  122. package/build/Components/DeviceType/icons/WindowTilted.js +8 -0
  123. package/build/Components/DeviceType/icons/WindowTilted.js.map +1 -0
  124. package/build/Components/DeviceType/icons/index.d.ts +28 -0
  125. package/build/Components/DeviceType/icons/index.js +28 -0
  126. package/build/Components/DeviceType/icons/index.js.map +1 -0
  127. package/build/Components/FileBrowser.d.ts +187 -0
  128. package/build/Components/FileBrowser.js +1711 -0
  129. package/build/Components/FileBrowser.js.map +1 -0
  130. package/build/Components/FileViewer.d.ts +49 -0
  131. package/build/Components/FileViewer.js +247 -0
  132. package/build/Components/FileViewer.js.map +1 -0
  133. package/build/Components/Icon.d.ts +35 -0
  134. package/build/Components/Icon.js +140 -0
  135. package/build/Components/Icon.js.map +1 -0
  136. package/build/Components/IconPicker.d.ts +25 -0
  137. package/build/Components/IconPicker.js +72 -0
  138. package/build/Components/IconPicker.js.map +1 -0
  139. package/build/Components/IconSelector.d.ts +33 -0
  140. package/build/Components/IconSelector.js +2086 -0
  141. package/build/Components/IconSelector.js.map +1 -0
  142. package/build/Components/Image.d.ts +31 -0
  143. package/build/Components/Image.js +126 -0
  144. package/build/Components/Image.js.map +1 -0
  145. package/build/Components/InfoBox.d.ts +37 -0
  146. package/build/Components/InfoBox.js +115 -0
  147. package/build/Components/InfoBox.js.map +1 -0
  148. package/build/Components/IobUri.d.ts +14 -0
  149. package/build/Components/IobUri.js +168 -0
  150. package/build/Components/IobUri.js.map +1 -0
  151. package/build/Components/Loader.d.ts +31 -0
  152. package/build/Components/Loader.js +265 -0
  153. package/build/Components/Loader.js.map +1 -0
  154. package/build/Components/Loaders/MV.d.ts +17 -0
  155. package/build/Components/Loaders/MV.js +61 -0
  156. package/build/Components/Loaders/MV.js.map +1 -0
  157. package/build/Components/Loaders/PT.d.ts +27 -0
  158. package/build/Components/Loaders/PT.js +150 -0
  159. package/build/Components/Loaders/PT.js.map +1 -0
  160. package/build/Components/Loaders/Vendor.d.ts +22 -0
  161. package/build/Components/Loaders/Vendor.js +52 -0
  162. package/build/Components/Loaders/Vendor.js.map +1 -0
  163. package/build/Components/Logo.d.ts +18 -0
  164. package/build/Components/Logo.js +109 -0
  165. package/build/Components/Logo.js.map +1 -0
  166. package/build/Components/MDUtils.d.ts +11 -0
  167. package/build/Components/MDUtils.js +99 -0
  168. package/build/Components/MDUtils.js.map +1 -0
  169. package/build/Components/ObjectBrowser.d.ts +665 -0
  170. package/build/Components/ObjectBrowser.js +6245 -0
  171. package/build/Components/ObjectBrowser.js.map +1 -0
  172. package/build/Components/Router.d.ts +21 -0
  173. package/build/Components/Router.js +77 -0
  174. package/build/Components/Router.js.map +1 -0
  175. package/build/Components/SaveCloseButtons.d.ts +20 -0
  176. package/build/Components/SaveCloseButtons.js +65 -0
  177. package/build/Components/SaveCloseButtons.js.map +1 -0
  178. package/build/Components/Schedule.d.ts +62 -0
  179. package/build/Components/Schedule.js +1266 -0
  180. package/build/Components/Schedule.js.map +1 -0
  181. package/build/Components/SelectWithIcon.d.ts +37 -0
  182. package/build/Components/SelectWithIcon.js +139 -0
  183. package/build/Components/SelectWithIcon.js.map +1 -0
  184. package/build/Components/SimpleCron/cronText.d.ts +10 -0
  185. package/build/Components/SimpleCron/cronText.js +14 -0
  186. package/build/Components/SimpleCron/cronText.js.map +1 -0
  187. package/build/Components/SimpleCron/index.d.ts +55 -0
  188. package/build/Components/SimpleCron/index.js +698 -0
  189. package/build/Components/SimpleCron/index.js.map +1 -0
  190. package/build/Components/TabContainer.d.ts +15 -0
  191. package/build/Components/TabContainer.js +23 -0
  192. package/build/Components/TabContainer.js.map +1 -0
  193. package/build/Components/TabContent.d.ts +11 -0
  194. package/build/Components/TabContent.js +20 -0
  195. package/build/Components/TabContent.js.map +1 -0
  196. package/build/Components/TabHeader.d.ts +6 -0
  197. package/build/Components/TabHeader.js +6 -0
  198. package/build/Components/TabHeader.js.map +1 -0
  199. package/build/Components/TableResize.d.ts +45 -0
  200. package/build/Components/TableResize.js +204 -0
  201. package/build/Components/TableResize.js.map +1 -0
  202. package/build/Components/TextWithIcon.d.ts +21 -0
  203. package/build/Components/TextWithIcon.js +113 -0
  204. package/build/Components/TextWithIcon.js.map +1 -0
  205. package/build/Components/ToggleThemeMenu.d.ts +12 -0
  206. package/build/Components/ToggleThemeMenu.js +13 -0
  207. package/build/Components/ToggleThemeMenu.js.map +1 -0
  208. package/build/Components/TreeTable.d.ts +79 -0
  209. package/build/Components/TreeTable.js +538 -0
  210. package/build/Components/TreeTable.js.map +1 -0
  211. package/build/Components/UploadImage.d.ts +23 -0
  212. package/build/Components/UploadImage.js +516 -0
  213. package/build/Components/UploadImage.js.map +1 -0
  214. package/build/Components/Utils.d.ts +331 -0
  215. package/build/Components/Utils.js +1605 -0
  216. package/build/Components/Utils.js.map +1 -0
  217. package/build/Components/withWidth.d.ts +2 -0
  218. package/build/Components/withWidth.js +22 -0
  219. package/build/Components/withWidth.js.map +1 -0
  220. package/build/Connection.d.ts +1 -0
  221. package/build/Connection.js +2 -0
  222. package/build/Connection.js.map +1 -0
  223. package/build/Dialogs/ComplexCron.d.ts +24 -0
  224. package/build/Dialogs/ComplexCron.js +85 -0
  225. package/build/Dialogs/ComplexCron.js.map +1 -0
  226. package/build/Dialogs/Confirm.d.ts +39 -0
  227. package/build/Dialogs/Confirm.js +83 -0
  228. package/build/Dialogs/Confirm.js.map +1 -0
  229. package/build/Dialogs/Cron.d.ts +29 -0
  230. package/build/Dialogs/Cron.js +72 -0
  231. package/build/Dialogs/Cron.js.map +1 -0
  232. package/build/Dialogs/Error.d.ts +18 -0
  233. package/build/Dialogs/Error.js +27 -0
  234. package/build/Dialogs/Error.js.map +1 -0
  235. package/build/Dialogs/Message.d.ts +20 -0
  236. package/build/Dialogs/Message.js +29 -0
  237. package/build/Dialogs/Message.js.map +1 -0
  238. package/build/Dialogs/SelectFile.d.ts +85 -0
  239. package/build/Dialogs/SelectFile.js +115 -0
  240. package/build/Dialogs/SelectFile.js.map +1 -0
  241. package/build/Dialogs/SelectID.d.ts +102 -0
  242. package/build/Dialogs/SelectID.js +151 -0
  243. package/build/Dialogs/SelectID.js.map +1 -0
  244. package/build/Dialogs/SimpleCron.d.ts +19 -0
  245. package/build/Dialogs/SimpleCron.js +46 -0
  246. package/build/Dialogs/SimpleCron.js.map +1 -0
  247. package/build/Dialogs/TextInput.d.ts +2 -0
  248. package/build/Dialogs/TextInput.js +31 -0
  249. package/build/Dialogs/TextInput.js.map +1 -0
  250. package/build/GenericApp.d.ts +209 -0
  251. package/build/GenericApp.js +842 -0
  252. package/build/GenericApp.js.map +1 -0
  253. package/build/LegacyConnection.d.ts +938 -0
  254. package/build/LegacyConnection.js +2849 -0
  255. package/build/LegacyConnection.js.map +1 -0
  256. package/build/Prompt.d.ts +5 -0
  257. package/build/Prompt.js +19 -0
  258. package/build/Prompt.js.map +1 -0
  259. package/build/Theme.d.ts +5 -0
  260. package/build/Theme.js +344 -0
  261. package/build/Theme.js.map +1 -0
  262. package/build/assets/devices/parseNames.d.ts +0 -0
  263. package/build/assets/devices/parseNames.js +35 -0
  264. package/build/assets/devices/parseNames.js.map +1 -0
  265. package/build/assets/devices.json +1 -0
  266. package/build/assets/lamp_ceiling.svg +9 -0
  267. package/build/assets/lamp_table.svg +8 -0
  268. package/build/assets/no_icon.svg +9 -0
  269. package/build/assets/rooms/parseNames.d.ts +0 -0
  270. package/build/assets/rooms/parseNames.js +35 -0
  271. package/build/assets/rooms/parseNames.js.map +1 -0
  272. package/build/assets/rooms.json +1 -0
  273. package/build/dictionary.d.ts +1 -0
  274. package/build/dictionary.js +25 -0
  275. package/build/dictionary.js.map +1 -0
  276. package/build/globals.d.ts +19 -0
  277. package/build/i18n/de.json +480 -0
  278. package/build/i18n/en.json +480 -0
  279. package/build/i18n/es.json +480 -0
  280. package/build/i18n/fr.json +480 -0
  281. package/build/i18n/it.json +475 -0
  282. package/build/i18n/nl.json +475 -0
  283. package/build/i18n/pl.json +475 -0
  284. package/build/i18n/pt.json +475 -0
  285. package/build/i18n/ru.json +475 -0
  286. package/build/i18n/uk.json +475 -0
  287. package/build/i18n/zh-cn.json +475 -0
  288. package/build/i18n.d.ts +84 -0
  289. package/build/i18n.js +224 -0
  290. package/build/i18n.js.map +1 -0
  291. package/build/icons/IconAdapter.d.ts +3 -0
  292. package/build/icons/IconAdapter.js +7 -0
  293. package/build/icons/IconAdapter.js.map +1 -0
  294. package/build/icons/IconAlias.d.ts +3 -0
  295. package/build/icons/IconAlias.js +7 -0
  296. package/build/icons/IconAlias.js.map +1 -0
  297. package/build/icons/IconButtonImage.d.ts +3 -0
  298. package/build/icons/IconButtonImage.js +9 -0
  299. package/build/icons/IconButtonImage.js.map +1 -0
  300. package/build/icons/IconChannel.d.ts +3 -0
  301. package/build/icons/IconChannel.js +10 -0
  302. package/build/icons/IconChannel.js.map +1 -0
  303. package/build/icons/IconClearFilter.d.ts +3 -0
  304. package/build/icons/IconClearFilter.js +8 -0
  305. package/build/icons/IconClearFilter.js.map +1 -0
  306. package/build/icons/IconClosed.d.ts +3 -0
  307. package/build/icons/IconClosed.js +7 -0
  308. package/build/icons/IconClosed.js.map +1 -0
  309. package/build/icons/IconCopy.d.ts +3 -0
  310. package/build/icons/IconCopy.js +6 -0
  311. package/build/icons/IconCopy.js.map +1 -0
  312. package/build/icons/IconDevice.d.ts +3 -0
  313. package/build/icons/IconDevice.js +16 -0
  314. package/build/icons/IconDevice.js.map +1 -0
  315. package/build/icons/IconDocument.d.ts +3 -0
  316. package/build/icons/IconDocument.js +7 -0
  317. package/build/icons/IconDocument.js.map +1 -0
  318. package/build/icons/IconDocumentReadOnly.d.ts +3 -0
  319. package/build/icons/IconDocumentReadOnly.js +8 -0
  320. package/build/icons/IconDocumentReadOnly.js.map +1 -0
  321. package/build/icons/IconExpert.d.ts +3 -0
  322. package/build/icons/IconExpert.js +7 -0
  323. package/build/icons/IconExpert.js.map +1 -0
  324. package/build/icons/IconFx.d.ts +3 -0
  325. package/build/icons/IconFx.js +6 -0
  326. package/build/icons/IconFx.js.map +1 -0
  327. package/build/icons/IconInstance.d.ts +3 -0
  328. package/build/icons/IconInstance.js +7 -0
  329. package/build/icons/IconInstance.js.map +1 -0
  330. package/build/icons/IconLogout.d.ts +3 -0
  331. package/build/icons/IconLogout.js +7 -0
  332. package/build/icons/IconLogout.js.map +1 -0
  333. package/build/icons/IconNoIcon.d.ts +3 -0
  334. package/build/icons/IconNoIcon.js +6 -0
  335. package/build/icons/IconNoIcon.js.map +1 -0
  336. package/build/icons/IconOpen.d.ts +3 -0
  337. package/build/icons/IconOpen.js +7 -0
  338. package/build/icons/IconOpen.js.map +1 -0
  339. package/build/icons/IconState.d.ts +3 -0
  340. package/build/icons/IconState.js +7 -0
  341. package/build/icons/IconState.js.map +1 -0
  342. package/build/icons/IconVacuum.d.ts +3 -0
  343. package/build/icons/IconVacuum.js +12 -0
  344. package/build/icons/IconVacuum.js.map +1 -0
  345. package/build/index.css +56 -0
  346. package/build/index.d.ts +87 -0
  347. package/build/index.js +85 -0
  348. package/build/index.js.map +1 -0
  349. package/build/modulefederation.admin.config.d.ts +13 -0
  350. package/build/modulefederation.admin.config.js +45 -0
  351. package/build/modulefederation.admin.config.js.map +1 -0
  352. package/build/types.d.ts +236 -0
  353. package/i18n/de.json +480 -0
  354. package/i18n/en.json +480 -0
  355. package/i18n/es.json +480 -0
  356. package/i18n/fr.json +480 -0
  357. package/i18n/it.json +475 -0
  358. package/i18n/nl.json +475 -0
  359. package/i18n/pl.json +475 -0
  360. package/i18n/pt.json +475 -0
  361. package/i18n/ru.json +475 -0
  362. package/i18n/uk.json +475 -0
  363. package/i18n/zh-cn.json +475 -0
  364. package/index.css +56 -0
  365. package/modulefederation.admin.config.d.ts +20 -0
  366. package/modulefederation.admin.config.js +54 -0
  367. package/package.json +86 -0
  368. package/tasksExample.js +91 -0
@@ -0,0 +1,842 @@
1
+ /**
2
+ * Copyright 2018-2024 Denis Haev (bluefox) <dogafox@gmail.com>
3
+ *
4
+ * MIT License
5
+ *
6
+ */
7
+ import React from 'react';
8
+ import { PROGRESS, Connection } from '@iobroker/socket-client';
9
+ import * as Sentry from '@sentry/browser';
10
+ import { Snackbar, IconButton } from '@mui/material';
11
+ import { Close as IconClose } from '@mui/icons-material';
12
+ import { printPrompt } from './Prompt';
13
+ import { Theme } from './Theme';
14
+ import { Loader } from './Components/Loader';
15
+ import { Router } from './Components/Router';
16
+ import { Utils } from './Components/Utils';
17
+ import { SaveCloseButtons } from './Components/SaveCloseButtons';
18
+ import { DialogConfirm } from './Dialogs/Confirm';
19
+ import { I18n } from './i18n';
20
+ import { DialogError } from './Dialogs/Error';
21
+ import { dictionary } from './dictionary';
22
+ // import './index.css';
23
+ const cssStyle = `
24
+ html {
25
+ height: 100%;
26
+ }
27
+
28
+ body {
29
+ margin: 0;
30
+ padding: 0;
31
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
32
+ -webkit-font-smoothing: antialiased;
33
+ -moz-osx-font-smoothing: grayscale;
34
+ width: 100%;
35
+ height: 100%;
36
+ overflow: hidden;
37
+ }
38
+
39
+ /* scrollbar */
40
+ ::-webkit-scrollbar-track {
41
+ background-color: #ccc;
42
+ border-radius: 5px;
43
+ }
44
+
45
+ ::-webkit-scrollbar {
46
+ width: 5px;
47
+ height: 5px;
48
+ background-color: #ccc;
49
+ }
50
+
51
+ ::-webkit-scrollbar-thumb {
52
+ background-color: #575757;
53
+ border-radius: 5px;
54
+ }
55
+
56
+ #root {
57
+ height: 100%;
58
+ }
59
+
60
+ .App {
61
+ height: 100%;
62
+ }
63
+
64
+ @keyframes glow {
65
+ from {
66
+ background-color: initial;
67
+ }
68
+ to {
69
+ background-color: #58c458;
70
+ }
71
+ }
72
+ `;
73
+ function isIFrame() {
74
+ try {
75
+ return window.self !== window.top;
76
+ }
77
+ catch {
78
+ return true;
79
+ }
80
+ }
81
+ export class GenericApp extends Router {
82
+ socket;
83
+ isIFrame = isIFrame();
84
+ instance;
85
+ adapterName;
86
+ instanceId;
87
+ newReact;
88
+ encryptedFields;
89
+ sentryDSN;
90
+ alertDialogRendered;
91
+ _secret;
92
+ _systemConfig;
93
+ // it is not readonly
94
+ savedNative;
95
+ common = null;
96
+ sentryStarted = false;
97
+ sentryInited = false;
98
+ resizeTimer = null;
99
+ constructor(props, settings) {
100
+ const ConnectionClass = (props.Connection ||
101
+ settings?.Connection ||
102
+ Connection);
103
+ // const ConnectionClass = props.Connection === 'admin' || settings.Connection = 'admin' ? AdminConnection : (props.Connection || settings.Connection || Connection);
104
+ if (!window.document.getElementById('generic-app-iobroker-component')) {
105
+ const style = window.document.createElement('style');
106
+ style.setAttribute('id', 'generic-app-iobroker-component');
107
+ style.innerHTML = cssStyle;
108
+ window.document.head.appendChild(style);
109
+ }
110
+ // Remove `!Connection.isWeb() && window.adapterName !== 'material'` when iobroker.socket will support native ws
111
+ if (!GenericApp.isWeb() && window.io && window.location.port === '3000') {
112
+ try {
113
+ const io = new window.SocketClient();
114
+ delete window.io;
115
+ window.io = io;
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ }
121
+ super(props);
122
+ printPrompt();
123
+ const query = (window.location.search || '').replace(/^\?/, '').replace(/#.*$/, '');
124
+ const args = {};
125
+ query
126
+ .trim()
127
+ .split('&')
128
+ .filter(t => t.trim())
129
+ .forEach(b => {
130
+ const parts = b.split('=');
131
+ args[parts[0]] = parts.length === 2 ? parts[1] : true;
132
+ if (args[parts[0]] === 'true') {
133
+ args[parts[0]] = true;
134
+ }
135
+ else if (args[parts[0]] === 'false') {
136
+ args[parts[0]] = false;
137
+ }
138
+ });
139
+ // extract instance from URL
140
+ this.instance =
141
+ settings?.instance ??
142
+ props.instance ??
143
+ (args.instance !== undefined
144
+ ? parseInt(args.instance, 10) || 0
145
+ : parseInt(window.location.search.slice(1), 10) || 0);
146
+ // extract adapter name from URL
147
+ const tmp = window.location.pathname.split('/');
148
+ this.adapterName =
149
+ settings?.adapterName || props.adapterName || window.adapterName || tmp[tmp.length - 2] || 'iot';
150
+ this.instanceId = `system.adapter.${this.adapterName}.${this.instance}`;
151
+ this.newReact = args.newReact === true; // it is admin5
152
+ const location = Router.getLocation();
153
+ location.tab =
154
+ location.tab ||
155
+ (window._localStorage || window.localStorage).getItem(`${this.adapterName}-adapter`) ||
156
+ '';
157
+ const themeInstance = this.createTheme();
158
+ this.state = Object.assign(this.state || {}, // keep the existing state
159
+ {
160
+ selectedTab: (window._localStorage || window.localStorage).getItem(`${this.adapterName}-adapter`) || '',
161
+ selectedTabNum: -1,
162
+ native: {},
163
+ errorText: '',
164
+ changed: false,
165
+ connected: false,
166
+ loaded: false,
167
+ isConfigurationError: '',
168
+ expertMode: false,
169
+ toast: '',
170
+ theme: themeInstance,
171
+ themeName: this.getThemeName(themeInstance),
172
+ themeType: this.getThemeType(themeInstance),
173
+ bottomButtons: (settings && settings.bottomButtons) === false ? false : props?.bottomButtons !== false,
174
+ width: GenericApp.getWidth(),
175
+ confirmClose: false,
176
+ _alert: false,
177
+ _alertType: 'info',
178
+ _alertMessage: '',
179
+ });
180
+ // init translations
181
+ const translations = dictionary;
182
+ // merge together
183
+ if (settings?.translations) {
184
+ Object.keys(settings.translations).forEach(lang => {
185
+ if (settings.translations) {
186
+ translations[lang] = Object.assign(translations[lang], settings.translations[lang] || {});
187
+ }
188
+ });
189
+ }
190
+ else if (props.translations) {
191
+ Object.keys(props.translations).forEach(lang => {
192
+ if (props.translations) {
193
+ translations[lang] = Object.assign(translations[lang], props.translations[lang] || {});
194
+ }
195
+ });
196
+ }
197
+ I18n.setTranslations(translations);
198
+ this.savedNative = {}; // to detect if the config changed
199
+ this.encryptedFields = props.encryptedFields || settings?.encryptedFields || [];
200
+ this.sentryDSN = (settings && settings.sentryDSN) || props.sentryDSN;
201
+ if (window.socketUrl) {
202
+ if (window.socketUrl.startsWith(':')) {
203
+ window.socketUrl = `${window.location.protocol}//${window.location.hostname}${window.socketUrl}`;
204
+ }
205
+ else if (!window.socketUrl.startsWith('http://') && !window.socketUrl.startsWith('https://')) {
206
+ window.socketUrl = `${window.location.protocol}//${window.socketUrl}`;
207
+ }
208
+ }
209
+ this.alertDialogRendered = false;
210
+ if (!window.iobOldAlert) {
211
+ window.iobOldAlert = window.alert;
212
+ }
213
+ window.alert = message => {
214
+ if (!this.alertDialogRendered) {
215
+ window.iobOldAlert(message);
216
+ return;
217
+ }
218
+ if (message?.toString().toLowerCase().includes('error')) {
219
+ console.error(message);
220
+ this.showAlert(message.toString(), 'error');
221
+ }
222
+ else {
223
+ console.log(message);
224
+ this.showAlert(message.toString(), 'info');
225
+ }
226
+ };
227
+ // @ts-expect-error either make props in ConnectionProps required or the constructor needs to accept than as they are (means adapt socket-client)
228
+ this.socket = new ConnectionClass({
229
+ ...(props?.socket || settings?.socket),
230
+ name: this.adapterName,
231
+ doNotLoadAllObjects: settings?.doNotLoadAllObjects,
232
+ onProgress: (progress) => {
233
+ if (progress === PROGRESS.CONNECTING) {
234
+ this.setState({ connected: false });
235
+ }
236
+ else if (progress === PROGRESS.READY) {
237
+ this.setState({ connected: true });
238
+ }
239
+ else {
240
+ this.setState({ connected: true });
241
+ }
242
+ },
243
+ onReady: ( /* objects, scripts */) => {
244
+ I18n.setLanguage(this.socket.systemLang);
245
+ // subscribe because of language and expert mode
246
+ this.socket
247
+ .subscribeObject('system.config', this.onSystemConfigChanged)
248
+ .then(() => this.getSystemConfig())
249
+ .then(obj => {
250
+ this._secret =
251
+ (typeof obj !== 'undefined' && obj.native && obj.native.secret) || 'Zgfr56gFe87jJOM';
252
+ this._systemConfig = obj?.common || {};
253
+ return this.socket.getObject(this.instanceId);
254
+ })
255
+ .then(async (obj) => {
256
+ let waitPromise;
257
+ const instanceObj = obj;
258
+ const sentryPluginEnabled = (await this.socket.getState(`${this.instanceId}.plugins.sentry.enabled`))?.val;
259
+ const sentryEnabled = sentryPluginEnabled !== false &&
260
+ this._systemConfig?.diag !== 'none' &&
261
+ instanceObj?.common &&
262
+ instanceObj.common.name &&
263
+ instanceObj.common.version &&
264
+ // @ts-expect-error will be extended in js-controller TODO: (BF: 2024.05.30) this is redundant to state `${this.instanceId}.plugins.sentry.enabled`, remove this in future when admin sets the state correctly
265
+ !instanceObj.common.disableDataReporting &&
266
+ window.location.host !== 'localhost:3000';
267
+ // activate sentry plugin
268
+ if (!this.sentryStarted && this.sentryDSN && sentryEnabled) {
269
+ this.sentryStarted = true;
270
+ Sentry.init({
271
+ dsn: this.sentryDSN,
272
+ release: `iobroker.${instanceObj.common.name}@${instanceObj.common.version}`,
273
+ integrations: [Sentry.dedupeIntegration()],
274
+ });
275
+ console.log('Sentry initialized');
276
+ }
277
+ // read UUID and init sentry with it.
278
+ // for backward compatibility it will be processed separately from the above logic: some adapters could still have this.sentryDSN as undefined
279
+ if (!this.sentryInited && sentryEnabled) {
280
+ this.sentryInited = true;
281
+ waitPromise = this.socket.getObject('system.meta.uuid').then(uuidObj => {
282
+ if (uuidObj && uuidObj.native && uuidObj.native.uuid) {
283
+ const scope = Sentry.getCurrentScope();
284
+ scope.setUser({ id: uuidObj.native.uuid });
285
+ }
286
+ });
287
+ }
288
+ waitPromise = waitPromise instanceof Promise ? waitPromise : Promise.resolve();
289
+ void waitPromise.then(() => {
290
+ if (instanceObj) {
291
+ this.common = instanceObj?.common;
292
+ this.onPrepareLoad(instanceObj.native, instanceObj.encryptedNative); // decode all secrets
293
+ this.savedNative = JSON.parse(JSON.stringify(instanceObj.native));
294
+ this.setState({ native: instanceObj.native, loaded: true, expertMode: this.getExpertMode() }, () => this.onConnectionReady && this.onConnectionReady());
295
+ }
296
+ else {
297
+ console.warn('Cannot load instance settings');
298
+ this.setState({
299
+ native: {},
300
+ loaded: true,
301
+ expertMode: this.getExpertMode(),
302
+ }, () => this.onConnectionReady && this.onConnectionReady());
303
+ }
304
+ });
305
+ })
306
+ .catch(e => window.alert(`Cannot settings: ${e}`));
307
+ },
308
+ onError: (err) => {
309
+ console.error(err);
310
+ this.showError(err);
311
+ },
312
+ });
313
+ }
314
+ /**
315
+ * Checks if this connection is running in a web adapter and not in an admin.
316
+ *
317
+ * @returns True if running in a web adapter or in a socketio adapter.
318
+ */
319
+ static isWeb() {
320
+ return window.socketUrl !== undefined;
321
+ }
322
+ showAlert(message, type) {
323
+ if (type !== 'error' && type !== 'warning' && type !== 'info' && type !== 'success') {
324
+ type = 'info';
325
+ }
326
+ this.setState({
327
+ _alert: true,
328
+ _alertType: type,
329
+ _alertMessage: message,
330
+ });
331
+ }
332
+ renderAlertSnackbar() {
333
+ this.alertDialogRendered = true;
334
+ return (React.createElement(Snackbar, { style: this.state._alertType === 'error'
335
+ ? { backgroundColor: '#f44336' }
336
+ : this.state._alertType === 'success'
337
+ ? { backgroundColor: '#4caf50' }
338
+ : undefined, open: this.state._alert, autoHideDuration: 6000, onClose: (_e, reason) => reason !== 'clickaway' && this.setState({ _alert: false }), message: this.state._alertMessage }));
339
+ }
340
+ onSystemConfigChanged = (id, obj) => {
341
+ if (obj && id === 'system.config') {
342
+ if (this.socket.systemLang !== obj?.common.language) {
343
+ this.socket.systemLang = obj?.common.language || 'en';
344
+ I18n.setLanguage(this.socket.systemLang);
345
+ }
346
+ if (this._systemConfig?.expertMode !== !!obj?.common?.expertMode) {
347
+ this._systemConfig =
348
+ obj?.common || {};
349
+ this.setState({ expertMode: this.getExpertMode() });
350
+ }
351
+ else {
352
+ this._systemConfig =
353
+ obj?.common || {};
354
+ }
355
+ }
356
+ };
357
+ /**
358
+ * Called immediately after a component is mounted. Setting state here will trigger re-rendering.
359
+ */
360
+ componentDidMount() {
361
+ window.addEventListener('resize', this.onResize, true);
362
+ window.addEventListener('message', this.onReceiveMessage, false);
363
+ super.componentDidMount();
364
+ }
365
+ /**
366
+ * Called immediately before a component is destroyed.
367
+ */
368
+ componentWillUnmount() {
369
+ window.removeEventListener('resize', this.onResize, true);
370
+ window.removeEventListener('message', this.onReceiveMessage, false);
371
+ // restore window.alert
372
+ if (window.iobOldAlert) {
373
+ window.alert = window.iobOldAlert;
374
+ delete window.iobOldAlert;
375
+ }
376
+ super.componentWillUnmount();
377
+ }
378
+ onReceiveMessage = (message) => {
379
+ if (message?.data) {
380
+ if (message.data === 'updateTheme') {
381
+ const newThemeName = Utils.getThemeName();
382
+ Utils.setThemeName(Utils.getThemeName());
383
+ const newTheme = this.createTheme(newThemeName);
384
+ this.setState({
385
+ theme: newTheme,
386
+ themeName: this.getThemeName(newTheme),
387
+ themeType: this.getThemeType(newTheme),
388
+ }, () => {
389
+ this.props.onThemeChange && this.props.onThemeChange(newThemeName);
390
+ this.onThemeChanged && this.onThemeChanged(newThemeName);
391
+ });
392
+ }
393
+ else if (message.data === 'updateExpertMode') {
394
+ this.onToggleExpertMode && this.onToggleExpertMode(this.getExpertMode());
395
+ }
396
+ else if (message.data !== 'chartReady') {
397
+ // if not "echart ready" message
398
+ console.debug(`Received unknown message: "${JSON.stringify(message.data)}". May be it will be processed later`);
399
+ }
400
+ }
401
+ };
402
+ onResize = () => {
403
+ this.resizeTimer && clearTimeout(this.resizeTimer);
404
+ this.resizeTimer = setTimeout(() => {
405
+ this.resizeTimer = null;
406
+ this.setState({ width: GenericApp.getWidth() });
407
+ }, 200);
408
+ };
409
+ /**
410
+ * Gets the width depending on the window inner width.
411
+ */
412
+ static getWidth() {
413
+ /**
414
+ * innerWidth |xs sm md lg xl
415
+ * |-------|-------|-------|-------|------>
416
+ * width | xs | sm | md | lg | xl
417
+ */
418
+ const SIZES = {
419
+ xs: 0,
420
+ sm: 600,
421
+ md: 960,
422
+ lg: 1280,
423
+ xl: 1920,
424
+ };
425
+ const width = window.innerWidth;
426
+ const keys = Object.keys(SIZES).reverse();
427
+ const widthComputed = keys.find(key => width >= SIZES[key]);
428
+ return widthComputed || 'xs';
429
+ }
430
+ /**
431
+ * Get a theme
432
+ *
433
+ * @param name Theme name
434
+ */
435
+ // eslint-disable-next-line class-methods-use-this
436
+ createTheme(name) {
437
+ return Theme(Utils.getThemeName(name));
438
+ }
439
+ /**
440
+ * Get the theme name
441
+ */
442
+ // eslint-disable-next-line class-methods-use-this
443
+ getThemeName(currentTheme) {
444
+ return currentTheme.name;
445
+ }
446
+ /**
447
+ * Get the theme type
448
+ */
449
+ // eslint-disable-next-line class-methods-use-this
450
+ getThemeType(currentTheme) {
451
+ return currentTheme.palette.mode;
452
+ }
453
+ // eslint-disable-next-line class-methods-use-this
454
+ onThemeChanged(_newThemeName) { }
455
+ // eslint-disable-next-line class-methods-use-this
456
+ onToggleExpertMode(_expertMode) { }
457
+ /**
458
+ * Changes the current theme
459
+ */
460
+ toggleTheme(newThemeName) {
461
+ const themeName = this.state.themeName;
462
+ // dark => blue => colored => light => dark
463
+ newThemeName =
464
+ newThemeName ||
465
+ (themeName === 'dark'
466
+ ? 'light'
467
+ : themeName === 'blue'
468
+ ? 'light'
469
+ : themeName === 'colored'
470
+ ? 'light'
471
+ : 'dark');
472
+ if (newThemeName !== themeName) {
473
+ Utils.setThemeName(newThemeName);
474
+ const newTheme = this.createTheme(newThemeName);
475
+ this.setState({
476
+ theme: newTheme,
477
+ themeName: this.getThemeName(newTheme),
478
+ themeType: this.getThemeType(newTheme),
479
+ }, () => {
480
+ this.props.onThemeChange && this.props.onThemeChange(newThemeName || 'light');
481
+ this.onThemeChanged && this.onThemeChanged(newThemeName || 'light');
482
+ });
483
+ }
484
+ }
485
+ /**
486
+ * Gets the system configuration.
487
+ */
488
+ getSystemConfig() {
489
+ return this.socket.getSystemConfig();
490
+ }
491
+ /**
492
+ * Get current expert mode
493
+ */
494
+ getExpertMode() {
495
+ return window.sessionStorage.getItem('App.expertMode') === 'true' || !!this._systemConfig?.expertMode;
496
+ }
497
+ /**
498
+ * Gets called when the socket.io connection is ready.
499
+ * You can overload this function to execute own commands.
500
+ */
501
+ // eslint-disable-next-line class-methods-use-this
502
+ onConnectionReady() { }
503
+ /**
504
+ * Encrypts a string.
505
+ */
506
+ encrypt(value) {
507
+ let result = '';
508
+ if (this._secret) {
509
+ for (let i = 0; i < value.length; i++) {
510
+ result += String.fromCharCode(this._secret[i % this._secret.length].charCodeAt(0) ^ value.charCodeAt(i));
511
+ }
512
+ }
513
+ return result;
514
+ }
515
+ /**
516
+ * Decrypts a string.
517
+ */
518
+ decrypt(value) {
519
+ let result = '';
520
+ if (this._secret) {
521
+ for (let i = 0; i < value.length; i++) {
522
+ result += String.fromCharCode(this._secret[i % this._secret.length].charCodeAt(0) ^ value.charCodeAt(i));
523
+ }
524
+ }
525
+ return result;
526
+ }
527
+ /**
528
+ * Gets called when the navigation hash changes.
529
+ * You may override this if needed.
530
+ */
531
+ onHashChanged() {
532
+ const location = Router.getLocation();
533
+ if (location.tab !== this.state.selectedTab) {
534
+ this.selectTab(location.tab);
535
+ }
536
+ }
537
+ /**
538
+ * Selects the given tab.
539
+ */
540
+ selectTab(tab, index) {
541
+ (window._localStorage || window.localStorage).setItem(`${this.adapterName}-adapter`, tab);
542
+ this.setState({ selectedTab: tab, selectedTabNum: index });
543
+ }
544
+ /**
545
+ * Gets called before the settings are saved.
546
+ * You may override this if needed.
547
+ */
548
+ onPrepareSave(settings) {
549
+ // here you can encode values
550
+ this.encryptedFields?.forEach(attr => {
551
+ if (settings[attr]) {
552
+ settings[attr] = this.encrypt(settings[attr]);
553
+ }
554
+ });
555
+ return true;
556
+ }
557
+ /**
558
+ * Gets called after the settings are loaded.
559
+ * You may override this if needed.
560
+ *
561
+ * @param settings instance settings from native part
562
+ * @param encryptedNative optional list of fields to be decrypted
563
+ */
564
+ onPrepareLoad(settings, encryptedNative) {
565
+ // here you can encode values
566
+ this.encryptedFields?.forEach(attr => {
567
+ if (settings[attr]) {
568
+ settings[attr] = this.decrypt(settings[attr]);
569
+ }
570
+ });
571
+ encryptedNative?.forEach(attr => {
572
+ this.encryptedFields = this.encryptedFields || [];
573
+ !this.encryptedFields.includes(attr) && this.encryptedFields.push(attr);
574
+ if (settings[attr]) {
575
+ settings[attr] = this.decrypt(settings[attr]);
576
+ }
577
+ });
578
+ }
579
+ /**
580
+ * Gets the extendable instances.
581
+ */
582
+ async getExtendableInstances() {
583
+ try {
584
+ const instances = await this.socket.getObjectViewSystem('instance', 'system.adapter.', 'system.adapter.\u9999');
585
+ return Object.values(instances).filter(instance => !!instance?.common?.webExtendable);
586
+ }
587
+ catch {
588
+ return [];
589
+ }
590
+ }
591
+ /**
592
+ * Gets the IP addresses of the given host.
593
+ */
594
+ async getIpAddresses(host) {
595
+ const ips = await this.socket.getHostByIp(host || this.common?.host || '');
596
+ // translate names
597
+ const ip4 = ips.find(ip => ip.address === '0.0.0.0');
598
+ if (ip4) {
599
+ ip4.name = `[IPv4] 0.0.0.0 - ${I18n.t('ra_Listen on all IPs')}`;
600
+ }
601
+ const ip6 = ips.find(ip => ip.address === '::');
602
+ if (ip6) {
603
+ ip6.name = `[IPv4] :: - ${I18n.t('ra_Listen on all IPs')}`;
604
+ }
605
+ return ips;
606
+ }
607
+ /**
608
+ * Saves the settings to the server.
609
+ *
610
+ * @param isClose True if the user is closing the dialog.
611
+ */
612
+ onSave(isClose) {
613
+ let oldObj;
614
+ if (this.state.isConfigurationError) {
615
+ this.setState({ errorText: this.state.isConfigurationError });
616
+ return;
617
+ }
618
+ this.socket
619
+ .getObject(this.instanceId)
620
+ .then(_oldObj => {
621
+ oldObj = (_oldObj || {});
622
+ for (const a in this.state.native) {
623
+ if (Object.prototype.hasOwnProperty.call(this.state.native, a)) {
624
+ if (this.state.native[a] === null) {
625
+ oldObj.native[a] = null;
626
+ }
627
+ else if (this.state.native[a] !== undefined) {
628
+ oldObj.native[a] = JSON.parse(JSON.stringify(this.state.native[a]));
629
+ }
630
+ else {
631
+ delete oldObj.native[a];
632
+ }
633
+ }
634
+ }
635
+ if (this.state.common) {
636
+ for (const b in this.state.common) {
637
+ if (this.state.common[b] === null) {
638
+ oldObj.common[b] = null;
639
+ }
640
+ else if (this.state.common[b] !== undefined) {
641
+ oldObj.common[b] = JSON.parse(JSON.stringify(this.state.common[b]));
642
+ }
643
+ else {
644
+ delete oldObj.common[b];
645
+ }
646
+ }
647
+ }
648
+ if (this.onPrepareSave(oldObj.native) !== false) {
649
+ return this.socket.setObject(this.instanceId, oldObj);
650
+ }
651
+ return Promise.reject(new Error('Invalid configuration'));
652
+ })
653
+ .then(() => {
654
+ this.savedNative = oldObj.native;
655
+ globalThis.changed = false;
656
+ try {
657
+ window.parent.postMessage('nochange', '*');
658
+ }
659
+ catch {
660
+ // ignore
661
+ }
662
+ this.setState({ changed: false }, () => {
663
+ isClose && GenericApp.onClose();
664
+ });
665
+ })
666
+ .catch(e => console.error(`Cannot save configuration: ${e}`));
667
+ }
668
+ /**
669
+ * Renders the toast.
670
+ */
671
+ renderToast() {
672
+ if (!this.state.toast) {
673
+ return null;
674
+ }
675
+ return (React.createElement(Snackbar, { anchorOrigin: {
676
+ vertical: 'bottom',
677
+ horizontal: 'left',
678
+ }, open: !0, autoHideDuration: 6000, onClose: () => this.setState({ toast: '' }), ContentProps: { 'aria-describedby': 'message-id' }, message: React.createElement("span", { id: "message-id" }, this.state.toast), action: [
679
+ React.createElement(IconButton, { key: "close", "aria-label": "Close", color: "inherit", onClick: () => this.setState({ toast: '' }), size: "large" },
680
+ React.createElement(IconClose, null)),
681
+ ] }));
682
+ }
683
+ /**
684
+ * Closes the dialog.
685
+ */
686
+ static onClose() {
687
+ if (typeof window.parent !== 'undefined' && window.parent) {
688
+ try {
689
+ if (window.parent.$iframeDialog && typeof window.parent.$iframeDialog.close === 'function') {
690
+ window.parent.$iframeDialog.close();
691
+ }
692
+ else {
693
+ window.parent.postMessage('close', '*');
694
+ }
695
+ }
696
+ catch {
697
+ window.parent.postMessage('close', '*');
698
+ }
699
+ }
700
+ }
701
+ /**
702
+ * Renders the error dialog.
703
+ */
704
+ renderError() {
705
+ if (!this.state.errorText) {
706
+ return null;
707
+ }
708
+ return (React.createElement(DialogError, { text: this.state.errorText, onClose: () => this.setState({ errorText: '' }) }));
709
+ }
710
+ /**
711
+ * Checks if the configuration has changed.
712
+ *
713
+ * @param native the new state
714
+ */
715
+ getIsChanged(native) {
716
+ native = native || this.state.native;
717
+ const isChanged = JSON.stringify(native) !== JSON.stringify(this.savedNative);
718
+ globalThis.changed = isChanged;
719
+ return isChanged;
720
+ }
721
+ /**
722
+ * Gets called when loading the configuration.
723
+ *
724
+ * @param newNative The new configuration object.
725
+ */
726
+ onLoadConfig(newNative) {
727
+ if (JSON.stringify(newNative) !== JSON.stringify(this.state.native)) {
728
+ this.setState({ native: newNative, changed: this.getIsChanged(newNative) });
729
+ }
730
+ }
731
+ /**
732
+ * Sets the configuration error.
733
+ */
734
+ setConfigurationError(errorText) {
735
+ if (this.state.isConfigurationError !== errorText) {
736
+ this.setState({ isConfigurationError: errorText });
737
+ }
738
+ }
739
+ /**
740
+ * Renders the save and close buttons.
741
+ */
742
+ renderSaveCloseButtons() {
743
+ if (!this.state.confirmClose && !this.state.bottomButtons) {
744
+ return null;
745
+ }
746
+ return (React.createElement(React.Fragment, null,
747
+ this.state.bottomButtons ? (React.createElement(SaveCloseButtons, { theme: this.state.theme, newReact: this.newReact, noTextOnButtons: this.state.width === 'xs' || this.state.width === 'sm' || this.state.width === 'md', changed: this.state.changed, onSave: (isClose) => this.onSave(isClose), onClose: () => {
748
+ if (this.state.changed) {
749
+ this.setState({ confirmClose: true });
750
+ }
751
+ else {
752
+ GenericApp.onClose();
753
+ }
754
+ }, error: !!this.state.isConfigurationError })) : null,
755
+ this.state.confirmClose ? (React.createElement(DialogConfirm, { title: I18n.t('ra_Please confirm'), text: I18n.t('ra_Some data are not stored. Discard?'), ok: I18n.t('ra_Discard'), cancel: I18n.t('ra_Cancel'), onClose: (isYes) => this.setState({ confirmClose: false }, () => isYes && GenericApp.onClose()) })) : null));
756
+ }
757
+ _updateNativeValue(obj, attrs, value) {
758
+ if (typeof attrs !== 'object') {
759
+ attrs = attrs.split('.');
760
+ }
761
+ const attr = attrs.shift() || '';
762
+ if (!attrs.length) {
763
+ if (value && typeof value === 'object') {
764
+ if (JSON.stringify(obj[attr]) !== JSON.stringify(value)) {
765
+ obj[attr] = value;
766
+ return true;
767
+ }
768
+ return false;
769
+ }
770
+ if (obj[attr] !== value) {
771
+ obj[attr] = value;
772
+ return true;
773
+ }
774
+ return false;
775
+ }
776
+ obj[attr] = obj[attr] || {};
777
+ if (typeof obj[attr] !== 'object') {
778
+ throw new Error(`attribute ${attr} is no object, but ${typeof obj[attr]}`);
779
+ }
780
+ return this._updateNativeValue(obj[attr], attrs, value);
781
+ }
782
+ /**
783
+ * Update the native value
784
+ *
785
+ * @param attr The attribute name with dots as delimiter.
786
+ * @param value The new value.
787
+ * @param cb Callback which will be called upon completion.
788
+ */
789
+ updateNativeValue(attr, value, cb) {
790
+ const native = JSON.parse(JSON.stringify(this.state.native));
791
+ if (this._updateNativeValue(native, attr, value)) {
792
+ const changed = this.getIsChanged(native);
793
+ if (changed !== this.state.changed) {
794
+ try {
795
+ window.parent.postMessage(changed ? 'change' : 'nochange', '*');
796
+ }
797
+ catch {
798
+ // ignore
799
+ }
800
+ }
801
+ this.setState({ native, changed }, cb);
802
+ }
803
+ }
804
+ /**
805
+ * Set the error text to be shown.
806
+ */
807
+ showError(text) {
808
+ this.setState({ errorText: text });
809
+ }
810
+ /**
811
+ * Sets the toast to be shown.
812
+ *
813
+ * @param toast Text to be shown.
814
+ */
815
+ showToast(toast) {
816
+ this.setState({ toast });
817
+ }
818
+ /**
819
+ * Renders helper dialogs
820
+ */
821
+ renderHelperDialogs() {
822
+ return (React.createElement(React.Fragment, null,
823
+ this.renderError(),
824
+ this.renderToast(),
825
+ this.renderSaveCloseButtons(),
826
+ this.renderAlertSnackbar()));
827
+ }
828
+ /**
829
+ * Renders this component.
830
+ */
831
+ render() {
832
+ if (!this.state.loaded) {
833
+ return React.createElement(Loader, { themeType: this.state.themeType });
834
+ }
835
+ return (React.createElement("div", { className: "App" },
836
+ this.renderError(),
837
+ this.renderToast(),
838
+ this.renderSaveCloseButtons(),
839
+ this.renderAlertSnackbar()));
840
+ }
841
+ }
842
+ //# sourceMappingURL=GenericApp.js.map