ngx-ui-hero
Version:
Simple, fast and reliable utilities for Angular.
194 lines • 43.3 kB
JavaScript
import { Component, EventEmitter, Inject, Input, IterableDiffers, Optional, Output, ViewChild } from '@angular/core';
import { NG_ASYNC_VALIDATORS, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgModel } from '@angular/forms';
import { ElementBase } from '../../base/element-base';
import { INPUT_FORMS_CONFIG } from '../../input-forms-config.constants';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
import * as i3 from "../../../ui/directives/click-outside.directive";
import * as i4 from "../../../ui/directives/auto-focus.directive";
import * as i5 from "ngx-bootstrap/tooltip";
import * as i6 from "../../../ui/pipes/search-by.pipe";
let identifier = 0;
export class InputMultiselectComponent extends ElementBase {
constructor(validators, asyncValidators, config, iterableDiffers) {
super(validators, asyncValidators, config);
this.config = config;
this.iterableDiffers = iterableDiffers;
this.placeholder = 'Select...';
this.searchPlaceholder = 'Search...';
this.displayTextProperty = 'text';
this.valueProperty = 'value';
this.emptyMessage = 'No results found.';
this.selectAllButtonLabel = 'Select all';
this.clearSelectionButtonLabel = 'Clear selection';
this.maxCountOfLabelsToShow = 3;
this.onChange = new EventEmitter();
this.identifier = `input-multiselect-${identifier++}`;
if (config.multiSelect) {
Object.assign(this, config.multiSelect);
}
this._differModel = this.iterableDiffers.find([]).create(null);
this._differOptions = this.iterableDiffers.find([]).create(null);
}
get options() {
return this._options;
}
set options(value) {
this._options = value;
this.Init();
}
ngOnInit() {
this.Init();
}
ngDoCheck() {
let changesInModel = this._differModel.diff(this.value);
let changesInOptions = this._differOptions.diff(this._options);
if (changesInModel || (changesInOptions && !this.modelInitialized)) {
this.Init();
}
}
Init() {
if (!this.value || !this.options || this.value.length == 0 || this.options.length == 0) {
if ((!this.value || this.value.length == 0) && this.options) {
this.ToggleAllItemsSelection(false, false);
}
return;
}
for (let i = 0; i < this.options.length; i++) {
this.options[i].selected = this.value.filter(x => this.options[i][this.valueProperty] == x[this.valueProperty]).length > 0;
}
this.modelInitialized = true;
}
ToggleDropDown(event, value) {
if ((value == false && !this.showOptions) || (value == undefined && this.disabled))
return;
if (value == undefined) {
if (this.showOptions) {
this.setComboTouched();
}
this.showOptions = !this.showOptions;
}
else {
if (!value && this.showOptions) {
this.setComboTouched();
}
this.showOptions = value;
}
this.clearSearch();
}
ToggleItemSelected(item) {
if (this.disabled) {
return;
}
item.selected = !item.selected;
this.updateModel();
this.onChange.emit();
}
ToggleAllItemsSelection(value, emitChanges) {
if (this.disabled) {
return;
}
if (!this.options || this.options.length == 0)
return;
for (let i = 0; i < this.options.length; i++) {
this.options[i].selected = value;
}
this.updateModel();
this.clearSearch();
if (emitChanges)
this.onChange.emit();
}
ItemSelectedCheckChanged() {
if (this.disabled) {
return;
}
this.updateModel();
this.onChange.emit();
}
RemoveItem(item, index, event) {
if (this.disabled || !this.options || this.options.length == 0) {
return;
}
let itemToRemove = this.options.find(x => x[this.valueProperty] == item[this.valueProperty]);
if (itemToRemove) {
this.ToggleItemSelected(itemToRemove);
this.clearSearch();
}
else {
this.value.splice(index, 1);
}
event.stopPropagation();
}
OnComboPressed(event) {
if (event.keyCode == 13) {
this.ToggleDropDown(null);
event.preventDefault();
}
}
clearSearch() {
this.search = '';
}
updateModel() {
if (!this.options || this.options.length == 0) {
this.value = [];
return;
}
this.value = this.options.filter(x => x.selected);
}
setComboTouched() {
this.comboTouched = true;
}
}
InputMultiselectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InputMultiselectComponent, deps: [{ token: NG_VALIDATORS, optional: true }, { token: NG_ASYNC_VALIDATORS, optional: true }, { token: INPUT_FORMS_CONFIG }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Component });
InputMultiselectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: InputMultiselectComponent, selector: "input-multiselect", inputs: { placeholder: "placeholder", searchPlaceholder: "searchPlaceholder", displayTextProperty: "displayTextProperty", valueProperty: "valueProperty", emptyMessage: "emptyMessage", selectAllButtonLabel: "selectAllButtonLabel", clearSelectionButtonLabel: "clearSelectionButtonLabel", maxCountOfLabelsToShow: "maxCountOfLabelsToShow", options: "options" }, outputs: { onChange: "onChange" }, providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: InputMultiselectComponent,
multi: true
}], viewQueries: [{ propertyName: "model", first: true, predicate: NgModel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div [id]=\"identifier\" class=\"ui-multiselect\">\n <label *ngIf=\"label\">\n {{label}}\n <span class=\"required-symbol\" *ngIf=\"isRequired\"> *</span>\n <i class=\"fa fa-question-circle ml-2\" tooltip=\"{{help}}\" container=\"body\" *ngIf=\"help\"></i>\n </label>\n\n <input type=\"hidden\" [(ngModel)]=\"value\" />\n <div class=\"combobox d-flex align-items-center justify-content-between\" \n [ngClass]=\"{\n 'has-validations': showValidations,\n 'open': showOptions, \n 'disabled': disabled,\n 'is-valid': !showOptions && !disabled && comboTouched && (!isRequired || value?.length > 0),\n 'is-invalid': !showOptions && !disabled && comboTouched && isRequired && (!value || value.length == 0)\n }\"\n (click)=\"ToggleDropDown($event)\" (keyup)=\"OnComboPressed($event)\" tabindex=\"0\">\n\n <span *ngIf=\"!value || value.length == 0\">{{placeholder}}</span>\n\n <div *ngIf=\"value?.length > 0\" class=\"selected-items d-flex align-items-center\">\n <span class=\"badge\" *ngFor=\"let item of value | slice:0:maxCountOfLabelsToShow; let i = index;\" (click)=\"RemoveItem(item, i, $event)\">\n <span class=\"text-truncate\">{{item[displayTextProperty]}}</span>\n <i class=\"fa fa-times ml-2\" *ngIf=\"!disabled\"></i>\n </span>\n <span *ngIf=\"value.length > maxCountOfLabelsToShow\">...</span>\n </div>\n\n <i class=\"fa\" [ngClass]=\"{'fa-caret-down': !showOptions, 'fa-caret-up': showOptions}\"></i>\n </div>\n\n <div class=\"dropdown-options shadow fadeInDown\" *ngIf=\"showOptions\" (clickOutside)=\"ToggleDropDown($event, false)\">\n <div class=\"options-container\" *ngIf=\"options?.length > 0\">\n <div class=\"toolbar d-flex align-items-center\">\n <input type=\"text\" class=\"form-control flex-grow-1\" name=\"{{identifier}}-search\" [(ngModel)]=\"search\" placeholder=\"{{searchPlaceholder}}\" auto-focus />\n <button type=\"button\" class=\"btn btn-light ml-1 flex-shrink-0\" (click)=\"ToggleAllItemsSelection(true, true)\" [disabled]=\"disabled\"><i class=\"fa fa-check-square\"></i> {{selectAllButtonLabel}}</button>\n <button type=\"button\" class=\"btn btn-light ml-1 flex-shrink-0\" (click)=\"ToggleAllItemsSelection(false, true)\" [disabled]=\"disabled\"><i class=\"fa fa-eraser\"></i> {{clearSelectionButtonLabel}}</button>\n </div>\n\n <ul>\n <li class=\"d-flex\" *ngFor=\"let item of options | searchBy : displayTextProperty : search\" [ngClass]=\"{'selected': item.selected}\">\n <div class=\"checkbox mr-3 flex-shrink-0\">\n <input type=\"checkbox\" name=\"{{identifier}}-option\" [(ngModel)]=\"item.selected\" (change)=\"ItemSelectedCheckChanged()\" [disabled]=\"disabled\" />\n </div>\n <span class=\"link\" (click)=\"ToggleItemSelected(item)\">{{item[displayTextProperty]}}</span>\n </li>\n </ul>\n\n <small class=\"empty-results\" *ngIf=\"(options | searchBy : displayTextProperty : search).length == 0\">{{emptyMessage}}</small>\n </div>\n\n <small class=\"empty-results\" *ngIf=\"!options || options.length == 0\">{{emptyMessage}}</small>\n </div>\n</div>\n\n<small class=\"text-muted\" *ngIf=\"description\">{{description}}</small>\n", styles: ["@keyframes fadeInDown{0%{opacity:0;transform:translate3d(0,-5%,0)}to{opacity:1;transform:translateZ(0)}}.fadeInDown{animation-name:fadeInDown;animation-duration:.35s;animation-fill-mode:both}.ui-multiselect{position:relative}.ui-multiselect *{-webkit-user-select:none;user-select:none}.ui-multiselect>.combobox{outline:none;background-color:#fff;padding:.375rem .4rem .375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.ui-multiselect>.combobox>span{color:#6c757d;font-size:1rem;line-height:1.5}.ui-multiselect>.combobox>i{color:#495057;font-size:14px;margin-left:10px}.ui-multiselect>.combobox .selected-items{margin-left:-5px;overflow:hidden}.ui-multiselect>.combobox .selected-items .badge{margin-right:3px;line-height:1;color:#888;background-color:#e0e0e0;border-bottom:2px solid #ccc;border-left:2px solid #ccc;padding:5px 7px 4px}.ui-multiselect>.combobox .selected-items .badge>span{display:inline-block;max-width:150px}.ui-multiselect>.combobox .selected-items .badge:hover{cursor:pointer;color:#fff;background-color:#007bff;border-bottom:2px solid #00559a;border-left:2px solid #00559a}.ui-multiselect>.combobox.open{border-radius:.25rem .25rem 0 0}.ui-multiselect>.combobox.disabled{background-color:#e9ecef;border-color:#ced4da}.ui-multiselect>.combobox.has-validations.is-invalid{border-color:#dc3545}.ui-multiselect>.combobox.has-validations.is-invalid.open{box-shadow:0 0 0 .2rem #dc354540}.ui-multiselect>.combobox.has-validations.is-valid{border-color:#28a745}.ui-multiselect>.combobox.has-validations.is-valid.open{box-shadow:0 0 0 .2rem #28a74540}.ui-multiselect>.dropdown-options{background-color:#fff;border:1px solid #ced4da;border-radius:0 0 .25rem .25rem;position:absolute;top:100%;left:0;width:100%;z-index:20;margin-top:-1px;min-width:300px}.ui-multiselect>.dropdown-options>.options-container{display:inherit;position:initial;font-family:inherit;background-color:inherit;box-shadow:none;height:auto;width:auto;color:inherit;font-size:inherit;letter-spacing:inherit;line-height:inherit;padding:inherit;border-radius:inherit}.ui-multiselect>.dropdown-options .toolbar{padding:3px;border-bottom:1px solid #ced4da;background-color:#f8f9fa}.ui-multiselect>.dropdown-options .toolbar input[type=text]{background-color:transparent;border:0;padding:.375rem .55rem;box-shadow:none!important;min-width:0}.ui-multiselect>.dropdown-options ul{max-height:300px;overflow-y:scroll;overflow-x:hidden;margin:0;padding:0}.ui-multiselect>.dropdown-options ul li{list-style:none;border-bottom:1px solid #ced4da}.ui-multiselect>.dropdown-options ul li>.checkbox{background-color:#f0f0f0;border-right:1px solid #ced4da;padding:12px 15px;display:flex;align-items:center}.ui-multiselect>.dropdown-options ul li>.checkbox input[type=checkbox]{width:17px;height:17px}.ui-multiselect>.dropdown-options ul li>span{cursor:pointer;padding:8px 0}.ui-multiselect>.dropdown-options ul li.selected{color:#007bff}.ui-multiselect>.dropdown-options ul li:hover{background-color:#f9f9f9}.ui-multiselect>.dropdown-options ul li:last-child{border-bottom:0}.ui-multiselect>.dropdown-options .empty-results{font-style:italic;padding:12px;display:block;color:#6b6b6b}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.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: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutsideEnabled", "attachOutsideOnClick", "delayClickOutsideInit", "emitOnBlur", "exclude", "excludeBeforeClick", "clickOutsideEvents"], outputs: ["clickOutside"] }, { kind: "directive", type: i4.AutoFocusDirective, selector: "[auto-focus]" }, { kind: "directive", type: i5.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["containerClass", "tooltipAnimation", "tooltipFadeDuration", "isOpen", "tooltipHtml", "tooltip", "tooltipPlacement", "placement", "tooltipIsOpen", "tooltipEnable", "isDisabled", "tooltipAppendToBody", "container", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "delay", "tooltipTrigger", "triggers", "adaptivePosition"], outputs: ["tooltipChange", "tooltipStateChanged", "onShown", "onHidden"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "pipe", type: i6.SearchByPipe, name: "searchBy" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InputMultiselectComponent, decorators: [{
type: Component,
args: [{ selector: 'input-multiselect', providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: InputMultiselectComponent,
multi: true
}], template: "<div [id]=\"identifier\" class=\"ui-multiselect\">\n <label *ngIf=\"label\">\n {{label}}\n <span class=\"required-symbol\" *ngIf=\"isRequired\"> *</span>\n <i class=\"fa fa-question-circle ml-2\" tooltip=\"{{help}}\" container=\"body\" *ngIf=\"help\"></i>\n </label>\n\n <input type=\"hidden\" [(ngModel)]=\"value\" />\n <div class=\"combobox d-flex align-items-center justify-content-between\" \n [ngClass]=\"{\n 'has-validations': showValidations,\n 'open': showOptions, \n 'disabled': disabled,\n 'is-valid': !showOptions && !disabled && comboTouched && (!isRequired || value?.length > 0),\n 'is-invalid': !showOptions && !disabled && comboTouched && isRequired && (!value || value.length == 0)\n }\"\n (click)=\"ToggleDropDown($event)\" (keyup)=\"OnComboPressed($event)\" tabindex=\"0\">\n\n <span *ngIf=\"!value || value.length == 0\">{{placeholder}}</span>\n\n <div *ngIf=\"value?.length > 0\" class=\"selected-items d-flex align-items-center\">\n <span class=\"badge\" *ngFor=\"let item of value | slice:0:maxCountOfLabelsToShow; let i = index;\" (click)=\"RemoveItem(item, i, $event)\">\n <span class=\"text-truncate\">{{item[displayTextProperty]}}</span>\n <i class=\"fa fa-times ml-2\" *ngIf=\"!disabled\"></i>\n </span>\n <span *ngIf=\"value.length > maxCountOfLabelsToShow\">...</span>\n </div>\n\n <i class=\"fa\" [ngClass]=\"{'fa-caret-down': !showOptions, 'fa-caret-up': showOptions}\"></i>\n </div>\n\n <div class=\"dropdown-options shadow fadeInDown\" *ngIf=\"showOptions\" (clickOutside)=\"ToggleDropDown($event, false)\">\n <div class=\"options-container\" *ngIf=\"options?.length > 0\">\n <div class=\"toolbar d-flex align-items-center\">\n <input type=\"text\" class=\"form-control flex-grow-1\" name=\"{{identifier}}-search\" [(ngModel)]=\"search\" placeholder=\"{{searchPlaceholder}}\" auto-focus />\n <button type=\"button\" class=\"btn btn-light ml-1 flex-shrink-0\" (click)=\"ToggleAllItemsSelection(true, true)\" [disabled]=\"disabled\"><i class=\"fa fa-check-square\"></i> {{selectAllButtonLabel}}</button>\n <button type=\"button\" class=\"btn btn-light ml-1 flex-shrink-0\" (click)=\"ToggleAllItemsSelection(false, true)\" [disabled]=\"disabled\"><i class=\"fa fa-eraser\"></i> {{clearSelectionButtonLabel}}</button>\n </div>\n\n <ul>\n <li class=\"d-flex\" *ngFor=\"let item of options | searchBy : displayTextProperty : search\" [ngClass]=\"{'selected': item.selected}\">\n <div class=\"checkbox mr-3 flex-shrink-0\">\n <input type=\"checkbox\" name=\"{{identifier}}-option\" [(ngModel)]=\"item.selected\" (change)=\"ItemSelectedCheckChanged()\" [disabled]=\"disabled\" />\n </div>\n <span class=\"link\" (click)=\"ToggleItemSelected(item)\">{{item[displayTextProperty]}}</span>\n </li>\n </ul>\n\n <small class=\"empty-results\" *ngIf=\"(options | searchBy : displayTextProperty : search).length == 0\">{{emptyMessage}}</small>\n </div>\n\n <small class=\"empty-results\" *ngIf=\"!options || options.length == 0\">{{emptyMessage}}</small>\n </div>\n</div>\n\n<small class=\"text-muted\" *ngIf=\"description\">{{description}}</small>\n", styles: ["@keyframes fadeInDown{0%{opacity:0;transform:translate3d(0,-5%,0)}to{opacity:1;transform:translateZ(0)}}.fadeInDown{animation-name:fadeInDown;animation-duration:.35s;animation-fill-mode:both}.ui-multiselect{position:relative}.ui-multiselect *{-webkit-user-select:none;user-select:none}.ui-multiselect>.combobox{outline:none;background-color:#fff;padding:.375rem .4rem .375rem .75rem;border:1px solid #ced4da;border-radius:.25rem}.ui-multiselect>.combobox>span{color:#6c757d;font-size:1rem;line-height:1.5}.ui-multiselect>.combobox>i{color:#495057;font-size:14px;margin-left:10px}.ui-multiselect>.combobox .selected-items{margin-left:-5px;overflow:hidden}.ui-multiselect>.combobox .selected-items .badge{margin-right:3px;line-height:1;color:#888;background-color:#e0e0e0;border-bottom:2px solid #ccc;border-left:2px solid #ccc;padding:5px 7px 4px}.ui-multiselect>.combobox .selected-items .badge>span{display:inline-block;max-width:150px}.ui-multiselect>.combobox .selected-items .badge:hover{cursor:pointer;color:#fff;background-color:#007bff;border-bottom:2px solid #00559a;border-left:2px solid #00559a}.ui-multiselect>.combobox.open{border-radius:.25rem .25rem 0 0}.ui-multiselect>.combobox.disabled{background-color:#e9ecef;border-color:#ced4da}.ui-multiselect>.combobox.has-validations.is-invalid{border-color:#dc3545}.ui-multiselect>.combobox.has-validations.is-invalid.open{box-shadow:0 0 0 .2rem #dc354540}.ui-multiselect>.combobox.has-validations.is-valid{border-color:#28a745}.ui-multiselect>.combobox.has-validations.is-valid.open{box-shadow:0 0 0 .2rem #28a74540}.ui-multiselect>.dropdown-options{background-color:#fff;border:1px solid #ced4da;border-radius:0 0 .25rem .25rem;position:absolute;top:100%;left:0;width:100%;z-index:20;margin-top:-1px;min-width:300px}.ui-multiselect>.dropdown-options>.options-container{display:inherit;position:initial;font-family:inherit;background-color:inherit;box-shadow:none;height:auto;width:auto;color:inherit;font-size:inherit;letter-spacing:inherit;line-height:inherit;padding:inherit;border-radius:inherit}.ui-multiselect>.dropdown-options .toolbar{padding:3px;border-bottom:1px solid #ced4da;background-color:#f8f9fa}.ui-multiselect>.dropdown-options .toolbar input[type=text]{background-color:transparent;border:0;padding:.375rem .55rem;box-shadow:none!important;min-width:0}.ui-multiselect>.dropdown-options ul{max-height:300px;overflow-y:scroll;overflow-x:hidden;margin:0;padding:0}.ui-multiselect>.dropdown-options ul li{list-style:none;border-bottom:1px solid #ced4da}.ui-multiselect>.dropdown-options ul li>.checkbox{background-color:#f0f0f0;border-right:1px solid #ced4da;padding:12px 15px;display:flex;align-items:center}.ui-multiselect>.dropdown-options ul li>.checkbox input[type=checkbox]{width:17px;height:17px}.ui-multiselect>.dropdown-options ul li>span{cursor:pointer;padding:8px 0}.ui-multiselect>.dropdown-options ul li.selected{color:#007bff}.ui-multiselect>.dropdown-options ul li:hover{background-color:#f9f9f9}.ui-multiselect>.dropdown-options ul li:last-child{border-bottom:0}.ui-multiselect>.dropdown-options .empty-results{font-style:italic;padding:12px;display:block;color:#6b6b6b}\n"] }]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [NG_VALIDATORS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [INPUT_FORMS_CONFIG]
}] }, { type: i0.IterableDiffers }]; }, propDecorators: { placeholder: [{
type: Input
}], searchPlaceholder: [{
type: Input
}], displayTextProperty: [{
type: Input
}], valueProperty: [{
type: Input
}], emptyMessage: [{
type: Input
}], selectAllButtonLabel: [{
type: Input
}], clearSelectionButtonLabel: [{
type: Input
}], maxCountOfLabelsToShow: [{
type: Input
}], onChange: [{
type: Output
}], model: [{
type: ViewChild,
args: [NgModel, { static: true }]
}], options: [{
type: Input,
args: ['options']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtbXVsdGlzZWxlY3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXVpLWhlcm8vc3JjL2xpYi9pbnB1dC1mb3Jtcy9jb21wb25lbnRzL2lucHV0LW11bHRpc2VsZWN0L2lucHV0LW11bHRpc2VsZWN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC11aS1oZXJvL3NyYy9saWIvaW5wdXQtZm9ybXMvY29tcG9uZW50cy9pbnB1dC1tdWx0aXNlbGVjdC9pbnB1dC1tdWx0aXNlbGVjdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFXLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBVSxRQUFRLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0SSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWhHLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUd0RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7Ozs7Ozs7QUFFeEUsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBWW5CLE1BQU0sT0FBTyx5QkFBMEIsU0FBUSxXQUFnQjtJQStCN0QsWUFDcUMsVUFBMEIsRUFDcEIsZUFBb0MsRUFDeEMsTUFBd0IsRUFDckQsZUFBZ0M7UUFFeEMsS0FBSyxDQUFDLFVBQVUsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFITixXQUFNLEdBQU4sTUFBTSxDQUFrQjtRQUNyRCxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUExQjFCLGdCQUFXLEdBQUcsV0FBVyxDQUFDO1FBQzFCLHNCQUFp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O2dCQUNVLG1CQUFtQjtzQkFBbEMsS0FBSztnQkFDVSxhQUFhO3NCQUE1QixLQUFLO2dCQUNVLFlBQVk7c0JBQTNCLEtBQUs7Z0JBQ1Usb0JBQW9CO3NCQUFuQyxLQUFLO2dCQUNVLHlCQUF5QjtzQkFBeEMsS0FBSztnQkFDVSxzQkFBc0I7c0JBQXJDLEtBQUs7Z0JBQ1csUUFBUTtzQkFBeEIsTUFBTTtnQkFDNkIsS0FBSztzQkFBeEMsU0FBUzt1QkFBQyxPQUFPLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDO2dCQU05QixPQUFPO3NCQURWLEtBQUs7dUJBQUMsU0FBUyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRG9DaGVjaywgRXZlbnRFbWl0dGVyLCBJbmplY3QsIElucHV0LCBJdGVyYWJsZURpZmZlcnMsIE9uSW5pdCwgT3B0aW9uYWwsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOR19BU1lOQ19WQUxJREFUT1JTLCBOR19WQUxJREFUT1JTLCBOR19WQUxVRV9BQ0NFU1NPUiwgTmdNb2RlbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgRWxlbWVudEJhc2UgfSBmcm9tICcuLi8uLi9iYXNlL2VsZW1lbnQtYmFzZSc7XG5pbXBvcnQgeyBBc3luY1ZhbGlkYXRvckFycmF5LCBWYWxpZGF0b3JBcnJheSB9IGZyb20gJy4uLy4uL2Jhc2UvdmFsaWRhdGUnO1xuaW1wb3J0IHsgSW5wdXRGb3Jtc0NvbmZpZyB9IGZyb20gJy4uLy4uL2lucHV0LWZvcm1zLWNvbmZpZyc7XG5pbXBvcnQgeyBJTlBVVF9GT1JNU19DT05GSUcgfSBmcm9tICcuLi8uLi9pbnB1dC1mb3Jtcy1jb25maWcuY29uc3RhbnRzJztcblxubGV0IGlkZW50aWZpZXIgPSAwO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdpbnB1dC1tdWx0aXNlbGVjdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9pbnB1dC1tdWx0aXNlbGVjdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2lucHV0LW11bHRpc2VsZWN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIHByb3ZpZGVyczogW3tcbiAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICB1c2VFeGlzdGluZzogSW5wdXRNdWx0aXNlbGVjdENvbXBvbmVudCxcbiAgICBtdWx0aTogdHJ1ZVxuICB9XVxufSlcbmV4cG9ydCBjbGFzcyBJbnB1dE11bHRpc2VsZWN0Q29tcG9uZW50IGV4dGVuZHMgRWxlbWVudEJhc2U8YW55PiBpbXBsZW1lbnRzIE9uSW5pdCwgRG9DaGVjayB7XG4gIHByaXZhdGUgX2RpZmZlck1vZGVsOiBhbnk7ICBcbiAgcHJpdmF0ZSBfZGlmZmVyT3B0aW9uczogYW55OyAgXG4gIHByaXZhdGUgX29wdGlvbnM6IEFycmF5PGFueT47XG4gIHNob3dPcHRpb25zOiBib29sZWFuO1xuICBjb21ib1RvdWNoZWQ6IGJvb2xlYW47XG4gIG1vZGVsSW5pdGlhbGl6ZWQ6IGJvb2xlYW47XG4gIHNlYXJjaDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIHB1YmxpYyBwbGFjZWhvbGRlciA9ICdTZWxlY3QuLi4nO1xuICBASW5wdXQoKSBwdWJsaWMgc2VhcmNoUGxhY2Vob2xkZXIgPSAnU2VhcmNoLi4uJztcbiAgQElucHV0KCkgcHVibGljIGRpc3BsYXlUZXh0UHJvcGVydHk6IHN0cmluZyA9ICd0ZXh0JztcbiAgQElucHV0KCkgcHVibGljIHZhbHVlUHJvcGVydHk6IHN0cmluZyA9ICd2YWx1ZSc7XG4gIEBJbnB1dCgpIHB1YmxpYyBlbXB0eU1lc3NhZ2U6IHN0cmluZyA9ICdObyByZXN1bHRzIGZvdW5kLic7XG4gIEBJbnB1dCgpIHB1YmxpYyBzZWxlY3RBbGxCdXR0b25MYWJlbDogc3RyaW5nID0gJ1NlbGVjdCBhbGwnO1xuICBASW5wdXQoKSBwdWJsaWMgY2xlYXJTZWxlY3Rpb25CdXR0b25MYWJlbDogc3RyaW5nID0gJ0NsZWFyIHNlbGVjdGlvbic7XG4gIEBJbnB1dCgpIHB1YmxpYyBtYXhDb3VudE9mTGFiZWxzVG9TaG93OiBudW1iZXIgPSAzO1xuICBAT3V0cHV0KCkgcHVibGljIG9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBWaWV3Q2hpbGQoTmdNb2RlbCwge3N0YXRpYzogdHJ1ZX0pIG1vZGVsOiBOZ01vZGVsO1xuXG4gIGdldCBvcHRpb25zKCk6IEFycmF5PGFueT4ge1xuICAgIHJldHVybiB0aGlzLl9vcHRpb25zO1xuICB9ICAgIFxuICBASW5wdXQoJ29wdGlvbnMnKVxuICBzZXQgb3B0aW9ucyh2YWx1ZTogQXJyYXk8YW55Pikge1xuICAgIHRoaXMuX29wdGlvbnMgPSB2YWx1ZTtcbiAgICB0aGlzLkluaXQoKTtcbiAgfVxuICBcbiAgcHVibGljIGlkZW50aWZpZXIgPSBgaW5wdXQtbXVsdGlzZWxlY3QtJHtpZGVudGlmaWVyKyt9YDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KE5HX1ZBTElEQVRPUlMpIHZhbGlkYXRvcnM6IFZhbGlkYXRvckFycmF5LFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoTkdfQVNZTkNfVkFMSURBVE9SUykgYXN5bmNWYWxpZGF0b3JzOiBBc3luY1ZhbGlkYXRvckFycmF5LFxuICAgIEBJbmplY3QoIElOUFVUX0ZPUk1TX0NPTkZJRyApIHB1YmxpYyBjb25maWc6IElucHV0Rm9ybXNDb25maWcsXG4gICAgcHJpdmF0ZSBpdGVyYWJsZURpZmZlcnM6IEl0ZXJhYmxlRGlmZmVycyxcbiAgKSB7XG4gICAgc3VwZXIodmFsaWRhdG9ycywgYXN5bmNWYWxpZGF0b3JzLCBjb25maWcpO1xuXG4gICAgaWYgKGNvbmZpZy5tdWx0aVNlbGVjdCkge1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBjb25maWcubXVsdGlTZWxlY3QpO1xuICAgIH1cblxuICAgIHRoaXMuX2RpZmZlck1vZGVsID0gdGhpcy5pdGVyYWJsZURpZmZlcnMuZmluZChbXSkuY3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2RpZmZlck9wdGlvbnMgPSB0aGlzLml0ZXJhYmxlRGlmZmVycy5maW5kKFtdKS5jcmVhdGUobnVsbCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLkluaXQoKTtcbiAgfVxuICBuZ0RvQ2hlY2soKTogdm9pZCB7XG4gICAgbGV0IGNoYW5nZXNJbk1vZGVsID0gdGhpcy5fZGlmZmVyTW9kZWwuZGlmZih0aGlzLnZhbHVlKTtcbiAgICBsZXQgY2hhbmdlc0luT3B0aW9ucyA9IHRoaXMuX2RpZmZlck9wdGlvbnMuZGlmZih0aGlzLl9vcHRpb25zKTtcblxuICAgIGlmIChjaGFuZ2VzSW5Nb2RlbCB8fCAoY2hhbmdlc0luT3B0aW9ucyAmJiAhdGhpcy5tb2RlbEluaXRpYWxpemVkKSkge1xuICAgICAgdGhpcy5Jbml0KCk7XG4gICAgfVxuICB9XG5cbiAgSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudmFsdWUgfHwgIXRoaXMub3B0aW9ucyB8fCB0aGlzLnZhbHVlLmxlbmd0aCA9PSAwIHx8IHRoaXMub3B0aW9ucy5sZW5ndGggPT0gMCkgeyAgICAgIFxuICAgICAgaWYgKCghdGhpcy52YWx1ZSB8fCB0aGlzLnZhbHVlLmxlbmd0aCA9PSAwKSAmJiB0aGlzLm9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5Ub2dnbGVBbGxJdGVtc1NlbGVjdGlvbihmYWxzZSwgZmFsc2UpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9wdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMub3B0aW9uc1tpXS5zZWxlY3RlZCA9IHRoaXMudmFsdWUuZmlsdGVyKHggPT4gdGhpcy5vcHRpb25zW2ldW3RoaXMudmFsdWVQcm9wZXJ0eV0gPT0geFt0aGlzLnZhbHVlUHJvcGVydHldKS5sZW5ndGggPiAwO1xuICAgIH1cblxuICAgIHRoaXMubW9kZWxJbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICBUb2dnbGVEcm9wRG93bihldmVudDogTW91c2VFdmVudCwgdmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKCh2YWx1ZSA9PSBmYWxzZSAmJiAhdGhpcy5zaG93T3B0aW9ucykgfHwgKHZhbHVlID09IHVuZGVmaW5lZCAmJiB0aGlzLmRpc2FibGVkKSkgcmV0dXJuO1xuXG4gICAgaWYgKHZhbHVlID09IHVuZGVmaW5lZCkgeyBcbiAgICAgIGlmICh0aGlzLnNob3dPcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc2V0Q29tYm9Ub3VjaGVkKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2hvd09wdGlvbnMgPSAhdGhpcy5zaG93T3B0aW9uczsgICAgICBcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCF2YWx1ZSAmJiB0aGlzLnNob3dPcHRpb25zKSB7XG4gICAgICAgIHRoaXMuc2V0Q29tYm9Ub3VjaGVkKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2hvd09wdGlvbnMgPSB2YWx1ZTtcbiAgICB9XG4gICAgXG4gICAgdGhpcy5jbGVhclNlYXJjaCgpO1xuICB9XG4gIFRvZ2dsZUl0ZW1TZWxlY3RlZChpdGVtOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBcbiAgICBpdGVtLnNlbGVjdGVkID0gIWl0ZW0uc2VsZWN0ZWQ7XG4gICAgdGhpcy51cGRhdGVNb2RlbCgpO1xuICAgIHRoaXMub25DaGFuZ2UuZW1pdCgpO1xuICB9XG4gIFRvZ2dsZUFsbEl0ZW1zU2VsZWN0aW9uKHZhbHVlOiBib29sZWFuLCBlbWl0Q2hhbmdlczogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIGlmICghdGhpcy5vcHRpb25zIHx8IHRoaXMub3B0aW9ucy5sZW5ndGggPT0gMCkgcmV0dXJuO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9wdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMub3B0aW9uc1tpXS5zZWxlY3RlZCA9IHZhbHVlO1xuICAgIH1cblxuICAgIHRoaXMudXBkYXRlTW9kZWwoKTtcbiAgICB0aGlzLmNsZWFyU2VhcmNoKCk7XG5cbiAgICBpZiAoZW1pdENoYW5nZXMpIHRoaXMub25DaGFuZ2UuZW1pdCgpO1xuICB9XG4gIEl0ZW1TZWxlY3RlZENoZWNrQ2hhbmdlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBcbiAgICB0aGlzLnVwZGF0ZU1vZGVsKCk7XG4gICAgdGhpcy5vbkNoYW5nZS5lbWl0KCk7XG4gIH0gIFxuXG4gIFJlbW92ZUl0ZW0oaXRlbTogYW55LCBpbmRleDogbnVtYmVyLCBldmVudDogYW55KSB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgIXRoaXMub3B0aW9ucyB8fCB0aGlzLm9wdGlvbnMubGVuZ3RoID09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgXG4gICAgbGV0IGl0ZW1Ub1JlbW92ZSA9IHRoaXMub3B0aW9ucy5maW5kKHggPT4geFt0aGlzLnZhbHVlUHJvcGVydHldID09IGl0ZW1bdGhpcy52YWx1ZVByb3BlcnR5XSk7XG5cbiAgICBpZiAoaXRlbVRvUmVtb3ZlKSB7XG4gICAgICB0aGlzLlRvZ2dsZUl0ZW1TZWxlY3RlZChpdGVtVG9SZW1vdmUpO1xuICAgICAgdGhpcy5jbGVhclNlYXJjaCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnZhbHVlLnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cbiAgXG4gIE9uQ29tYm9QcmVzc2VkKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50LmtleUNvZGUgPT0gMTMpIHtcbiAgICAgIHRoaXMuVG9nZ2xlRHJvcERvd24obnVsbCk7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2xlYXJTZWFyY2goKTogdm9pZCB7XG4gICAgdGhpcy5zZWFyY2ggPSAnJztcbiAgfVxuICBwcml2YXRlIHVwZGF0ZU1vZGVsKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5vcHRpb25zIHx8IHRoaXMub3B0aW9ucy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhpcy52YWx1ZSA9IFtdO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBcbiAgICB0aGlzLnZhbHVlID0gdGhpcy5vcHRpb25zLmZpbHRlcih4ID0+IHguc2VsZWN0ZWQpO1xuICB9XG4gIHByaXZhdGUgc2V0Q29tYm9Ub3VjaGVkKCk6IHZvaWQge1xuICAgIHRoaXMuY29tYm9Ub3VjaGVkID0gdHJ1ZTtcbiAgfVxuXG59XG4iLCI8ZGl2IFtpZF09XCJpZGVudGlmaWVyXCIgY2xhc3M9XCJ1aS1tdWx0aXNlbGVjdFwiPlxuICAgIDxsYWJlbCAqbmdJZj1cImxhYmVsXCI+XG4gICAgICAgIHt7bGFiZWx9fVxuICAgICAgICA8c3BhbiBjbGFzcz1cInJlcXVpcmVkLXN5bWJvbFwiICpuZ0lmPVwiaXNSZXF1aXJlZFwiPiAqPC9zcGFuPlxuICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXF1ZXN0aW9uLWNpcmNsZSBtbC0yXCIgdG9vbHRpcD1cInt7aGVscH19XCIgY29udGFpbmVyPVwiYm9keVwiICpuZ0lmPVwiaGVscFwiPjwvaT5cbiAgICA8L2xhYmVsPlxuXG4gICAgPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBbKG5nTW9kZWwpXT1cInZhbHVlXCIgLz5cbiAgICA8ZGl2IGNsYXNzPVwiY29tYm9ib3ggZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlblwiIFxuICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAnaGFzLXZhbGlkYXRpb25zJzogc2hvd1ZhbGlkYXRpb25zLFxuICAgICAgICAgICAgJ29wZW4nOiBzaG93T3B0aW9ucywgXG4gICAgICAgICAgICAnZGlzYWJsZWQnOiBkaXNhYmxlZCxcbiAgICAgICAgICAgICdpcy12YWxpZCc6ICFzaG93T3B0aW9ucyAmJiAhZGlzYWJsZWQgJiYgY29tYm9Ub3VjaGVkICYmICghaXNSZXF1aXJlZCB8fCB2YWx1ZT8ubGVuZ3RoID4gMCksXG4gICAgICAgICAgICAnaXMtaW52YWxpZCc6ICFzaG93T3B0aW9ucyAmJiAhZGlzYWJsZWQgJiYgY29tYm9Ub3VjaGVkICYmIGlzUmVxdWlyZWQgJiYgKCF2YWx1ZSB8fCB2YWx1ZS5sZW5ndGggPT0gMClcbiAgICAgICAgfVwiXG4gICAgICAgIChjbGljayk9XCJUb2dnbGVEcm9wRG93bigkZXZlbnQpXCIgKGtleXVwKT1cIk9uQ29tYm9QcmVzc2VkKCRldmVudClcIiB0YWJpbmRleD1cIjBcIj5cblxuICAgICAgICA8c3BhbiAqbmdJZj1cIiF2YWx1ZSB8fCB2YWx1ZS5sZW5ndGggPT0gMFwiPnt7cGxhY2Vob2xkZXJ9fTwvc3Bhbj5cblxuICAgICAgICA8ZGl2ICpuZ0lmPVwidmFsdWU/Lmxlbmd0aCA+IDBcIiBjbGFzcz1cInNlbGVjdGVkLWl0ZW1zIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYmFkZ2VcIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiB2YWx1ZSB8IHNsaWNlOjA6bWF4Q291bnRPZkxhYmVsc1RvU2hvdzsgbGV0IGkgPSBpbmRleDtcIiAoY2xpY2spPVwiUmVtb3ZlSXRlbShpdGVtLCBpLCAkZXZlbnQpXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCI+e3tpdGVtW2Rpc3BsYXlUZXh0UHJvcGVydHldfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS10aW1lcyBtbC0yXCIgKm5nSWY9XCIhZGlzYWJsZWRcIj48L2k+XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiAqbmdJZj1cInZhbHVlLmxlbmd0aCA+IG1heENvdW50T2ZMYWJlbHNUb1Nob3dcIj4uLi48L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxpIGNsYXNzPVwiZmFcIiBbbmdDbGFzc109XCJ7J2ZhLWNhcmV0LWRvd24nOiAhc2hvd09wdGlvbnMsICdmYS1jYXJldC11cCc6IHNob3dPcHRpb25zfVwiPjwvaT5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJkcm9wZG93bi1vcHRpb25zIHNoYWRvdyBmYWRlSW5Eb3duXCIgKm5nSWY9XCJzaG93T3B0aW9uc1wiIChjbGlja091dHNpZGUpPVwiVG9nZ2xlRHJvcERvd24oJGV2ZW50LCBmYWxzZSlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm9wdGlvbnMtY29udGFpbmVyXCIgKm5nSWY9XCJvcHRpb25zPy5sZW5ndGggPiAwXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbGJhciBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZmxleC1ncm93LTFcIiBuYW1lPVwie3tpZGVudGlmaWVyfX0tc2VhcmNoXCIgWyhuZ01vZGVsKV09XCJzZWFyY2hcIiBwbGFjZWhvbGRlcj1cInt7c2VhcmNoUGxhY2Vob2xkZXJ9fVwiIGF1dG8tZm9jdXMgLz5cbiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tbGlnaHQgbWwtMSBmbGV4LXNocmluay0wXCIgKGNsaWNrKT1cIlRvZ2dsZUFsbEl0ZW1zU2VsZWN0aW9uKHRydWUsIHRydWUpXCIgW2Rpc2FibGVkXT1cImRpc2FibGVkXCI+PGkgY2xhc3M9XCJmYSBmYS1jaGVjay1zcXVhcmVcIj48L2k+IHt7c2VsZWN0QWxsQnV0dG9uTGFiZWx9fTwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBtbC0xIGZsZXgtc2hyaW5rLTBcIiAoY2xpY2spPVwiVG9nZ2xlQWxsSXRlbXNTZWxlY3Rpb24oZmFsc2UsIHRydWUpXCIgW2Rpc2FibGVkXT1cImRpc2FibGVkXCI+PGkgY2xhc3M9XCJmYSBmYS1lcmFzZXJcIj48L2k+IHt7Y2xlYXJTZWxlY3Rpb25CdXR0b25MYWJlbH19PC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPHVsPlxuICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImQtZmxleFwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIG9wdGlvbnMgfCBzZWFyY2hCeSA6IGRpc3BsYXlUZXh0UHJvcGVydHkgOiBzZWFyY2hcIiBbbmdDbGFzc109XCJ7J3NlbGVjdGVkJzogaXRlbS5zZWxlY3RlZH1cIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNoZWNrYm94IG1yLTMgZmxleC1zaHJpbmstMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIG5hbWU9XCJ7e2lkZW50aWZpZXJ9fS1vcHRpb25cIiBbKG5nTW9kZWwpXT1cIml0ZW0uc2VsZWN0ZWRcIiAoY2hhbmdlKT1cIkl0ZW1TZWxlY3RlZENoZWNrQ2hhbmdlZCgpXCIgW2Rpc2FibGVkXT1cImRpc2FibGVkXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGlua1wiIChjbGljayk9XCJUb2dnbGVJdGVtU2VsZWN0ZWQoaXRlbSlcIj57e2l0ZW1bZGlzcGxheVRleHRQcm9wZXJ0eV19fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgPC91bD5cblxuICAgICAgICAgICAgPHNtYWxsIGNsYXNzPVwiZW1wdHktcmVzdWx0c1wiICpuZ0lmPVwiKG9wdGlvbnMgfCBzZWFyY2hCeSA6IGRpc3BsYXlUZXh0UHJvcGVydHkgOiBzZWFyY2gpLmxlbmd0aCA9PSAwXCI+e3tlbXB0eU1lc3NhZ2V9fTwvc21hbGw+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxzbWFsbCBjbGFzcz1cImVtcHR5LXJlc3VsdHNcIiAqbmdJZj1cIiFvcHRpb25zIHx8IG9wdGlvbnMubGVuZ3RoID09IDBcIj57e2VtcHR5TWVzc2FnZX19PC9zbWFsbD5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuXG48c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCIgKm5nSWY9XCJkZXNjcmlwdGlvblwiPnt7ZGVzY3JpcHRpb259fTwvc21hbGw+XG4iXX0=