UNPKG

ngx-mat-tui-calendar

Version:

Angular Material Design wrapper, supporting theming, for the Toast UI Calendar, suitable for web-based scheduling, events, appointments, and day planner applications.

147 lines 38.6 kB
import { Component, Inject } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { LocalDate } from '../local-date.js'; import * as i0 from "@angular/core"; import * as i1 from "@angular/material/dialog"; import * as i2 from "@angular/material/form-field"; import * as i3 from "@angular/material/radio"; import * as i4 from "@angular/material/datepicker"; import * as i5 from "@angular/material/divider"; import * as i6 from "@angular/material/button"; import * as i7 from "@angular/forms"; import * as i8 from "@angular/material/input"; import * as i9 from "@angular/common"; import * as i10 from "mat-timepicker"; export class NgxMatTuiCalendarEditorDialogComponent { constructor(data, dialogRef) { // console.log('NgxMatTuiCalendarEditorDialogComponent.constructor: schedule:', schedule); this.data = data; this.dialogRef = dialogRef; this.titleStr = ''; this.locationStr = ''; this.closed = false; this.isAllDay = false; this.themeClass = ''; // console.log('NgxMatTuiCalendarEditorDialogComponent.constructor: data:', data); this.color = data.darkMode ? 'accent' : 'primary'; const schedule = data.schedule; if (schedule == null) { this.id = null; } else { if (schedule.id) { this.id = schedule.id.toString(); } } this.titleStr = (schedule.title) ? schedule.title.toString() : ''; this.locationStr = (schedule.location) ? schedule.location.toString() : ''; this.isAllDay = (schedule.isAllDay == true); this.startDate = LocalDate.convertToJsDate(schedule.start); this.endDate = LocalDate.convertToJsDate(schedule.end); this.startTime = new Date(this.startDate); this.endTime = new Date(this.endDate); this.startDate.setHours(0, 0, 0, 1); this.endDate.setHours(0, 0, 0, 1); this.eventForm = new FormGroup({ title: new FormControl(this.titleStr), location: new FormControl(this.locationStr), scheduleType: new FormControl((schedule.isAllDay == true) ? "all-day" : "time-slot"), start: new FormControl(this.startDate), end: new FormControl(this.endDate), date: new FormControl(this.startDate), time1: new FormControl(this.startTime), time2: new FormControl(this.endTime, [Validators.required]), }, this.getDateValidator()); } getDateValidator() { const validator = (group) => { const scheduleType = group.get("scheduleType").value; if (group.get("scheduleType").value == "time-slot") { let time1 = group.get("time1").value; let time2 = group.get("time2").value; if (time1 >= time2) { return { dates: "End time must be later than the start time" }; } } return {}; }; return validator; } ngOnInit() { // console.dir(`Dialog config: ${this.dialogConfig}`); // let start: Date = (LocalDate.convertToJsDate(this.schedule.start)).toDate(); // let end: Date = (LocalDate.convertToJsDate(this.schedule.end)).toDate(); // this.eventForm.get("date").setValue(start); // this.eventForm.get("start").setValue(start); // this.eventForm.get("end").setValue(end); } onSave(form) { // console.log(`onSave form.invalid=${form.invalid}; this.closed=${this.closed} this.titleStr=${this.titleStr}`); if (form.invalid || this.closed) return; let schedule = this.data.schedule; schedule.title = this.eventForm.get("title").value; schedule.location = this.eventForm.get("location").value; schedule.isAllDay = this.isAllDay; schedule.category = this.isAllDay ? 'allday' : 'time'; // CATEGORY MUST BE DEFINED: 'milestone', 'task', allday', 'time' if (this.isAllDay) { schedule.start = LocalDate.convertToJsDate(this.eventForm.get("start").value); schedule.start.setHours(0, 0, 0, 1); schedule.end = LocalDate.convertToJsDate(this.eventForm.get("end").value); schedule.end.setHours(0, 0, 0, 1); } else { this.startTime = LocalDate.convertToJsDate(this.eventForm.get("time1").value); schedule.start = LocalDate.convertToJsDate(this.eventForm.get("date").value); schedule.start.setHours(this.startTime.getHours(), this.startTime.getMinutes(), this.startTime.getSeconds(), this.startTime.getMilliseconds()); this.endTime = LocalDate.convertToJsDate(this.eventForm.get("time2").value); schedule.end = LocalDate.convertToJsDate(this.eventForm.get("date").value); schedule.end.setHours(this.endTime.getHours(), this.endTime.getMinutes(), this.endTime.getSeconds(), this.endTime.getMilliseconds()); } // console.log(`pop-up-event-editor.component.ts: user clicked SAVE event=${schedule}`); // this.eventOutput.emit(schedule); form.resetForm(); this.closeMe(schedule); } onCancel() { // this.cancelled.emit(); // console.log('openPopupScheduleEditor: user clicked CANCEL'); this.closeMe(null); } onDelete() { // this.cancelled.emit(); // console.log('openPopupScheduleEditor: user clicked DELETE'); this.closeMe(this.data.schedule, true); } closeMe(schedule, performDelete) { // console.log('closeMe: The dialog is closing', schedule); this.closed = true; this.dialogRef.close({ schedule, performDelete: (performDelete == true) }); } log(str) { // console.warn(str); } onUseAllDay() { this.isAllDay = true; } onUseTimeSlot() { this.isAllDay = false; } } NgxMatTuiCalendarEditorDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.13", ngImport: i0, type: NgxMatTuiCalendarEditorDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component }); NgxMatTuiCalendarEditorDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.13", type: NgxMatTuiCalendarEditorDialogComponent, selector: "ngx-mat-tui-calendar-editor-dialog", ngImport: i0, template: "<div [className]=\"data.themeClass + ' ' + 'event-editor'\">\n <form id=\"my-form\" [formGroup]=\"eventForm\" class=\"event-editor-form\" (submit)=\"onSave(postForm);\" #postForm=\"ngForm\">\n <div class=\"grid-wrapper\">\n <div class=\"grid-title\">\n <mat-form-field [color]=\"color\" class=\"editor-title\">\n <input matInput type=\"text\" name=\"title\" formControlName=\"title\" placeholder=\"Title\">\n <!-- <mat-error style=\"height: fit-content;\" *ngIf=\"title.invalid\">Please enter a title (of 1 characters or more)\n for\n your event.</mat-error> -->\n </mat-form-field>\n </div>\n <div class=\"grid-location\">\n <mat-form-field [color]=\"color\" class=\"editor-location\">\n <input matInput type=\"location\" name=\"location\" formControlName=\"location\" placeholder=\"Location\">\n </mat-form-field>\n </div>\n <div class=\"grid-radios\" style=\"display: flex;\">\n <mat-radio-group [color]=\"color\" aria-label=\"Select an option\" style=\"margin-bottom: 1em;\" name=\"scheduleType\"\n formControlName=\"scheduleType\" required>\n <mat-radio-button value=\"all-day\" (change)=\"onUseAllDay()\" id=\"button-all-day\" [color]=\"color\" class=\"radio-button\">All Day\n </mat-radio-button>\n <mat-radio-button value=\"time-slot\" (change)=\"onUseTimeSlot()\" id=\"button-time-slot\" [color]=\"color\" class=\"radio-button\">Time Slot\n </mat-radio-button>\n </mat-radio-group>\n </div>\n <div class=\"grid-date\">\n <mat-form-field *ngIf=\"isAllDay\" [color]=\"color\" class=\"date-range-form-field\" appearance=\"fill\">\n <mat-label [color]=\"color\">Pick a Date Range</mat-label>\n <mat-date-range-input [color]=\"color\" [panelClass]=\"data.themeClass\" [rangePicker]=\"rangePicker\" #dateRangeInput>\n <input matStartDate placeholder=\"Start date\" formControlName=\"start\" name=\"start\">\n <input matEndDate placeholder=\"End date\" formControlName=\"end\" name=\"end\">\n </mat-date-range-input>\n <mat-datepicker-toggle [color]=\"color\" [panelClass]=\"data.themeClass\" matSuffix [for]=\"rangePicker\"></mat-datepicker-toggle>\n <mat-date-range-picker [color]=\"color\" class=\"picker\" #rangePicker></mat-date-range-picker>\n </mat-form-field>\n <mat-form-field [color]=\"color\" *ngIf=\"!isAllDay\" class=\"date-form-field\" appearance=\"fill\">\n <mat-label>Choose a date</mat-label>\n <input matInput [matDatepicker]=\"dpicker\" formControlName=\"date\" name=\"date\">\n <mat-datepicker-toggle [color]=\"color\" matSuffix [for]=\"dpicker\"></mat-datepicker-toggle>\n <mat-datepicker [color]=\"color\" #dpicker></mat-datepicker>\n </mat-form-field>\n </div>\n <div *ngIf=\"!isAllDay\" class=\"grid-time time-slot\">\n <mat-form-field [color]=\"color\" class=\"form-field-time\" appearance=\"fill\">\n <mat-label>Start</mat-label>\n <input matTimepicker [color]=\"color\" [strict]=\"false\" id=\"timepicker-start\" mode=\"12h\" formControlName=\"time1\" name=\"time1\"\n placeholder=\"Please select time...\">\n </mat-form-field>\n <mat-form-field [color]=\"color\" class=\"form-field-time\" appearance=\"fill\">\n <mat-label>End</mat-label>\n <input matTimepicker [color]=\"color\" [strict]=\"false\" id=\"timepicker-end\" mode=\"12h\" formControlName=\"time2\" name=\"time2\"\n placeholder=\"Please select time...\">\n </mat-form-field>\n </div>\n <div *ngIf=\"!isAllDay\" class=\"grid-error\">\n <label *ngIf=\"eventForm.invalid\">{{ eventForm.errors?.dates }}</label>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"editor-footer\">\n <button mat-raised-button [color]=\"color\" id=\"editor-submit-button\" type=\"submit\" style=\"margin-right: 4px;\">SAVE</button>\n <button mat-raised-button id=\"editor-delete-button\" type=\"button\" (click)=\"onDelete()\" *ngIf=\"(data.schedule.id!=null)\">DELETE</button>\n <button mat-raised-button id=\"editor-cancel-button\" type=\"button\" (click)=\"onCancel()\">CANCEL</button>\n </div>\n </form>\n </div>", styles: [".event-editor{padding:.25rem;margin-top:.25rem;max-width:425px}.grid-wrapper{display:grid;grid-template-columns:110px 290px;grid-template-rows:50px 50px 70px 70px 20px;grid-gap:2px;gap:2px}.grid-title{grid-column:1/3;grid-row:1}.grid-location{grid-column:1/3;grid-row:2}.grid-radios{grid-column:1;grid-row:3}.grid-date{grid-column:2;grid-row:3}.grid-time{grid-column:2;grid-row:4}.grid-error{grid-column:1/3;grid-row:5}.editor-title{width:100%;margin-bottom:auto}.editor-location{width:100%;margin-bottom:auto}.editor-footer{justify-self:right;align-self:center;margin-top:.5rem;height:40px}#editor-cancel-button{float:right}.date-range-form-field{width:290px}.date-form-field{width:290px}.time-slot{display:flex;flex-direction:row}.form-field-time{width:140px;padding:0;margin-right:10px}.form-field-time-wrapper{width:140px;padding:0 8px;margin-right:10px}.radio-button{width:120px;margin-top:10px;margin-bottom:10px;display:flex;flex-direction:row}.grid-error{color:red;font-size:.8rem}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "floatLabel", "appearance", "hideRequiredMarker", "hintLabel"], exportAs: ["matFormField"] }, { type: i3.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["separator", "comparisonStart", "comparisonEnd", "rangePicker", "required", "dateFilter", "min", "max", "disabled"], exportAs: ["matDateRangeInput"] }, { type: i4.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["tabIndex", "disabled", "for", "aria-label", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { type: i4.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i5.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { type: i6.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["id", "disabled", "required", "type", "value", "readonly", "placeholder", "errorStateMatcher", "aria-describedby"], exportAs: ["matInput"] }, { 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]" }, { type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i7.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i3.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }, { type: i7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.MatLabel, selector: "mat-label" }, { type: i4.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i4.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i2.MatSuffix, selector: "[matSuffix]" }, { type: i4.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i10.MatTimepickerDirective, selector: "input[matTimepicker]", inputs: ["okButtonTemplate", "cancelButtonTemplate", "okLabel", "cancelLabel", "anteMeridiemAbbreviation", "postMeridiemAbbreviation", "mode", "color", "disableDialogOpenOnClick", "strict", "value", "id", "errorStateMatcher", "disabled", "readonly", "required", "placeholder", "minDate", "maxDate"], outputs: ["timeChange", "invalidInput"], exportAs: ["matTimepicker"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.13", ngImport: i0, type: NgxMatTuiCalendarEditorDialogComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-mat-tui-calendar-editor-dialog', templateUrl: './ngx-mat-tui-calendar-editor-dialog.component.html', styleUrls: ['./ngx-mat-tui-calendar-editor-dialog.component.scss'] }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA] }] }, { type: i1.MatDialogRef }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdC10dWktY2FsZW5kYXItZWRpdG9yLWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0LXR1aS1jYWxlbmRhci9zcmMvbGliL25neC1tYXQtdHVpLWNhbGVuZGFyLWVkaXRvci1kaWFsb2cvbmd4LW1hdC10dWktY2FsZW5kYXItZWRpdG9yLWRpYWxvZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0LXR1aS1jYWxlbmRhci9zcmMvbGliL25neC1tYXQtdHVpLWNhbGVuZGFyLWVkaXRvci1kaWFsb2cvbmd4LW1hdC10dWktY2FsZW5kYXItZWRpdG9yLWRpYWxvZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUEyQixNQUFNLEVBQTRCLE1BQU0sZUFBZSxDQUFDO0FBQ3JHLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUF1QixVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RixPQUFPLEVBQWdCLGVBQWUsRUFBOEIsTUFBTSwwQkFBMEIsQ0FBQztBQUlyRyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7Ozs7Ozs7Ozs7OztBQVM3QyxNQUFNLE9BQU8sc0NBQXNDO0lBZWpELFlBQ2tDLElBQTJCLEVBQ3BELFNBQStEO1FBRXRFLDBGQUEwRjtRQUgxRCxTQUFJLEdBQUosSUFBSSxDQUF1QjtRQUNwRCxjQUFTLEdBQVQsU0FBUyxDQUFzRDtRQWZ4RSxhQUFRLEdBQVcsRUFBRSxDQUFDO1FBQ3RCLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLFdBQU0sR0FBWSxLQUFLLENBQUM7UUFPeEIsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUUxQixlQUFVLEdBQVcsRUFBRSxDQUFDO1FBUXRCLGtGQUFrRjtRQUNsRixJQUFJLENBQUMsS0FBSyxH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LENBQUM7SUFDeEIsQ0FBQzs7b0lBN0pVLHNDQUFzQyxrQkFnQnZDLGVBQWU7d0hBaEJkLHNDQUFzQywwRUNmbkQsKzNJQWlFUTs0RkRsREssc0NBQXNDO2tCQUxsRCxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxvQ0FBb0M7b0JBQzlDLFdBQVcsRUFBRSxxREFBcUQ7b0JBQ2xFLFNBQVMsRUFBRSxDQUFDLHFEQUFxRCxDQUFDO2lCQUNuRTs7MEJBaUJJLE1BQU07MkJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsIEluamVjdCwgSW5wdXQsIE9uSW5pdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBOZ0Zvcm0sIFZhbGlkYXRvckZuLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTWF0RGlhbG9nUmVmLCBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZywgTWF0RGlhbG9nQ29uZmlnIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcblxuaW1wb3J0IHsgRGF0ZVR5cGUsIGRlZmF1bHQgYXMgQ2FsZW5kYXIsIElFdmVudFNjaGVkdWxlT2JqZWN0LCBJU2NoZWR1bGUsIFRaRGF0ZSB9IGZyb20gJ3R1aS1jYWxlbmRhcic7XG5cbmltcG9ydCB7IExvY2FsRGF0ZSB9IGZyb20gJy4uL2xvY2FsLWRhdGUuanMnO1xuaW1wb3J0IHsgQ2FsZW5kYXJFZGl0b3JPcHRpb25zIH0gZnJvbSAnLi4vY2FsZW5kYXItZWRpdG9yLW9wdGlvbnMnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1tYXQtdHVpLWNhbGVuZGFyLWVkaXRvci1kaWFsb2cnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LW1hdC10dWktY2FsZW5kYXItZWRpdG9yLWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25neC1tYXQtdHVpLWNhbGVuZGFyLWVkaXRvci1kaWFsb2cuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hNYXRUdWlDYWxlbmRhckVkaXRvckRpYWxvZ0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgdGl0bGVTdHI6IHN0cmluZyA9ICcnO1xuICBsb2NhdGlvblN0cjogc3RyaW5nID0gJyc7XG4gIGNsb3NlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBldmVudEZvcm06IEZvcm1Hcm91cDtcbiAgZGF0ZTogRGF0ZTtcbiAgc3RhcnREYXRlOiBEYXRlO1xuICBlbmREYXRlOiBEYXRlO1xuICBzdGFydFRpbWU6IERhdGU7XG4gIGVuZFRpbWU6IERhdGU7XG4gIGlzQWxsRGF5OiBib29sZWFuID0gZmFsc2U7XG4gIGNvbG9yOiBzdHJpbmc7XG4gIHRoZW1lQ2xhc3M6IHN0cmluZyA9ICcnO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTUFUX0RJQUxPR19EQVRBKSBwdWJsaWMgZGF0YTogQ2FsZW5kYXJFZGl0b3JPcHRpb25zLFxuICAgIHB1YmxpYyBkaWFsb2dSZWY6IE1hdERpYWxvZ1JlZjxOZ3hNYXRUdWlDYWxlbmRhckVkaXRvckRpYWxvZ0NvbXBvbmVudD4sXG4gICkge1xuICAgIC8vIGNvbnNvbGUubG9nKCdOZ3hNYXRUdWlDYWxlbmRhckVkaXRvckRpYWxvZ0NvbXBvbmVudC5jb25zdHJ1Y3Rvcjogc2NoZWR1bGU6Jywgc2NoZWR1bGUpO1xuXG4gICAgLy8gY29uc29sZS5sb2coJ05neE1hdFR1aUNhbGVuZGFyRWRpdG9yRGlhbG9nQ29tcG9uZW50LmNvbnN0cnVjdG9yOiBkYXRhOicsIGRhdGEpO1xuICAgIHRoaXMuY29sb3IgPSBkYXRhLmRhcmtNb2RlID8gJ2FjY2VudCcgOiAncHJpbWFyeSc7XG5cbiAgICBjb25zdCBzY2hlZHVsZSA9IGRhdGEuc2NoZWR1bGU7XG4gICAgaWYgKHNjaGVkdWxlID09IG51bGwpIHtcbiAgICAgIHRoaXMuaWQgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoc2NoZWR1bGUuaWQpIHtcbiAgICAgICAgdGhpcy5pZCA9IHNjaGVkdWxlLmlkLnRvU3RyaW5nKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudGl0bGVTdHIgPSAoc2NoZWR1bGUudGl0bGUpID8gc2NoZWR1bGUudGl0bGUudG9TdHJpbmcoKSA6ICcnO1xuICAgIHRoaXMubG9jYXRpb25TdHIgPSAoc2NoZWR1bGUubG9jYXRpb24pID8gc2NoZWR1bGUubG9jYXRpb24udG9TdHJpbmcoKSA6ICcnO1xuXG5cbiAgICB0aGlzLmlzQWxsRGF5ID0gKHNjaGVkdWxlLmlzQWxsRGF5ID09IHRydWUpO1xuXG4gICAgdGhpcy5zdGFydERhdGUgPSBMb2NhbERhdGUuY29udmVydFRvSnNEYXRlKHNjaGVkdWxlLnN0YXJ0KSBhcyBEYXRlO1xuICAgIHRoaXMuZW5kRGF0ZSA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUoc2NoZWR1bGUuZW5kKSBhcyBEYXRlO1xuXG4gICAgdGhpcy5zdGFydFRpbWUgPSBuZXcgRGF0ZSh0aGlzLnN0YXJ0RGF0ZSk7XG4gICAgdGhpcy5lbmRUaW1lID0gbmV3IERhdGUodGhpcy5lbmREYXRlKTtcbiAgICB0aGlzLnN0YXJ0RGF0ZS5zZXRIb3VycygwLCAwLCAwLCAxKTtcbiAgICB0aGlzLmVuZERhdGUuc2V0SG91cnMoMCwgMCwgMCwgMSk7XG5cbiAgICB0aGlzLmV2ZW50Rm9ybSA9IG5ldyBGb3JtR3JvdXAoXG4gICAgICB7XG4gICAgICAgIHRpdGxlOiBuZXcgRm9ybUNvbnRyb2wodGhpcy50aXRsZVN0ciksXG4gICAgICAgIGxvY2F0aW9uOiBuZXcgRm9ybUNvbnRyb2wodGhpcy5sb2NhdGlvblN0ciksXG4gICAgICAgIHNjaGVkdWxlVHlwZTogbmV3IEZvcm1Db250cm9sKChzY2hlZHVsZS5pc0FsbERheSA9PSB0cnVlKSA/IFwiYWxsLWRheVwiIDogXCJ0aW1lLXNsb3RcIiksXG4gICAgICAgIHN0YXJ0OiBuZXcgRm9ybUNvbnRyb2wodGhpcy5zdGFydERhdGUpLFxuICAgICAgICBlbmQ6IG5ldyBGb3JtQ29udHJvbCh0aGlzLmVuZERhdGUpLFxuICAgICAgICBkYXRlOiBuZXcgRm9ybUNvbnRyb2wodGhpcy5zdGFydERhdGUpLFxuICAgICAgICB0aW1lMTogbmV3IEZvcm1Db250cm9sKHRoaXMuc3RhcnRUaW1lKSxcbiAgICAgICAgdGltZTI6IG5ldyBGb3JtQ29udHJvbCh0aGlzLmVuZFRpbWUsIFtWYWxpZGF0b3JzLnJlcXVpcmVkXSksXG4gICAgICB9LFxuICAgICAgdGhpcy5nZXREYXRlVmFsaWRhdG9yKCksXG4gICAgKTtcblxuICB9XG5cbiAgZ2V0RGF0ZVZhbGlkYXRvcigpIHtcbiAgICBjb25zdCB2YWxpZGF0b3I6IFZhbGlkYXRvckZuID0gKGdyb3VwOiBGb3JtR3JvdXApOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0+IHtcbiAgICAgIGNvbnN0IHNjaGVkdWxlVHlwZSA9IGdyb3VwLmdldChcInNjaGVkdWxlVHlwZVwiKS52YWx1ZTtcbiAgICAgIGlmIChncm91cC5nZXQoXCJzY2hlZHVsZVR5cGVcIikudmFsdWUgPT0gXCJ0aW1lLXNsb3RcIikge1xuICAgICAgICBsZXQgdGltZTEgPSBncm91cC5nZXQoXCJ0aW1lMVwiKS52YWx1ZTtcbiAgICAgICAgbGV0IHRpbWUyID0gZ3JvdXAuZ2V0KFwidGltZTJcIikudmFsdWU7XG4gICAgICAgIGlmICh0aW1lMSA+PSB0aW1lMikge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkYXRlczogXCJFbmQgdGltZSBtdXN0IGJlIGxhdGVyIHRoYW4gdGhlIHN0YXJ0IHRpbWVcIlxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7fTtcbiAgICB9O1xuICAgIHJldHVybiB2YWxpZGF0b3I7XG4gIH1cblxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIGNvbnNvbGUuZGlyKGBEaWFsb2cgY29uZmlnOiAke3RoaXMuZGlhbG9nQ29uZmlnfWApO1xuICAgIC8vIGxldCBzdGFydDogRGF0ZSA9IChMb2NhbERhdGUuY29udmVydFRvSnNEYXRlKHRoaXMuc2NoZWR1bGUuc3RhcnQpKS50b0RhdGUoKTtcbiAgICAvLyBsZXQgZW5kOiBEYXRlID0gKExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5zY2hlZHVsZS5lbmQpKS50b0RhdGUoKTtcbiAgICAvLyB0aGlzLmV2ZW50Rm9ybS5nZXQoXCJkYXRlXCIpLnNldFZhbHVlKHN0YXJ0KTtcbiAgICAvLyB0aGlzLmV2ZW50Rm9ybS5nZXQoXCJzdGFydFwiKS5zZXRWYWx1ZShzdGFydCk7XG4gICAgLy8gdGhpcy5ldmVudEZvcm0uZ2V0KFwiZW5kXCIpLnNldFZhbHVlKGVuZCk7XG5cbiAgfVxuXG5cblxuICBvblNhdmUoZm9ybTogTmdGb3JtKSB7XG4gICAgLy8gY29uc29sZS5sb2coYG9uU2F2ZSBmb3JtLmludmFsaWQ9JHtmb3JtLmludmFsaWR9OyB0aGlzLmNsb3NlZD0ke3RoaXMuY2xvc2VkfSB0aGlzLnRpdGxlU3RyPSR7dGhpcy50aXRsZVN0cn1gKTtcbiAgICBpZiAoZm9ybS5pbnZhbGlkIHx8IHRoaXMuY2xvc2VkKSByZXR1cm47XG4gICAgbGV0IHNjaGVkdWxlID0gdGhpcy5kYXRhLnNjaGVkdWxlO1xuICAgIHNjaGVkdWxlLnRpdGxlID0gdGhpcy5ldmVudEZvcm0uZ2V0KFwidGl0bGVcIikudmFsdWU7XG4gICAgc2NoZWR1bGUubG9jYXRpb24gPSB0aGlzLmV2ZW50Rm9ybS5nZXQoXCJsb2NhdGlvblwiKS52YWx1ZTtcbiAgICBzY2hlZHVsZS5pc0FsbERheSA9IHRoaXMuaXNBbGxEYXk7XG4gICAgc2NoZWR1bGUuY2F0ZWdvcnkgPSB0aGlzLmlzQWxsRGF5ID8gJ2FsbGRheScgOiAndGltZSc7ICAvLyBDQVRFR09SWSBNVVNUIEJFIERFRklORUQ6ICdtaWxlc3RvbmUnLCAndGFzaycsIGFsbGRheScsICd0aW1lJ1xuICAgIGlmICh0aGlzLmlzQWxsRGF5KSB7XG4gICAgICBzY2hlZHVsZS5zdGFydCA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5ldmVudEZvcm0uZ2V0KFwic3RhcnRcIikudmFsdWUpIGFzIERhdGU7XG4gICAgICBzY2hlZHVsZS5zdGFydC5zZXRIb3VycygwLCAwLCAwLCAxKTtcbiAgICAgIHNjaGVkdWxlLmVuZCA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5ldmVudEZvcm0uZ2V0KFwiZW5kXCIpLnZhbHVlKSBhcyBEYXRlO1xuICAgICAgc2NoZWR1bGUuZW5kLnNldEhvdXJzKDAsIDAsIDAsIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0YXJ0VGltZSA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5ldmVudEZvcm0uZ2V0KFwidGltZTFcIikudmFsdWUpIGFzIERhdGU7XG4gICAgICBzY2hlZHVsZS5zdGFydCA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5ldmVudEZvcm0uZ2V0KFwiZGF0ZVwiKS52YWx1ZSkgYXMgRGF0ZTtcbiAgICAgIHNjaGVkdWxlLnN0YXJ0LnNldEhvdXJzKFxuICAgICAgICB0aGlzLnN0YXJ0VGltZS5nZXRIb3VycygpLFxuICAgICAgICB0aGlzLnN0YXJ0VGltZS5nZXRNaW51dGVzKCksXG4gICAgICAgIHRoaXMuc3RhcnRUaW1lLmdldFNlY29uZHMoKSxcbiAgICAgICAgdGhpcy5zdGFydFRpbWUuZ2V0TWlsbGlzZWNvbmRzKCksXG4gICAgICApO1xuICAgICAgdGhpcy5lbmRUaW1lID0gTG9jYWxEYXRlLmNvbnZlcnRUb0pzRGF0ZSh0aGlzLmV2ZW50Rm9ybS5nZXQoXCJ0aW1lMlwiKS52YWx1ZSkgYXMgRGF0ZTtcbiAgICAgIHNjaGVkdWxlLmVuZCA9IExvY2FsRGF0ZS5jb252ZXJ0VG9Kc0RhdGUodGhpcy5ldmVudEZvcm0uZ2V0KFwiZGF0ZVwiKS52YWx1ZSkgYXMgRGF0ZTtcbiAgICAgIHNjaGVkdWxlLmVuZC5zZXRIb3VycyhcbiAgICAgICAgdGhpcy5lbmRUaW1lLmdldEhvdXJzKCksXG4gICAgICAgIHRoaXMuZW5kVGltZS5nZXRNaW51dGVzKCksXG4gICAgICAgIHRoaXMuZW5kVGltZS5nZXRTZWNvbmRzKCksXG4gICAgICAgIHRoaXMuZW5kVGltZS5nZXRNaWxsaXNlY29uZHMoKSxcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIGNvbnNvbGUubG9nKGBwb3AtdXAtZXZlbnQtZWRpdG9yLmNvbXBvbmVudC50czogdXNlciBjbGlja2VkIFNBVkUgZXZlbnQ9JHtzY2hlZHVsZX1gKTtcbiAgICAvLyB0aGlzLmV2ZW50T3V0cHV0LmVtaXQoc2NoZWR1bGUpO1xuICAgIGZvcm0ucmVzZXRGb3JtKCk7XG4gICAgdGhpcy5jbG9zZU1lKHNjaGVkdWxlKTtcbiAgfVxuXG4gIG9uQ2FuY2VsKCkge1xuICAgIC8vIHRoaXMuY2FuY2VsbGVkLmVtaXQoKTtcbiAgICAvLyBjb25zb2xlLmxvZygnb3BlblBvcHVwU2NoZWR1bGVFZGl0b3I6IHVzZXIgY2xpY2tlZCBDQU5DRUwnKTtcbiAgICB0aGlzLmNsb3NlTWUobnVsbCk7XG4gIH1cblxuICBvbkRlbGV0ZSgpIHtcbiAgICAvLyB0aGlzLmNhbmNlbGxlZC5lbWl0KCk7XG4gICAgLy8gY29uc29sZS5sb2coJ29wZW5Qb3B1cFNjaGVkdWxlRWRpdG9yOiB1c2VyIGNsaWNrZWQgREVMRVRFJyk7XG4gICAgdGhpcy5jbG9zZU1lKHRoaXMuZGF0YS5zY2hlZHVsZSwgdHJ1ZSk7XG4gIH1cblxuXG4gIGNsb3NlTWUoc2NoZWR1bGU6IElTY2hlZHVsZSwgcGVyZm9ybURlbGV0ZT86IGJvb2xlYW4pIHtcbiAgICAvLyBjb25zb2xlLmxvZygnY2xvc2VNZTogVGhlIGRpYWxvZyBpcyBjbG9zaW5nJywgc2NoZWR1bGUpO1xuICAgIHRoaXMuY2xvc2VkID0gdHJ1ZTtcbiAgICB0aGlzLmRpYWxvZ1JlZi5jbG9zZSh7IHNjaGVkdWxlLCBwZXJmb3JtRGVsZXRlOiAocGVyZm9ybURlbGV0ZSA9PSB0cnVlKSB9KTtcbiAgfVxuXG4gIGxvZyhzdHIpIHtcbiAgICAvLyBjb25zb2xlLndhcm4oc3RyKTtcbiAgfVxuXG4gIG9uVXNlQWxsRGF5KCkge1xuICAgIHRoaXMuaXNBbGxEYXkgPSB0cnVlO1xuICB9XG4gIG9uVXNlVGltZVNsb3QoKSB7XG4gICAgdGhpcy5pc0FsbERheSA9IGZhbHNlO1xuICB9XG5cbn1cbiIsIjxkaXYgW2NsYXNzTmFtZV09XCJkYXRhLnRoZW1lQ2xhc3MgKyAnICcgKyAnZXZlbnQtZWRpdG9yJ1wiPlxuICAgIDxmb3JtIGlkPVwibXktZm9ybVwiIFtmb3JtR3JvdXBdPVwiZXZlbnRGb3JtXCIgY2xhc3M9XCJldmVudC1lZGl0b3ItZm9ybVwiIChzdWJtaXQpPVwib25TYXZlKHBvc3RGb3JtKTtcIiAjcG9zdEZvcm09XCJuZ0Zvcm1cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJncmlkLXdyYXBwZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQtdGl0bGVcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW2NvbG9yXT1cImNvbG9yXCIgY2xhc3M9XCJlZGl0b3ItdGl0bGVcIj5cbiAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCB0eXBlPVwidGV4dFwiIG5hbWU9XCJ0aXRsZVwiIGZvcm1Db250cm9sTmFtZT1cInRpdGxlXCIgcGxhY2Vob2xkZXI9XCJUaXRsZVwiPlxuICAgICAgICAgICAgPCEtLSA8bWF0LWVycm9yIHN0eWxlPVwiaGVpZ2h0OiBmaXQtY29udGVudDtcIiAqbmdJZj1cInRpdGxlLmludmFsaWRcIj5QbGVhc2UgZW50ZXIgYSB0aXRsZSAob2YgMSBjaGFyYWN0ZXJzIG9yIG1vcmUpXG4gICAgICAgICAgICAgIGZvclxuICAgICAgICAgICAgICB5b3VyIGV2ZW50LjwvbWF0LWVycm9yPiAtLT5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQtbG9jYXRpb25cIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW2NvbG9yXT1cImNvbG9yXCIgY2xhc3M9XCJlZGl0b3ItbG9jYXRpb25cIj5cbiAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCB0eXBlPVwibG9jYXRpb25cIiBuYW1lPVwibG9jYXRpb25cIiBmb3JtQ29udHJvbE5hbWU9XCJsb2NhdGlvblwiIHBsYWNlaG9sZGVyPVwiTG9jYXRpb25cIj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQtcmFkaW9zXCIgc3R5bGU9XCJkaXNwbGF5OiBmbGV4O1wiPlxuICAgICAgICAgIDxtYXQtcmFkaW8tZ3JvdXAgW2NvbG9yXT1cImNvbG9yXCIgYXJpYS1sYWJlbD1cIlNlbGVjdCBhbiBvcHRpb25cIiAgc3R5bGU9XCJtYXJnaW4tYm90dG9tOiAxZW07XCIgbmFtZT1cInNjaGVkdWxlVHlwZVwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzY2hlZHVsZVR5cGVcIiByZXF1aXJlZD5cbiAgICAgICAgICAgIDxtYXQtcmFkaW8tYnV0dG9uIHZhbHVlPVwiYWxsLWRheVwiIChjaGFuZ2UpPVwib25Vc2VBbGxEYXkoKVwiIGlkPVwiYnV0dG9uLWFsbC1kYXlcIiBbY29sb3JdPVwiY29sb3JcIiBjbGFzcz1cInJhZGlvLWJ1dHRvblwiPkFsbCBEYXlcbiAgICAgICAgICAgIDwvbWF0LXJhZGlvLWJ1dHRvbj5cbiAgICAgICAgICAgIDxtYXQtcmFkaW8tYnV0dG9uIHZhbHVlPVwidGltZS1zbG90XCIgKGNoYW5nZSk9XCJvblVzZVRpbWVTbG90KClcIiBpZD1cImJ1dHRvbi10aW1lLXNsb3RcIiBbY29sb3JdPVwiY29sb3JcIiBjbGFzcz1cInJhZGlvLWJ1dHRvblwiPlRpbWUgU2xvdFxuICAgICAgICAgICAgPC9tYXQtcmFkaW8tYnV0dG9uPlxuICAgICAgICAgIDwvbWF0LXJhZGlvLWdyb3VwPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQtZGF0ZVwiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImlzQWxsRGF5XCIgW2NvbG9yXT1cImNvbG9yXCIgY2xhc3M9XCJkYXRlLXJhbmdlLWZvcm0tZmllbGRcIiBhcHBlYXJhbmNlPVwiZmlsbFwiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbCBbY29sb3JdPVwiY29sb3JcIj5QaWNrIGEgRGF0ZSBSYW5nZTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPG1hdC1kYXRlLXJhbmdlLWlucHV0IFtjb2xvcl09XCJjb2xvclwiIFtwYW5lbENsYXNzXT1cImRhdGEudGhlbWVDbGFzc1wiIFtyYW5nZVBpY2tlcl09XCJyYW5nZVBpY2tlclwiICNkYXRlUmFuZ2VJbnB1dD5cbiAgICAgICAgICAgICAgPGlucHV0IG1hdFN0YXJ0RGF0ZSBwbGFjZWhvbGRlcj1cIlN0YXJ0IGRhdGVcIiBmb3JtQ29udHJvbE5hbWU9XCJzdGFydFwiIG5hbWU9XCJzdGFydFwiPlxuICAgICAgICAgICAgICA8aW5wdXQgbWF0RW5kRGF0ZSBwbGFjZWhvbGRlcj1cIkVuZCBkYXRlXCIgZm9ybUNvbnRyb2xOYW1lPVwiZW5kXCIgbmFtZT1cImVuZFwiPlxuICAgICAgICAgICAgPC9tYXQtZGF0ZS1yYW5nZS1pbnB1dD5cbiAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyLXRvZ2dsZSBbY29sb3JdPVwiY29sb3JcIiBbcGFuZWxDbGFzc109XCJkYXRhLnRoZW1lQ2xhc3NcIiBtYXRTdWZmaXggW2Zvcl09XCJyYW5nZVBpY2tlclwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPlxuICAgICAgICAgICAgPG1hdC1kYXRlLXJhbmdlLXBpY2tlciBbY29sb3JdPVwiY29sb3JcIiBjbGFzcz1cInBpY2tlclwiICNyYW5nZVBpY2tlcj48L21hdC1kYXRlLXJhbmdlLXBpY2tlcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBbY29sb3JdPVwiY29sb3JcIiAqbmdJZj1cIiFpc0FsbERheVwiIGNsYXNzPVwiZGF0ZS1mb3JtLWZpZWxkXCIgYXBwZWFyYW5jZT1cImZpbGxcIj5cbiAgICAgICAgICAgIDxtYXQtbGFiZWw+Q2hvb3NlIGEgZGF0ZTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IFttYXREYXRlcGlja2VyXT1cImRwaWNrZXJcIiBmb3JtQ29udHJvbE5hbWU9XCJkYXRlXCIgbmFtZT1cImRhdGVcIj5cbiAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlci10b2dnbGUgW2NvbG9yXT1cImNvbG9yXCIgbWF0U3VmZml4IFtmb3JdPVwiZHBpY2tlclwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPlxuICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyIFtjb2xvcl09XCJjb2xvclwiICNkcGlja2VyPjwvbWF0LWRhdGVwaWNrZXI+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgKm5nSWY9XCIhaXNBbGxEYXlcIiBjbGFzcz1cImdyaWQtdGltZSB0aW1lLXNsb3RcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW2NvbG9yXT1cImNvbG9yXCIgY2xhc3M9XCJmb3JtLWZpZWxkLXRpbWVcIiBhcHBlYXJhbmNlPVwiZmlsbFwiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD5TdGFydDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgPGlucHV0IG1hdFRpbWVwaWNrZXIgW2NvbG9yXT1cImNvbG9yXCIgW3N0cmljdF09XCJmYWxzZVwiIGlkPVwidGltZXBpY2tlci1zdGFydFwiIG1vZGU9XCIxMmhcIiBmb3JtQ29udHJvbE5hbWU9XCJ0aW1lMVwiIG5hbWU9XCJ0aW1lMVwiXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiUGxlYXNlIHNlbGVjdCB0aW1lLi4uXCI+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgW2NvbG9yXT1cImNvbG9yXCIgY2xhc3M9XCJmb3JtLWZpZWxkLXRpbWVcIiBhcHBlYXJhbmNlPVwiZmlsbFwiPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD5FbmQ8L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCBtYXRUaW1lcGlja2VyIFtjb2xvcl09XCJjb2xvclwiIFtzdHJpY3RdPVwiZmFsc2VcIiBpZD1cInRpbWVwaWNrZXItZW5kXCIgbW9kZT1cIjEyaFwiIGZvcm1Db250cm9sTmFtZT1cInRpbWUyXCIgbmFtZT1cInRpbWUyXCJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJQbGVhc2Ugc2VsZWN0IHRpbWUuLi5cIj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIiFpc0FsbERheVwiIGNsYXNzPVwiZ3JpZC1lcnJvclwiPlxuICAgICAgICAgIDxsYWJlbCAqbmdJZj1cImV2ZW50Rm9ybS5pbnZhbGlkXCI+e3sgZXZlbnRGb3JtLmVycm9ycz8uZGF0ZXMgfX08L2xhYmVsPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPG1hdC1kaXZpZGVyPjwvbWF0LWRpdmlkZXI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZWRpdG9yLWZvb3RlclwiPlxuICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIFtjb2xvcl09XCJjb2xvclwiIGlkPVwiZWRpdG9yLXN1Ym1pdC1idXR0b25cIiB0eXBlPVwic3VibWl0XCIgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6IDRweDtcIj5TQVZFPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gaWQ9XCJlZGl0b3ItZGVsZXRlLWJ1dHRvblwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwib25EZWxldGUoKVwiICpuZ0lmPVwiKGRhdGEuc2NoZWR1bGUuaWQhPW51bGwpXCI+REVMRVRFPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gaWQ9XCJlZGl0b3ItY2FuY2VsLWJ1dHRvblwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwib25DYW5jZWwoKVwiPkNBTkNFTDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9mb3JtPlxuICA8L2Rpdj4iXX0=