UNPKG

truly-ui

Version:

Web Components for Desktop Applications.

201 lines (199 loc) 42.6 kB
/* MIT License Copyright (c) 2019 Temainfo Software Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewChild } from '@angular/core'; import { SlotSettingsType } from './types/slot-settings.type'; import { WorkScaleType } from './types/work-scale.type'; import { ScheduleI18n } from './i18n/schedule-i18n'; import * as i0 from "@angular/core"; import * as i1 from "./services/work-scale.service"; import * as i2 from "./services/event.service"; import * as i3 from "./services/holiday.service"; import * as i4 from "./services/generate-events.service"; import * as i5 from "@angular/common"; import * as i6 from "../blockui/blockui"; import * as i7 from "../button/button"; import * as i8 from "../loader/loader"; import * as i9 from "./views/day/view-day.component"; import * as i10 from "./views/week/week.component"; import * as i11 from "./views/day-list/day-list.component"; import * as i12 from "./parts/heading/heading.component"; export class TlSchedule { set events(events) { if (!events) { this._events = []; } else { this._events = [...events].sort((a, b) => a.date.start - b.date.start); this._events = JSON.parse(JSON.stringify(this._events)); this.setScrollTopOnChange(); } } get events() { return this._events; } constructor(workScaleService, changeDetection, eventService, holidayService, generateEventsService) { this.workScaleService = workScaleService; this.changeDetection = changeDetection; this.eventService = eventService; this.holidayService = holidayService; this.generateEventsService = generateEventsService; this.defaultView = 'day'; this.views = ['day', 'dayList', 'weekList']; this.currentDate = new Date(); this.height = '550px'; this.slotSettings = new SlotSettingsType(2, 43); this.workScale = new WorkScaleType('08:00', '18:00', 30); this.showNowIndicator = false; this.texts = ScheduleI18n; this.isLoading = false; this.holidays = []; this.allowScheduleInHolidays = false; this.changeView = new EventEmitter(); this.changeDate = new EventEmitter(); this.rowDbClick = new EventEmitter(); this.rowClick = new EventEmitter(); this.eventDbClick = new EventEmitter(); this.eventClick = new EventEmitter(); this.eventMouseover = new EventEmitter(); this.eventMouseout = new EventEmitter(); this.eventContextmenu = new EventEmitter(); this.newEventClick = new EventEmitter(); this.releaseSchedule = new EventEmitter(); this.existsScale = false; } ngOnInit() { this.convertSlarNumberToArray(); this.changeDetection.detectChanges(); } ngOnChanges(changes) { this.existsScale = this.workScaleService.exitsWorkScale(this.workScale); if (changes['holidays']) { this.handleHoliday(changes['holidays'].currentValue); } if (this.existsScale) { this.handleScrollView(); } this.changeDetection.detectChanges(); } onChangeView(view) { this.defaultView = view; this.changeView.emit(view); } onChangeDate($event) { this.currentDate = new Date($event.year, $event.month, $event.day); this.workScaleService.currentDate = new Date($event.year, $event.month, $event.day); this.eventService.getEventsOfDay(); this.changeDate.emit($event); this.handleHoliday(); this.changeDetection.detectChanges(); } onClickReleaseSchedule(holiday) { this.releaseSchedule.emit(holiday); } setScrollTopOnChange() { this.scrollTopOfscrollView = this.scheduleviews.nativeElement ? this.scheduleviews.nativeElement.scrollTop : 0; } handleScrollView(date = this.currentDate) { if (!this.scheduleviews) { return; } this.setScrollTopOnChange(); setTimeout(() => { this.scheduleviews.nativeElement.scrollTop = (this.isSameDay(date) ? this.generateEventsService.convertMillisecondsToPixel() : this.scrollTopOfscrollView); }, 100); } isSameDay(date) { const nowDate = new Date(); return date.getDate() === nowDate.getDate() && date.getDay() === nowDate.getDay() && date.getFullYear() === nowDate.getFullYear(); } handleHoliday(holidays = this.holidays) { this.currentHoliday = this.holidayService.handleHoliday(holidays, this.currentDate); this.changeDetection.detectChanges(); } convertSlarNumberToArray() { this.slatNumberRowsAsArray = Array(this.slotSettings.slotCount); this.changeDetection.detectChanges(); } } /** @nocollapse */ TlSchedule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlSchedule, deps: [{ token: i1.WorkScaleService }, { token: i0.ChangeDetectorRef }, { token: i2.EventService }, { token: i3.HolidayService }, { token: i4.GenerateEventsService }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ TlSchedule.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlSchedule, selector: "tl-schedule", inputs: { defaultView: "defaultView", views: "views", statusConfig: "statusConfig", typesConfig: "typesConfig", currentDate: "currentDate", height: "height", slotSettings: "slotSettings", workScale: "workScale", showNowIndicator: "showNowIndicator", texts: "texts", isLoading: "isLoading", eventButtonTemplate: "eventButtonTemplate", holidays: "holidays", allowScheduleInHolidays: "allowScheduleInHolidays", events: "events" }, outputs: { changeView: "changeView", changeDate: "changeDate", rowDbClick: "rowDbClick", rowClick: "rowClick", eventDbClick: "eventDbClick", eventClick: "eventClick", eventMouseover: "eventMouseover", eventMouseout: "eventMouseout", eventContextmenu: "eventContextmenu", newEventClick: "newEventClick", releaseSchedule: "releaseSchedule" }, viewQueries: [{ propertyName: "scheduleviews", first: true, predicate: ["scheduleviews"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"ui-wrapper-schedule\">\n\n <!-- SCHEDULE HEADER -->\n <div class=\"ui-schedule-header\">\n <tl-schedule-heading\n [texts]=\"texts\"\n [views]=\"views\"\n [defaultView]=\"defaultView\"\n [currentDate]=\"currentDate\"\n [eventButtonTemplate]=\"eventButtonTemplate\"\n (changeView)=\"onChangeView($event)\"\n (changeDate)=\"onChangeDate($event)\"\n (newEventClick)=\"newEventClick.emit()\"\n ></tl-schedule-heading>\n </div>\n\n <!-- SCHEDULE BODY -->\n <div class=\"ui-schedule-body\"\n [tlBlockui]=\"(currentHoliday?.id && !allowScheduleInHolidays && !currentHoliday?.attend) && existsScale\"\n [blockuiConfig]=\"{ message: currentHoliday?.description, icon: 'fas fa-umbrella-beach', color: '#ccc' }\"\n [ngStyle]=\"{height: 'calc(' + height +' - 52px)'} \" [ngSwitch]=\"defaultView\">\n <div class=\"loading\" *ngIf=\"isLoading\">\n <div class=\"loader\">\n <tl-loader></tl-loader>\n </div>\n </div>\n <div class=\"holiday\" *ngIf=\"(currentHoliday?.id && !allowScheduleInHolidays && !currentHoliday?.attend) && existsScale\">\n <div class=\"ms-button-attend\">\n <tl-button (click)=\"onClickReleaseSchedule(currentHoliday)\" [text]=\"'Liberar Atendimento'\" [color]=\"'primary'\"></tl-button>\n </div>\n </div>\n <div class=\"ui-schedule-views\" #scheduleviews [tlBlockui]=\"(!workScale || !existsScale)\"\n [blockuiConfig]=\"{ message: texts.scaleNotFound, icon: 'fas fa-address-book', color: '#ccc' }\"\n [ngStyle]=\"{overflowY: !existsScale ? 'hidden' : 'visible'}\">\n <tl-view-day\n *ngSwitchCase=\"'day'\"\n [currentDate]=\"currentDate\"\n [showNowIndicator]=\"showNowIndicator\"\n [statusConfig]=\"statusConfig\"\n [typesConfig]=\"typesConfig\"\n [events]=\"events\"\n [slotSettings]=\"slotSettings\"\n [slatNumberRowsAsArray]=\"slatNumberRowsAsArray\"\n [workScale]=\"workScale\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-view-day>\n\n <tl-week\n *ngSwitchCase=\"'weekList'\"\n [showNowIndicator]=\"showNowIndicator\"\n [statusConfig]=\"statusConfig\"\n [typesConfig]=\"typesConfig\"\n [events]=\"events\"\n [slotSettings]=\"slotSettings\"\n [slatNumberRowsAsArray]=\"slatNumberRowsAsArray\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-week>\n\n <tl-day-list\n *ngSwitchCase=\"'dayList'\"\n [statusConfig]=\"statusConfig\"\n [events]=\"events\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-day-list>\n\n <!--<tl-day-list-->\n <!--*ngSwitchCase=\"'dayList'\"-->\n <!--[events]=\"eventsOfDay\"-->\n <!--[currentDate]=\"currentDate\"-->\n <!--[statusConfig]=\"statusConfig\"-->\n <!--(onEventClick)=\"eventClick.emit($event)\"-->\n <!--(onEventDbClick)=\"eventDbClick.emit($event)\"-->\n <!--(onEventMouseover)=\"eventMouseover.emit($event)\"-->\n <!--(onEventMouseout)=\"eventMouseout.emit($event)\"-->\n <!--&gt;</tl-day-list>-->\n </div>\n </div>\n\n <!-- SCHEDULE FOOTER -->\n <div class=\"schedule-footer\"></div>\n</div>\n", styles: [".ui-wrapper-schedule{width:100%}.loading{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.loading .loader{width:50px;height:50px}.holiday{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.holiday .ms-button-attend{margin-top:120px}.ui-schedule-header{border-top:1px solid #D6D6D6;border-left:1px solid #D6D6D6;border-right:1px solid #D6D6D6;box-sizing:border-box;height:50px;width:100%}.ui-schedule-body{border:1px solid #D6D6D6;position:relative}.ui-schedule-views{height:100%;width:100%;box-sizing:content-box;overflow-x:hidden;overflow-y:visible;position:relative}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i6.TlBlockUI, selector: "[tlBlockui]", inputs: ["tlBlockui", "dimensionsFrom", "blockuiConfig"] }, { kind: "component", type: i7.TlButton, selector: "tl-button", inputs: ["text", "iconAddonBefore", "iconAddonAfter", "iconBeforeText", "iconAfterText", "height", "width", "disabled", "flatBorder", "colorIconBefore", "colorIconAfter", "template", "outline", "color", "loaderColor", "isLoading", "indexShortcut", "textLoading"], outputs: ["selected"] }, { kind: "component", type: i8.TlLoader, selector: "tl-loader", inputs: ["color", "strokeWidth"] }, { kind: "component", type: i9.ViewDayComponent, selector: "tl-view-day", inputs: ["currentDate", "statusConfig", "typesConfig", "showNowIndicator", "slotSettings", "workScale", "slatNumberRowsAsArray", "texts", "events"], outputs: ["onRowDbClick", "onRowClick", "onEventDbClick", "onEventClick", "onEventMouseover", "onEventMouseout", "onEventContextmenu"] }, { kind: "component", type: i10.WeekComponent, selector: "tl-week", inputs: ["statusConfig", "typesConfig", "showNowIndicator", "slotSettings", "workScale", "slatNumberRowsAsArray", "texts", "events"], outputs: ["onRowDbClick", "onRowClick", "onEventDbClick", "onEventClick", "onEventMouseover", "onEventMouseout", "onEventContextmenu"] }, { kind: "component", type: i11.DayListComponent, selector: "tl-day-list", inputs: ["events", "statusConfig", "currentDate"], outputs: ["onEventDbClick", "onEventClick", "onEventMouseover", "onEventMouseout"] }, { kind: "component", type: i12.HeadingComponent, selector: "tl-schedule-heading", inputs: ["views", "defaultView", "currentDate", "texts", "eventButtonTemplate"], outputs: ["changeView", "changeDate", "newEventClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlSchedule, decorators: [{ type: Component, args: [{ selector: 'tl-schedule', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-wrapper-schedule\">\n\n <!-- SCHEDULE HEADER -->\n <div class=\"ui-schedule-header\">\n <tl-schedule-heading\n [texts]=\"texts\"\n [views]=\"views\"\n [defaultView]=\"defaultView\"\n [currentDate]=\"currentDate\"\n [eventButtonTemplate]=\"eventButtonTemplate\"\n (changeView)=\"onChangeView($event)\"\n (changeDate)=\"onChangeDate($event)\"\n (newEventClick)=\"newEventClick.emit()\"\n ></tl-schedule-heading>\n </div>\n\n <!-- SCHEDULE BODY -->\n <div class=\"ui-schedule-body\"\n [tlBlockui]=\"(currentHoliday?.id && !allowScheduleInHolidays && !currentHoliday?.attend) && existsScale\"\n [blockuiConfig]=\"{ message: currentHoliday?.description, icon: 'fas fa-umbrella-beach', color: '#ccc' }\"\n [ngStyle]=\"{height: 'calc(' + height +' - 52px)'} \" [ngSwitch]=\"defaultView\">\n <div class=\"loading\" *ngIf=\"isLoading\">\n <div class=\"loader\">\n <tl-loader></tl-loader>\n </div>\n </div>\n <div class=\"holiday\" *ngIf=\"(currentHoliday?.id && !allowScheduleInHolidays && !currentHoliday?.attend) && existsScale\">\n <div class=\"ms-button-attend\">\n <tl-button (click)=\"onClickReleaseSchedule(currentHoliday)\" [text]=\"'Liberar Atendimento'\" [color]=\"'primary'\"></tl-button>\n </div>\n </div>\n <div class=\"ui-schedule-views\" #scheduleviews [tlBlockui]=\"(!workScale || !existsScale)\"\n [blockuiConfig]=\"{ message: texts.scaleNotFound, icon: 'fas fa-address-book', color: '#ccc' }\"\n [ngStyle]=\"{overflowY: !existsScale ? 'hidden' : 'visible'}\">\n <tl-view-day\n *ngSwitchCase=\"'day'\"\n [currentDate]=\"currentDate\"\n [showNowIndicator]=\"showNowIndicator\"\n [statusConfig]=\"statusConfig\"\n [typesConfig]=\"typesConfig\"\n [events]=\"events\"\n [slotSettings]=\"slotSettings\"\n [slatNumberRowsAsArray]=\"slatNumberRowsAsArray\"\n [workScale]=\"workScale\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-view-day>\n\n <tl-week\n *ngSwitchCase=\"'weekList'\"\n [showNowIndicator]=\"showNowIndicator\"\n [statusConfig]=\"statusConfig\"\n [typesConfig]=\"typesConfig\"\n [events]=\"events\"\n [slotSettings]=\"slotSettings\"\n [slatNumberRowsAsArray]=\"slatNumberRowsAsArray\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-week>\n\n <tl-day-list\n *ngSwitchCase=\"'dayList'\"\n [statusConfig]=\"statusConfig\"\n [events]=\"events\"\n (onEventContextmenu)=\"eventContextmenu.emit($event)\"\n (onRowClick)=\"rowClick.emit($event)\"\n (onRowDbClick)=\"rowDbClick.emit($event)\"\n (onEventClick)=\"eventClick.emit($event)\"\n (onEventDbClick)=\"eventDbClick.emit($event)\"\n (onEventMouseover)=\"eventMouseover.emit($event)\"\n (onEventMouseout)=\"eventMouseout.emit($event)\"\n ></tl-day-list>\n\n <!--<tl-day-list-->\n <!--*ngSwitchCase=\"'dayList'\"-->\n <!--[events]=\"eventsOfDay\"-->\n <!--[currentDate]=\"currentDate\"-->\n <!--[statusConfig]=\"statusConfig\"-->\n <!--(onEventClick)=\"eventClick.emit($event)\"-->\n <!--(onEventDbClick)=\"eventDbClick.emit($event)\"-->\n <!--(onEventMouseover)=\"eventMouseover.emit($event)\"-->\n <!--(onEventMouseout)=\"eventMouseout.emit($event)\"-->\n <!--&gt;</tl-day-list>-->\n </div>\n </div>\n\n <!-- SCHEDULE FOOTER -->\n <div class=\"schedule-footer\"></div>\n</div>\n", styles: [".ui-wrapper-schedule{width:100%}.loading{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.loading .loader{width:50px;height:50px}.holiday{z-index:1;width:100%;height:100%;position:absolute;display:flex;align-items:center;justify-content:center}.holiday .ms-button-attend{margin-top:120px}.ui-schedule-header{border-top:1px solid #D6D6D6;border-left:1px solid #D6D6D6;border-right:1px solid #D6D6D6;box-sizing:border-box;height:50px;width:100%}.ui-schedule-body{border:1px solid #D6D6D6;position:relative}.ui-schedule-views{height:100%;width:100%;box-sizing:content-box;overflow-x:hidden;overflow-y:visible;position:relative}\n"] }] }], ctorParameters: function () { return [{ type: i1.WorkScaleService }, { type: i0.ChangeDetectorRef }, { type: i2.EventService }, { type: i3.HolidayService }, { type: i4.GenerateEventsService }]; }, propDecorators: { defaultView: [{ type: Input }], views: [{ type: Input }], statusConfig: [{ type: Input }], typesConfig: [{ type: Input }], currentDate: [{ type: Input }], height: [{ type: Input }], slotSettings: [{ type: Input }], workScale: [{ type: Input }], showNowIndicator: [{ type: Input }], texts: [{ type: Input }], isLoading: [{ type: Input }], eventButtonTemplate: [{ type: Input }], holidays: [{ type: Input }], allowScheduleInHolidays: [{ type: Input }], events: [{ type: Input, args: ['events'] }], changeView: [{ type: Output }], changeDate: [{ type: Output }], rowDbClick: [{ type: Output }], rowClick: [{ type: Output }], eventDbClick: [{ type: Output }], eventClick: [{ type: Output }], eventMouseover: [{ type: Output }], eventMouseout: [{ type: Output }], eventContextmenu: [{ type: Output }], newEventClick: [{ type: Output }], releaseSchedule: [{ type: Output }], scheduleviews: [{ type: ViewChild, args: ['scheduleviews', { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZWR1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90cnVseS11aS9zcmMvY29tcG9uZW50cy9zY2hlZHVsZS9zY2hlZHVsZS50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL3NjaGVkdWxlL3NjaGVkdWxlLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBSUwsTUFBTSxFQUNOLFlBQVksRUFFWix1QkFBdUIsRUFDVixTQUFTLEVBQ3ZCLE1BQU0sZUFBZSxDQUFDO0FBSXZCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzlELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUd4RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7Ozs7Ozs7Ozs7O0FBV3BELE1BQU0sT0FBTyxVQUFVO0lBOEJyQixJQUFxQixNQUFNLENBQUUsTUFBNEI7UUFDdkQsSUFBSyxDQUFDLE1BQU0sRUFBRTtZQUNaLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1NBQ25CO2FBQU07WUFDTCxJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBRSxDQUFDLEVBQUUsQ0FBQyxFQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBRyxDQUFDO1lBQzNFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBRSxDQUFDO1lBQzFELElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFD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QUFqQixLQUFLO2dCQUVHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFFZSxNQUFNO3NCQUExQixLQUFLO3VCQUFDLFFBQVE7Z0JBVUwsVUFBVTtzQkFBbkIsTUFBTTtnQkFFRyxVQUFVO3NCQUFuQixNQUFNO2dCQUVHLFVBQVU7c0JBQW5CLE1BQU07Z0JBRUcsUUFBUTtzQkFBakIsTUFBTTtnQkFFRyxZQUFZO3NCQUFyQixNQUFNO2dCQUVHLFVBQVU7c0JBQW5CLE1BQU07Z0JBRUcsY0FBYztzQkFBdkIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNO2dCQUVHLGdCQUFnQjtzQkFBekIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNO2dCQUVHLGVBQWU7c0JBQXhCLE1BQU07Z0JBRXVDLGFBQWE7c0JBQTFELFNBQVM7dUJBQUMsZUFBZSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gTUlUIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAxOSBUZW1haW5mbyBTb2Z0d2FyZVxuXG4gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiBTT0ZUV0FSRS5cbiAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTY2hlZHVsZURhdGFTb3VyY2UgfSBmcm9tICcuL3R5cGVzL2RhdGFzb3VyY2UudHlwZSc7XG5pbXBvcnQgeyBTdGF0dXNUeXBlIH0gZnJvbSAnLi90eXBlcy9zdGF0dXMudHlwZSc7XG5pbXBvcnQgeyBWaWV3VHlwZSB9IGZyb20gJy4vdHlwZXMvdmlldy50eXBlJztcbmltcG9ydCB7IFNsb3RTZXR0aW5nc1R5cGUgfSBmcm9tICcuL3R5cGVzL3Nsb3Qtc2V0dGluZ3MudHlwZSc7XG5pbXBvcnQgeyBXb3JrU2NhbGVUeXBlIH0gZnJvbSAnLi90eXBlcy93b3JrLXNjYWxlLnR5cGUnO1xuaW1wb3J0IHsgV29ya1NjYWxlU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvd29yay1zY2FsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEV2ZW50U2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvZXZlbnQuc2VydmljZSc7XG5pbXBvcnQgeyBTY2hlZHVsZUkxOG4gfSBmcm9tICcuL2kxOG4vc2NoZWR1bGUtaTE4bic7XG5pbXBvcnQgeyBIb2xpZGF5c1R5cGUgfSBmcm9tICcuL3R5cGVzL2hvbGlkYXlzLnR5cGUnO1xuaW1wb3J0IHsgSG9saWRheVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2hvbGlkYXkuc2VydmljZSc7XG5pbXBvcnQgeyBHZW5lcmF0ZUV2ZW50c1NlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2dlbmVyYXRlLWV2ZW50cy5zZXJ2aWNlJztcblxuQENvbXBvbmVudCgge1xuICBzZWxlY3RvcjogJ3RsLXNjaGVkdWxlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NjaGVkdWxlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsgJy4vc2NoZWR1bGUuc2NzcycgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgVGxTY2hlZHVsZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoKSBkZWZhdWx0VmlldzogVmlld1R5cGUgPSAnZGF5JztcblxuICBASW5wdXQoKSB2aWV3czogQXJyYXk8Vmlld1R5cGU+ID0gWyAnZGF5JywgJ2RheUxpc3QnLCAnd2Vla0xpc3QnIF07XG5cbiAgQElucHV0KCkgc3RhdHVzQ29uZmlnOiBTdGF0dXNUeXBlO1xuXG4gIEBJbnB1dCgpIHR5cGVzQ29uZmlnOiBhbnk7XG5cbiAgQElucHV0KCkgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIEBJbnB1dCgpIGhlaWdodCA9ICc1NTBweCc7XG5cbiAgQElucHV0KCkgc2xvdFNldHRpbmdzOiBTbG90U2V0dGluZ3NUeXBlID0gbmV3IFNsb3RTZXR0aW5nc1R5cGUoICAyLCA0Myk7XG5cbiAgQElucHV0KCkgd29ya1NjYWxlOiBXb3JrU2NhbGVUeXBlIHwgV29ya1NjYWxlVHlwZVtdID0gbmV3IFdvcmtTY2FsZVR5cGUoICcwODowMCcsICcxODowMCcsIDMwICk7XG5cbiAgQElucHV0KCkgc2hvd05vd0luZGljYXRvciA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIHRleHRzID0gU2NoZWR1bGVJMThuO1xuXG4gIEBJbnB1dCgpIGlzTG9hZGluZyA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGV2ZW50QnV0dG9uVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgQElucHV0KCkgaG9saWRheXM6IEFycmF5PEhvbGlkYXlzVHlwZT4gPSBbXTtcblxuICBASW5wdXQoKSBhbGxvd1NjaGVkdWxlSW5Ib2xpZGF5cyA9IGZhbHNlO1xuXG4gIEBJbnB1dCgnZXZlbnRzJykgc2V0IGV2ZW50cyggZXZlbnRzOiBTY2hlZHVsZURhdGFTb3VyY2VbXSkge1xuICAgIGlmICggIWV2ZW50cykge1xuICAgICAgdGhpcy5fZXZlbnRzID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2V2ZW50cyA9IFsuLi5ldmVudHNdLnNvcnQoKCBhLCBiICkgPT4gYS5kYXRlLnN0YXJ0IC0gYi5kYXRlLnN0YXJ0ICApO1xuICAgICAgdGhpcy5fZXZlbnRzID0gSlNPTi5wYXJzZSggSlNPTi5zdHJpbmdpZnkodGhpcy5fZXZlbnRzKSApO1xuICAgICAgdGhpcy5zZXRTY3JvbGxUb3BPbkNoYW5nZSgpO1xuICAgIH1cbiAgfVxuXG4gIEBPdXRwdXQoKSBjaGFuZ2VWaWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxWaWV3VHlwZT4oKTtcblxuICBAT3V0cHV0KCkgY2hhbmdlRGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgcm93RGJDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgcm93Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIGV2ZW50RGJDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgZXZlbnRDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgZXZlbnRNb3VzZW92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIGV2ZW50TW91c2VvdXQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIGV2ZW50Q29udGV4dG1lbnUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIG5ld0V2ZW50Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIHJlbGVhc2VTY2hlZHVsZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAVmlld0NoaWxkKCdzY2hlZHVsZXZpZXdzJywgeyBzdGF0aWM6IHRydWUgfSkgc2NoZWR1bGV2aWV3cztcblxuICBwdWJsaWMgc2xhdE51bWJlclJvd3NBc0FycmF5OiBBcnJheTxOdW1iZXI+O1xuXG4gIHB1YmxpYyBleGlzdHNTY2FsZSA9IGZhbHNlO1xuXG4gIHB1YmxpYyBjdXJyZW50SG9saWRheTogSG9saWRheXNUeXBlO1xuXG4gIHByaXZhdGUgX2V2ZW50czogU2NoZWR1bGVEYXRhU291cmNlW107XG5cbiAgcHJpdmF0ZSBzY3JvbGxUb3BPZnNjcm9sbFZpZXc6IG51bWJlcjtcblxuICBnZXQgZXZlbnRzKCk6IFNjaGVkdWxlRGF0YVNvdXJjZVtdIHtcbiAgICByZXR1cm4gdGhpcy5fZXZlbnRzO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHdvcmtTY2FsZVNlcnZpY2U6IFdvcmtTY2FsZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHByaXZhdGUgZXZlbnRTZXJ2aWNlOiBFdmVudFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBob2xpZGF5U2VydmljZTogSG9saWRheVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUV2ZW50c1NlcnZpY2U6IEdlbmVyYXRlRXZlbnRzU2VydmljZVxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5jb252ZXJ0U2xhck51bWJlclRvQXJyYXkoKTtcbiAgICB0aGlzLmNoYW5nZURldGVjdGlvbi5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyggY2hhbmdlczogU2ltcGxlQ2hhbmdlcyApIHtcbiAgICB0aGlzLmV4aXN0c1NjYWxlID0gdGhpcy53b3JrU2NhbGVTZXJ2aWNlLmV4aXRzV29ya1NjYWxlKCB0aGlzLndvcmtTY2FsZSApO1xuICAgIGlmICggY2hhbmdlc1snaG9saWRheXMnXSApIHtcbiAgICAgIHRoaXMuaGFuZGxlSG9saWRheSggY2hhbmdlc1snaG9saWRheXMnXS5jdXJyZW50VmFsdWUgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZXhpc3RzU2NhbGUgKSB7XG4gICAgICB0aGlzLmhhbmRsZVNjcm9sbFZpZXcoKTtcbiAgICB9XG4gICAgdGhpcy5jaGFuZ2VEZXRlY3Rpb24uZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgb25DaGFuZ2VWaWV3KCB2aWV3OiBWaWV3VHlwZSApIHtcbiAgICB0aGlzLmRlZmF1bHRWaWV3ID0gdmlldztcbiAgICB0aGlzLmNoYW5nZVZpZXcuZW1pdCggdmlldyApO1xuICB9XG5cbiAgb25DaGFuZ2VEYXRlKCRldmVudCkge1xuICAgIHRoaXMuY3VycmVudERhdGUgPSBuZXcgRGF0ZSggJGV2ZW50LnllYXIsICRldmVudC5tb250aCwgJGV2ZW50LmRheSk7XG4gICAgdGhpcy53b3JrU2NhbGVTZXJ2aWNlLmN1cnJlbnREYXRlID0gbmV3IERhdGUoICRldmVudC55ZWFyLCAkZXZlbnQubW9udGgsICRldmVudC5kYXkpO1xuICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmdldEV2ZW50c09mRGF5KCk7XG4gICAgdGhpcy5jaGFuZ2VEYXRlLmVtaXQoICRldmVudCApO1xuICAgIHRoaXMuaGFuZGxlSG9saWRheSgpO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIG9uQ2xpY2tSZWxlYXNlU2NoZWR1bGUoIGhvbGlkYXk6IEhvbGlkYXlzVHlwZSApIHtcbiAgICB0aGlzLnJlbGVhc2VTY2hlZHVsZS5lbWl0KCBob2xpZGF5ICk7XG4gIH1cblxuICBwcml2YXRlIHNldFNjcm9sbFRvcE9uQ2hhbmdlKCkge1xuICAgIHRoaXMuc2Nyb2xsVG9wT2ZzY3JvbGxWaWV3ID0gdGhpcy5zY2hlZHVsZXZpZXdzLm5hdGl2ZUVsZW1lbnQgPyB0aGlzLnNjaGVkdWxldmlld3MubmF0aXZlRWxlbWVudC5zY3JvbGxUb3AgOiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVTY3JvbGxWaWV3KCBkYXRlID0gdGhpcy5jdXJyZW50RGF0ZSkge1xuICAgIGlmICggIXRoaXMuc2NoZWR1bGV2aWV3cyApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zZXRTY3JvbGxUb3BPbkNoYW5nZSgpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5zY2hlZHVsZXZpZXdzLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gKFxuICAgICAgICB0aGlzLmlzU2FtZURheSggZGF0ZSApID8gdGhpcy5nZW5lcmF0ZUV2ZW50c1NlcnZpY2UuY29udmVydE1pbGxpc2Vjb25kc1RvUGl4ZWwoKSA6IHRoaXMuc2Nyb2xsVG9wT2ZzY3JvbGxWaWV3XG4gICAgICApO1xuICAgIH0sIDEwMCk7XG4gIH1cblxuICBwcml2YXRlIGlzU2FtZURheSggZGF0ZSApIHtcbiAgICBjb25zdCBub3dEYXRlID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gZGF0ZS5nZXREYXRlKCkgPT09IG5vd0RhdGUuZ2V0RGF0ZSgpICYmXG4gICAgICAgICAgIGRhdGUuZ2V0RGF5KCkgPT09IG5vd0RhdGUuZ2V0RGF5KCkgJiZcbiAgICAgICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpID09PSBub3dEYXRlLmdldEZ1bGxZZWFyKCk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUhvbGlkYXkoIGhvbGlkYXlzID0gdGhpcy5ob2xpZGF5cyApIHtcbiAgICB0aGlzLmN1cnJlbnRIb2xpZGF5ID0gdGhpcy5ob2xpZGF5U2VydmljZS5oYW5kbGVIb2xpZGF5KCBob2xpZGF5cywgdGhpcy5jdXJyZW50RGF0ZSApO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHByaXZhdGUgY29udmVydFNsYXJOdW1iZXJUb0FycmF5KCkge1xuICAgIHRoaXMuc2xhdE51bWJlclJvd3NBc0FycmF5ID0gQXJyYXkoIHRoaXMuc2xvdFNldHRpbmdzLnNsb3RDb3VudCApO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLmRldGVjdENoYW5nZXMoKTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInVpLXdyYXBwZXItc2NoZWR1bGVcIj5cblxuICA8IS0tIFNDSEVEVUxFIEhFQURFUiAtLT5cbiAgPGRpdiBjbGFzcz1cInVpLXNjaGVkdWxlLWhlYWRlclwiPlxuICAgIDx0bC1zY2hlZHVsZS1oZWFkaW5nXG4gICAgICBbdGV4dHNdPVwidGV4dHNcIlxuICAgICAgW3ZpZXdzXT1cInZpZXdzXCJcbiAgICAgIFtkZWZhdWx0Vmlld109XCJkZWZhdWx0Vmlld1wiXG4gICAgICBbY3VycmVudERhdGVdPVwiY3VycmVudERhdGVcIlxuICAgICAgW2V2ZW50QnV0dG9uVGVtcGxhdGVdPVwiZXZlbnRCdXR0b25UZW1wbGF0ZVwiXG4gICAgICAoY2hhbmdlVmlldyk9XCJvbkNoYW5nZVZpZXcoJGV2ZW50KVwiXG4gICAgICAoY2hhbmdlRGF0ZSk9XCJvbkNoYW5nZURhdGUoJGV2ZW50KVwiXG4gICAgICAobmV3RXZlbnRDbGljayk9XCJuZXdFdmVudENsaWNrLmVtaXQoKVwiXG4gICAgPjwvdGwtc2NoZWR1bGUtaGVhZGluZz5cbiAgPC9kaXY+XG5cbiAgPCEtLSBTQ0hFRFVMRSBCT0RZIC0tPlxuICA8ZGl2ICBjbGFzcz1cInVpLXNjaGVkdWxlLWJvZHlcIlxuICAgICAgICBbdGxCbG9ja3VpXT1cIihjdXJyZW50SG9saWRheT8uaWQgJiYgIWFsbG93U2NoZWR1bGVJbkhvbGlkYXlzICYmICFjdXJyZW50SG9saWRheT8uYXR0ZW5kKSAmJiBleGlzdHNTY2FsZVwiXG4gICAgICAgIFtibG9ja3VpQ29uZmlnXT1cInsgbWVzc2FnZTogY3VycmVudEhvbGlkYXk/LmRlc2NyaXB0aW9uLCBpY29uOiAnZmFzIGZhLXVtYnJlbGxhLWJlYWNoJywgY29sb3I6ICcjY2NjJyB9XCJcbiAgICAgICAgW25nU3R5bGVdPVwie2hlaWdodDogJ2NhbGMoJyArIGhlaWdodCArJyAtIDUycHgpJ30gXCIgW25nU3dpdGNoXT1cImRlZmF1bHRWaWV3XCI+XG4gICAgPGRpdiBjbGFzcz1cImxvYWRpbmdcIiAqbmdJZj1cImlzTG9hZGluZ1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImxvYWRlclwiPlxuICAgICAgICA8dGwtbG9hZGVyPjwvdGwtbG9hZGVyPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImhvbGlkYXlcIiAqbmdJZj1cIihjdXJyZW50SG9saWRheT8uaWQgJiYgIWFsbG93U2NoZWR1bGVJbkhvbGlkYXlzICYmICFjdXJyZW50SG9saWRheT8uYXR0ZW5kKSAmJiBleGlzdHNTY2FsZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cIm1zLWJ1dHRvbi1hdHRlbmRcIj5cbiAgICAgICAgPHRsLWJ1dHRvbiAoY2xpY2spPVwib25DbGlja1JlbGVhc2VTY2hlZHVsZShjdXJyZW50SG9saWRheSlcIiBbdGV4dF09XCInTGliZXJhciBBdGVuZGltZW50bydcIiBbY29sb3JdPVwiJ3ByaW1hcnknXCI+PC90bC1idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwidWktc2NoZWR1bGUtdmlld3NcIiAgI3NjaGVkdWxldmlld3MgW3RsQmxvY2t1aV09XCIoIXdvcmtTY2FsZSB8fCAhZXhpc3RzU2NhbGUpXCJcbiAgICAgICAgIFtibG9ja3VpQ29uZmlnXT1cInsgbWVzc2FnZTogdGV4dHMuc2NhbGVOb3RGb3VuZCwgaWNvbjogJ2ZhcyBmYS1hZGRyZXNzLWJvb2snLCBjb2xvcjogJyNjY2MnIH1cIlxuICAgICAgICAgW25nU3R5bGVdPVwie292ZXJmbG93WTogIWV4aXN0c1NjYWxlID8gJ2hpZGRlbicgOiAndmlzaWJsZSd9XCI+XG4gICAgICA8dGwtdmlldy1kYXlcbiAgICAgICAgKm5nU3dpdGNoQ2FzZT1cIidkYXknXCJcbiAgICAgICAgW2N1cnJlbnREYXRlXT1cImN1cnJlbnREYXRlXCJcbiAgICAgICAgW3Nob3dOb3dJbmRpY2F0b3JdPVwic2hvd05vd0luZGljYXRvclwiXG4gICAgICAgIFtzdGF0dXNDb25maWddPVwic3RhdHVzQ29uZmlnXCJcbiAgICAgICAgW3R5cGVzQ29uZmlnXT1cInR5cGVzQ29uZmlnXCJcbiAgICAgICAgW2V2ZW50c109XCJldmVudHNcIlxuICAgICAgICBbc2xvdFNldHRpbmdzXT1cInNsb3RTZXR0aW5nc1wiXG4gICAgICAgIFtzbGF0TnVtYmVyUm93c0FzQXJyYXldPVwic2xhdE51bWJlclJvd3NBc0FycmF5XCJcbiAgICAgICAgW3dvcmtTY2FsZV09XCJ3b3JrU2NhbGVcIlxuICAgICAgICAob25FdmVudENvbnRleHRtZW51KT1cImV2ZW50Q29udGV4dG1lbnUuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgKG9uUm93Q2xpY2spPVwicm93Q2xpY2suZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgKG9uUm93RGJDbGljayk9XCJyb3dEYkNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgIChvbkV2ZW50Q2xpY2spPVwiZXZlbnRDbGljay5lbWl0KCRldmVudClcIlxuICAgICAgICAob25FdmVudERiQ2xpY2spPVwiZXZlbnREYkNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgIChvbkV2ZW50TW91c2VvdmVyKT1cImV2ZW50TW91c2VvdmVyLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgIChvbkV2ZW50TW91c2VvdXQpPVwiZXZlbnRNb3VzZW91dC5lbWl0KCRldmVudClcIlxuICAgICAgPjwvdGwtdmlldy1kYXk+XG5cbiAgICAgIDx0bC13ZWVrXG4gICAgICAqbmdTd2l0Y2hDYXNlPVwiJ3dlZWtMaXN0J1wiXG4gICAgICBbc2hvd05vd0luZGljYXRvcl09XCJzaG93Tm93SW5kaWNhdG9yXCJcbiAgICAgIFtzdGF0dXNDb25maWddPVwic3RhdHVzQ29uZmlnXCJcbiAgICAgIFt0eXBlc0NvbmZpZ109XCJ0eXBlc0NvbmZpZ1wiXG4gICAgICBbZXZlbnRzXT1cImV2ZW50c1wiXG4gICAgICBbc2xvdFNldHRpbmdzXT1cInNsb3RTZXR0aW5nc1wiXG4gICAgICBbc2xhdE51bWJlclJvd3NBc0FycmF5XT1cInNsYXROdW1iZXJSb3dzQXNBcnJheVwiXG4gICAgICAob25FdmVudENvbnRleHRtZW51KT1cImV2ZW50Q29udGV4dG1lbnUuZW1pdCgkZXZlbnQpXCJcbiAgICAgIChvblJvd0NsaWNrKT1cInJvd0NsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAob25Sb3dEYkNsaWNrKT1cInJvd0RiQ2xpY2suZW1pdCgkZXZlbnQpXCJcbiAgICAgIChvbkV2ZW50Q2xpY2spPVwiZXZlbnRDbGljay5lbWl0KCRldmVudClcIlxuICAgICAgKG9uRXZlbnREYkNsaWNrKT1cImV2ZW50RGJDbGljay5lbWl0KCRldmVudClcIlxuICAgICAgKG9uRXZlbnRNb3VzZW92ZXIpPVwiZXZlbnRNb3VzZW92ZXIuZW1pdCgkZXZlbnQpXCJcbiAgICAgIChvbkV2ZW50TW91c2VvdXQpPVwiZXZlbnRNb3VzZW91dC5lbWl0KCRldmVudClcIlxuICAgICAgPjwvdGwtd2Vlaz5cblxuICAgICAgPHRsLWRheS1saXN0XG4gICAgICAqbmdTd2l0Y2hDYXNlPVwiJ2RheUxpc3QnXCJcbiAgICAgIFtzdGF0dXNDb25maWddPVwic3RhdHVzQ29uZmlnXCJcbiAgICAgIFtldmVudHNdPVwiZXZlbnRzXCJcbiAgICAgIChvbkV2ZW50Q29udGV4dG1lbnUpPVwiZXZlbnRDb250ZXh0bWVudS5lbWl0KCRldmVudClcIlxuICAgICAgKG9uUm93Q2xpY2spPVwicm93Q2xpY2suZW1pdCgkZXZlbnQpXCJcbiAgICAgIChvblJvd0RiQ2xpY2spPVwicm93RGJDbGljay5lbWl0KCRldmVudClcIlxuICAgICAgKG9uRXZlbnRDbGljayk9XCJldmVudENsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAob25FdmVudERiQ2xpY2spPVwiZXZlbnREYkNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAob25FdmVudE1vdXNlb3Zlcik9XCJldmVudE1vdXNlb3Zlci5lbWl0KCRldmVudClcIlxuICAgICAgKG9uRXZlbnRNb3VzZW91dCk9XCJldmVudE1vdXNlb3V0LmVtaXQoJGV2ZW50KVwiXG4gICAgICA+PC90bC1kYXktbGlzdD5cblxuICAgICAgPCEtLTx0bC1kYXktbGlzdC0tPlxuICAgICAgPCEtLSpuZ1N3aXRjaENhc2U9XCInZGF5TGlzdCdcIi0tPlxuICAgICAgPCEtLVtldmVudHNdPVwiZXZlbnRzT2ZEYXlcIi0tPlxuICAgICAgPCEtLVtjdXJyZW50RGF0ZV09XCJjdXJyZW50RGF0ZVwiLS0+XG4gICAgICA8IS0tW3N0YXR1c0NvbmZpZ109XCJzdGF0dXNDb25maWdcIi0tPlxuICAgICAgPCEtLShvbkV2ZW50Q2xpY2spPVwiZXZlbnRDbGljay5lbWl0KCRldmVudClcIi0tPlxuICAgICAgPCEtLShvbkV2ZW50RGJDbGljayk9XCJldmVudERiQ2xpY2suZW1pdCgkZXZlbnQpXCItLT5cbiAgICAgIDwhLS0ob25FdmVudE1vdXNlb3Zlcik9XCJldmVudE1vdXNlb3Zlci5lbWl0KCRldmVudClcIi0tPlxuICAgICAgPCEtLShvbkV2ZW50TW91c2VvdXQpPVwiZXZlbnRNb3VzZW91dC5lbWl0KCRldmVudClcIi0tPlxuICAgICAgPCEtLSZndDs8L3RsLWRheS1saXN0Pi0tPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuICA8IS0tIFNDSEVEVUxFIEZPT1RFUiAtLT5cbiAgPGRpdiBjbGFzcz1cInNjaGVkdWxlLWZvb3RlclwiPjwvZGl2PlxuPC9kaXY+XG4iXX0=