UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

221 lines 42.1 kB
import { BsDropdownDirective } from 'ngx-bootstrap/dropdown'; import { gettext } from '../i18n/gettext'; import { Component, EventEmitter, HostListener, Input, Output, ViewChild, ContentChildren, inject } from '@angular/core'; import { ListItemComponent } from '../list-group/list-item.component'; import { TranslateService } from '@ngx-translate/core'; import { PropertyValueTransformService } from '../i18n'; import * as i0 from "@angular/core"; import * as i1 from "ngx-bootstrap/dropdown"; import * as i2 from "../common/icon.directive"; import * as i3 from "@angular/common"; import * as i4 from "../common/dropdown-direction.directive"; import * as i5 from "@angular/forms"; import * as i6 from "../i18n/c8y-translate.pipe"; import * as i7 from "../i18n/name-transform.pipe"; export class SelectLegacyComponent { constructor() { this.placeholder = gettext('Select item'); this.applyLabel = gettext('Apply'); this.disableApplyOnNoSelection = false; this.addDropdownContainerToBody = false; this.onChange = new EventEmitter(); this.textFilter = ''; this.labelText = ''; this.isOpen = false; this.filteredItems = []; this.searchFilter = null; this.sizeToShowFilter = 5; this.labelsForSelectAll = { all: gettext('All'), allFiltered: gettext('All filtered'), none: gettext('Select filter') }; this.showAllLabel = false; this.itemsSelected = new Set(); this.stopClicks = false; this.propertyValueTransformService = inject(PropertyValueTransformService); this.translateService = inject(TranslateService); } set selected(value) { this._selected = value || []; } get selected() { return this._selected; } preventClick(evt) { if (this.stopClicks) { evt.stopPropagation(); } this.stopClicks = this.isOpen; } isOpenChange(isOpen) { this.isOpen = isOpen; if (isOpen) { this.updateSelected(); this.searchFilter = null; } else { this.stopClicks = false; } } outterSelected(item) { const { selected } = this; let isSelected = () => false; if (typeof selected === 'function') { isSelected = selected; } else if (Array.isArray(selected)) { isSelected = (i) => selected.indexOf(i) > -1; } return isSelected(item); } isSelected(item) { return this.itemsSelected.has(item); } isAllItemsSelected() { return this.itemsSelected.size === this.items.length; } isAllFilteredSelected() { return this.itemsSelected.size === this.filteredItems.length; } isNoItemSelected() { return !this.itemsSelected.size; } applyChanges() { const selected = Array.from(this.itemsSelected.values()); this.onChange.emit(selected); this.dropdown.hide(); } selectAll(checked) { this.itemsSelected.clear(); this.filteredItems.forEach(item => this.onChangeItem(checked, item)); } ngOnInit() { if (this.updateItems) { this.updateItems.subscribe(() => { this.updateSelected(); this.updateLabel(); this.showAllLabel = this.isAllItemsSelected(); }); } } onChangeItem(checked, item) { if (checked) { this.itemsSelected.add(item); } else { this.itemsSelected.delete(item); } } deselectItem(item) { this.itemsSelected.delete(item); const selected = Array.from(this.itemsSelected.values()); this.onChange.emit(selected); } updateFiltered(term) { if (term) { const search = new RegExp(term, 'i'); this.filteredItems = this.items.filter(({ name }) => search.test(name)); } else { this.filteredItems = this.items; } } getSelectAllToggleStatus() { const label = this.getLabel(); const checked = this.isAllSelected(); const indeterminate = !checked && this.itemsSelected.size > 0; return { label, checked, indeterminate }; } ngOnChanges(changes) { if (this.isOpen) { return; } if (changes.items || changes.selected || changes.applyLabel) { this.updateSelected(); this.updateLabel(); this.showAllLabel = this.isAllItemsSelected(); } } ngOnDestroy() { if (this.updateItems && !this.updateItems.closed) { this.updateItems.unsubscribe(); } } updateLabel() { const outterSelected = this.items.filter(i => this.outterSelected(i)); if (typeof this.selectedLabel === 'string') { const itemName = this.propertyValueTransformService.getName({ name: this.selectedLabel }); this.labelText = itemName && this.translateService.instant(itemName); } else if (typeof this.selectedLabel === 'function') { const itemName = this.propertyValueTransformService.getName({ name: this.selectedLabel(outterSelected) }); this.labelText = itemName && this.translateService.instant(itemName); } else { this.labelText = outterSelected .map(({ name }) => { const itemName = this.propertyValueTransformService.getName({ name }); return itemName && this.translateService.instant(itemName); }) .join(', '); } } updateSelected() { const { itemsSelected, items } = this; itemsSelected.clear(); items.forEach(item => { if (this.outterSelected(item)) { itemsSelected.add(item); } }); this.filteredItems = items; } isAllSelected() { if (this.getLabel() === this.labelsForSelectAll.allFiltered) { return this.isAllFilteredSelected(); } else { return this.isAllItemsSelected(); } } getLabel() { return this.searchFilter ? this.labelsForSelectAll.allFiltered : this.labelsForSelectAll.all; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectLegacyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectLegacyComponent, selector: "c8y-select-legacy", inputs: { placeholder: "placeholder", selectedLabel: "selectedLabel", applyLabel: "applyLabel", items: "items", selected: "selected", updateItems: "updateItems", disableApplyOnNoSelection: "disableApplyOnNoSelection", addDropdownContainerToBody: "addDropdownContainerToBody" }, outputs: { onChange: "onChange" }, host: { listeners: { "click": "preventClick($event)" } }, queries: [{ propertyName: "liChildren", predicate: ListItemComponent }], viewQueries: [{ propertyName: "dropdown", first: true, predicate: BsDropdownDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"dropdown fit-w\"\n container=\"{{ addDropdownContainerToBody ? 'body' : null }}\"\n (isOpenChange)=\"isOpenChange($event)\"\n dropdown\n #dropdown=\"bs-dropdown\"\n c8yDropdownDirection\n px-event=\"Select type\"\n [insideClick]=\"true\"\n>\n <div class=\"input-group dropdown-toggle\">\n <div\n class=\"form-control pointer d-flex inner-scroll\"\n (click)=\"dropdown.isOpen = !dropdown.isOpen\"\n >\n <ng-container *ngIf=\"itemsSelected.size !== items.length; else all\">\n <em\n class=\"text-muted\"\n *ngIf=\"itemsSelected.size === 0\"\n >\n {{ placeholder | translate }}\n </em>\n <span\n class=\"tag tag--info chip\"\n *ngFor=\"let selectedItem of itemsSelected\"\n >\n <button\n class=\"btn btn-xs btn-clean text-10\"\n title=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n (click)=\"deselectItem(selectedItem); $event.stopPropagation()\"\n >\n <i [c8yIcon]=\"'times'\"></i>\n </button>\n {{ selectedItem.name | nameTransform | translate }}\n </span>\n </ng-container>\n <ng-template #all>\n {{ 'All`possible options`' | translate }}\n </ng-template>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default d-flex a-i-center w-auto\"\n title=\"{{ labelText || placeholder | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n >\n <i class=\"c8y-glyph-caret icon-16\"></i>\n </button>\n </div>\n </div>\n\n <ul\n class=\"dropdown-menu multiselect-container\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-li\"></ng-content>\n <ng-container *ngIf=\"liChildren.length === 0\">\n <li\n class=\"multiselect-item sticky-top\"\n *ngIf=\"items.length > sizeToShowFilter\"\n >\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Filter' | translate }}\u2026\"\n type=\"search\"\n (keyup)=\"updateFiltered($event.target.value)\"\n [(ngModel)]=\"searchFilter\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"!textFilter\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"textFilter\"\n (click)=\"textFilter = ''\"\n ></i>\n </span>\n </div>\n </li>\n\n <li class=\"multiselect-item\">\n <label\n class=\"c8y-checkbox input-sm\"\n [title]=\"getSelectAllToggleStatus().label | translate\"\n ng-click=\"vm.toggleSelectAll(); $event.preventDefault()\"\n >\n <input\n class=\"m-t-0\"\n type=\"checkbox\"\n [checked]=\"getSelectAllToggleStatus().checked\"\n (change)=\"selectAll($event.target.checked)\"\n [indeterminate]=\"getSelectAllToggleStatus().indeterminate\"\n />\n <span></span>\n <span class=\"label-text\">\n {{ getSelectAllToggleStatus().label | translate }}\n </span>\n </label>\n </li>\n\n <li\n class=\"multiselect-item\"\n *ngFor=\"let item of filteredItems\"\n >\n <label\n class=\"c8y-checkbox d-flex a-i-center\"\n [title]=\"item.name | nameTransform | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(item)\"\n (change)=\"onChangeItem($event.target.checked, item)\"\n />\n <span></span>\n <span class=\"m-l-8\">{{ item.name | nameTransform | translate }}</span>\n </label>\n </li>\n <li class=\"divider\"></li>\n <li class=\"sticky-bottom bg-level-0\">\n <button\n class=\"btn btn-primary btn-block\"\n title=\"{{ applyLabel | translate }}\"\n [disabled]=\"disableApplyOnNoSelection && isNoItemSelected()\"\n (click)=\"applyChanges()\"\n >\n {{ applyLabel | translate }}\n </button>\n </li>\n </ng-container>\n </ul>\n</div>\n", dependencies: [{ kind: "directive", type: i1.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DropdownDirectionDirective, selector: "[dropdown][c8yBsDropdownDirection],[dropdown][c8yDropdownDirection]" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i6.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i7.NameTransformPipe, name: "nameTransform" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectLegacyComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-select-legacy', template: "<div\n class=\"dropdown fit-w\"\n container=\"{{ addDropdownContainerToBody ? 'body' : null }}\"\n (isOpenChange)=\"isOpenChange($event)\"\n dropdown\n #dropdown=\"bs-dropdown\"\n c8yDropdownDirection\n px-event=\"Select type\"\n [insideClick]=\"true\"\n>\n <div class=\"input-group dropdown-toggle\">\n <div\n class=\"form-control pointer d-flex inner-scroll\"\n (click)=\"dropdown.isOpen = !dropdown.isOpen\"\n >\n <ng-container *ngIf=\"itemsSelected.size !== items.length; else all\">\n <em\n class=\"text-muted\"\n *ngIf=\"itemsSelected.size === 0\"\n >\n {{ placeholder | translate }}\n </em>\n <span\n class=\"tag tag--info chip\"\n *ngFor=\"let selectedItem of itemsSelected\"\n >\n <button\n class=\"btn btn-xs btn-clean text-10\"\n title=\"{{ 'Remove' | translate }}\"\n type=\"button\"\n (click)=\"deselectItem(selectedItem); $event.stopPropagation()\"\n >\n <i [c8yIcon]=\"'times'\"></i>\n </button>\n {{ selectedItem.name | nameTransform | translate }}\n </span>\n </ng-container>\n <ng-template #all>\n {{ 'All`possible options`' | translate }}\n </ng-template>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default d-flex a-i-center w-auto\"\n title=\"{{ labelText || placeholder | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n >\n <i class=\"c8y-glyph-caret icon-16\"></i>\n </button>\n </div>\n </div>\n\n <ul\n class=\"dropdown-menu multiselect-container\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-li\"></ng-content>\n <ng-container *ngIf=\"liChildren.length === 0\">\n <li\n class=\"multiselect-item sticky-top\"\n *ngIf=\"items.length > sizeToShowFilter\"\n >\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Filter' | translate }}\u2026\"\n type=\"search\"\n (keyup)=\"updateFiltered($event.target.value)\"\n [(ngModel)]=\"searchFilter\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"!textFilter\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"textFilter\"\n (click)=\"textFilter = ''\"\n ></i>\n </span>\n </div>\n </li>\n\n <li class=\"multiselect-item\">\n <label\n class=\"c8y-checkbox input-sm\"\n [title]=\"getSelectAllToggleStatus().label | translate\"\n ng-click=\"vm.toggleSelectAll(); $event.preventDefault()\"\n >\n <input\n class=\"m-t-0\"\n type=\"checkbox\"\n [checked]=\"getSelectAllToggleStatus().checked\"\n (change)=\"selectAll($event.target.checked)\"\n [indeterminate]=\"getSelectAllToggleStatus().indeterminate\"\n />\n <span></span>\n <span class=\"label-text\">\n {{ getSelectAllToggleStatus().label | translate }}\n </span>\n </label>\n </li>\n\n <li\n class=\"multiselect-item\"\n *ngFor=\"let item of filteredItems\"\n >\n <label\n class=\"c8y-checkbox d-flex a-i-center\"\n [title]=\"item.name | nameTransform | translate\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(item)\"\n (change)=\"onChangeItem($event.target.checked, item)\"\n />\n <span></span>\n <span class=\"m-l-8\">{{ item.name | nameTransform | translate }}</span>\n </label>\n </li>\n <li class=\"divider\"></li>\n <li class=\"sticky-bottom bg-level-0\">\n <button\n class=\"btn btn-primary btn-block\"\n title=\"{{ applyLabel | translate }}\"\n [disabled]=\"disableApplyOnNoSelection && isNoItemSelected()\"\n (click)=\"applyChanges()\"\n >\n {{ applyLabel | translate }}\n </button>\n </li>\n </ng-container>\n </ul>\n</div>\n" }] }], propDecorators: { placeholder: [{ type: Input }], selectedLabel: [{ type: Input }], applyLabel: [{ type: Input }], items: [{ type: Input }], selected: [{ type: Input }], updateItems: [{ type: Input }], disableApplyOnNoSelection: [{ type: Input }], addDropdownContainerToBody: [{ type: Input }], onChange: [{ type: Output }], dropdown: [{ type: ViewChild, args: [BsDropdownDirective, { static: false }] }], liChildren: [{ type: ContentChildren, args: [ListItemComponent] }], preventClick: [{ type: HostListener, args: ['click', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LWxlZ2FjeS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL3NlbGVjdC9zZWxlY3QtbGVnYWN5LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL2NvcmUvc2VsZWN0L3NlbGVjdC1sZWdhY3kuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUVOLFNBQVMsRUFDVCxlQUFlLEVBRWYsTUFBTSxFQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRXRFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7Ozs7Ozs7O0FBTXhELE1BQU0sT0FBTyxxQkFBcUI7SUFKbEM7UUFLVyxnQkFBVyxHQUFXLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUU3QyxlQUFVLEdBQVcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBWXRDLDhCQUF5QixHQUFHLEtBQUssQ0FBQztRQUNsQywrQkFBMEIsR0FBRyxLQUFLLENBQUM7UUFDbEMsYUFBUSxHQUF5QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBRzlELGVBQVUsR0FBRyxFQUFFLENBQUM7UUFDaEIsY0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNmLFdBQU0sR0FBRyxLQUFLLENBQUM7UUFDZixrQkFBYSxHQUFXLEVBQUUsQ0FBQztRQUMzQixpQkFBWSxHQUFHLElBQUksQ0FBQztRQUNYLHFCQUFnQixHQUFXLENB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Z0JBUUcsV0FBVztzQkFBbkIsS0FBSztnQkFDRyx5QkFBeUI7c0JBQWpDLEtBQUs7Z0JBQ0csMEJBQTBCO3NCQUFsQyxLQUFLO2dCQUNJLFFBQVE7c0JBQWpCLE1BQU07Z0JBQzRDLFFBQVE7c0JBQTFELFNBQVM7dUJBQUMsbUJBQW1CLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUNiLFVBQVU7c0JBQTdDLGVBQWU7dUJBQUMsaUJBQWlCO2dCQW9CbEMsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJzRHJvcGRvd25EaXJlY3RpdmUgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2Ryb3Bkb3duJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICcuLi9pMThuL2dldHRleHQnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q2hpbGQsXG4gIENvbnRlbnRDaGlsZHJlbixcbiAgT25Jbml0LFxuICBpbmplY3Rcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMaXN0SXRlbUNvbXBvbmVudCB9IGZyb20gJy4uL2xpc3QtZ3JvdXAvbGlzdC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJdGVtLCBzZWxlY3RlZEZ1bmN0aW9uLCBzZWxlY3RlZExhYmVsRnVuY3Rpb24gfSBmcm9tICcuL3NlbGVjdC5tb2RlbCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBQcm9wZXJ0eVZhbHVlVHJhbnNmb3JtU2VydmljZSB9IGZyb20gJy4uL2kxOG4nO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktc2VsZWN0LWxlZ2FjeScsXG4gIHRlbXBsYXRlVXJsOiAnLi9zZWxlY3QtbGVnYWN5LmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3RMZWdhY3lDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uSW5pdCB7XG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSBnZXR0ZXh0KCdTZWxlY3QgaXRlbScpO1xuICBASW5wdXQoKSBzZWxlY3RlZExhYmVsOiBzdHJpbmcgfCBzZWxlY3RlZExhYmVsRnVuY3Rpb247XG4gIEBJbnB1dCgpIGFwcGx5TGFiZWw6IHN0cmluZyA9IGdldHRleHQoJ0FwcGx5Jyk7XG4gIEBJbnB1dCgpIGl0ZW1zOiBJdGVtW107XG5cbiAgQElucHV0KClcbiAgc2V0IHNlbGVjdGVkKHZhbHVlOiBJdGVtW10gfCBzZWxlY3RlZEZ1bmN0aW9uKSB7XG4gICAgdGhpcy5fc2VsZWN0ZWQgPSB2YWx1ZSB8fCBbXTtcbiAgfVxuICBnZXQgc2VsZWN0ZWQoKTogSXRlbVtdIHwgc2VsZWN0ZWRGdW5jdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkO1xuICB9XG5cbiAgQElucHV0KCkgdXBkYXRlSXRlbXM6IEV2ZW50RW1pdHRlcjxib29sZWFuPjtcbiAgQElucHV0KCkgZGlzYWJsZUFwcGx5T25Ob1NlbGVjdGlvbiA9IGZhbHNlO1xuICBASW5wdXQoKSBhZGREcm9wZG93bkNvbnRhaW5lclRvQm9keSA9IGZhbHNlO1xuICBAT3V0cHV0KCkgb25DaGFuZ2U6IEV2ZW50RW1pdHRlcjxJdGVtW10+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAVmlld0NoaWxkKEJzRHJvcGRvd25EaXJlY3RpdmUsIHsgc3RhdGljOiBmYWxzZSB9KSBkcm9wZG93bjogQnNEcm9wZG93bkRpcmVjdGl2ZTtcbiAgQENvbnRlbnRDaGlsZHJlbihMaXN0SXRlbUNvbXBvbmVudCkgbGlDaGlsZHJlbjtcbiAgdGV4dEZpbHRlciA9ICcnO1xuICBsYWJlbFRleHQgPSAnJztcbiAgaXNPcGVuID0gZmFsc2U7XG4gIGZpbHRlcmVkSXRlbXM6IEl0ZW1bXSA9IFtdO1xuICBzZWFyY2hGaWx0ZXIgPSBudWxsO1xuICByZWFkb25seSBzaXplVG9TaG93RmlsdGVyOiBudW1iZXIgPSA1O1xuICBsYWJlbHNGb3JTZWxlY3RBbGw6IGFueSA9IHtcbiAgICBhbGw6IGdldHRleHQoJ0FsbCcpLFxuICAgIGFsbEZpbHRlcmVkOiBnZXR0ZXh0KCdBbGwgZmlsdGVyZWQnKSxcbiAgICBub25lOiBnZXR0ZXh0KCdTZWxlY3QgZmlsdGVy4oCmJylcbiAgfTtcbiAgc2hvd0FsbExhYmVsID0gZmFsc2U7XG4gIGl0ZW1zU2VsZWN0ZWQ6IFNldDxJdGVtPiA9IG5ldyBTZXQoKTtcbiAgcHJpdmF0ZSBzdG9wQ2xpY2tzID0gZmFsc2U7XG4gIHByaXZhdGUgcHJvcGVydHlWYWx1ZVRyYW5zZm9ybVNlcnZpY2UgPSBpbmplY3QoUHJvcGVydHlWYWx1ZVRyYW5zZm9ybVNlcnZpY2UpO1xuICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2UgPSBpbmplY3QoVHJhbnNsYXRlU2VydmljZSk7XG4gIHByaXZhdGUgX3NlbGVjdGVkOiBJdGVtW10gfCBzZWxlY3RlZEZ1bmN0aW9uO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ2NsaWNrJywgWyckZXZlbnQnXSlcbiAgcHJldmVudENsaWNrKGV2dCkge1xuICAgIGlmICh0aGlzLnN0b3BDbGlja3MpIHtcbiAgICAgIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG4gICAgdGhpcy5zdG9wQ2xpY2tzID0gdGhpcy5pc09wZW47XG4gIH1cblxuICBpc09wZW5DaGFuZ2UoaXNPcGVuOiBib29sZWFuKSB7XG4gICAgdGhpcy5pc09wZW4gPSBpc09wZW47XG4gICAgaWYgKGlzT3Blbikge1xuICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgdGhpcy5zZWFyY2hGaWx0ZXIgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0b3BDbGlja3MgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBvdXR0ZXJTZWxlY3RlZChpdGVtOiBJdGVtKSB7XG4gICAgY29uc3QgeyBzZWxlY3RlZCB9ID0gdGhpcztcbiAgICBsZXQgaXNTZWxlY3RlZDogYW55ID0gKCkgPT4gZmFsc2U7XG4gICAgaWYgKHR5cGVvZiBzZWxlY3RlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaXNTZWxlY3RlZCA9IHNlbGVjdGVkO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShzZWxlY3RlZCkpIHtcbiAgICAgIGlzU2VsZWN0ZWQgPSAoaTogSXRlbSkgPT4gc2VsZWN0ZWQuaW5kZXhPZihpKSA+IC0xO1xuICAgIH1cbiAgICByZXR1cm4gaXNTZWxlY3RlZChpdGVtKTtcbiAgfVxuXG4gIGlzU2VsZWN0ZWQoaXRlbTogSXRlbSkge1xuICAgIHJldHVybiB0aGlzLml0ZW1zU2VsZWN0ZWQuaGFzKGl0ZW0pO1xuICB9XG5cbiAgaXNBbGxJdGVtc1NlbGVjdGVkKCkge1xuICAgIHJldHVybiB0aGlzLml0ZW1zU2VsZWN0ZWQuc2l6ZSA9PT0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gIH1cblxuICBpc0FsbEZpbHRlcmVkU2VsZWN0ZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXNTZWxlY3RlZC5zaXplID09PSB0aGlzLmZpbHRlcmVkSXRlbXMubGVuZ3RoO1xuICB9XG5cbiAgaXNOb0l0ZW1TZWxlY3RlZCgpIHtcbiAgICByZXR1cm4gIXRoaXMuaXRlbXNTZWxlY3RlZC5zaXplO1xuICB9XG5cbiAgYXBwbHlDaGFuZ2VzKCkge1xuICAgIGNvbnN0IHNlbGVjdGVkID0gQXJyYXkuZnJvbSh0aGlzLml0ZW1zU2VsZWN0ZWQudmFsdWVzKCkpO1xuICAgIHRoaXMub25DaGFuZ2UuZW1pdChzZWxlY3RlZCk7XG4gICAgdGhpcy5kcm9wZG93bi5oaWRlKCk7XG4gIH1cblxuICBzZWxlY3RBbGwoY2hlY2tlZDogYm9vbGVhbikge1xuICAgIHRoaXMuaXRlbXNTZWxlY3RlZC5jbGVhcigpO1xuICAgIHRoaXMuZmlsdGVyZWRJdGVtcy5mb3JFYWNoKGl0ZW0gPT4gdGhpcy5vbkNoYW5nZUl0ZW0oY2hlY2tlZCwgaXRlbSkpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMudXBkYXRlSXRlbXMpIHtcbiAgICAgIHRoaXMudXBkYXRlSXRlbXMuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxhYmVsKCk7XG4gICAgICAgIHRoaXMuc2hvd0FsbExhYmVsID0gdGhpcy5pc0FsbEl0ZW1zU2VsZWN0ZWQoKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uQ2hhbmdlSXRlbShjaGVja2VkOiBib29sZWFuLCBpdGVtOiBJdGVtKSB7XG4gICAgaWYgKGNoZWNrZWQpIHtcbiAgICAgIHRoaXMuaXRlbXNTZWxlY3RlZC5hZGQoaXRlbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaXRlbXNTZWxlY3RlZC5kZWxldGUoaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgZGVzZWxlY3RJdGVtKGl0ZW06IEl0ZW0pIHtcbiAgICB0aGlzLml0ZW1zU2VsZWN0ZWQuZGVsZXRlKGl0ZW0pO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gQXJyYXkuZnJvbSh0aGlzLml0ZW1zU2VsZWN0ZWQudmFsdWVzKCkpO1xuICAgIHRoaXMub25DaGFuZ2UuZW1pdChzZWxlY3RlZCk7XG4gIH1cblxuICB1cGRhdGVGaWx0ZXJlZCh0ZXJtOiBzdHJpbmcpIHtcbiAgICBpZiAodGVybSkge1xuICAgICAgY29uc3Qgc2VhcmNoID0gbmV3IFJlZ0V4cCh0ZXJtLCAnaScpO1xuICAgICAgdGhpcy5maWx0ZXJlZEl0ZW1zID0gdGhpcy5pdGVtcy5maWx0ZXIoKHsgbmFtZSB9KSA9PiBzZWFyY2gudGVzdChuYW1lKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmlsdGVyZWRJdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgfVxuICB9XG5cbiAgZ2V0U2VsZWN0QWxsVG9nZ2xlU3RhdHVzKCkge1xuICAgIGNvbnN0IGxhYmVsID0gdGhpcy5nZXRMYWJlbCgpO1xuICAgIGNvbnN0IGNoZWNrZWQgPSB0aGlzLmlzQWxsU2VsZWN0ZWQoKTtcbiAgICBjb25zdCBpbmRldGVybWluYXRlID0gIWNoZWNrZWQgJiYgdGhpcy5pdGVtc1NlbGVjdGVkLnNpemUgPiAwO1xuXG4gICAgcmV0dXJuIHsgbGFiZWwsIGNoZWNrZWQsIGluZGV0ZXJtaW5hdGUgfTtcbiAgfVxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLml0ZW1zIHx8IGNoYW5nZXMuc2VsZWN0ZWQgfHwgY2hhbmdlcy5hcHBseUxhYmVsKSB7XG4gICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkKCk7XG4gICAgICB0aGlzLnVwZGF0ZUxhYmVsKCk7XG4gICAgICB0aGlzLnNob3dBbGxMYWJlbCA9IHRoaXMuaXNBbGxJdGVtc1NlbGVjdGVkKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMudXBkYXRlSXRlbXMgJiYgIXRoaXMudXBkYXRlSXRlbXMuY2xvc2VkKSB7XG4gICAgICB0aGlzLnVwZGF0ZUl0ZW1zLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVMYWJlbCgpIHtcbiAgICBjb25zdCBvdXR0ZXJTZWxlY3RlZCA9IHRoaXMuaXRlbXMuZmlsdGVyKGkgPT4gdGhpcy5vdXR0ZXJTZWxlY3RlZChpKSk7XG4gICAgaWYgKHR5cGVvZiB0aGlzLnNlbGVjdGVkTGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBpdGVtTmFtZSA9IHRoaXMucHJvcGVydHlWYWx1ZVRyYW5zZm9ybVNlcnZpY2UuZ2V0TmFtZSh7IG5hbWU6IHRoaXMuc2VsZWN0ZWRMYWJlbCB9KTtcbiAgICAgIHRoaXMubGFiZWxUZXh0ID0gaXRlbU5hbWUgJiYgdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoaXRlbU5hbWUpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuc2VsZWN0ZWRMYWJlbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uc3QgaXRlbU5hbWUgPSB0aGlzLnByb3BlcnR5VmFsdWVUcmFuc2Zvcm1TZXJ2aWNlLmdldE5hbWUoe1xuICAgICAgICBuYW1lOiB0aGlzLnNlbGVjdGVkTGFiZWwob3V0dGVyU2VsZWN0ZWQpXG4gICAgICB9KTtcbiAgICAgIHRoaXMubGFiZWxUZXh0ID0gaXRlbU5hbWUgJiYgdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoaXRlbU5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxhYmVsVGV4dCA9IG91dHRlclNlbGVjdGVkXG4gICAgICAgIC5tYXAoKHsgbmFtZSB9KSA9PiB7XG4gICAgICAgICAgY29uc3QgaXRlbU5hbWUgPSB0aGlzLnByb3BlcnR5VmFsdWVUcmFuc2Zvcm1TZXJ2aWNlLmdldE5hbWUoeyBuYW1lIH0pO1xuICAgICAgICAgIHJldHVybiBpdGVtTmFtZSAmJiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChpdGVtTmFtZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5qb2luKCcsICcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlU2VsZWN0ZWQoKSB7XG4gICAgY29uc3QgeyBpdGVtc1NlbGVjdGVkLCBpdGVtcyB9ID0gdGhpcztcbiAgICBpdGVtc1NlbGVjdGVkLmNsZWFyKCk7XG4gICAgaXRlbXMuZm9yRWFjaChpdGVtID0+IHtcbiAgICAgIGlmICh0aGlzLm91dHRlclNlbGVjdGVkKGl0ZW0pKSB7XG4gICAgICAgIGl0ZW1zU2VsZWN0ZWQuYWRkKGl0ZW0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuZmlsdGVyZWRJdGVtcyA9IGl0ZW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0FsbFNlbGVjdGVkKCkge1xuICAgIGlmICh0aGlzLmdldExhYmVsKCkgPT09IHRoaXMubGFiZWxzRm9yU2VsZWN0QWxsLmFsbEZpbHRlcmVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5pc0FsbEZpbHRlcmVkU2VsZWN0ZWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuaXNBbGxJdGVtc1NlbGVjdGVkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRMYWJlbCgpIHtcbiAgICByZXR1cm4gdGhpcy5zZWFyY2hGaWx0ZXIgPyB0aGlzLmxhYmVsc0ZvclNlbGVjdEFsbC5hbGxGaWx0ZXJlZCA6IHRoaXMubGFiZWxzRm9yU2VsZWN0QWxsLmFsbDtcbiAgfVxufVxuIiwiPGRpdlxuICBjbGFzcz1cImRyb3Bkb3duIGZpdC13XCJcbiAgY29udGFpbmVyPVwie3sgYWRkRHJvcGRvd25Db250YWluZXJUb0JvZHkgPyAnYm9keScgOiBudWxsIH19XCJcbiAgKGlzT3BlbkNoYW5nZSk9XCJpc09wZW5DaGFuZ2UoJGV2ZW50KVwiXG4gIGRyb3Bkb3duXG4gICNkcm9wZG93bj1cImJzLWRyb3Bkb3duXCJcbiAgYzh5RHJvcGRvd25EaXJlY3Rpb25cbiAgcHgtZXZlbnQ9XCJTZWxlY3QgdHlwZVwiXG4gIFtpbnNpZGVDbGlja109XCJ0cnVlXCJcbj5cbiAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwIGRyb3Bkb3duLXRvZ2dsZVwiPlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sIHBvaW50ZXIgZC1mbGV4IGlubmVyLXNjcm9sbFwiXG4gICAgICAoY2xpY2spPVwiZHJvcGRvd24uaXNPcGVuID0gIWRyb3Bkb3duLmlzT3BlblwiXG4gICAgPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW1zU2VsZWN0ZWQuc2l6ZSAhPT0gaXRlbXMubGVuZ3RoOyBlbHNlIGFsbFwiPlxuICAgICAgICA8ZW1cbiAgICAgICAgICBjbGFzcz1cInRleHQtbXV0ZWRcIlxuICAgICAgICAgICpuZ0lmPVwiaXRlbXNTZWxlY3RlZC5zaXplID09PSAwXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IHBsYWNlaG9sZGVyIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvZW0+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJ0YWcgdGFnLS1pbmZvIGNoaXBcIlxuICAgICAgICAgICpuZ0Zvcj1cImxldCBzZWxlY3RlZEl0ZW0gb2YgaXRlbXNTZWxlY3RlZFwiXG4gICAgICAgID5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBjbGFzcz1cImJ0biBidG4teHMgYnRuLWNsZWFuIHRleHQtMTBcIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyAnUmVtb3ZlJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIChjbGljayk9XCJkZXNlbGVjdEl0ZW0oc2VsZWN0ZWRJdGVtKTsgJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aSBbYzh5SWNvbl09XCIndGltZXMnXCI+PC9pPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIHt7IHNlbGVjdGVkSXRlbS5uYW1lIHwgbmFtZVRyYW5zZm9ybSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYWxsPlxuICAgICAgICB7eyAnQWxsYHBvc3NpYmxlIG9wdGlvbnNgJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0IGQtZmxleCBhLWktY2VudGVyIHctYXV0b1wiXG4gICAgICAgIHRpdGxlPVwie3sgbGFiZWxUZXh0IHx8IHBsYWNlaG9sZGVyIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgYXJpYS1oYXNwb3B1cD1cInRydWVcIlxuICAgICAgICBkcm9wZG93blRvZ2dsZVxuICAgICAgPlxuICAgICAgICA8aSBjbGFzcz1cImM4eS1nbHlwaC1jYXJldCBpY29uLTE2XCI+PC9pPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDx1bFxuICAgIGNsYXNzPVwiZHJvcGRvd24tbWVudSBtdWx0aXNlbGVjdC1jb250YWluZXJcIlxuICAgICpkcm9wZG93bk1lbnVcbiAgPlxuICAgIDxuZy1jb250ZW50IHNlbGVjdD1cImM4eS1saVwiPjwvbmctY29udGVudD5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibGlDaGlsZHJlbi5sZW5ndGggPT09IDBcIj5cbiAgICAgIDxsaVxuICAgICAgICBjbGFzcz1cIm11bHRpc2VsZWN0LWl0ZW0gc3RpY2t5LXRvcFwiXG4gICAgICAgICpuZ0lmPVwiaXRlbXMubGVuZ3RoID4gc2l6ZVRvU2hvd0ZpbHRlclwiXG4gICAgICA+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cCBpbnB1dC1ncm91cC1zZWFyY2hcIj5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ0ZpbHRlcicgfCB0cmFuc2xhdGUgfX3igKZcIlxuICAgICAgICAgICAgdHlwZT1cInNlYXJjaFwiXG4gICAgICAgICAgICAoa2V5dXApPVwidXBkYXRlRmlsdGVyZWQoJGV2ZW50LnRhcmdldC52YWx1ZSlcIlxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWFyY2hGaWx0ZXJcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJpbnB1dC1ncm91cC1hZGRvblwiPlxuICAgICAgICAgICAgPGlcbiAgICAgICAgICAgICAgYzh5SWNvbj1cInNlYXJjaFwiXG4gICAgICAgICAgICAgICpuZ0lmPVwiIXRleHRGaWx0ZXJcIlxuICAgICAgICAgICAgPjwvaT5cbiAgICAgICAgICAgIDxpXG4gICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1tdXRlZFwiXG4gICAgICAgICAgICAgIGM4eUljb249XCJ0aW1lc1wiXG4gICAgICAgICAgICAgICpuZ0lmPVwidGV4dEZpbHRlclwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJ0ZXh0RmlsdGVyID0gJydcIlxuICAgICAgICAgICAgPjwvaT5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9saT5cblxuICAgICAgPGxpIGNsYXNzPVwibXVsdGlzZWxlY3QtaXRlbVwiPlxuICAgICAgICA8bGFiZWxcbiAgICAgICAgICBjbGFzcz1cImM4eS1jaGVja2JveCBpbnB1dC1zbVwiXG4gICAgICAgICAgW3RpdGxlXT1cImdldFNlbGVjdEFsbFRvZ2dsZVN0YXR1cygpLmxhYmVsIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICBuZy1jbGljaz1cInZtLnRvZ2dsZVNlbGVjdEFsbCgpOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG4gICAgICAgID5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIGNsYXNzPVwibS10LTBcIlxuICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgIFtjaGVja2VkXT1cImdldFNlbGVjdEFsbFRvZ2dsZVN0YXR1cygpLmNoZWNrZWRcIlxuICAgICAgICAgICAgKGNoYW5nZSk9XCJzZWxlY3RBbGwoJGV2ZW50LnRhcmdldC5jaGVja2VkKVwiXG4gICAgICAgICAgICBbaW5kZXRlcm1pbmF0ZV09XCJnZXRTZWxlY3RBbGxUb2dnbGVTdGF0dXMoKS5pbmRldGVybWluYXRlXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxzcGFuPjwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLXRleHRcIj5cbiAgICAgICAgICAgIHt7IGdldFNlbGVjdEFsbFRvZ2dsZVN0YXR1cygpLmxhYmVsIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9saT5cblxuICAgICAgPGxpXG4gICAgICAgIGNsYXNzPVwibXVsdGlzZWxlY3QtaXRlbVwiXG4gICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGZpbHRlcmVkSXRlbXNcIlxuICAgICAgPlxuICAgICAgICA8bGFiZWxcbiAgICAgICAgICBjbGFzcz1cImM4eS1jaGVja2JveCBkLWZsZXggYS1pLWNlbnRlclwiXG4gICAgICAgICAgW3RpdGxlXT1cIml0ZW0ubmFtZSB8IG5hbWVUcmFuc2Zvcm0gfCB0cmFuc2xhdGVcIlxuICAgICAgICA+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgICAgW2NoZWNrZWRdPVwiaXNTZWxlY3RlZChpdGVtKVwiXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uQ2hhbmdlSXRlbSgkZXZlbnQudGFyZ2V0LmNoZWNrZWQsIGl0ZW0pXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxzcGFuPjwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm0tbC04XCI+e3sgaXRlbS5uYW1lIHwgbmFtZVRyYW5zZm9ybSB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvbGk+XG4gICAgICA8bGkgY2xhc3M9XCJkaXZpZGVyXCI+PC9saT5cbiAgICAgIDxsaSBjbGFzcz1cInN0aWNreS1ib3R0b20gYmctbGV2ZWwtMFwiPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgYnRuLWJsb2NrXCJcbiAgICAgICAgICB0aXRsZT1cInt7IGFwcGx5TGFiZWwgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlQXBwbHlPbk5vU2VsZWN0aW9uICYmIGlzTm9JdGVtU2VsZWN0ZWQoKVwiXG4gICAgICAgICAgKGNsaWNrKT1cImFwcGx5Q2hhbmdlcygpXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IGFwcGx5TGFiZWwgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2xpPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L3VsPlxuPC9kaXY+XG4iXX0=