UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

510 lines 69.1 kB
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