systelab-components
Version:
systelab-components is a set of components that use wide accepted and adopted standard technologies like Angular and Bootstrap, as well as other popular libraries. Please read the ATTRIBUTION.md file for a complete list of dependencies.
383 lines • 65.5 kB
JavaScript
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { addDays } from 'date-fns';
import { DataTransformerService } from './date-transformer.service';
import * as i0 from "@angular/core";
import * as i1 from "systelab-translate";
import * as i2 from "./date-transformer.service";
import * as i3 from "primeng/api";
import * as i4 from "@angular/common";
import * as i5 from "@angular/forms";
import * as i6 from "primeng/calendar";
import * as i7 from "../button/button.component";
export class DatepickerComponent {
get currentDate() {
return this._currentDate;
}
set currentDate(value) {
this._currentDate = value;
if (this.markPreviousAfterDate || (this.warnDaysBefore && this.warnDaysBefore > 0)) {
if (!this.warnDaysBefore) {
this.warnDaysBefore = 1;
}
this.checkPreviousAfterDate();
}
if (this.warnDaysAfter && this.warnDaysAfter > 0) {
this.checkTooFarDate();
}
}
constructor(myRenderer, i18nService, dataTransformerService, config) {
this.myRenderer = myRenderer;
this.i18nService = i18nService;
this.dataTransformerService = dataTransformerService;
this.config = config;
this.disabled = false;
this.error = false;
this.required = false;
this.markPreviousAfterDate = false;
this.showTodayButton = false;
this.inline = false;
this.autofocus = false;
this.withIntegratedTime = false;
this.onlyTime = false;
this.showOtherMonths = true;
this.selectOtherMonths = false;
this.currentDateChange = new EventEmitter();
this.inputChanged = false;
this.previousAfterDate = false;
this.tooFarDate = false;
this.isTablet = false;
this.datepickerId = (Math.random() * (999999999999 - 1)).toString();
this.headerElement = document.getElementById(this.datepickerId);
}
ngOnInit() {
this.getLanguage();
this.currentDocSize = window.innerWidth;
this.currentLanguage = this.i18nService.getCurrentLanguage();
this.addListeners();
if (navigator.userAgent.indexOf('iPad') > -1 || navigator.userAgent.indexOf('Android') > -1) {
this.isTablet = true;
}
}
ngAfterViewInit() {
const newElement = document.createElement('i');
if (!this.inline) {
newElement.className = this.onlyTime ? 'icon-clock' : 'icon-calendar';
if (this.currentCalendar) {
if (this.autofocus) {
this.currentCalendar.el.nativeElement.querySelector('input')
.focus();
}
this.currentCalendar.el.nativeElement.childNodes[0].className = 'p-calendar slab-form-icon w-100';
this.currentCalendar.el.nativeElement.childNodes[0].appendChild(newElement);
}
}
if (this.tabindex) {
this.currentCalendar.el.nativeElement.querySelector('input')
.setAttribute('tabindex', this.tabindex);
}
}
ngDoCheck() {
if (window.innerWidth !== this.currentDocSize) {
this.currentDocSize = window.innerWidth;
this.closeDatepicker();
}
if (this.headerElement !== document.getElementById(this.datepickerId)) {
this.headerElement = document.getElementById(this.datepickerId);
if (this.headerElement) {
this.repositionateCalendar(new ElementRef(this.headerElement.parentElement.parentElement));
}
}
if (this.currentLanguage !== this.i18nService.getCurrentLanguage()) {
this.currentLanguage = this.i18nService.getCurrentLanguage();
this.getLanguage();
}
}
ngOnDestroy() {
this.destroyKeyListener?.();
this.destroyWheelListener?.();
}
selectDate() {
this.formatError = false;
this.currentDateChange.emit(this.currentDate);
this.inputChanged = false;
}
changeDate() {
this.formatError = false;
if (this.currentCalendar?.inputfieldViewChild.nativeElement.value !== undefined) {
const dateStr = this.currentCalendar.inputfieldViewChild.nativeElement.value.trim()
.toLowerCase();
if (this.inputChanged) {
if (dateStr.length >= 2) {
const transformedDate = this.dataTransformerService.processShortcuts(dateStr, this.fromDateForRelativeDates);
if (transformedDate) {
this.currentDate = transformedDate;
}
else {
if (this.onlyTime || this.withIntegratedTime) {
const splitDateByHours = dateStr.split(':');
if (!this.onlyTime) {
switch (splitDateByHours.length) {
case 1:
this.infereDate(dateStr);
break;
case 2:
const hourPosition = splitDateByHours[0].length - 2;
const dateString = splitDateByHours[0].substring(0, hourPosition);
this.infereDate(dateString);
this.parseTime(+splitDateByHours[0].substring(hourPosition), +splitDateByHours[1]);
break;
default:
this.formatError = true;
break;
}
}
else {
const hour = +splitDateByHours[0];
const minute = +splitDateByHours[1];
this.currentDate = new Date();
this.parseTime(hour, minute);
}
}
else {
this.infereDate(dateStr);
}
}
}
this.currentDateChange.emit(this.currentDate);
this.inputChanged = false;
}
}
}
parseTime(hour, minute) {
const isValidHour = hour >= 0 && hour <= 23;
const isValidMinute = minute >= 0 && minute <= 59;
if (!isValidHour || !isValidMinute) {
this.formatError = true;
}
else {
this.currentDate.setHours(hour, minute);
}
}
infereDate(dateStr) {
const inferedDate = this.dataTransformerService.infereDate(dateStr, this.i18nService.getDateFormatForDatePicker());
if (inferedDate) {
this.currentDate = inferedDate;
}
else {
this.formatError = true;
}
}
onInput(event) {
if (event.code === 'Enter' || event.code === 'Tab') {
this.currentCalendar.inputfieldViewChild.nativeElement.blur();
this.currentCalendar.onBlur.emit(event);
this.closeDatepicker();
}
else {
this.inputChanged = true;
}
}
saveEventOnFocus(evt) {
this.inputElement = new ElementRef(evt.target);
this.focusEvt = evt;
}
repositionateCalendar(element) {
try {
const { inputElementTop, inputElementHeight, datepickerElementHeight } = this.inputElement.nativeElement.getBoundingClientRect();
if (inputElementTop + inputElementHeight + datepickerElementHeight > window.innerHeight) {
const newTop = inputElementTop + inputElementHeight - (datepickerElementHeight + inputElementHeight + 10);
this.myRenderer.setAttribute(element.nativeElement, 'top', newTop + 'px');
}
}
catch (ex) {
}
}
nextMonth() {
if (this.currentCalendar) {
let month = this.currentCalendar.currentMonth;
if (month < 11) {
month++;
this.currentCalendar.onMonthDropdownChange(month.toString());
}
else {
month = 0;
let year = this.currentCalendar.currentYear;
year++;
this.currentCalendar.onMonthDropdownChange(month.toString());
this.currentCalendar.onYearDropdownChange(year.toString());
}
}
}
prevMonth() {
if (this.currentCalendar) {
let month = this.currentCalendar.currentMonth;
if (month > 0) {
month--;
this.currentCalendar.onMonthDropdownChange(month.toString());
}
else {
month = 11;
let year = this.currentCalendar.currentYear;
year--;
this.currentCalendar.onMonthDropdownChange(month.toString());
this.currentCalendar.onYearDropdownChange(year.toString());
}
}
}
nextYear() {
if (this.currentCalendar) {
const currentYear = this.currentCalendar.currentYear + 1;
this.currentCalendar.onYearDropdownChange(currentYear.toString());
}
}
prevYear() {
if (this.currentCalendar) {
const currentYear = this.currentCalendar.currentYear - 1;
this.currentCalendar.onYearDropdownChange(currentYear.toString());
}
}
clearDate(event) {
if (this.currentCalendar) {
this.currentDate = null;
this.currentCalendar.onClearButtonClick(event);
this.currentDateChange.emit(this.currentDate);
this.inputChanged = false;
}
}
setTodayDate() {
if (this.currentCalendar) {
this.currentDate = new Date();
this.currentDateChange.emit(this.currentDate);
this.inputChanged = false;
}
}
closeDatepicker() {
if (this.currentCalendar) {
this.currentCalendar.focus = false;
this.currentCalendar.overlayVisible = false;
}
}
checkPreviousAfterDate() {
if (this._currentDate) {
this._currentDate.setHours(0, 0, 0, 0);
const pastDate = addDays(new Date(), this.warnDaysBefore * -1);
pastDate.setHours(0, 0, 0, 0);
this.previousAfterDate = this._currentDate.getTime() <= pastDate.getTime();
}
else {
this.previousAfterDate = false;
}
}
checkTooFarDate() {
if (this._currentDate) {
this._currentDate.setHours(0, 0, 0, 0);
const futureDate = addDays(new Date(), this.warnDaysAfter);
this.tooFarDate = this._currentDate.getTime() >= futureDate.getTime();
}
else {
this.tooFarDate = false;
}
}
getLanguage() {
const weekDaysNames = [];
const weekDaysNamesShort = [];
const monthNames = [];
const monthNamesShort = [];
/* eslint-disable max-len */
this.i18nService.get(['COMMON_SUNDAY', 'COMMON_MONDAY', 'COMMON_TUESDAY', 'COMMON_WEDNESDAY', 'COMMON_THURSDAY', 'COMMON_FRIDAY', 'COMMON_SATURDAY'])
.subscribe((res) => {
weekDaysNames.push(res.COMMON_SUNDAY, res.COMMON_MONDAY, res.COMMON_TUESDAY, res.COMMON_WEDNESDAY, res.COMMON_THURSDAY, res.COMMON_FRIDAY, res.COMMON_SATURDAY);
});
this.i18nService.get(['COMMON_SEVENTH_DAY', 'COMMON_FIRST_DAY', 'COMMON_SECOND_DAY', 'COMMON_THIRD_DAY', 'COMMON_FOURTH_DAY', 'COMMON_FIFTH_DAY', 'COMMON_SIXTH_DAY'])
.subscribe((res) => {
weekDaysNamesShort.push(res.COMMON_SEVENTH_DAY, res.COMMON_FIRST_DAY, res.COMMON_SECOND_DAY, res.COMMON_THIRD_DAY, res.COMMON_FOURTH_DAY, res.COMMON_FIFTH_DAY, res.COMMON_SIXTH_DAY);
});
this.i18nService.get(['COMMON_JANUARY', 'COMMON_FEBRUARY', 'COMMON_MARCH', 'COMMON_APRIL', 'COMMON_MAY', 'COMMON_JUNE', 'COMMON_JULY', 'COMMON_AUGUST', 'COMMON_SEPTEMBER', 'COMMON_OCTOBER', 'COMMON_NOVEMBER', 'COMMON_DECEMBER'])
.subscribe((res) => {
monthNames.push(res.COMMON_JANUARY, res.COMMON_FEBRUARY, res.COMMON_MARCH, res.COMMON_APRIL, res.COMMON_MAY, res.COMMON_JUNE, res.COMMON_JULY, res.COMMON_AUGUST, res.COMMON_SEPTEMBER, res.COMMON_OCTOBER, res.COMMON_NOVEMBER, res.COMMON_DECEMBER);
});
this.i18nService.get(['JOB_MONTHS_1', 'JOB_MONTHS_2', 'JOB_MONTHS_3', 'JOB_MONTHS_4', 'JOB_MONTHS_5', 'JOB_MONTHS_6', 'JOB_MONTHS_7', 'JOB_MONTHS_8', 'JOB_MONTHS_9', 'JOB_MONTHS_10', 'JOB_MONTHS_11', 'JOB_MONTHS_12'])
.subscribe((res) => {
monthNamesShort.push(res.JOB_MONTHS_1, res.JOB_MONTHS_2, res.JOB_MONTHS_3, res.JOB_MONTHS_4, res.JOB_MONTHS_5, res.JOB_MONTHS_6, res.JOB_MONTHS_7, res.JOB_MONTHS_8, res.JOB_MONTHS_9, res.JOB_MONTHS_10, res.JOB_MONTHS_11, res.JOB_MONTHS_12);
});
this.language = {
translations: {
dayNames: weekDaysNames,
dayNamesShort: weekDaysNamesShort,
dayNamesMin: weekDaysNamesShort,
monthNames: monthNames,
monthNamesShort: monthNamesShort
}
};
this.language.firstDayOfWeek = this.i18nService.getFirstDayOfWeek();
this.language.dateFormatValue = this.dateFormat ? this.dateFormat : this.i18nService.getDateFormatForDatePicker(true);
if (this.currentCalendar) {
this.currentCalendar.dateFormat = this.dateFormat || this.language.dateFormatValue;
}
this.config.setTranslation(this.language.translations);
}
addListeners() {
this.destroyWheelListener = this.myRenderer.listen('window', 'wheel', () => {
this.closeDatepicker();
});
this.destroyKeyListener = this.myRenderer.listen('document', 'keydown', (evt) => {
if (evt.key === 'Escape' || evt.key === 'Tab') {
this.closeDatepicker();
}
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: DatepickerComponent, deps: [{ token: i0.Renderer2 }, { token: i1.I18nService }, { token: i2.DataTransformerService }, { token: i3.PrimeNGConfig }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: DatepickerComponent, selector: "systelab-datepicker", inputs: { disabled: "disabled", error: "error", required: "required", inputExpandHeight: "inputExpandHeight", markPreviousAfterDate: "markPreviousAfterDate", inputFontSize: "inputFontSize", showTodayButton: "showTodayButton", inline: "inline", minDate: "minDate", maxDate: "maxDate", warnDaysBefore: "warnDaysBefore", warnDaysAfter: "warnDaysAfter", autofocus: "autofocus", fromDateForRelativeDates: "fromDateForRelativeDates", tabindex: "tabindex", withIntegratedTime: "withIntegratedTime", onlyTime: "onlyTime", showOtherMonths: "showOtherMonths", selectOtherMonths: "selectOtherMonths", dateFormat: "dateFormat", currentDate: "currentDate" }, outputs: { currentDateChange: "currentDateChange" }, providers: [DataTransformerService], viewQueries: [{ propertyName: "currentCalendar", first: true, predicate: ["calendar"], descendants: true, static: true }], ngImport: i0, template: "<p-calendar #calendar [(ngModel)]=\"currentDate\" [showIcon]=\"false\"\n [dateFormat]=\"language.dateFormatValue\"\n [firstDayOfWeek]=\"language.firstDayOfWeek\"\n (onFocus)=\"saveEventOnFocus($event)\"\n (onBlur)=\"changeDate()\"\n (onSelect)=\"selectDate()\"\n (onInput)=\"onInput($event)\"\n [showOtherMonths]=\"showOtherMonths\"\n [selectOtherMonths]=\"selectOtherMonths\"\n [minDate]=\"minDate\"\n [focusTrap]=\"false\"\n [maxDate]=\"maxDate\"\n [inline]=\"inline\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [readonlyInput]=\"isTablet\"\n [style.font-size.px]=\"inputFontSize\"\n [showTime]=\"withIntegratedTime\"\n [timeOnly]=\"onlyTime\"\n [showTransitionOptions]=\"'1ms linear'\"\n [hideTransitionOptions]=\"'1ms linear'\"\n appendTo=\"body\"\n [tabindex]=\"tabindex\"\n [ngClass]=\"{'date-error': formatError || error || (required && !currentDate), 'is-disabled': disabled, 'warning-date': tooFarDate || previousAfterDate, 'input-expand-height':inputExpandHeight}\">\n <ng-template pTemplate=\"header\" *ngIf=\"!onlyTime\">\n <div id=\"{{datepickerId}}\" class=\"slab-datepicker-header\">\n <a id=\"previousYear\" class=\"icon-angle-double-left slab-icon-medium\" (click)=\"prevYear()\"></a>\n <a id=\"previousMonth\" class=\"icon-angle-left slab-icon-medium\" (click)=\"prevMonth()\"></a>\n <a id=\"nextYear\" class=\"icon-angle-double-right slab-icon-medium\" (click)=\"nextYear()\"></a>\n <a id=\"nextMonth\" class=\"icon-angle-right slab-icon-medium\" (click)=\"nextMonth()\"></a>\n <div class=\"p-datepicker-title d-flex align-items-center justify-content-center\">\n <span class=\"p-datepicker-month\">{{ language.translations.monthNames[currentCalendar.currentMonth] }} </span>\n <span class=\"p-datepicker-year\">{{ currentCalendar.currentYear }}</span>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"footer\">\n <div *ngIf=\"!inline\" class=\"p-3 d-flex border-top\">\n <systelab-button *ngIf=\"showTodayButton\" id=\"today\" size=\"small\" class=\"mr-auto\"\n (click)=\"setTodayDate()\">{{ 'COMMON_TODAY' | translate | async }}</systelab-button>\n <systelab-button id=\"clear\" size=\"small\" type=\"danger\" class=\"ml-auto\"\n (click)=\"clearDate($event)\">{{ 'COMMON_CLEAR' | translate | async }}</systelab-button>\n </div>\n </ng-template>\n</p-calendar>\n\n", dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i6.Calendar, selector: "p-calendar", inputs: ["style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: i7.ButtonComponent, selector: "systelab-button", inputs: ["disabled", "type", "size"], outputs: ["action"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.GeneralTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: DatepickerComponent, decorators: [{
type: Component,
args: [{ selector: 'systelab-datepicker', providers: [DataTransformerService], template: "<p-calendar #calendar [(ngModel)]=\"currentDate\" [showIcon]=\"false\"\n [dateFormat]=\"language.dateFormatValue\"\n [firstDayOfWeek]=\"language.firstDayOfWeek\"\n (onFocus)=\"saveEventOnFocus($event)\"\n (onBlur)=\"changeDate()\"\n (onSelect)=\"selectDate()\"\n (onInput)=\"onInput($event)\"\n [showOtherMonths]=\"showOtherMonths\"\n [selectOtherMonths]=\"selectOtherMonths\"\n [minDate]=\"minDate\"\n [focusTrap]=\"false\"\n [maxDate]=\"maxDate\"\n [inline]=\"inline\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [readonlyInput]=\"isTablet\"\n [style.font-size.px]=\"inputFontSize\"\n [showTime]=\"withIntegratedTime\"\n [timeOnly]=\"onlyTime\"\n [showTransitionOptions]=\"'1ms linear'\"\n [hideTransitionOptions]=\"'1ms linear'\"\n appendTo=\"body\"\n [tabindex]=\"tabindex\"\n [ngClass]=\"{'date-error': formatError || error || (required && !currentDate), 'is-disabled': disabled, 'warning-date': tooFarDate || previousAfterDate, 'input-expand-height':inputExpandHeight}\">\n <ng-template pTemplate=\"header\" *ngIf=\"!onlyTime\">\n <div id=\"{{datepickerId}}\" class=\"slab-datepicker-header\">\n <a id=\"previousYear\" class=\"icon-angle-double-left slab-icon-medium\" (click)=\"prevYear()\"></a>\n <a id=\"previousMonth\" class=\"icon-angle-left slab-icon-medium\" (click)=\"prevMonth()\"></a>\n <a id=\"nextYear\" class=\"icon-angle-double-right slab-icon-medium\" (click)=\"nextYear()\"></a>\n <a id=\"nextMonth\" class=\"icon-angle-right slab-icon-medium\" (click)=\"nextMonth()\"></a>\n <div class=\"p-datepicker-title d-flex align-items-center justify-content-center\">\n <span class=\"p-datepicker-month\">{{ language.translations.monthNames[currentCalendar.currentMonth] }} </span>\n <span class=\"p-datepicker-year\">{{ currentCalendar.currentYear }}</span>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"footer\">\n <div *ngIf=\"!inline\" class=\"p-3 d-flex border-top\">\n <systelab-button *ngIf=\"showTodayButton\" id=\"today\" size=\"small\" class=\"mr-auto\"\n (click)=\"setTodayDate()\">{{ 'COMMON_TODAY' | translate | async }}</systelab-button>\n <systelab-button id=\"clear\" size=\"small\" type=\"danger\" class=\"ml-auto\"\n (click)=\"clearDate($event)\">{{ 'COMMON_CLEAR' | translate | async }}</systelab-button>\n </div>\n </ng-template>\n</p-calendar>\n\n" }]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1.I18nService }, { type: i2.DataTransformerService }, { type: i3.PrimeNGConfig }], propDecorators: { disabled: [{
type: Input
}], error: [{
type: Input
}], required: [{
type: Input
}], inputExpandHeight: [{
type: Input
}], markPreviousAfterDate: [{
type: Input
}], inputFontSize: [{
type: Input
}], showTodayButton: [{
type: Input
}], inline: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], warnDaysBefore: [{
type: Input
}], warnDaysAfter: [{
type: Input
}], autofocus: [{
type: Input
}], fromDateForRelativeDates: [{
type: Input
}], tabindex: [{
type: Input
}], withIntegratedTime: [{
type: Input
}], onlyTime: [{
type: Input
}], showOtherMonths: [{
type: Input
}], selectOtherMonths: [{
type: Input
}], dateFormat: [{
type: Input
}], currentDate: [{
type: Input
}], currentDateChange: [{
type: Output
}], currentCalendar: [{
type: ViewChild,
args: ['calendar', { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zeXN0ZWxhYi1jb21wb25lbnRzL3NyYy9saWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N5c3RlbGFiLWNvbXBvbmVudHMvc3JjL2xpYi9kYXRlcGlja2VyL2RhdGVwaWNrZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVOLFNBQVMsRUFFVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRU4sU0FBUyxFQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFJbkMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7Ozs7OztBQU9wRSxNQUFNLE9BQU8sbUJBQW1CO0lBdUIvQixJQUNJLFdBQVc7UUFDZCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDMUIsQ0FBQztJQUVELElBQUksV0FBVyxDQUFDLEtBQVc7UUFDMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDMUIsSUFBSSxJQUFJLENBQUMscUJBQXFCLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDLEVBQUU7WUFFbkYsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3pCLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDO2FBQ3hCO1lBRUQsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7U0FDOUI7UUFDRCxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLEVBQUU7WUFDakQsSUFBSSxDQUFDLGVBQWUsRUFBRSxD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LHdCQUF3QjtzQkFBdkMsS0FBSztnQkFDVSxRQUFRO3NCQUF2QixLQUFLO2dCQUNVLGtCQUFrQjtzQkFBakMsS0FBSztnQkFDVSxRQUFRO3NCQUF2QixLQUFLO2dCQUNVLGVBQWU7c0JBQTlCLEtBQUs7Z0JBQ1UsaUJBQWlCO3NCQUFoQyxLQUFLO2dCQUNVLFVBQVU7c0JBQXpCLEtBQUs7Z0JBR0YsV0FBVztzQkFEZCxLQUFLO2dCQW9CVyxpQkFBaUI7c0JBQWpDLE1BQU07Z0JBRXVDLGVBQWU7c0JBQTVELFNBQVM7dUJBQUMsVUFBVSxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdEFmdGVyVmlld0luaXQsXG5cdENvbXBvbmVudCxcblx0RG9DaGVjayxcblx0RWxlbWVudFJlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRJbnB1dCxcblx0T25EZXN0cm95LFxuXHRPbkluaXQsXG5cdE91dHB1dCxcblx0UmVuZGVyZXIyLFxuXHRWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBhZGREYXlzIH0gZnJvbSAnZGF0ZS1mbnMnO1xuaW1wb3J0IHsgUHJpbWVOR0NvbmZpZyB9IGZyb20gJ3ByaW1lbmcvYXBpJztcbmltcG9ydCB7IENhbGVuZGFyIH0gZnJvbSAncHJpbWVuZy9jYWxlbmRhcic7XG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJ3N5c3RlbGFiLXRyYW5zbGF0ZSc7XG5pbXBvcnQgeyBEYXRhVHJhbnNmb3JtZXJTZXJ2aWNlIH0gZnJvbSAnLi9kYXRlLXRyYW5zZm9ybWVyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICAgICdzeXN0ZWxhYi1kYXRlcGlja2VyJyxcblx0dGVtcGxhdGVVcmw6ICdkYXRlcGlja2VyLmNvbXBvbmVudC5odG1sJyxcblx0cHJvdmlkZXJzOiAgIFtEYXRhVHJhbnNmb3JtZXJTZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBEYXRlcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBEb0NoZWNrLCBPbkRlc3Ryb3kge1xuXG5cdEBJbnB1dCgpIHB1YmxpYyBkaXNhYmxlZCA9IGZhbHNlO1xuXHRASW5wdXQoKSBwdWJsaWMgZXJyb3IgPSBmYWxzZTtcblx0QElucHV0KCkgcHVibGljIHJlcXVpcmVkID0gZmFsc2U7XG5cdEBJbnB1dCgpIHB1YmxpYyBpbnB1dEV4cGFuZEhlaWdodDogYm9vbGVhbjtcblx0QElucHV0KCkgcHVibGljIG1hcmtQcmV2aW91c0FmdGVyRGF0ZSA9IGZhbHNlO1xuXHRASW5wdXQoKSBwdWJsaWMgaW5wdXRGb250U2l6ZTogbnVtYmVyO1xuXHRASW5wdXQoKSBwdWJsaWMgc2hvd1RvZGF5QnV0dG9uID0gZmFsc2U7XG5cdEBJbnB1dCgpIHB1YmxpYyBpbmxpbmUgPSBmYWxzZTtcblx0QElucHV0KCkgcHVibGljIG1pbkRhdGU6IERhdGU7XG5cdEBJbnB1dCgpIHB1YmxpYyBtYXhEYXRlOiBEYXRlO1xuXHRASW5wdXQoKSBwdWJsaWMgd2FybkRheXNCZWZvcmU6IG51bWJlcjtcblx0QElucHV0KCkgcHVibGljIHdhcm5EYXlzQWZ0ZXI6IG51bWJlcjtcblx0QElucHV0KCkgcHVibGljIGF1dG9mb2N1cyA9IGZhbHNlO1xuXHRASW5wdXQoKSBwdWJsaWMgZnJvbURhdGVGb3JSZWxhdGl2ZURhdGVzOiBEYXRlO1xuXHRASW5wdXQoKSBwdWJsaWMgdGFiaW5kZXg6IG51bWJlcjtcblx0QElucHV0KCkgcHVibGljIHdpdGhJbnRlZ3JhdGVkVGltZSA9IGZhbHNlO1xuXHRASW5wdXQoKSBwdWJsaWMgb25seVRpbWUgPSBmYWxzZTtcblx0QElucHV0KCkgcHVibGljIHNob3dPdGhlck1vbnRocyA9IHRydWU7XG5cdEBJbnB1dCgpIHB1YmxpYyBzZWxlY3RPdGhlck1vbnRocyA9IGZhbHNlO1xuXHRASW5wdXQoKSBwdWJsaWMgZGF0ZUZvcm1hdDogc3RyaW5nO1xuXG5cdEBJbnB1dCgpXG5cdGdldCBjdXJyZW50RGF0ZSgpOiBEYXRlIHtcblx0XHRyZXR1cm4gdGhpcy5fY3VycmVudERhdGU7XG5cdH1cblxuXHRzZXQgY3VycmVudERhdGUodmFsdWU6IERhdGUpIHtcblx0XHR0aGlzLl9jdXJyZW50RGF0ZSA9IHZhbHVlO1xuXHRcdGlmICh0aGlzLm1hcmtQcmV2aW91c0FmdGVyRGF0ZSB8fCAodGhpcy53YXJuRGF5c0JlZm9yZSAmJiB0aGlzLndhcm5EYXlzQmVmb3JlID4gMCkpIHtcblxuXHRcdFx0aWYgKCF0aGlzLndhcm5EYXlzQmVmb3JlKSB7XG5cdFx0XHRcdHRoaXMud2FybkRheXNCZWZvcmUgPSAxO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmNoZWNrUHJldmlvdXNBZnRlckRhdGUoKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMud2FybkRheXNBZnRlciAmJiB0aGlzLndhcm5EYXlzQWZ0ZXIgPiAwKSB7XG5cdFx0XHR0aGlzLmNoZWNrVG9vRmFyRGF0ZSgpO1xuXHRcdH1cblx0fVxuXG5cdEBPdXRwdXQoKSBwdWJsaWMgY3VycmVudERhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPERhdGU+KCk7XG5cblx0QFZpZXdDaGlsZCgnY2FsZW5kYXInLCB7c3RhdGljOiB0cnVlfSkgcHVibGljIGN1cnJlbnRDYWxlbmRhcjogQ2FsZW5kYXI7XG5cblx0cHVibGljIGlucHV0Q2hhbmdlZCA9IGZhbHNlO1xuXHRwcm90ZWN0ZWQgX2N1cnJlbnREYXRlOiBEYXRlO1xuXHRwdWJsaWMgcHJldmlvdXNBZnRlckRhdGUgPSBmYWxzZTtcblx0cHVibGljIHRvb0ZhckRhdGUgPSBmYWxzZTtcblx0cHVibGljIGxhbmd1YWdlOiBhbnk7XG5cblx0cHVibGljIGN1cnJlbnREb2NTaXplOiBudW1iZXI7XG5cdHB1YmxpYyBjdXJyZW50TGFuZ3VhZ2U6IHN0cmluZztcblx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHlwZXNcblx0cHVibGljIGRlc3Ryb3lXaGVlbExpc3RlbmVyOiBGdW5jdGlvbjtcblx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHlwZXNcblx0cHVibGljIGRlc3Ryb3lLZXlMaXN0ZW5lcjogRnVuY3Rpb247XG5cdHB1YmxpYyBpbnB1dEVsZW1lbnQ6IEVsZW1lbnRSZWY7XG5cdHB1YmxpYyBmb2N1c0V2dDogRm9jdXNFdmVudDtcblx0cHVibGljIGlzVGFibGV0ID0gZmFsc2U7XG5cdHB1YmxpYyBkYXRlcGlja2VySWQ6IHN0cmluZyA9IChNYXRoLnJhbmRvbSgpICogKDk5OTk5OTk5OTk5OSAtIDEpKS50b1N0cmluZygpO1xuXHRwdWJsaWMgZm9ybWF0RXJyb3I6IGJvb2xlYW47XG5cblx0cHJpdmF0ZSBoZWFkZXJFbGVtZW50OiBhbnkgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmRhdGVwaWNrZXJJZCk7XG5cblx0Y29uc3RydWN0b3IocHJvdGVjdGVkIG15UmVuZGVyZXI6IFJlbmRlcmVyMiwgcHJvdGVjdGVkIGkxOG5TZXJ2aWNlOiBJMThuU2VydmljZSwgcHJvdGVjdGVkIGRhdGFUcmFuc2Zvcm1lclNlcnZpY2U6IERhdGFUcmFuc2Zvcm1lclNlcnZpY2UsIHByb3RlY3RlZCBjb25maWc6IFByaW1lTkdDb25maWcpIHtcblx0fVxuXG5cdHB1YmxpYyBuZ09uSW5pdCgpIHtcblx0XHR0aGlzLmdldExhbmd1YWdlKCk7XG5cblx0XHR0aGlzLmN1cnJlbnREb2NTaXplID0gd2luZG93LmlubmVyV2lkdGg7XG5cdFx0dGhpcy5jdXJyZW50TGFuZ3VhZ2UgPSB0aGlzLmkxOG5TZXJ2aWNlLmdldEN1cnJlbnRMYW5ndWFnZSgpO1xuXG5cdFx0dGhpcy5hZGRMaXN0ZW5lcnMoKTtcblx0XHRpZiAobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdpUGFkJykgPiAtMSB8fCBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0FuZHJvaWQnKSA+IC0xKSB7XG5cdFx0XHR0aGlzLmlzVGFibGV0ID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xuXHRcdGNvbnN0IG5ld0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpJyk7XG5cdFx0aWYgKCF0aGlzLmlubGluZSkge1xuXHRcdFx0bmV3RWxlbWVudC5jbGFzc05hbWUgPSB0aGlzLm9ubHlUaW1lID8gJ2ljb24tY2xvY2snIDogJ2ljb24tY2FsZW5kYXInO1xuXHRcdFx0aWYgKHRoaXMuY3VycmVudENhbGVuZGFyKSB7XG5cdFx0XHRcdGlmICh0aGlzLmF1dG9mb2N1cykge1xuXHRcdFx0XHRcdHRoaXMuY3VycmVudENhbGVuZGFyLmVsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXQnKVxuXHRcdFx0XHRcdFx0LmZvY3VzKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5jdXJyZW50Q2FsZW5kYXIuZWwubmF0aXZlRWxlbWVudC5jaGlsZE5vZGVzWzBdLmNsYXNzTmFtZSA9ICdwLWNhbGVuZGFyIHNsYWItZm9ybS1pY29uIHctMTAwJztcblx0XHRcdFx0dGhpcy5jdXJyZW50Q2FsZW5kYXIuZWwubmF0aXZlRWxlbWVudC5jaGlsZE5vZGVzWzBdLmFwcGVuZENoaWxkKG5ld0VsZW1lbnQpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAodGhpcy50YWJpbmRleCkge1xuXHRcdFx0dGhpcy5jdXJyZW50Q2FsZW5kYXIuZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdpbnB1dCcpXG5cdFx0XHRcdC5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgdGhpcy50YWJpbmRleCk7XG5cdFx0fVxuXG5cdH1cblxuXHRwdWJsaWMgbmdEb0NoZWNrKCkge1xuXHRcdGlmICh3aW5kb3cuaW5uZXJXaWR0aCAhPT0gdGhpcy5jdXJyZW50RG9jU2l6ZSkge1xuXHRcdFx0dGhpcy5jdXJyZW50RG9jU2l6ZSA9IHdpbmRvdy5pbm5lcldpZHRoO1xuXHRcdFx0dGhpcy5jbG9zZURhdGVwaWNrZXIoKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5oZWFkZXJFbGVtZW50ICE9PSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmRhdGVwaWNrZXJJZCkpIHtcblx0XHRcdHRoaXMuaGVhZGVyRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZGF0ZXBpY2tlcklkKTtcblx0XHRcdGlmICh0aGlzLmhlYWRlckVsZW1lbnQpIHtcblx0XHRcdFx0dGhpcy5yZXBvc2l0aW9uYXRlQ2FsZW5kYXIobmV3IEVsZW1lbnRSZWYodGhpcy5oZWFkZXJFbGVtZW50LnBhcmVudEVsZW1lbnQucGFyZW50RWxlbWVudCkpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICh0aGlzLmN1cnJlbnRMYW5ndWFnZSAhPT0gdGhpcy5pMThuU2VydmljZS5nZXRDdXJyZW50TGFuZ3VhZ2UoKSkge1xuXHRcdFx0dGhpcy5jdXJyZW50TGFuZ3VhZ2UgPSB0aGlzLmkxOG5TZXJ2aWNlLmdldEN1cnJlbnRMYW5ndWFnZSgpO1xuXHRcdFx0dGhpcy5nZXRMYW5ndWFnZSgpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcblx0XHR0aGlzLmRlc3Ryb3lLZXlMaXN0ZW5lcj8uKCk7XG5cdFx0dGhpcy5kZXN0cm95V2hlZWxMaXN0ZW5lcj8uKCk7XG5cdH1cblxuXHRwdWJsaWMgc2VsZWN0RGF0ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZvcm1hdEVycm9yID0gZmFsc2U7XG5cdFx0dGhpcy5jdXJyZW50RGF0ZUNoYW5nZS5lbWl0KHRoaXMuY3VycmVudERhdGUpO1xuXHRcdHRoaXMuaW5wdXRDaGFuZ2VkID0gZmFsc2U7XG5cdH1cblxuXHRwdWJsaWMgY2hhbmdlRGF0ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZvcm1hdEVycm9yID0gZmFsc2U7XG5cdFx0aWYgKHRoaXMuY3VycmVudENhbGVuZGFyPy5pbnB1dGZpZWxkVmlld0NoaWxkLm5hdGl2ZUVsZW1lbnQudmFsdWUgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0Y29uc3QgZGF0ZVN0ciA9IHRoaXMuY3VycmVudENhbGVuZGFyLmlucHV0ZmllbGRWaWV3Q2hpbGQubmF0aXZlRWxlbWVudC52YWx1ZS50cmltKClcblx0XHRcdFx0LnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRpZiAodGhpcy5pbnB1dENoYW5nZWQpIHtcblx0XHRcdFx0aWYgKGRhdGVTdHIubGVuZ3RoID49IDIpIHtcblx0XHRcdFx0XHRjb25zdCB0cmFuc2Zvcm1lZERhdGUgPSB0aGlzLmRhdGFUcmFuc2Zvcm1lclNlcnZpY2UucHJvY2Vzc1Nob3J0Y3V0cyhkYXRlU3RyLCB0aGlzLmZyb21EYXRlRm9yUmVsYXRpdmVEYXRlcyk7XG5cdFx0XHRcdFx0aWYgKHRyYW5zZm9ybWVkRGF0ZSkge1xuXHRcdFx0XHRcdFx0dGhpcy5jdXJyZW50RGF0ZSA9IHRyYW