@elderbyte/ngx-starter 18.11.1 → 18.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/common/data/data-context/data-context-source-event-binding.mjs +24 -7
- package/esm2022/lib/common/data/datasource/data-source-change-event.mjs +20 -10
- package/esm2022/lib/common/data/datasource/patch/deep-partial-patcher.mjs +58 -0
- package/esm2022/lib/common/time/temporal-util.mjs +7 -1
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.mjs +9 -5
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs +6 -3
- package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.service.mjs +13 -3
- package/fesm2022/elderbyte-ngx-starter.mjs +128 -21
- package/fesm2022/elderbyte-ngx-starter.mjs.map +1 -1
- package/lib/common/data/data-context/data-context-source-event-binding.d.ts +2 -5
- package/lib/common/data/datasource/data-source-change-event.d.ts +14 -5
- package/lib/common/data/datasource/patch/deep-partial-patcher.d.ts +28 -0
- package/lib/common/time/temporal-util.d.ts +2 -0
- package/lib/components/time/elder-interval-picker/elder-interval-picker-toggle/elder-interval-picker-toggle.component.d.ts +2 -2
- package/lib/components/time/elder-interval-picker/elder-interval-picker.component.d.ts +2 -1
- package/lib/components/time/elder-interval-picker/elder-interval-picker.service.d.ts +4 -2
- package/package.json +1 -1
package/esm2022/lib/components/time/elder-interval-picker/elder-interval-picker.component.mjs
CHANGED
|
@@ -49,6 +49,7 @@ export class ElderIntervalPickerComponent {
|
|
|
49
49
|
this.isAnchorReadOnly = false;
|
|
50
50
|
this.isResultTextVisible = true;
|
|
51
51
|
this.isHelpTextsVisible = false;
|
|
52
|
+
this.isSelectLastModeExcludingToday = false;
|
|
52
53
|
this.dateChange = new EventEmitter();
|
|
53
54
|
this.inputInterval = input(null);
|
|
54
55
|
this.inputAnchorDateTime = input(null);
|
|
@@ -204,7 +205,7 @@ export class ElderIntervalPickerComponent {
|
|
|
204
205
|
return '';
|
|
205
206
|
}
|
|
206
207
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.2", ngImport: i0, type: ElderIntervalPickerComponent, deps: [{ token: i1.ElderIntervalPickerService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
207
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.2", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { isEmittingOnChange: { classPropertyName: "isEmittingOnChange", publicName: "isEmittingOnChange", isSignal: false, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: false, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: false, isRequired: false, transformFunction: null }, isAnchorReadOnly: { classPropertyName: "isAnchorReadOnly", publicName: "isAnchorReadOnly", isSignal: false, isRequired: false, transformFunction: null }, isResultTextVisible: { classPropertyName: "isResultTextVisible", publicName: "isResultTextVisible", isSignal: false, isRequired: false, transformFunction: null }, isHelpTextsVisible: { classPropertyName: "isHelpTextsVisible", publicName: "isHelpTextsVisible", isSignal: false, isRequired: false, transformFunction: null }, inputInterval: { classPropertyName: "inputInterval", publicName: "inputInterval", isSignal: true, isRequired: false, transformFunction: null }, inputAnchorDateTime: { classPropertyName: "inputAnchorDateTime", publicName: "inputAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || ' ' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectLastSevenDays()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDays()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i2.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: ElderLocalDateInputComponent, selector: "elder-local-date-input", inputs: ["zone", "autoDatePicker", "arrows", "today", "center", "datePickerTouchUi", "allowNull", "datePickerEnabled", "isoValue", "dateValue", "isoDateValue"], outputs: ["blurred", "valueUpdatedBlur", "isoValueChange", "dateValueChange", "isoDateValueChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
208
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.2", type: ElderIntervalPickerComponent, isStandalone: true, selector: "elder-interval-picker", inputs: { isEmittingOnChange: { classPropertyName: "isEmittingOnChange", publicName: "isEmittingOnChange", isSignal: false, isRequired: false, transformFunction: null }, intervalInputMode: { classPropertyName: "intervalInputMode", publicName: "intervalInputMode", isSignal: false, isRequired: false, transformFunction: null }, showAnchor: { classPropertyName: "showAnchor", publicName: "showAnchor", isSignal: false, isRequired: false, transformFunction: null }, isAnchorReadOnly: { classPropertyName: "isAnchorReadOnly", publicName: "isAnchorReadOnly", isSignal: false, isRequired: false, transformFunction: null }, isResultTextVisible: { classPropertyName: "isResultTextVisible", publicName: "isResultTextVisible", isSignal: false, isRequired: false, transformFunction: null }, isHelpTextsVisible: { classPropertyName: "isHelpTextsVisible", publicName: "isHelpTextsVisible", isSignal: false, isRequired: false, transformFunction: null }, isSelectLastModeExcludingToday: { classPropertyName: "isSelectLastModeExcludingToday", publicName: "isSelectLastModeExcludingToday", isSignal: false, isRequired: false, transformFunction: null }, inputInterval: { classPropertyName: "inputInterval", publicName: "inputInterval", isSignal: true, isRequired: false, transformFunction: null }, inputAnchorDateTime: { classPropertyName: "inputAnchorDateTime", publicName: "inputAnchorDateTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], viewQueries: [{ propertyName: "calendarStart", first: true, predicate: ["rangeCalendarStart"], descendants: true }, { propertyName: "calendarEnd", first: true, predicate: ["rangeCalendarEnd"], descendants: true }, { propertyName: "calendarStartElRef", first: true, predicate: ["rangeCalendarStart"], descendants: true, read: ElementRef }, { propertyName: "calendarEndElRef", first: true, predicate: ["rangeCalendarEnd"], descendants: true, read: ElementRef }, { propertyName: "startDateInput", first: true, predicate: ["startDateInput"], descendants: true }, { propertyName: "endDateInput", first: true, predicate: ["endDateInput"], descendants: true }], ngImport: i0, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || ' ' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (isSelectLastModeExcludingToday) {\n <button mat-button (click)=\"svc.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"svc.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"], dependencies: [{ kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i2.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd", "startDateAccessibleName", "endDateAccessibleName"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection", "_userDragDrop"], exportAs: ["matCalendar"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: ElderLocalDateInputComponent, selector: "elder-local-date-input", inputs: ["zone", "autoDatePicker", "arrows", "today", "center", "datePickerTouchUi", "allowNull", "datePickerEnabled", "isoValue", "dateValue", "isoDateValue"], outputs: ["blurred", "valueUpdatedBlur", "isoValueChange", "dateValueChange", "isoDateValueChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
208
209
|
}
|
|
209
210
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImport: i0, type: ElderIntervalPickerComponent, decorators: [{
|
|
210
211
|
type: Component,
|
|
@@ -226,7 +227,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImpor
|
|
|
226
227
|
MatTooltip,
|
|
227
228
|
TranslateModule,
|
|
228
229
|
MatMenuModule,
|
|
229
|
-
], providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || ' ' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectLastSevenDays()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDays()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
|
|
230
|
+
], providers: [ElderIntervalPickerService, { provide: DateAdapter, useClass: CustomDateAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"interval-picker-component p-md layout-col gap-xxl\">\n <div class=\"layout-row gap-xxl place-between-start\" style=\"gap: 5%\">\n <div class=\"layout-col gap-md pt-xs\">\n <ng-container *ngTemplateOutlet=\"intervalSelector\"></ng-container>\n </div>\n <div class=\"layout-col\">\n <!-- smart shift -->\n <div class=\"layout-row place-around-center\">\n <button mat-icon-button (click)=\"svc.smartShift(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ svc.viewIntervalMessage() }}</span>\n <button mat-icon-button (click)=\"svc.smartShift(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- calendars and input controls -->\n <ng-container *ngTemplateOutlet=\"calendarsTemplate\"></ng-container>\n </div>\n <div class=\"pt-xs\" style=\"width: 25%\">\n <div class=\"layout-col gap-lg\">\n <div class=\"layout-col gap-xs place-start-start\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectSmartInterval' | translate }}</h5>\n }\n <!-- select current -->\n <button mat-button (click)=\"svc.selectCurrentWeek()\">\n {{ 'intervalPicker.currentPeriod.week' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentMonth()\">\n {{ 'intervalPicker.currentPeriod.month' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentQuarter()\">\n {{ 'intervalPicker.currentPeriod.quarter' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectCurrentYear()\">\n {{ 'intervalPicker.currentPeriod.year' | translate }}\n </button>\n </div>\n <div class=\"fixed-shifts-container\">\n <ng-container *ngTemplateOutlet=\"fixedShifts\"></ng-container>\n </div>\n </div>\n </div>\n </div>\n <div class=\"layout-row place-between-center gap-xxl pt-sm\">\n <div>\n @if (showAnchor) {\n <ng-container *ngTemplateOutlet=\"anchorInputField\"></ng-container>\n }\n </div>\n @if (isResultTextVisible) {\n <!-- result interval -->\n <div class=\"layout-col place-center-center\">\n <div class=\"date-interval mat-caption pt-xs\">\n @if (svc.startDateTimeAsJSDate()) {\n {{ svc.startDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.startDateNotSet' | translate }}\n }\n <span> - </span>\n @if (svc.endDateTimeAsJSDate()) {\n {{ svc.endDateTimeAsJSDate() | date: 'dd.MM. y, HH:mm:ss' }}\n } @else {\n {{ 'intervalPicker.endDateNotSet' | translate }}\n }\n </div>\n <div>\n <span class=\"mat-caption\">{{ svc.deltaHumanReadable() || ' ' }}</span>\n </div>\n </div>\n }\n <div class=\"layout-row gap-lg\">\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"clearStartAndEndDateTimes()\"\n [disabled]=\"svc.isStartAndEndDatesEmpty()\"\n >\n {{ 'intervalPicker.clear' | translate }}\n </button>\n\n @if (!this.isEmittingOnChange) {\n <button color=\"primary\" mat-raised-button (click)=\"svc.emitMainDates()\">\n {{ 'actions.ok' | translate }}\n </button>\n }\n </div>\n </div>\n</div>\n\n<ng-template #intervalSelector>\n <div class=\"layout-col\">\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.selectAbsoluteInterval' | translate }}</h5>\n }\n <div class=\"layout-row select-buttons-container gap-sm\">\n <div class=\"layout-col gap-xs place-start-stretch\">\n <button mat-button (click)=\"svc.selectCurrentDay()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.anchorDay' | translate }}\n } @else {\n {{ 'intervalPicker.today' | translate }}\n }\n </button>\n <button mat-button (click)=\"svc.selectYesterday()\">\n @if (svc.isFixedAnchorDateSet()) {\n {{ 'intervalPicker.last' | translate }} 1 {{ 'intervalPicker.day' | translate }}\n } @else {\n {{ 'intervalPicker.yesterday' | translate }}\n }\n </button>\n @if (isSelectLastModeExcludingToday) {\n <button mat-button (click)=\"svc.selectLastSevenDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysExcludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n } @else {\n <button mat-button (click)=\"svc.selectLastSevenDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 7 {{ 'intervalPicker.days' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastThirtyDaysIncludingToday()\">\n {{ 'intervalPicker.last' | translate }} 30 {{ 'intervalPicker.days' | translate }}\n </button>\n }\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"pt-sm\"></div>\n <button mat-button (click)=\"svc.selectLastFiveMinutes()\">\n {{ 'intervalPicker.last' | translate }} 5 {{ 'intervalPicker.minutes' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLastHour()\">\n {{ 'intervalPicker.last' | translate }} {{ 'intervalPicker.hour' | translate }}\n </button>\n <button mat-button (click)=\"svc.selectLast24Hours()\">\n {{ 'intervalPicker.last' | translate }} 24 {{ 'intervalPicker.hours' | translate }}\n </button>\n }\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #calendarsTemplate>\n <div class=\"layout-row place-around-center\" style=\"align-items: flex-start; min-height: 280px\">\n <mat-calendar\n #rangeCalendarStart\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleStartCalendarChange($event)\"\n [maxDate]=\"svc.endDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n <mat-calendar\n #rangeCalendarEnd\n style=\"width: 210px; max-width: 100%\"\n [selected]=\"svc.dateRangeForCalendar()\"\n (selectedChange)=\"handleEndCalendarChange($event)\"\n [minDate]=\"svc.startDateAsJSDate()\"\n [dateClass]=\"calendarAnchorDateCssClassFn\"\n >\n </mat-calendar>\n </div>\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startDate' | translate }}</mat-label>\n <input\n #startDateInput\n name=\"startDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.startDateHtmlString()\"\n (ngModelChange)=\"svc.setStartDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearStartDateTime()\"\n [disabled]=\"!this.svc.startDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n <div class=\"layout-row place-around-center\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endDate' | translate }}</mat-label>\n <input\n #endDateInput\n name=\"endDateInput\"\n matInput\n type=\"date\"\n [ngModel]=\"svc.endDateHtmlString()\"\n (ngModelChange)=\"svc.setEndDateFromHtmlString($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.clearEndDateTime()\"\n [disabled]=\"!this.svc.endDate()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n <br />\n @if (intervalInputMode === 'date-time-range') {\n <div class=\"layout-row place-around-center gap-xl pt-sm\">\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.startTime' | translate }}</mat-label>\n <input\n name=\"startTimeInput\"\n matInput\n type=\"time\"\n #startTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getStartTimeString()\"\n (ngModelChange)=\"svc.setStartTimeFromString($event, startTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearStartTime()\"\n [disabled]=\"!this.svc.isStartTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.endTime' | translate }}</mat-label>\n <input\n name=\"endTimeInput\"\n matInput\n type=\"time\"\n #endTimeControl=\"ngModel\"\n step=\"1\"\n [ngModel]=\"svc.getEndTimeString()\"\n (ngModelChange)=\"svc.setEndTimeFromString($event, endTimeControl)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.clearEndTime()\"\n [disabled]=\"!this.svc.isEndTimeSetAndNotMidnight()\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </div>\n }\n</ng-template>\n\n<ng-template #fixedShifts>\n @if (isHelpTextsVisible) {\n <h5 class=\"mat-h5\">{{ 'intervalPicker.shiftInterval' | translate }}</h5>\n }\n <div class=\"layout-col place-start-stretch\">\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftDay(-1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.day' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftDay(1)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftMonth(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.month' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftMonth(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <div class=\"layout-row place-between-center\">\n <button mat-icon-button (click)=\"svc.shiftYear(-1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.year' | translate }}</span>\n <button mat-icon-button (click)=\"svc.shiftYear(1, true)\" [disabled]=\"svc.isRangeNotSet()\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n\n @if (intervalInputMode === 'date-time-range') {\n <!-- shift minute -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.minute' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'minutes')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n <!-- shift hour -->\n <div class=\"layout-row place-between-center\">\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(-1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n <span>{{ 'intervalPicker.hour' | translate }}</span>\n <button\n mat-icon-button\n (click)=\"svc.shiftTime(1, 'hours')\"\n [disabled]=\"svc.isRangeNotSet()\"\n >\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #anchorInputField>\n <div class=\"layout-row flex-none gap-md\">\n <mat-menu #anchorMenu=\"matMenu\">\n @if (svc.startDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToEndDateTime()\"\n [disabled]=\"!svc.endDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">login</mat-icon>\n <span>{{ 'intervalPicker.endDate' | translate }}</span>\n </button>\n }\n @if (svc.endDate()) {\n <button\n mat-menu-item\n (click)=\"svc.setFixedAnchorPointToStartDateTime()\"\n [disabled]=\"!svc.startDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">logout</mat-icon>\n <span>{{ 'intervalPicker.startDate' | translate }}</span>\n </button>\n }\n @if (svc.fixedAnchorDate()) {\n <button\n mat-menu-item\n (click)=\"this.svc.resetFixedAnchorPoint()\"\n [disabled]=\"!svc.fixedAnchorDate() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n <span>{{ 'intervalPicker.clear' | translate }}</span>\n </button>\n }\n </mat-menu>\n\n <mat-form-field class=\"input-control-container\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorDate' | translate }}</mat-label>\n <elder-local-date-input\n name=\"anchorDateInput\"\n (valueUpdated)=\"svc.setAnchorDateFromForm($event)\"\n [value]=\"svc.getAnchorPointAsLocaleDate()\"\n [readonly]=\"isAnchorReadOnly\"\n >\n </elder-local-date-input>\n @if (!isAnchorReadOnly) {\n <button\n mat-icon-button\n matSuffix\n [matMenuTriggerFor]=\"anchorMenu\"\n [disabled]=\"svc.isStartAndEndDatesEmpty() && !svc.fixedAnchorDate()\"\n >\n <mat-icon class=\"material-symbols-outlined\">more_horiz</mat-icon>\n </button>\n }\n </mat-form-field>\n @if (intervalInputMode === 'date-time-range') {\n <mat-form-field class=\"input-control-container-short\" [subscriptSizing]=\"'dynamic'\">\n <mat-label>{{ 'intervalPicker.anchorTime' | translate }}</mat-label>\n <input\n matInput\n name=\"anchorTimeInput\"\n type=\"time\"\n #anchorTimeControl=\"ngModel\"\n step=\"1\"\n [readonly]=\"isAnchorReadOnly\"\n [ngModel]=\"svc.getAnchorTimeString()\"\n (ngModelChange)=\"svc.setAnchorTimeFromForm($event)\"\n />\n <button\n mat-icon-button\n matSuffix\n (click)=\"this.svc.resetFixedAnchorTime()\"\n [disabled]=\"!svc.isFixedAnchorTimeSetAndNotMidnight() || isAnchorReadOnly\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n }\n </div>\n</ng-template>\n", styles: [".interval-picker-component{min-width:840px;max-width:100%}.fixed-shifts-container{max-width:160px}.input-control-container{width:192px;max-width:100%}.input-control-container-short{width:140px;max-width:100%}.select-buttons-container button{white-space:nowrap;text-align:left;justify-content:flex-start}::ng-deep .interval-picker-component .mat-calendar-body-cell.elder-custom-anchor-date .mat-calendar-body-cell-content{border-radius:50%;background-color:#def;background-color:#b4d2ebbf}\n"] }]
|
|
230
231
|
}], ctorParameters: () => [{ type: i1.ElderIntervalPickerService }], propDecorators: { calendarStart: [{
|
|
231
232
|
type: ViewChild,
|
|
232
233
|
args: ['rangeCalendarStart']
|
|
@@ -257,7 +258,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.2", ngImpor
|
|
|
257
258
|
type: Input
|
|
258
259
|
}], isHelpTextsVisible: [{
|
|
259
260
|
type: Input
|
|
261
|
+
}], isSelectLastModeExcludingToday: [{
|
|
262
|
+
type: Input
|
|
260
263
|
}], dateChange: [{
|
|
261
264
|
type: Output
|
|
262
265
|
}] } });
|
|
263
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxNQUFNLEVBRU4sVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUE7QUFDdEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQTtBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDcEQsT0FBTyxFQUNMLFdBQVcsRUFFWCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixrQkFBa0IsR0FDbkIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNyQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhCQUE4QixDQUFBO0FBQ3BGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN0RCxPQUFPLEVBQUUs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WTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjO2dCQUVoQixrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFDRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0ksVUFBVTtzQkFBbkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbidcbmltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIGVmZmVjdCxcbiAgRWZmZWN0UmVmLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGlucHV0LFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJ1xuaW1wb3J0IHsgTWF0QnV0dG9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJ1xuaW1wb3J0IHsgRGF0ZUFkYXB0ZXIgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jb3JlJ1xuaW1wb3J0IHtcbiAgTWF0Q2FsZW5kYXIsXG4gIE1hdENhbGVuZGFyQ2VsbENsYXNzRnVuY3Rpb24sXG4gIE1hdERhdGVwaWNrZXJNb2R1bGUsXG4gIE1hdERhdGVwaWNrZXJUb2dnbGUsXG4gIE1hdERhdGVSYW5nZUlucHV0LFxuICBNYXREYXRlUmFuZ2VQaWNrZXIsXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RhdGVwaWNrZXInXG5pbXBvcnQgeyBNYXRGb3JtRmllbGRNb2R1bGUsIE1hdEhpbnQsIE1hdExhYmVsIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCdcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJ1xuaW1wb3J0IHsgTWF0SW5wdXRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCdcbmltcG9ydCB7IE1hdE1lbnVNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9tZW51J1xuaW1wb3J0IHsgTWF0VG9vbHRpcCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnXG5pbXBvcnQgeyBMb2dnZXJGYWN0b3J5IH0gZnJvbSAnQGVsZGVyYnl0ZS90cy1sb2dnZXInXG5pbXBvcnQgeyBUcmFuc2xhdGVNb2R1bGUgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJ1xuaW1wb3J0IHsgSW50ZXJ2YWwgfSBmcm9tICcuLi8uLi8uLi9jb21tb24vdGltZS9pbnRlcnZhbCdcbmltcG9ydCB7IFRlbXBvcmFsVXRpbCB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL3RlbXBvcmFsLXV0aWwnXG5pbXBvcnQgeyBDdXN0b21EYXRlQWRhcHRlciB9IGZyb20gJy4uLy4uLy4uL2NvbXBvbmVudHMvdGltZS9kYXRlLWFkYXB0ZXJzL2N1c3RvbS1kYXRlLWFkYXB0ZXInXG5pbXBvcnQgeyBJbnRlcnZhbElucHV0TW9kZSB9IGZyb20gJy4uLy4uLy4uL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1pbnB1dC9lbGRlci1pbnRlcnZhbC1pbnB1dC5jb21wb25lbnQnXG5pbXBvcnQgeyBFbGRlckxvY2FsRGF0ZUlucHV0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy90aW1lL2VsZGVyLWxvY2FsLWRhdGUtaW5wdXQvZWxkZXItbG9jYWwtZGF0ZS1pbnB1dC5jb21wb25lbnQnXG5pbXBvcnQgeyBFbGRlckludGVydmFsUGlja2VyU2VydmljZSB9IGZyb20gJy4vZWxkZXItaW50ZXJ2YWwtcGlja2VyLnNlcnZpY2UnXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2VsZGVyLWludGVydmFsLXBpY2tlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBNYXREYXRlUmFuZ2VQaWNrZXIsXG4gICAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgICBNYXREYXRlUmFuZ2VJbnB1dCxcbiAgICBNYXRGb3JtRmllbGRNb2R1bGUsXG4gICAgTWF0TGFiZWwsXG4gICAgTWF0SGludCxcbiAgICBNYXREYXRlcGlja2VyVG9nZ2xlLFxuICAgIE1hdElucHV0TW9kdWxlLFxuICAgIENvbW1vbk1vZHVsZSxcbiAgICBNYXRJY29uTW9kdWxlLFxuICAgIEZvcm1zTW9kdWxlLFxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcbiAgICBNYXRDYWxlbmRhcixcbiAgICBFbGRlckxvY2FsRGF0ZUlucHV0Q29tcG9uZW50LFxuICAgIE1hdFRvb2x0aXAsXG4gICAgVHJhbnNsYXRlTW9kdWxlLFxuICAgIE1hdE1lbnVNb2R1bGUsXG4gIF0sXG4gIHByb3ZpZGVyczogW0VsZGVySW50ZXJ2YWxQaWNrZXJTZXJ2aWNlLCB7IHByb3ZpZGU6IERhdGVBZGFwdGVyLCB1c2VDbGFzczogQ3VzdG9tRGF0ZUFkYXB0ZXIgfV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5zY3NzJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIEVsZGVySW50ZXJ2YWxQaWNrZXJDb21wb25lbnQge1xuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogRmllbGRzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZyA9IExvZ2dlckZhY3RvcnkuZ2V0TG9nZ2VyKHRoaXMuY29uc3RydWN0b3IubmFtZSlcbiAgcHVibGljIHJlYWRvbmx5IGNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm46IE1hdENhbGVuZGFyQ2VsbENsYXNzRnVuY3Rpb248RGF0ZT4gPSAoXG4gICAgY2VsbERhdGU6IERhdGUsXG4gICAgdmlldzogc3RyaW5nXG4gICk6IHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGbkJvZHkoY2VsbERhdGUsIHZpZXcpXG4gIH1cblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnKSBjYWxlbmRhclN0YXJ0ITogTWF0Q2FsZW5kYXI8RGF0ZT5cbiAgQFZpZXdDaGlsZCgncmFuZ2VDYWxlbmRhckVuZCcpIGNhbGVuZGFyRW5kITogTWF0Q2FsZW5kYXI8RGF0ZT5cblxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyU3RhcnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJTdGFydEVsUmVmITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJywgeyByZWFkOiBFbGVtZW50UmVmIH0pIGNhbGVuZGFyRW5kRWxSZWYhOiBFbGVtZW50UmVmXG5cbiAgQFZpZXdDaGlsZCgnc3RhcnREYXRlSW5wdXQnKSBzdGFydERhdGVJbnB1dCE6IEVsZW1lbnRSZWZcbiAgQFZpZXdDaGlsZCgnZW5kRGF0ZUlucHV0JykgZW5kRGF0ZUlucHV0ITogRWxlbWVudFJlZlxuXG4gIEBJbnB1dCgpIGlzRW1pdHRpbmdPbkNoYW5nZSA9IHRydWVcbiAgQElucHV0KCkgaW50ZXJ2YWxJbnB1dE1vZGU6IEludGVydmFsSW5wdXRNb2RlID0gJ2RhdGUtcmFuZ2UnXG4gIEBJbnB1dCgpIHNob3dBbmNob3IgPSBmYWxzZVxuICBASW5wdXQoKSBpc0FuY2hvclJlYWRPbmx5ID0gZmFsc2VcbiAgQElucHV0KCkgaXNSZXN1bHRUZXh0VmlzaWJsZSA9IHRydWVcbiAgQElucHV0KCkgaXNIZWxwVGV4dHNWaXNpYmxlID0gZmFsc2VcbiAgQE91dHB1dCgpIGRhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEludGVydmFsPigpXG4gIGlucHV0SW50ZXJ2YWwgPSBpbnB1dDxJbnRlcnZhbD4obnVsbClcbiAgaW5wdXRBbmNob3JEYXRlVGltZSA9IGlucHV0PERhdGU+KG51bGwpXG5cbiAgcHJpdmF0ZSBjYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXI6IChldmVudDogRm9jdXNFdmVudCkgPT4gdm9pZFxuXG4gIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiBDb25zdHJ1Y3RvciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzdmM6IEVsZGVySW50ZXJ2YWxQaWNrZXJTZXJ2aWNlKSB7XG4gICAgdGhpcy5zdmMuc2V0dXBJbnB1dEludGVydmFsKHRoaXMuaW5wdXRJbnRlcnZhbClcbiAgICB0aGlzLnN2Yy5zZXR1cElucHV0QW5jaG9yRGF0ZVRpbWUodGhpcy5pbnB1dEFuY2hvckRhdGVUaW1lKVxuICAgIHRoaXMuc3ZjLnNldHVwRXZlbnRFbWl0dGVyKHRoaXMuZGF0ZUNoYW5nZSlcbiAgfVxuXG4gIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiBMaWZlIEN5Y2xlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlucHV0SW50ZXJ2YWwpIHtcbiAgICAgIHRoaXMuc3ZjLnB1bGxJbnB1dEludGVydmFsKClcbiAgICB9XG4gICAgaWYgKHRoaXMuaW5wdXRBbmNob3JEYXRlVGltZSgpKSB7XG4gICAgICB0aGlzLnN2Yy5wdWxsSW5wdXRBbmNob3JEYXRlVGltZSgpXG4gICAgfVxuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmlzRW1pdHRpbmdPbkNoYW5nZS5zZXQodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpXG4gICAgdGhpcy5zZXR1cERhdGVJbnB1dENhbGVuZGFyRm9jdXNQcmV2ZW50aW9uKClcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIFB1YmxpYyBBUEkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgc2V0dXBEYXRlSW5wdXRDYWxlbmRhckZvY3VzUHJldmVudGlvbigpOiB2b2lkIHtcbiAgICAvLyBQcmV2ZW50cyB0aGUgZm9jdXMgb24gdGhlIGNhbGVuZGFyIHdoZW4gdGhlIGlucHV0IGZpZWxkIGlzIGNoYW5nZWQgdmlhIHRoZSBrZXlib2FyZFxuICAgIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyID0gKGV2ZW50OiBGb2N1c0V2ZW50KTogdm9pZCA9PiB7XG4gICAgICBpZiAoIWV2ZW50IHx8ICFldmVudC5yZWxhdGVkVGFyZ2V0KSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgICAgY29uc3QgcmVsVGFyZ2V0ID0gZXZlbnQucmVsYXRlZFRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50XG5cbiAgICAgIGlmIChyZWxUYXJnZXQubmFtZSA9PT0gJ3N0YXJ0RGF0ZUlucHV0Jykge1xuICAgICAgICB0aGlzLnN0YXJ0RGF0ZUlucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmIChyZWxUYXJnZXQubmFtZSA9PT0gJ2VuZERhdGVJbnB1dCcpIHtcbiAgICAgICAgdGhpcy5lbmREYXRlSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRTdGFydCA9IHRoaXMuY2FsZW5kYXJTdGFydEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcbiAgICBjb25zdCBuYXRpdmVFbGVtZW50RW5kID0gdGhpcy5jYWxlbmRhckVuZEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcblxuICAgIG5hdGl2ZUVsZW1lbnRTdGFydC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICAgIG5hdGl2ZUVsZW1lbnRFbmQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlciwgdHJ1ZSlcbiAgfVxuXG4gIGNsZWFyU3RhcnREYXRlVGltZSgpOiB2b2lkIHtcbiAgICB0aGlzLnN2Yy5jbGVhclN0YXJ0RGF0ZVRpbWUoKVxuXG4gICAgdGhpcy5zdmMucmVzZXRDYWxlbmRhck1vZGUoKVxuXG4gICAgaWYgKHRoaXMuaXNFbWl0dGluZ09uQ2hhbmdlKSB7XG4gICAgICB0aGlzLnN2Yy5lbWl0TWFpbkRhdGVzKClcbiAgICB9XG4gIH1cblxuICBjbGVhckVuZERhdGVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNsZWFyRW5kRGF0ZVRpbWUoKVxuXG4gICAgdGhpcy5zdmMucmVzZXRDYWxlbmRhck1vZGUoKVxuXG4gICAgaWYgKHRoaXMuaXNFbWl0dGluZ09uQ2hhbmdlKSB7XG4gICAgICB0aGlzLnN2Yy5lbWl0TWFpbkRhdGVzKClcbiAgICB9XG4gIH1cblxuICBjbGVhclN0YXJ0QW5kRW5kRGF0ZVRpbWVzKCk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNsZWFyU3RhcnREYXRlVGltZSgpXG4gICAgdGhpcy5zdmMuY2xlYXJFbmREYXRlVGltZSgpXG5cbiAgICB0aGlzLnN2Yy5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgIHRoaXMuc3ZjLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZVN0YXJ0Q2FsZW5kYXJDaGFuZ2UoY2hhbmdlZERhdGU6IERhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnN2Yy5jYWxlbmRhck1vZGUuc2V0KCdkYXlzJylcbiAgICBjb25zdCBuZXdQbGFpbkRhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0UGxhaW5EYXRlRnJvbUpTRGF0ZShjaGFuZ2VkRGF0ZSlcbiAgICB0aGlzLnN2Yy5zdGFydERhdGUuc2V0KG5ld1BsYWluRGF0ZSlcbiAgfVxuXG4gIGhhbmRsZUVuZENhbGVuZGFyQ2hhbmdlKGNoYW5nZWREYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuY2FsZW5kYXJNb2RlLnNldCgnZGF5cycpXG4gICAgY29uc3QgbmV3UGxhaW5EYXRlID0gVGVtcG9yYWxVdGlsLmdldFBsYWluRGF0ZUZyb21KU0RhdGUoY2hhbmdlZERhdGUpXG4gICAgdGhpcy5zdmMuZW5kRGF0ZS5zZXQobmV3UGxhaW5EYXRlKVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIFByaXZhdGUgbWV0aG9kcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgcHJpdmF0ZSByZW1vdmVFdmVudExpc3RlbmVycygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FsZW5kYXJTdGFydEVsUmVmIHx8ICF0aGlzLmNhbGVuZGFyRW5kRWxSZWYpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCB8fCAhdGhpcy5jYWxlbmRhckVuZEVsUmVmLm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRTdGFydCA9IHRoaXMuY2FsZW5kYXJTdGFydEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcbiAgICBjb25zdCBuYXRpdmVFbGVtZW50RW5kID0gdGhpcy5jYWxlbmRhckVuZEVsUmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnRcblxuICAgIG5hdGl2ZUVsZW1lbnRTdGFydC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICAgIG5hdGl2ZUVsZW1lbnRFbmQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlciwgdHJ1ZSlcbiAgfVxuXG4gIHByaXZhdGUgY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGbkJvZHkoY2VsbERhdGU6IERhdGUsIHZpZXc6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgYW5jaG9yRGF0ZSA9IHRoaXMuc3ZjLmZpeGVkQW5jaG9yRGF0ZSgpXG5cbiAgICBpZiAoIWFuY2hvckRhdGUpIHtcbiAgICAgIHJldHVybiAnJ1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0SlNEYXRlRnJvbVBsYWluRGF0ZVRpbWUoYW5jaG9yRGF0ZSlcblxuICAgIGlmICghZGF0ZSkge1xuICAgICAgcmV0dXJuICcnXG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgY2VsbERhdGUuZ2V0RGF0ZSgpID09PSBkYXRlLmdldERhdGUoKSAmJlxuICAgICAgY2VsbERhdGUuZ2V0TW9udGgoKSA9PT0gZGF0ZS5nZXRNb250aCgpICYmXG4gICAgICBjZWxsRGF0ZS5nZXRGdWxsWWVhcigpID09PSBkYXRlLmdldEZ1bGxZZWFyKClcbiAgICApIHtcbiAgICAgIHJldHVybiAnZWxkZXItY3VzdG9tLWFuY2hvci1kYXRlJ1xuICAgIH1cblxuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIEVmZmVjdHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgcHJpdmF0ZSByZWFkb25seSBfdXBkYXRlTWF0Q2FsZW5kYXJFbEFuY2hvckNzc0NsYXNzRWZmZWN0OiBFZmZlY3RSZWYgPSBlZmZlY3QoKCk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IGFuY2hvckRhdGUgPSB0aGlzLnN2Yy5hbmNob3JEYXRlKClcblxuICAgIGlmIChhbmNob3JEYXRlKSB7XG4gICAgICB0aGlzLmNhbGVuZGFyU3RhcnQudXBkYXRlVG9kYXlzRGF0ZSgpXG4gICAgICB0aGlzLmNhbGVuZGFyRW5kLnVwZGF0ZVRvZGF5c0RhdGUoKVxuICAgIH1cbiAgfSlcblxuICBwcml2YXRlIHJlYWRvbmx5IF91cGRhdGVNYXRDYWxlbmRhckVsU2VsZWN0aW9uRWZmZWN0OiBFZmZlY3RSZWYgPSBlZmZlY3QoKCk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHRoaXMuc3ZjLnN0YXJ0RGF0ZSgpXG4gICAgY29uc3QgZW5kRGF0ZSA9IHRoaXMuc3ZjLmVuZERhdGUoKVxuXG4gICAgaWYgKCF0aGlzLmNhbGVuZGFyU3RhcnQgfHwgIXRoaXMuY2FsZW5kYXJFbmQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghc3RhcnREYXRlICYmICFlbmREYXRlKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBjYWxlbmRhcjEgPSB0aGlzLmNhbGVuZGFyU3RhcnRcbiAgICBjb25zdCBjYWxlbmRhcjIgPSB0aGlzLmNhbGVuZGFyRW5kXG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIC8vIHRpbWVvdXQgaXMgbmVlZGVkIHRvIHJ1biBydW4gY2FsZW5kYXIgdXBkYXRlIGxhc3QsIG90aGVyd2lzZSB0aGVyZSBhcmUgaXNzdWVzXG4gICAgICBpZiAoc3RhcnREYXRlKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0SnNEYXRlID0gVGVtcG9yYWxVdGlsLmdldEpTRGF0ZUZyb21QbGFpbkRhdGVUaW1lKHN0YXJ0RGF0ZSlcbiAgICAgICAgY2FsZW5kYXIxLmFjdGl2ZURhdGUgPSBzdGFydEpzRGF0ZVxuICAgICAgfVxuXG4gICAgICBpZiAoZW5kRGF0ZSkge1xuICAgICAgICBjb25zdCBlbmRKc0RhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0SlNEYXRlRnJvbVBsYWluRGF0ZVRpbWUoZW5kRGF0ZSlcbiAgICAgICAgY2FsZW5kYXIyLmFjdGl2ZURhdGUgPSBlbmRKc0RhdGVcbiAgICAgIH1cbiAgICB9LCAwKVxuICB9KVxufVxuIiwiPGRpdiBjbGFzcz1cImludGVydmFsLXBpY2tlci1jb21wb25lbnQgcC1tZCBsYXlvdXQtY29sIGdhcC14eGxcIj5cbiAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgZ2FwLXh4bCBwbGFjZS1iZXR3ZWVuLXN0YXJ0XCIgc3R5bGU9XCJnYXA6IDUlXCI+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgZ2FwLW1kIHB0LXhzXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiaW50ZXJ2YWxTZWxlY3RvclwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sXCI+XG4gICAgICA8IS0tIHNtYXJ0IHNoaWZ0IC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYXJvdW5kLWNlbnRlclwiPlxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNtYXJ0U2hpZnQoLTEpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgc3ZjLnZpZXdJbnRlcnZhbE1lc3NhZ2UoKSB9fTwvc3Bhbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zbWFydFNoaWZ0KDEpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDwhLS0gY2FsZW5kYXJzIGFuZCBpbnB1dCBjb250cm9scyAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjYWxlbmRhcnNUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJwdC14c1wiIHN0eWxlPVwid2lkdGg6IDI1JVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgZ2FwLWxnXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC14cyBwbGFjZS1zdGFydC1zdGFydFwiPlxuICAgICAgICAgIEBpZiAoaXNIZWxwVGV4dHNWaXNpYmxlKSB7XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJtYXQtaDVcIj57eyAnaW50ZXJ2YWxQaWNrZXIuc2VsZWN0U21hcnRJbnRlcnZhbCcgfCB0cmFuc2xhdGUgfX08L2g1PlxuICAgICAgICAgIH1cbiAgICAgICAgICA8IS0tIHNlbGVjdCBjdXJyZW50IC0tPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdEN1cnJlbnRXZWVrKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLndlZWsnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudE1vbnRoKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLm1vbnRoJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdEN1cnJlbnRRdWFydGVyKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jdXJyZW50UGVyaW9kLnF1YXJ0ZXInIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudFllYXIoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QueWVhcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaXhlZC1zaGlmdHMtY29udGFpbmVyXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImZpeGVkU2hpZnRzXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlciBnYXAteHhsIHB0LXNtXCI+XG4gICAgPGRpdj5cbiAgICAgIEBpZiAoc2hvd0FuY2hvcikge1xuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYW5jaG9ySW5wdXRGaWVsZFwiPjwvbmctY29udGFpbmVyPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICAgIEBpZiAoaXNSZXN1bHRUZXh0VmlzaWJsZSkge1xuICAgICAgPCEtLSByZXN1bHQgaW50ZXJ2YWwgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBwbGFjZS1jZW50ZXItY2VudGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLWludGVydmFsIG1hdC1jYXB0aW9uIHB0LXhzXCI+XG4gICAgICAgICAgQGlmIChzdmMuc3RhcnREYXRlVGltZUFzSlNEYXRlKCkpIHtcbiAgICAgICAgICAgIHt7IHN2Yy5zdGFydERhdGVUaW1lQXNKU0RhdGUoKSB8IGRhdGU6ICdkZC5NTS4geSwgSEg6bW06c3MnIH19XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlTm90U2V0JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgICA8c3Bhbj4gLSA8L3NwYW4+XG4gICAgICAgICAgQGlmIChzdmMuZW5kRGF0ZVRpbWVBc0pTRGF0ZSgpKSB7XG4gICAgICAgICAgICB7eyBzdmMuZW5kRGF0ZVRpbWVBc0pTRGF0ZSgpIHwgZGF0ZTogJ2RkLk1NLiB5LCBISDptbTpzcycgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5lbmREYXRlTm90U2V0JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXY+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXQtY2FwdGlvblwiPnt7IHN2Yy5kZWx0YUh1bWFuUmVhZGFibGUoKSB8fCAnJm5ic3A7JyB9fTwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgZ2FwLWxnXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXG4gICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgIChjbGljayk9XCJjbGVhclN0YXJ0QW5kRW5kRGF0ZVRpbWVzKClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwic3ZjLmlzU3RhcnRBbmRFbmREYXRlc0VtcHR5KClcIlxuICAgICAgPlxuICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuY2xlYXInIHwgdHJhbnNsYXRlIH19XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgQGlmICghdGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgICAgPGJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiBtYXQtcmFpc2VkLWJ1dHRvbiAoY2xpY2spPVwic3ZjLmVtaXRNYWluRGF0ZXMoKVwiPlxuICAgICAgICAgIHt7ICdhY3Rpb25zLm9rJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNpbnRlcnZhbFNlbGVjdG9yPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbFwiPlxuICAgIEBpZiAoaXNIZWxwVGV4dHNWaXNpYmxlKSB7XG4gICAgICA8aDUgY2xhc3M9XCJtYXQtaDVcIj57eyAnaW50ZXJ2YWxQaWNrZXIuc2VsZWN0QWJzb2x1dGVJbnRlcnZhbCcgfCB0cmFuc2xhdGUgfX08L2g1PlxuICAgIH1cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBzZWxlY3QtYnV0dG9ucy1jb250YWluZXIgZ2FwLXNtXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAteHMgcGxhY2Utc3RhcnQtc3RyZXRjaFwiPlxuICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RDdXJyZW50RGF5KClcIj5cbiAgICAgICAgICBAaWYgKHN2Yy5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpKSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuYW5jaG9yRGF5JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLnRvZGF5JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdFllc3RlcmRheSgpXCI+XG4gICAgICAgICAgQGlmIChzdmMuaXNGaXhlZEFuY2hvckRhdGVTZXQoKSkge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDEge3sgJ2ludGVydmFsUGlja2VyLmRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci55ZXN0ZXJkYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdFNldmVuRGF5cygpXCI+XG4gICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDcge3sgJ2ludGVydmFsUGlja2VyLmRheXMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0VGhpcnR5RGF5cygpXCI+XG4gICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDMwIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgQGlmIChpbnRlcnZhbElucHV0TW9kZSA9PT0gJ2RhdGUtdGltZS1yYW5nZScpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicHQtc21cIj48L2Rpdj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0Rml2ZU1pbnV0ZXMoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDUge3sgJ2ludGVydmFsUGlja2VyLm1pbnV0ZXMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdEhvdXIoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IHt7ICdpbnRlcnZhbFBpY2tlci5ob3VyJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3QyNEhvdXJzKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSAyNCB7eyAnaW50ZXJ2YWxQaWNrZXIuaG91cnMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjY2FsZW5kYXJzVGVtcGxhdGU+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIiBzdHlsZT1cImFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0OyBtaW4taGVpZ2h0OiAyODBweFwiPlxuICAgIDxtYXQtY2FsZW5kYXJcbiAgICAgICNyYW5nZUNhbGVuZGFyU3RhcnRcbiAgICAgIHN0eWxlPVwid2lkdGg6IDIxMHB4OyBtYXgtd2lkdGg6IDEwMCVcIlxuICAgICAgW3NlbGVjdGVkXT1cInN2Yy5kYXRlUmFuZ2VGb3JDYWxlbmRhcigpXCJcbiAgICAgIChzZWxlY3RlZENoYW5nZSk9XCJoYW5kbGVTdGFydENhbGVuZGFyQ2hhbmdlKCRldmVudClcIlxuICAgICAgW21heERhdGVdPVwic3ZjLmVuZERhdGVBc0pTRGF0ZSgpXCJcbiAgICAgIFtkYXRlQ2xhc3NdPVwiY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGblwiXG4gICAgPlxuICAgIDwvbWF0LWNhbGVuZGFyPlxuICAgIDxtYXQtY2FsZW5kYXJcbiAgICAgICNyYW5nZUNhbGVuZGFyRW5kXG4gICAgICBzdHlsZT1cIndpZHRoOiAyMTBweDsgbWF4LXdpZHRoOiAxMDAlXCJcbiAgICAgIFtzZWxlY3RlZF09XCJzdmMuZGF0ZVJhbmdlRm9yQ2FsZW5kYXIoKVwiXG4gICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwiaGFuZGxlRW5kQ2FsZW5kYXJDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICBbbWluRGF0ZV09XCJzdmMuc3RhcnREYXRlQXNKU0RhdGUoKVwiXG4gICAgICBbZGF0ZUNsYXNzXT1cImNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm5cIlxuICAgID5cbiAgICA8L21hdC1jYWxlbmRhcj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXIgZ2FwLXhsIHB0LXNtXCI+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYXJvdW5kLWNlbnRlclwiPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgICNzdGFydERhdGVJbnB1dFxuICAgICAgICAgIG5hbWU9XCJzdGFydERhdGVJbnB1dFwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICB0eXBlPVwiZGF0ZVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwic3ZjLnN0YXJ0RGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldFN0YXJ0RGF0ZUZyb21IdG1sU3RyaW5nKCRldmVudClcIlxuICAgICAgICAvPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgKGNsaWNrKT1cInRoaXMuY2xlYXJTdGFydERhdGVUaW1lKClcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCIhdGhpcy5zdmMuc3RhcnREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuZW5kRGF0ZScgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgI2VuZERhdGVJbnB1dFxuICAgICAgICAgIG5hbWU9XCJlbmREYXRlSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5lbmREYXRlSHRtbFN0cmluZygpXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdmMuc2V0RW5kRGF0ZUZyb21IdG1sU3RyaW5nKCRldmVudClcIlxuICAgICAgICAvPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgKGNsaWNrKT1cInRoaXMuY2xlYXJFbmREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMuc3ZjLmVuZERhdGUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8YnIgLz5cbiAgQGlmIChpbnRlcnZhbElucHV0TW9kZSA9PT0gJ2RhdGUtdGltZS1yYW5nZScpIHtcbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5zdGFydFRpbWUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG5hbWU9XCJzdGFydFRpbWVJbnB1dFwiXG4gICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICB0eXBlPVwidGltZVwiXG4gICAgICAgICAgI3N0YXJ0VGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwic3ZjLmdldFN0YXJ0VGltZVN0cmluZygpXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdmMuc2V0U3RhcnRUaW1lRnJvbVN0cmluZygkZXZlbnQsIHN0YXJ0VGltZUNvbnRyb2wpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5jbGVhclN0YXJ0VGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMuc3ZjLmlzU3RhcnRUaW1lU2V0QW5kTm90TWlkbmlnaHQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmVuZFRpbWUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG5hbWU9XCJlbmRUaW1lSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cInRpbWVcIlxuICAgICAgICAgICNlbmRUaW1lQ29udHJvbD1cIm5nTW9kZWxcIlxuICAgICAgICAgIHN0ZXA9XCIxXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJzdmMuZ2V0RW5kVGltZVN0cmluZygpXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdmMuc2V0RW5kVGltZUZyb21TdHJpbmcoJGV2ZW50LCBlbmRUaW1lQ29udHJvbClcIlxuICAgICAgICAvPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgKGNsaWNrKT1cInRoaXMuc3ZjLmNsZWFyRW5kVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMuc3ZjLmlzRW5kVGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICB9XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2ZpeGVkU2hpZnRzPlxuICBAaWYgKGlzSGVscFRleHRzVmlzaWJsZSkge1xuICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zaGlmdEludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gIH1cbiAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgcGxhY2Utc3RhcnQtc3RyZXRjaFwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNoaWZ0RGF5KC0xKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5kYXknIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdERheSgxKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRNb250aCgtMSwgdHJ1ZSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIubW9udGgnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdE1vbnRoKDEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdFllYXIoLTEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLnllYXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdFllYXIoMSwgdHJ1ZSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuXG4gICAgQGlmIChpbnRlcnZhbElucHV0TW9kZSA9PT0gJ2RhdGUtdGltZS1yYW5nZScpIHtcbiAgICAgIDwhLS0gc2hpZnQgbWludXRlIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIChjbGljayk9XCJzdmMuc2hpZnRUaW1lKC0xLCAnbWludXRlcycpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLm1pbnV0ZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwic3ZjLnNoaWZ0VGltZSgxLCAnbWludXRlcycpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDwhLS0gc2hpZnQgaG91ciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwic3ZjLnNoaWZ0VGltZSgtMSwgJ2hvdXJzJylcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuaG91cicgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwic3ZjLnNoaWZ0VGltZSgxLCAnaG91cnMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjYW5jaG9ySW5wdXRGaWVsZD5cbiAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgZmxleC1ub25lIGdhcC1tZFwiPlxuICAgIDxtYXQtbWVudSAjYW5jaG9yTWVudT1cIm1hdE1lbnVcIj5cbiAgICAgIEBpZiAoc3ZjLnN0YXJ0RGF0ZSgpKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtbWVudS1pdGVtXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zZXRGaXhlZEFuY2hvclBvaW50VG9FbmREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXN2Yy5lbmREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPmxvZ2luPC9tYXQtaWNvbj5cbiAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuZW5kRGF0ZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChzdmMuZW5kRGF0ZSgpKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtbWVudS1pdGVtXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zZXRGaXhlZEFuY2hvclBvaW50VG9TdGFydERhdGVUaW1lKClcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCIhc3ZjLnN0YXJ0RGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5sb2dvdXQ8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIEBpZiAoc3ZjLmZpeGVkQW5jaG9yRGF0ZSgpKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtbWVudS1pdGVtXG4gICAgICAgICAgKGNsaWNrKT1cInRoaXMuc3ZjLnJlc2V0Rml4ZWRBbmNob3JQb2ludCgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXN2Yy5maXhlZEFuY2hvckRhdGUoKSB8fCBpc0FuY2hvclJlYWRPbmx5XCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmNsZWFyJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgPC9tYXQtbWVudT5cblxuICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmFuY2hvckRhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICA8ZWxkZXItbG9jYWwtZGF0ZS1pbnB1dFxuICAgICAgICBuYW1lPVwiYW5jaG9yRGF0ZUlucHV0XCJcbiAgICAgICAgKHZhbHVlVXBkYXRlZCk9XCJzdmMuc2V0QW5jaG9yRGF0ZUZyb21Gb3JtKCRldmVudClcIlxuICAgICAgICBbdmFsdWVdPVwic3ZjLmdldEFuY2hvclBvaW50QXNMb2NhbGVEYXRlKClcIlxuICAgICAgICBbcmVhZG9ubHldPVwiaXNBbmNob3JSZWFkT25seVwiXG4gICAgICA+XG4gICAgICA8L2VsZGVyLWxvY2FsLWRhdGUtaW5wdXQ+XG4gICAgICBAaWYgKCFpc0FuY2hvclJlYWRPbmx5KSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICBbbWF0TWVudVRyaWdnZXJGb3JdPVwiYW5jaG9yTWVudVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1N0YXJ0QW5kRW5kRGF0ZXNFbXB0eSgpICYmICFzdmMuZml4ZWRBbmNob3JEYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPm1vcmVfaG9yaXo8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lci1zaG9ydFwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmFuY2hvclRpbWUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgbmFtZT1cImFuY2hvclRpbWVJbnB1dFwiXG4gICAgICAgICAgdHlwZT1cInRpbWVcIlxuICAgICAgICAgICNhbmNob3JUaW1lQ29udHJvbD1cIm5nTW9kZWxcIlxuICAgICAgICAgIHN0ZXA9XCIxXCJcbiAgICAgICAgICBbcmVhZG9ubHldPVwiaXNBbmNob3JSZWFkT25seVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwic3ZjLmdldEFuY2hvclRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldEFuY2hvclRpbWVGcm9tRm9ybSgkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5yZXNldEZpeGVkQW5jaG9yVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXN2Yy5pc0ZpeGVkQW5jaG9yVGltZVNldEFuZE5vdE1pZG5pZ2h0KCkgfHwgaXNBbmNob3JSZWFkT25seVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=
|
|
266
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2VsZGVyYnl0ZS9uZ3gtc3RhcnRlci9zcmMvbGliL2NvbXBvbmVudHMvdGltZS9lbGRlci1pbnRlcnZhbC1waWNrZXIvZWxkZXItaW50ZXJ2YWwtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUM5QyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxNQUFNLEVBRU4sVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUE7QUFDdEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzVDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQTtBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDcEQsT0FBTyxFQUNMLFdBQVcsRUFFWCxtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixrQkFBa0IsR0FDbkIsTUFBTSw4QkFBOEIsQ0FBQTtBQUNyQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhCQUE4QixDQUFBO0FBQ3BGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBQ3RELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUE7QUFDcEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBRXJELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQTtBQUNqRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0REFBNEQsQ0FBQTtBQUU5RixPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxrRkFBa0YsQ0FBQTtBQUMvSCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQTs7Ozs7Ozs7Ozs7O0FBNkI1RSxNQUFNLE9BQU8sNEJBQTRCO0lBcUN2Qzs7OztnRkFJNEU7SUFFNUUsWUFBbUIsR0FBK0I7UUFBL0IsUUFBRyxHQUFILEdBQUcsQ0FBNEI7UUExQ2xEOzs7O29GQUk0RTtRQUUzRCxRQUFHLEdBQUcsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3JELGlDQUE0QixHQUF1QyxDQUNqRixRQUFjLEVBQ2QsSUFBWSxFQUNKLEVBQUU7WUFDVixPQUFPLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDOUQsQ0FBQyxDQUFBO1FBV1EsdUJBQWtCLEdBQUcsSUFBSSxDQUFBO1FBQ3pCLHNCQUFpQixHQUFzQixZQUFZLENBQUE7UUFDbkQsZUFBVSxHQUFHLEtBQUssQ0FBQTtRQUNsQixxQkFBZ0IsR0FBRyxLQUFLLENBQUE7UUFDeEIsd0JBQW1CLEdBQUcsSUFBSSxDQUFBO1FBQzFCLHVCQUFrQixHQUFHLEtBQUssQ0FBQTtRQUMxQixtQ0FBOEIsR0FBRyxLQUFLLENBQUE7UUFDckMsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFZLENBQUE7UUFDbkQsa0JBQWEsR0FBRyxLQUFLLENBQVcsSUFBSSxDQUFDLENBQUE7UUFDckMsd0JBQW1CLEdBQUcsS0FBSyxDQUFPLElBQUksQ0FBQyxDQUFBO1FBaUt2Qzs7OztvRkFJNEU7UUFFM0QsNkNBQXdDLEdBQWMsTUFBTSxDQUFDLEdBQVMsRUFBRTtZQUN2RixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFBO1lBRXhDLElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO2dCQUNyQyxJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDckMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFBO1FBRWUsd0NBQW1DLEdBQWMsTUFBTSxDQUFDLEdBQVMsRUFBRTtZQUNsRixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFBO1lBQ3RDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUE7WUFFbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQzdDLE9BQU07WUFDUixDQUFDO1lBRUQsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUMzQixPQUFNO1lBQ1IsQ0FBQztZQUVELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUE7WUFDcEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTtZQUVsQyxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNkLGdGQUFnRjtnQkFDaEYsSUFBSSxTQUFTLEVBQUUsQ0FBQztvQkFDZCxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUMsU0FBUyxDQUFDLENBQUE7b0JBQ3RFLFNBQVMsQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFBO2dCQUNwQyxDQUFDO2dCQUVELElBQUksT0FBTyxFQUFFLENBQUM7b0JBQ1osTUFBTSxTQUFTLEdBQUcsWUFBWSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFBO29CQUNsRSxTQUFTLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQTtnQkFDbEMsQ0FBQztZQUNILENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNQLENBQUMsQ0FBQyxDQUFBO1FBaE1BLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBQy9DLElBQUksQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUE7UUFDM0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDN0MsQ0FBQztJQUVEOzs7O2dGQUk0RTtJQUU1RSxRQUFRO1FBQ04sSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1FBQzlCLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLENBQUM7WUFDL0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsRUFBRSxDQUFBO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO1FBQ3hELElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxDQUFBO0lBQzlDLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUE7SUFDN0IsQ0FBQztJQUVEOzs7O2dGQUk0RTtJQUU1RSxxQ0FBcUM7UUFDbkMsc0ZBQXNGO1FBQ3RGLElBQUksQ0FBQywyQkFBMkIsR0FBRyxDQUFDLEtBQWlCLEVBQVEsRUFBRTtZQUM3RCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUNuQyxPQUFNO1lBQ1IsQ0FBQztZQUNELEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQTtZQUN0QixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsYUFBaUMsQ0FBQTtZQUV6RCxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztnQkFDeEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUE7Z0JBQ3pDLE9BQU07WUFDUixDQUFDO1lBQ0QsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO2dCQUN0QyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtnQkFDdkMsT0FBTTtZQUNSLENBQUM7UUFDSCxDQUFDLENBQUE7UUFFRCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUE0QixDQUFBO1FBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQTRCLENBQUE7UUFFM0Usa0JBQWtCLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUNwRixnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLDJCQUEyQixFQUFFLElBQUksQ0FBQyxDQUFBO0lBQ3BGLENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1FBRTdCLElBQUksQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtRQUU1QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxJQUFJLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUE7UUFFM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1FBRTVCLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVELHlCQUF5QjtRQUN2QixJQUFJLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLENBQUE7UUFDN0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1FBRTNCLElBQUksQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtRQUU1QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFFRCx5QkFBeUIsQ0FBQyxXQUFpQjtRQUN6QyxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDakMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ3JFLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUN0QyxDQUFDO0lBRUQsdUJBQXVCLENBQUMsV0FBaUI7UUFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ2pDLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUNyRSxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDcEMsQ0FBQztJQUVEOzs7O2dGQUk0RTtJQUVwRSxvQkFBb0I7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3ZELE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkYsT0FBTTtRQUNSLENBQUM7UUFFRCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUE0QixDQUFBO1FBQy9FLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGFBQTRCLENBQUE7UUFFM0Usa0JBQWtCLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUN2RixnQkFBZ0IsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLDJCQUEyQixFQUFFLElBQUksQ0FBQyxDQUFBO0lBQ3ZGLENBQUM7SUFFTyxnQ0FBZ0MsQ0FBQyxRQUFjLEVBQUUsSUFBWTtRQUNuRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxDQUFBO1FBRTdDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixPQUFPLEVBQUUsQ0FBQTtRQUNYLENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsMEJBQTBCLENBQUMsVUFBVSxDQUFDLENBQUE7UUFFaEUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsT0FBTyxFQUFFLENBQUE7UUFDWCxDQUFDO1FBRUQsSUFDRSxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNyQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUN2QyxRQUFRLENBQUMsV0FBVyxFQUFFLEtBQUssSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUM3QyxDQUFDO1lBQ0QsT0FBTywwQkFBMEIsQ0FBQTtRQUNuQyxDQUFDO1FBRUQsT0FBTyxFQUFFLENBQUE7SUFDWCxDQUFDOzhHQWhNVSw0QkFBNEI7a0dBQTVCLDRCQUE0QiwrZ0RBTDVCLENBQUMsMEJBQTBCLEVBQUUsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLHVVQXVCckQsVUFBVSwrR0FDWixVQUFVLCtOQ3BGbkQsMGpmQTBaQSxtaUJEL1dJLG1CQUFtQiwwYkFFbkIsa0JBQWtCLDJhQUlsQixjQUFjLDBXQUNkLFlBQVksd1BBQ1osYUFBYSxtTEFDYixXQUFXLDhtQkFDWCxlQUFlLHlVQUVmLDRCQUE0Qix3VUFFNUIsZUFBZSwyRkFDZixhQUFhOzsyRkFPSiw0QkFBNEI7a0JBM0J4QyxTQUFTOytCQUNFLHVCQUF1QixjQUNyQixJQUFJLFdBQ1A7d0JBQ1Asa0JBQWtCO3dCQUNsQixtQkFBbUI7d0JBQ25CLGlCQUFpQjt3QkFDakIsa0JBQWtCO3dCQUNsQixRQUFRO3dCQUNSLE9BQU87d0JBQ1AsbUJBQW1CO3dCQUNuQixjQUFjO3dCQUNkLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixXQUFXO3dCQUNYLGVBQWU7d0JBQ2YsV0FBVzt3QkFDWCw0QkFBNEI7d0JBQzVCLFVBQVU7d0JBQ1YsZUFBZTt3QkFDZixhQUFhO3FCQUNkLGFBQ1UsQ0FBQywwQkFBMEIsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLENBQUMsbUJBRzdFLHVCQUF1QixDQUFDLE1BQU07K0ZBaUJkLGFBQWE7c0JBQTdDLFNBQVM7dUJBQUMsb0JBQW9CO2dCQUNBLFdBQVc7c0JBQXpDLFNBQVM7dUJBQUMsa0JBQWtCO2dCQUUwQixrQkFBa0I7c0JBQXhFLFNBQVM7dUJBQUMsb0JBQW9CLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO2dCQUNBLGdCQUFnQjtzQkFBcEUsU0FBUzt1QkFBQyxrQkFBa0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBRXRCLGNBQWM7c0JBQTFDLFNBQVM7dUJBQUMsZ0JBQWdCO2dCQUNBLFlBQVk7c0JBQXRDLFNBQVM7dUJBQUMsY0FBYztnQkFFaEIsa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLDhCQUE4QjtzQkFBdEMsS0FBSztnQkFDSSxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJ1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgZWZmZWN0LFxuICBFZmZlY3RSZWYsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgaW5wdXQsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nXG5pbXBvcnQgeyBEYXRlQWRhcHRlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnXG5pbXBvcnQge1xuICBNYXRDYWxlbmRhcixcbiAgTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbixcbiAgTWF0RGF0ZXBpY2tlck1vZHVsZSxcbiAgTWF0RGF0ZXBpY2tlclRvZ2dsZSxcbiAgTWF0RGF0ZVJhbmdlSW5wdXQsXG4gIE1hdERhdGVSYW5nZVBpY2tlcixcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGF0ZXBpY2tlcidcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSwgTWF0SGludCwgTWF0TGFiZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJ1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0J1xuaW1wb3J0IHsgTWF0TWVudU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnXG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCdcbmltcG9ydCB7IExvZ2dlckZhY3RvcnkgfSBmcm9tICdAZWxkZXJieXRlL3RzLWxvZ2dlcidcbmltcG9ydCB7IFRyYW5zbGF0ZU1vZHVsZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnXG5pbXBvcnQgeyBJbnRlcnZhbCB9IGZyb20gJy4uLy4uLy4uL2NvbW1vbi90aW1lL2ludGVydmFsJ1xuaW1wb3J0IHsgVGVtcG9yYWxVdGlsIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL3RpbWUvdGVtcG9yYWwtdXRpbCdcbmltcG9ydCB7IEN1c3RvbURhdGVBZGFwdGVyIH0gZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy90aW1lL2RhdGUtYWRhcHRlcnMvY3VzdG9tLWRhdGUtYWRhcHRlcidcbmltcG9ydCB7IEludGVydmFsSW5wdXRNb2RlIH0gZnJvbSAnLi4vLi4vLi4vY29tcG9uZW50cy90aW1lL2VsZGVyLWludGVydmFsLWlucHV0L2VsZGVyLWludGVydmFsLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEVsZGVyTG9jYWxEYXRlSW5wdXRDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9jb21wb25lbnRzL3RpbWUvZWxkZXItbG9jYWwtZGF0ZS1pbnB1dC9lbGRlci1sb2NhbC1kYXRlLWlucHV0LmNvbXBvbmVudCdcbmltcG9ydCB7IEVsZGVySW50ZXJ2YWxQaWNrZXJTZXJ2aWNlIH0gZnJvbSAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuc2VydmljZSdcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZWxkZXItaW50ZXJ2YWwtcGlja2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIE1hdERhdGVSYW5nZVBpY2tlcixcbiAgICBNYXREYXRlcGlja2VyTW9kdWxlLFxuICAgIE1hdERhdGVSYW5nZUlucHV0LFxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcbiAgICBNYXRMYWJlbCxcbiAgICBNYXRIaW50LFxuICAgIE1hdERhdGVwaWNrZXJUb2dnbGUsXG4gICAgTWF0SW5wdXRNb2R1bGUsXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIE1hdEljb25Nb2R1bGUsXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgTWF0QnV0dG9uTW9kdWxlLFxuICAgIE1hdENhbGVuZGFyLFxuICAgIEVsZGVyTG9jYWxEYXRlSW5wdXRDb21wb25lbnQsXG4gICAgTWF0VG9vbHRpcCxcbiAgICBUcmFuc2xhdGVNb2R1bGUsXG4gICAgTWF0TWVudU1vZHVsZSxcbiAgXSxcbiAgcHJvdmlkZXJzOiBbRWxkZXJJbnRlcnZhbFBpY2tlclNlcnZpY2UsIHsgcHJvdmlkZTogRGF0ZUFkYXB0ZXIsIHVzZUNsYXNzOiBDdXN0b21EYXRlQWRhcHRlciB9XSxcbiAgdGVtcGxhdGVVcmw6ICcuL2VsZGVyLWludGVydmFsLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9lbGRlci1pbnRlcnZhbC1waWNrZXIuY29tcG9uZW50LnNjc3MnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRWxkZXJJbnRlcnZhbFBpY2tlckNvbXBvbmVudCB7XG4gIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiBGaWVsZHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nID0gTG9nZ2VyRmFjdG9yeS5nZXRMb2dnZXIodGhpcy5jb25zdHJ1Y3Rvci5uYW1lKVxuICBwdWJsaWMgcmVhZG9ubHkgY2FsZW5kYXJBbmNob3JEYXRlQ3NzQ2xhc3NGbjogTWF0Q2FsZW5kYXJDZWxsQ2xhc3NGdW5jdGlvbjxEYXRlPiA9IChcbiAgICBjZWxsRGF0ZTogRGF0ZSxcbiAgICB2aWV3OiBzdHJpbmdcbiAgKTogc3RyaW5nID0+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuQm9keShjZWxsRGF0ZSwgdmlldylcbiAgfVxuXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJTdGFydCcpIGNhbGVuZGFyU3RhcnQhOiBNYXRDYWxlbmRhcjxEYXRlPlxuICBAVmlld0NoaWxkKCdyYW5nZUNhbGVuZGFyRW5kJykgY2FsZW5kYXJFbmQhOiBNYXRDYWxlbmRhcjxEYXRlPlxuXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJTdGFydCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KSBjYWxlbmRhclN0YXJ0RWxSZWYhOiBFbGVtZW50UmVmXG4gIEBWaWV3Q2hpbGQoJ3JhbmdlQ2FsZW5kYXJFbmQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgY2FsZW5kYXJFbmRFbFJlZiE6IEVsZW1lbnRSZWZcblxuICBAVmlld0NoaWxkKCdzdGFydERhdGVJbnB1dCcpIHN0YXJ0RGF0ZUlucHV0ITogRWxlbWVudFJlZlxuICBAVmlld0NoaWxkKCdlbmREYXRlSW5wdXQnKSBlbmREYXRlSW5wdXQhOiBFbGVtZW50UmVmXG5cbiAgQElucHV0KCkgaXNFbWl0dGluZ09uQ2hhbmdlID0gdHJ1ZVxuICBASW5wdXQoKSBpbnRlcnZhbElucHV0TW9kZTogSW50ZXJ2YWxJbnB1dE1vZGUgPSAnZGF0ZS1yYW5nZSdcbiAgQElucHV0KCkgc2hvd0FuY2hvciA9IGZhbHNlXG4gIEBJbnB1dCgpIGlzQW5jaG9yUmVhZE9ubHkgPSBmYWxzZVxuICBASW5wdXQoKSBpc1Jlc3VsdFRleHRWaXNpYmxlID0gdHJ1ZVxuICBASW5wdXQoKSBpc0hlbHBUZXh0c1Zpc2libGUgPSBmYWxzZVxuICBASW5wdXQoKSBpc1NlbGVjdExhc3RNb2RlRXhjbHVkaW5nVG9kYXkgPSBmYWxzZVxuICBAT3V0cHV0KCkgZGF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8SW50ZXJ2YWw+KClcbiAgaW5wdXRJbnRlcnZhbCA9IGlucHV0PEludGVydmFsPihudWxsKVxuICBpbnB1dEFuY2hvckRhdGVUaW1lID0gaW5wdXQ8RGF0ZT4obnVsbClcblxuICBwcml2YXRlIGNhbGVuZGFyRWxGb2N1c0V2ZW50SGFuZGxlcjogKGV2ZW50OiBGb2N1c0V2ZW50KSA9PiB2b2lkXG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIENvbnN0cnVjdG9yICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgY29uc3RydWN0b3IocHVibGljIHN2YzogRWxkZXJJbnRlcnZhbFBpY2tlclNlcnZpY2UpIHtcbiAgICB0aGlzLnN2Yy5zZXR1cElucHV0SW50ZXJ2YWwodGhpcy5pbnB1dEludGVydmFsKVxuICAgIHRoaXMuc3ZjLnNldHVwSW5wdXRBbmNob3JEYXRlVGltZSh0aGlzLmlucHV0QW5jaG9yRGF0ZVRpbWUpXG4gICAgdGhpcy5zdmMuc2V0dXBFdmVudEVtaXR0ZXIodGhpcy5kYXRlQ2hhbmdlKVxuICB9XG5cbiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqIExpZmUgQ3ljbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW5wdXRJbnRlcnZhbCkge1xuICAgICAgdGhpcy5zdmMucHVsbElucHV0SW50ZXJ2YWwoKVxuICAgIH1cbiAgICBpZiAodGhpcy5pbnB1dEFuY2hvckRhdGVUaW1lKCkpIHtcbiAgICAgIHRoaXMuc3ZjLnB1bGxJbnB1dEFuY2hvckRhdGVUaW1lKClcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuaXNFbWl0dGluZ09uQ2hhbmdlLnNldCh0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSlcbiAgICB0aGlzLnNldHVwRGF0ZUlucHV0Q2FsZW5kYXJGb2N1c1ByZXZlbnRpb24oKVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVycygpXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogUHVibGljIEFQSSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBzZXR1cERhdGVJbnB1dENhbGVuZGFyRm9jdXNQcmV2ZW50aW9uKCk6IHZvaWQge1xuICAgIC8vIFByZXZlbnRzIHRoZSBmb2N1cyBvbiB0aGUgY2FsZW5kYXIgd2hlbiB0aGUgaW5wdXQgZmllbGQgaXMgY2hhbmdlZCB2aWEgdGhlIGtleWJvYXJkXG4gICAgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIgPSAoZXZlbnQ6IEZvY3VzRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LnJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICBjb25zdCByZWxUYXJnZXQgPSBldmVudC5yZWxhdGVkVGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnRcblxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnc3RhcnREYXRlSW5wdXQnKSB7XG4gICAgICAgIHRoaXMuc3RhcnREYXRlSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgaWYgKHJlbFRhcmdldC5uYW1lID09PSAnZW5kRGF0ZUlucHV0Jykge1xuICAgICAgICB0aGlzLmVuZERhdGVJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgY2xlYXJTdGFydERhdGVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNsZWFyU3RhcnREYXRlVGltZSgpXG5cbiAgICB0aGlzLnN2Yy5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgIHRoaXMuc3ZjLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIGNsZWFyRW5kRGF0ZVRpbWUoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuY2xlYXJFbmREYXRlVGltZSgpXG5cbiAgICB0aGlzLnN2Yy5yZXNldENhbGVuZGFyTW9kZSgpXG5cbiAgICBpZiAodGhpcy5pc0VtaXR0aW5nT25DaGFuZ2UpIHtcbiAgICAgIHRoaXMuc3ZjLmVtaXRNYWluRGF0ZXMoKVxuICAgIH1cbiAgfVxuXG4gIGNsZWFyU3RhcnRBbmRFbmREYXRlVGltZXMoKTogdm9pZCB7XG4gICAgdGhpcy5zdmMuY2xlYXJTdGFydERhdGVUaW1lKClcbiAgICB0aGlzLnN2Yy5jbGVhckVuZERhdGVUaW1lKClcblxuICAgIHRoaXMuc3ZjLnJlc2V0Q2FsZW5kYXJNb2RlKClcblxuICAgIGlmICh0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSkge1xuICAgICAgdGhpcy5zdmMuZW1pdE1haW5EYXRlcygpXG4gICAgfVxuICB9XG5cbiAgaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZShjaGFuZ2VkRGF0ZTogRGF0ZSk6IHZvaWQge1xuICAgIHRoaXMuc3ZjLmNhbGVuZGFyTW9kZS5zZXQoJ2RheXMnKVxuICAgIGNvbnN0IG5ld1BsYWluRGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRQbGFpbkRhdGVGcm9tSlNEYXRlKGNoYW5nZWREYXRlKVxuICAgIHRoaXMuc3ZjLnN0YXJ0RGF0ZS5zZXQobmV3UGxhaW5EYXRlKVxuICB9XG5cbiAgaGFuZGxlRW5kQ2FsZW5kYXJDaGFuZ2UoY2hhbmdlZERhdGU6IERhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnN2Yy5jYWxlbmRhck1vZGUuc2V0KCdkYXlzJylcbiAgICBjb25zdCBuZXdQbGFpbkRhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0UGxhaW5EYXRlRnJvbUpTRGF0ZShjaGFuZ2VkRGF0ZSlcbiAgICB0aGlzLnN2Yy5lbmREYXRlLnNldChuZXdQbGFpbkRhdGUpXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogUHJpdmF0ZSBtZXRob2RzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlbW92ZUV2ZW50TGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYgfHwgIXRoaXMuY2FsZW5kYXJFbmRFbFJlZikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNhbGVuZGFyU3RhcnRFbFJlZi5uYXRpdmVFbGVtZW50IHx8ICF0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3QgbmF0aXZlRWxlbWVudFN0YXJ0ID0gdGhpcy5jYWxlbmRhclN0YXJ0RWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgIGNvbnN0IG5hdGl2ZUVsZW1lbnRFbmQgPSB0aGlzLmNhbGVuZGFyRW5kRWxSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuXG4gICAgbmF0aXZlRWxlbWVudFN0YXJ0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5jYWxlbmRhckVsRm9jdXNFdmVudEhhbmRsZXIsIHRydWUpXG4gICAgbmF0aXZlRWxlbWVudEVuZC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuY2FsZW5kYXJFbEZvY3VzRXZlbnRIYW5kbGVyLCB0cnVlKVxuICB9XG5cbiAgcHJpdmF0ZSBjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuQm9keShjZWxsRGF0ZTogRGF0ZSwgdmlldzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBhbmNob3JEYXRlID0gdGhpcy5zdmMuZml4ZWRBbmNob3JEYXRlKClcblxuICAgIGlmICghYW5jaG9yRGF0ZSkge1xuICAgICAgcmV0dXJuICcnXG4gICAgfVxuXG4gICAgY29uc3QgZGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRKU0RhdGVGcm9tUGxhaW5EYXRlVGltZShhbmNob3JEYXRlKVxuXG4gICAgaWYgKCFkYXRlKSB7XG4gICAgICByZXR1cm4gJydcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBjZWxsRGF0ZS5nZXREYXRlKCkgPT09IGRhdGUuZ2V0RGF0ZSgpICYmXG4gICAgICBjZWxsRGF0ZS5nZXRNb250aCgpID09PSBkYXRlLmdldE1vbnRoKCkgJiZcbiAgICAgIGNlbGxEYXRlLmdldEZ1bGxZZWFyKCkgPT09IGRhdGUuZ2V0RnVsbFllYXIoKVxuICAgICkge1xuICAgICAgcmV0dXJuICdlbGRlci1jdXN0b20tYW5jaG9yLWRhdGUnXG4gICAgfVxuXG4gICAgcmV0dXJuICcnXG4gIH1cblxuICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAgICogRWZmZWN0cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICBwcml2YXRlIHJlYWRvbmx5IF91cGRhdGVNYXRDYWxlbmRhckVsQW5jaG9yQ3NzQ2xhc3NFZmZlY3Q6IEVmZmVjdFJlZiA9IGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgY29uc3QgYW5jaG9yRGF0ZSA9IHRoaXMuc3ZjLmFuY2hvckRhdGUoKVxuXG4gICAgaWYgKGFuY2hvckRhdGUpIHtcbiAgICAgIHRoaXMuY2FsZW5kYXJTdGFydC51cGRhdGVUb2RheXNEYXRlKClcbiAgICAgIHRoaXMuY2FsZW5kYXJFbmQudXBkYXRlVG9kYXlzRGF0ZSgpXG4gICAgfVxuICB9KVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3VwZGF0ZU1hdENhbGVuZGFyRWxTZWxlY3Rpb25FZmZlY3Q6IEVmZmVjdFJlZiA9IGVmZmVjdCgoKTogdm9pZCA9PiB7XG4gICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5zdmMuc3RhcnREYXRlKClcbiAgICBjb25zdCBlbmREYXRlID0gdGhpcy5zdmMuZW5kRGF0ZSgpXG5cbiAgICBpZiAoIXRoaXMuY2FsZW5kYXJTdGFydCB8fCAhdGhpcy5jYWxlbmRhckVuZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKCFzdGFydERhdGUgJiYgIWVuZERhdGUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IGNhbGVuZGFyMSA9IHRoaXMuY2FsZW5kYXJTdGFydFxuICAgIGNvbnN0IGNhbGVuZGFyMiA9IHRoaXMuY2FsZW5kYXJFbmRcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gdGltZW91dCBpcyBuZWVkZWQgdG8gcnVuIHJ1biBjYWxlbmRhciB1cGRhdGUgbGFzdCwgb3RoZXJ3aXNlIHRoZXJlIGFyZSBpc3N1ZXNcbiAgICAgIGlmIChzdGFydERhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRKc0RhdGUgPSBUZW1wb3JhbFV0aWwuZ2V0SlNEYXRlRnJvbVBsYWluRGF0ZVRpbWUoc3RhcnREYXRlKVxuICAgICAgICBjYWxlbmRhcjEuYWN0aXZlRGF0ZSA9IHN0YXJ0SnNEYXRlXG4gICAgICB9XG5cbiAgICAgIGlmIChlbmREYXRlKSB7XG4gICAgICAgIGNvbnN0IGVuZEpzRGF0ZSA9IFRlbXBvcmFsVXRpbC5nZXRKU0RhdGVGcm9tUGxhaW5EYXRlVGltZShlbmREYXRlKVxuICAgICAgICBjYWxlbmRhcjIuYWN0aXZlRGF0ZSA9IGVuZEpzRGF0ZVxuICAgICAgfVxuICAgIH0sIDApXG4gIH0pXG59XG4iLCI8ZGl2IGNsYXNzPVwiaW50ZXJ2YWwtcGlja2VyLWNvbXBvbmVudCBwLW1kIGxheW91dC1jb2wgZ2FwLXh4bFwiPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBnYXAteHhsIHBsYWNlLWJldHdlZW4tc3RhcnRcIiBzdHlsZT1cImdhcDogNSVcIj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAtbWQgcHQteHNcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJpbnRlcnZhbFNlbGVjdG9yXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2xcIj5cbiAgICAgIDwhLS0gc21hcnQgc2hpZnQgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc21hcnRTaGlmdCgtMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8c3Bhbj57eyBzdmMudmlld0ludGVydmFsTWVzc2FnZSgpIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNtYXJ0U2hpZnQoMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPCEtLSBjYWxlbmRhcnMgYW5kIGlucHV0IGNvbnRyb2xzIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNhbGVuZGFyc1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInB0LXhzXCIgc3R5bGU9XCJ3aWR0aDogMjUlXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LWNvbCBnYXAtbGdcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImxheW91dC1jb2wgZ2FwLXhzIHBsYWNlLXN0YXJ0LXN0YXJ0XCI+XG4gICAgICAgICAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICAgICAgICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zZWxlY3RTbWFydEludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgICAgICAgfVxuICAgICAgICAgIDwhLS0gc2VsZWN0IGN1cnJlbnQgLS0+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudFdlZWsoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2Qud2VlaycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RDdXJyZW50TW9udGgoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QubW9udGgnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0Q3VycmVudFF1YXJ0ZXIoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmN1cnJlbnRQZXJpb2QucXVhcnRlcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RDdXJyZW50WWVhcigpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIuY3VycmVudFBlcmlvZC55ZWFyJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZpeGVkLXNoaWZ0cy1jb250YWluZXJcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZml4ZWRTaGlmdHNcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyIGdhcC14eGwgcHQtc21cIj5cbiAgICA8ZGl2PlxuICAgICAgQGlmIChzaG93QW5jaG9yKSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhbmNob3JJbnB1dEZpZWxkXCI+PC9uZy1jb250YWluZXI+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgQGlmIChpc1Jlc3VsdFRleHRWaXNpYmxlKSB7XG4gICAgICA8IS0tIHJlc3VsdCBpbnRlcnZhbCAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIHBsYWNlLWNlbnRlci1jZW50ZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtaW50ZXJ2YWwgbWF0LWNhcHRpb24gcHQteHNcIj5cbiAgICAgICAgICBAaWYgKHN2Yy5zdGFydERhdGVUaW1lQXNKU0RhdGUoKSkge1xuICAgICAgICAgICAge3sgc3ZjLnN0YXJ0RGF0ZVRpbWVBc0pTRGF0ZSgpIHwgZGF0ZTogJ2RkLk1NLiB5LCBISDptbTpzcycgfX1cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5zdGFydERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICAgIDxzcGFuPiAtIDwvc3Bhbj5cbiAgICAgICAgICBAaWYgKHN2Yy5lbmREYXRlVGltZUFzSlNEYXRlKCkpIHtcbiAgICAgICAgICAgIHt7IHN2Yy5lbmREYXRlVGltZUFzSlNEYXRlKCkgfCBkYXRlOiAnZGQuTU0uIHksIEhIOm1tOnNzJyB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGVOb3RTZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdC1jYXB0aW9uXCI+e3sgc3ZjLmRlbHRhSHVtYW5SZWFkYWJsZSgpIHx8ICcmbmJzcDsnIH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBnYXAtbGdcIj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cbiAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgKGNsaWNrKT1cImNsZWFyU3RhcnRBbmRFbmREYXRlVGltZXMoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNTdGFydEFuZEVuZERhdGVzRW1wdHkoKVwiXG4gICAgICA+XG4gICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5jbGVhcicgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICBAaWYgKCF0aGlzLmlzRW1pdHRpbmdPbkNoYW5nZSkge1xuICAgICAgICA8YnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJzdmMuZW1pdE1haW5EYXRlcygpXCI+XG4gICAgICAgICAge3sgJ2FjdGlvbnMub2snIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI2ludGVydmFsU2VsZWN0b3I+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sXCI+XG4gICAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICAgIDxoNSBjbGFzcz1cIm1hdC1oNVwiPnt7ICdpbnRlcnZhbFBpY2tlci5zZWxlY3RBYnNvbHV0ZUludGVydmFsJyB8IHRyYW5zbGF0ZSB9fTwvaDU+XG4gICAgfVxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHNlbGVjdC1idXR0b25zLWNvbnRhaW5lciBnYXAtc21cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIGdhcC14cyBwbGFjZS1zdGFydC1zdHJldGNoXCI+XG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdEN1cnJlbnREYXkoKVwiPlxuICAgICAgICAgIEBpZiAoc3ZjLmlzRml4ZWRBbmNob3JEYXRlU2V0KCkpIHtcbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JEYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIudG9kYXknIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0WWVzdGVyZGF5KClcIj5cbiAgICAgICAgICBAaWYgKHN2Yy5pc0ZpeGVkQW5jaG9yRGF0ZVNldCgpKSB7XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMSB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLnllc3RlcmRheScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICB9XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICBAaWYgKGlzU2VsZWN0TGFzdE1vZGVFeGNsdWRpbmdUb2RheSkge1xuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RTZXZlbkRheXNFeGNsdWRpbmdUb2RheSgpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gNyB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5cycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0VGhpcnR5RGF5c0V4Y2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSAzMCB7eyAnaW50ZXJ2YWxQaWNrZXIuZGF5cycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdFNldmVuRGF5c0luY2x1ZGluZ1RvZGF5KClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSA3IHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RUaGlydHlEYXlzSW5jbHVkaW5nVG9kYXkoKVwiPlxuICAgICAgICAgICAge3sgJ2ludGVydmFsUGlja2VyLmxhc3QnIHwgdHJhbnNsYXRlIH19IDMwIHt7ICdpbnRlcnZhbFBpY2tlci5kYXlzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInB0LXNtXCI+PC9kaXY+XG4gICAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJzdmMuc2VsZWN0TGFzdEZpdmVNaW51dGVzKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSA1IHt7ICdpbnRlcnZhbFBpY2tlci5taW51dGVzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNlbGVjdExhc3RIb3VyKClcIj5cbiAgICAgICAgICAgIHt7ICdpbnRlcnZhbFBpY2tlci5sYXN0JyB8IHRyYW5zbGF0ZSB9fSB7eyAnaW50ZXJ2YWxQaWNrZXIuaG91cicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInN2Yy5zZWxlY3RMYXN0MjRIb3VycygpXCI+XG4gICAgICAgICAgICB7eyAnaW50ZXJ2YWxQaWNrZXIubGFzdCcgfCB0cmFuc2xhdGUgfX0gMjQge3sgJ2ludGVydmFsUGlja2VyLmhvdXJzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2NhbGVuZGFyc1RlbXBsYXRlPlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCIgc3R5bGU9XCJhbGlnbi1pdGVtczogZmxleC1zdGFydDsgbWluLWhlaWdodDogMjgwcHhcIj5cbiAgICA8bWF0LWNhbGVuZGFyXG4gICAgICAjcmFuZ2VDYWxlbmRhclN0YXJ0XG4gICAgICBzdHlsZT1cIndpZHRoOiAyMTBweDsgbWF4LXdpZHRoOiAxMDAlXCJcbiAgICAgIFtzZWxlY3RlZF09XCJzdmMuZGF0ZVJhbmdlRm9yQ2FsZW5kYXIoKVwiXG4gICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwiaGFuZGxlU3RhcnRDYWxlbmRhckNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIFttYXhEYXRlXT1cInN2Yy5lbmREYXRlQXNKU0RhdGUoKVwiXG4gICAgICBbZGF0ZUNsYXNzXT1cImNhbGVuZGFyQW5jaG9yRGF0ZUNzc0NsYXNzRm5cIlxuICAgID5cbiAgICA8L21hdC1jYWxlbmRhcj5cbiAgICA8bWF0LWNhbGVuZGFyXG4gICAgICAjcmFuZ2VDYWxlbmRhckVuZFxuICAgICAgc3R5bGU9XCJ3aWR0aDogMjEwcHg7IG1heC13aWR0aDogMTAwJVwiXG4gICAgICBbc2VsZWN0ZWRdPVwic3ZjLmRhdGVSYW5nZUZvckNhbGVuZGFyKClcIlxuICAgICAgKHNlbGVjdGVkQ2hhbmdlKT1cImhhbmRsZUVuZENhbGVuZGFyQ2hhbmdlKCRldmVudClcIlxuICAgICAgW21pbkRhdGVdPVwic3ZjLnN0YXJ0RGF0ZUFzSlNEYXRlKClcIlxuICAgICAgW2RhdGVDbGFzc109XCJjYWxlbmRhckFuY2hvckRhdGVDc3NDbGFzc0ZuXCJcbiAgICA+XG4gICAgPC9tYXQtY2FsZW5kYXI+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyIGdhcC14bCBwdC1zbVwiPlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWFyb3VuZC1jZW50ZXJcIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICAjc3RhcnREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwic3RhcnREYXRlSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cImRhdGVcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5zdGFydERhdGVIdG1sU3RyaW5nKClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN2Yy5zZXRTdGFydERhdGVGcm9tSHRtbFN0cmluZygkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLmNsZWFyU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRoaXMuc3ZjLnN0YXJ0RGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1hcm91bmQtY2VudGVyXCI+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgICNlbmREYXRlSW5wdXRcbiAgICAgICAgICBuYW1lPVwiZW5kRGF0ZUlucHV0XCJcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIHR5cGU9XCJkYXRlXCJcbiAgICAgICAgICBbbmdNb2RlbF09XCJzdmMuZW5kRGF0ZUh0bWxTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldEVuZERhdGVGcm9tSHRtbFN0cmluZygkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLmNsZWFyRW5kRGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5lbmREYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGJyIC8+XG4gIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYXJvdW5kLWNlbnRlciBnYXAteGwgcHQtc21cIj5cbiAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LWNvbnRyb2wtY29udGFpbmVyXCIgW3N1YnNjcmlwdFNpemluZ109XCInZHluYW1pYydcIj5cbiAgICAgICAgPG1hdC1sYWJlbD57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBuYW1lPVwic3RhcnRUaW1lSW5wdXRcIlxuICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgdHlwZT1cInRpbWVcIlxuICAgICAgICAgICNzdGFydFRpbWVDb250cm9sPVwibmdNb2RlbFwiXG4gICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5nZXRTdGFydFRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldFN0YXJ0VGltZUZyb21TdHJpbmcoJGV2ZW50LCBzdGFydFRpbWVDb250cm9sKVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5zdmMuY2xlYXJTdGFydFRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5pc1N0YXJ0VGltZVNldEFuZE5vdE1pZG5pZ2h0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXJcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5lbmRUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBuYW1lPVwiZW5kVGltZUlucHV0XCJcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAjZW5kVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW25nTW9kZWxdPVwic3ZjLmdldEVuZFRpbWVTdHJpbmcoKVwiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3ZjLnNldEVuZFRpbWVGcm9tU3RyaW5nKCRldmVudCwgZW5kVGltZUNvbnRyb2wpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5jbGVhckVuZFRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiF0aGlzLnN2Yy5pc0VuZFRpbWVTZXRBbmROb3RNaWRuaWdodCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgfVxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNmaXhlZFNoaWZ0cz5cbiAgQGlmIChpc0hlbHBUZXh0c1Zpc2libGUpIHtcbiAgICA8aDUgY2xhc3M9XCJtYXQtaDVcIj57eyAnaW50ZXJ2YWxQaWNrZXIuc2hpZnRJbnRlcnZhbCcgfCB0cmFuc2xhdGUgfX08L2g1PlxuICB9XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtY29sIHBsYWNlLXN0YXJ0LXN0cmV0Y2hcIj5cbiAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInN2Yy5zaGlmdERheSgtMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuZGF5JyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnREYXkoMSlcIiBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiPlxuICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X3JpZ2h0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwic3ZjLnNoaWZ0TW9udGgoLTEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLm1vbnRoJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRNb250aCgxLCB0cnVlKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImxheW91dC1yb3cgcGxhY2UtYmV0d2Vlbi1jZW50ZXJcIj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRZZWFyKC0xLCB0cnVlKVwiIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfbGVmdDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci55ZWFyJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJzdmMuc2hpZnRZZWFyKDEsIHRydWUpXCIgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cblxuICAgIEBpZiAoaW50ZXJ2YWxJbnB1dE1vZGUgPT09ICdkYXRlLXRpbWUtcmFuZ2UnKSB7XG4gICAgICA8IS0tIHNoaWZ0IG1pbnV0ZSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IHBsYWNlLWJldHdlZW4tY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAoY2xpY2spPVwic3ZjLnNoaWZ0VGltZSgtMSwgJ21pbnV0ZXMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19sZWZ0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5taW51dGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoMSwgJ21pbnV0ZXMnKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cInN2Yy5pc1JhbmdlTm90U2V0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmtleWJvYXJkX2RvdWJsZV9hcnJvd19yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIHNoaWZ0IGhvdXIgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwibGF5b3V0LXJvdyBwbGFjZS1iZXR3ZWVuLWNlbnRlclwiPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoLTEsICdob3VycycpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwic3ZjLmlzUmFuZ2VOb3RTZXQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+a2V5Ym9hcmRfZG91YmxlX2Fycm93X2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmhvdXInIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgKGNsaWNrKT1cInN2Yy5zaGlmdFRpbWUoMSwgJ2hvdXJzJylcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNSYW5nZU5vdFNldCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbj5rZXlib2FyZF9kb3VibGVfYXJyb3dfcmlnaHQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2FuY2hvcklucHV0RmllbGQ+XG4gIDxkaXYgY2xhc3M9XCJsYXlvdXQtcm93IGZsZXgtbm9uZSBnYXAtbWRcIj5cbiAgICA8bWF0LW1lbnUgI2FuY2hvck1lbnU9XCJtYXRNZW51XCI+XG4gICAgICBAaWYgKHN2Yy5zdGFydERhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJzdmMuc2V0Rml4ZWRBbmNob3JQb2ludFRvRW5kRGF0ZVRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuZW5kRGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5sb2dpbjwvbWF0LWljb24+XG4gICAgICAgICAgPHNwYW4+e3sgJ2ludGVydmFsUGlja2VyLmVuZERhdGUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIEBpZiAoc3ZjLmVuZERhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJzdmMuc2V0Rml4ZWRBbmNob3JQb2ludFRvU3RhcnREYXRlVGltZSgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIXN2Yy5zdGFydERhdGUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkXCI+bG9nb3V0PC9tYXQtaWNvbj5cbiAgICAgICAgICA8c3Bhbj57eyAnaW50ZXJ2YWxQaWNrZXIuc3RhcnREYXRlJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgICBAaWYgKHN2Yy5maXhlZEFuY2hvckRhdGUoKSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgIChjbGljayk9XCJ0aGlzLnN2Yy5yZXNldEZpeGVkQW5jaG9yUG9pbnQoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuZml4ZWRBbmNob3JEYXRlKCkgfHwgaXNBbmNob3JSZWFkT25seVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPnt7ICdpbnRlcnZhbFBpY2tlci5jbGVhcicgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvbWF0LW1lbnU+XG5cbiAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1jb250cm9sLWNvbnRhaW5lclwiIFtzdWJzY3JpcHRTaXppbmddPVwiJ2R5bmFtaWMnXCI+XG4gICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JEYXRlJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgPGVsZGVyLWxvY2FsLWRhdGUtaW5wdXRcbiAgICAgICAgbmFtZT1cImFuY2hvckRhdGVJbnB1dFwiXG4gICAgICAgICh2YWx1ZVVwZGF0ZWQpPVwic3ZjLnNldEFuY2hvckRhdGVGcm9tRm9ybSgkZXZlbnQpXCJcbiAgICAgICAgW3ZhbHVlXT1cInN2Yy5nZXRBbmNob3JQb2ludEFzTG9jYWxlRGF0ZSgpXCJcbiAgICAgICAgW3JlYWRvbmx5XT1cImlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgPlxuICAgICAgPC9lbGRlci1sb2NhbC1kYXRlLWlucHV0PlxuICAgICAgQGlmICghaXNBbmNob3JSZWFkT25seSkge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImFuY2hvck1lbnVcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzdmMuaXNTdGFydEFuZEVuZERhdGVzRW1wdHkoKSAmJiAhc3ZjLmZpeGVkQW5jaG9yRGF0ZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWRcIj5tb3JlX2hvcml6PC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICBAaWYgKGludGVydmFsSW5wdXRNb2RlID09PSAnZGF0ZS10aW1lLXJhbmdlJykge1xuICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtY29udHJvbC1jb250YWluZXItc2hvcnRcIiBbc3Vic2NyaXB0U2l6aW5nXT1cIidkeW5hbWljJ1wiPlxuICAgICAgICA8bWF0LWxhYmVsPnt7ICdpbnRlcnZhbFBpY2tlci5hbmNob3JUaW1lJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgIG5hbWU9XCJhbmNob3JUaW1lSW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJ0aW1lXCJcbiAgICAgICAgICAjYW5jaG9yVGltZUNvbnRyb2w9XCJuZ01vZGVsXCJcbiAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgW3JlYWRvbmx5XT1cImlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInN2Yy5nZXRBbmNob3JUaW1lU3RyaW5nKClcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN2Yy5zZXRBbmNob3JUaW1lRnJvbUZvcm0oJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgICAoY2xpY2spPVwidGhpcy5zdmMucmVzZXRGaXhlZEFuY2hvclRpbWUoKVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmMuaXNGaXhlZEFuY2hvclRpbWVTZXRBbmROb3RNaWRuaWdodCgpIHx8IGlzQW5jaG9yUmVhZE9ubHlcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgIH1cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19
|