@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
510 lines • 69.1 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, Injector } from '@angular/core';
import { DateTime } from '@microsoft/windows-admin-center-sdk/core/base/date/date-time';
import { DateType } from '@microsoft/windows-admin-center-sdk/core/base/date/date-type';
import { TimeUnit } from '@microsoft/windows-admin-center-sdk/core/base/date/time-unit';
import { Yield } from '@microsoft/windows-admin-center-sdk/core/base/decorators/yield.decorator';
import { KeyCode } from '@microsoft/windows-admin-center-sdk/core/data/accessibility-manager';
import { Globalization } from '@microsoft/windows-admin-center-sdk/core/data/globalization';
import { DateLikeFormFieldComponent } from '../date-like/date-like-form-field.component';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../../../tooltip/tooltip.directive";
import * as i3 from "../../validation-alert/validation-alert.component";
import * as i4 from "../../form-field-layout/form-field-layout.component";
const _c0 = ["type", "calendar"];
function CalendarFormFieldComponent_div_12_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 13);
i0.ɵɵtext(1);
i0.ɵɵelementEnd();
} if (rf & 2) {
const heading_r3 = ctx.$implicit;
i0.ɵɵadvance(1);
i0.ɵɵtextInterpolate(heading_r3);
} }
function CalendarFormFieldComponent_div_13_button_1_Template(rf, ctx) { if (rf & 1) {
const _r8 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "button", 15);
i0.ɵɵlistener("click", function CalendarFormFieldComponent_div_13_button_1_Template_button_click_0_listener() { const restoredCtx = i0.ɵɵrestoreView(_r8); const day_r6 = restoredCtx.$implicit; const ctx_r7 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r7.selectDay(day_r6.date)); })("keydown", function CalendarFormFieldComponent_div_13_button_1_Template_button_keydown_0_listener($event) { const restoredCtx = i0.ɵɵrestoreView(_r8); const day_r6 = restoredCtx.$implicit; const ctx_r9 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r9.onDayBlockKeyDown($event, day_r6)); });
i0.ɵɵtext(1);
i0.ɵɵelementEnd();
} if (rf & 2) {
const day_r6 = ctx.$implicit;
const ctx_r5 = i0.ɵɵnextContext(2);
i0.ɵɵclassProp("sme-selected", ctx_r5.isDaySelected(day_r6.date))("sme-calendar-block-today", day_r6.isToday)("sme-calendar-block-other-month", !day_r6.isCurrentMonth);
i0.ɵɵattribute("data-timestamp", day_r6.timestamp)("aria-label", ctx_r5.convertDateToScreenReaderFormat(day_r6.date))("aria-pressed", ctx_r5.isDaySelected(day_r6.date));
i0.ɵɵadvance(1);
i0.ɵɵtextInterpolate1(" ", day_r6.date.getDate(), " ");
} }
function CalendarFormFieldComponent_div_13_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 9);
i0.ɵɵtemplate(1, CalendarFormFieldComponent_div_13_button_1_Template, 2, 10, "button", 14);
i0.ɵɵelementEnd();
} if (rf & 2) {
const week_r4 = ctx.$implicit;
i0.ɵɵadvance(1);
i0.ɵɵproperty("ngForOf", week_r4);
} }
function CalendarFormFieldComponent_sme_validation_alert_14_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelement(0, "sme-validation-alert", 16);
} if (rf & 2) {
const ctx_r2 = i0.ɵɵnextContext();
i0.ɵɵproperty("alert", ctx_r2.alert);
} }
/**
* Calendar Form Field Component
*/
export class CalendarFormFieldComponent extends DateLikeFormFieldComponent {
/**
* Initializes a new instance of the @see CalendarFormFieldComponent class.
* @param injector The angular injection service. required by @see SmeInjectableBase decorator in the @see BaseComponent class
*/
constructor(injector) {
super(injector);
this.currentYear = this.now.getFullYear();
this.currentMonth = this.now.getMonth();
this.dayBlocks = [];
this.dayHeadings = [
this.strings.MsftSmeShell.Angular.Calendar.Heading.Sunday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Monday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Tuesday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Wednesday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Thursday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Friday,
this.strings.MsftSmeShell.Angular.Calendar.Heading.Saturday
];
this.daysOfWeek = [
this.strings.MsftSmeShell.Angular.Calendar.Day.Sunday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Monday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Tuesday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Wednesday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Thursday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Friday,
this.strings.MsftSmeShell.Angular.Calendar.Day.Saturday
];
}
/**
* The source name to use for logging
*/
get logSourceName() {
return 'CalendarFormFieldComponent';
}
/**
* Gets the selected year
*/
get selectedYear() {
return this.selectedDate ? this.selectedDate.getFullYear() : null;
}
/**
* Gets the selected month
*/
get selectedMonth() {
return this.selectedDate ? this.selectedDate.getMonth() : null;
}
/**
* Gets the text for the currently viewed month
*/
get headerText() {
const monthText = this.strings.MsftSmeShell.Angular.Calendar.Month[this.currentMonth + 1];
const yearText = this.currentYear.toString();
return `${monthText} ${yearText}`;
}
/**
* Gets a value indicating if the current view contains today's date
*/
get isTodayInView() {
return this.nowYear === this.currentYear && this.nowMonth === this.currentMonth;
}
/**
* Gets a value indicating if the current view contains today's date
*/
get isSelectionInView() {
return this.nowYear === this.currentYear && this.nowMonth === this.currentMonth;
}
/**
* A workaround to have Screen reader know this is a required "input" field.
*/
get ariaLabel() {
if (this.required) {
return this.strings.MsftSmeShell.Angular.Calendar.AriaLabel.Required.format(this.label);
}
return this.label;
}
/**
* Implementation of angular OnInit interface
*/
ngOnInit() {
super.ngOnInit();
this.generateDayBlocks();
}
/**
* Occurs when the previous month button has been clicked
*/
onPreviousClicked(event) {
event.preventDefault();
event.stopPropagation();
this.goToPreviousMonth();
}
/**
* Occurs when the next month button has been clicked
*/
onNextClicked(event) {
event.preventDefault();
event.stopPropagation();
this.goToNextMonth();
}
/**
* Occurs when the go to today button has been clicked
*/
onGoToTodayClicked(event) {
event.preventDefault();
event.stopPropagation();
this.goToToday();
this.yieldFocus();
}
/**
* Changes the current view to include the previous month
*/
goToPreviousMonth() {
this.currentMonth--;
if (this.currentMonth < 0) {
this.currentMonth = 11;
this.currentYear--;
}
this.generateDayBlocks();
}
/**
* Changes the current view to include the previous month
*/
goToNextMonth() {
this.currentMonth++;
if (this.currentMonth >= 12) {
this.currentMonth = 0;
this.currentYear++;
}
this.generateDayBlocks();
}
/**
* Selects a day in the calander
*/
selectDay(day) {
const newDate = DateType.convert(day, DateType.Date);
this.selectedDate = newDate;
this.value = DateType.convert(newDate, MsftSme.isNullOrUndefined(this.dateType) ? this.detectedDateType : this.dateType);
}
/**
* Indicates if a given day is selected
*/
isDaySelected(day) {
return DateTime.isEqualDates(day, this.selectedDate);
}
/**
* Applies the focus to the current element
*/
focus() {
const element = this.hostElement.nativeElement.querySelector('.sme-calendar-block.sme-selected, .sme-calendar-block.sme-calendar-block-today');
if (element) {
element.focus();
return;
}
super.focus();
}
yieldFocus() {
this.focus();
}
/**
* Brings today into view
*/
goToToday() {
if (!this.isTodayInView) {
this.goTo(this.nowYear, this.nowMonth);
}
}
/**
* Brings selected date into view
*/
goToSelection() {
if (!this.isSelectionInView) {
this.goTo(this.selectedYear, this.selectedMonth);
}
}
/**
* Brings a month and year into view
*/
goTo(year, month) {
this.currentYear = year;
this.currentMonth = month;
this.generateDayBlocks();
}
/**
* Handles keydown events on dat blocks
*/
onDayBlockKeyDown(event, day) {
let goToDate;
switch (event.keyCode) {
case KeyCode.UpArrow: {
// go back one week
goToDate = new Date(day.date);
goToDate.setDate(goToDate.getDate() - 7);
break;
}
case KeyCode.DownArrow: {
// go forward one week
goToDate = new Date(day.date);
goToDate.setDate(goToDate.getDate() + 7);
break;
}
case KeyCode.LeftArrow: {
// go back one Day
goToDate = new Date(day.date);
goToDate.setDate(goToDate.getDate() - 1);
break;
}
case KeyCode.RightArrow: {
// go forward one Day
goToDate = new Date(day.date);
goToDate.setDate(goToDate.getDate() + 1);
break;
}
case KeyCode.Home: {
if (event.ctrlKey) {
// go to beginning of current month
goToDate = new Date(day.date);
goToDate.setDate(1);
}
else {
// go to beginning of current week
const currentWeekDay = day.date.getDay();
goToDate = new Date(day.timestamp - (TimeUnit.Day * currentWeekDay));
}
break;
}
case KeyCode.End: {
if (event.ctrlKey) {
// go to end of current month
goToDate = new Date(day.date);
// go to first day of current month (avoid ase were day is > 28 and the next month is Feb.)
goToDate.setDate(1);
// go to next month
goToDate.setMonth(goToDate.getMonth() + 1);
// go back one day
goToDate.setDate(0);
}
else {
// go to end of current week
const currentWeekDay = day.date.getDay();
const daysLeftInWeek = 6 - currentWeekDay;
goToDate = new Date(day.timestamp + (TimeUnit.Day * daysLeftInWeek));
}
break;
}
case KeyCode.PageUp: {
// go to previous month
goToDate = new Date(day.date);
goToDate.setMonth(goToDate.getMonth() - 1);
break;
}
case KeyCode.PageDown: {
// go to next month
goToDate = new Date(day.date);
goToDate.setMonth(goToDate.getMonth() + 1);
break;
}
default: {
return;
}
}
if (MsftSme.isNullOrUndefined(goToDate)) {
return;
}
this.focusOnDate(goToDate);
// handle all keys
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
}
/**
* Occurs every time the value of the control changes, in the UI or programmatically.
* @param value the value of the form control
*/
onValueChanged(value) {
this.selectedDate = value ? DateType.convert(value, DateType.Date) : new Date();
super.onValueChanged(this.selectedDate);
}
/**
* Performs validation that is internal to this control
* @param c The form control attached to this instance
*/
validate(c) {
return this.validateAsDate(c) || super.validate(c);
}
/**
* Generates the current view of day blocks
*/
generateDayBlocks() {
const firstWeekDay = (new Date(this.currentYear, this.currentMonth, 1)).getDay();
const lastMonth = DateTime.getLastDayOfPreviousMonth(this.currentYear, this.currentMonth);
const nextMonth = DateTime.getFirstDayOfNextMonth(this.currentYear, this.currentMonth);
const lastDayOfLastMonth = DateTime.getLastDayOfMonth(lastMonth.getFullYear(), lastMonth.getMonth()).getDate();
const lastDayOfMonth = DateTime.getLastDayOfMonth(this.currentYear, this.currentMonth).getDate();
this.dayBlocks = [];
let currentWeek = [];
this.dayBlocks.push(currentWeek);
// Fill the left over days of last month into the first week.
for (let i = 0; i < firstWeekDay; i++) {
const date = new Date(lastMonth.getFullYear(), lastMonth.getMonth(), lastDayOfLastMonth - firstWeekDay + i + 1);
currentWeek.push({
date: date,
isCurrentMonth: false,
isToday: false,
timestamp: date.getTime()
});
}
// Fill the first a few days of current month into the first week.
for (let i = 0; i < 7 - firstWeekDay; i++) {
const currentDay = i + 1;
const date = new Date(this.currentYear, this.currentMonth, currentDay);
currentWeek.push({
date: date,
isCurrentMonth: true,
isToday: this.currentYear === this.nowYear
&& this.currentMonth === this.nowMonth
&& currentDay === this.nowDay,
timestamp: date.getTime()
});
}
// Fill the rest of the days of current month into rest of weeks.
for (let i = 7 - firstWeekDay + 1; i <= lastDayOfMonth; i++) {
if (currentWeek.length === 7) {
currentWeek = [];
this.dayBlocks.push(currentWeek);
}
const currentDay = i;
const date = new Date(this.currentYear, this.currentMonth, currentDay);
currentWeek.push({
date: date,
isCurrentMonth: true,
isToday: this.currentYear === this.nowYear
&& this.currentMonth === this.nowMonth
&& currentDay === this.nowDay,
timestamp: date.getTime()
});
}
// Fill the rest of the last week of current month with the first a few days of next month.
let remainingDays = 7 - currentWeek.length;
for (let i = 1; i <= remainingDays; i++) {
const date = new Date(nextMonth.getFullYear(), nextMonth.getMonth(), i);
currentWeek.push({
date: date,
isCurrentMonth: false,
isToday: false,
timestamp: date.getTime()
});
}
// Fill the rest of day blocks with days of next month to make sure in total there
// are 6 weeks of day blocks.
while (this.dayBlocks.length < 6) {
currentWeek = [];
for (let i = 0; i < 7; i++) {
remainingDays++;
const date = new Date(nextMonth.getFullYear(), nextMonth.getMonth(), remainingDays);
currentWeek.push({
date: date,
isCurrentMonth: false,
isToday: false,
timestamp: date.getTime()
});
}
this.dayBlocks.push(currentWeek);
}
}
/**
* attempts to find a day button via its timestamp
*/
findDayButton(date) {
const timestamp = date.getTime();
const selector = `button.sme-calendar-block[data-timestamp="${timestamp}"]`;
return this.hostElement.nativeElement.querySelector(selector);
}
/**
* Brings focus to a given date
*/
focusOnDate(date) {
// try to find date button
let dayButton = this.findDayButton(date);
if (!dayButton) {
// bring date into view and try again
this.goTo(date.getFullYear(), date.getMonth());
setTimeout(() => {
dayButton = this.findDayButton(date);
if (dayButton) {
dayButton.focus();
}
});
}
else {
dayButton.focus();
}
}
convertDateToScreenReaderFormat(day) {
return this.daysOfWeek[day.getDay()] + ', ' + Globalization.dateOnly(day);
}
}
/** @nocollapse */ CalendarFormFieldComponent.ɵfac = function CalendarFormFieldComponent_Factory(t) { return new (t || CalendarFormFieldComponent)(i0.ɵɵdirectiveInject(i0.Injector)); };
/** @nocollapse */ CalendarFormFieldComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: CalendarFormFieldComponent, selectors: [["sme-form-field", "type", "calendar"]], features: [i0.ɵɵInheritDefinitionFeature], attrs: _c0, decls: 15, vars: 14, consts: [["role", "region", 3, "formField"], [1, "sme-calendar", "sme-focus-zone", "sme-form-field-editor"], [1, "sme-calendar-header"], [1, "sme-calendar-header-text"], ["type", "button", 1, "sme-button-trigger", "sme-button-auto-width", 3, "disabled", "title", "click"], [1, "sme-icon", "sme-icon-calendar"], ["type", "button", 1, "sme-button-trigger", "sme-button-auto-width", 3, "title", "click"], [1, "sme-icon", "sme-icon-up"], [1, "sme-icon", "sme-icon-down"], [1, "sme-calendar-block-row"], ["class", "sme-calendar-block sme-calendar-block-header", 4, "ngFor", "ngForOf"], ["class", "sme-calendar-block-row", 4, "ngFor", "ngForOf"], [3, "alert", 4, "ngIf"], [1, "sme-calendar-block", "sme-calendar-block-header"], ["type", "button", "class", "sme-calendar-block", 3, "sme-selected", "sme-calendar-block-today", "sme-calendar-block-other-month", "click", "keydown", 4, "ngFor", "ngForOf"], ["type", "button", 1, "sme-calendar-block", 3, "click", "keydown"], [3, "alert"]], template: function CalendarFormFieldComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "sme-form-field-layout", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3);
i0.ɵɵtext(4);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(5, "button", 4);
i0.ɵɵlistener("click", function CalendarFormFieldComponent_Template_button_click_5_listener($event) { return ctx.onGoToTodayClicked($event); });
i0.ɵɵelement(6, "span", 5);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(7, "button", 6);
i0.ɵɵlistener("click", function CalendarFormFieldComponent_Template_button_click_7_listener($event) { return ctx.onPreviousClicked($event); });
i0.ɵɵelement(8, "span", 7);
i0.ɵɵelementEnd();
i0.ɵɵelementStart(9, "button", 6);
i0.ɵɵlistener("click", function CalendarFormFieldComponent_Template_button_click_9_listener($event) { return ctx.onNextClicked($event); });
i0.ɵɵelement(10, "span", 8);
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(11, "div", 9);
i0.ɵɵtemplate(12, CalendarFormFieldComponent_div_12_Template, 2, 1, "div", 10);
i0.ɵɵelementEnd();
i0.ɵɵtemplate(13, CalendarFormFieldComponent_div_13_Template, 2, 1, "div", 11);
i0.ɵɵelementEnd();
i0.ɵɵtemplate(14, CalendarFormFieldComponent_sme_validation_alert_14_Template, 1, 1, "sme-validation-alert", 12);
i0.ɵɵelementEnd();
} if (rf & 2) {
i0.ɵɵproperty("formField", ctx);
i0.ɵɵattribute("aria-label", ctx.ariaLabel);
i0.ɵɵadvance(3);
i0.ɵɵattribute("aria-live", "polite");
i0.ɵɵadvance(1);
i0.ɵɵtextInterpolate(ctx.headerText);
i0.ɵɵadvance(1);
i0.ɵɵproperty("disabled", ctx.isTodayInView)("title", ctx.strings.MsftSmeShell.Angular.Calendar.goToToday);
i0.ɵɵattribute("aria-label", ctx.strings.MsftSmeShell.Angular.Calendar.goToToday);
i0.ɵɵadvance(2);
i0.ɵɵproperty("title", ctx.strings.MsftSmeShell.Angular.Calendar.PreviousMonth);
i0.ɵɵattribute("aria-label", ctx.strings.MsftSmeShell.Angular.Calendar.PreviousMonth);
i0.ɵɵadvance(2);
i0.ɵɵproperty("title", ctx.strings.MsftSmeShell.Angular.Calendar.NextMonth);
i0.ɵɵattribute("aria-label", ctx.strings.MsftSmeShell.Angular.Calendar.NextMonth);
i0.ɵɵadvance(3);
i0.ɵɵproperty("ngForOf", ctx.dayHeadings);
i0.ɵɵadvance(1);
i0.ɵɵproperty("ngForOf", ctx.dayBlocks);
i0.ɵɵadvance(1);
i0.ɵɵproperty("ngIf", !ctx.compact);
} }, dependencies: [i1.NgForOf, i1.NgIf, i2.TooltipDirective, i3.ValidationAlertComponent, i4.FormFieldLayoutComponent], encapsulation: 2 });
__decorate([
Yield(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], CalendarFormFieldComponent.prototype, "yieldFocus", null);
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CalendarFormFieldComponent, [{
type: Component,
args: [{ selector: 'sme-form-field[type="calendar"]', template: "<sme-form-field-layout [formField]=\"this\" role=\"region\" [attr.aria-label]=\"ariaLabel\">\r\n <div class=\"sme-calendar sme-focus-zone sme-form-field-editor\">\r\n <div class=\"sme-calendar-header\">\r\n <div class=\"sme-calendar-header-text\" [attr.aria-live]=\"'polite'\">{{ headerText }}</div>\r\n <button type=\"button\" class=\"sme-button-trigger sme-button-auto-width\" [disabled]=\"isTodayInView\" (click)=\"onGoToTodayClicked($event)\"\r\n [title]=\"strings.MsftSmeShell.Angular.Calendar.goToToday\" [attr.aria-label]=\"strings.MsftSmeShell.Angular.Calendar.goToToday\">\r\n <span class=\"sme-icon sme-icon-calendar\"></span>\r\n </button>\r\n <button type=\"button\" class=\"sme-button-trigger sme-button-auto-width\" (click)=\"onPreviousClicked($event)\"\r\n [title]=\"strings.MsftSmeShell.Angular.Calendar.PreviousMonth\"\r\n [attr.aria-label]=\"strings.MsftSmeShell.Angular.Calendar.PreviousMonth\">\r\n <span class=\"sme-icon sme-icon-up\"></span>\r\n </button>\r\n <button type=\"button\" class=\"sme-button-trigger sme-button-auto-width\" (click)=\"onNextClicked($event)\"\r\n [title]=\"strings.MsftSmeShell.Angular.Calendar.NextMonth\" [attr.aria-label]=\"strings.MsftSmeShell.Angular.Calendar.NextMonth\">\r\n <span class=\"sme-icon sme-icon-down\"></span>\r\n </button>\r\n </div>\r\n <div class=\"sme-calendar-block-row\">\r\n <div class=\"sme-calendar-block sme-calendar-block-header\" *ngFor=\"let heading of dayHeadings\">{{ heading }}</div>\r\n </div>\r\n <div class=\"sme-calendar-block-row\" *ngFor=\"let week of dayBlocks\">\r\n <button type=\"button\" class=\"sme-calendar-block\" [attr.data-timestamp]=\"day.timestamp\" [attr.aria-label]=\"convertDateToScreenReaderFormat(day.date)\" *ngFor=\"let day of week\" (click)=\"selectDay(day.date)\"\r\n (keydown)=\"onDayBlockKeyDown($event, day)\" [class.sme-selected]=\"isDaySelected(day.date)\" [attr.aria-pressed]=\"isDaySelected(day.date)\"\r\n [class.sme-calendar-block-today]=\"day.isToday\" [class.sme-calendar-block-other-month]=\"!day.isCurrentMonth\">\r\n {{day.date.getDate()}}\r\n </button>\r\n </div>\r\n </div>\r\n <sme-validation-alert *ngIf=\"!compact\" [alert]=\"alert\"></sme-validation-alert>\r\n</sme-form-field-layout>\r\n" }]
}], function () { return [{ type: i0.Injector }]; }, { yieldFocus: [] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItZm9ybS1maWVsZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9mb3JtL2Zvcm0tZmllbGQvY2FsZW5kYXIvY2FsZW5kYXItZm9ybS1maWVsZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9mb3JtL2Zvcm0tZmllbGQvY2FsZW5kYXIvY2FsZW5kYXItZm9ybS1maWVsZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFFNUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhEQUE4RCxDQUFDO0FBQ3hGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4REFBOEQsQ0FBQztBQUN4RixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sOERBQThELENBQUM7QUFDeEYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDBFQUEwRSxDQUFDO0FBQ2pHLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxRUFBcUUsQ0FBQztBQUM5RixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkRBQTZELENBQUM7QUFFNUYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sNkNBQTZDLENBQUM7Ozs7Ozs7O0lDVW5GLCtCQUE4RjtJQUFBLFlBQWE7SUFBQSxpQkFBTTs7O0lBQW5CLGVBQWE7SUFBYixnQ0FBYTs7OztJQUczRyxrQ0FFb0g7SUFGMEQsNE9BQVMsZUFBQSw2QkFBbUIsQ0FBQSxJQUFDLHlPQUN4TCxlQUFBLHdDQUE4QixDQUFBLElBRDBKO0lBR3pNLFlBQ0Y7SUFBQSxpQkFBUzs7OztJQUgwQyxpRUFBOEMsNENBQUEsMERBQUE7SUFEaEQsa0RBQXFDLG1FQUFBLG1E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UUFBQyxpRkFBbUU7UUFLdkQsZUFBYztRQUFkLHlDQUFjO1FBRXpDLGVBQVk7UUFBWix1Q0FBWTtRQVE1QyxlQUFjO1FBQWQsbUNBQWM7O0FEMk1uQztJQUFDLEtBQUssRUFBRTs7Ozs0REFHUDt1RkFsTlEsMEJBQTBCO2NBSnRDLFNBQVM7MkJBQ0ksaUNBQWlDOzJEQW1ObkMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5qZWN0b3IsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGb3JtQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgRGF0ZVRpbWUgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2Jhc2UvZGF0ZS9kYXRlLXRpbWUnO1xyXG5pbXBvcnQgeyBEYXRlVHlwZSB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvYmFzZS9kYXRlL2RhdGUtdHlwZSc7XHJcbmltcG9ydCB7IFRpbWVVbml0IH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9iYXNlL2RhdGUvdGltZS11bml0JztcclxuaW1wb3J0IHsgWWllbGQgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2Jhc2UvZGVjb3JhdG9ycy95aWVsZC5kZWNvcmF0b3InO1xyXG5pbXBvcnQgeyBLZXlDb2RlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kYXRhL2FjY2Vzc2liaWxpdHktbWFuYWdlcic7XHJcbmltcG9ydCB7IEdsb2JhbGl6YXRpb24gfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RhdGEvZ2xvYmFsaXphdGlvbic7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25BbGVydHMgfSBmcm9tICcuLi8uLi92YWxpZGF0aW9uLWFsZXJ0L3ZhbGlkYXRpb24tYWxlcnQnO1xyXG5pbXBvcnQgeyBEYXRlTGlrZUZvcm1GaWVsZENvbXBvbmVudCB9IGZyb20gJy4uL2RhdGUtbGlrZS9kYXRlLWxpa2UtZm9ybS1maWVsZC5jb21wb25lbnQnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBEYXlCbG9jayB7XHJcbiAgICBkYXRlOiBEYXRlO1xyXG4gICAgaXNDdXJyZW50TW9udGg6IGJvb2xlYW47XHJcbiAgICBpc1RvZGF5OiBib29sZWFuO1xyXG4gICAgdGltZXN0YW1wOiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxlbmRhciBGb3JtIEZpZWxkIENvbXBvbmVudFxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3NtZS1mb3JtLWZpZWxkW3R5cGU9XCJjYWxlbmRhclwiXScsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vY2FsZW5kYXItZm9ybS1maWVsZC5jb21wb25lbnQuaHRtbCdcclxufSlcclxuZXhwb3J0IGNsYXNzIENhbGVuZGFyRm9ybUZpZWxkQ29tcG9uZW50IGV4dGVuZHMgRGF0ZUxpa2VGb3JtRmllbGRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHNvdXJjZSBuYW1lIHRvIHVzZSBmb3IgbG9nZ2luZ1xyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgZ2V0IGxvZ1NvdXJjZU5hbWUoKSB7XHJcbiAgICAgICAgcmV0dXJuICdDYWxlbmRhckZvcm1GaWVsZENvbXBvbmVudCc7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbnRlcm5hbCBzZWxlY3RlZCBkYXRlIHZhbHVlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZWxlY3RlZERhdGU6IERhdGU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBzZWxlY3RlZCB5ZWFyXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0IHNlbGVjdGVkWWVhcigpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkRGF0ZSA/IHRoaXMuc2VsZWN0ZWREYXRlLmdldEZ1bGxZZWFyKCkgOiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgc2VsZWN0ZWQgbW9udGhcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXQgc2VsZWN0ZWRNb250aCgpOiBudW1iZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkRGF0ZSA/IHRoaXMuc2VsZWN0ZWREYXRlLmdldE1vbnRoKCkgOiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgdGV4dCBmb3IgdGhlIGN1cnJlbnRseSB2aWV3ZWQgbW9udGhcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBoZWFkZXJUZXh0KCk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgbW9udGhUZXh0ID0gdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNhbGVuZGFyLk1vbnRoW3RoaXMuY3VycmVudE1vbnRoICsgMV07XHJcbiAgICAgICAgY29uc3QgeWVhclRleHQgPSB0aGlzLmN1cnJlbnRZZWFyLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgcmV0dXJuIGAke21vbnRoVGV4dH0gJHt5ZWFyVGV4dH1gO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBhIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIGN1cnJlbnQgdmlldyBjb250YWlucyB0b2RheSdzIGRhdGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBpc1RvZGF5SW5WaWV3KCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLm5vd1llYXIgPT09IHRoaXMuY3VycmVudFllYXIgJiYgdGhpcy5ub3dNb250aCA9PT0gdGhpcy5jdXJyZW50TW9udGg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIGEgdmFsdWUgaW5kaWNhdGluZyBpZiB0aGUgY3VycmVudCB2aWV3IGNvbnRhaW5zIHRvZGF5J3MgZGF0ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGlzU2VsZWN0aW9uSW5WaWV3KCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLm5vd1llYXIgPT09IHRoaXMuY3VycmVudFllYXIgJiYgdGhpcy5ub3dNb250aCA9PT0gdGhpcy5jdXJyZW50TW9udGg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBIHdvcmthcm91bmQgdG8gaGF2ZSBTY3JlZW4gcmVhZGVyIGtub3cgdGhpcyBpcyBhIHJlcXVpcmVkIFwiaW5wdXRcIiBmaWVsZC5cclxuICAgICAqL1xyXG5cclxuICAgIHB1YmxpYyBnZXQgYXJpYUxhYmVsKCk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKHRoaXMucmVxdWlyZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5BcmlhTGFiZWwuUmVxdWlyZWQuZm9ybWF0KHRoaXMubGFiZWwpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdGhpcy5sYWJlbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBjdXJyZW50bHkgdmlld2VkIHllYXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIGN1cnJlbnRZZWFyOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgY3VycmVudGx5IHZpZXdlZCBtb250aFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY3VycmVudE1vbnRoOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBIGxvY2FsaXplZCBsaXN0IG9mIGRhdGUgY29sdW1uIGhlYWRpbmdzXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkYXlIZWFkaW5nczogc3RyaW5nW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBIG1hdHJpeCBvZiB2aXNpYmxlIGRheXMgYWNvcmRpbmcgdG8gdGhlIHdlZWsgdGhleSBhcHBlYXIgaW4uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkYXlCbG9ja3M6IERheUJsb2NrW11bXTtcclxuXHJcbiAgICAvKipcclxuICAgICogQSBMb2NhbGl6ZWQgbGlzdCBvZiBkYXlzIG9mIHdlZWsuXHJcbiAgICAqL1xyXG4gICAgcHVibGljIGRheXNPZldlZWs6IHN0cmluZ1tdO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIEBzZWUgQ2FsZW5kYXJGb3JtRmllbGRDb21wb25lbnQgY2xhc3MuXHJcbiAgICAgKiBAcGFyYW0gaW5qZWN0b3IgVGhlIGFuZ3VsYXIgaW5qZWN0aW9uIHNlcnZpY2UuIHJlcXVpcmVkIGJ5IEBzZWUgU21lSW5qZWN0YWJsZUJhc2UgZGVjb3JhdG9yIGluIHRoZSBAc2VlIEJhc2VDb21wb25lbnQgY2xhc3NcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IoaW5qZWN0b3I6IEluamVjdG9yKSB7XHJcbiAgICAgICAgc3VwZXIoaW5qZWN0b3IpO1xyXG4gICAgICAgIHRoaXMuY3VycmVudFllYXIgPSB0aGlzLm5vdy5nZXRGdWxsWWVhcigpO1xyXG4gICAgICAgIHRoaXMuY3VycmVudE1vbnRoID0gdGhpcy5ub3cuZ2V0TW9udGgoKTtcclxuICAgICAgICB0aGlzLmRheUJsb2NrcyA9IFtdO1xyXG4gICAgICAgIHRoaXMuZGF5SGVhZGluZ3MgPSBbXHJcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5IZWFkaW5nLlN1bmRheSxcclxuICAgICAgICAgICAgdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNhbGVuZGFyLkhlYWRpbmcuTW9uZGF5LFxyXG4gICAgICAgICAgICB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ2FsZW5kYXIuSGVhZGluZy5UdWVzZGF5LFxyXG4gICAgICAgICAgICB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ2FsZW5kYXIuSGVhZGluZy5XZWRuZXNkYXksXHJcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5IZWFkaW5nLlRodXJzZGF5LFxyXG4gICAgICAgICAgICB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ2FsZW5kYXIuSGVhZGluZy5GcmlkYXksXHJcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5IZWFkaW5nLlNhdHVyZGF5XHJcbiAgICAgICAgXTtcclxuICAgICAgICB0aGlzLmRheXNPZldlZWsgPSBbXHJcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5EYXkuU3VuZGF5LFxyXG4gICAgICAgICAgICB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ2FsZW5kYXIuRGF5Lk1vbmRheSxcclxuICAgICAgICAgICAgdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNhbGVuZGFyLkRheS5UdWVzZGF5LFxyXG4gICAgICAgICAgICB0aGlzLnN0cmluZ3MuTXNmdFNtZVNoZWxsLkFuZ3VsYXIuQ2FsZW5kYXIuRGF5LldlZG5lc2RheSxcclxuICAgICAgICAgICAgdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNhbGVuZGFyLkRheS5UaHVyc2RheSxcclxuICAgICAgICAgICAgdGhpcy5zdHJpbmdzLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLkNhbGVuZGFyLkRheS5GcmlkYXksXHJcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncy5Nc2Z0U21lU2hlbGwuQW5ndWxhci5DYWxlbmRhci5EYXkuU2F0dXJkYXlcclxuICAgICAgICBdO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW1wbGVtZW50YXRpb24gb2YgYW5ndWxhciBPbkluaXQgaW50ZXJmYWNlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG4gICAgICAgIHRoaXMuZ2VuZXJhdGVEYXlCbG9ja3MoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE9jY3VycyB3aGVuIHRoZSBwcmV2aW91cyBtb250aCBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25QcmV2aW91c0NsaWNrZWQoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICB0aGlzLmdvVG9QcmV2aW91c01vbnRoKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPY2N1cnMgd2hlbiB0aGUgbmV4dCBtb250aCBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25OZXh0Q2xpY2tlZChldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIHRoaXMuZ29Ub05leHRNb250aCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogT2NjdXJzIHdoZW4gdGhlIGdvIHRvIHRvZGF5IGJ1dHRvbiBoYXMgYmVlb