@c8y/ngx-components 1021.13.3 → 1021.22.0

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 (432) hide show
  1. package/alarms/alarm-details.component.d.ts +1 -3
  2. package/alarms/alarm-details.component.d.ts.map +1 -1
  3. package/alarms/alarm-info.component.d.ts +9 -14
  4. package/alarms/alarm-info.component.d.ts.map +1 -1
  5. package/alarms/alarms-list.component.d.ts +2 -17
  6. package/alarms/alarms-list.component.d.ts.map +1 -1
  7. package/alarms/alarms-view.service.d.ts +1 -0
  8. package/alarms/alarms-view.service.d.ts.map +1 -1
  9. package/alarms/alarms.component.d.ts.map +1 -1
  10. package/alarms/alarms.helper.d.ts +5 -0
  11. package/alarms/alarms.helper.d.ts.map +1 -0
  12. package/alarms/alarms.model.d.ts +30 -0
  13. package/alarms/alarms.model.d.ts.map +1 -1
  14. package/alarms/alarms.module.d.ts.map +1 -1
  15. package/alarms/cockpit/index.d.ts.map +1 -1
  16. package/alarms/devicemanagement/index.d.ts.map +1 -1
  17. package/alarms/index.d.ts +5 -4
  18. package/alarms/index.d.ts.map +1 -1
  19. package/context-dashboard/context-dashboard.model.d.ts +1 -0
  20. package/context-dashboard/context-dashboard.model.d.ts.map +1 -1
  21. package/context-dashboard/context-dashboard.service.d.ts +7 -5
  22. package/context-dashboard/context-dashboard.service.d.ts.map +1 -1
  23. package/context-dashboard/dashboard-detail.component.d.ts +4 -7
  24. package/context-dashboard/dashboard-detail.component.d.ts.map +1 -1
  25. package/context-dashboard/dashboard-detail.service.d.ts +4 -4
  26. package/context-dashboard/dashboard-detail.service.d.ts.map +1 -1
  27. package/context-dashboard/dashboard-settings/dashboard-general-settings.component.d.ts +2 -2
  28. package/context-dashboard/dashboard-settings/dashboard-general-settings.component.d.ts.map +1 -1
  29. package/context-dashboard/dashboard-settings/typed-dashboard-settings.component.d.ts +19 -6
  30. package/context-dashboard/dashboard-settings/typed-dashboard-settings.component.d.ts.map +1 -1
  31. package/core/action-bar/action-bar-item.component.d.ts +1 -1
  32. package/core/action-bar/action-bar-item.component.d.ts.map +1 -1
  33. package/core/action-bar/action-bar.module.d.ts +6 -6
  34. package/core/action-bar/action-bar.module.d.ts.map +1 -1
  35. package/core/bootstrap/bootstrap.component.d.ts +3 -1
  36. package/core/bootstrap/bootstrap.component.d.ts.map +1 -1
  37. package/core/common/aggregation/aggregation.model.d.ts +39 -0
  38. package/core/common/aggregation/aggregation.model.d.ts.map +1 -0
  39. package/core/common/aggregation/aggregation.service.d.ts +17 -0
  40. package/core/common/aggregation/aggregation.service.d.ts.map +1 -0
  41. package/core/common/index.d.ts +4 -0
  42. package/core/common/index.d.ts.map +1 -1
  43. package/core/common/inter-app.service.d.ts +48 -0
  44. package/core/common/inter-app.service.d.ts.map +1 -0
  45. package/core/common/interval-based-reload.abstract.d.ts +120 -0
  46. package/core/common/interval-based-reload.abstract.d.ts.map +1 -0
  47. package/core/dashboard/dashboard.module.d.ts +24 -18
  48. package/core/dashboard/dashboard.module.d.ts.map +1 -1
  49. package/core/dashboard/index.d.ts +3 -0
  50. package/core/dashboard/index.d.ts.map +1 -1
  51. package/core/dashboard/widget-auto-refresh-context/auto-refresh-control.component.d.ts +31 -0
  52. package/core/dashboard/widget-auto-refresh-context/auto-refresh-control.component.d.ts.map +1 -0
  53. package/core/dashboard/widget-auto-refresh-context/auto-refresh-select-control.component.d.ts +17 -0
  54. package/core/dashboard/widget-auto-refresh-context/auto-refresh-select-control.component.d.ts.map +1 -0
  55. package/core/dashboard/widget-auto-refresh-context/global-refresh-loading.operator.d.ts +4 -0
  56. package/core/dashboard/widget-auto-refresh-context/global-refresh-loading.operator.d.ts.map +1 -0
  57. package/core/dashboard/widget-auto-refresh-context/index.d.ts +8 -0
  58. package/core/dashboard/widget-auto-refresh-context/index.d.ts.map +1 -0
  59. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context-icon-bar.component.d.ts +7 -0
  60. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context-icon-bar.component.d.ts.map +1 -0
  61. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.component.d.ts +29 -0
  62. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.component.d.ts.map +1 -0
  63. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.model.d.ts +15 -0
  64. package/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.model.d.ts.map +1 -0
  65. package/core/dashboard/widget-auto-refresh-context/widget-global-auto-refresh.service.d.ts +169 -0
  66. package/core/dashboard/widget-auto-refresh-context/widget-global-auto-refresh.service.d.ts.map +1 -0
  67. package/core/dashboard/widgets-dashboard.component.d.ts +6 -3
  68. package/core/dashboard/widgets-dashboard.component.d.ts.map +1 -1
  69. package/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.d.ts +2 -2
  70. package/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.d.ts.map +1 -1
  71. package/core/dashboard/wiget-time-context/widget-time-context-icon-bar/widget-time-context-icon-bar.component.d.ts +1 -1
  72. package/core/dashboard/wiget-time-context/widget-time-context-icon-bar/widget-time-context-icon-bar.component.d.ts.map +1 -1
  73. package/core/dashboard/wiget-time-context/widget-time-context-query.service.d.ts.map +1 -1
  74. package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts +11 -8
  75. package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts.map +1 -1
  76. package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts +6 -12
  77. package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts.map +1 -1
  78. package/core/header/header.module.d.ts +18 -18
  79. package/core/header/header.module.d.ts.map +1 -1
  80. package/core/header/title/title.component.d.ts +1 -1
  81. package/core/header/title/title.component.d.ts.map +1 -1
  82. package/core/i18n/cached-locale-dictionary.service.d.ts +5 -1
  83. package/core/i18n/cached-locale-dictionary.service.d.ts.map +1 -1
  84. package/core/i18n/i18n.module.d.ts +0 -4
  85. package/core/i18n/i18n.module.d.ts.map +1 -1
  86. package/core/i18n/index.d.ts +2 -1
  87. package/core/i18n/index.d.ts.map +1 -1
  88. package/core/i18n/translation-loader.service.d.ts +50 -0
  89. package/core/i18n/translation-loader.service.d.ts.map +1 -0
  90. package/core/i18n/translation-utils.d.ts +14 -0
  91. package/core/i18n/translation-utils.d.ts.map +1 -0
  92. package/core/plugins/plugins-resolve.service.d.ts +7 -10
  93. package/core/plugins/plugins-resolve.service.d.ts.map +1 -1
  94. package/core/router/context-route.component.d.ts +8 -3
  95. package/core/router/context-route.component.d.ts.map +1 -1
  96. package/core/router/context-route.service.d.ts +29 -3
  97. package/core/router/context-route.service.d.ts.map +1 -1
  98. package/core/router/router-tabs.resolver.d.ts +4 -1
  99. package/core/router/router-tabs.resolver.d.ts.map +1 -1
  100. package/core/router/router.model.d.ts +40 -3
  101. package/core/router/router.model.d.ts.map +1 -1
  102. package/core/router/router.module.d.ts +2 -1
  103. package/core/router/router.module.d.ts.map +1 -1
  104. package/core/router/router.service.d.ts +5 -4
  105. package/core/router/router.service.d.ts.map +1 -1
  106. package/core/router/scoped-context-route.service.d.ts +57 -0
  107. package/core/router/scoped-context-route.service.d.ts.map +1 -0
  108. package/core/router/view-context.service.d.ts +8 -18
  109. package/core/router/view-context.service.d.ts.map +1 -1
  110. package/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form-validation.service.d.ts +2 -1
  111. package/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form-validation.service.d.ts.map +1 -1
  112. package/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form.component.d.ts +11 -2
  113. package/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form.component.d.ts.map +1 -1
  114. package/datapoint-selector/datapoint-selection.model.d.ts +6 -0
  115. package/datapoint-selector/datapoint-selection.model.d.ts.map +1 -1
  116. package/datapoints-export-selector/c8y-ngx-components-datapoints-export-selector.d.ts.map +1 -0
  117. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-fetching.service.d.ts +117 -0
  118. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-fetching.service.d.ts.map +1 -0
  119. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-processing.service.d.ts +90 -0
  120. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-processing.service.d.ts.map +1 -0
  121. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.component.d.ts +160 -0
  122. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.component.d.ts.map +1 -0
  123. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.service.d.ts +89 -0
  124. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.service.d.ts.map +1 -0
  125. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-preview/datapoints-export-selector-preview.component.d.ts +11 -0
  126. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-preview/datapoints-export-selector-preview.component.d.ts.map +1 -0
  127. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-data-scope/datapoints-exports-selector-data-scope.component.d.ts +27 -0
  128. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-data-scope/datapoints-exports-selector-data-scope.component.d.ts.map +1 -0
  129. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-file-types/datapoints-exports-selector-file-types.component.d.ts +12 -0
  130. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-file-types/datapoints-exports-selector-file-types.component.d.ts.map +1 -0
  131. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-time-range/datapoints-exports-selector-time-range.component.d.ts +22 -0
  132. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-time-range/datapoints-exports-selector-time-range.component.d.ts.map +1 -0
  133. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/csv-generator.d.ts +3 -0
  134. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/csv-generator.d.ts.map +1 -0
  135. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/excel-generator.d.ts +9 -0
  136. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/excel-generator.d.ts.map +1 -0
  137. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/utils.service.d.ts +56 -0
  138. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/utils.service.d.ts.map +1 -0
  139. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-modal.component.d.ts +21 -0
  140. package/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-modal.component.d.ts.map +1 -0
  141. package/datapoints-export-selector/datapoints-export-selector.component.d.ts +14 -0
  142. package/datapoints-export-selector/datapoints-export-selector.component.d.ts.map +1 -0
  143. package/datapoints-export-selector/datapoints-export-selector.model.d.ts +232 -0
  144. package/datapoints-export-selector/datapoints-export-selector.model.d.ts.map +1 -0
  145. package/datapoints-export-selector/index.d.ts +15 -0
  146. package/datapoints-export-selector/index.d.ts.map +1 -0
  147. package/device-list/device-list.module.d.ts +4 -2
  148. package/device-list/device-list.module.d.ts.map +1 -1
  149. package/esm2022/alarms/alarm-details.component.mjs +7 -9
  150. package/esm2022/alarms/alarm-info.component.mjs +23 -33
  151. package/esm2022/alarms/alarms-list.component.mjs +5 -16
  152. package/esm2022/alarms/alarms-view.service.mjs +3 -2
  153. package/esm2022/alarms/alarms.component.mjs +10 -3
  154. package/esm2022/alarms/alarms.helper.mjs +32 -0
  155. package/esm2022/alarms/alarms.model.mjs +1 -1
  156. package/esm2022/alarms/alarms.module.mjs +5 -5
  157. package/esm2022/alarms/cockpit/index.mjs +13 -17
  158. package/esm2022/alarms/devicemanagement/index.mjs +15 -18
  159. package/esm2022/alarms/index.mjs +6 -5
  160. package/esm2022/context-dashboard/context-dashboard.component.mjs +4 -4
  161. package/esm2022/context-dashboard/context-dashboard.model.mjs +1 -1
  162. package/esm2022/context-dashboard/context-dashboard.service.mjs +47 -21
  163. package/esm2022/context-dashboard/dashboard-detail.component.mjs +8 -16
  164. package/esm2022/context-dashboard/dashboard-detail.service.mjs +13 -6
  165. package/esm2022/context-dashboard/dashboard-settings/dashboard-general-settings.component.mjs +3 -3
  166. package/esm2022/context-dashboard/dashboard-settings/typed-dashboard-settings.component.mjs +32 -11
  167. package/esm2022/core/action-bar/action-bar-item.component.mjs +3 -3
  168. package/esm2022/core/action-bar/action-bar.module.mjs +16 -5
  169. package/esm2022/core/bootstrap/bootstrap.component.mjs +21 -16
  170. package/esm2022/core/common/aggregation/aggregation.model.mjs +46 -0
  171. package/esm2022/core/common/aggregation/aggregation.service.mjs +34 -0
  172. package/esm2022/core/common/humanize-app-name.model.mjs +2 -2
  173. package/esm2022/core/common/humanize-app-name.pipe.mjs +2 -2
  174. package/esm2022/core/common/index.mjs +5 -1
  175. package/esm2022/core/common/inter-app.service.mjs +76 -0
  176. package/esm2022/core/common/interval-based-reload.abstract.mjs +110 -0
  177. package/esm2022/core/countdown-interval/countdown-interval.component.mjs +3 -3
  178. package/esm2022/core/dashboard/dashboard-child.component.mjs +6 -5
  179. package/esm2022/core/dashboard/dashboard.module.mjs +18 -1
  180. package/esm2022/core/dashboard/index.mjs +4 -1
  181. package/esm2022/core/dashboard/widget-auto-refresh-context/auto-refresh-control.component.mjs +101 -0
  182. package/esm2022/core/dashboard/widget-auto-refresh-context/auto-refresh-select-control.component.mjs +50 -0
  183. package/esm2022/core/dashboard/widget-auto-refresh-context/global-refresh-loading.operator.mjs +7 -0
  184. package/esm2022/core/dashboard/widget-auto-refresh-context/index.mjs +8 -0
  185. package/esm2022/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context-icon-bar.component.mjs +18 -0
  186. package/esm2022/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.component.mjs +127 -0
  187. package/esm2022/core/dashboard/widget-auto-refresh-context/widget-auto-refresh-context.model.mjs +5 -0
  188. package/esm2022/core/dashboard/widget-auto-refresh-context/widget-global-auto-refresh.service.mjs +233 -0
  189. package/esm2022/core/dashboard/widgets-dashboard.component.mjs +35 -30
  190. package/esm2022/core/dashboard/wiget-time-context/aggregation-picker/aggregation-picker.component.mjs +4 -4
  191. package/esm2022/core/dashboard/wiget-time-context/realtime-control/realtime-control.component.mjs +2 -2
  192. package/esm2022/core/dashboard/wiget-time-context/widget-time-context-icon-bar/widget-time-context-icon-bar.component.mjs +5 -5
  193. package/esm2022/core/dashboard/wiget-time-context/widget-time-context-query.service.mjs +7 -4
  194. package/esm2022/core/dashboard/wiget-time-context/widget-time-context.component.mjs +37 -37
  195. package/esm2022/core/dashboard/wiget-time-context/widget-time-context.model.mjs +1 -28
  196. package/esm2022/core/date-time-picker/date-time-picker.component.mjs +3 -3
  197. package/esm2022/core/header/header.module.mjs +7 -5
  198. package/esm2022/core/header/title/title.component.mjs +3 -3
  199. package/esm2022/core/i18n/cached-locale-dictionary.service.mjs +1 -1
  200. package/esm2022/core/i18n/i18n.module.mjs +7 -14
  201. package/esm2022/core/i18n/index.mjs +3 -2
  202. package/esm2022/core/i18n/translate.parser.mjs +2 -2
  203. package/esm2022/core/i18n/translation-loader.service.mjs +132 -0
  204. package/esm2022/core/i18n/translation-utils.mjs +24 -0
  205. package/esm2022/core/plugins/plugins-resolve.service.mjs +12 -37
  206. package/esm2022/core/router/context-route.component.mjs +23 -13
  207. package/esm2022/core/router/context-route.service.mjs +37 -5
  208. package/esm2022/core/router/router-tabs.resolver.mjs +46 -15
  209. package/esm2022/core/router/router.model.mjs +6 -1
  210. package/esm2022/core/router/router.module.mjs +20 -13
  211. package/esm2022/core/router/router.service.mjs +24 -10
  212. package/esm2022/core/router/scoped-context-route.service.mjs +152 -0
  213. package/esm2022/core/router/view-context.service.mjs +59 -16
  214. package/esm2022/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form-validation.service.mjs +13 -6
  215. package/esm2022/datapoint-selector/datapoint-attributes-form/datapoint-attributes-form.component.mjs +22 -5
  216. package/esm2022/datapoint-selector/datapoint-selection-list/datapoint-selection-list.component.mjs +3 -3
  217. package/esm2022/datapoint-selector/datapoint-selection.model.mjs +1 -1
  218. package/esm2022/datapoint-selector/datapoint-selector-list-item/datapoint-selector-list-item.component.mjs +3 -3
  219. package/esm2022/datapoints-export-selector/c8y-ngx-components-datapoints-export-selector.mjs +5 -0
  220. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-fetching.service.mjs +407 -0
  221. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/data-processing.service.mjs +207 -0
  222. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.component.mjs +467 -0
  223. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-file-exporter.service.mjs +187 -0
  224. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-export-selector-preview/datapoints-export-selector-preview.component.mjs +27 -0
  225. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-data-scope/datapoints-exports-selector-data-scope.component.mjs +41 -0
  226. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-file-types/datapoints-exports-selector-file-types.component.mjs +23 -0
  227. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/datapoints-exports-selector-time-range/datapoints-exports-selector-time-range.component.mjs +42 -0
  228. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/csv-generator.mjs +120 -0
  229. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/generators/excel-generator.mjs +282 -0
  230. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-file-exporter/utils.service.mjs +76 -0
  231. package/esm2022/datapoints-export-selector/datapoints-export-selector-modal/datapoints-export-selector-modal.component.mjs +46 -0
  232. package/esm2022/datapoints-export-selector/datapoints-export-selector.component.mjs +42 -0
  233. package/esm2022/datapoints-export-selector/datapoints-export-selector.model.mjs +43 -0
  234. package/esm2022/datapoints-export-selector/index.mjs +15 -0
  235. package/esm2022/device-list/add-smart-group.component.mjs +4 -3
  236. package/esm2022/device-list/device-list.module.mjs +22 -4
  237. package/esm2022/map/cluster-map.component.mjs +41 -13
  238. package/esm2022/map/map-status.component.mjs +6 -5
  239. package/esm2022/map/map.component.mjs +9 -5
  240. package/esm2022/map/map.model.mjs +1 -1
  241. package/esm2022/translation-editor/c8y-ngx-components-translation-editor.mjs +5 -0
  242. package/esm2022/translation-editor/data/c8y-ngx-components-translation-editor-data.mjs +5 -0
  243. package/esm2022/translation-editor/data/index.mjs +2 -0
  244. package/esm2022/translation-editor/data/translation-store.service.mjs +175 -0
  245. package/esm2022/translation-editor/index.mjs +10 -0
  246. package/esm2022/translation-editor/lazy/add-translation-modal/add-translation-modal.component.mjs +70 -0
  247. package/esm2022/translation-editor/lazy/c8y-ngx-components-translation-editor-lazy.mjs +5 -0
  248. package/esm2022/translation-editor/lazy/index.mjs +2 -0
  249. package/esm2022/translation-editor/lazy/manage-translation-cell-renderer/manage-translation-cell-renderer.component.mjs +53 -0
  250. package/esm2022/translation-editor/lazy/translation-editor/translation-editor.component.mjs +124 -0
  251. package/esm2022/translation-editor/translation-editor-naviagtor-factory.service.mjs +31 -0
  252. package/esm2022/widgets/cockpit/index.mjs +4 -2
  253. package/esm2022/widgets/cockpit-exports/index.mjs +8 -1
  254. package/esm2022/widgets/definitions/alarms/alarm-list/index.mjs +6 -2
  255. package/esm2022/widgets/definitions/alarms/all-critical-alarms/index.mjs +6 -2
  256. package/esm2022/widgets/definitions/alarms/recent-alarms/index.mjs +6 -2
  257. package/esm2022/widgets/definitions/datapoints-table/c8y-ngx-components-widgets-definitions-datapoints-table.mjs +5 -0
  258. package/esm2022/widgets/definitions/datapoints-table/index.mjs +34 -0
  259. package/esm2022/widgets/definitions/index.mjs +2 -1
  260. package/esm2022/widgets/definitions/map/index.mjs +4 -2
  261. package/esm2022/widgets/implementations/alarms/alarm-list-widget-config/alarm-list-widget-config.component.mjs +29 -15
  262. package/esm2022/widgets/implementations/alarms/alarm-list-widget-view/alarm-list-widget.component.mjs +57 -25
  263. package/esm2022/widgets/implementations/alarms/alarm-list-widget.model.mjs +2 -1
  264. package/esm2022/widgets/implementations/alarms/alarm-widget-alarms-reload.component.mjs +19 -21
  265. package/esm2022/widgets/implementations/datapoints-table/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +5 -0
  266. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.component.mjs +383 -0
  267. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.service.mjs +124 -0
  268. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/adjust-aggregated-time-range.pipe.mjs +191 -0
  269. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/apply-range-class.pipe.mjs +36 -0
  270. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/column-title.pipe.mjs +45 -0
  271. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.mjs +116 -0
  272. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/datapoints-table.component.mjs +116 -0
  273. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/dynamic-column.directive.mjs +43 -0
  274. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.component.mjs +282 -0
  275. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.service.mjs +430 -0
  276. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/virtual-scroll-listener.directive.mjs +75 -0
  277. package/esm2022/widgets/implementations/datapoints-table/datapoints-table-widget.model.mjs +76 -0
  278. package/esm2022/widgets/implementations/datapoints-table/datapoints-table.service.mjs +52 -0
  279. package/esm2022/widgets/implementations/datapoints-table/date-range-picker.component.mjs +68 -0
  280. package/esm2022/widgets/implementations/datapoints-table/index.mjs +10 -0
  281. package/esm2022/widgets/implementations/map/map-widget-config.component.mjs +19 -11
  282. package/esm2022/widgets/implementations/map/map-widget.component.mjs +20 -2
  283. package/esm2022/widgets/implementations/map/map-widget.model.mjs +1 -1
  284. package/fesm2022/c8y-ngx-components-alarms-cockpit.mjs +12 -16
  285. package/fesm2022/c8y-ngx-components-alarms-cockpit.mjs.map +1 -1
  286. package/fesm2022/c8y-ngx-components-alarms-devicemanagement.mjs +14 -17
  287. package/fesm2022/c8y-ngx-components-alarms-devicemanagement.mjs.map +1 -1
  288. package/fesm2022/c8y-ngx-components-alarms.mjs +203 -185
  289. package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
  290. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +135 -91
  291. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  292. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +37 -13
  293. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
  294. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +1928 -0
  295. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -0
  296. package/fesm2022/c8y-ngx-components-device-list.mjs +24 -5
  297. package/fesm2022/c8y-ngx-components-device-list.mjs.map +1 -1
  298. package/fesm2022/c8y-ngx-components-map.mjs +52 -19
  299. package/fesm2022/c8y-ngx-components-map.mjs.map +1 -1
  300. package/fesm2022/c8y-ngx-components-translation-editor-data.mjs +181 -0
  301. package/fesm2022/c8y-ngx-components-translation-editor-data.mjs.map +1 -0
  302. package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs +236 -0
  303. package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs.map +1 -0
  304. package/fesm2022/c8y-ngx-components-translation-editor.mjs +46 -0
  305. package/fesm2022/c8y-ngx-components-translation-editor.mjs.map +1 -0
  306. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs +7 -0
  307. package/fesm2022/c8y-ngx-components-widgets-cockpit-exports.mjs.map +1 -1
  308. package/fesm2022/c8y-ngx-components-widgets-cockpit.mjs +3 -1
  309. package/fesm2022/c8y-ngx-components-widgets-cockpit.mjs.map +1 -1
  310. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-alarm-list.mjs +5 -1
  311. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-alarm-list.mjs.map +1 -1
  312. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-all-critical-alarms.mjs +5 -1
  313. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-all-critical-alarms.mjs.map +1 -1
  314. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-recent-alarms.mjs +5 -1
  315. package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-recent-alarms.mjs.map +1 -1
  316. package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-table.mjs +41 -0
  317. package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-table.mjs.map +1 -0
  318. package/fesm2022/c8y-ngx-components-widgets-definitions-map.mjs +3 -1
  319. package/fesm2022/c8y-ngx-components-widgets-definitions-map.mjs.map +1 -1
  320. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs +1 -0
  321. package/fesm2022/c8y-ngx-components-widgets-definitions.mjs.map +1 -1
  322. package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +101 -58
  323. package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs.map +1 -1
  324. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +1967 -0
  325. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -0
  326. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs +37 -11
  327. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs.map +1 -1
  328. package/fesm2022/c8y-ngx-components.mjs +5476 -4396
  329. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  330. package/locales/de.po +289 -18
  331. package/locales/en.po +12 -0
  332. package/locales/en_US.po +3 -0
  333. package/locales/es.po +253 -18
  334. package/locales/fr.po +253 -18
  335. package/locales/ja_JP.po +282 -18
  336. package/locales/locales.pot +257 -18
  337. package/locales/nl.po +253 -18
  338. package/locales/pl.po +253 -18
  339. package/locales/pt_BR.po +253 -18
  340. package/map/cluster-map.component.d.ts +8 -3
  341. package/map/cluster-map.component.d.ts.map +1 -1
  342. package/map/map-status.component.d.ts +0 -3
  343. package/map/map-status.component.d.ts.map +1 -1
  344. package/map/map.component.d.ts +4 -2
  345. package/map/map.component.d.ts.map +1 -1
  346. package/map/map.model.d.ts +2 -1
  347. package/map/map.model.d.ts.map +1 -1
  348. package/package.json +1 -1
  349. package/translation-editor/c8y-ngx-components-translation-editor.d.ts.map +1 -0
  350. package/translation-editor/data/c8y-ngx-components-translation-editor-data.d.ts.map +1 -0
  351. package/translation-editor/data/index.d.ts +2 -0
  352. package/translation-editor/data/index.d.ts.map +1 -0
  353. package/translation-editor/data/translation-store.service.d.ts +61 -0
  354. package/translation-editor/data/translation-store.service.d.ts.map +1 -0
  355. package/translation-editor/index.d.ts +2 -0
  356. package/translation-editor/index.d.ts.map +1 -0
  357. package/translation-editor/lazy/add-translation-modal/add-translation-modal.component.d.ts +30 -0
  358. package/translation-editor/lazy/add-translation-modal/add-translation-modal.component.d.ts.map +1 -0
  359. package/translation-editor/lazy/c8y-ngx-components-translation-editor-lazy.d.ts.map +1 -0
  360. package/translation-editor/lazy/index.d.ts +2 -0
  361. package/translation-editor/lazy/index.d.ts.map +1 -0
  362. package/translation-editor/lazy/manage-translation-cell-renderer/manage-translation-cell-renderer.component.d.ts +22 -0
  363. package/translation-editor/lazy/manage-translation-cell-renderer/manage-translation-cell-renderer.component.d.ts.map +1 -0
  364. package/translation-editor/lazy/translation-editor/translation-editor.component.d.ts +34 -0
  365. package/translation-editor/lazy/translation-editor/translation-editor.component.d.ts.map +1 -0
  366. package/translation-editor/translation-editor-naviagtor-factory.service.d.ts +11 -0
  367. package/translation-editor/translation-editor-naviagtor-factory.service.d.ts.map +1 -0
  368. package/widgets/cockpit/index.d.ts +13 -0
  369. package/widgets/cockpit/index.d.ts.map +1 -1
  370. package/widgets/cockpit-exports/index.d.ts +6 -0
  371. package/widgets/cockpit-exports/index.d.ts.map +1 -1
  372. package/widgets/definitions/alarms/alarm-list/index.d.ts +2 -0
  373. package/widgets/definitions/alarms/alarm-list/index.d.ts.map +1 -1
  374. package/widgets/definitions/alarms/all-critical-alarms/index.d.ts +2 -0
  375. package/widgets/definitions/alarms/all-critical-alarms/index.d.ts.map +1 -1
  376. package/widgets/definitions/alarms/recent-alarms/index.d.ts +2 -0
  377. package/widgets/definitions/alarms/recent-alarms/index.d.ts.map +1 -1
  378. package/widgets/definitions/datapoints-table/c8y-ngx-components-widgets-definitions-datapoints-table.d.ts.map +1 -0
  379. package/widgets/definitions/datapoints-table/index.d.ts +14 -0
  380. package/widgets/definitions/datapoints-table/index.d.ts.map +1 -0
  381. package/widgets/definitions/index.d.ts +1 -0
  382. package/widgets/definitions/index.d.ts.map +1 -1
  383. package/widgets/definitions/map/index.d.ts +2 -1
  384. package/widgets/definitions/map/index.d.ts.map +1 -1
  385. package/widgets/implementations/alarms/alarm-list-widget-config/alarm-list-widget-config.component.d.ts +5 -9
  386. package/widgets/implementations/alarms/alarm-list-widget-config/alarm-list-widget-config.component.d.ts.map +1 -1
  387. package/widgets/implementations/alarms/alarm-list-widget-view/alarm-list-widget.component.d.ts +17 -10
  388. package/widgets/implementations/alarms/alarm-list-widget-view/alarm-list-widget.component.d.ts.map +1 -1
  389. package/widgets/implementations/alarms/alarm-list-widget.model.d.ts +5 -1
  390. package/widgets/implementations/alarms/alarm-list-widget.model.d.ts.map +1 -1
  391. package/widgets/implementations/alarms/alarm-widget-alarms-reload.component.d.ts +5 -11
  392. package/widgets/implementations/alarms/alarm-widget-alarms-reload.component.d.ts.map +1 -1
  393. package/widgets/implementations/datapoints-table/c8y-ngx-components-widgets-implementations-datapoints-table.d.ts.map +1 -0
  394. package/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.component.d.ts +129 -0
  395. package/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.component.d.ts.map +1 -0
  396. package/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.service.d.ts +56 -0
  397. package/widgets/implementations/datapoints-table/datapoints-table-config/datapoints-table-config.service.d.ts.map +1 -0
  398. package/widgets/implementations/datapoints-table/datapoints-table-view/adjust-aggregated-time-range.pipe.d.ts +88 -0
  399. package/widgets/implementations/datapoints-table/datapoints-table-view/adjust-aggregated-time-range.pipe.d.ts.map +1 -0
  400. package/widgets/implementations/datapoints-table/datapoints-table-view/apply-range-class.pipe.d.ts +19 -0
  401. package/widgets/implementations/datapoints-table/datapoints-table-view/apply-range-class.pipe.d.ts.map +1 -0
  402. package/widgets/implementations/datapoints-table/datapoints-table-view/column-title.pipe.d.ts +26 -0
  403. package/widgets/implementations/datapoints-table/datapoints-table-view/column-title.pipe.d.ts.map +1 -0
  404. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.d.ts +63 -0
  405. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.d.ts.map +1 -0
  406. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/datapoints-table.component.d.ts +38 -0
  407. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/datapoints-table.component.d.ts.map +1 -0
  408. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/dynamic-column.directive.d.ts +13 -0
  409. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table/dynamic-column.directive.d.ts.map +1 -0
  410. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.component.d.ts +123 -0
  411. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.component.d.ts.map +1 -0
  412. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.service.d.ts +196 -0
  413. package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-table-view.service.d.ts.map +1 -0
  414. package/widgets/implementations/datapoints-table/datapoints-table-view/virtual-scroll-listener.directive.d.ts +41 -0
  415. package/widgets/implementations/datapoints-table/datapoints-table-view/virtual-scroll-listener.directive.d.ts.map +1 -0
  416. package/widgets/implementations/datapoints-table/datapoints-table-widget.model.d.ts +175 -0
  417. package/widgets/implementations/datapoints-table/datapoints-table-widget.model.d.ts.map +1 -0
  418. package/widgets/implementations/datapoints-table/datapoints-table.service.d.ts +12 -0
  419. package/widgets/implementations/datapoints-table/datapoints-table.service.d.ts.map +1 -0
  420. package/widgets/implementations/datapoints-table/date-range-picker.component.d.ts +34 -0
  421. package/widgets/implementations/datapoints-table/date-range-picker.component.d.ts.map +1 -0
  422. package/widgets/implementations/datapoints-table/index.d.ts +10 -0
  423. package/widgets/implementations/datapoints-table/index.d.ts.map +1 -0
  424. package/widgets/implementations/map/map-widget-config.component.d.ts +4 -4
  425. package/widgets/implementations/map/map-widget-config.component.d.ts.map +1 -1
  426. package/widgets/implementations/map/map-widget.component.d.ts +8 -3
  427. package/widgets/implementations/map/map-widget.component.d.ts.map +1 -1
  428. package/widgets/implementations/map/map-widget.model.d.ts +4 -3
  429. package/widgets/implementations/map/map-widget.model.d.ts.map +1 -1
  430. package/core/i18n/translate.loader.d.ts +0 -31
  431. package/core/i18n/translate.loader.d.ts.map +0 -1
  432. package/esm2022/core/i18n/translate.loader.mjs +0 -71
@@ -0,0 +1,407 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { DomSanitizer } from '@angular/platform-browser';
3
+ import { MeasurementService } from '@c8y/client';
4
+ import { AGGREGATION_VALUES, AlertService, gettext } from '@c8y/ngx-components';
5
+ import { TranslateService } from '@ngx-translate/core';
6
+ import { MEASUREMENTS_PREVIEW_ITEMS_LIMIT } from '../../datapoints-export-selector.model';
7
+ import { UtilsService } from './utils.service';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@c8y/ngx-components";
10
+ import * as i2 from "@c8y/client";
11
+ import * as i3 from "@angular/platform-browser";
12
+ import * as i4 from "@ngx-translate/core";
13
+ import * as i5 from "./utils.service";
14
+ export class DataFetchingService {
15
+ constructor(alertService, measurementService, sanitizer, translateService, utilsService) {
16
+ this.alertService = alertService;
17
+ this.measurementService = measurementService;
18
+ this.sanitizer = sanitizer;
19
+ this.translateService = translateService;
20
+ this.utilsService = utilsService;
21
+ }
22
+ /**
23
+ * Checks if any of measurements requests may exceeded the limit,
24
+ * after which the export data is processed by the backend and the generated CSV/Excel file is sent by email.
25
+ *
26
+ * The threshold is set to 50_000 records in application's core properties (export.data.synchronous.limit).
27
+ *
28
+ * @param exportConfig - The export configuration.
29
+ * @returns A promise that returns an array of objects representing datapoints files that will be sent by email.
30
+ */
31
+ async getDatapointsExceedingLimit(exportConfig) {
32
+ const backendProcessingLimit = 50_000;
33
+ const promises = exportConfig.datapointDetails.map(async (details) => {
34
+ try {
35
+ const filter = {
36
+ dateFrom: exportConfig.dateFrom,
37
+ dateTo: exportConfig.dateTo,
38
+ pageSize: 1,
39
+ source: details.source,
40
+ valueFragmentSeries: details.valueFragmentSeries,
41
+ valueFragmentType: details.valueFragmentType,
42
+ withTotalElements: true
43
+ };
44
+ const response = await this.measurementService.list(filter);
45
+ if (response?.paging?.totalElements > backendProcessingLimit) {
46
+ return {
47
+ datapointDetail: {
48
+ source: details.source,
49
+ valueFragmentSeries: details.valueFragmentSeries,
50
+ valueFragmentType: details.valueFragmentType
51
+ },
52
+ totalElements: response.paging.totalElements
53
+ };
54
+ }
55
+ else {
56
+ return null;
57
+ }
58
+ }
59
+ catch (error) {
60
+ this.alertService.addServerFailure(error);
61
+ }
62
+ });
63
+ const results = await Promise.all(promises);
64
+ const datapointsExceedingLimit = results.filter(result => result !== null);
65
+ return datapointsExceedingLimit;
66
+ }
67
+ /**
68
+ * Retrieves the message to be displayed when the limit of datapoints is exceeded during file export.
69
+ *
70
+ * @param hasNoExportableData - Indicates if there is no exportable data because the date range of all selected datapoints exceeds 1,000,000 records.
71
+ * @param emailDeliverableCount - The number of datapoint exports that exceed the limit, will be proceeded by the backend and sent by email.
72
+ * @param browserDownloadableCount - The number of datapoint exports that can be downloaded directly.
73
+ * @param skippedDatapointCount - The number of datapoint exports skipped due to exceeding the measurements API limit of 1,000,000 records.
74
+ * @param totalDatapointsSelectedForExportCount - Total number of datapoint selected for exports.
75
+ * @returns The message that can be injected.
76
+ */
77
+ getLimitExceededMessage(hasNoExportableData, emailDeliverableCount, browserDownloadableCount, nonRetrievableCount, totalDatapointsSelectedForExportCount) {
78
+ if (hasNoExportableData) {
79
+ const message = this.translateService.instant(gettext(`The data for selected datapoint(s) exceed 1,000,000 records, which is the limit for backend processing. To export this data, please reduce the date range.`));
80
+ return message;
81
+ }
82
+ const message = this.translateService.instant(gettext(`After clicking "Download":<br>
83
+ <ul>
84
+ <li><strong>{{$browserDownloadableCount}}</strong> datapoint(s) exports will be downloaded directly within one file: <em>exported_[csv/excel].zip</em></li>
85
+ <li><strong>{{$emailDeliverableCount}}</strong> datapoint(s) exports require further processing. The files will be sent to you via separate emails once completed, which may take some time.</li>
86
+ <li><strong>{{$nonRetrievableCount}}</strong> datapoint(s) exports exceeded 1,000,000 records, which is the limit for backend processing. To export these data, please reduce the date range. Otherwise, the data will neither be downloaded nor sent via email.</li>
87
+ </ul>
88
+ <p>The total number of data points that can be exported is: <strong>{{$totalExportableDatapointsCount}} out of {{$totalDatapointsSelectedForExportCount}}</strong>.
89
+ <p><strong>Note:</strong> The file name convention of files within zip file is: <code>[source]_[fragment_series].[csv/xls]</code></p>`), {
90
+ $browserDownloadableCount: browserDownloadableCount,
91
+ $emailDeliverableCount: emailDeliverableCount,
92
+ $nonRetrievableCount: nonRetrievableCount,
93
+ $totalDatapointsSelectedForExportCount: totalDatapointsSelectedForExportCount,
94
+ $totalExportableDatapointsCount: browserDownloadableCount + emailDeliverableCount
95
+ });
96
+ const trimmedMessage = this.removeZeroCountListItems(message, [
97
+ browserDownloadableCount,
98
+ emailDeliverableCount,
99
+ nonRetrievableCount
100
+ ]);
101
+ return trimmedMessage;
102
+ }
103
+ /**
104
+ * Displays an information alert about sending data via email.
105
+ *
106
+ * Only measurements API can send files via email.
107
+ *
108
+ * @param fileType - The type of file to be sent.
109
+ * @param datapointsExceedingLimit - The array of datapoints exceeding the limit.
110
+ */
111
+ showSendViaEmailInfoAlert(fileType, datapointsExceedingLimit) {
112
+ const messageTemplate = this.translateService.instant(gettext(`You will get {{$fileTypeText}} file(s) for {{$count}} series via email.`), { $count: datapointsExceedingLimit.length, $fileTypeText: fileType });
113
+ const formattedList = datapointsExceedingLimit
114
+ .map(datapoint => `• ${datapoint.datapointDetail.source}_${datapoint.datapointDetail.valueFragmentType}_${datapoint.datapointDetail.valueFragmentSeries}`)
115
+ .join('\n');
116
+ this.alertService.info(messageTemplate, formattedList);
117
+ }
118
+ async fetchMeasurementDataFilesAndPairWithSourceDetails(acceptFileType, exportConfig) {
119
+ const measurementFileConfig = {
120
+ exportConfig,
121
+ acceptFileType
122
+ };
123
+ const filePromises = exportConfig.datapointDetails.map(details => this.fetchAndProcessMeasurementFile(details, measurementFileConfig));
124
+ return Promise.all(filePromises);
125
+ }
126
+ async fetchAndProcessMeasurementFile(details, measurementFileConfig) {
127
+ const filter = this.prepareMeasurementsFilter(details, measurementFileConfig.exportConfig);
128
+ const header = { accept: measurementFileConfig.acceptFileType };
129
+ try {
130
+ const measurementFileResponse = await this.measurementService.getMeasurementsFile(filter, header);
131
+ // If the status is 200, then the file is in the response.
132
+ // If the status is 202, then the file is being processed by the backend and will be sent by email.
133
+ if (measurementFileResponse.status === 200) {
134
+ return this.mergeMeasurementsWithItsSourceDetails(details, measurementFileResponse);
135
+ }
136
+ }
137
+ catch (error) {
138
+ this.alertService.addServerFailure(error);
139
+ }
140
+ }
141
+ async mergeMeasurementsWithItsSourceDetails(details, measurementFile) {
142
+ return {
143
+ source: details.source,
144
+ valueFragmentSeries: details.valueFragmentSeries,
145
+ valueFragmentType: details.valueFragmentType,
146
+ fetchedMeasurementsBlobFile: await measurementFile.blob()
147
+ };
148
+ }
149
+ async fetchAndPrepareDataToExport(exportConfig, isMeasurement) {
150
+ return isMeasurement
151
+ ? await this.fetchAndPrepareMeasurementDataToExportForPreview(exportConfig)
152
+ : await this.fetchAndPrepareSeriesDataToExport(exportConfig);
153
+ }
154
+ async getSourcesWithPermissionsToRead(datapointDetails) {
155
+ const dateFrom = new Date();
156
+ const dateTo = new Date(dateFrom);
157
+ const fetchedDataPromises = datapointDetails.map(async (datapoint) => {
158
+ const rawFilter = {
159
+ dateFrom,
160
+ dateTo,
161
+ source: datapoint.source
162
+ };
163
+ try {
164
+ const { res } = await this.fetchSeriesData(rawFilter);
165
+ if (res?.status === 200) {
166
+ return datapoint.source;
167
+ }
168
+ return null;
169
+ }
170
+ catch (error) {
171
+ // If an error occurs during fetch, return null to prevent promise rejection
172
+ return null;
173
+ }
174
+ });
175
+ const fetchedSources = await Promise.all(fetchedDataPromises);
176
+ return fetchedSources.filter((source) => source !== null);
177
+ }
178
+ /**
179
+ * Fetches and prepares measurement data for preview.
180
+ *
181
+ * Empty DataToExport object can be returned, because unlike series data,
182
+ * measurement data is not further processed besides showing only in the preview.
183
+ * CSV/Excel files are generated by the backend for measurements.
184
+ *
185
+ * @param exportConfig - The export configuration.
186
+ * @returns A promise that resolves to an array of DataToExport objects or null when no data is fetched.
187
+ */
188
+ async fetchAndPrepareMeasurementDataToExportForPreview(exportConfig) {
189
+ const dataToExportPromises = exportConfig.datapointDetails.map(async (details) => {
190
+ const fetchedMeasurementData = await this.fetchMeasurementDataForPreview(details, exportConfig);
191
+ if (fetchedMeasurementData?.data?.length) {
192
+ return this.processMeasurementDataForPreview(details, fetchedMeasurementData.data);
193
+ }
194
+ return null;
195
+ });
196
+ return await Promise.all(dataToExportPromises);
197
+ }
198
+ async fetchMeasurementDataForPreview(details, exportConfig) {
199
+ let measurements;
200
+ const filter = this.prepareMeasurementsFilter(details, exportConfig, MEASUREMENTS_PREVIEW_ITEMS_LIMIT);
201
+ try {
202
+ // TODO: consider adding a cache mechanism -> MTM-60289
203
+ // When user switches between report types, and rest of the settings are the same, then the data should not be fetched again?
204
+ measurements = await this.measurementService.list(filter);
205
+ }
206
+ catch (error) {
207
+ this.alertService.addServerFailure(error);
208
+ }
209
+ return measurements;
210
+ }
211
+ prepareMeasurementsFilter(details, exportConfig, pageSize) {
212
+ const filter = {
213
+ // Round the 'from' time to the previous full minute.
214
+ dateFrom: this.adjustDate(exportConfig.dateFrom, -1),
215
+ // Round the 'to' time to the nearest full minute.
216
+ dateTo: this.adjustDate(exportConfig.dateTo, 1),
217
+ source: details.source,
218
+ valueFragmentSeries: details.valueFragmentSeries,
219
+ valueFragmentType: details.valueFragmentType
220
+ };
221
+ if (pageSize) {
222
+ filter.pageSize = pageSize;
223
+ }
224
+ return filter;
225
+ }
226
+ processMeasurementDataForPreview(details, data) {
227
+ const unit = data[0][details.valueFragmentType][details.valueFragmentSeries]?.unit || '';
228
+ const values = {};
229
+ data.forEach(measurement => {
230
+ values[measurement.time] =
231
+ measurement[details.valueFragmentType][details.valueFragmentSeries].value;
232
+ });
233
+ return { ...details, unit, timeValueMap: values };
234
+ }
235
+ async fetchAndPrepareSeriesDataToExport(exportConfig) {
236
+ const datapointsValuesDataMap = this.groupSeriesByDeviceId(exportConfig.datapointDetails);
237
+ const fetchedDataPromises = Array.from(datapointsValuesDataMap).map(async ([source, series]) => {
238
+ const { dateFrom, dateTo, aggregation } = exportConfig;
239
+ const rawFilter = {
240
+ dateFrom,
241
+ dateTo,
242
+ source,
243
+ series,
244
+ aggregationType: aggregation
245
+ };
246
+ const { data } = await this.fetchSeriesData(rawFilter);
247
+ return { source, data };
248
+ });
249
+ const fetchedDataGroupedBySource = await Promise.all(fetchedDataPromises);
250
+ return this.processSeriesData(exportConfig.datapointDetails, fetchedDataGroupedBySource);
251
+ }
252
+ /**
253
+ * Returns a map of active data points device IDs with their corresponding series.
254
+ *
255
+ * Example output:
256
+ * ```typescript
257
+ * new Map([
258
+ * ['844657202', ['c8y_Temperature.T']],
259
+ * ['32666427', ['c8y_Battery.Battery']]
260
+ * ]);
261
+ * ```
262
+ * @param datapointDetails - An array of data points details.
263
+ * @returns A map where the key is the data point ID and the value is an array of data point series.
264
+ */
265
+ groupSeriesByDeviceId(datapointDetails) {
266
+ return datapointDetails.reduce((map, { valueFragmentType, valueFragmentSeries, source }) => {
267
+ const value = `${valueFragmentType}.${valueFragmentSeries}`;
268
+ const existingValue = map.get(source) ?? [];
269
+ map.set(source, [...existingValue, value]);
270
+ return map;
271
+ }, new Map());
272
+ }
273
+ async fetchSeriesData(rawFilter) {
274
+ let seriesData;
275
+ const filter = this.prepareSeriesFilter({
276
+ dateFrom: rawFilter.dateFrom,
277
+ dateTo: rawFilter.dateTo,
278
+ source: rawFilter.source,
279
+ series: rawFilter.series,
280
+ aggregationType: rawFilter.aggregationType
281
+ });
282
+ try {
283
+ // TODO: consider adding a cache mechanism -> MTM-60289
284
+ // When user switches between report types, and rest of the settings are the same, then the data should not be fetched again?
285
+ seriesData = await this.measurementService.listSeries(filter);
286
+ }
287
+ catch (error) {
288
+ this.alertService.addServerFailure(error);
289
+ }
290
+ return seriesData;
291
+ }
292
+ prepareSeriesFilter(filters) {
293
+ const { dateFrom, dateTo, source, series, aggregationType } = filters;
294
+ // Round the 'from' time to the previous full minute.
295
+ const from = this.adjustDate(dateFrom, -1);
296
+ // Round the 'to' time to the nearest full minute.
297
+ const to = this.adjustDate(dateTo, 1);
298
+ const filter = {
299
+ dateFrom: from,
300
+ dateTo: to,
301
+ source: source,
302
+ revert: true
303
+ };
304
+ // The 'NONE' aggregation type is not handled by a backend, so even when is selected, it is not passed as a filter parameter.
305
+ if (aggregationType && aggregationType !== AGGREGATION_VALUES.none) {
306
+ filter.aggregationType = aggregationType;
307
+ }
308
+ // TODO: it is a temporal workaround for a bug in the backend,
309
+ // where the series with more than one dot are impossible to retrieve:
310
+ // https://cumulocity.atlassian.net/browse/MTM-59277
311
+ if (series) {
312
+ const hasMoreThanOneDot = series.some(s => s.split('.').length > 2);
313
+ if (!hasMoreThanOneDot) {
314
+ filter.series = series;
315
+ }
316
+ }
317
+ return filter;
318
+ }
319
+ /**
320
+ * Processes the fetched series data and prepares it for export.
321
+ *
322
+ * @param datapointDetails - An array of data point details.
323
+ * @param fetchedDataMap - A map of fetched series data grouped by source.
324
+ * @returns An array of DataToExport objects.
325
+ */
326
+ processSeriesData(datapointDetails, fetchedDataMap) {
327
+ const valuesGroupedBySource = this.utilsService.transformDataStructure(fetchedDataMap);
328
+ return datapointDetails.map((details) => {
329
+ let unit;
330
+ let data;
331
+ /**
332
+ * Unique key to distinguish between different series from same source,
333
+ * e.g.: c8y_Acceleration.accelerationX, c8y_Acceleration.accelerationY, c8y_Acceleration.accelerationZ
334
+ */
335
+ const seriesKey = `${details.valueFragmentType}.${details.valueFragmentSeries}`;
336
+ if (valuesGroupedBySource[details.source][seriesKey]) {
337
+ unit = valuesGroupedBySource[details.source][seriesKey].seriesDetails.unit;
338
+ data = valuesGroupedBySource[details.source][seriesKey].values;
339
+ }
340
+ return {
341
+ ...details,
342
+ unit,
343
+ timeValueMap: data
344
+ };
345
+ });
346
+ }
347
+ /**
348
+ * Adjusts the given date by adding the specified number of minutes and setting seconds to 0.
349
+ *
350
+ * @param date - The date to be adjusted in string format.
351
+ * @param minutes - The number of minutes to add to the date.
352
+ * @returns The adjusted date in the format 'YYYY-MM-DDTHH:mm:ss+HH:MM'.
353
+ */
354
+ adjustDate(date, minutes) {
355
+ const dateTime = new Date(date);
356
+ dateTime.setMinutes(dateTime.getMinutes() + minutes);
357
+ dateTime.setSeconds(0);
358
+ const offset = -dateTime.getTimezoneOffset();
359
+ const offsetSign = offset >= 0 ? '+' : '-';
360
+ const pad = (num) => (num < 10 ? '0' + num : num.toString());
361
+ const offsetHours = pad(Math.floor(Math.abs(offset) / 60));
362
+ const offsetMinutes = pad(Math.abs(offset) % 60);
363
+ const year = dateTime.getFullYear();
364
+ const month = pad(dateTime.getMonth() + 1);
365
+ const day = pad(dateTime.getDate());
366
+ const hours = pad(dateTime.getHours());
367
+ const minutesString = pad(dateTime.getMinutes());
368
+ const seconds = '00';
369
+ return `${year}-${month}-${day}T${hours}:${minutesString}:${seconds}${offsetSign}${offsetHours}:${offsetMinutes}`;
370
+ }
371
+ /**
372
+ * Trims the given HTML message by removing list items that correspond to zero counts.
373
+ *
374
+ * @param message - The HTML string containing the message with list items.
375
+ * @param counts - An array of number values corresponding to each list item.
376
+ * @param countToTrim - A count that will be trimmed with corresponding list item.
377
+ * @returns A trimmed HTML string with list items removed where the corresponding count is zero.
378
+ *
379
+ * Example:
380
+ * ```typescript
381
+ * const message = '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>';
382
+ * const counts = [1, 0, 2];
383
+ * const trimmedMessage = this.removeZeroCountListItems(message, counts);
384
+ * // Result: '<ul><li>Item 1</li><li>Item 3</li></ul>'
385
+ * ```
386
+ */
387
+ removeZeroCountListItems(message, counts, countToTrim = 0) {
388
+ const parser = new DOMParser();
389
+ const doc = parser.parseFromString(message, 'text/html');
390
+ const listItems = doc.querySelectorAll('ul li');
391
+ listItems.forEach((item, index) => {
392
+ if (counts[index] === countToTrim) {
393
+ item.remove();
394
+ }
395
+ });
396
+ return doc.body.innerHTML;
397
+ }
398
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DataFetchingService, deps: [{ token: i1.AlertService }, { token: i2.MeasurementService }, { token: i3.DomSanitizer }, { token: i4.TranslateService }, { token: i5.UtilsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
399
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DataFetchingService, providedIn: 'root' }); }
400
+ }
401
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: DataFetchingService, decorators: [{
402
+ type: Injectable,
403
+ args: [{
404
+ providedIn: 'root'
405
+ }]
406
+ }], ctorParameters: () => [{ type: i1.AlertService }, { type: i2.MeasurementService }, { type: i3.DomSanitizer }, { type: i4.TranslateService }, { type: i5.UtilsService }] });
407
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1mZXRjaGluZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vZGF0YXBvaW50cy1leHBvcnQtc2VsZWN0b3IvZGF0YXBvaW50cy1leHBvcnQtc2VsZWN0b3ItbW9kYWwvZGF0YXBvaW50cy1leHBvcnQtc2VsZWN0b3ItZmlsZS1leHBvcnRlci9kYXRhLWZldGNoaW5nLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDekQsT0FBTyxFQVNMLGtCQUFrQixFQUNuQixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFRTCxnQ0FBZ0MsRUFFakMsTUFBTSx3Q0FBd0MsQ0FBQztBQUNoRCxPQUFPLEVBQWMsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7QUFLM0QsTUFBTSxPQUFPLG1CQUFtQjtJQUM5QixZQUNVLFlBQTBCLEVBQzFCLGtCQUFzQyxFQUN0QyxTQUF1QixFQUN2QixnQkFBa0MsRUFDbEMsWUFBMEI7UUFKMUIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN0QyxjQUFTLEdBQVQsU0FBUyxDQUFjO1FBQ3ZCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsaUJBQVksR0FBWixZQUFZLENBQWM7SUFDakMsQ0FBQztJQUVKOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLDJCQUEyQixDQUMvQixZQUEwQjtRQUUxQixNQUFNLHNCQUFzQixHQUFHLE1BQU0sQ0FB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QUssSUFBSSxhQUFhLElBQUksT0FBTyxHQUFHLFVBQVUsR0FBRyxXQUFXLElBQUksYUFBYSxFQUFFLENBQUM7SUFDcEgsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7T0FlRztJQUNLLHdCQUF3QixDQUFDLE9BQWUsRUFBRSxNQUFnQixFQUFFLFdBQVcsR0FBRyxDQUFDO1FBQ2pGLE1BQU0sTUFBTSxHQUFHLElBQUksU0FBUyxFQUFFLENBQUM7UUFDL0IsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDekQsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRWhELFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDaEMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzVCLENBQUM7OEdBcmdCVSxtQkFBbUI7a0hBQW5CLG1CQUFtQixjQUZsQixNQUFNOzsyRkFFUCxtQkFBbUI7a0JBSC9CLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQge1xuICBhZ2dyZWdhdGlvblR5cGUsXG4gIElGZXRjaFJlc3BvbnNlLFxuICBJTWVhc3VyZW1lbnQsXG4gIElNZWFzdXJlbWVudEZpbHRlcixcbiAgSVJlc3VsdCxcbiAgSVJlc3VsdExpc3QsXG4gIElTZXJpZXMsXG4gIElTZXJpZXNGaWx0ZXIsXG4gIE1lYXN1cmVtZW50U2VydmljZVxufSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBBR0dSRUdBVElPTl9WQUxVRVMsIEFsZXJ0U2VydmljZSwgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHtcbiAgRGF0YXBvaW50RGV0YWlscyxcbiAgRGF0YXBvaW50c0V4Y2VlZGluZ0xpbWl0LFxuICBEYXRhcG9pbnRzVmFsdWVzRGF0YU1hcCxcbiAgRGF0YVRvRXhwb3J0LFxuICBEYXRhVG9FeHBvcnRXaXRoQmFja2VuZENyZWF0ZWRGaWxlLFxuICBFeHBvcnRDb25maWcsXG4gIE1lYXN1cmVtZW50RmlsZUNvbmZpZyxcbiAgTUVBU1VSRU1FTlRTX1BSRVZJRVdfSVRFTVNfTElNSVQsXG4gIFRpbWVTZXJpZXNEYXRhXG59IGZyb20gJy4uLy4uL2RhdGFwb2ludHMtZXhwb3J0LXNlbGVjdG9yLm1vZGVsJztcbmltcG9ydCB7IFNvdXJjZUl0ZW0sIFV0aWxzU2VydmljZSB9IGZyb20gJy4vdXRpbHMuc2VydmljZSc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIERhdGFGZXRjaGluZ1NlcnZpY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgbWVhc3VyZW1lbnRTZXJ2aWNlOiBNZWFzdXJlbWVudFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSB1dGlsc1NlcnZpY2U6IFV0aWxzU2VydmljZVxuICApIHt9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhbnkgb2YgbWVhc3VyZW1lbnRzIHJlcXVlc3RzIG1heSBleGNlZWRlZCB0aGUgbGltaXQsXG4gICAqIGFmdGVyIHdoaWNoIHRoZSBleHBvcnQgZGF0YSBpcyBwcm9jZXNzZWQgYnkgdGhlIGJhY2tlbmQgYW5kIHRoZSBnZW5lcmF0ZWQgQ1NWL0V4Y2VsIGZpbGUgaXMgc2VudCBieSBlbWFpbC5cbiAgICpcbiAgICogVGhlIHRocmVzaG9sZCBpcyBzZXQgdG8gNTBfMDAwIHJlY29yZHMgaW4gYXBwbGljYXRpb24ncyBjb3JlIHByb3BlcnRpZXMgKGV4cG9ydC5kYXRhLnN5bmNocm9ub3VzLmxpbWl0KS5cbiAgICpcbiAgICogQHBhcmFtIGV4cG9ydENvbmZpZyAtIFRoZSBleHBvcnQgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmV0dXJucyBhbiBhcnJheSBvZiBvYmplY3RzIHJlcHJlc2VudGluZyBkYXRhcG9pbnRzIGZpbGVzIHRoYXQgd2lsbCBiZSBzZW50IGJ5IGVtYWlsLlxuICAgKi9cbiAgYXN5bmMgZ2V0RGF0YXBvaW50c0V4Y2VlZGluZ0xpbWl0KFxuICAgIGV4cG9ydENvbmZpZzogRXhwb3J0Q29uZmlnXG4gICk6IFByb21pc2U8RGF0YXBvaW50c0V4Y2VlZGluZ0xpbWl0W10+IHtcbiAgICBjb25zdCBiYWNrZW5kUHJvY2Vzc2luZ0xpbWl0ID0gNTBfMDAwO1xuXG4gICAgY29uc3QgcHJvbWlzZXM6IFByb21pc2U8RGF0YXBvaW50c0V4Y2VlZGluZ0xpbWl0PltdID0gZXhwb3J0Q29uZmlnLmRhdGFwb2ludERldGFpbHMubWFwKFxuICAgICAgYXN5bmMgZGV0YWlscyA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZmlsdGVyOiBJTWVhc3VyZW1lbnRGaWx0ZXIgPSB7XG4gICAgICAgICAgICBkYXRlRnJvbTogZXhwb3J0Q29uZmlnLmRhdGVGcm9tLFxuICAgICAgICAgICAgZGF0ZVRvOiBleHBvcnRDb25maWcuZGF0ZVRvLFxuICAgICAgICAgICAgcGFnZVNpemU6IDEsXG4gICAgICAgICAgICBzb3VyY2U6IGRldGFpbHMuc291cmNlLFxuICAgICAgICAgICAgdmFsdWVGcmFnbWVudFNlcmllczogZGV0YWlscy52YWx1ZUZyYWdtZW50U2VyaWVzLFxuICAgICAgICAgICAgdmFsdWVGcmFnbWVudFR5cGU6IGRldGFpbHMudmFsdWVGcmFnbWVudFR5cGUsXG4gICAgICAgICAgICB3aXRoVG90YWxFbGVtZW50czogdHJ1ZVxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubWVhc3VyZW1lbnRTZXJ2aWNlLmxpc3QoZmlsdGVyKTtcblxuICAgICAgICAgIGlmIChyZXNwb25zZT8ucGFnaW5nPy50b3RhbEVsZW1lbnRzID4gYmFja2VuZFByb2Nlc3NpbmdMaW1pdCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZGF0YXBvaW50RGV0YWlsOiB7XG4gICAgICAgICAgICAgICAgc291cmNlOiBkZXRhaWxzLnNvdXJjZSxcbiAgICAgICAgICAgICAgICB2YWx1ZUZyYWdtZW50U2VyaWVzOiBkZXRhaWxzLnZhbHVlRnJhZ21lbnRTZXJpZXMsXG4gICAgICAgICAgICAgICAgdmFsdWVGcmFnbWVudFR5cGU6IGRldGFpbHMudmFsdWVGcmFnbWVudFR5cGVcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgdG90YWxFbGVtZW50czogcmVzcG9uc2UucGFnaW5nLnRvdGFsRWxlbWVudHNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRTZXJ2ZXJGYWlsdXJlKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHRzOiBEYXRhcG9pbnRzRXhjZWVkaW5nTGltaXRbXSA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblxuICAgIGNvbnN0IGRhdGFwb2ludHNFeGNlZWRpbmdMaW1pdCA9IHJlc3VsdHMuZmlsdGVyKHJlc3VsdCA9PiByZXN1bHQgIT09IG51bGwpO1xuXG4gICAgcmV0dXJuIGRhdGFwb2ludHNFeGNlZWRpbmdMaW1pdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkIHdoZW4gdGhlIGxpbWl0IG9mIGRhdGFwb2ludHMgaXMgZXhjZWVkZWQgZHVyaW5nIGZpbGUgZXhwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0gaGFzTm9FeHBvcnRhYmxlRGF0YSAtIEluZGljYXRlcyBpZiB0aGVyZSBpcyBubyBleHBvcnRhYmxlIGRhdGEgYmVjYXVzZSB0aGUgZGF0ZSByYW5nZSBvZiBhbGwgc2VsZWN0ZWQgZGF0YXBvaW50cyBleGNlZWRzIDEsMDAwLDAwMCByZWNvcmRzLlxuICAgKiBAcGFyYW0gZW1haWxEZWxpdmVyYWJsZUNvdW50IC0gVGhlIG51bWJlciBvZiBkYXRhcG9pbnQgZXhwb3J0cyB0aGF0IGV4Y2VlZCB0aGUgbGltaXQsIHdpbGwgYmUgcHJvY2VlZGVkIGJ5IHRoZSBiYWNrZW5kIGFuZCBzZW50IGJ5IGVtYWlsLlxuICAgKiBAcGFyYW0gYnJvd3NlckRvd25sb2FkYWJsZUNvdW50IC0gVGhlIG51bWJlciBvZiBkYXRhcG9pbnQgZXhwb3J0cyB0aGF0IGNhbiBiZSBkb3dubG9hZGVkIGRpcmVjdGx5LlxuICAgKiBAcGFyYW0gc2tpcHBlZERhdGFwb2ludENvdW50IC0gVGhlIG51bWJlciBvZiBkYXRhcG9pbnQgZXhwb3J0cyBza2lwcGVkIGR1ZSB0byBleGNlZWRpbmcgdGhlIG1lYXN1cmVtZW50cyBBUEkgbGltaXQgb2YgMSwwMDAsMDAwIHJlY29yZHMuXG4gICAqIEBwYXJhbSB0b3RhbERhdGFwb2ludHNTZWxlY3RlZEZvckV4cG9ydENvdW50IC0gVG90YWwgbnVtYmVyIG9mIGRhdGFwb2ludCBzZWxlY3RlZCBmb3IgZXhwb3J0cy5cbiAgICogQHJldHVybnMgVGhlIG1lc3NhZ2UgdGhhdCBjYW4gYmUgaW5qZWN0ZWQuXG4gICAqL1xuICBnZXRMaW1pdEV4Y2VlZGVkTWVzc2FnZShcbiAgICBoYXNOb0V4cG9ydGFibGVEYXRhOiBib29sZWFuLFxuICAgIGVtYWlsRGVsaXZlcmFibGVDb3VudD86IG51bWJlcixcbiAgICBicm93c2VyRG93bmxvYWRhYmxlQ291bnQ/OiBudW1iZXIsXG4gICAgbm9uUmV0cmlldmFibGVDb3VudD86IG51bWJlcixcbiAgICB0b3RhbERhdGFwb2ludHNTZWxlY3RlZEZvckV4cG9ydENvdW50PzogbnVtYmVyXG4gICk6IHN0cmluZyB7XG4gICAgaWYgKGhhc05vRXhwb3J0YWJsZURhdGEpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgICAgZ2V0dGV4dChcbiAgICAgICAgICBgVGhlIGRhdGEgZm9yIHNlbGVjdGVkIGRhdGFwb2ludChzKSBleGNlZWQgMSwwMDAsMDAwIHJlY29yZHMsIHdoaWNoIGlzIHRoZSBsaW1pdCBmb3IgYmFja2VuZCBwcm9jZXNzaW5nLiBUbyBleHBvcnQgdGhpcyBkYXRhLCBwbGVhc2UgcmVkdWNlIHRoZSBkYXRlIHJhbmdlLmBcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cblxuICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgIGdldHRleHQoXG4gICAgICAgIGBBZnRlciBjbGlja2luZyBcIkRvd25sb2FkXCI6PGJyPlxuICAgICAgICA8dWw+XG4gICAgICAgICAgPGxpPjxzdHJvbmc+e3skYnJvd3NlckRvd25sb2FkYWJsZUNvdW50fX08L3N0cm9uZz4gZGF0YXBvaW50KHMpIGV4cG9ydHMgd2lsbCBiZSBkb3dubG9hZGVkIGRpcmVjdGx5IHdpdGhpbiBvbmUgZmlsZTogPGVtPmV4cG9ydGVkX1tjc3YvZXhjZWxdLnppcDwvZW0+PC9saT5cbiAgICAgICAgICA8bGk+PHN0cm9uZz57eyRlbWFpbERlbGl2ZXJhYmxlQ291bnR9fTwvc3Ryb25nPiBkYXRhcG9pbnQocykgZXhwb3J0cyByZXF1aXJlIGZ1cnRoZXIgcHJvY2Vzc2luZy4gVGhlIGZpbGVzIHdpbGwgYmUgc2VudCB0byB5b3UgdmlhIHNlcGFyYXRlIGVtYWlscyBvbmNlIGNvbXBsZXRlZCwgd2hpY2ggbWF5IHRha2Ugc29tZSB0aW1lLjwvbGk+XG4gICAgICAgICAgPGxpPjxzdHJvbmc+e3skbm9uUmV0cmlldmFibGVDb3VudH19PC9zdHJvbmc+IGRhdGFwb2ludChzKSBleHBvcnRzIGV4Y2VlZGVkIDEsMDAwLDAwMCByZWNvcmRzLCB3aGljaCBpcyB0aGUgbGltaXQgZm9yIGJhY2tlbmQgcHJvY2Vzc2luZy4gVG8gZXhwb3J0IHRoZXNlIGRhdGEsIHBsZWFzZSByZWR1Y2UgdGhlIGRhdGUgcmFuZ2UuIE90aGVyd2lzZSwgdGhlIGRhdGEgd2lsbCBuZWl0aGVyIGJlIGRvd25sb2FkZWQgbm9yIHNlbnQgdmlhIGVtYWlsLjwvbGk+XG4gICAgICAgIDwvdWw+XG4gICAgICAgIDxwPlRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBjYW4gYmUgZXhwb3J0ZWQgaXM6IDxzdHJvbmc+e3skdG90YWxFeHBvcnRhYmxlRGF0YXBvaW50c0NvdW50fX0gb3V0IG9mIHt7JHRvdGFsRGF0YXBvaW50c1NlbGVjdGVkRm9yRXhwb3J0Q291bnR9fTwvc3Ryb25nPi5cbiAgICAgICAgPHA+PHN0cm9uZz5Ob3RlOjwvc3Ryb25nPiBUaGUgZmlsZSBuYW1lIGNvbnZlbnRpb24gb2YgZmlsZXMgd2l0aGluIHppcCBmaWxlIGlzOiA8Y29kZT5bc291cmNlXV9bZnJhZ21lbnRfc2VyaWVzXS5bY3N2L3hsc108L2NvZGU+PC9wPmBcbiAgICAgICksXG4gICAgICB7XG4gICAgICAgICRicm93c2VyRG93bmxvYWRhYmxlQ291bnQ6IGJyb3dzZXJEb3dubG9hZGFibGVDb3VudCxcbiAgICAgICAgJGVtYWlsRGVsaXZlcmFibGVDb3VudDogZW1haWxEZWxpdmVyYWJsZUNvdW50LFxuICAgICAgICAkbm9uUmV0cmlldmFibGVDb3VudDogbm9uUmV0cmlldmFibGVDb3VudCxcbiAgICAgICAgJHRvdGFsRGF0YXBvaW50c1NlbGVjdGVkRm9yRXhwb3J0Q291bnQ6IHRvdGFsRGF0YXBvaW50c1NlbGVjdGVkRm9yRXhwb3J0Q291bnQsXG4gICAgICAgICR0b3RhbEV4cG9ydGFibGVEYXRhcG9pbnRzQ291bnQ6IGJyb3dzZXJEb3dubG9hZGFibGVDb3VudCArIGVtYWlsRGVsaXZlcmFibGVDb3VudFxuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCB0cmltbWVkTWVzc2FnZSA9IHRoaXMucmVtb3ZlWmVyb0NvdW50TGlzdEl0ZW1zKG1lc3NhZ2UsIFtcbiAgICAgIGJyb3dzZXJEb3dubG9hZGFibGVDb3VudCxcbiAgICAgIGVtYWlsRGVsaXZlcmFibGVDb3VudCxcbiAgICAgIG5vblJldHJpZXZhYmxlQ291bnRcbiAgICBdKTtcblxuICAgIHJldHVybiB0cmltbWVkTWVzc2FnZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNwbGF5cyBhbiBpbmZvcm1hdGlvbiBhbGVydCBhYm91dCBzZW5kaW5nIGRhdGEgdmlhIGVtYWlsLlxuICAgKlxuICAgKiBPbmx5IG1lYXN1cmVtZW50cyBBUEkgY2FuIHNlbmQgZmlsZXMgdmlhIGVtYWlsLlxuICAgKlxuICAgKiBAcGFyYW0gZmlsZVR5cGUgLSBUaGUgdHlwZSBvZiBmaWxlIHRvIGJlIHNlbnQuXG4gICAqIEBwYXJhbSBkYXRhcG9pbnRzRXhjZWVkaW5nTGltaXQgLSBUaGUgYXJyYXkgb2YgZGF0YXBvaW50cyBleGNlZWRpbmcgdGhlIGxpbWl0LlxuICAgKi9cbiAgc2hvd1NlbmRWaWFFbWFpbEluZm9BbGVydChcbiAgICBmaWxlVHlwZTogc3RyaW5nLFxuICAgIGRhdGFwb2ludHNFeGNlZWRpbmdMaW1pdDogRGF0YXBvaW50c0V4Y2VlZGluZ0xpbWl0W11cbiAgKTogdm9pZCB7XG4gICAgY29uc3QgbWVzc2FnZVRlbXBsYXRlID0gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoXG4gICAgICBnZXR0ZXh0KGBZb3Ugd2lsbCBnZXQge3skZmlsZVR5cGVUZXh0fX0gZmlsZShzKSBmb3Ige3skY291bnR9fSBzZXJpZXMgdmlhIGVtYWlsLmApLFxuICAgICAgeyAkY291bnQ6IGRhdGFwb2ludHNFeGNlZWRpbmdMaW1pdC5sZW5ndGgsICRmaWxlVHlwZVRleHQ6IGZpbGVUeXBlIH1cbiAgICApO1xuICAgIGNvbnN0IGZvcm1hdHRlZExpc3QgPSBkYXRhcG9pbnRzRXhjZWVkaW5nTGltaXRcbiAgICAgIC5tYXAoXG4gICAgICAgIGRhdGFwb2ludCA9PlxuICAgICAgICAgIGDigKIgJHtkYXRhcG9pbnQuZGF0YXBvaW50RGV0YWlsLnNvdXJjZX1fJHtkYXRhcG9pbnQuZGF0YXBvaW50RGV0YWlsLnZhbHVlRnJhZ21lbnRUeXBlfV8ke2RhdGFwb2ludC5kYXRhcG9pbnREZXRhaWwudmFsdWVGcmFnbWVudFNlcmllc31gXG4gICAgICApXG4gICAgICAuam9pbignXFxuJyk7XG5cbiAgICB0aGlzLmFsZXJ0U2VydmljZS5pbmZvKG1lc3NhZ2VUZW1wbGF0ZSwgZm9ybWF0dGVkTGlzdCk7XG4gIH1cblxuICBhc3luYyBmZXRjaE1lYXN1cmVtZW50RGF0YUZpbGVzQW5kUGFpcldpdGhTb3VyY2VEZXRhaWxzKFxuICAgIGFjY2VwdEZpbGVUeXBlOiBzdHJpbmcsXG4gICAgZXhwb3J0Q29uZmlnOiBFeHBvcnRDb25maWdcbiAgKTogUHJvbWlzZTxEYXRhVG9FeHBvcnRXaXRoQmFja2VuZENyZWF0ZWRGaWxlW10+IHtcbiAgICBjb25zdCBtZWFzdXJlbWVudEZpbGVDb25maWc6IE1lYXN1cmVtZW50RmlsZUNvbmZpZyA9IHtcbiAgICAgIGV4cG9ydENvbmZpZyxcbiAgICAgIGFjY2VwdEZpbGVUeXBlXG4gICAgfTtcbiAgICBjb25zdCBmaWxlUHJvbWlzZXMgPSBleHBvcnRDb25maWcuZGF0YXBvaW50RGV0YWlscy5tYXAoZGV0YWlscyA9PlxuICAgICAgdGhpcy5mZXRjaEFuZFByb2Nlc3NNZWFzdXJlbWVudEZpbGUoZGV0YWlscywgbWVhc3VyZW1lbnRGaWxlQ29uZmlnKVxuICAgICk7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKGZpbGVQcm9taXNlcyk7XG4gIH1cblxuICBhc3luYyBmZXRjaEFuZFByb2Nlc3NNZWFzdXJlbWVudEZpbGUoXG4gICAgZGV0YWlsczogRGF0YXBvaW50RGV0YWlscyxcbiAgICBtZWFzdXJlbWVudEZpbGVDb25maWc6IE1lYXN1cmVtZW50RmlsZUNvbmZpZ1xuICApOiBQcm9taXNlPERhdGFUb0V4cG9ydFdpdGhCYWNrZW5kQ3JlYXRlZEZpbGUgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBmaWx0ZXI6IElNZWFzdXJlbWVudEZpbHRlciA9IHRoaXMucHJlcGFyZU1lYXN1cmVtZW50c0ZpbHRlcihcbiAgICAgIGRldGFpbHMsXG4gICAgICBtZWFzdXJlbWVudEZpbGVDb25maWcuZXhwb3J0Q29uZmlnXG4gICAgKTtcbiAgICBjb25zdCBoZWFkZXIgPSB7IGFjY2VwdDogbWVhc3VyZW1lbnRGaWxlQ29uZmlnLmFjY2VwdEZpbGVUeXBlIH07XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgbWVhc3VyZW1lbnRGaWxlUmVzcG9uc2U6IElGZXRjaFJlc3BvbnNlID1cbiAgICAgICAgYXdhaXQgdGhpcy5tZWFzdXJlbWVudFNlcnZpY2UuZ2V0TWVhc3VyZW1lbnRzRmlsZShmaWx0ZXIsIGhlYWRlcik7XG5cbiAgICAgIC8vIElmIHRoZSBzdGF0dXMgaXMgMjAwLCB0aGVuIHRoZSBmaWxlIGlzIGluIHRoZSByZXNwb25zZS5cbiAgICAgIC8vIElmIHRoZSBzdGF0dXMgaXMgMjAyLCB0aGVuIHRoZSBmaWxlIGlzIGJlaW5nIHByb2Nlc3NlZCBieSB0aGUgYmFja2VuZCBhbmQgd2lsbCBiZSBzZW50IGJ5IGVtYWlsLlxuICAgICAgaWYgKG1lYXN1cmVtZW50RmlsZVJlc3BvbnNlLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlTWVhc3VyZW1lbnRzV2l0aEl0c1NvdXJjZURldGFpbHMoZGV0YWlscywgbWVhc3VyZW1lbnRGaWxlUmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRTZXJ2ZXJGYWlsdXJlKGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBtZXJnZU1lYXN1cmVtZW50c1dpdGhJdHNTb3VyY2VEZXRhaWxzKFxuICAgIGRldGFpbHM6IERhdGFwb2ludERldGFpbHMsXG4gICAgbWVhc3VyZW1lbnRGaWxlOiBJRmV0Y2hSZXNwb25zZVxuICApOiBQcm9taXNlPERhdGFUb0V4cG9ydFdpdGhCYWNrZW5kQ3JlYXRlZEZpbGU+IHtcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlOiBkZXRhaWxzLnNvdXJjZSxcbiAgICAgIHZhbHVlRnJhZ21lbnRTZXJpZXM6IGRldGFpbHMudmFsdWVGcmFnbWVudFNlcmllcyxcbiAgICAgIHZhbHVlRnJhZ21lbnRUeXBlOiBkZXRhaWxzLnZhbHVlRnJhZ21lbnRUeXBlLFxuICAgICAgZmV0Y2hlZE1lYXN1cmVtZW50c0Jsb2JGaWxlOiBhd2FpdCBtZWFzdXJlbWVudEZpbGUuYmxvYigpXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGZldGNoQW5kUHJlcGFyZURhdGFUb0V4cG9ydChcbiAgICBleHBvcnRDb25maWc6IEV4cG9ydENvbmZpZyxcbiAgICBpc01lYXN1cmVtZW50OiBib29sZWFuXG4gICk6IFByb21pc2U8RGF0YVRvRXhwb3J0W10+IHtcbiAgICByZXR1cm4gaXNNZWFzdXJlbWVudFxuICAgICAgPyBhd2FpdCB0aGlzLmZldGNoQW5kUHJlcGFyZU1lYXN1cmVtZW50RGF0YVRvRXhwb3J0Rm9yUHJldmlldyhleHBvcnRDb25maWcpXG4gICAgICA6IGF3YWl0IHRoaXMuZmV0Y2hBbmRQcmVwYXJlU2VyaWVzRGF0YVRvRXhwb3J0KGV4cG9ydENvbmZpZyk7XG4gIH1cblxuICBhc3luYyBnZXRTb3VyY2VzV2l0aFBlcm1pc3Npb25zVG9SZWFkKGRhdGFwb2ludERldGFpbHM6IERhdGFwb2ludERldGFpbHNbXSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBkYXRlRnJvbSA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgZGF0ZVRvID0gbmV3IERhdGUoZGF0ZUZyb20pO1xuXG4gICAgY29uc3QgZmV0Y2hlZERhdGFQcm9taXNlcyA9IGRhdGFwb2ludERldGFpbHMubWFwKGFzeW5jIGRhdGFwb2ludCA9PiB7XG4gICAgICBjb25zdCByYXdGaWx0ZXI6IElTZXJpZXNGaWx0ZXIgPSB7XG4gICAgICAgIGRhdGVGcm9tLFxuICAgICAgICBkYXRlVG8sXG4gICAgICAgIHNvdXJjZTogZGF0YXBvaW50LnNvdXJjZVxuICAgICAgfTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyByZXMgfTogSVJlc3VsdDxJU2VyaWVzPiA9IGF3YWl0IHRoaXMuZmV0Y2hTZXJpZXNEYXRhKHJhd0ZpbHRlcik7XG4gICAgICAgIGlmIChyZXM/LnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgcmV0dXJuIGRhdGFwb2ludC5zb3VyY2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBJZiBhbiBlcnJvciBvY2N1cnMgZHVyaW5nIGZldGNoLCByZXR1cm4gbnVsbCB0byBwcmV2ZW50IHByb21pc2UgcmVqZWN0aW9uXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgZmV0Y2hlZFNvdXJjZXMgPSBhd2FpdCBQcm9taXNlLmFsbChmZXRjaGVkRGF0YVByb21pc2VzKTtcbiAgICByZXR1cm4gZmV0Y2hlZFNvdXJjZXMuZmlsdGVyKChzb3VyY2UpOiBzb3VyY2UgaXMgc3RyaW5nID0+IHNvdXJjZSAhPT0gbnVsbCk7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyBhbmQgcHJlcGFyZXMgbWVhc3VyZW1lbnQgZGF0YSBmb3IgcHJldmlldy5cbiAgICpcbiAgICogRW1wdHkgRGF0YVRvRXhwb3J0IG9iamVjdCBjYW4gYmUgcmV0dXJuZWQsIGJlY2F1c2UgdW5saWtlIHNlcmllcyBkYXRhLFxuICAgKiBtZWFzdXJlbWVudCBkYXRhIGlzIG5vdCBmdXJ0aGVyIHByb2Nlc3NlZCBiZXNpZGVzIHNob3dpbmcgb25seSBpbiB0aGUgcHJldmlldy5cbiAgICogQ1NWL0V4Y2VsIGZpbGVzIGFyZSBnZW5lcmF0ZWQgYnkgdGhlIGJhY2tlbmQgZm9yIG1lYXN1cmVtZW50cy5cbiAgICpcbiAgICogQHBhcmFtIGV4cG9ydENvbmZpZyAtIFRoZSBleHBvcnQgY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgRGF0YVRvRXhwb3J0IG9iamVjdHMgb3IgbnVsbCB3aGVuIG5vIGRhdGEgaXMgZmV0Y2hlZC5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hBbmRQcmVwYXJlTWVhc3VyZW1lbnREYXRhVG9FeHBvcnRGb3JQcmV2aWV3KFxuICAgIGV4cG9ydENvbmZpZzogRXhwb3J0Q29uZmlnXG4gICk6IFByb21pc2U8RGF0YVRvRXhwb3J0W10+IHwgbnVsbCB7XG4gICAgY29uc3QgZGF0YVRvRXhwb3J0UHJvbWlzZXM6IFByb21pc2U8RGF0YVRvRXhwb3J0PltdID0gZXhwb3J0Q29uZmlnLmRhdGFwb2ludERldGFpbHMubWFwKFxuICAgICAgYXN5bmMgZGV0YWlscyA9PiB7XG4gICAgICAgIGNvbnN0IGZldGNoZWRNZWFzdXJlbWVudERhdGE6IElSZXN1bHRMaXN0PElNZWFzdXJlbWVudD4gPVxuICAgICAgICAgIGF3YWl0IHRoaXMuZmV0Y2hNZWFzdXJlbWVudERhdGFGb3JQcmV2aWV3KGRldGFpbHMsIGV4cG9ydENvbmZpZyk7XG5cbiAgICAgICAgaWYgKGZldGNoZWRNZWFzdXJlbWVudERhdGE/LmRhdGE/Lmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NNZWFzdXJlbWVudERhdGFGb3JQcmV2aWV3KGRldGFpbHMsIGZldGNoZWRNZWFzdXJlbWVudERhdGEuZGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgKTtcblxuICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChkYXRhVG9FeHBvcnRQcm9taXNlcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoTWVhc3VyZW1lbnREYXRhRm9yUHJldmlldyhcbiAgICBkZXRhaWxzOiBEYXRhcG9pbnREZXRhaWxzLFxuICAgIGV4cG9ydENvbmZpZzogRXhwb3J0Q29uZmlnXG4gICk6IFByb21pc2U8SVJlc3VsdExpc3Q8SU1lYXN1cmVtZW50Pj4gfCB1bmRlZmluZWQge1xuICAgIGxldCBtZWFzdXJlbWVudHM6IElSZXN1bHRMaXN0PElNZWFzdXJlbWVudD4gfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBmaWx0ZXI6IElNZWFzdXJlbWVudEZpbHRlciA9IHRoaXMucHJlcGFyZU1lYXN1cmVtZW50c0ZpbHRlcihcbiAgICAgIGRldGFpbHMsXG4gICAgICBleHBvcnRDb25maWcsXG4gICAgICBNRUFTVVJFTUVOVFNfUFJFVklFV19JVEVNU19MSU1JVFxuICAgICk7XG5cbiAgICB0cnkge1xuICAgICAgLy8gVE9ETzogY29uc2lkZXIgYWRkaW5nIGEgY2FjaGUgbWVjaGFuaXNtIC0+IE1UTS02MDI4OVxuICAgICAgLy8gV2hlbiB1c2VyIHN3aXRjaGVzIGJldHdlZW4gcmVwb3J0IHR5cGVzLCBhbmQgcmVzdCBvZiB0aGUgc2V0dGluZ3MgYXJlIHRoZSBzYW1lLCB0aGVuIHRoZSBkYXRhIHNob3VsZCBub3QgYmUgZmV0Y2hlZCBhZ2Fpbj9cbiAgICAgIG1lYXN1cmVtZW50cyA9IGF3YWl0IHRoaXMubWVhc3VyZW1lbnRTZXJ2aWNlLmxpc3QoZmlsdGVyKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2UuYWRkU2VydmVyRmFpbHVyZShlcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1lYXN1cmVtZW50cztcbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZU1lYXN1cmVtZW50c0ZpbHRlcihcbiAgICBkZXRhaWxzOiBEYXRhcG9pbnREZXRhaWxzLFxuICAgIGV4cG9ydENvbmZpZzogRXhwb3J0Q29uZmlnLFxuICAgIHBhZ2VTaXplPzogbnVtYmVyXG4gICk6IElNZWFzdXJlbWVudEZpbHRlciB7XG4gICAgY29uc3QgZmlsdGVyOiBJTWVhc3VyZW1lbnRGaWx0ZXIgPSB7XG4gICAgICAvLyBSb3VuZCB0aGUgJ2Zyb20nIHRpbWUgdG8gdGhlIHByZXZpb3VzIGZ1bGwgbWludXRlLlxuICAgICAgZGF0ZUZyb206IHRoaXMuYWRqdXN0RGF0ZShleHBvcnRDb25maWcuZGF0ZUZyb20sIC0xKSxcbiAgICAgIC8vIFJvdW5kIHRoZSAndG8nIHRpbWUgdG8gdGhlIG5lYXJlc3QgZnVsbCBtaW51dGUuXG4gICAgICBkYXRlVG86IHRoaXMuYWRqdXN0RGF0ZShleHBvcnRDb25maWcuZGF0ZVRvLCAxKSxcbiAgICAgIHNvdXJjZTogZGV0YWlscy5zb3VyY2UsXG4gICAgICB2YWx1ZUZyYWdtZW50U2VyaWVzOiBkZXRhaWxzLnZhbHVlRnJhZ21lbnRTZXJpZXMsXG4gICAgICB2YWx1ZUZyYWdtZW50VHlwZTogZGV0YWlscy52YWx1ZUZyYWdtZW50VHlwZVxuICAgIH07XG5cbiAgICBpZiAocGFnZVNpemUpIHtcbiAgICAgIGZpbHRlci5wYWdlU2l6ZSA9IHBhZ2VTaXplO1xuICAgIH1cblxuICAgIHJldHVybiBmaWx0ZXI7XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NNZWFzdXJlbWVudERhdGFGb3JQcmV2aWV3KFxuICAgIGRldGFpbHM6IERhdGFwb2ludERldGFpbHMsXG4gICAgZGF0YTogSU1lYXN1cmVtZW50W11cbiAgKTogRGF0YVRvRXhwb3J0IHtcbiAgICBjb25zdCB1bml0ID0gZGF0YVswXVtkZXRhaWxzLnZhbHVlRnJhZ21lbnRUeXBlXVtkZXRhaWxzLnZhbHVlRnJhZ21lbnRTZXJpZXNdPy51bml0IHx8ICcnO1xuXG4gICAgY29uc3QgdmFsdWVzOiB7IFt0aW1lc3RhbXA6IHN0cmluZ106IG51bWJlciB9ID0ge307XG4gICAgZGF0YS5mb3JFYWNoKG1lYXN1cmVtZW50ID0+IHtcbiAgICAgIHZhbHVlc1ttZWFzdXJlbWVudC50aW1lXSA9XG4gICAgICAgIG1lYXN1cmVtZW50W2RldGFpbHMudmFsdWVGcmFnbWVudFR5cGVdW2RldGFpbHMudmFsdWVGcmFnbWVudFNlcmllc10udmFsdWU7XG4gICAgfSk7XG5cbiAgICByZXR1cm4geyAuLi5kZXRhaWxzLCB1bml0LCB0aW1lVmFsdWVNYXA6IHZhbHVlcyB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaEFuZFByZXBhcmVTZXJpZXNEYXRhVG9FeHBvcnQoZXhwb3J0Q29uZmlnOiBFeHBvcnRDb25maWcpIHtcbiAgICBjb25zdCBkYXRhcG9pbnRzVmFsdWVzRGF0YU1hcDogRGF0YXBvaW50c1ZhbHVlc0RhdGFNYXAgPSB0aGlzLmdyb3VwU2VyaWVzQnlEZXZpY2VJZChcbiAgICAgIGV4cG9ydENvbmZpZy5kYXRhcG9pbnREZXRhaWxzXG4gICAgKTtcblxuICAgIGNvbnN0IGZldGNoZWREYXRhUHJvbWlzZXMgPSBBcnJheS5mcm9tKGRhdGFwb2ludHNWYWx1ZXNEYXRhTWFwKS5tYXAoXG4gICAgICBhc3luYyAoW3NvdXJjZSwgc2VyaWVzXSkgPT4ge1xuICAgICAgICBjb25zdCB7IGRhdGVGcm9tLCBkYXRlVG8sIGFnZ3JlZ2F0aW9uIH0gPSBleHBvcnRDb25maWc7XG5cbiAgICAgICAgY29uc3QgcmF3RmlsdGVyOiBJU2VyaWVzRmlsdGVyID0ge1xuICAgICAgICAgIGRhdGVGcm9tLFxuICAgICAgICAgIGRhdGVUbyxcbiAgICAgICAgICBzb3VyY2UsXG4gICAgICAgICAgc2VyaWVzLFxuICAgICAgICAgIGFnZ3JlZ2F0aW9uVHlwZTogYWdncmVnYXRpb24gYXMgYWdncmVnYXRpb25UeXBlXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgeyBkYXRhIH06IElSZXN1bHQ8SVNlcmllcz4gPSBhd2FpdCB0aGlzLmZldGNoU2VyaWVzRGF0YShyYXdGaWx0ZXIpO1xuXG4gICAgICAgIHJldHVybiB7IHNvdXJjZSwgZGF0YSB9O1xuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCBmZXRjaGVkRGF0YUdyb3VwZWRCeVNvdXJjZTogU291cmNlSXRlbVtdID0gYXdhaXQgUHJvbWlzZS5hbGwoZmV0Y2hlZERhdGFQcm9taXNlcyk7XG5cbiAgICByZXR1cm4gdGhpcy5wcm9jZXNzU2VyaWVzRGF0YShleHBvcnRDb25maWcuZGF0YXBvaW50RGV0YWlscywgZmV0Y2hlZERhdGFHcm91cGVkQnlTb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBtYXAgb2YgYWN0aXZlIGRhdGEgcG9pbnRzIGRldmljZSBJRHMgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIHNlcmllcy5cbiAgICpcbiAgICogRXhhbXBsZSBvdXRwdXQ6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogbmV3IE1hcChbXG4gICAqICAgWyc4NDQ2NTcyMDInLCBbJ2M4eV9UZW1wZXJhdHVyZS5UJ11dLFxuICAgKiAgIFsnMzI2NjY0MjcnLCBbJ2M4eV9CYXR0ZXJ5LkJhdHRlcnknXV1cbiAgICogXSk7XG4gICAqIGBgYFxuICAgKiBAcGFyYW0gZGF0YXBvaW50RGV0YWlscyAtIEFuIGFycmF5IG9mIGRhdGEgcG9pbnRzIGRldGFpbHMuXG4gICAqIEByZXR1cm5zIEEgbWFwIHdoZXJlIHRoZSBrZXkgaXMgdGhlIGRhdGEgcG9pbnQgSUQgYW5kIHRoZSB2YWx1ZSBpcyBhbiBhcnJheSBvZiBkYXRhIHBvaW50IHNlcmllcy5cbiAgICovXG4gIHByaXZhdGUgZ3JvdXBTZXJpZXNCeURldmljZUlkKGRhdGFwb2ludERldGFpbHM6IERhdGFwb2ludERldGFpbHNbXSk6IERhdGFwb2ludHNWYWx1ZXNEYXRhTWFwIHtcbiAgICByZXR1cm4gZGF0YXBvaW50RGV0YWlscy5yZWR1Y2UoXG4gICAgICAoXG4gICAgICAgIG1hcDogRGF0YXBvaW50c1ZhbHVlc0RhdGFNYXAsXG4gICAgICAgIHsgdmFsdWVGcmFnbWVudFR5cGUsIHZhbHVlRnJhZ21lbnRTZXJpZXMsIHNvdXJjZSB9OiBEYXRhcG9pbnREZXRhaWxzXG4gICAgICApID0+IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBgJHt2YWx1ZUZyYWdtZW50VHlwZX0uJHt2YWx1ZUZyYWdtZW50U2VyaWVzfWA7XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nVmFsdWUgPSBtYXAuZ2V0KHNvdXJjZSkgPz8gW107XG4gICAgICAgIG1hcC5zZXQoc291cmNlLCBbLi4uZXhpc3RpbmdWYWx1ZSwgdmFsdWVdKTtcbiAgICAgICAgcmV0dXJuIG1hcDtcbiAgICAgIH0sXG4gICAgICBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KClcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaFNlcmllc0RhdGEocmF3RmlsdGVyOiBJU2VyaWVzRmlsdGVyKTogUHJvbWlzZTxJUmVzdWx0PElTZXJpZXM+PiB8IHVuZGVmaW5lZCB7XG4gICAgbGV0IHNlcmllc0RhdGE6IElSZXN1bHQ8SVNlcmllcz4gfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBmaWx0ZXI6IElTZXJpZXNGaWx0ZXIgPSB0aGlzLnByZXBhcmVTZXJpZXNGaWx0ZXIoe1xuICAgICAgZGF0ZUZyb206IHJhd0ZpbHRlci5kYXRlRnJvbSxcbiAgICAgIGRhdGVUbzogcmF3RmlsdGVyLmRhdGVUbyxcbiAgICAgIHNvdXJjZTogcmF3RmlsdGVyLnNvdXJjZSxcbiAgICAgIHNlcmllczogcmF3RmlsdGVyLnNlcmllcyxcbiAgICAgIGFnZ3JlZ2F0aW9uVHlwZTogcmF3RmlsdGVyLmFnZ3JlZ2F0aW9uVHlwZVxuICAgIH0pO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFRPRE86IGNvbnNpZGVyIGFkZGluZyBhIGNhY2hlIG1lY2hhbmlzbSAtPiBNVE0tNjAyODlcbiAgICAgIC8vIFdoZW4gdXNlciBzd2l0Y2hlcyBiZXR3ZWVuIHJlcG9ydCB0eXBlcywgYW5kIHJlc3Qgb2YgdGhlIHNldHRpbmdzIGFyZSB0aGUgc2FtZSwgdGhlbiB0aGUgZGF0YSBzaG91bGQgbm90IGJlIGZldGNoZWQgYWdhaW4/XG4gICAgICBzZXJpZXNEYXRhID0gYXdhaXQgdGhpcy5tZWFzdXJlbWVudFNlcnZpY2UubGlzdFNlcmllcyhmaWx0ZXIpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRTZXJ2ZXJGYWlsdXJlKGVycm9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VyaWVzRGF0YTtcbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZVNlcmllc0ZpbHRlcihmaWx0ZXJzOiBJU2VyaWVzRmlsdGVyKTogSVNlcmllc0ZpbHRlciB7XG4gICAgY29uc3QgeyBkYXRlRnJvbSwgZGF0ZVRvLCBzb3VyY2UsIHNlcmllcywgYWdncmVnYXRpb25UeXBlIH0gPSBmaWx0ZXJzO1xuICAgIC8vIFJvdW5kIHRoZSAnZnJvbScgdGltZSB0byB0aGUgcHJldmlvdXMgZnVsbCBtaW51dGUuXG4gICAgY29uc3QgZnJvbSA9IHRoaXMuYWRqdXN0RGF0ZShkYXRlRnJvbSwgLTEpO1xuICAgIC8vIFJvdW5kIHRoZSAndG8nIHRpbWUgdG8gdGhlIG5lYXJlc3QgZnVsbCBtaW51dGUuXG4gICAgY29uc3QgdG8gPSB0aGlzLmFkanVzdERhdGUoZGF0ZVRvLCAxKTtcblxuICAgIGNvbnN0IGZpbHRlcjogSVNlcmllc0ZpbHRlciA9IHtcbiAgICAgIGRhdGVGcm9tOiBmcm9tLFxuICAgICAgZGF0ZVRvOiB0byxcbiAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgcmV2ZXJ0OiB0cnVlXG4gICAgfTtcblxuICAgIC8vIFRoZSAnTk9ORScgYWdncmVnYXRpb24gdHlwZSBpcyBub3QgaGFuZGxlZCBieSBhIGJhY2tlbmQsIHNvIGV2ZW4gd2hlbiBpcyBzZWxlY3RlZCwgaXQgaXMgbm90IHBhc3NlZCBhcyBhIGZpbHRlciBwYXJhbWV0ZXIuXG4gICAgaWYgKGFnZ3JlZ2F0aW9uVHlwZSAmJiBhZ2dyZWdhdGlvblR5cGUgIT09IChBR0dSRUdBVElPTl9WQUxVRVMubm9uZSBhcyBhZ2dyZWdhdGlvblR5cGUpKSB7XG4gICAgICBmaWx0ZXIuYWdncmVnYXRpb25UeXBlID0gYWdncmVnYXRpb25UeXBlO1xuICAgIH1cblxuICAgIC8vIFRPRE86IGl0IGlzIGEgdGVtcG9yYWwgd29ya2Fyb3VuZCBmb3IgYSBidWcgaW4gdGhlIGJhY2tlbmQsXG4gICAgLy8gd2hlcmUgdGhlIHNlcmllcyB3aXRoIG1vcmUgdGhhbiBvbmUgZG90IGFyZSBpbXBvc3NpYmxlIHRvIHJldHJpZXZlOlxuICAgIC8vIGh0dHBzOi8vY3VtdWxvY2l0eS5hdGxhc3NpYW4ubmV0L2Jyb3dzZS9NVE0tNTkyNzdcbiAgICBpZiAoc2VyaWVzKSB7XG4gICAgICBjb25zdCBoYXNNb3JlVGhhbk9uZURvdCA9IChzZXJpZXMgYXMgc3RyaW5nW10pLnNvbWUocyA9PiBzLnNwbGl0KCcuJykubGVuZ3RoID4gMik7XG4gICAgICBpZiAoIWhhc01vcmVUaGFuT25lRG90KSB7XG4gICAgICAgIGZpbHRlci5zZXJpZXMgPSBzZXJpZXM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbHRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzZXMgdGhlIGZldGNoZWQgc2VyaWVzIGRhdGEgYW5kIHByZXBhcmVzIGl0IGZvciBleHBvcnQuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhcG9pbnREZXRhaWxzIC0gQW4gYXJyYXkgb2YgZGF0YSBwb2ludCBkZXRhaWxzLlxuICAgKiBAcGFyYW0gZmV0Y2hlZERhdGFNYXAgLSBBIG1hcCBvZiBmZXRjaGVkIHNlcmllcyBkYXRhIGdyb3VwZWQgYnkgc291cmNlLlxuICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBEYXRhVG9FeHBvcnQgb2JqZWN0cy5cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc1Nlcmllc0RhdGEoZGF0YXBvaW50RGV0YWlsczogRGF0YXBvaW50RGV0YWlsc1tdLCBmZXRjaGVkRGF0YU1hcDogU291cmNlSXRlbVtdKSB7XG4gICAgY29uc3QgdmFsdWVzR3JvdXBlZEJ5U291cmNlID0gdGhpcy51dGlsc1NlcnZpY2UudHJhbnNmb3JtRGF0YVN0cnVjdHVyZShmZXRjaGVkRGF0YU1hcCk7XG5cbiAgICByZXR1cm4gZGF0YXBvaW50RGV0YWlscy5tYXAoKGRldGFpbHM6IERhdGFwb2ludERldGFpbHMpID0+IHtcbiAgICAgIGxldCB1bml0OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgZGF0YTogVGltZVNlcmllc0RhdGE7XG5cbiAgICAgIC8qKlxuICAgICAgICogVW5pcXVlIGtleSB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIGRpZmZlcmVudCBzZXJpZXMgZnJvbSBzYW1lIHNvdXJjZSxcbiAgICAgICAqIGUuZy46IGM4eV9BY2NlbGVyYXRpb24uYWNjZWxlcmF0aW9uWCwgYzh5X0FjY2VsZXJhdGlvbi5hY2NlbGVyYXRpb25ZLCBjOHlfQWNjZWxlcmF0aW9uLmFjY2VsZXJhdGlvblpcbiAgICAgICAqL1xuICAgICAgY29uc3Qgc2VyaWVzS2V5ID0gYCR7ZGV0YWlscy52YWx1ZUZyYWdtZW50VHlwZX0uJHtkZXRhaWxzLnZhbHVlRnJhZ21lbnRTZXJpZXN9YDtcblxuICAgICAgaWYgKHZhbHVlc0dyb3VwZWRCeVNvdXJjZVtkZXRhaWxzLnNvdXJjZV1bc2VyaWVzS2V5XSkge1xuICAgICAgICB1bml0ID0gdmFsdWVzR3JvdXBlZEJ5U291cmNlW2RldGFpbHMuc291cmNlXVtzZXJpZXNLZXldLnNlcmllc0RldGFpbHMudW5pdDtcbiAgICAgICAgZGF0YSA9IHZhbHVlc0dyb3VwZWRCeVNvdXJjZVtkZXRhaWxzLnNvdXJjZV1bc2VyaWVzS2V5XS52YWx1ZXM7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmRldGFpbHMsXG4gICAgICAgIHVuaXQsXG4gICAgICAgIHRpbWVWYWx1ZU1hcDogZGF0YVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGp1c3RzIHRoZSBnaXZlbiBkYXRlIGJ5IGFkZGluZyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBtaW51dGVzIGFuZCBzZXR0aW5nIHNlY29uZHMgdG8gMC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGUgLSBUaGUgZGF0ZSB0byBiZSBhZGp1c3RlZCBpbiBzdHJpbmcgZm9ybWF0LlxuICAgKiBAcGFyYW0gbWludXRlcyAtIFRoZSBudW1iZXIgb2YgbWludXRlcyB0byBhZGQgdG8gdGhlIGRhdGUuXG4gICAqIEByZXR1cm5zIFRoZSBhZGp1c3RlZCBkYXRlIGluIHRoZSBmb3JtYXQgJ1lZWVktTU0tRERUSEg6bW06c3MrSEg6TU0nLlxuICAgKi9cbiAgcHJpdmF0ZSBhZGp1c3REYXRlKGRhdGU6IHN0cmluZyB8IERhdGUsIG1pbnV0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgZGF0ZVRpbWUgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICBkYXRlVGltZS5zZXRNaW51dGVzKGRhdGVUaW1lLmdldE1pbnV0ZXMoKSArIG1pbnV0ZXMpO1xuICAgIGRhdGVUaW1lLnNldFNlY29uZHMoMCk7XG5cbiAgICBjb25zdCBvZmZzZXQgPSAtZGF0ZVRpbWUuZ2V0VGltZXpvbmVPZmZzZXQoKTtcbiAgICBjb25zdCBvZmZzZXRTaWduID0gb2Zmc2V0ID49IDAgPyAnKycgOiAnLSc7XG4gICAgY29uc3QgcGFkID0gKG51bTogbnVtYmVyKTogc3RyaW5nID0+IChudW0gPCAxMCA/ICcwJyArIG51bSA6IG51bS50b1N0cmluZygpKTtcbiAgICBjb25zdCBvZmZzZXRIb3VycyA9IHBhZChNYXRoLmZsb29yKE1hdGguYWJzKG9mZnNldCkgLyA2MCkpO1xuICAgIGNvbnN0IG9mZnNldE1pbnV0ZXMgPSBwYWQoTWF0aC5hYnMob2Zmc2V0KSAlIDYwKTtcblxuICAgIGNvbnN0IHllYXIgPSBkYXRlVGltZS5nZXRGdWxsWWVhcigpO1xuICAgIGNvbnN0IG1vbnRoID0gcGFkKGRhdGVUaW1lLmdldE1vbnRoKCkgKyAxKTtcbiAgICBjb25zdCBkYXkgPSBwYWQoZGF0ZVRpbWUuZ2V0RGF0ZSgpKTtcbiAgICBjb25zdCBob3VycyA9IHBhZChkYXRlVGltZS5nZXRIb3VycygpKTtcbiAgICBjb25zdCBtaW51dGVzU3RyaW5nID0gcGFkKGRhdGVUaW1lLmdldE1pbnV0ZXMoKSk7XG4gICAgY29uc3Qgc2Vjb25kcyA9ICcwMCc7XG5cbiAgICByZXR1cm4gYCR7eWVhcn0tJHttb250aH0tJHtkYXl9VCR7aG91cnN9OiR7bWludXRlc1N0cmluZ306JHtzZWNvbmRzfSR7b2Zmc2V0U2lnbn0ke29mZnNldEhvdXJzfToke29mZnNldE1pbnV0ZXN9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmltcyB0aGUgZ2l2ZW4gSFRNTCBtZXNzYWdlIGJ5IHJlbW92aW5nIGxpc3QgaXRlbXMgdGhhdCBjb3JyZXNwb25kIHRvIHplcm8gY291bnRzLlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBIVE1MIHN0cmluZyBjb250YWluaW5nIHRoZSBtZXNzYWdlIHdpdGggbGlzdCBpdGVtcy5cbiAgICogQHBhcmFtIGNvdW50cyAtIEFuIGFycmF5IG9mIG51bWJlciB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBlYWNoIGxpc3QgaXRlbS5cbiAgICogQHBhcmFtIGNvdW50VG9UcmltIC0gQSBjb3VudCB0aGF0IHdpbGwgYmUgdHJpbW1lZCB3aXRoIGNvcnJlc3BvbmRpbmcgbGlzdCBpdGVtLlxuICAgKiBAcmV0dXJucyBBIHRyaW1tZWQgSFRNTCBzdHJpbmcgd2l0aCBsaXN0IGl0ZW1zIHJlbW92ZWQgd2hlcmUgdGhlIGNvcnJlc3BvbmRpbmcgY291bnQgaXMgemVyby5cbiAgICpcbiAgICogRXhhbXBsZTpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBtZXNzYWdlID0gJzx1bD48bGk+SXRlbSAxPC9saT48bGk+SXRlbSAyPC9saT48bGk+SXRlbSAzPC9saT48L3VsPic7XG4gICAqIGNvbnN0IGNvdW50cyA9IFsxLCAwLCAyXTtcbiAgICogY29uc3QgdHJpbW1lZE1lc3NhZ2UgPSB0aGlzLnJlbW92ZVplcm9Db3VudExpc3RJdGVtcyhtZXNzYWdlLCBjb3VudHMpO1xuICAgKiAvLyBSZXN1bHQ6ICc8dWw+PGxpPkl0ZW0gMTwvbGk+PGxpPkl0ZW0gMzwvbGk+PC91bD4nXG4gICAqIGBgYFxuICAgKi9cbiAgcHJpdmF0ZSByZW1vdmVaZXJvQ291bnRMaXN0SXRlbXMobWVzc2FnZTogc3RyaW5nLCBjb3VudHM6IG51bWJlcltdLCBjb3VudFRvVHJpbSA9IDApOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcbiAgICBjb25zdCBkb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKG1lc3NhZ2UsICd0ZXh0L2h0bWwnKTtcbiAgICBjb25zdCBsaXN0SXRlbXMgPSBkb2MucXVlcnlTZWxlY3RvckFsbCgndWwgbGknKTtcblxuICAgIGxpc3RJdGVtcy5mb3JFYWNoKChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgaWYgKGNvdW50c1tpbmRleF0gPT09IGNvdW50VG9UcmltKSB7XG4gICAgICAgIGl0ZW0ucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZG9jLmJvZHkuaW5uZXJIVE1MO1xuICB9XG59XG4iXX0=