@elderbyte/ngx-starter 18.12.2 → 18.12.4

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 (320) hide show
  1. package/esm2022/lib/common/data/datasource/patch/deep-partial-patcher.mjs +2 -2
  2. package/esm2022/lib/common/enums/elder-enum-translation.service.mjs +3 -3
  3. package/esm2022/lib/common/forms/elder-form-field-control-base.directive.mjs +3 -3
  4. package/esm2022/lib/common/forms/elder-from-field-base.mjs +3 -3
  5. package/esm2022/lib/common/forms/elder-from-field-customizable-base.mjs +3 -3
  6. package/esm2022/lib/common/forms/elder-from-field-entity-base.mjs +3 -3
  7. package/esm2022/lib/common/forms/elder-from-field-multi-entity-base.mjs +3 -3
  8. package/esm2022/lib/common/forms/form-field-base.component.mjs +3 -3
  9. package/esm2022/lib/common/forms/multi-model-base.component.mjs +3 -3
  10. package/esm2022/lib/common/forms/template-composite-control.mjs +3 -3
  11. package/esm2022/lib/common/forms/value-accessor-base.mjs +3 -3
  12. package/esm2022/lib/common/http/http-client-builder.service.mjs +3 -3
  13. package/esm2022/lib/common/http/http-client-pristine.mjs +3 -3
  14. package/esm2022/lib/common/http/transfer/data-transfer-factory.mjs +3 -3
  15. package/esm2022/lib/common/time/temporal-util.mjs +13 -1
  16. package/esm2022/lib/common/url/elder-router.service.mjs +3 -3
  17. package/esm2022/lib/common/url/elder-url-fragment-params.service.mjs +3 -3
  18. package/esm2022/lib/components/access-denied/elder-access-denied.component.mjs +3 -3
  19. package/esm2022/lib/components/access-denied/elder-access-denied.module.mjs +4 -4
  20. package/esm2022/lib/components/auditing/audited-entity/elder-audited-entity.component.mjs +3 -3
  21. package/esm2022/lib/components/auditing/elder-audit.module.mjs +4 -4
  22. package/esm2022/lib/components/badge/elder-badge/elder-badge.component.mjs +9 -9
  23. package/esm2022/lib/components/badge/elder-badge.directive.mjs +3 -3
  24. package/esm2022/lib/components/badge/elder-badge.module.mjs +4 -4
  25. package/esm2022/lib/components/button-group/elder-button-group/elder-button-group.component.mjs +3 -3
  26. package/esm2022/lib/components/button-group/elder-button-group.module.mjs +4 -4
  27. package/esm2022/lib/components/card-organizer/card-organizer/elder-card-organizer.component.mjs +3 -3
  28. package/esm2022/lib/components/card-organizer/card-organizer/elder-stack-card.directive.mjs +3 -3
  29. package/esm2022/lib/components/card-organizer/card-stack/elder-card-stack.component.mjs +3 -3
  30. package/esm2022/lib/components/card-organizer/elder-card-organizer.module.mjs +4 -4
  31. package/esm2022/lib/components/cards/elder-card/elder-card-header/elder-card-header.component.mjs +3 -3
  32. package/esm2022/lib/components/cards/elder-card/elder-card.component.mjs +18 -18
  33. package/esm2022/lib/components/cards/elder-card/elder-card.module.mjs +4 -4
  34. package/esm2022/lib/components/chips/elder-chip-label.directive.mjs +3 -3
  35. package/esm2022/lib/components/chips/elder-chips.module.mjs +4 -4
  36. package/esm2022/lib/components/connectivity/elder-connectivity.module.mjs +4 -4
  37. package/esm2022/lib/components/connectivity/elder-connectivity.service.mjs +3 -3
  38. package/esm2022/lib/components/connectivity/offline-indicator/elder-offline-indicator.component.mjs +3 -3
  39. package/esm2022/lib/components/containers/elder-containers.module.mjs +4 -4
  40. package/esm2022/lib/components/containers/elder-scroll-container/elder-scroll-container.component.mjs +3 -3
  41. package/esm2022/lib/components/csv/elder-csv-export-btn/elder-csv-export-btn.component.mjs +3 -3
  42. package/esm2022/lib/components/csv/elder-csv-stream-exporter-builder.service.mjs +3 -3
  43. package/esm2022/lib/components/csv/elder-csv.module.mjs +4 -4
  44. package/esm2022/lib/components/currency/elder-currency.module.mjs +4 -4
  45. package/esm2022/lib/components/currency/elder-currency.pipe.mjs +3 -3
  46. package/esm2022/lib/components/data-transfer/elder-data-transfer.module.mjs +4 -4
  47. package/esm2022/lib/components/data-transfer/elder-data-transfer.service.mjs +3 -3
  48. package/esm2022/lib/components/data-transfer/http-data-transfer/http-data-transfer.component.mjs +3 -3
  49. package/esm2022/lib/components/data-transfer/http-data-transfer-aggregate/http-data-transfer-aggregate.component.mjs +3 -3
  50. package/esm2022/lib/components/data-transfer/http-data-transfer-indicator/http-data-transfer-indicator.component.mjs +3 -3
  51. package/esm2022/lib/components/data-transfer/http-data-transfer-overview/http-data-transfer-overview.component.mjs +3 -3
  52. package/esm2022/lib/components/data-view/base/elder-data-view-base.mjs +3 -3
  53. package/esm2022/lib/components/data-view/common/composite-sort/composite-sort-dc.directive.mjs +3 -3
  54. package/esm2022/lib/components/data-view/common/composite-sort/elder-composite-sort/elder-composite-sort.component.mjs +3 -3
  55. package/esm2022/lib/components/data-view/common/data-context-state-indicator/data-context-state-indicator.component.mjs +3 -3
  56. package/esm2022/lib/components/data-view/common/elder-data-common.module.mjs +4 -4
  57. package/esm2022/lib/components/data-view/common/elder-data-toolbar/elder-data-toolbar.component.mjs +6 -6
  58. package/esm2022/lib/components/data-view/common/elder-single-sort/elder-single-sort.component.mjs +3 -3
  59. package/esm2022/lib/components/data-view/common/selection/data-context-selection.directive.mjs +3 -3
  60. package/esm2022/lib/components/data-view/common/selection/elder-selection-master-checkbox/elder-selection-master-checkbox.component.mjs +3 -3
  61. package/esm2022/lib/components/data-view/grid/elder-grid/elder-grid.component.mjs +9 -9
  62. package/esm2022/lib/components/data-view/grid/elder-grid.module.mjs +4 -4
  63. package/esm2022/lib/components/data-view/master-detail/elder-detail-dialog/elder-detail-dialog.component.mjs +3 -3
  64. package/esm2022/lib/components/data-view/master-detail/elder-detail.directive.mjs +3 -3
  65. package/esm2022/lib/components/data-view/master-detail/elder-master-activation.directive.mjs +3 -3
  66. package/esm2022/lib/components/data-view/master-detail/elder-master-detail.component.mjs +3 -3
  67. package/esm2022/lib/components/data-view/master-detail/elder-master-detail.module.mjs +4 -4
  68. package/esm2022/lib/components/data-view/master-detail/elder-master-detail.service.mjs +3 -3
  69. package/esm2022/lib/components/data-view/master-detail/elder-master.directive.mjs +3 -3
  70. package/esm2022/lib/components/data-view/simple/elder-simple-selection-view/elder-simple-selection-view.component.mjs +3 -3
  71. package/esm2022/lib/components/data-view/simple/elder-simple-selection-view/elder-simple-selection-view.module.mjs +4 -4
  72. package/esm2022/lib/components/data-view/table/activation/elder-delete-active.directive.mjs +3 -3
  73. package/esm2022/lib/components/data-view/table/activation/elder-table-activation.directive.mjs +3 -3
  74. package/esm2022/lib/components/data-view/table/elder-center-cell.directive.mjs +3 -3
  75. package/esm2022/lib/components/data-view/table/elder-number-cell.directive.mjs +3 -3
  76. package/esm2022/lib/components/data-view/table/elder-paginator-intl.mjs +3 -3
  77. package/esm2022/lib/components/data-view/table/elder-table/elder-table-toolbar.directive.mjs +3 -3
  78. package/esm2022/lib/components/data-view/table/elder-table/elder-table.component.mjs +3 -3
  79. package/esm2022/lib/components/data-view/table/elder-table-column.directive.mjs +3 -3
  80. package/esm2022/lib/components/data-view/table/elder-table-extension.directive.mjs +3 -3
  81. package/esm2022/lib/components/data-view/table/elder-table-root.directive.mjs +3 -3
  82. package/esm2022/lib/components/data-view/table/elder-table-row.directive.mjs +3 -3
  83. package/esm2022/lib/components/data-view/table/elder-table-sort.directive.mjs +3 -3
  84. package/esm2022/lib/components/data-view/table/elder-table.module.mjs +4 -4
  85. package/esm2022/lib/components/data-view/table/model/elder-table-model.mjs +3 -3
  86. package/esm2022/lib/components/dialogs/confirm-dialog/elder-confirm-dialog.component.mjs +3 -3
  87. package/esm2022/lib/components/dialogs/elder-dialog.module.mjs +4 -4
  88. package/esm2022/lib/components/dialogs/elder-dialog.service.mjs +3 -3
  89. package/esm2022/lib/components/dialogs/question-dialog/elder-question-dialog.component.mjs +3 -3
  90. package/esm2022/lib/components/dialogs/selection-dialog/elder-selection-dialog/elder-selection-dialog.component.mjs +3 -3
  91. package/esm2022/lib/components/dialogs/selection-dialog/elder-selection-dialog.directive.mjs +3 -3
  92. package/esm2022/lib/components/errors/elder-error.module.mjs +4 -4
  93. package/esm2022/lib/components/errors/exception-detail/elder-exception-detail.component.mjs +3 -3
  94. package/esm2022/lib/components/expand-toggle-button/elder-expand-toggle-button.component.mjs +3 -3
  95. package/esm2022/lib/components/expand-toggle-button/elder-expand-toggle-button.module.mjs +4 -4
  96. package/esm2022/lib/components/files/blob-viewer/elder-blob-viewer.component.mjs +3 -3
  97. package/esm2022/lib/components/files/drag-n-drop/elder-drop-zone/elder-drop-zone.component.mjs +3 -3
  98. package/esm2022/lib/components/files/drag-n-drop/global-drag-drop.service.mjs +3 -3
  99. package/esm2022/lib/components/files/elder-file-drop-zone.directive.mjs +3 -3
  100. package/esm2022/lib/components/files/elder-file-select.directive.mjs +3 -3
  101. package/esm2022/lib/components/files/elder-file.module.mjs +4 -4
  102. package/esm2022/lib/components/files/file-select/file-select.component.mjs +3 -3
  103. package/esm2022/lib/components/files/file-upload/file-upload.component.mjs +3 -3
  104. package/esm2022/lib/components/forms/clipboard/elder-clipboard.service.mjs +3 -3
  105. package/esm2022/lib/components/forms/directives/base/elder-class-hostbinding-base.mjs +3 -3
  106. package/esm2022/lib/components/forms/directives/elder-clipboard-put.directive.mjs +3 -3
  107. package/esm2022/lib/components/forms/directives/elder-delayed-focus.directive.mjs +3 -3
  108. package/esm2022/lib/components/forms/directives/elder-form-field-dense.directive.mjs +3 -3
  109. package/esm2022/lib/components/forms/directives/elder-form-field-label.directive.mjs +3 -3
  110. package/esm2022/lib/components/forms/directives/elder-form-field-no-hint.directive.mjs +3 -3
  111. package/esm2022/lib/components/forms/directives/elder-form-field-no-spinner.directive.mjs +3 -3
  112. package/esm2022/lib/components/forms/directives/elder-forms-directives.module.mjs +4 -4
  113. package/esm2022/lib/components/forms/directives/elder-initial-value.directive.mjs +3 -3
  114. package/esm2022/lib/components/forms/directives/elder-input-pattern.directive.mjs +3 -3
  115. package/esm2022/lib/components/forms/directives/elder-key-event.directive.mjs +3 -3
  116. package/esm2022/lib/components/forms/directives/elder-next-focusable.directive.mjs +3 -3
  117. package/esm2022/lib/components/forms/directives/elder-plug-parent-form.directive.mjs +3 -3
  118. package/esm2022/lib/components/forms/directives/elder-stop-event-propagation.directive.mjs +3 -3
  119. package/esm2022/lib/components/forms/directives/elder-tab-focus-trap.directive.mjs +3 -3
  120. package/esm2022/lib/components/forms/directives/elder-touched.directive.mjs +3 -3
  121. package/esm2022/lib/components/forms/directives/elder-triple-state-checkbox.directive.mjs +3 -3
  122. package/esm2022/lib/components/forms/directives/validation/elder-validation-error.directive.mjs +3 -3
  123. package/esm2022/lib/components/forms/directives/validation/strategies/common-validation-message-strategy.mjs +3 -3
  124. package/esm2022/lib/components/forms/directives/validation/strategies/dynamic-validation-message-strategy.mjs +3 -3
  125. package/esm2022/lib/components/forms/directives/validation/validation-message-renderer.service.mjs +3 -3
  126. package/esm2022/lib/components/forms/directives/validation/validators/elder-max.validator.mjs +3 -3
  127. package/esm2022/lib/components/forms/directives/validation/validators/elder-min.validator.mjs +3 -3
  128. package/esm2022/lib/components/forms/directives/validation/validators/elder-multiple-of.validator.mjs +3 -3
  129. package/esm2022/lib/components/forms/directives/validation/validators/elder-required-ignore-zero.validator.mjs +3 -3
  130. package/esm2022/lib/components/forms/elder-forms.module.mjs +4 -4
  131. package/esm2022/lib/components/forms/search/domain/context/search-context.service.mjs +3 -3
  132. package/esm2022/lib/components/forms/search/domain/url/elder-search-url.directive.mjs +3 -3
  133. package/esm2022/lib/components/forms/search/domain/url/elder-search-url.service.mjs +3 -3
  134. package/esm2022/lib/components/forms/search/elder-search-context.directive.mjs +3 -3
  135. package/esm2022/lib/components/forms/search/elder-search-input.directive.mjs +3 -3
  136. package/esm2022/lib/components/forms/search/elder-search.module.mjs +4 -4
  137. package/esm2022/lib/components/forms/search/search-box/elder-search-box.component.mjs +3 -3
  138. package/esm2022/lib/components/forms/search/search-box/elder-search-panel.component.mjs +3 -3
  139. package/esm2022/lib/components/global-search/elder-global-search.component.mjs +3 -3
  140. package/esm2022/lib/components/global-search/elder-global-search.module.mjs +4 -4
  141. package/esm2022/lib/components/global-search/elder-global-search.service.mjs +3 -3
  142. package/esm2022/lib/components/graph/elder-progress-bar/elder-progress-bar.component.mjs +3 -3
  143. package/esm2022/lib/components/graph/elder-progress-bar/elder-progress-bar.module.mjs +4 -4
  144. package/esm2022/lib/components/headers/elder-header/elder-header.component.mjs +3 -3
  145. package/esm2022/lib/components/headers/elder-header.module.mjs +4 -4
  146. package/esm2022/lib/components/http-support/elder-http-client.service.mjs +3 -3
  147. package/esm2022/lib/components/i18n/entities/elder-i18n-entities.module.mjs +4 -4
  148. package/esm2022/lib/components/i18n/entities/elder-localized-input/elder-localized-input.component.mjs +3 -3
  149. package/esm2022/lib/components/i18n/entities/elder-localized-input-dialog/elder-localized-input-dialog.component.mjs +3 -3
  150. package/esm2022/lib/components/i18n/entities/elder-localized-input-dialog.service.mjs +3 -3
  151. package/esm2022/lib/components/i18n/entities/elder-localized-input-table/elder-localized-input-table.component.mjs +3 -3
  152. package/esm2022/lib/components/i18n/entities/elder-localized-text-column.directive.mjs +3 -3
  153. package/esm2022/lib/components/i18n/entities/elder-localized-texts.directive.mjs +3 -3
  154. package/esm2022/lib/components/i18n/entities/picker/i18n-pick-async.pipe.mjs +3 -3
  155. package/esm2022/lib/components/i18n/entities/picker/i18n-pick.pipe.mjs +3 -3
  156. package/esm2022/lib/components/i18n/entities/picker/localisation-picker.service.mjs +3 -3
  157. package/esm2022/lib/components/i18n/language/elder-language-interceptor.mjs +3 -3
  158. package/esm2022/lib/components/i18n/language/elder-language.module.mjs +4 -4
  159. package/esm2022/lib/components/i18n/language/elder-language.service.mjs +3 -3
  160. package/esm2022/lib/components/i18n/language/language-switcher/elder-language-switcher.component.mjs +3 -3
  161. package/esm2022/lib/components/i18n/locales/elder-locales-de-ch.module.mjs +4 -4
  162. package/esm2022/lib/components/iframes/data-view/data-view-iframe/data-view-iframe.component.mjs +3 -3
  163. package/esm2022/lib/components/iframes/data-view/data-view-iframe-adapter.directive.mjs +3 -3
  164. package/esm2022/lib/components/iframes/elder-iframe.module.mjs +4 -4
  165. package/esm2022/lib/components/iframes/iframe-close.directive.mjs +3 -3
  166. package/esm2022/lib/components/iframes/iframe-dialog/iframe-dialog.component.mjs +3 -3
  167. package/esm2022/lib/components/iframes/iframe-host/iframe-host.component.mjs +3 -3
  168. package/esm2022/lib/components/iframes/iframe-side-content/iframe-side-content.component.mjs +3 -3
  169. package/esm2022/lib/components/iframes/iframe.service.mjs +3 -3
  170. package/esm2022/lib/components/infinitescroll/elder-infinite-autocomplete.directive.mjs +3 -3
  171. package/esm2022/lib/components/infinitescroll/elder-infinite-scroll.directive.mjs +3 -3
  172. package/esm2022/lib/components/infinitescroll/elder-infinite-scroll.module.mjs +4 -4
  173. package/esm2022/lib/components/input/autocomplete/elder-autocomplete/elder-suggestion-panel.component.mjs +3 -3
  174. package/esm2022/lib/components/input/autocomplete/elder-autocomplete-many.directive.mjs +3 -3
  175. package/esm2022/lib/components/input/autocomplete/elder-autocomplete.directive.mjs +3 -3
  176. package/esm2022/lib/components/input/autocomplete/elder-autocomplete.module.mjs +4 -4
  177. package/esm2022/lib/components/labels/elder-labels.module.mjs +4 -4
  178. package/esm2022/lib/components/labels/labels-input/labels-input.component.mjs +3 -3
  179. package/esm2022/lib/components/measures/dimensions/dimensions-input/elder-dimensions-input.component.mjs +3 -3
  180. package/esm2022/lib/components/measures/dimensions/validation/elder-required-dimensions.validator.mjs +3 -3
  181. package/esm2022/lib/components/measures/directives/elder-unit-select.directive.mjs +3 -3
  182. package/esm2022/lib/components/measures/elder-measures.module.mjs +8 -8
  183. package/esm2022/lib/components/measures/elder-quantity-transform.pipe.mjs +3 -3
  184. package/esm2022/lib/components/measures/elder-quantity.pipe.mjs +3 -3
  185. package/esm2022/lib/components/measures/elder-unit.service.mjs +3 -3
  186. package/esm2022/lib/components/measures/quantity-input/quantity-form-field/elder-quantity-form-field.component.mjs +3 -3
  187. package/esm2022/lib/components/measures/quantity-input/quantity-input-control/elder-quantity-input-control.component.mjs +3 -3
  188. package/esm2022/lib/components/measures/quantity-input/validation/elder-quantity-range.validator.mjs +3 -3
  189. package/esm2022/lib/components/measures/quantity-input/validation/elder-required-quantity.validator.mjs +3 -3
  190. package/esm2022/lib/components/measures/util/elder-quantity.service.mjs +3 -3
  191. package/esm2022/lib/components/navigation/bread-crumbs/bread-crumbs/elder-bread-crumbs.component.mjs +3 -3
  192. package/esm2022/lib/components/navigation/bread-crumbs/elder-bread-crumbs.module.mjs +4 -4
  193. package/esm2022/lib/components/navigation/nav/elder-nav.module.mjs +4 -4
  194. package/esm2022/lib/components/navigation/nav/nav-group/elder-nav-group.component.mjs +3 -3
  195. package/esm2022/lib/components/navigation/nav/nav-link/elder-nav-link.component.mjs +3 -3
  196. package/esm2022/lib/components/navigation/nav/nav-list/elder-nav-list.component.mjs +3 -3
  197. package/esm2022/lib/components/navigation/toolbar/elder-toolbar-column.directive.mjs +3 -3
  198. package/esm2022/lib/components/navigation/toolbar/elder-toolbar.module.mjs +4 -4
  199. package/esm2022/lib/components/navigation/toolbar/elder-toolbar.service.mjs +3 -3
  200. package/esm2022/lib/components/navigation/toolbar/toolbar/elder-toolbar.component.mjs +3 -3
  201. package/esm2022/lib/components/navigation/toolbar/toolbar-title/elder-toolbar-title.component.mjs +3 -3
  202. package/esm2022/lib/components/navigation/toolbar/toolbar-title/elder-toolbar-title.service.mjs +3 -3
  203. package/esm2022/lib/components/overlays/elder-overlay-origin.directive.mjs +3 -3
  204. package/esm2022/lib/components/overlays/elder-overlay-ref.mjs +3 -3
  205. package/esm2022/lib/components/overlays/elder-overlay-trigger.directive.mjs +3 -3
  206. package/esm2022/lib/components/overlays/elder-overlay.component.mjs +3 -3
  207. package/esm2022/lib/components/overlays/elder-overlay.module.mjs +4 -4
  208. package/esm2022/lib/components/page/exit-guard/page-exit-guard.module.mjs +4 -4
  209. package/esm2022/lib/components/page/exit-guard/page-exit-guard.service.mjs +3 -3
  210. package/esm2022/lib/components/page/exit-guard/page-exit-lock/page-exit-lock.component.mjs +3 -3
  211. package/esm2022/lib/components/page/exit-guard/page-exit-lock-indicator/page-exit-lock-indicator.component.mjs +3 -3
  212. package/esm2022/lib/components/page/exit-guard/page-exit-lock-overview/page-exit-lock-overview.component.mjs +3 -3
  213. package/esm2022/lib/components/panels/card-panel/elder-card-panel.component.mjs +3 -3
  214. package/esm2022/lib/components/panels/elder-dialog-panel/elder-dialog-panel.component.mjs +3 -3
  215. package/esm2022/lib/components/panels/elder-panel.module.mjs +4 -4
  216. package/esm2022/lib/components/panels/flat/elder-panel.component.mjs +3 -3
  217. package/esm2022/lib/components/panels/toggle-panel/elder-toggle-panel-trigger.directive.mjs +3 -3
  218. package/esm2022/lib/components/panels/toggle-panel/elder-toggle-panel.component.mjs +9 -9
  219. package/esm2022/lib/components/scrollbar/elder-scrollbar.directive.mjs +3 -3
  220. package/esm2022/lib/components/scrollbar/elder-scrollbar.module.mjs +4 -4
  221. package/esm2022/lib/components/select/auto/elder-auto-select-first.directive.mjs +3 -3
  222. package/esm2022/lib/components/select/auto/elder-auto-select-first.service.mjs +3 -3
  223. package/esm2022/lib/components/select/auto/elder-auto-select-suggest-first.directive.mjs +3 -3
  224. package/esm2022/lib/components/select/elder-select-base.mjs +3 -3
  225. package/esm2022/lib/components/select/elder-select-chip.directive.mjs +9 -9
  226. package/esm2022/lib/components/select/elder-select-on-tab.directive.mjs +3 -3
  227. package/esm2022/lib/components/select/elder-select-value.directive.mjs +3 -3
  228. package/esm2022/lib/components/select/elder-select.module.mjs +4 -4
  229. package/esm2022/lib/components/select/filter/elder-chips-include-exclude.directive.mjs +3 -3
  230. package/esm2022/lib/components/select/filter/elder-filter-chip-template/elder-filter-chip-template.component.mjs +3 -3
  231. package/esm2022/lib/components/select/multi/elder-chip-select-option/elder-select-option.component.mjs +3 -3
  232. package/esm2022/lib/components/select/multi/elder-multi-select-base.mjs +3 -3
  233. package/esm2022/lib/components/select/multi/elder-multi-select-chip-options/elder-multi-select-chip-options.component.mjs +3 -3
  234. package/esm2022/lib/components/select/multi/elder-multi-select-chips/elder-multi-select-chips.component.mjs +3 -3
  235. package/esm2022/lib/components/select/multi/elder-multi-select-form-field.mjs +3 -3
  236. package/esm2022/lib/components/select/multi/elder-mutli-select-all-directive.mjs +3 -3
  237. package/esm2022/lib/components/select/multi/elder-search-include-exclude.directive.mjs +3 -3
  238. package/esm2022/lib/components/select/popup/selection-model-popup-trigger-adapter.directive.mjs +3 -3
  239. package/esm2022/lib/components/select/popup/selection-model-popup.directive.mjs +3 -3
  240. package/esm2022/lib/components/select/popup/templated-selection-dialog/templated-selection-dialog.component.mjs +3 -3
  241. package/esm2022/lib/components/select/single/elder-clear-select.directive.mjs +3 -3
  242. package/esm2022/lib/components/select/single/elder-select/elder-select.component.mjs +3 -3
  243. package/esm2022/lib/components/select/single/elder-select-form-field.mjs +3 -3
  244. package/esm2022/lib/components/select-chip-list/chip-list-select/elder-chip-list-select.component.mjs +3 -3
  245. package/esm2022/lib/components/select-chip-list/elder-chip-list-select.module.mjs +4 -4
  246. package/esm2022/lib/components/shell/drawers/elder-route-outlet-drawer.service.mjs +3 -3
  247. package/esm2022/lib/components/shell/drawers/elder-router-outlet.service.mjs +3 -3
  248. package/esm2022/lib/components/shell/elder-shell-slot.directive.mjs +3 -3
  249. package/esm2022/lib/components/shell/elder-shell.module.mjs +4 -4
  250. package/esm2022/lib/components/shell/elder-shell.service.mjs +3 -3
  251. package/esm2022/lib/components/shell/header/elder-app-header/elder-app-header.component.mjs +3 -3
  252. package/esm2022/lib/components/shell/shell/elder-shell.component.mjs +12 -12
  253. package/esm2022/lib/components/shell/shell-navigation-toggle/elder-shell-navigation-toggle.component.mjs +3 -3
  254. package/esm2022/lib/components/tabs/elder-tab/elder-tab.directive.mjs +3 -3
  255. package/esm2022/lib/components/tabs/elder-tab-group-routing/elder-tab-group-routing.directive.mjs +3 -3
  256. package/esm2022/lib/components/tabs/elder-tab.module.mjs +4 -4
  257. package/esm2022/lib/components/theme/elder-theme-applier.directive.mjs +3 -3
  258. package/esm2022/lib/components/theme/elder-theme-preference.service.mjs +3 -3
  259. package/esm2022/lib/components/theme/elder-theme-toggle/elder-theme-toggle.component.mjs +3 -3
  260. package/esm2022/lib/components/theme/elder-theme.directive.mjs +3 -3
  261. package/esm2022/lib/components/theme/elder-theme.module.mjs +4 -4
  262. package/esm2022/lib/components/theme/elder-theme.service.mjs +3 -3
  263. package/esm2022/lib/components/time/date-adapters/custom-date-adapter.mjs +3 -3
  264. package/esm2022/lib/components/time/duration/elder-duration-input/elder-duration-input.component.mjs +3 -3
  265. package/esm2022/lib/components/time/elder-date-switcher/elder-date-switcher.component.mjs +3 -3
  266. package/esm2022/lib/components/time/elder-date-time-input/elder-date-time-input.component.mjs +3 -3
  267. package/esm2022/lib/components/time/elder-interval-input/elder-interval-input.component.mjs +3 -3
  268. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-binding.directive.mjs +7 -12
  269. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.mjs +83 -81
  270. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +82 -99
  271. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.mjs +284 -0
  272. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model.mjs +445 -0
  273. package/esm2022/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.mjs +37 -0
  274. package/esm2022/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.mjs +25 -0
  275. package/esm2022/lib/components/time/elder-local-date-input/elder-local-date-input.component.mjs +3 -3
  276. package/esm2022/lib/components/time/elder-local-time-input/elder-local-time-input.component.mjs +3 -3
  277. package/esm2022/lib/components/time/elder-time.module.mjs +4 -4
  278. package/esm2022/lib/components/time/period/elder-period-input/elder-period-input.component.mjs +3 -3
  279. package/esm2022/lib/components/time/pipes/to-iso-date-string.pipe.mjs +3 -3
  280. package/esm2022/lib/components/toasts/elder-toast.module.mjs +4 -4
  281. package/esm2022/lib/components/toasts/elder-toast.service.mjs +3 -3
  282. package/esm2022/lib/components/toasts/standard-toast/standard-toast.component.mjs +3 -3
  283. package/esm2022/lib/components/url-fragment/elder-url-fragment.module.mjs +4 -4
  284. package/esm2022/lib/components/url-fragment/url-fragment-switcher/elder-url-fragment-switcher.component.mjs +3 -3
  285. package/esm2022/lib/components/viewers/elder-svg-viewer/elder-svg-viewer.component.mjs +3 -3
  286. package/esm2022/lib/components/viewers/elder-viewers.module.mjs +4 -4
  287. package/esm2022/lib/features/event-source/fetch/reactive-fetch-event-source.service.mjs +3 -3
  288. package/esm2022/lib/features/event-source/standard/elder-event-source.service.mjs +3 -3
  289. package/esm2022/lib/features/kafent/access-token-provider.mjs +3 -3
  290. package/esm2022/lib/features/kafent/kafent-config.mjs +3 -3
  291. package/esm2022/lib/features/kafent/kafent-event-stream.mjs +3 -3
  292. package/esm2022/lib/features/kafent/kafent-event.service.mjs +3 -3
  293. package/esm2022/lib/features/kafent/kafent.module.mjs +4 -4
  294. package/esm2022/lib/features/kafent/sse/kafent-event-stream-sse.service.mjs +3 -3
  295. package/esm2022/lib/pipes/bytes.pipe.mjs +3 -3
  296. package/esm2022/lib/pipes/elder-pipes.module.mjs +10 -10
  297. package/esm2022/lib/pipes/elder-repeat.pipe.mjs +3 -3
  298. package/esm2022/lib/pipes/elder-round.pipe.mjs +3 -3
  299. package/esm2022/lib/pipes/elder-safe-url.pipe.mjs +3 -3
  300. package/esm2022/lib/pipes/elder-truncate.pipe.mjs +3 -3
  301. package/esm2022/lib/pipes/iso-duration.pipe.mjs +3 -3
  302. package/esm2022/lib/pipes/iso-interval-parse.pipe.mjs +3 -3
  303. package/esm2022/lib/pipes/iso-interval.pipe.mjs +3 -3
  304. package/esm2022/lib/pipes/time-ago.pipe.mjs +3 -3
  305. package/esm2022/lib/pipes/time-duration.pipe.mjs +3 -3
  306. package/esm2022/lib/pipes/weight.pipe.mjs +3 -3
  307. package/fesm2022/elderbyte-ngx-starter.mjs +1644 -1576
  308. package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
  309. package/lib/common/time/temporal-util.d.ts +2 -0
  310. package/lib/components/time/elder-interval-picker/elder-interval-picker-binding.directive.d.ts +3 -6
  311. package/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +25 -18
  312. package/lib/components/time/elder-interval-picker/elder-interval-picker.component.d.ts +19 -25
  313. package/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.d.ts +77 -0
  314. package/lib/components/time/elder-interval-picker/model/interval-picker-model.d.ts +113 -0
  315. package/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.d.ts +7 -0
  316. package/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.d.ts +4 -0
  317. package/package.json +1 -1
  318. package/src/assets/i18n/fr.json +123 -0
  319. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.service.mjs +0 -708
  320. package/lib/components/time/elder-interval-picker/elder-interval-picker.service.d.ts +0 -132
@@ -1,5 +1,5 @@
1
1
  import { CommonModule } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, effect, ElementRef, EventEmitter, input, Input, Output, ViewChild, } from '@angular/core';
2
+ import { booleanAttribute, ChangeDetectionStrategy, Component, effect, ElementRef, EventEmitter, Input, input, Output, ViewChild, } from '@angular/core';
3
3
  import { FormsModule } from '@angular/forms';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import { DateAdapter } from '@angular/material/core';
@@ -12,11 +12,11 @@ import { MatTooltip } from '@angular/material/tooltip';
12
12
  import { LoggerFactory } from '@elderbyte/ts-logger';
13
13
  import { TranslateModule } from '@ngx-translate/core';
14
14
  import { TemporalUtil } from '../../../common/time/temporal-util';
15
- import { CustomDateAdapter } from '../../../components/time/date-adapters/custom-date-adapter';
16
- import { ElderLocalDateInputComponent } from '../../../components/time/elder-local-date-input/elder-local-date-input.component';
17
- import { ElderIntervalPickerService } from './elder-interval-picker.service';
15
+ import { CustomDateAdapter } from '../date-adapters/custom-date-adapter';
16
+ import { ElderLocalDateInputComponent } from '../elder-local-date-input/elder-local-date-input.component';
17
+ import { IntervalPickerModel } from './model/interval-picker-model';
18
18
  import * as i0 from "@angular/core";
19
- import * as i1 from "./elder-interval-picker.service";
19
+ import * as i1 from "./model/interval-picker-model";
20
20
  import * as i2 from "@angular/material/datepicker";
21
21
  import * as i3 from "@angular/material/form-field";
22
22
  import * as i4 from "@angular/material/input";
@@ -27,87 +27,57 @@ import * as i8 from "@angular/material/button";
27
27
  import * as i9 from "@ngx-translate/core";
28
28
  import * as i10 from "@angular/material/menu";
29
29
  export class ElderIntervalPickerComponent {
30
+ set interval(value) {
31
+ this.model.setInterval(value);
32
+ }
33
+ set anchorDateTime(value) {
34
+ this.model.setAnchorDateTime(value);
35
+ }
30
36
  /***************************************************************************
31
37
  * *
32
38
  * Constructor *
33
39
  * *
34
40
  **************************************************************************/
35
- constructor(svc) {
36
- this.svc = svc;
41
+ constructor(model) {
42
+ this.model = model;
37
43
  /***************************************************************************
38
44
  * *
39
45
  * Fields *
40
46
  * *
41
47
  **************************************************************************/
42
48
  this.log = LoggerFactory.getLogger(this.constructor.name);
49
+ this.emitOnChange = input(true, { transform: (v) => booleanAttribute(v) });
50
+ this.intervalInputMode = input('date-range');
51
+ this.showAnchor = input(false, { transform: (v) => booleanAttribute(v) });
52
+ this.anchorReadOnly = input(false, { transform: (v) => booleanAttribute(v) });
53
+ this.showResultText = input(true, { transform: (v) => booleanAttribute(v) });
54
+ this.showHelpText = input(false, { transform: (v) => booleanAttribute(v) });
55
+ this.lastExcludesToday = input(false, { transform: (v) => booleanAttribute(v) });
56
+ this.dateChange = new EventEmitter();
43
57
  this.calendarAnchorDateCssClassFn = (cellDate, view) => {
44
58
  return this.calendarAnchorDateCssClassFnBody(cellDate, view);
45
59
  };
46
- this.isEmittingOnChange = true;
47
- this.intervalInputMode = 'date-range';
48
- this.showAnchor = false;
49
- this.isAnchorReadOnly = false;
50
- this.isResultTextVisible = true;
51
- this.isHelpTextsVisible = false;
52
- this.isSelectLastModeExcludingToday = false;
53
- this.dateChange = new EventEmitter();
54
- this.inputInterval = input(null);
55
- this.inputAnchorDateTime = input(null);
56
- /***************************************************************************
57
- * *
58
- * Effects *
59
- * *
60
- **************************************************************************/
61
- this._updateMatCalendarElAnchorCssClassEffect = effect(() => {
62
- const anchorDate = this.svc.anchorDate();
63
- if (anchorDate) {
64
- this.calendarStart.updateTodaysDate();
65
- this.calendarEnd.updateTodaysDate();
60
+ this.model.setupEventEmitter(this.dateChange);
61
+ effect(() => {
62
+ if (this.model.anchorDate()) {
63
+ this.updateMatCalendarTodayDate();
66
64
  }
67
65
  });
68
- this._updateMatCalendarElSelectionEffect = effect(() => {
69
- const startDate = this.svc.startDate();
70
- const endDate = this.svc.endDate();
71
- if (!this.calendarStart || !this.calendarEnd) {
72
- return;
73
- }
74
- if (!startDate && !endDate) {
75
- return;
76
- }
77
- const calendar1 = this.calendarStart;
78
- const calendar2 = this.calendarEnd;
79
- setTimeout(() => {
80
- // timeout is needed to run run calendar update last, otherwise there are issues
81
- if (startDate) {
82
- const startJsDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
83
- calendar1.activeDate = startJsDate;
84
- }
85
- if (endDate) {
86
- const endJsDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
87
- calendar2.activeDate = endJsDate;
88
- }
89
- }, 0);
66
+ effect(() => {
67
+ this.updateMatCalendarActiveDate(this.model.startDate(), this.model.endDate());
90
68
  });
91
- this.svc.setupInputInterval(this.inputInterval);
92
- this.svc.setupInputAnchorDateTime(this.inputAnchorDateTime);
93
- this.svc.setupEventEmitter(this.dateChange);
94
69
  }
95
70
  /***************************************************************************
96
71
  * *
97
72
  * Life Cycle *
98
73
  * *
99
74
  **************************************************************************/
100
- ngOnInit() {
101
- if (this.inputInterval) {
102
- this.svc.pullInputInterval();
103
- }
104
- if (this.inputAnchorDateTime()) {
105
- this.svc.pullInputAnchorDateTime();
106
- }
107
- }
108
75
  ngAfterViewInit() {
109
- this.svc.isEmittingOnChange.set(this.isEmittingOnChange);
76
+ this.model.isEmittingOnChange.set(this.emitOnChange());
110
77
  this.setupDateInputCalendarFocusPrevention();
78
+ setTimeout(() => {
79
+ this.model.setInitialized();
80
+ }, 0);
111
81
  }
112
82
  ngOnDestroy() {
113
83
  this.removeEventListeners();
@@ -140,36 +110,36 @@ export class ElderIntervalPickerComponent {
140
110
  nativeElementEnd.addEventListener('focus', this.calendarElFocusEventHandler, true);
141
111
  }
142
112
  clearStartDateTime() {
143
- this.svc.clearStartDateTime();
144
- this.svc.resetCalendarMode();
145
- if (this.isEmittingOnChange) {
146
- this.svc.emitMainDates();
113
+ this.model.clearStartDateTime();
114
+ this.model.resetCalendarMode();
115
+ if (this.emitOnChange()) {
116
+ this.model.emitMainDates();
147
117
  }
148
118
  }
149
119
  clearEndDateTime() {
150
- this.svc.clearEndDateTime();
151
- this.svc.resetCalendarMode();
152
- if (this.isEmittingOnChange) {
153
- this.svc.emitMainDates();
120
+ this.model.clearEndDateTime();
121
+ this.model.resetCalendarMode();
122
+ if (this.emitOnChange()) {
123
+ this.model.emitMainDates();
154
124
  }
155
125
  }
156
126
  clearStartAndEndDateTimes() {
157
- this.svc.clearStartDateTime();
158
- this.svc.clearEndDateTime();
159
- this.svc.resetCalendarMode();
160
- if (this.isEmittingOnChange) {
161
- this.svc.emitMainDates();
127
+ this.model.clearStartDateTime();
128
+ this.model.clearEndDateTime();
129
+ this.model.resetCalendarMode();
130
+ if (this.emitOnChange()) {
131
+ this.model.emitMainDates();
162
132
  }
163
133
  }
164
134
  handleStartCalendarChange(changedDate) {
165
- this.svc.calendarMode.set('days');
135
+ this.model.calendarMode.set('days');
166
136
  const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
167
- this.svc.startDate.set(newPlainDate);
137
+ this.model.setStartDate(newPlainDate);
168
138
  }
169
139
  handleEndCalendarChange(changedDate) {
170
- this.svc.calendarMode.set('days');
140
+ this.model.calendarMode.set('days');
171
141
  const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
172
- this.svc.endDate.set(newPlainDate);
142
+ this.model.setEndDate(newPlainDate);
173
143
  }
174
144
  /***************************************************************************
175
145
  * *
@@ -189,7 +159,7 @@ export class ElderIntervalPickerComponent {
189
159
  nativeElementEnd.removeEventListener('focus', this.calendarElFocusEventHandler, true);
190
160
  }
191
161
  calendarAnchorDateCssClassFnBody(cellDate, view) {
192
- const anchorDate = this.svc.fixedAnchorDate();
162
+ const anchorDate = this.model.fixedAnchorDate();
193
163
  if (!anchorDate) {
194
164
  return '';
195
165
  }
@@ -204,10 +174,33 @@ export class ElderIntervalPickerComponent {
204
174
  }
205
175
  return '';
206
176
  }
207
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.2", ngImport: i0, type: ElderIntervalPickerComponent, deps: [{ token: i1.ElderIntervalPickerService }], target: i0.ɵɵFactoryTarget.Component }); }
208
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.2", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { isEmittingOnChange: { classPropertyName: "isEmittingOnChange", publicName: "isEmittingOnChange", isSignal: false, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: false, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: false, isRequired: false, transformFunction: null }, isAnchorReadOnly: { classPropertyName: "isAnchorReadOnly", publicName: "isAnchorReadOnly", isSignal: false, isRequired: false, transformFunction: null }, isResultTextVisible: { classPropertyName: "isResultTextVisible", publicName: "isResultTextVisible", isSignal: false, isRequired: false, transformFunction: null }, isHelpTextsVisible: { classPropertyName: "isHelpTextsVisible", publicName: "isHelpTextsVisible", isSignal: false, isRequired: false, transformFunction: null }, isSelectLastModeExcludingToday: { classPropertyName: "isSelectLastModeExcludingToday", publicName: "isSelectLastModeExcludingToday", isSignal: false, isRequired: false, transformFunction: null }, inputInterval: { classPropertyName: "inputInterval", publicName: "inputInterval", isSignal: true, isRequired: false, transformFunction: null }, inputAnchorDateTime: { classPropertyName: "inputAnchorDateTime", publicName: "inputAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (isSelectLastModeExcludingToday) {\n <button mat-button (click)=\"svc.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"svc.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i2.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: ElderLocalDateInputComponent, selector: "elder-local-date-input", inputs: ["zone", "autoDatePicker", "arrows", "today", "center", "datePickerTouchUi", "allowNull", "datePickerEnabled", "isoValue", "dateValue", "isoDateValue"], outputs: ["blurred", "valueUpdatedBlur", "isoValueChange", "dateValueChange", "isoDateValueChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
177
+ updateMatCalendarActiveDate(startDate, endDate) {
178
+ if (!this.calendarStart || !this.calendarEnd) {
179
+ return;
180
+ }
181
+ if (!startDate && !endDate) {
182
+ return;
183
+ }
184
+ const calendarStart = this.calendarStart;
185
+ const calendarEnd = this.calendarEnd;
186
+ setTimeout(() => {
187
+ // timeout is needed to run calendar update last, otherwise there are issues
188
+ if (startDate) {
189
+ calendarStart.activeDate = TemporalUtil.getJSDateFromPlainDateTime(startDate);
190
+ }
191
+ if (endDate) {
192
+ calendarEnd.activeDate = TemporalUtil.getJSDateFromPlainDateTime(endDate);
193
+ }
194
+ }, 0);
195
+ }
196
+ updateMatCalendarTodayDate() {
197
+ this.calendarStart.updateTodaysDate();
198
+ this.calendarEnd.updateTodaysDate();
199
+ }
200
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, deps: [{ token: i1.IntervalPickerModel }], target: i0.ɵɵFactoryTarget.Component }); }
201
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { emitOnChange: { classPropertyName: "emitOnChange", publicName: "emitOnChange", isSignal: true, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: true, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: true, isRequired: false, transformFunction: null }, anchorReadOnly: { classPropertyName: "anchorReadOnly", publicName: "anchorReadOnly", isSignal: true, isRequired: false, transformFunction: null }, showResultText: { classPropertyName: "showResultText", publicName: "showResultText", isSignal: true, isRequired: false, transformFunction: null }, showHelpText: { classPropertyName: "showHelpText", publicName: "showHelpText", isSignal: true, isRequired: false, transformFunction: null }, lastExcludesToday: { classPropertyName: "lastExcludesToday", publicName: "lastExcludesToday", isSignal: true, isRequired: false, transformFunction: null }, interval: { classPropertyName: "interval", publicName: "interval", isSignal: false, isRequired: false, transformFunction: null }, anchorDateTime: { classPropertyName: "anchorDateTime", publicName: "anchorDateTime", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [IntervalPickerModel, { provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"model.editor.smartShift(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ model.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"model.editor.smartShift(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"model.editor.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (showResultText()) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (model.startDateTimeAsJSDate()) {\n {{ model.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (model.endDateTimeAsJSDate()) {\n {{ model.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ model.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"model.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.emitOnChange()) {\n <button color=\"primary\" mat-raised-button (click)=\"model.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"model.editor.selectCurrentDay()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"model.editor.selectYesterday()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (lastExcludesToday()) {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"model.editor.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"model.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"model.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.startDateHtmlString()\"\n (ngModelChange)=\"model.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.model.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.endDateHtmlString()\"\n (ngModelChange)=\"model.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.model.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getStartTimeString()\"\n (ngModelChange)=\"model.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearStartTime()\"\n [disabled]=\"!this.model.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getEndTimeString()\"\n (ngModelChange)=\"model.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearEndTime()\"\n [disabled]=\"!this.model.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftDay(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftDay(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftMonth(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftMonth(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftYear(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftYear(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode() === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (model.startDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!model.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (model.endDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!model.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (model.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.model.resetFixedAnchorPoint()\"\n [disabled]=\"!model.fixedAnchorDate() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"model.setAnchorDateFromForm($event)\"\n [value]=\"model.getAnchorPointAsLocaleDate()\"\n [readonly]=\"anchorReadOnly()\"\n >\n </elder-local-date-input>\n @if (!anchorReadOnly()) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"model.isStartAndEndDatesEmpty() && !model.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"model.getAnchorTimeString()\"\n (ngModelChange)=\"model.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.resetFixedAnchorTime()\"\n [disabled]=\"!model.isFixedAnchorTimeSetAndNotMidnight() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i2.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: ElderLocalDateInputComponent, selector: "elder-local-date-input", inputs: ["zone", "autoDatePicker", "arrows", "today", "center", "datePickerTouchUi", "allowNull", "datePickerEnabled", "isoValue", "dateValue", "isoDateValue"], outputs: ["blurred", "valueUpdatedBlur", "isoValueChange", "dateValueChange", "isoDateValueChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
209
202
  }
210
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
211
204
  type: Component,
212
205
  args: [{ selector: 'elder-interval-picker', standalone: true, imports: [
213
206
  MatDateRangePicker,
@@ -227,8 +220,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImpor
227
220
  MatTooltip,
228
221
  TranslateModule,
229
222
  MatMenuModule,
230
- ], providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (isSelectLastModeExcludingToday) {\n <button mat-button (click)=\"svc.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"svc.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
231
- }], ctorParameters: () => [{ type: i1.ElderIntervalPickerService }], propDecorators: { calendarStart: [{
223
+ ], providers: [IntervalPickerModel, { provide: DateAdapter, useClass: CustomDateAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"model.editor.smartShift(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ model.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"model.editor.smartShift(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"model.editor.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor()) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (showResultText()) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (model.startDateTimeAsJSDate()) {\n {{ model.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (model.endDateTimeAsJSDate()) {\n {{ model.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ model.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"model.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.emitOnChange()) {\n <button color=\"primary\" mat-raised-button (click)=\"model.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"model.editor.selectCurrentDay()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"model.editor.selectYesterday()\">\n @if (model.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (lastExcludesToday()) {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"model.editor.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"model.editor.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"model.editor.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"model.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"model.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"model.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.startDateHtmlString()\"\n (ngModelChange)=\"model.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.model.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"model.endDateHtmlString()\"\n (ngModelChange)=\"model.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.model.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getStartTimeString()\"\n (ngModelChange)=\"model.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearStartTime()\"\n [disabled]=\"!this.model.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"model.getEndTimeString()\"\n (ngModelChange)=\"model.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.clearEndTime()\"\n [disabled]=\"!this.model.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (showHelpText()) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftDay(-1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftDay(1)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftMonth(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftMonth(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"model.editor.shiftYear(-1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"model.editor.shiftYear(1, true)\" [disabled]=\"model.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode() === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'minutes')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(-1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"model.editor.shiftTime(1, 'hours')\"\n [disabled]=\"model.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (model.startDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!model.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (model.endDate()) {\n <button\n mat-menu-item\n (click)=\"model.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!model.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (model.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.model.resetFixedAnchorPoint()\"\n [disabled]=\"!model.fixedAnchorDate() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"model.setAnchorDateFromForm($event)\"\n [value]=\"model.getAnchorPointAsLocaleDate()\"\n [readonly]=\"anchorReadOnly()\"\n >\n </elder-local-date-input>\n @if (!anchorReadOnly()) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"model.isStartAndEndDatesEmpty() && !model.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode() === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"anchorReadOnly()\"\n [ngModel]=\"model.getAnchorTimeString()\"\n (ngModelChange)=\"model.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.model.resetFixedAnchorTime()\"\n [disabled]=\"!model.isFixedAnchorTimeSetAndNotMidnight() || anchorReadOnly()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
224
+ }], ctorParameters: () => [{ type: i1.IntervalPickerModel }], propDecorators: { calendarStart: [{
232
225
  type: ViewChild,
233
226
  args: ['rangeCalendarStart']
234
227
  }], calendarEnd: [{
@@ -246,21 +239,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImpor
246
239
  }], endDateInput: [{
247
240
  type: ViewChild,
248
241
  args: ['endDateInput']
249
- }], isEmittingOnChange: [{
250
- type: Input
251
- }], intervalInputMode: [{
252
- type: Input
253
- }], showAnchor: [{
254
- type: Input
255
- }], isAnchorReadOnly: [{
256
- type: Input
257
- }], isResultTextVisible: [{
258
- type: Input
259
- }], isHelpTextsVisible: [{
260
- type: Input
261
- }], isSelectLastModeExcludingToday: [{
262
- type: Input
263
242
  }], dateChange: [{
264
243
  type: Output
244
+ }], interval: [{
245
+ type: Input
246
+ }], anchorDateTime: [{
247
+ type: Input
265
248
  }] } });
266
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxNQUFNLEVBRU4sVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUE7QUFDdEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQTtBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDcEQsT0FBTyxFQUNMLFdBQVcsRUFFWCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixrQkFBa0IsR0FDbkIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNyQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhCQUE4QixDQUFBO0FBQ3BGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN0RCxPQUFPLEVBQUUs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LFNBQVM7dUJBQUMsZ0JBQWdCO2dCQUNBLFlBQVk7c0JBQXRDLFNBQVM7dUJBQUMsY0FBYztnQkFFaEIsa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLDhCQUE4QjtzQkFBdEMsS0FBSztnQkFDSSxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJ1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgZWZmZWN0LFxuICBFZmZlY3RSZWYsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgaW5wdXQsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nXG5pbXBvcnQgeyBEYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnXG5pbXBvcnQge1xuICBNYXRDYWxlbmRhcixcbiAgTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbixcbiAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gIE1hdERhdGVSYW5nZVBpY2tlcixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcidcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSwgTWF0SGludCwgTWF0TGFiZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJ1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0J1xuaW1wb3J0IHsgTWF0TWVudU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnXG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCdcbmltcG9ydCB7IExvZ2dlckZhY3RvcnkgfSBmcm9tICdAZWxkZXJieXRlL3RzLWxvZ2dlcidcbmltcG9ydCB7IFRyYW5zbGF0ZU1vZHVsZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnXG5pbXBvcnQgeyBJbnRlcnZhbCB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL2ludGVydmFsJ1xuaW1wb3J0IHsgVGVtcG9yYWxVdGlsIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL3RpbWUvdGVtcG9yYWwtdXRpbCdcbmltcG9ydCB7IEN1c3RvbURhdGVBZGFwdGVyIH0gZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy90aW1lL2RhdGUtYWRhcHRlcnMvY3VzdG9tLWRhdGUtYWRhcHRlcidcbmltcG9ydCB7IEludGVydmFsSW5wdXRNb2RlIH0gZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy90aW1lL2VsZGVyLWludGVydmFsLWlucHV0L2VsZGVyLWludGVydmFsLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEVsZGVyTG9jYWxEYXRlSW5wdXRDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9jb21wb25lbnRzL3RpbWUvZWxkZXItbG9jYWwtZGF0ZS1pbnB1dC9lbGRlci1sb2NhbC1kYXRlLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEVsZGVySW50ZXJ2YWxQaWNrZXJTZXJ2aWNlIH0gZnJvbSAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuc2VydmljZSdcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZWxkZXItaW50ZXJ2YWwtcGlja2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIE1hdERhdGVSYW5nZVBpY2tlcixcbiAgICBNYXREYXRlcGlja2VyTW9kdWxlLFxuICAgIE1hdERhdGVSYW5nZUlucHV0LFxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcbiAgICBNYXRMYWJlbCxcbiAgICBNYXRIaW50LFxuICAgIE1hdERhdGVwaWNrZXJUb2dnbGUsXG4gICAgTWF0SW5wdXRNb2R1bGUsXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIE1hdEljb25Nb2R1bGUsXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgTWF0QnV0dG9uTW9kdWxlLFxuICAgIE1hdENhbGVuZGFyLFxuICAgIEVsZGVyTG9jYWxEYXRlSW5wdXRDb21wb25lbnQsXG4gICAgTWF0VG9vbHRpcCxcbiAgICBUcmFuc2xhdGVNb2R1bGUsXG4gICAgTWF0TWVudU1vZHVsZSxcbiAgXSxcbiAgcHJvdmlkZXJzOiBbRWxkZXJJbnRlcnZhbFBpY2tlclNlcnZpY2UsIHsgcHJvdmlkZTogRGF0ZUFkYXB0ZXIsIHVzZUNsYXNzOiBDdXN0b21EYXRlQWRhcHRlciB9XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2VsZGVyLWludGVydmFsLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50LnNjc3MnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRWxkZXJJbnRlcnZhbFBpY2tlckNvbXBvbmVudCB7XG4gIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiBGaWVsZHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nID0gTG9nZ2VyRmFjdG9yeS5nZXRMb2dnZXIodGhpcy5jb25zdHJ1Y3Rvci5uYW1lKVxuICBwdWJsaWMgcmVhZG9ubHkgY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGbjogTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbjxEYXRlPiA9IChcbiAgICBjZWxsRGF0ZTogRGF0ZSxcbiAgICB2aWV3OiBzdHJpbmdcbiAgKTogc3RyaW5nID0+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuQm9keShjZWxsRGF0ZSwgdmlldylcbiAgfVxuXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJTdGFydCcpIGNhbGVuZGFyU3RhcnQhOiBNYXRDYWxlbmRhcjxEYXRlPlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJykgY2FsZW5kYXJFbmQhOiBNYXRDYWxlbmRhcjxEYXRlPlxuXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJTdGFydCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KSBjYWxlbmRhclN0YXJ0RWxSZWYhOiBFbGVtZW50UmVmXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJFbmQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJFbmRFbFJlZiE6IEVsZW1lbnRSZWZcblxuICBAVmlld0NoaWxkKCdzdGFydERhdGVJbnB1dCcpIHN0YXJ0RGF0ZUlucHV0ITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdlbmREYXRlSW5wdXQnKSBlbmREYXRlSW5wdXQhOiBFbGVtZW50UmVmXG5cbiAgQElucHV0KCkgaXNFbWl0dGluZ09uQ2hhbmdlID0gdHJ1ZVxuICBASW5wdXQoKSBpbnRlcnZhbElucHV0TW9kZTogSW50ZXJ2YWxJbnB1dE1vZGUgPSAnZGF0ZS1yYW5nZSdcbiAgQElucHV0KCkgc2hvd0FuY2hvciA9IGZhbHNlXG4gIEBJbnB1dCgpIGlzQW5jaG9yUmVhZE9ubHkgPSBmYWxzZVxuICBASW5wdXQoKSBpc1Jlc3VsdFRleHRWaXNpYmxlID0gdHJ1ZVxuICBASW5wdXQoKSBpc0hlbHBUZXh0c1Zpc2libGUgPSBmYWxzZVxuICBASW5wdXQoKSBpc1NlbGVjdExhc3RNb2RlRXhjbHVkaW5nVG9kYXkgPSBmYWxzZVxuICBAT3V0cHV0KCkgZGF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8SW50ZXJ2YWw+KClcbiAgaW5wdXRJbnRlcnZhbCA9IGlucHV0PEludGVydmFsPihudWxsKVxuICBpbnB1dEFuY2hvckRhdGVUaW1lID0gaW5wdXQ8RGF0ZT4obnVsbClcblxuICBwcml2YXRlIGNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlcjogKGV2ZW50OiBGb2N1c0V2ZW50KSA9PiB2b2lkXG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIENvbnN0cnVjdG9yICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgY29uc3RydWN0b3IocHVibGljIHN2YzogRWxkZXJJbnRlcnZhbFBpY2tlclNlcnZpY2UpIHtcbiAgICB0aGlzLnN2Yy5zZXR1cElucHV0SW50ZXJ2YWwodGhpcy5pbnB1dEludGVydmFsKVxuICAgIHRoaXMuc3ZjLnNldHVwSW5wdXRBbmNob3JEYXRlVGltZSh0aGlzLmlucHV0QW5jaG9yRGF0ZVRpbWUpXG4gICAgdGhpcy5zdmMuc2V0dXBFdmVudEVtaXR0ZXIodGhpcy5kYXRlQ2hhbmdlKVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIExpZmUgQ3ljbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW5wdXRJbnRlcnZhbCkge1xuICAgICAgdGhpcy5zdmMucHVsbElucHV0SW50ZXJ2YWwoKVxuICAgIH1cbiAgICBpZiAodGhpcy5pbnB1dEFuY2hvckRhdGVUaW1lKCkpIHtcbiAgICAgIHRoaXMuc3ZjLnB1bGxJbnB1dEFuY2hvckRhdGVUaW1lKClcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuaXNFbWl0dGluZ09uQ2hhbmdlLnNldCh0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSlcbiAgICB0aGlzLnNldHVwRGF0ZUlucHV0Q2FsZW5kYXJGb2N1c1ByZXZlbnRpb24oKVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVycygpXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogUHVibGljIEFQSSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBzZXR1cERhdGVJbnB1dENhbGVuZGFyRm9jdXNQcmV2ZW50aW9uKCk6IHZvaWQge1xuICAgIC8vIFByZXZlbnRzIHRoZSBmb2N1cyBvbiB0aGUgY2FsZW5kYXIgd2hlbiB0aGUgaW5wdXQgZmllbGQgaXMgY2hhbmdlZCB2aWEgdGhlIGtleWJvYXJkXG4gICAgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIgPSAoZXZlbnQ6IEZvY3VzRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LnJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICBjb25zdCByZWxUYXJnZXQgPSBldmVudC5yZWxhdGVkVGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnRcblxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnc3RhcnREYXRlSW5wdXQnKSB7XG4gICAgICAgIHRoaXMuc3RhcnREYXRlSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnZW5kRGF0ZUlucHV0Jykge1xuICAgICAgICB0aGlzLmVuZERhdGVJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgY2xlYXJTdGFydERhdGVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNsZWFyU3RhcnREYXRlVGltZSgpXG5cbiAgICB0aGlzLnN2Yy5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgIHRoaXMuc3ZjLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIGNsZWFyRW5kRGF0ZVRpbWUoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuY2xlYXJFbmREYXRlVGltZSgpXG5cbiAgICB0aGlzLnN2Yy5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgIHRoaXMuc3ZjLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIGNsZWFyU3RhcnRBbmRFbmREYXRlVGltZXMoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuY2xlYXJTdGFydERhdGVUaW1lKClcbiAgICB0aGlzLnN2Yy5jbGVhckVuZERhdGVUaW1lKClcblxuICAgIHRoaXMuc3ZjLnJlc2V0Q2FsZW5kYXJNb2RlKClcblxuICAgIGlmICh0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSkge1xuICAgICAgdGhpcy5zdmMuZW1pdE1haW5EYXRlcygpXG4gICAgfVxuICB9XG5cbiAgaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZShjaGFuZ2VkRGF0ZTogRGF0ZSk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNhbGVuZGFyTW9kZS5zZXQoJ2RheXMnKVxuICAgIGNvbnN0IG5ld1BsYWluRGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRQbGFpbkRhdGVGcm9tSlNEYXRlKGNoYW5nZWREYXRlKVxuICAgIHRoaXMuc3ZjLnN0YXJ0RGF0ZS5zZXQobmV3UGxhaW5EYXRlKVxuICB9XG5cbiAgaGFuZGxlRW5kQ2FsZW5kYXJDaGFuZ2UoY2hhbmdlZERhdGU6IERhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnN2Yy5jYWxlbmRhck1vZGUuc2V0KCdkYXlzJylcbiAgICBjb25zdCBuZXdQbGFpbkRhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0UGxhaW5EYXRlRnJvbUpTRGF0ZShjaGFuZ2VkRGF0ZSlcbiAgICB0aGlzLnN2Yy5lbmREYXRlLnNldChuZXdQbGFpbkRhdGUpXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogUHJpdmF0ZSBtZXRob2RzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlbW92ZUV2ZW50TGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYgfHwgIXRoaXMuY2FsZW5kYXJFbmRFbFJlZikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNhbGVuZGFyU3RhcnRFbFJlZi5uYXRpdmVFbGVtZW50IHx8ICF0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgcHJpdmF0ZSBjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuQm9keShjZWxsRGF0ZTogRGF0ZSwgdmlldzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBhbmNob3JEYXRlID0gdGhpcy5zdmMuZml4ZWRBbmNob3JEYXRlKClcblxuICAgIGlmICghYW5jaG9yRGF0ZSkge1xuICAgICAgcmV0dXJuICcnXG4gICAgfVxuXG4gICAgY29uc3QgZGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRKU0RhdGVGcm9tUGxhaW5EYXRlVGltZShhbmNob3JEYXRlKVxuXG4gICAgaWYgKCFkYXRlKSB7XG4gICAgICByZXR1cm4gJydcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBjZWxsRGF0ZS5nZXREYXRlKCkgPT09IGRhdGUuZ2V0RGF0ZSgpICYmXG4gICAgICBjZWxsRGF0ZS5nZXRNb250aCgpID09PSBkYXRlLmdldE1vbnRoKCkgJiZcbiAgICAgIGNlbGxEYXRlLmdldEZ1bGxZZWFyKCkgPT09IGRhdGUuZ2V0RnVsbFllYXIoKVxuICAgICkge1xuICAgICAgcmV0dXJuICdlbGRlci1jdXN0b20tYW5jaG9yLWRhdGUnXG4gICAgfVxuXG4gICAgcmV0dXJuICcnXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogRWZmZWN0cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlYWRvbmx5IF91cGRhdGVNYXRDYWxlbmRhckVsQW5jaG9yQ3NzQ2xhc3NFZmZlY3Q6IEVmZmVjdFJlZiA9IGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgY29uc3QgYW5jaG9yRGF0ZSA9IHRoaXMuc3ZjLmFuY2hvckRhdGUoKVxuXG4gICAgaWYgKGFuY2hvckRhdGUpIHtcbiAgICAgIHRoaXMuY2FsZW5kYXJTdGFydC51cGRhdGVUb2RheXNEYXRlKClcbiAgICAgIHRoaXMuY2FsZW5kYXJFbmQudXBkYXRlVG9kYXlzRGF0ZSgpXG4gICAgfVxuICB9KVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3VwZGF0ZU1hdENhbGVuZGFyRWxTZWxlY3Rpb25FZmZlY3Q6IEVmZmVjdFJlZiA9IGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5zdmMuc3RhcnREYXRlKClcbiAgICBjb25zdCBlbmREYXRlID0gdGhpcy5zdmMuZW5kRGF0ZSgpXG5cbiAgICBpZiAoIXRoaXMuY2FsZW5kYXJTdGFydCB8fCAhdGhpcy5jYWxlbmRhckVuZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCFzdGFydERhdGUgJiYgIWVuZERhdGUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGNhbGVuZGFyMSA9IHRoaXMuY2FsZW5kYXJTdGFydFxuICAgIGNvbnN0IGNhbGVuZGFyMiA9IHRoaXMuY2FsZW5kYXJFbmRcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gdGltZW91dCBpcyBuZWVkZWQgdG8gcnVuIHJ1biBjYWxlbmRhciB1cGRhdGUgbGFzdCwgb3RoZXJ3aXNlIHRoZXJlIGFyZSBpc3N1ZXNcbiAgICAgIGlmIChzdGFydERhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRKc0RhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0SlNEYXRlRnJvbVBsYWluRGF0ZVRpbWUoc3RhcnREYXRlKVxuICAgICAgICBjYWxlbmRhcjEuYWN0aXZlRGF0ZSA9IHN0YXJ0SnNEYXRlXG4gICAgICB9XG5cbiAgICAgIGlmIChlbmREYXRlKSB7XG4gICAgICAgIGNvbnN0IGVuZEpzRGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRKU0RhdGVGcm9tUGxhaW5EYXRlVGltZShlbmREYXRlKVxuICAgICAgICBjYWxlbmRhcjIuYWN0aXZlRGF0ZSA9IGVuZEpzRGF0ZVxuICAgICAgfVxuICAgIH0sIDApXG4gIH0pXG59XG4iLCI8ZGl2IGNsYXNzPVwiaW50ZXJ2YWwtcGlja2VyLWNvbXBvbmVudCBwLW1kIGxheW91dC1jb2wgZ2FwLXh4bFwiPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBnYXAteHhsIHBsYWNlLWJldHdlZW4tc3RhcnRcIiBzdHlsZT1cImdhcDogNSVcIj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAtbWQgcHQteHNcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJpbnRlcnZhbFNlbGVjdG9yXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2xcIj5cbiAgICAgIDwhLS0gc21hcnQgc2hpZnQgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc21hcnRTaGlmdCgtMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8c3Bhbj57eyBzdmMudmlld0ludGVydmFsTWVzc2FnZSgpIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNtYXJ0U2hpZnQoMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPCEtLSBjYWxlbmRhcnMgYW5kIGlucHV0IGNvbnRyb2xzIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNhbGVuZGFyc1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInB0LXhzXCIgc3R5bGU9XCJ3aWR0aDogMjUlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAtbGdcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgZ2FwLXhzIHBsYWNlLXN0YXJ0LXN0YXJ0XCI+XG4gICAgICAgICAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICAgICAgICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zZWxlY3RTbWFydEludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgICAgICAgfVxuICAgICAgICAgIDwhLS0gc2VsZWN0IGN1cnJlbnQgLS0+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudFdlZWsoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2Qud2VlaycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RDdXJyZW50TW9udGgoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QubW9udGgnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudFF1YXJ0ZXIoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QucXVhcnRlcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RDdXJyZW50WWVhcigpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuY3VycmVudFBlcmlvZC55ZWFyJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZpeGVkLXNoaWZ0cy1jb250YWluZXJcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZml4ZWRTaGlmdHNcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyIGdhcC14eGwgcHQtc21cIj5cbiAgICA8ZGl2PlxuICAgICAgQGlmIChzaG93QW5jaG9yKSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhbmNob3JJbnB1dEZpZWxkXCI+PC9uZy1jb250YWluZXI+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgQGlmIChpc1Jlc3VsdFRleHRWaXNpYmxlKSB7XG4gICAgICA8IS0tIHJlc3VsdCBpbnRlcnZhbCAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIHBsYWNlLWNlbnRlci1jZW50ZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtaW50ZXJ2YWwgbWF0LWNhcHRpb24gcHQteHNcIj5cbiAgICAgICAgICBAaWYgKHN2Yy5zdGFydERhdGVUaW1lQXNKU0RhdGUoKSkge1xuICAgICAgICAgICAge3sgc3ZjLnN0YXJ0RGF0ZVRpbWVBc0pTRGF0ZSgpIHwgZGF0ZTogJ2RkLk1NLiB5LCBISDptbTpzcycgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICAgIDxzcGFuPiAtIDwvc3Bhbj5cbiAgICAgICAgICBAaWYgKHN2Yy5lbmREYXRlVGltZUFzSlNEYXRlKCkpIHtcbiAgICAgICAgICAgIHt7IHN2Yy5lbmREYXRlVGltZUFzSlNEYXRlKCkgfCBkYXRlOiAnZGQuTU0uIHksIEhIOm1tOnNzJyB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdC1jYXB0aW9uXCI+e3sgc3ZjLmRlbHRhSHVtYW5SZWFkYWJsZSgpIHx8ICcmbmJzcDsnIH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBnYXAtbGdcIj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cbiAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgKGNsaWNrKT1cImNsZWFyU3RhcnRBbmRFbmREYXRlVGltZXMoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNTdGFydEFuZEVuZERhdGVzRW1wdHkoKVwiXG4gICAgICA+XG4gICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jbGVhcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICBAaWYgKCF0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSkge1xuICAgICAgICA8YnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJzdmMuZW1pdE1haW5EYXRlcygpXCI+XG4gICAgICAgICAge3sgJ2FjdGlvbnMub2snIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI2ludGVydmFsU2VsZWN0b3I+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sXCI+XG4gICAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zZWxlY3RBYnNvbHV0ZUludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgfVxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHNlbGVjdC1idXR0b25zLWNvbnRhaW5lciBnYXAtc21cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC14cyBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdEN1cnJlbnREYXkoKVwiPlxuICAgICAgICAgIEBpZiAoc3ZjLmlzRml4ZWRBbmNob3JEYXRlU2V0KCkpIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JEYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIudG9kYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0WWVzdGVyZGF5KClcIj5cbiAgICAgICAgICBAaWYgKHN2Yy5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpKSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMSB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLnllc3RlcmRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICBAaWYgKGlzU2VsZWN0TGFzdE1vZGVFeGNsdWRpbmdUb2RheSkge1xuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RTZXZlbkRheXNFeGNsdWRpbmdUb2RheSgpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gNyB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5cycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0VGhpcnR5RGF5c0V4Y2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSAzMCB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5cycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdFNldmVuRGF5c0luY2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSA3IHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RUaGlydHlEYXlzSW5jbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDMwIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInB0LXNtXCI+PC9kaXY+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdEZpdmVNaW51dGVzKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSA1IHt7ICdpbnRlcnZhbFBpY2tlci5taW51dGVzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RIb3VyKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSB7eyAnaW50ZXJ2YWxQaWNrZXIuaG91cicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0MjRIb3VycygpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMjQge3sgJ2ludGVydmFsUGlja2VyLmhvdXJzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2NhbGVuZGFyc1RlbXBsYXRlPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCIgc3R5bGU9XCJhbGlnbi1pdGVtczogZmxleC1zdGFydDsgbWluLWhlaWdodDogMjgwcHhcIj5cbiAgICA8bWF0LWNhbGVuZGFyXG4gICAgICAjcmFuZ2VDYWxlbmRhclN0YXJ0XG4gICAgICBzdHlsZT1cIndpZHRoOiAyMTBweDsgbWF4LXdpZHRoOiAxMDAlXCJcbiAgICAgIFtzZWxlY3RlZF09XCJzdmMuZGF0ZVJhbmdlRm9yQ2FsZW5kYXIoKVwiXG4gICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwiaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIFttYXhEYXRlXT1cInN2Yy5lbmREYXRlQXNKU0RhdGUoKVwiXG4gICAgICBbZGF0ZUNsYXNzXT1cImNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm5cIlxuICAgID5cbiAgICA8L21hdC1jYWxlbmRhcj5cbiAgICA8bWF0LWNhbGVuZGFyXG4gICAgICAjcmFuZ2VDYWxlbmRhckVuZFxuICAgICAgc3R5bGU9XCJ3aWR0aDogMjEwcHg7IG1heC13aWR0aDogMTAwJVwiXG4gICAgICBbc2VsZWN0ZWRdPVwic3ZjLmRhdGVSYW5nZUZvckNhbGVuZGFyKClcIlxuICAgICAgKHNlbGVjdGVkQ2hhbmdlKT1cImhhbmRsZUVuZENhbGVuZGFyQ2hhbmdlKCRldmVudClcIlxuICAgICAgW21pbkRhdGVdPVwic3ZjLnN0YXJ0RGF0ZUFzSlNEYXRlKClcIlxuICAgICAgW2RhdGVDbGFzc109XCJjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuXCJcbiAgICA+XG4gICAgPC9tYXQtY2FsZW5kYXI+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICAjc3RhcnREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwic3RhcnREYXRlSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5zdGFydERhdGVIdG1sU3RyaW5nKClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN2Yy5zZXRTdGFydERhdGVGcm9tSHRtbFN0cmluZygkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLmNsZWFyU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMuc3ZjLnN0YXJ0RGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgICNlbmREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwiZW5kRGF0ZUlucHV0XCJcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIHR5cGU9XCJkYXRlXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJzdmMuZW5kRGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldEVuZERhdGVGcm9tSHRtbFN0cmluZygkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLmNsZWFyRW5kRGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5lbmREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGJyIC8+XG4gIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYXJvdW5kLWNlbnRlciBnYXAteGwgcHQtc21cIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBuYW1lPVwic3RhcnRUaW1lSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cInRpbWVcIlxuICAgICAgICAgICNzdGFydFRpbWVDb250cm9sPVwibmdNb2RlbFwiXG4gICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5nZXRTdGFydFRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldFN0YXJ0VGltZUZyb21TdHJpbmcoJGV2ZW50LCBzdGFydFRpbWVDb250cm9sKVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5zdmMuY2xlYXJTdGFydFRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5pc1N0YXJ0VGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5lbmRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBuYW1lPVwiZW5kVGltZUlucHV0XCJcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAjZW5kVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwic3ZjLmdldEVuZFRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldEVuZFRpbWVGcm9tU3RyaW5nKCRldmVudCwgZW5kVGltZUNvbnRyb2wpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5jbGVhckVuZFRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5pc0VuZFRpbWVTZXRBbmROb3RNaWRuaWdodCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgfVxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNmaXhlZFNoaWZ0cz5cbiAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICA8aDUgY2xhc3M9XCJtYXQtaDVcIj57eyAnaW50ZXJ2YWxQaWNrZXIuc2hpZnRJbnRlcnZhbCcgfCB0cmFuc2xhdGUgfX08L2g1PlxuICB9XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIHBsYWNlLXN0YXJ0LXN0cmV0Y2hcIj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdERheSgtMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuZGF5JyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnREYXkoMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNoaWZ0TW9udGgoLTEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLm1vbnRoJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRNb250aCgxLCB0cnVlKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRZZWFyKC0xLCB0cnVlKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci55ZWFyJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRZZWFyKDEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cblxuICAgIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICA8IS0tIHNoaWZ0IG1pbnV0ZSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwic3ZjLnNoaWZ0VGltZSgtMSwgJ21pbnV0ZXMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5taW51dGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoMSwgJ21pbnV0ZXMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIHNoaWZ0IGhvdXIgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoLTEsICdob3VycycpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmhvdXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoMSwgJ2hvdXJzJylcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2FuY2hvcklucHV0RmllbGQ+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IGZsZXgtbm9uZSBnYXAtbWRcIj5cbiAgICA8bWF0LW1lbnUgI2FuY2hvck1lbnU9XCJtYXRNZW51XCI+XG4gICAgICBAaWYgKHN2Yy5zdGFydERhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJzdmMuc2V0Rml4ZWRBbmNob3JQb2ludFRvRW5kRGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuZW5kRGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5sb2dpbjwvbWF0LWljb24+XG4gICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIEBpZiAoc3ZjLmVuZERhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJzdmMuc2V0Rml4ZWRBbmNob3JQb2ludFRvU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXN2Yy5zdGFydERhdGUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkXCI+bG9nb3V0PC9tYXQtaWNvbj5cbiAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgICBAaWYgKHN2Yy5maXhlZEFuY2hvckRhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5yZXNldEZpeGVkQW5jaG9yUG9pbnQoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuZml4ZWRBbmNob3JEYXRlKCkgfHwgaXNBbmNob3JSZWFkT25seVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5jbGVhcicgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvbWF0LW1lbnU+XG5cbiAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JEYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgPGVsZGVyLWxvY2FsLWRhdGUtaW5wdXRcbiAgICAgICAgbmFtZT1cImFuY2hvckRhdGVJbnB1dFwiXG4gICAgICAgICh2YWx1ZVVwZGF0ZWQpPVwic3ZjLnNldEFuY2hvckRhdGVGcm9tRm9ybSgkZXZlbnQpXCJcbiAgICAgICAgW3ZhbHVlXT1cInN2Yy5nZXRBbmNob3JQb2ludEFzTG9jYWxlRGF0ZSgpXCJcbiAgICAgICAgW3JlYWRvbmx5XT1cImlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgPlxuICAgICAgPC9lbGRlci1sb2NhbC1kYXRlLWlucHV0PlxuICAgICAgQGlmICghaXNBbmNob3JSZWFkT25seSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImFuY2hvck1lbnVcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNTdGFydEFuZEVuZERhdGVzRW1wdHkoKSAmJiAhc3ZjLmZpeGVkQW5jaG9yRGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5tb3JlX2hvcml6PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlID09PSAnZGF0ZS10aW1lLXJhbmdlJykge1xuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXItc2hvcnRcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIG5hbWU9XCJhbmNob3JUaW1lSW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAjYW5jaG9yVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW3JlYWRvbmx5XT1cImlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5nZXRBbmNob3JUaW1lU3RyaW5nKClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN2Yy5zZXRBbmNob3JUaW1lRnJvbUZvcm0oJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5zdmMucmVzZXRGaXhlZEFuY2hvclRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuaXNGaXhlZEFuY2hvclRpbWVTZXRBbmROb3RNaWRuaWdodCgpIHx8IGlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIH1cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19
249
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBRUwsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsTUFBTSxFQUNOLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUNMLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFBO0FBQ3RCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDMUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBQ3BELE9BQU8sRUFDTCxXQUFXLEVBRVgsbUJBQW1CLEVBQ25CLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsa0JBQWtCLEdBQ25CLE1BQU0sOEJBQThCLENBQUE7QUFDckMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTtBQUNwRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFBO0FBQ3hELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFDdEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ3BELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUVyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0NBQW9DLENBQUE7QUFDakUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0NBQXNDLENBQUE7QUFFeEUsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNERBQTRELENBQUE7QUFDekcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sK0JBQStCLENBQUE7Ozs7Ozs7Ozs7OztBQThCbkUsTUFBTSxPQUFPLDRCQUE0QjtJQThCdkMsSUFDVyxRQUFRLENBQUMsS0FBZTtRQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUMvQixDQUFDO0lBRUQsSUFDVyxjQUFjLENBQUMsS0FBVztRQUNuQyxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ3JDLENBQUM7SUFFRDs7OztnRkFJNEU7SUFFNUUsWUFBbUIsS0FBMEI7UUFBMUIsVUFBSyxHQUFMLEtBQUssQ0FBcUI7UUE3QzdDOzs7O29GQUk0RTtRQUUzRCxRQUFHLEdBQUcsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBV3JELGlCQUFZLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ3JFLHNCQUFpQixHQUFHLEtBQUssQ0FBb0IsWUFBWSxDQUFDLENBQUE7UUFDMUQsZUFBVSxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUNwRSxtQkFBYyxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUN4RSxtQkFBYyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUN2RSxpQkFBWSxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUN0RSxzQkFBaUIsR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFakYsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFZLENBQUE7UUFxSm5DLGlDQUE0QixHQUF1QyxDQUNqRixRQUFjLEVBQ2QsSUFBWSxFQUNKLEVBQUU7WUFDVixPQUFPLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDOUQsQ0FBQyxDQUFBO1FBcklDLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBRTdDLE1BQU0sQ0FBQyxHQUFTLEVBQUU7WUFDaEIsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7Z0JBQzVCLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFBO1lBQ25DLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQTtRQUVGLE1BQU0sQ0FBQyxHQUFTLEVBQUU7WUFDaEIsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBQ2hGLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7O2dGQUk0RTtJQUVyRSxlQUFlO1FBQ3BCLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFBO1FBQ3RELElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxDQUFBO1FBQzVDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFBO1FBQzdCLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNQLENBQUM7SUFFTSxXQUFXO1FBQ2hCLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFBO0lBQzdCLENBQUM7SUFFRDs7OztnRkFJNEU7SUFFckUscUNBQXFDO1FBQzFDLHNGQUFzRjtRQUN0RixJQUFJLENBQUMsMkJBQTJCLEdBQUcsQ0FBQyxLQUFpQixFQUFRLEVBQUU7WUFDN0QsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDbkMsT0FBTTtZQUNSLENBQUM7WUFDRCxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUE7WUFDdEIsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLGFBQWlDLENBQUE7WUFFekQsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFBO2dCQUN6QyxPQUFNO1lBQ1IsQ0FBQztZQUNELElBQUksU0FBUyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUE7Z0JBQ3ZDLE9BQU07WUFDUixDQUFDO1FBQ0gsQ0FBQyxDQUFBO1FBRUQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBNEIsQ0FBQTtRQUMvRSxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUE0QixDQUFBO1FBRTNFLGtCQUFrQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDcEYsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUNwRixDQUFDO0lBRU0sa0JBQWtCO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQTtRQUUvQixJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUE7UUFFOUIsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQzVCLENBQUM7SUFDSCxDQUFDO0lBRU0sZ0JBQWdCO1FBQ3JCLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtRQUU3QixJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUE7UUFFOUIsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQzVCLENBQUM7SUFDSCxDQUFDO0lBRU0seUJBQXlCO1FBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQTtRQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLENBQUE7UUFFN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1FBRTlCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUVNLHlCQUF5QixDQUFDLFdBQWlCO1FBQ2hELElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsc0JBQXNCLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDckUsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDdkMsQ0FBQztJQUVNLHVCQUF1QixDQUFDLFdBQWlCO1FBQzlDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsc0JBQXNCLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDckUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDckMsQ0FBQztJQUVEOzs7O2dGQUk0RTtJQUVwRSxvQkFBb0I7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3ZELE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkYsT0FBTTtRQUNSLENBQUM7UUFFRCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUE0QixDQUFBO1FBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQTRCLENBQUE7UUFFM0Usa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUN2RixnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLDJCQUEyQixFQUFFLElBQUksQ0FBQyxDQUFBO0lBQ3ZGLENBQUM7SUFTTyxnQ0FBZ0MsQ0FBQyxRQUFjLEVBQUUsSUFBWTtRQUNuRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFBO1FBRS9DLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixPQUFPLEVBQUUsQ0FBQTtRQUNYLENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUMsVUFBVSxDQUFDLENBQUE7UUFFaEUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsT0FBTyxFQUFFLENBQUE7UUFDWCxDQUFDO1FBRUQsSUFDRSxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNyQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUN2QyxRQUFRLENBQUMsV0FBVyxFQUFFLEtBQUssSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUM3QyxDQUFDO1lBQ0QsT0FBTywwQkFBMEIsQ0FBQTtRQUNuQyxDQUFDO1FBRUQsT0FBTyxFQUFFLENBQUE7SUFDWCxDQUFDO0lBRU8sMkJBQTJCLENBQUMsU0FBNkIsRUFBRSxPQUEyQjtRQUM1RixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUM3QyxPQUFNO1FBQ1IsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMzQixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUE7UUFDeEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTtRQUVwQyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsNEVBQTRFO1lBQzVFLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsYUFBYSxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUMsU0FBUyxDQUFDLENBQUE7WUFDL0UsQ0FBQztZQUVELElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1osV0FBVyxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDM0UsQ0FBQztRQUNILENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUNQLENBQUM7SUFFTywwQkFBMEI7UUFDaEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1FBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtJQUNyQyxDQUFDOzhHQXpPVSw0QkFBNEI7a0dBQTVCLDRCQUE0Qiw0NENBTDVCLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLHVVQWlCOUMsVUFBVSwrR0FDWixVQUFVLCtOQ2pGbkQsdTFmQTBaQSxtaUJENVdJLG1CQUFtQiwwYkFFbkIsa0JBQWtCLDJhQUlsQixjQUFjLDBXQUNkLFlBQVksd1BBQ1osYUFBYSxtTEFDYixXQUFXLDhtQkFDWCxlQUFlLHlVQUVmLDRCQUE0Qix3VUFFNUIsZUFBZSwyRkFDZixhQUFhOzsyRkFPSiw0QkFBNEI7a0JBM0J4QyxTQUFTOytCQUNFLHVCQUF1QixjQUNyQixJQUFJLFdBQ1A7d0JBQ1Asa0JBQWtCO3dCQUNsQixtQkFBbUI7d0JBQ25CLGlCQUFpQjt3QkFDakIsa0JBQWtCO3dCQUNsQixRQUFRO3dCQUNSLE9BQU87d0JBQ1AsbUJBQW1CO3dCQUNuQixjQUFjO3dCQUNkLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixXQUFXO3dCQUNYLGVBQWU7d0JBQ2YsV0FBVzt3QkFDWCw0QkFBNEI7d0JBQzVCLFVBQVU7d0JBQ1YsZUFBZTt3QkFDZixhQUFhO3FCQUNkLGFBQ1UsQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLENBQUMsbUJBR3RFLHVCQUF1QixDQUFDLE1BQU07d0ZBV2QsYUFBYTtzQkFBN0MsU0FBUzt1QkFBQyxvQkFBb0I7Z0JBQ0EsV0FBVztzQkFBekMsU0FBUzt1QkFBQyxrQkFBa0I7Z0JBRTBCLGtCQUFrQjtzQkFBeEUsU0FBUzt1QkFBQyxvQkFBb0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBQ0EsZ0JBQWdCO3NCQUFwRSxTQUFTO3VCQUFDLGtCQUFrQixFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRTtnQkFFdEIsY0FBYztzQkFBMUMsU0FBUzt1QkFBQyxnQkFBZ0I7Z0JBQ0EsWUFBWTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjO2dCQVVmLFVBQVU7c0JBQW5CLE1BQU07Z0JBS0ksUUFBUTtzQkFEbEIsS0FBSztnQkFNSyxjQUFjO3NCQUR4QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJ1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgYm9vbGVhbkF0dHJpYnV0ZSxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgZWZmZWN0LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBpbnB1dCxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nXG5pbXBvcnQgeyBEYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnXG5pbXBvcnQge1xuICBNYXRDYWxlbmRhcixcbiAgTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbixcbiAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gIE1hdERhdGVSYW5nZVBpY2tlcixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcidcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSwgTWF0SGludCwgTWF0TGFiZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJ1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0J1xuaW1wb3J0IHsgTWF0TWVudU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnXG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCdcbmltcG9ydCB7IExvZ2dlckZhY3RvcnkgfSBmcm9tICdAZWxkZXJieXRlL3RzLWxvZ2dlcidcbmltcG9ydCB7IFRyYW5zbGF0ZU1vZHVsZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnXG5pbXBvcnQgeyBJbnRlcnZhbCB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL2ludGVydmFsJ1xuaW1wb3J0IHsgVGVtcG9yYWxVdGlsIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL3RpbWUvdGVtcG9yYWwtdXRpbCdcbmltcG9ydCB7IEN1c3RvbURhdGVBZGFwdGVyIH0gZnJvbSAnLi4vZGF0ZS1hZGFwdGVycy9jdXN0b20tZGF0ZS1hZGFwdGVyJ1xuaW1wb3J0IHsgSW50ZXJ2YWxJbnB1dE1vZGUgfSBmcm9tICcuLi9lbGRlci1pbnRlcnZhbC1pbnB1dC9lbGRlci1pbnRlcnZhbC1pbnB1dC5jb21wb25lbnQnXG5pbXBvcnQgeyBFbGRlckxvY2FsRGF0ZUlucHV0Q29tcG9uZW50IH0gZnJvbSAnLi4vZWxkZXItbG9jYWwtZGF0ZS1pbnB1dC9lbGRlci1sb2NhbC1kYXRlLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEludGVydmFsUGlja2VyTW9kZWwgfSBmcm9tICcuL21vZGVsL2ludGVydmFsLXBpY2tlci1tb2RlbCdcbmltcG9ydCB7IFRlbXBvcmFsIH0gZnJvbSAnQGpzLXRlbXBvcmFsL3BvbHlmaWxsJ1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdlbGRlci1pbnRlcnZhbC1waWNrZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgTWF0RGF0ZVJhbmdlUGlja2VyLFxuICAgIE1hdERhdGVwaWNrZXJNb2R1bGUsXG4gICAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgICBNYXRJbnB1dE1vZHVsZSxcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgTWF0SWNvbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FsZW5kYXIsXG4gICAgRWxkZXJMb2NhbERhdGVJbnB1dENvbXBvbmVudCxcbiAgICBNYXRUb29sdGlwLFxuICAgIFRyYW5zbGF0ZU1vZHVsZSxcbiAgICBNYXRNZW51TW9kdWxlLFxuICBdLFxuICBwcm92aWRlcnM6IFtJbnRlcnZhbFBpY2tlck1vZGVsLCB7IHByb3ZpZGU6IERhdGVBZGFwdGVyLCB1c2VDbGFzczogQ3VzdG9tRGF0ZUFkYXB0ZXIgfV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5zY3NzJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIEVsZGVySW50ZXJ2YWxQaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogRmllbGRzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKHRoaXMuY29uc3RydWN0b3IubmFtZSlcblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnKSBjYWxlbmRhclN0YXJ0ITogTWF0Q2FsZW5kYXI8RGF0ZT5cbiAgQFZpZXdDaGlsZCgncmFuZ2VDYWxlbmRhckVuZCcpIGNhbGVuZGFyRW5kITogTWF0Q2FsZW5kYXI8RGF0ZT5cblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJTdGFydEVsUmVmITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJywgeyByZWFkOiBFbGVtZW50UmVmIH0pIGNhbGVuZGFyRW5kRWxSZWYhOiBFbGVtZW50UmVmXG5cbiAgQFZpZXdDaGlsZCgnc3RhcnREYXRlSW5wdXQnKSBzdGFydERhdGVJbnB1dCE6IEVsZW1lbnRSZWZcbiAgQFZpZXdDaGlsZCgnZW5kRGF0ZUlucHV0JykgZW5kRGF0ZUlucHV0ITogRWxlbWVudFJlZlxuXG4gIHB1YmxpYyByZWFkb25seSBlbWl0T25DaGFuZ2UgPSBpbnB1dCh0cnVlLCB7IHRyYW5zZm9ybTogKHYpID0+IGJvb2xlYW5BdHRyaWJ1dGUodikgfSlcbiAgcHVibGljIHJlYWRvbmx5IGludGVydmFsSW5wdXRNb2RlID0gaW5wdXQ8SW50ZXJ2YWxJbnB1dE1vZGU+KCdkYXRlLXJhbmdlJylcbiAgcHVibGljIHJlYWRvbmx5IHNob3dBbmNob3IgPSBpbnB1dChmYWxzZSwgeyB0cmFuc2Zvcm06ICh2KSA9PiBib29sZWFuQXR0cmlidXRlKHYpIH0pXG4gIHB1YmxpYyByZWFkb25seSBhbmNob3JSZWFkT25seSA9IGlucHV0KGZhbHNlLCB7IHRyYW5zZm9ybTogKHYpID0+IGJvb2xlYW5BdHRyaWJ1dGUodikgfSlcbiAgcHVibGljIHJlYWRvbmx5IHNob3dSZXN1bHRUZXh0ID0gaW5wdXQodHJ1ZSwgeyB0cmFuc2Zvcm06ICh2KSA9PiBib29sZWFuQXR0cmlidXRlKHYpIH0pXG4gIHB1YmxpYyByZWFkb25seSBzaG93SGVscFRleHQgPSBpbnB1dChmYWxzZSwgeyB0cmFuc2Zvcm06ICh2KSA9PiBib29sZWFuQXR0cmlidXRlKHYpIH0pXG4gIHB1YmxpYyByZWFkb25seSBsYXN0RXhjbHVkZXNUb2RheSA9IGlucHV0KGZhbHNlLCB7IHRyYW5zZm9ybTogKHYpID0+IGJvb2xlYW5BdHRyaWJ1dGUodikgfSlcblxuICBAT3V0cHV0KCkgZGF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8SW50ZXJ2YWw+KClcblxuICBwcml2YXRlIGNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlcjogKGV2ZW50OiBGb2N1c0V2ZW50KSA9PiB2b2lkXG5cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBpbnRlcnZhbCh2YWx1ZTogSW50ZXJ2YWwpIHtcbiAgICB0aGlzLm1vZGVsLnNldEludGVydmFsKHZhbHVlKVxuICB9XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBhbmNob3JEYXRlVGltZSh2YWx1ZTogRGF0ZSkge1xuICAgIHRoaXMubW9kZWwuc2V0QW5jaG9yRGF0ZVRpbWUodmFsdWUpXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogQ29uc3RydWN0b3IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgbW9kZWw6IEludGVydmFsUGlja2VyTW9kZWwpIHtcbiAgICB0aGlzLm1vZGVsLnNldHVwRXZlbnRFbWl0dGVyKHRoaXMuZGF0ZUNoYW5nZSlcblxuICAgIGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgICBpZiAodGhpcy5tb2RlbC5hbmNob3JEYXRlKCkpIHtcbiAgICAgICAgdGhpcy51cGRhdGVNYXRDYWxlbmRhclRvZGF5RGF0ZSgpXG4gICAgICB9XG4gICAgfSlcblxuICAgIGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgICB0aGlzLnVwZGF0ZU1hdENhbGVuZGFyQWN0aXZlRGF0ZSh0aGlzLm1vZGVsLnN0YXJ0RGF0ZSgpLCB0aGlzLm1vZGVsLmVuZERhdGUoKSlcbiAgICB9KVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIExpZmUgQ3ljbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGVsLmlzRW1pdHRpbmdPbkNoYW5nZS5zZXQodGhpcy5lbWl0T25DaGFuZ2UoKSlcbiAgICB0aGlzLnNldHVwRGF0ZUlucHV0Q2FsZW5kYXJGb2N1c1ByZXZlbnRpb24oKVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5tb2RlbC5zZXRJbml0aWFsaXplZCgpXG4gICAgfSwgMClcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXJzKClcbiAgfVxuXG4gIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiBQdWJsaWMgQVBJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gIHB1YmxpYyBzZXR1cERhdGVJbnB1dENhbGVuZGFyRm9jdXNQcmV2ZW50aW9uKCk6IHZvaWQge1xuICAgIC8vIFByZXZlbnRzIHRoZSBmb2N1cyBvbiB0aGUgY2FsZW5kYXIgd2hlbiB0aGUgaW5wdXQgZmllbGQgaXMgY2hhbmdlZCB2aWEgdGhlIGtleWJvYXJkXG4gICAgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIgPSAoZXZlbnQ6IEZvY3VzRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LnJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICBjb25zdCByZWxUYXJnZXQgPSBldmVudC5yZWxhdGVkVGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnRcblxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnc3RhcnREYXRlSW5wdXQnKSB7XG4gICAgICAgIHRoaXMuc3RhcnREYXRlSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnZW5kRGF0ZUlucHV0Jykge1xuICAgICAgICB0aGlzLmVuZERhdGVJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgcHVibGljIGNsZWFyU3RhcnREYXRlVGltZSgpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGVsLmNsZWFyU3RhcnREYXRlVGltZSgpXG5cbiAgICB0aGlzLm1vZGVsLnJlc2V0Q2FsZW5kYXJNb2RlKClcblxuICAgIGlmICh0aGlzLmVtaXRPbkNoYW5nZSgpKSB7XG4gICAgICB0aGlzLm1vZGVsLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjbGVhckVuZERhdGVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMubW9kZWwuY2xlYXJFbmREYXRlVGltZSgpXG5cbiAgICB0aGlzLm1vZGVsLnJlc2V0Q2FsZW5kYXJNb2RlKClcblxuICAgIGlmICh0aGlzLmVtaXRPbkNoYW5nZSgpKSB7XG4gICAgICB0aGlzLm1vZGVsLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBjbGVhclN0YXJ0QW5kRW5kRGF0ZVRpbWVzKCk6IHZvaWQge1xuICAgIHRoaXMubW9kZWwuY2xlYXJTdGFydERhdGVUaW1lKClcbiAgICB0aGlzLm1vZGVsLmNsZWFyRW5kRGF0ZVRpbWUoKVxuXG4gICAgdGhpcy5tb2RlbC5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5lbWl0T25DaGFuZ2UoKSkge1xuICAgICAgdGhpcy5tb2RlbC5lbWl0TWFpbkRhdGVzKClcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZShjaGFuZ2VkRGF0ZTogRGF0ZSk6IHZvaWQge1xuICAgIHRoaXMubW9kZWwuY2FsZW5kYXJNb2RlLnNldCgnZGF5cycpXG4gICAgY29uc3QgbmV3UGxhaW5EYXRlID0gVGVtcG9yYWxVdGlsLmdldFBsYWluRGF0ZUZyb21KU0RhdGUoY2hhbmdlZERhdGUpXG4gICAgdGhpcy5tb2RlbC5zZXRTdGFydERhdGUobmV3UGxhaW5EYXRlKVxuICB9XG5cbiAgcHVibGljIGhhbmRsZUVuZENhbGVuZGFyQ2hhbmdlKGNoYW5nZWREYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5tb2RlbC5jYWxlbmRhck1vZGUuc2V0KCdkYXlzJylcbiAgICBjb25zdCBuZXdQbGFpbkRhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0UGxhaW5EYXRlRnJvbUpTRGF0ZShjaGFuZ2VkRGF0ZSlcbiAgICB0aGlzLm1vZGVsLnNldEVuZERhdGUobmV3UGxhaW5EYXRlKVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIFByaXZhdGUgbWV0aG9kcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgcHJpdmF0ZSByZW1vdmVFdmVudExpc3RlbmVycygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FsZW5kYXJTdGFydEVsUmVmIHx8ICF0aGlzLmNhbGVuZGFyRW5kRWxSZWYpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCB8fCAhdGhpcy5jYWxlbmRhckVuZEVsUmVmLm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRTdGFydCA9IHRoaXMuY2FsZW5kYXJTdGFydEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcbiAgICBjb25zdCBuYXRpdmVFbGVtZW50RW5kID0gdGhpcy5jYWxlbmRhckVuZEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcblxuICAgIG5hdGl2ZUVsZW1lbnRTdGFydC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICAgIG5hdGl2ZUVsZW1lbnRFbmQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlciwgdHJ1ZSlcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuOiBNYXRDYWxlbmRhckNlbGxDbGFzc0Z1bmN0aW9uPERhdGU+ID0gKFxuICAgIGNlbGxEYXRlOiBEYXRlLFxuICAgIHZpZXc6IHN0cmluZ1xuICApOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiB0aGlzLmNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm5Cb2R5KGNlbGxEYXRlLCB2aWV3KVxuICB9XG5cbiAgcHJpdmF0ZSBjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuQm9keShjZWxsRGF0ZTogRGF0ZSwgdmlldzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBhbmNob3JEYXRlID0gdGhpcy5tb2RlbC5maXhlZEFuY2hvckRhdGUoKVxuXG4gICAgaWYgKCFhbmNob3JEYXRlKSB7XG4gICAgICByZXR1cm4gJydcbiAgICB9XG5cbiAgICBjb25zdCBkYXRlID0gVGVtcG9yYWxVdGlsLmdldEpTRGF0ZUZyb21QbGFpbkRhdGVUaW1lKGFuY2hvckRhdGUpXG5cbiAgICBpZiAoIWRhdGUpIHtcbiAgICAgIHJldHVybiAnJ1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGNlbGxEYXRlLmdldERhdGUoKSA9PT0gZGF0ZS5nZXREYXRlKCkgJiZcbiAgICAgIGNlbGxEYXRlLmdldE1vbnRoKCkgPT09IGRhdGUuZ2V0TW9udGgoKSAmJlxuICAgICAgY2VsbERhdGUuZ2V0RnVsbFllYXIoKSA9PT0gZGF0ZS5nZXRGdWxsWWVhcigpXG4gICAgKSB7XG4gICAgICByZXR1cm4gJ2VsZGVyLWN1c3RvbS1hbmNob3ItZGF0ZSdcbiAgICB9XG5cbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlTWF0Q2FsZW5kYXJBY3RpdmVEYXRlKHN0YXJ0RGF0ZTogVGVtcG9yYWwuUGxhaW5EYXRlLCBlbmREYXRlOiBUZW1wb3JhbC5QbGFpbkRhdGUpIHtcbiAgICBpZiAoIXRoaXMuY2FsZW5kYXJTdGFydCB8fCAhdGhpcy5jYWxlbmRhckVuZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCFzdGFydERhdGUgJiYgIWVuZERhdGUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGNhbGVuZGFyU3RhcnQgPSB0aGlzLmNhbGVuZGFyU3RhcnRcbiAgICBjb25zdCBjYWxlbmRhckVuZCA9IHRoaXMuY2FsZW5kYXJFbmRcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gdGltZW91dCBpcyBuZWVkZWQgdG8gcnVuIGNhbGVuZGFyIHVwZGF0ZSBsYXN0LCBvdGhlcndpc2UgdGhlcmUgYXJlIGlzc3Vlc1xuICAgICAgaWYgKHN0YXJ0RGF0ZSkge1xuICAgICAgICBjYWxlbmRhclN0YXJ0LmFjdGl2ZURhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0SlNEYXRlRnJvbVBsYWluRGF0ZVRpbWUoc3RhcnREYXRlKVxuICAgICAgfVxuXG4gICAgICBpZiAoZW5kRGF0ZSkge1xuICAgICAgICBjYWxlbmRhckVuZC5hY3RpdmVEYXRlID0gVGVtcG9yYWxVdGlsLmdldEpTRGF0ZUZyb21QbGFpbkRhdGVUaW1lKGVuZERhdGUpXG4gICAgICB9XG4gICAgfSwgMClcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlTWF0Q2FsZW5kYXJUb2RheURhdGUoKTogdm9pZCB7XG4gICAgdGhpcy5jYWxlbmRhclN0YXJ0LnVwZGF0ZVRvZGF5c0RhdGUoKVxuICAgIHRoaXMuY2FsZW5kYXJFbmQudXBkYXRlVG9kYXlzRGF0ZSgpXG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJpbnRlcnZhbC1waWNrZXItY29tcG9uZW50IHAtbWQgbGF5b3V0LWNvbCBnYXAteHhsXCI+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IGdhcC14eGwgcGxhY2UtYmV0d2Vlbi1zdGFydFwiIHN0eWxlPVwiZ2FwOiA1JVwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC1tZCBwdC14c1wiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImludGVydmFsU2VsZWN0b3JcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbFwiPlxuICAgICAgPCEtLSBzbWFydCBzaGlmdCAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zbWFydFNoaWZ0KC0xKVwiIFtkaXNhYmxlZF09XCJtb2RlbC5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgbW9kZWwudmlld0ludGVydmFsTWVzc2FnZSgpIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNtYXJ0U2hpZnQoMSlcIiBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIGNhbGVuZGFycyBhbmQgaW5wdXQgY29udHJvbHMgLS0+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FsZW5kYXJzVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwicHQteHNcIiBzdHlsZT1cIndpZHRoOiAyNSVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC1sZ1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAteHMgcGxhY2Utc3RhcnQtc3RhcnRcIj5cbiAgICAgICAgICBAaWYgKHNob3dIZWxwVGV4dCgpKSB7XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJtYXQtaDVcIj57eyAnaW50ZXJ2YWxQaWNrZXIuc2VsZWN0U21hcnRJbnRlcnZhbCcgfCB0cmFuc2xhdGUgfX08L2g1PlxuICAgICAgICAgIH1cbiAgICAgICAgICA8IS0tIHNlbGVjdCBjdXJyZW50IC0tPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNlbGVjdEN1cnJlbnRXZWVrKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLndlZWsnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2VsZWN0Q3VycmVudE1vbnRoKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLm1vbnRoJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNlbGVjdEN1cnJlbnRRdWFydGVyKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLnF1YXJ0ZXInIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2VsZWN0Q3VycmVudFllYXIoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QueWVhcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaXhlZC1zaGlmdHMtY29udGFpbmVyXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImZpeGVkU2hpZnRzXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlciBnYXAteHhsIHB0LXNtXCI+XG4gICAgPGRpdj5cbiAgICAgIEBpZiAoc2hvd0FuY2hvcigpKSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhbmNob3JJbnB1dEZpZWxkXCI+PC9uZy1jb250YWluZXI+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgQGlmIChzaG93UmVzdWx0VGV4dCgpKSB7XG4gICAgICA8IS0tIHJlc3VsdCBpbnRlcnZhbCAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIHBsYWNlLWNlbnRlci1jZW50ZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtaW50ZXJ2YWwgbWF0LWNhcHRpb24gcHQteHNcIj5cbiAgICAgICAgICBAaWYgKG1vZGVsLnN0YXJ0RGF0ZVRpbWVBc0pTRGF0ZSgpKSB7XG4gICAgICAgICAgICB7eyBtb2RlbC5zdGFydERhdGVUaW1lQXNKU0RhdGUoKSB8IGRhdGU6ICdkZC5NTS4geSwgSEg6bW06c3MnIH19XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlTm90U2V0JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgICA8c3Bhbj4gLSA8L3NwYW4+XG4gICAgICAgICAgQGlmIChtb2RlbC5lbmREYXRlVGltZUFzSlNEYXRlKCkpIHtcbiAgICAgICAgICAgIHt7IG1vZGVsLmVuZERhdGVUaW1lQXNKU0RhdGUoKSB8IGRhdGU6ICdkZC5NTS4geSwgSEg6bW06c3MnIH19XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuZW5kRGF0ZU5vdFNldCcgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2PlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0LWNhcHRpb25cIj57eyBtb2RlbC5kZWx0YUh1bWFuUmVhZGFibGUoKSB8fCAnJm5ic3A7JyB9fTwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgZ2FwLWxnXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXG4gICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgIChjbGljayk9XCJjbGVhclN0YXJ0QW5kRW5kRGF0ZVRpbWVzKClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwibW9kZWwuaXNTdGFydEFuZEVuZERhdGVzRW1wdHkoKVwiXG4gICAgICA+XG4gICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jbGVhcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICBAaWYgKCF0aGlzLmVtaXRPbkNoYW5nZSgpKSB7XG4gICAgICAgIDxidXR0b24gY29sb3I9XCJwcmltYXJ5XCIgbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVtaXRNYWluRGF0ZXMoKVwiPlxuICAgICAgICAgIHt7ICdhY3Rpb25zLm9rJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNpbnRlcnZhbFNlbGVjdG9yPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbFwiPlxuICAgIEBpZiAoc2hvd0hlbHBUZXh0KCkpIHtcbiAgICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zZWxlY3RBYnNvbHV0ZUludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgfVxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHNlbGVjdC1idXR0b25zLWNvbnRhaW5lciBnYXAtc21cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC14cyBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNlbGVjdEN1cnJlbnREYXkoKVwiPlxuICAgICAgICAgIEBpZiAobW9kZWwuaXNGaXhlZEFuY2hvckRhdGVTZXQoKSkge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmFuY2hvckRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci50b2RheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zZWxlY3RZZXN0ZXJkYXkoKVwiPlxuICAgICAgICAgIEBpZiAobW9kZWwuaXNGaXhlZEFuY2hvckRhdGVTZXQoKSkge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDEge3sgJ2ludGVydmFsUGlja2VyLmRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci55ZXN0ZXJkYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgQGlmIChsYXN0RXhjbHVkZXNUb2RheSgpKSB7XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2VsZWN0TGFzdFNldmVuRGF5c0V4Y2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSA3IHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNlbGVjdExhc3RUaGlydHlEYXlzRXhjbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDMwIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zZWxlY3RMYXN0U2V2ZW5EYXlzSW5jbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDcge3sgJ2ludGVydmFsUGlja2VyLmRheXMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2VsZWN0TGFzdFRoaXJ0eURheXNJbmNsdWRpbmdUb2RheSgpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMzAge3sgJ2ludGVydmFsUGlja2VyLmRheXMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICAgICAgQGlmIChpbnRlcnZhbElucHV0TW9kZSgpID09PSAnZGF0ZS10aW1lLXJhbmdlJykge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwdC1zbVwiPjwvZGl2PlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNlbGVjdExhc3RGaXZlTWludXRlcygpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gNSB7eyAnaW50ZXJ2YWxQaWNrZXIubWludXRlcycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zZWxlY3RMYXN0SG91cigpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0ge3sgJ2ludGVydmFsUGlja2VyLmhvdXInIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2VsZWN0TGFzdDI0SG91cnMoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDI0IHt7ICdpbnRlcnZhbFBpY2tlci5ob3VycycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNjYWxlbmRhcnNUZW1wbGF0ZT5cbiAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYXJvdW5kLWNlbnRlclwiIHN0eWxlPVwiYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7IG1pbi1oZWlnaHQ6IDI4MHB4XCI+XG4gICAgPG1hdC1jYWxlbmRhclxuICAgICAgI3JhbmdlQ2FsZW5kYXJTdGFydFxuICAgICAgc3R5bGU9XCJ3aWR0aDogMjEwcHg7IG1heC13aWR0aDogMTAwJVwiXG4gICAgICBbc2VsZWN0ZWRdPVwibW9kZWwuZGF0ZVJhbmdlRm9yQ2FsZW5kYXIoKVwiXG4gICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwiaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIFttYXhEYXRlXT1cIm1vZGVsLmVuZERhdGVBc0pTRGF0ZSgpXCJcbiAgICAgIFtkYXRlQ2xhc3NdPVwiY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGblwiXG4gICAgPlxuICAgIDwvbWF0LWNhbGVuZGFyPlxuICAgIDxtYXQtY2FsZW5kYXJcbiAgICAgICNyYW5nZUNhbGVuZGFyRW5kXG4gICAgICBzdHlsZT1cIndpZHRoOiAyMTBweDsgbWF4LXdpZHRoOiAxMDAlXCJcbiAgICAgIFtzZWxlY3RlZF09XCJtb2RlbC5kYXRlUmFuZ2VGb3JDYWxlbmRhcigpXCJcbiAgICAgIChzZWxlY3RlZENoYW5nZSk9XCJoYW5kbGVFbmRDYWxlbmRhckNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIFttaW5EYXRlXT1cIm1vZGVsLnN0YXJ0RGF0ZUFzSlNEYXRlKClcIlxuICAgICAgW2RhdGVDbGFzc109XCJjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuXCJcbiAgICA+XG4gICAgPC9tYXQtY2FsZW5kYXI+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICAjc3RhcnREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwic3RhcnREYXRlSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cIm1vZGVsLnN0YXJ0RGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwibW9kZWwuc2V0U3RhcnREYXRlRnJvbUh0bWxTdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5jbGVhclN0YXJ0RGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLm1vZGVsLnN0YXJ0RGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgICNlbmREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwiZW5kRGF0ZUlucHV0XCJcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIHR5cGU9XCJkYXRlXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJtb2RlbC5lbmREYXRlSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJtb2RlbC5zZXRFbmREYXRlRnJvbUh0bWxTdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5jbGVhckVuZERhdGVUaW1lKClcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCIhdGhpcy5tb2RlbC5lbmREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGJyIC8+XG4gIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUoKSA9PT0gJ2RhdGUtdGltZS1yYW5nZScpIHtcbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5zdGFydFRpbWUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG5hbWU9XCJzdGFydFRpbWVJbnB1dFwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICB0eXBlPVwidGltZVwiXG4gICAgICAgICAgI3N0YXJ0VGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwibW9kZWwuZ2V0U3RhcnRUaW1lU3RyaW5nKClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm1vZGVsLnNldFN0YXJ0VGltZUZyb21TdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5tb2RlbC5jbGVhclN0YXJ0VGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMubW9kZWwuaXNTdGFydFRpbWVTZXRBbmROb3RNaWRuaWdodCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuZW5kVGltZScgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgbmFtZT1cImVuZFRpbWVJbnB1dFwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICB0eXBlPVwidGltZVwiXG4gICAgICAgICAgI2VuZFRpbWVDb250cm9sPVwibmdNb2RlbFwiXG4gICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cIm1vZGVsLmdldEVuZFRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwibW9kZWwuc2V0RW5kVGltZUZyb21TdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5tb2RlbC5jbGVhckVuZFRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLm1vZGVsLmlzRW5kVGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICB9XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2ZpeGVkU2hpZnRzPlxuICBAaWYgKHNob3dIZWxwVGV4dCgpKSB7XG4gICAgPGg1IGNsYXNzPVwibWF0LWg1XCI+e3sgJ2ludGVydmFsUGlja2VyLnNoaWZ0SW50ZXJ2YWwnIHwgdHJhbnNsYXRlIH19PC9oNT5cbiAgfVxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2hpZnREYXkoLTEpXCIgW2Rpc2FibGVkXT1cIm1vZGVsLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuZGF5JyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2hpZnREYXkoMSlcIiBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2hpZnRNb250aCgtMSwgdHJ1ZSlcIiBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5tb250aCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNoaWZ0TW9udGgoMSwgdHJ1ZSlcIiBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2hpZnRZZWFyKC0xLCB0cnVlKVwiIFtkaXNhYmxlZF09XCJtb2RlbC5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLnllYXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zaGlmdFllYXIoMSwgdHJ1ZSlcIiBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlKCkgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICA8IS0tIHNoaWZ0IG1pbnV0ZSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNoaWZ0VGltZSgtMSwgJ21pbnV0ZXMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIm1vZGVsLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLm1pbnV0ZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwibW9kZWwuZWRpdG9yLnNoaWZ0VGltZSgxLCAnbWludXRlcycpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwibW9kZWwuaXNSYW5nZU5vdFNldCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPCEtLSBzaGlmdCBob3VyIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIChjbGljayk9XCJtb2RlbC5lZGl0b3Iuc2hpZnRUaW1lKC0xLCAnaG91cnMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIm1vZGVsLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmhvdXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cIm1vZGVsLmVkaXRvci5zaGlmdFRpbWUoMSwgJ2hvdXJzJylcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJtb2RlbC5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjYW5jaG9ySW5wdXRGaWVsZD5cbiAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgZmxleC1ub25lIGdhcC1tZFwiPlxuICAgIDxtYXQtbWVudSAjYW5jaG9yTWVudT1cIm1hdE1lbnVcIj5cbiAgICAgIEBpZiAobW9kZWwuc3RhcnREYXRlKCkpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1tZW51LWl0ZW1cbiAgICAgICAgICAoY2xpY2spPVwibW9kZWwuc2V0Rml4ZWRBbmNob3JQb2ludFRvRW5kRGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFtb2RlbC5lbmREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPmxvZ2luPC9tYXQtaWNvbj5cbiAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuZW5kRGF0ZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChtb2RlbC5lbmREYXRlKCkpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1tZW51LWl0ZW1cbiAgICAgICAgICAoY2xpY2spPVwibW9kZWwuc2V0Rml4ZWRBbmNob3JQb2ludFRvU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIW1vZGVsLnN0YXJ0RGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5sb2dvdXQ8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIEBpZiAobW9kZWwuZml4ZWRBbmNob3JEYXRlKCkpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1tZW51LWl0ZW1cbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5tb2RlbC5yZXNldEZpeGVkQW5jaG9yUG9pbnQoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFtb2RlbC5maXhlZEFuY2hvckRhdGUoKSB8fCBhbmNob3JSZWFkT25seSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmNsZWFyJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgPC9tYXQtbWVudT5cblxuICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmFuY2hvckRhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICA8ZWxkZXItbG9jYWwtZGF0ZS1pbnB1dFxuICAgICAgICBuYW1lPVwiYW5jaG9yRGF0ZUlucHV0XCJcbiAgICAgICAgKHZhbHVlVXBkYXRlZCk9XCJtb2RlbC5zZXRBbmNob3JEYXRlRnJvbUZvcm0oJGV2ZW50KVwiXG4gICAgICAgIFt2YWx1ZV09XCJtb2RlbC5nZXRBbmNob3JQb2ludEFzTG9jYWxlRGF0ZSgpXCJcbiAgICAgICAgW3JlYWRvbmx5XT1cImFuY2hvclJlYWRPbmx5KClcIlxuICAgICAgPlxuICAgICAgPC9lbGRlci1sb2NhbC1kYXRlLWlucHV0PlxuICAgICAgQGlmICghYW5jaG9yUmVhZE9ubHkoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImFuY2hvck1lbnVcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJtb2RlbC5pc1N0YXJ0QW5kRW5kRGF0ZXNFbXB0eSgpICYmICFtb2RlbC5maXhlZEFuY2hvckRhdGUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkXCI+bW9yZV9ob3JpejwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgQGlmIChpbnRlcnZhbElucHV0TW9kZSgpID09PSAnZGF0ZS10aW1lLXJhbmdlJykge1xuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXItc2hvcnRcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIG5hbWU9XCJhbmNob3JUaW1lSW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAjYW5jaG9yVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW3JlYWRvbmx5XT1cImFuY2hvclJlYWRPbmx5KClcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cIm1vZGVsLmdldEFuY2hvclRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwibW9kZWwuc2V0QW5jaG9yVGltZUZyb21Gb3JtKCRldmVudClcIlxuICAgICAgICAvPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgKGNsaWNrKT1cInRoaXMubW9kZWwucmVzZXRGaXhlZEFuY2hvclRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFtb2RlbC5pc0ZpeGVkQW5jaG9yVGltZVNldEFuZE5vdE1pZG5pZ2h0KCkgfHwgYW5jaG9yUmVhZE9ubHkoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=