@elderbyte/ngx-starter 18.12.4 → 18.12.6

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 (49) hide show
  1. package/esm2022/lib/common/data/data-context/indexed-entities.mjs +13 -2
  2. package/esm2022/lib/common/selection/selection-model.mjs +4 -3
  3. package/esm2022/lib/components/data-view/common/selection/data-context-selection.directive.mjs +4 -2
  4. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.mjs +21 -0
  5. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.mjs +24 -0
  6. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-controller.mjs +43 -0
  7. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-form-controller.mjs +69 -0
  8. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-select-controller.mjs +117 -0
  9. package/esm2022/lib/components/time/elder-interval-picker/controller/interval-shift-controller.mjs +44 -0
  10. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +87 -130
  11. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-binding/elder-interval-picker-binding.directive.mjs +41 -0
  12. package/esm2022/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.mjs +144 -0
  13. package/esm2022/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.mjs +93 -0
  14. package/esm2022/lib/components/time/elder-interval-picker/model/anchor-state.mjs +54 -0
  15. package/esm2022/lib/components/time/elder-interval-picker/model/interval-state.mjs +37 -0
  16. package/esm2022/lib/components/time/elder-interval-picker/model/smart-shift-state.mjs +10 -0
  17. package/esm2022/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.mjs +96 -0
  18. package/esm2022/lib/components/time/elder-interval-picker/util/interval-picker-util.mjs +194 -0
  19. package/esm2022/lib/components/time/elder-time.module.mjs +5 -5
  20. package/fesm2022/elderbyte-ngx-starter.mjs +789 -892
  21. package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
  22. package/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.d.ts +9 -0
  23. package/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.d.ts +7 -0
  24. package/lib/components/time/elder-interval-picker/controller/interval-controller.d.ts +35 -0
  25. package/lib/components/time/elder-interval-picker/controller/interval-form-controller.d.ts +12 -0
  26. package/lib/components/time/elder-interval-picker/controller/interval-select-controller.d.ts +22 -0
  27. package/lib/components/time/elder-interval-picker/controller/interval-shift-controller.d.ts +13 -0
  28. package/lib/components/time/elder-interval-picker/elder-interval-picker.component.d.ts +26 -34
  29. package/lib/components/time/elder-interval-picker/{elder-interval-picker-binding.directive.d.ts → interval-picker-binding/elder-interval-picker-binding.directive.d.ts} +3 -4
  30. package/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +37 -0
  31. package/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.d.ts +46 -0
  32. package/lib/components/time/elder-interval-picker/model/anchor-state.d.ts +20 -0
  33. package/lib/components/time/elder-interval-picker/model/interval-state.d.ts +16 -0
  34. package/lib/components/time/elder-interval-picker/model/smart-shift-state.d.ts +8 -0
  35. package/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.d.ts +30 -0
  36. package/lib/components/time/elder-interval-picker/util/interval-picker-util.d.ts +20 -0
  37. package/lib/components/time/elder-time.module.d.ts +4 -4
  38. package/package.json +1 -1
  39. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-binding.directive.mjs +0 -40
  40. package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.mjs +0 -202
  41. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.mjs +0 -284
  42. package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model.mjs +0 -445
  43. package/esm2022/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.mjs +0 -37
  44. package/esm2022/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.mjs +0 -25
  45. package/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +0 -55
  46. package/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.d.ts +0 -77
  47. package/lib/components/time/elder-interval-picker/model/interval-picker-model.d.ts +0 -113
  48. package/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.d.ts +0 -7
  49. package/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.d.ts +0 -4
@@ -1,5 +1,6 @@
1
1
  import { CommonModule } from '@angular/common';
2
- import { booleanAttribute, ChangeDetectionStrategy, Component, effect, ElementRef, EventEmitter, Input, input, Output, ViewChild, } from '@angular/core';
2
+ import { ChangeDetectionStrategy, Component, ElementRef, Input, input, Output, ViewChild, } from '@angular/core';
3
+ import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
3
4
  import { FormsModule } from '@angular/forms';
4
5
  import { MatButtonModule } from '@angular/material/button';
5
6
  import { DateAdapter } from '@angular/material/core';
@@ -10,61 +11,80 @@ import { MatInputModule } from '@angular/material/input';
10
11
  import { MatMenuModule } from '@angular/material/menu';
11
12
  import { MatTooltip } from '@angular/material/tooltip';
12
13
  import { LoggerFactory } from '@elderbyte/ts-logger';
14
+ import { Temporal } from '@js-temporal/polyfill';
13
15
  import { TranslateModule } from '@ngx-translate/core';
14
- import { TemporalUtil } from '../../../common/time/temporal-util';
16
+ import { map } from 'rxjs';
17
+ import { coerceInterval, coerceIntervalIsoStr } from '../../../common/public_api';
15
18
  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';
19
+ import { ElderIntervalInputComponent, } from '../elder-interval-input/elder-interval-input.component';
20
+ import IntervalController from './controller/interval-controller';
21
+ import IntervalPickerStateManager from './manager/interval-picker-state-manager';
22
+ import IntervalPickerPresenter from './presenter/interval-picker-presenter';
23
+ import IntervalPickerUtil from './util/interval-picker-util';
18
24
  import * as i0 from "@angular/core";
19
- import * as i1 from "./model/interval-picker-model";
20
- import * as i2 from "@angular/material/datepicker";
21
- import * as i3 from "@angular/material/form-field";
22
- import * as i4 from "@angular/material/input";
23
- import * as i5 from "@angular/common";
24
- import * as i6 from "@angular/material/icon";
25
- import * as i7 from "@angular/forms";
26
- import * as i8 from "@angular/material/button";
27
- import * as i9 from "@ngx-translate/core";
28
- import * as i10 from "@angular/material/menu";
25
+ import * as i1 from "@angular/material/datepicker";
26
+ import * as i2 from "@angular/material/form-field";
27
+ import * as i3 from "@angular/material/input";
28
+ import * as i4 from "@angular/common";
29
+ import * as i5 from "@angular/material/icon";
30
+ import * as i6 from "@angular/forms";
31
+ import * as i7 from "@angular/material/button";
32
+ import * as i8 from "@ngx-translate/core";
33
+ import * as i9 from "@angular/material/menu";
29
34
  export class ElderIntervalPickerComponent {
30
- set interval(value) {
31
- this.model.setInterval(value);
32
- }
33
- set anchorDateTime(value) {
34
- this.model.setAnchorDateTime(value);
35
- }
36
35
  /***************************************************************************
37
36
  * *
38
37
  * Constructor *
39
38
  * *
40
39
  **************************************************************************/
41
- constructor(model) {
42
- this.model = model;
40
+ constructor() {
43
41
  /***************************************************************************
44
42
  * *
45
43
  * Fields *
46
44
  * *
47
45
  **************************************************************************/
48
46
  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();
57
- this.calendarAnchorDateCssClassFn = (cellDate, view) => {
58
- return this.calendarAnchorDateCssClassFnBody(cellDate, view);
59
- };
60
- this.model.setupEventEmitter(this.dateChange);
61
- effect(() => {
62
- if (this.model.anchorDate()) {
63
- this.updateMatCalendarTodayDate();
47
+ this.autoEmitMode = true;
48
+ this.emitOnChange = true;
49
+ this.emitType = 'interval';
50
+ this.intervalInputMode = input('date-time-range');
51
+ this.showAnchor = input(false);
52
+ this.anchorReadOnly = input(false);
53
+ this.externalAnchorDateTime = input(Temporal.Now.plainDateTimeISO());
54
+ this.externalInterval = input(null);
55
+ this.manager = new IntervalPickerStateManager();
56
+ this.controller = new IntervalController(this.manager);
57
+ this.presenter = new IntervalPickerPresenter(this.manager.interval$, this.manager.anchor$, this.manager.smartShift$);
58
+ this.manager.intervalChange.pipe(takeUntilDestroyed()).subscribe({
59
+ next: (state) => this.tryUpdateMatCalendarActiveDate(state),
60
+ });
61
+ this.intervalChange = this.manager.intervalChange.pipe(map((srcInterval) => {
62
+ if (!srcInterval) {
63
+ return null;
64
+ }
65
+ const elderInterval = IntervalPickerUtil.createElderInterval(srcInterval);
66
+ if (this.emitType === 'iso') {
67
+ console.log('emitting type iso', coerceIntervalIsoStr(elderInterval));
68
+ return coerceIntervalIsoStr(elderInterval);
64
69
  }
70
+ console.log('emitting type elder interval', elderInterval);
71
+ return elderInterval;
72
+ }));
73
+ this.manager.anchor$.pipe(takeUntilDestroyed()).subscribe((anchor) => {
74
+ IntervalPickerUtil.updateMatCalendarTodayDate(this.calendarStart, this.calendarEnd);
75
+ });
76
+ const externalAnchorObservable = toObservable(this.externalAnchorDateTime);
77
+ externalAnchorObservable.pipe(takeUntilDestroyed()).subscribe({
78
+ next: (date) => {
79
+ this.manager.setExternalAnchor(date);
80
+ },
65
81
  });
66
- effect(() => {
67
- this.updateMatCalendarActiveDate(this.model.startDate(), this.model.endDate());
82
+ const externalIntervalObservable = toObservable(this.externalInterval);
83
+ externalIntervalObservable.pipe(takeUntilDestroyed()).subscribe({
84
+ next: (interval) => {
85
+ const result = coerceInterval(interval);
86
+ this.manager.setInterval(IntervalPickerUtil.transformToIntervalState(result || null));
87
+ },
68
88
  });
69
89
  }
70
90
  /***************************************************************************
@@ -72,19 +92,21 @@ export class ElderIntervalPickerComponent {
72
92
  * Life Cycle *
73
93
  * *
74
94
  **************************************************************************/
95
+ ngOnInit() { }
96
+ ngOnDestroy() {
97
+ this.removeEventListeners();
98
+ }
75
99
  ngAfterViewInit() {
76
- this.model.isEmittingOnChange.set(this.emitOnChange());
77
100
  this.setupDateInputCalendarFocusPrevention();
78
101
  setTimeout(() => {
79
- this.model.setInitialized();
102
+ // this prevents ngmodel issue
103
+ this.manager.isInitialized = true;
104
+ console.log('externalInterval', this.externalInterval());
80
105
  }, 0);
81
106
  }
82
- ngOnDestroy() {
83
- this.removeEventListeners();
84
- }
85
107
  /***************************************************************************
86
108
  * *
87
- * Public API *
109
+ * Private methods *
88
110
  * *
89
111
  **************************************************************************/
90
112
  setupDateInputCalendarFocusPrevention() {
@@ -109,43 +131,6 @@ export class ElderIntervalPickerComponent {
109
131
  nativeElementStart.addEventListener('focus', this.calendarElFocusEventHandler, true);
110
132
  nativeElementEnd.addEventListener('focus', this.calendarElFocusEventHandler, true);
111
133
  }
112
- clearStartDateTime() {
113
- this.model.clearStartDateTime();
114
- this.model.resetCalendarMode();
115
- if (this.emitOnChange()) {
116
- this.model.emitMainDates();
117
- }
118
- }
119
- clearEndDateTime() {
120
- this.model.clearEndDateTime();
121
- this.model.resetCalendarMode();
122
- if (this.emitOnChange()) {
123
- this.model.emitMainDates();
124
- }
125
- }
126
- clearStartAndEndDateTimes() {
127
- this.model.clearStartDateTime();
128
- this.model.clearEndDateTime();
129
- this.model.resetCalendarMode();
130
- if (this.emitOnChange()) {
131
- this.model.emitMainDates();
132
- }
133
- }
134
- handleStartCalendarChange(changedDate) {
135
- this.model.calendarMode.set('days');
136
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
137
- this.model.setStartDate(newPlainDate);
138
- }
139
- handleEndCalendarChange(changedDate) {
140
- this.model.calendarMode.set('days');
141
- const newPlainDate = TemporalUtil.getPlainDateFromJSDate(changedDate);
142
- this.model.setEndDate(newPlainDate);
143
- }
144
- /***************************************************************************
145
- * *
146
- * Private methods *
147
- * *
148
- **************************************************************************/
149
134
  removeEventListeners() {
150
135
  if (!this.calendarStartElRef || !this.calendarEndElRef) {
151
136
  return;
@@ -158,47 +143,16 @@ export class ElderIntervalPickerComponent {
158
143
  nativeElementStart.removeEventListener('focus', this.calendarElFocusEventHandler, true);
159
144
  nativeElementEnd.removeEventListener('focus', this.calendarElFocusEventHandler, true);
160
145
  }
161
- calendarAnchorDateCssClassFnBody(cellDate, view) {
162
- const anchorDate = this.model.fixedAnchorDate();
163
- if (!anchorDate) {
164
- return '';
146
+ tryUpdateMatCalendarActiveDate(interval) {
147
+ try {
148
+ IntervalPickerUtil.updateMatCalendarActiveDate(this.calendarStart, this.calendarEnd, interval.startDate, interval.endDate);
165
149
  }
166
- const date = TemporalUtil.getJSDateFromPlainDateTime(anchorDate);
167
- if (!date) {
168
- return '';
150
+ catch (e) {
151
+ console.debug('Failed to update calendar active date', e);
169
152
  }
170
- if (cellDate.getDate() === date.getDate() &&
171
- cellDate.getMonth() === date.getMonth() &&
172
- cellDate.getFullYear() === date.getFullYear()) {
173
- return 'elder-custom-anchor-date';
174
- }
175
- return '';
176
- }
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
153
  }
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 }); }
154
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
155
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.5", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { autoEmitMode: { classPropertyName: "autoEmitMode", publicName: "autoEmitMode", isSignal: false, isRequired: false, transformFunction: null }, emitOnChange: { classPropertyName: "emitOnChange", publicName: "emitOnChange", isSignal: false, isRequired: false, transformFunction: null }, emitType: { classPropertyName: "emitType", publicName: "emitType", isSignal: false, 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 }, externalAnchorDateTime: { classPropertyName: "externalAnchorDateTime", publicName: "externalAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null }, externalInterval: { classPropertyName: "externalInterval", publicName: "externalInterval", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { intervalChange: "intervalChange" }, providers: [{ 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 <div class=\"layout-col\">\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)=\"controller.select.selectCurrentDay()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectYesterday()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast365daysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 365\n {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"controller.select.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5\n {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24\n {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ presenter.smartShiftMessage() }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <div\n class=\"layout-row place-around-center\"\n style=\"align-items: flex-start; min-height: 280px\"\n >\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setStartDateFromJSDate($event)\"\n [maxDate]=\"presenter.endDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setEndDateFromJSDate($event)\"\n [minDate]=\"presenter.startDateTimeAsJSDate()\"\n [dateClass]=\"presenter.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]=\"presenter.startDateHtmlString()\"\n (ngModelChange)=\"controller.form.setStartDateFromString($event)\"\n />\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]=\"presenter.endDateHtmlString()\"\n (ngModelChange)=\"controller.form.setEndDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n </div>\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]=\"presenter.startTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearStartTime()\"\n [disabled]=\"!presenter.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]=\"presenter.endTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearEndTime()\"\n [disabled]=\"!presenter.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n <br />\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 <!-- select current -->\n <button mat-button (click)=\"controller.select.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (true) {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftMinute(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftHour(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftHour(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\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 <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (presenter.startDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!presenter.startDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (presenter.endDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!presenter.endDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (presenter.isFixedAnchorDateSet()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.resetAnchor()\"\n [disabled]=\"!presenter.isFixedAnchorDateSet() || 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 <input\n #startDateInput\n name=\"anchorDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.anchorDateHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorDateFromString($event)\"\n [readonly]=\"anchorReadOnly()\"\n />\n @if (!anchorReadOnly()) {\n <button mat-icon-button matSuffix [matMenuTriggerFor]=\"anchorMenu\" [disabled]=\"presenter.isAnchorMenuDisabled()\">\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]=\"presenter.anchorTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.anchor.resetAnchorTime()\"\n [disabled]=\"anchorReadOnly() || presenter.isAnchorTimeMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n }\n </div>\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (presenter.startDateTimeAsJSDate()) {\n {{ presenter.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (presenter.endDateTimeAsJSDate()) {\n {{ presenter.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ presenter.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"controller.clearInterval()\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.autoEmitMode) {\n <button color=\"primary\" mat-raised-button (click)=\"controller.manualEmit()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n</div>\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: i1.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: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.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: "pipe", type: i4.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i9.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: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.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 }); }
202
156
  }
203
157
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
204
158
  type: Component,
@@ -216,12 +170,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
216
170
  FormsModule,
217
171
  MatButtonModule,
218
172
  MatCalendar,
219
- ElderLocalDateInputComponent,
220
173
  MatTooltip,
221
174
  TranslateModule,
222
175
  MatMenuModule,
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: [{
176
+ ElderIntervalInputComponent,
177
+ MatMenuModule,
178
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: DateAdapter, useClass: CustomDateAdapter }], 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 <div class=\"layout-col\">\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)=\"controller.select.selectCurrentDay()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectYesterday()\">\n @if (presenter.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"controller.select.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30\n {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast365daysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 365\n {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode() === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"controller.select.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5\n {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24\n {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ presenter.smartShiftMessage() }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.smartShift(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <div\n class=\"layout-row place-around-center\"\n style=\"align-items: flex-start; min-height: 280px\"\n >\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setStartDateFromJSDate($event)\"\n [maxDate]=\"presenter.endDateTimeAsJSDate()\"\n [dateClass]=\"presenter.calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"presenter.dateRangeForCalendar()\"\n (selectedChange)=\"controller.calendar.setEndDateFromJSDate($event)\"\n [minDate]=\"presenter.startDateTimeAsJSDate()\"\n [dateClass]=\"presenter.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]=\"presenter.startDateHtmlString()\"\n (ngModelChange)=\"controller.form.setStartDateFromString($event)\"\n />\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]=\"presenter.endDateHtmlString()\"\n (ngModelChange)=\"controller.form.setEndDateFromString($event)\"\n />\n </mat-form-field>\n </div>\n </div>\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]=\"presenter.startTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setStartTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearStartTime()\"\n [disabled]=\"!presenter.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]=\"presenter.endTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setEndTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.clearEndTime()\"\n [disabled]=\"!presenter.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n <br />\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 <!-- select current -->\n <button mat-button (click)=\"controller.select.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"controller.select.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftDay(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMonth(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftYear(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (true) {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"controller.shift.shiftMinute(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftMinute(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftHour(-1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\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)=\"controller.shift.shiftHour(1)\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\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 <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (presenter.startDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!presenter.startDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (presenter.endDateHtmlString()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!presenter.endDateHtmlString()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (presenter.isFixedAnchorDateSet()) {\n <button\n mat-menu-item\n (click)=\"controller.anchor.resetAnchor()\"\n [disabled]=\"!presenter.isFixedAnchorDateSet() || 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 <input\n #startDateInput\n name=\"anchorDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"presenter.anchorDateHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorDateFromString($event)\"\n [readonly]=\"anchorReadOnly()\"\n />\n @if (!anchorReadOnly()) {\n <button mat-icon-button matSuffix [matMenuTriggerFor]=\"anchorMenu\" [disabled]=\"presenter.isAnchorMenuDisabled()\">\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]=\"presenter.anchorTimeHtmlString()\"\n (ngModelChange)=\"controller.form.setAnchorTimeFromString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"controller.anchor.resetAnchorTime()\"\n [disabled]=\"anchorReadOnly() || presenter.isAnchorTimeMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n }\n </div>\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (presenter.startDateTimeAsJSDate()) {\n {{ presenter.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (presenter.endDateTimeAsJSDate()) {\n {{ presenter.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ presenter.deltaHumanReadable() || '&nbsp;' }}</span>\n </div>\n </div>\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"controller.clearInterval()\"\n [disabled]=\"!presenter.isValidIntervalSet()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.autoEmitMode) {\n <button color=\"primary\" mat-raised-button (click)=\"controller.manualEmit()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n</div>\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"] }]
179
+ }], ctorParameters: () => [], propDecorators: { intervalChange: [{
180
+ type: Output
181
+ }], autoEmitMode: [{
182
+ type: Input
183
+ }], emitOnChange: [{
184
+ type: Input
185
+ }], emitType: [{
186
+ type: Input
187
+ }], calendarStart: [{
225
188
  type: ViewChild,
226
189
  args: ['rangeCalendarStart']
227
190
  }], calendarEnd: [{
@@ -239,11 +202,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImpor
239
202
  }], endDateInput: [{
240
203
  type: ViewChild,
241
204
  args: ['endDateInput']
242
- }], dateChange: [{
243
- type: Output
244
- }], interval: [{
245
- type: Input
246
- }], anchorDateTime: [{
247
- type: Input
248
205
  }] } });
249
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBRUwsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsTUFBTSxFQUNOLFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUNMLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFBO0FBQ3RCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUE7QUFDMUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBQ3BELE9BQU8sRUFDTCxXQUFXLEVBRVgsbUJBQW1CLEVBQ25CLG1CQUFtQixFQUNuQixpQkFBaUIsRUFDakIsa0JBQWtCLEdBQ25CLE1BQU0sOEJBQThCLENBQUE7QUFDckMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTtBQUNwRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFD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ZTt3QkFDZixhQUFhO3FCQUNkLGFBQ1UsQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLENBQUMsbUJBR3RFLHVCQUF1QixDQUFDLE1BQU07d0ZBV2QsYUFBYTtzQkFBN0MsU0FBUzt1QkFBQyxvQkFBb0I7Z0JBQ0EsV0FBVztzQkFBekMsU0FBUzt1QkFBQyxrQkFBa0I7Z0JBRTBCLGtCQUFrQjtzQkFBeEUsU0FBUzt1QkFBQyxvQkFBb0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBQ0EsZ0JBQWdCO3NCQUFwRSxTQUFTO3VCQUFDLGtCQUFrQixFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRTtnQkFFdEIsY0FBYztzQkFBMUMsU0FBUzt1QkFBQyxnQkFBZ0I7Z0JBQ0EsWUFBWTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjO2dCQVVmLFVBQVU7c0JBQW5CLE1BQU07Z0JBS0ksUUFBUTtzQkFEbEIsS0FBSztnQkFNSyxjQUFjO3NCQUR4QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJ1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgYm9vbGVhbkF0dHJpYnV0ZSxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgZWZmZWN0LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBpbnB1dCxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nXG5pbXBvcnQgeyBEYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnXG5pbXBvcnQge1xuICBNYXRDYWxlbmRhcixcbiAgTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbixcbiAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gIE1hdERhdGVSYW5nZVBpY2tlcixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcidcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSwgTWF0SGludCwgTWF0TGFiZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJ1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0J1xuaW1wb3J0IHsgTWF0TWVudU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnXG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCdcbmltcG9ydCB7IExvZ2dlckZhY3RvcnkgfSBmcm9tICdAZWxkZXJieXRlL3RzLWxvZ2dlcidcbmltcG9ydCB7IFRyYW5zbGF0ZU1vZHVsZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnXG5pbXBvcnQgeyBJbnRlcnZhbCB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL2ludGVydmFsJ1xuaW1wb3J0IHsgVGVtcG9yYWxVdGlsIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL3RpbWUvdGVtcG9yYWwtdXRpbCdcbmltcG9ydCB7IEN1c3RvbURhdGVBZGFwdGVyIH0gZnJvbSAnLi4vZGF0ZS1hZGFwdGVycy9jdXN0b20tZGF0ZS1hZGFwdGVyJ1xuaW1wb3J0IHsgSW50ZXJ2YWxJbnB1dE1vZGUgfSBmcm9tICcuLi9lbGRlci1pbnRlcnZhbC1pbnB1dC9lbGRlci1pbnRlcnZhbC1pbnB1dC5jb21wb25lbnQnXG5pbXBvcnQgeyBFbGRlckxvY2FsRGF0ZUlucHV0Q29tcG9uZW50IH0gZnJvbSAnLi4vZWxkZXItbG9jYWwtZGF0ZS1pbnB1dC9lbGRlci1sb2NhbC1kYXRlLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEludGVydmFsUGlja2VyTW9kZWwgfSBmcm9tICcuL21vZGVsL2ludGVydmFsLXBpY2tlci1tb2RlbCdcbmltcG9ydCB7IFRlbXBvcmFsIH0gZnJvbSAnQGpzLXRlbXBvcmFsL3BvbHlmaWxsJ1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdlbGRlci1pbnRlcnZhbC1waWNrZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgTWF0RGF0ZVJhbmdlUGlja2VyLFxuICAgIE1hdERhdGVwaWNrZXJNb2R1bGUsXG4gICAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgICBNYXRJbnB1dE1vZHVsZSxcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgTWF0SWNvbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FsZW5kYXIsXG4gICAgRWxkZXJMb2NhbERhdGVJbnB1dENvbXBvbmVudCxcbiAgICBNYXRUb29sdGlwLFxuICAgIFRyYW5zbGF0ZU1vZHVsZSxcbiAgICBNYXRNZW51TW9kdWxlLFxuICBdLFxuICBwcm92aWRlcnM6IFtJbnRlcnZhbFBpY2tlck1vZGVsLCB7IHByb3ZpZGU6IERhdGVBZGFwdGVyLCB1c2VDbGFzczogQ3VzdG9tRGF0ZUFkYXB0ZXIgfV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5zY3NzJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIEVsZGVySW50ZXJ2YWxQaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogRmllbGRzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKHRoaXMuY29uc3RydWN0b3IubmFtZSlcblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnKSBjYWxlbmRhclN0YXJ0ITogTWF0Q2FsZW5kYXI8RGF0ZT5cbiAgQFZpZXdDaGlsZCgncmFuZ2VDYWxlbmRhckVuZCcpIGNhbGVuZGFyRW5kITogTWF0Q2FsZW5kYXI8RGF0ZT5cblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJTdGFydEVsUmVmITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJywgeyByZWFkOiBFbGVtZW50UmVmIH0pIGNhbGVuZGFyRW5kRWxSZWYhOiBFbGVtZW50UmVmXG5cbiAgQFZpZXdDaGlsZCgnc3RhcnREYXRlSW5wdXQnKSBzdGFydERhdGVJbnB1dCE6IEVsZW1lbnRSZWZcbiAgQFZpZXdDaGlsZCgnZW5kRGF0ZUlucHV0JykgZW5kRGF0ZUlucHV0ITogRWxlbWVudFJlZlxuXG4gIHB1YmxpYyByZWFkb25seSBlbWl0T25DaGFuZ2UgPSBpbnB1dCh0cnVlLCB7IHRyYW5zZm9ybTogKHYpID0+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=
206
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsS0FBSyxFQUNMLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFBO0FBQ3RCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQTtBQUM3RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFBO0FBQzFELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUNwRCxPQUFPLEVBQ0wsV0FBVyxFQUNYLG1CQUFtQixFQUNuQixtQkFBbUIsRUFDbkIsaUJBQWlCLEVBQ2pCLGtCQUFrQixHQUNuQixNQUFNLDhCQUE4QixDQUFBO0FBQ3JDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sOEJBQThCLENBQUE7QUFDcEYsT0FBTyxFQUFFLGFBQWEsRUFB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QUFvQixFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRTtnQkFDQSxnQkFBZ0I7c0JBQXBFLFNBQVM7dUJBQUMsa0JBQWtCLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO2dCQUV0QixjQUFjO3NCQUExQyxTQUFTO3VCQUFDLGdCQUFnQjtnQkFDQSxZQUFZO3NCQUF0QyxTQUFTO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBJbnB1dCxcbiAgaW5wdXQsXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJ1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkLCB0b09ic2VydmFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCdcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nXG5pbXBvcnQgeyBEYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnXG5pbXBvcnQge1xuICBNYXRDYWxlbmRhcixcbiAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gIE1hdERhdGVSYW5nZVBpY2tlcixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcidcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSwgTWF0SGludCwgTWF0TGFiZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJ1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0J1xuaW1wb3J0IHsgTWF0TWVudU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnXG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCdcbmltcG9ydCB7IExvZ2dlckZhY3RvcnkgfSBmcm9tICdAZWxkZXJieXRlL3RzLWxvZ2dlcidcbmltcG9ydCB7IFRlbXBvcmFsIH0gZnJvbSAnQGpzLXRlbXBvcmFsL3BvbHlmaWxsJ1xuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSdcbmltcG9ydCB7IG1hcCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBjb2VyY2VJbnRlcnZhbCwgY29lcmNlSW50ZXJ2YWxJc29TdHIgfSBmcm9tICcuLi8uLi8uLi9jb21tb24vcHVibGljX2FwaSdcbmltcG9ydCB7IEludGVydmFsLCBJc29JbnRlcnZhbFN0ciB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL2ludGVydmFsJ1xuaW1wb3J0IHsgQ3VzdG9tRGF0ZUFkYXB0ZXIgfSBmcm9tICcuLi9kYXRlLWFkYXB0ZXJzL2N1c3RvbS1kYXRlLWFkYXB0ZXInXG5pbXBvcnQge1xuICBFbGRlckludGVydmFsSW5wdXRDb21wb25lbnQsXG4gIEludGVydmFsSW5wdXRNb2RlLFxufSBmcm9tICcuLi9lbGRlci1pbnRlcnZhbC1pbnB1dC9lbGRlci1pbnRlcnZhbC1pbnB1dC5jb21wb25lbnQnXG5pbXBvcnQgSW50ZXJ2YWxDb250cm9sbGVyIGZyb20gJy4vY29udHJvbGxlci9pbnRlcnZhbC1jb250cm9sbGVyJ1xuaW1wb3J0IEludGVydmFsUGlja2VyU3RhdGVNYW5hZ2VyIGZyb20gJy4vbWFuYWdlci9pbnRlcnZhbC1waWNrZXItc3RhdGUtbWFuYWdlcidcbmltcG9ydCBJbnRlcnZhbFN0YXRlIGZyb20gJy4vbW9kZWwvaW50ZXJ2YWwtc3RhdGUnXG5pbXBvcnQgSW50ZXJ2YWxQaWNrZXJQcmVzZW50ZXIgZnJvbSAnLi9wcmVzZW50ZXIvaW50ZXJ2YWwtcGlja2VyLXByZXNlbnRlcidcbmltcG9ydCBJbnRlcnZhbFBpY2tlclV0aWwgZnJvbSAnLi91dGlsL2ludGVydmFsLXBpY2tlci11dGlsJ1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdlbGRlci1pbnRlcnZhbC1waWNrZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgTWF0RGF0ZVJhbmdlUGlja2VyLFxuICAgIE1hdERhdGVwaWNrZXJNb2R1bGUsXG4gICAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgICBNYXRJbnB1dE1vZHVsZSxcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgTWF0SWNvbk1vZHVsZSxcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FsZW5kYXIsXG4gICAgTWF0VG9vbHRpcCxcbiAgICBUcmFuc2xhdGVNb2R1bGUsXG4gICAgTWF0TWVudU1vZHVsZSxcbiAgICBFbGRlckludGVydmFsSW5wdXRDb21wb25lbnQsXG4gICAgTWF0TWVudU1vZHVsZSxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5zY3NzJyxcbiAgcHJvdmlkZXJzOiBbeyBwcm92aWRlOiBEYXRlQWRhcHRlciwgdXNlQ2xhc3M6IEN1c3RvbURhdGVBZGFwdGVyIH1dLFxufSlcbmV4cG9ydCBjbGFzcyBFbGRlckludGVydmFsUGlja2VyQ29tcG9uZW50IHtcbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIEZpZWxkcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgcHJpdmF0ZSByZWFkb25seSBsb2cgPSBMb2dnZXJGYWN0b3J5LmdldExvZ2dlcih0aGlzLmNvbnN0cnVjdG9yLm5hbWUpXG5cbiAgLy8gUHJpdmF0ZVxuICBwcml2YXRlIHJlYWRvbmx5IG1hbmFnZXI6IEludGVydmFsUGlja2VyU3RhdGVNYW5hZ2VyXG5cbiAgLy8gUHVibGljXG4gIHB1YmxpYyByZWFkb25seSBjb250cm9sbGVyOiBJbnRlcnZhbENvbnRyb2xsZXJcbiAgcHVibGljIHJlYWRvbmx5IHByZXNlbnRlcjogSW50ZXJ2YWxQaWNrZXJQcmVzZW50ZXJcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHJlYWRvbmx5IGludGVydmFsQ2hhbmdlOiBPYnNlcnZhYmxlPEludGVydmFsIHwgSXNvSW50ZXJ2YWxTdHIgfCBudWxsPlxuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBhdXRvRW1pdE1vZGUgPSB0cnVlXG5cbiAgQElucHV0KClcbiAgcHVibGljIGVtaXRPbkNoYW5nZSA9IHRydWVcblxuICBASW5wdXQoKVxuICBwdWJsaWMgZW1pdFR5cGU6ICdpbnRlcnZhbCcgfCAnaXNvJyA9ICdpbnRlcnZhbCdcblxuICBpbnRlcnZhbElucHV0TW9kZSA9IGlucHV0PEludGVydmFsSW5wdXRNb2RlPignZGF0ZS10aW1lLXJhbmdlJylcbiAgc2hvd0FuY2hvciA9IGlucHV0PGJvb2xlYW4+KGZhbHNlKVxuICBhbmNob3JSZWFkT25seSA9IGlucHV0PGJvb2xlYW4+KGZhbHNlKVxuICBleHRlcm5hbEFuY2hvckRhdGVUaW1lID0gaW5wdXQ8VGVtcG9yYWwuUGxhaW5EYXRlVGltZSB8IG51bGw+KFRlbXBvcmFsLk5vdy5wbGFpbkRhdGVUaW1lSVNPKCkpXG4gIGV4dGVybmFsSW50ZXJ2YWwgPSBpbnB1dDxJbnRlcnZhbCB8IElzb0ludGVydmFsU3RyIHwgbnVsbD4obnVsbClcblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnKSBjYWxlbmRhclN0YXJ0ITogTWF0Q2FsZW5kYXI8RGF0ZT5cbiAgQFZpZXdDaGlsZCgncmFuZ2VDYWxlbmRhckVuZCcpIGNhbGVuZGFyRW5kITogTWF0Q2FsZW5kYXI8RGF0ZT5cblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJTdGFydEVsUmVmITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJywgeyByZWFkOiBFbGVtZW50UmVmIH0pIGNhbGVuZGFyRW5kRWxSZWYhOiBFbGVtZW50UmVmXG5cbiAgQFZpZXdDaGlsZCgnc3RhcnREYXRlSW5wdXQnKSBzdGFydERhdGVJbnB1dCE6IEVsZW1lbnRSZWZcbiAgQFZpZXdDaGlsZCgnZW5kRGF0ZUlucHV0JykgZW5kRGF0ZUlucHV0ITogRWxlbWVudFJlZlxuXG4gIHByaXZhdGUgY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyOiAoZXZlbnQ6IEZvY3VzRXZlbnQpID0+IHZvaWRcblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogQ29uc3RydWN0b3IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLm1hbmFnZXIgPSBuZXcgSW50ZXJ2YWxQaWNrZXJTdGF0ZU1hbmFnZXIoKVxuICAgIHRoaXMuY29udHJvbGxlciA9IG5ldyBJbnRlcnZhbENvbnRyb2xsZXIodGhpcy5tYW5hZ2VyKVxuICAgIHRoaXMucHJlc2VudGVyID0gbmV3IEludGVydmFsUGlja2VyUHJlc2VudGVyKFxuICAgICAgdGhpcy5tYW5hZ2VyLmludGVydmFsJCxcbiAgICAgIHRoaXMubWFuYWdlci5hbmNob3IkLFxuICAgICAgdGhpcy5tYW5hZ2VyLnNtYXJ0U2hpZnQkXG4gICAgKVxuXG4gICAgdGhpcy5tYW5hZ2VyLmludGVydmFsQ2hhbmdlLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAoc3RhdGUpID0+IHRoaXMudHJ5VXBkYXRlTWF0Q2FsZW5kYXJBY3RpdmVEYXRlKHN0YXRlKSxcbiAgICB9KVxuXG4gICAgdGhpcy5pbnRlcnZhbENoYW5nZSA9IHRoaXMubWFuYWdlci5pbnRlcnZhbENoYW5nZS5waXBlKFxuICAgICAgbWFwKChzcmNJbnRlcnZhbDogYW55KSA9PiB7XG4gICAgICAgIGlmICghc3JjSW50ZXJ2YWwpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZWxkZXJJbnRlcnZhbCA9IEludGVydmFsUGlja2VyVXRpbC5jcmVhdGVFbGRlckludGVydmFsKHNyY0ludGVydmFsKVxuXG4gICAgICAgIGlmICh0aGlzLmVtaXRUeXBlID09PSAnaXNvJykge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdlbWl0dGluZyB0eXBlIGlzbycsIGNvZXJjZUludGVydmFsSXNvU3RyKGVsZGVySW50ZXJ2YWwpKVxuICAgICAgICAgIHJldHVybiBjb2VyY2VJbnRlcnZhbElzb1N0cihlbGRlckludGVydmFsKVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc29sZS5sb2coJ2VtaXR0aW5nIHR5cGUgZWxkZXIgaW50ZXJ2YWwnLCBlbGRlckludGVydmFsKVxuICAgICAgICByZXR1cm4gZWxkZXJJbnRlcnZhbFxuICAgICAgfSlcbiAgICApXG5cbiAgICB0aGlzLm1hbmFnZXIuYW5jaG9yJC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCgpKS5zdWJzY3JpYmUoKGFuY2hvcikgPT4ge1xuICAgICAgSW50ZXJ2YWxQaWNrZXJVdGlsLnVwZGF0ZU1hdENhbGVuZGFyVG9kYXlEYXRlKHRoaXMuY2FsZW5kYXJTdGFydCwgdGhpcy5jYWxlbmRhckVuZClcbiAgICB9KVxuXG4gICAgY29uc3QgZXh0ZXJuYWxBbmNob3JPYnNlcnZhYmxlID0gdG9PYnNlcnZhYmxlKHRoaXMuZXh0ZXJuYWxBbmNob3JEYXRlVGltZSlcbiAgICBleHRlcm5hbEFuY2hvck9ic2VydmFibGUucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQoKSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChkYXRlKSA9PiB7XG4gICAgICAgIHRoaXMubWFuYWdlci5zZXRFeHRlcm5hbEFuY2hvcihkYXRlKVxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgZXh0ZXJuYWxJbnRlcnZhbE9ic2VydmFibGUgPSB0b09ic2VydmFibGUodGhpcy5leHRlcm5hbEludGVydmFsKVxuICAgIGV4dGVybmFsSW50ZXJ2YWxPYnNlcnZhYmxlLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAoaW50ZXJ2YWw6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBjb2VyY2VJbnRlcnZhbChpbnRlcnZhbClcbiAgICAgICAgdGhpcy5tYW5hZ2VyLnNldEludGVydmFsKEludGVydmFsUGlja2VyVXRpbC50cmFuc2Zvcm1Ub0ludGVydmFsU3RhdGUocmVzdWx0IHx8IG51bGwpKVxuICAgICAgfSxcbiAgICB9KVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIExpZmUgQ3ljbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgbmdPbkluaXQoKTogdm9pZCB7fVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKVxuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuc2V0dXBEYXRlSW5wdXRDYWxlbmRhckZvY3VzUHJldmVudGlvbigpXG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIC8vIHRoaXMgcHJldmVudHMgbmdtb2RlbCBpc3N1ZVxuICAgICAgdGhpcy5tYW5hZ2VyLmlzSW5pdGlhbGl6ZWQgPSB0cnVlXG4gICAgICBjb25zb2xlLmxvZygnZXh0ZXJuYWxJbnRlcnZhbCcsIHRoaXMuZXh0ZXJuYWxJbnRlcnZhbCgpKVxuICAgIH0sIDApXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogUHJpdmF0ZSBtZXRob2RzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHNldHVwRGF0ZUlucHV0Q2FsZW5kYXJGb2N1c1ByZXZlbnRpb24oKTogdm9pZCB7XG4gICAgLy8gUHJldmVudHMgdGhlIGZvY3VzIG9uIHRoZSBjYWxlbmRhciB3aGVuIHRoZSBpbnB1dCBmaWVsZCBpcyBjaGFuZ2VkIHZpYSB0aGUga2V5Ym9hcmRcbiAgICB0aGlzLmNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlciA9IChldmVudDogRm9jdXNFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKCFldmVudCB8fCAhZXZlbnQucmVsYXRlZFRhcmdldCkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgIGNvbnN0IHJlbFRhcmdldCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQgYXMgSFRNTElucHV0RWxlbWVudFxuXG4gICAgICBpZiAocmVsVGFyZ2V0Lm5hbWUgPT09ICdzdGFydERhdGVJbnB1dCcpIHtcbiAgICAgICAgdGhpcy5zdGFydERhdGVJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBpZiAocmVsVGFyZ2V0Lm5hbWUgPT09ICdlbmREYXRlSW5wdXQnKSB7XG4gICAgICAgIHRoaXMuZW5kRGF0ZUlucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBuYXRpdmVFbGVtZW50U3RhcnQgPSB0aGlzLmNhbGVuZGFyU3RhcnRFbFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50XG4gICAgY29uc3QgbmF0aXZlRWxlbWVudEVuZCA9IHRoaXMuY2FsZW5kYXJFbmRFbFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50XG5cbiAgICBuYXRpdmVFbGVtZW50U3RhcnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlciwgdHJ1ZSlcbiAgICBuYXRpdmVFbGVtZW50RW5kLmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gIH1cblxuICBwcml2YXRlIHJlbW92ZUV2ZW50TGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYgfHwgIXRoaXMuY2FsZW5kYXJFbmRFbFJlZikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNhbGVuZGFyU3RhcnRFbFJlZi5uYXRpdmVFbGVtZW50IHx8ICF0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgcHJpdmF0ZSB0cnlVcGRhdGVNYXRDYWxlbmRhckFjdGl2ZURhdGUoaW50ZXJ2YWw6IEludGVydmFsU3RhdGUpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgSW50ZXJ2YWxQaWNrZXJVdGlsLnVwZGF0ZU1hdENhbGVuZGFyQWN0aXZlRGF0ZShcbiAgICAgICAgdGhpcy5jYWxlbmRhclN0YXJ0LFxuICAgICAgICB0aGlzLmNhbGVuZGFyRW5kLFxuICAgICAgICBpbnRlcnZhbC5zdGFydERhdGUsXG4gICAgICAgIGludGVydmFsLmVuZERhdGVcbiAgICAgIClcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdGYWlsZWQgdG8gdXBkYXRlIGNhbGVuZGFyIGFjdGl2ZSBkYXRlJywgZSlcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJpbnRlcnZhbC1waWNrZXItY29tcG9uZW50IHAtbWQgbGF5b3V0LWNvbCBnYXAteHhsXCI+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IGdhcC14eGwgcGxhY2UtYmV0d2Vlbi1zdGFydFwiIHN0eWxlPVwiZ2FwOiA1JVwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC1tZCBwdC14c1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2xcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgc2VsZWN0LWJ1dHRvbnMtY29udGFpbmVyIGdhcC1zbVwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC14cyBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIuc2VsZWN0LnNlbGVjdEN1cnJlbnREYXkoKVwiPlxuICAgICAgICAgICAgICBAaWYgKHByZXNlbnRlci5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpKSB7XG4gICAgICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmFuY2hvckRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLnRvZGF5JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwiY29udHJvbGxlci5zZWxlY3Quc2VsZWN0WWVzdGVyZGF5KClcIj5cbiAgICAgICAgICAgICAgQGlmIChwcmVzZW50ZXIuaXNGaXhlZEFuY2hvckRhdGVTZXQoKSkge1xuICAgICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSAxIHt7ICdpbnRlcnZhbFBpY2tlci5kYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci55ZXN0ZXJkYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJjb250cm9sbGVyLnNlbGVjdC5zZWxlY3RMYXN0U2V2ZW5EYXlzSW5jbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gN1xuICAgICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5cycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJjb250cm9sbGVyLnNlbGVjdC5zZWxlY3RMYXN0VGhpcnR5RGF5c0luY2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDMwXG4gICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIuc2VsZWN0LnNlbGVjdExhc3QzNjVkYXlzSW5jbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMzY1XG4gICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlKCkgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwdC1zbVwiPjwvZGl2PlxuICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIuc2VsZWN0LnNlbGVjdExhc3RGaXZlTWludXRlcygpXCI+XG4gICAgICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDVcbiAgICAgICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubWludXRlcycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwiY29udHJvbGxlci5zZWxlY3Quc2VsZWN0TGFzdEhvdXIoKVwiPlxuICAgICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSB7eyAnaW50ZXJ2YWxQaWNrZXIuaG91cicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwiY29udHJvbGxlci5zZWxlY3Quc2VsZWN0TGFzdDI0SG91cnMoKVwiPlxuICAgICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSAyNFxuICAgICAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5ob3VycycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2xcIj5cbiAgICAgIDwhLS0gc21hcnQgc2hpZnQgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwiY29udHJvbGxlci5zaGlmdC5zbWFydFNoaWZ0KC0xKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxzcGFuPnt7IHByZXNlbnRlci5zbWFydFNoaWZ0TWVzc2FnZSgpIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc21hcnRTaGlmdCgxKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIGNhbGVuZGFycyBhbmQgaW5wdXQgY29udHJvbHMgLS0+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCJcbiAgICAgICAgc3R5bGU9XCJhbGlnbi1pdGVtczogZmxleC1zdGFydDsgbWluLWhlaWdodDogMjgwcHhcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWNhbGVuZGFyXG4gICAgICAgICAgI3JhbmdlQ2FsZW5kYXJTdGFydFxuICAgICAgICAgIHN0eWxlPVwid2lkdGg6IDIxMHB4OyBtYXgtd2lkdGg6IDEwMCVcIlxuICAgICAgICAgIFtzZWxlY3RlZF09XCJwcmVzZW50ZXIuZGF0ZVJhbmdlRm9yQ2FsZW5kYXIoKVwiXG4gICAgICAgICAgKHNlbGVjdGVkQ2hhbmdlKT1cImNvbnRyb2xsZXIuY2FsZW5kYXIuc2V0U3RhcnREYXRlRnJvbUpTRGF0ZSgkZXZlbnQpXCJcbiAgICAgICAgICBbbWF4RGF0ZV09XCJwcmVzZW50ZXIuZW5kRGF0ZVRpbWVBc0pTRGF0ZSgpXCJcbiAgICAgICAgICBbZGF0ZUNsYXNzXT1cInByZXNlbnRlci5jYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuXCJcbiAgICAgICAgPlxuICAgICAgICA8L21hdC1jYWxlbmRhcj5cbiAgICAgICAgPG1hdC1jYWxlbmRhclxuICAgICAgICAgICNyYW5nZUNhbGVuZGFyRW5kXG4gICAgICAgICAgc3R5bGU9XCJ3aWR0aDogMjEwcHg7IG1heC13aWR0aDogMTAwJVwiXG4gICAgICAgICAgW3NlbGVjdGVkXT1cInByZXNlbnRlci5kYXRlUmFuZ2VGb3JDYWxlbmRhcigpXCJcbiAgICAgICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwiY29udHJvbGxlci5jYWxlbmRhci5zZXRFbmREYXRlRnJvbUpTRGF0ZSgkZXZlbnQpXCJcbiAgICAgICAgICBbbWluRGF0ZV09XCJwcmVzZW50ZXIuc3RhcnREYXRlVGltZUFzSlNEYXRlKClcIlxuICAgICAgICAgIFtkYXRlQ2xhc3NdPVwicHJlc2VudGVyLmNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm5cIlxuICAgICAgICA+XG4gICAgICAgIDwvbWF0LWNhbGVuZGFyPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICNzdGFydERhdGVJbnB1dFxuICAgICAgICAgICAgICBuYW1lPVwic3RhcnREYXRlSW5wdXRcIlxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwiZGF0ZVwiXG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInByZXNlbnRlci5zdGFydERhdGVIdG1sU3RyaW5nKClcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJjb250cm9sbGVyLmZvcm0uc2V0U3RhcnREYXRlRnJvbVN0cmluZygkZXZlbnQpXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5lbmREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICNlbmREYXRlSW5wdXRcbiAgICAgICAgICAgICAgbmFtZT1cImVuZERhdGVJbnB1dFwiXG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIHR5cGU9XCJkYXRlXCJcbiAgICAgICAgICAgICAgW25nTW9kZWxdPVwicHJlc2VudGVyLmVuZERhdGVIdG1sU3RyaW5nKClcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJjb250cm9sbGVyLmZvcm0uc2V0RW5kRGF0ZUZyb21TdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlKCkgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXIgZ2FwLXhsIHB0LXNtXCI+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIG5hbWU9XCJzdGFydFRpbWVJbnB1dFwiXG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAgICAgI3N0YXJ0VGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgICAgICBbbmdNb2RlbF09XCJwcmVzZW50ZXIuc3RhcnRUaW1lSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY29udHJvbGxlci5mb3JtLnNldFN0YXJ0VGltZUZyb21TdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLmNsZWFyU3RhcnRUaW1lKClcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByZXNlbnRlci5pc1N0YXJ0VGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5lbmRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIG5hbWU9XCJlbmRUaW1lSW5wdXRcIlxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwidGltZVwiXG4gICAgICAgICAgICAgICNlbmRUaW1lQ29udHJvbD1cIm5nTW9kZWxcIlxuICAgICAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInByZXNlbnRlci5lbmRUaW1lSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY29udHJvbGxlci5mb3JtLnNldEVuZFRpbWVGcm9tU3RyaW5nKCRldmVudClcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAoY2xpY2spPVwiY29udHJvbGxlci5jbGVhckVuZFRpbWUoKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcHJlc2VudGVyLmlzRW5kVGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8YnIgLz5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwicHQteHNcIiBzdHlsZT1cIndpZHRoOiAyNSVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC1sZ1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAteHMgcGxhY2Utc3RhcnQtc3RhcnRcIj5cbiAgICAgICAgICA8IS0tIHNlbGVjdCBjdXJyZW50IC0tPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwiY29udHJvbGxlci5zZWxlY3Quc2VsZWN0Q3VycmVudFdlZWsoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2Qud2VlaycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIuc2VsZWN0LnNlbGVjdEN1cnJlbnRNb250aCgpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuY3VycmVudFBlcmlvZC5tb250aCcgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIuc2VsZWN0LnNlbGVjdEN1cnJlbnRRdWFydGVyKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLnF1YXJ0ZXInIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJjb250cm9sbGVyLnNlbGVjdC5zZWxlY3RDdXJyZW50WWVhcigpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuY3VycmVudFBlcmlvZC55ZWFyJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZpeGVkLXNoaWZ0cy1jb250YWluZXJcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc2hpZnREYXkoLTEpXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByZXNlbnRlci5pc1ZhbGlkSW50ZXJ2YWxTZXQoKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmRheScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiY29udHJvbGxlci5zaGlmdC5zaGlmdERheSgxKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc2hpZnRNb250aCgtMSlcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcHJlc2VudGVyLmlzVmFsaWRJbnRlcnZhbFNldCgpXCJcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIubW9udGgnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc2hpZnRNb250aCgxKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc2hpZnRZZWFyKC0xKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci55ZWFyJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLnNoaWZ0LnNoaWZ0WWVhcigxKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIEBpZiAodHJ1ZSkge1xuICAgICAgICAgICAgICA8IS0tIHNoaWZ0IG1pbnV0ZSAtLT5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLnNoaWZ0LnNoaWZ0TWludXRlKC0xKVwiXG4gICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByZXNlbnRlci5pc1ZhbGlkSW50ZXJ2YWxTZXQoKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIubWludXRlJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLnNoaWZ0LnNoaWZ0TWludXRlKDEpXCJcbiAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcHJlc2VudGVyLmlzVmFsaWRJbnRlcnZhbFNldCgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwhLS0gc2hpZnQgaG91ciAtLT5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLnNoaWZ0LnNoaWZ0SG91cigtMSlcIlxuICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuaXNWYWxpZEludGVydmFsU2V0KClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmhvdXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuc2hpZnQuc2hpZnRIb3VyKDEpXCJcbiAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcHJlc2VudGVyLmlzVmFsaWRJbnRlcnZhbFNldCgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG48ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlciBnYXAteHhsIHB0LXNtXCI+XG4gIDxkaXY+XG4gICAgQGlmIChzaG93QW5jaG9yKCkpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IGZsZXgtbm9uZSBnYXAtbWRcIj5cbiAgICAgICAgPG1hdC1tZW51ICNhbmNob3JNZW51PVwibWF0TWVudVwiPlxuICAgICAgICAgIEBpZiAocHJlc2VudGVyLnN0YXJ0RGF0ZUh0bWxTdHJpbmcoKSkge1xuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXG4gICAgICAgICAgICAgIChjbGljayk9XCJjb250cm9sbGVyLmFuY2hvci5zZXRGaXhlZEFuY2hvclBvaW50VG9FbmREYXRlVGltZSgpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuc3RhcnREYXRlSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPmxvZ2luPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBpZiAocHJlc2VudGVyLmVuZERhdGVIdG1sU3RyaW5nKCkpIHtcbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgICAgICAoY2xpY2spPVwiY29udHJvbGxlci5hbmNob3Iuc2V0Rml4ZWRBbmNob3JQb2ludFRvU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcmVzZW50ZXIuZW5kRGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5sb2dvdXQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgICBAaWYgKHByZXNlbnRlci5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpKSB7XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cbiAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRyb2xsZXIuYW5jaG9yLnJlc2V0QW5jaG9yKClcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXByZXNlbnRlci5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpIHx8IGFuY2hvclJlYWRPbmx5KClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuY2xlYXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgfVxuICAgICAgICA8L21hdC1tZW51PlxuXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JEYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgI3N0YXJ0RGF0ZUlucHV0XG4gICAgICAgICAgICBuYW1lPVwiYW5jaG9yRGF0ZUlucHV0XCJcbiAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICB0eXBlPVwiZGF0ZVwiXG4gICAgICAgICAgICBbbmdNb2RlbF09XCJwcmVzZW50ZXIuYW5jaG9yRGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJjb250cm9sbGVyLmZvcm0uc2V0QW5jaG9yRGF0ZUZyb21TdHJpbmcoJGV2ZW50KVwiXG4gICAgICAgICAgICBbcmVhZG9ubHldPVwiYW5jaG9yUmVhZE9ubHkoKVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICBAaWYgKCFhbmNob3JSZWFkT25seSgpKSB7XG4gICAgICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBtYXRTdWZmaXggW21hdE1lbnVUcmlnZ2VyRm9yXT1cImFuY2hvck1lbnVcIiBbZGlzYWJsZWRdPVwicHJlc2VudGVyLmlzQW5jaG9yTWVudURpc2FibGVkKClcIj5cbiAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPm1vcmVfaG9yaXo8L21hdC1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgfVxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlKCkgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXItc2hvcnRcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuYW5jaG9yVGltZScgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBuYW1lPVwiYW5jaG9yVGltZUlucHV0XCJcbiAgICAgICAgICAgICAgdHlwZT1cInRpbWVcIlxuICAgICAgICAgICAgICAjYW5jaG9yVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiYW5jaG9yUmVhZE9ubHkoKVwiXG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInByZXNlbnRlci5hbmNob3JUaW1lSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY29udHJvbGxlci5mb3JtLnNldEFuY2hvclRpbWVGcm9tU3RyaW5nKCRldmVudClcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAoY2xpY2spPVwiY29udHJvbGxlci5hbmNob3IucmVzZXRBbmNob3JUaW1lKClcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYW5jaG9yUmVhZE9ubHkoKSB8fCBwcmVzZW50ZXIuaXNBbmNob3JUaW1lTWlkbmlnaHQoKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIDwvZGl2PlxuICA8IS0tIHJlc3VsdCBpbnRlcnZhbCAtLT5cbiAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgcGxhY2UtY2VudGVyLWNlbnRlclwiPlxuICAgIDxkaXYgY2xhc3M9XCJkYXRlLWludGVydmFsIG1hdC1jYXB0aW9uIHB0LXhzXCI+XG4gICAgICBAaWYgKHByZXNlbnRlci5zdGFydERhdGVUaW1lQXNKU0RhdGUoKSkge1xuICAgICAgICB7eyBwcmVzZW50ZXIuc3RhcnREYXRlVGltZUFzSlNEYXRlKCkgfCBkYXRlOiAnZGQuTU0uIHksIEhIOm1tOnNzJyB9fVxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICB9XG4gICAgICA8c3Bhbj4gLSA8L3NwYW4+XG4gICAgICBAaWYgKHByZXNlbnRlci5lbmREYXRlVGltZUFzSlNEYXRlKCkpIHtcbiAgICAgICAge3sgcHJlc2VudGVyLmVuZERhdGVUaW1lQXNKU0RhdGUoKSB8IGRhdGU6ICdkZC5NTS4geSwgSEg6bW06c3MnIH19XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgPGRpdj5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWF0LWNhcHRpb25cIj57eyBwcmVzZW50ZXIuZGVsdGFIdW1hblJlYWRhYmxlKCkgfHwgJyZuYnNwOycgfX08L3NwYW4+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBnYXAtbGdcIj5cbiAgICA8YnV0dG9uXG4gICAgICBtYXQtcmFpc2VkLWJ1dHRvblxuICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgIChjbGljayk9XCJjb250cm9sbGVyLmNsZWFySW50ZXJ2YWwoKVwiXG4gICAgICBbZGlzYWJsZWRdPVwiIXByZXNlbnRlci5pc1ZhbGlkSW50ZXJ2YWxTZXQoKVwiXG4gICAgPlxuICAgICAge3sgJ2ludGVydmFsUGlja2VyLmNsZWFyJyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvYnV0dG9uPlxuXG4gICAgQGlmICghdGhpcy5hdXRvRW1pdE1vZGUpIHtcbiAgICAgIDxidXR0b24gY29sb3I9XCJwcmltYXJ5XCIgbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cImNvbnRyb2xsZXIubWFudWFsRW1pdCgpXCI+XG4gICAgICAgIHt7ICdhY3Rpb25zLm9rJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgPC9idXR0b24+XG4gICAgfVxuICA8L2Rpdj5cbjwvZGl2PlxuIl19