@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.
- package/esm2022/lib/common/data/data-context/indexed-entities.mjs +13 -2
- package/esm2022/lib/common/selection/selection-model.mjs +4 -3
- package/esm2022/lib/components/data-view/common/selection/data-context-selection.directive.mjs +4 -2
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.mjs +21 -0
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.mjs +24 -0
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-controller.mjs +43 -0
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-form-controller.mjs +69 -0
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-select-controller.mjs +117 -0
- package/esm2022/lib/components/time/elder-interval-picker/controller/interval-shift-controller.mjs +44 -0
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +87 -130
- package/esm2022/lib/components/time/elder-interval-picker/interval-picker-binding/elder-interval-picker-binding.directive.mjs +41 -0
- package/esm2022/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.mjs +144 -0
- package/esm2022/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.mjs +93 -0
- package/esm2022/lib/components/time/elder-interval-picker/model/anchor-state.mjs +54 -0
- package/esm2022/lib/components/time/elder-interval-picker/model/interval-state.mjs +37 -0
- package/esm2022/lib/components/time/elder-interval-picker/model/smart-shift-state.mjs +10 -0
- package/esm2022/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.mjs +96 -0
- package/esm2022/lib/components/time/elder-interval-picker/util/interval-picker-util.mjs +194 -0
- package/esm2022/lib/components/time/elder-time.module.mjs +5 -5
- package/fesm2022/elderbyte-ngx-starter.mjs +789 -892
- package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
- package/lib/components/time/elder-interval-picker/controller/interval-anchor-controller.d.ts +9 -0
- package/lib/components/time/elder-interval-picker/controller/interval-calendar-controller.d.ts +7 -0
- package/lib/components/time/elder-interval-picker/controller/interval-controller.d.ts +35 -0
- package/lib/components/time/elder-interval-picker/controller/interval-form-controller.d.ts +12 -0
- package/lib/components/time/elder-interval-picker/controller/interval-select-controller.d.ts +22 -0
- package/lib/components/time/elder-interval-picker/controller/interval-shift-controller.d.ts +13 -0
- package/lib/components/time/elder-interval-picker/elder-interval-picker.component.d.ts +26 -34
- 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
- package/lib/components/time/elder-interval-picker/interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +37 -0
- package/lib/components/time/elder-interval-picker/manager/interval-picker-state-manager.d.ts +46 -0
- package/lib/components/time/elder-interval-picker/model/anchor-state.d.ts +20 -0
- package/lib/components/time/elder-interval-picker/model/interval-state.d.ts +16 -0
- package/lib/components/time/elder-interval-picker/model/smart-shift-state.d.ts +8 -0
- package/lib/components/time/elder-interval-picker/presenter/interval-picker-presenter.d.ts +30 -0
- package/lib/components/time/elder-interval-picker/util/interval-picker-util.d.ts +20 -0
- package/lib/components/time/elder-time.module.d.ts +4 -4
- package/package.json +1 -1
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-binding.directive.mjs +0 -40
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.mjs +0 -202
- package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.mjs +0 -284
- package/esm2022/lib/components/time/elder-interval-picker/model/interval-picker-model.mjs +0 -445
- package/esm2022/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.mjs +0 -37
- package/esm2022/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.mjs +0 -25
- package/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +0 -55
- package/lib/components/time/elder-interval-picker/model/interval-picker-model-editor.d.ts +0 -77
- package/lib/components/time/elder-interval-picker/model/interval-picker-model.d.ts +0 -113
- package/lib/components/time/elder-interval-picker/model/plain-date-interval-message-renderer.d.ts +0 -7
- package/lib/components/time/elder-interval-picker/model/plain-temporal-duration-message-renderer.d.ts +0 -4
package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
|
-
import {
|
|
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 {
|
|
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 {
|
|
17
|
-
import
|
|
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 "
|
|
20
|
-
import * as i2 from "@angular/material/
|
|
21
|
-
import * as i3 from "@angular/material/
|
|
22
|
-
import * as i4 from "@angular/
|
|
23
|
-
import * as i5 from "@angular/
|
|
24
|
-
import * as i6 from "@angular/
|
|
25
|
-
import * as i7 from "@angular/
|
|
26
|
-
import * as i8 from "@
|
|
27
|
-
import * as i9 from "@
|
|
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(
|
|
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.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return '';
|
|
146
|
+
tryUpdateMatCalendarActiveDate(interval) {
|
|
147
|
+
try {
|
|
148
|
+
IntervalPickerUtil.updateMatCalendarActiveDate(this.calendarStart, this.calendarEnd, interval.startDate, interval.endDate);
|
|
165
149
|
}
|
|
166
|
-
|
|
167
|
-
|
|
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: [
|
|
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() || ' ' }}</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() || ' ' }}</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() || ' ' }}</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
|
-
|
|
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() || ' ' }}</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
|