@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
79 lines • 17.7 kB
JavaScript
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SearchBuilderFocusService } from '../search-builder-focus.service';
import { SearchBuilderGroupService } from './search-builder-group.service';
import * as i0 from "@angular/core";
import * as i1 from "../../../directives/accessibility/focus-indicator/focus-indicator.directive";
import * as i2 from "../../../directives/accessibility/focus-within/focus-within.directive";
import * as i3 from "@angular/common";
import * as i4 from "../../icon/icon.component";
import * as i5 from "../search-builder-outlet/search-builder-outlet.directive";
export class SearchBuilderGroupComponent {
constructor() {
this.searchBuilderGroupService = inject(SearchBuilderGroupService);
this._searchBuilderFocusService = inject(SearchBuilderFocusService);
this.operator = 'and';
this.addText = 'Add a field';
this.showPlaceholder = false;
this.removeFieldButtonAriaLabel = 'Remove field';
this.add = new EventEmitter();
this.remove = new EventEmitter();
this.focusIndex = -1;
this._onDestroy = new Subject();
}
ngOnInit() {
// ensure we have a name otherwise throw an error
if (!this.id) {
throw new Error('Search builder group must have an id attribute.');
}
// otherwise register the group
this.searchBuilderGroupService.init(this.id);
// Track focus for child components
this._searchBuilderFocusService.focus$.pipe(takeUntil(this._onDestroy)).subscribe(focus => {
this.focusIndex = (focus.groupId === this.id) ? focus.index : -1;
});
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
addField(event) {
this.add.emit(event);
}
removeFieldAtIndex(index, field) {
this.searchBuilderGroupService.removeAtIndex(index);
this.remove.emit(field);
}
setFocus(index) {
this._searchBuilderFocusService.setFocus(this.id, index);
}
clearFocus() {
this._searchBuilderFocusService.clearFocus();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SearchBuilderGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: SearchBuilderGroupComponent, selector: "ux-search-builder-group", inputs: { id: "id", header: "header", operator: "operator", addText: "addText", placeholder: "placeholder", showPlaceholder: "showPlaceholder", removeFieldButtonAriaLabel: "removeFieldButtonAriaLabel" }, outputs: { add: "add", remove: "remove" }, providers: [SearchBuilderGroupService], ngImport: i0, template: "<h4 class=\"search-group-title\">{{ header }}</h4>\n\n<div class=\"search-group-content\">\n\n <div class=\"search-group-operator search-group-operator-{{ operator }}\"\n [class.hidden-operator]=\"searchBuilderGroupService.getQuery().length < 2\">{{ operator }}</div>\n\n <div class=\"search-group-items\">\n\n @for (field of searchBuilderGroupService.getQuery(); track field; let i = $index) {\n <div\n class=\"search-group-item-container\"\n [class.search-group-item-focus]=\"focusIndex === i\"\n (uxFocusWithin)=\"setFocus(i)\"\n (uxBlurWithin)=\"clearFocus()\">\n <div class=\"search-group-item\">\n <ng-container *uxSearchBuilderOutlet=\"field.type; context: field; groupId: id; index: i\"></ng-container>\n </div>\n <button type=\"button\"\n uxFocusIndicator\n [attr.aria-label]=\"removeFieldButtonAriaLabel\"\n class=\"search-group-item-remove\"\n (click)=\"removeFieldAtIndex(i, field)\">\n <ux-icon name=\"close\"></ux-icon>\n </button>\n </div>\n }\n\n <!-- Placeholder Item -->\n @if (showPlaceholder) {\n <!-- The Default Placeholder -->\n @if (!placeholder) {\n <div class=\"search-group-item-container placeholder-item\">\n <div class=\"search-group-item\">\n <label class=\"form-label\">New field</label>\n <div class=\"form-control\"></div>\n </div>\n </div>\n }\n <!-- Allow a custom placeholder -->\n <ng-container *ngTemplateOutlet=\"placeholder\"></ng-container>\n }\n\n </div>\n\n <button type=\"button\" uxFocusIndicator class=\"search-builder-group-add-field\" (click)=\"addField($event)\">\n <ux-icon class=\"search-builder-group-add-field-icon\" name=\"add\"></ux-icon>\n <span class=\"search-builder-group-add-field-label\">{{ addText }}</span>\n </button>\n\n</div>\n\n<hr class=\"search-builder-group-divider\">\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.FocusWithinDirective, selector: "[uxFocusWithin],[uxBlurWithin]", outputs: ["uxFocusWithin", "uxBlurWithin"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "directive", type: i5.SearchBuilderOutletDirective, selector: "[uxSearchBuilderOutlet]", inputs: ["uxSearchBuilderOutlet", "uxSearchBuilderOutletContext", "uxSearchBuilderOutletGroupId", "uxSearchBuilderOutletIndex"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SearchBuilderGroupComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-search-builder-group', providers: [SearchBuilderGroupService], template: "<h4 class=\"search-group-title\">{{ header }}</h4>\n\n<div class=\"search-group-content\">\n\n <div class=\"search-group-operator search-group-operator-{{ operator }}\"\n [class.hidden-operator]=\"searchBuilderGroupService.getQuery().length < 2\">{{ operator }}</div>\n\n <div class=\"search-group-items\">\n\n @for (field of searchBuilderGroupService.getQuery(); track field; let i = $index) {\n <div\n class=\"search-group-item-container\"\n [class.search-group-item-focus]=\"focusIndex === i\"\n (uxFocusWithin)=\"setFocus(i)\"\n (uxBlurWithin)=\"clearFocus()\">\n <div class=\"search-group-item\">\n <ng-container *uxSearchBuilderOutlet=\"field.type; context: field; groupId: id; index: i\"></ng-container>\n </div>\n <button type=\"button\"\n uxFocusIndicator\n [attr.aria-label]=\"removeFieldButtonAriaLabel\"\n class=\"search-group-item-remove\"\n (click)=\"removeFieldAtIndex(i, field)\">\n <ux-icon name=\"close\"></ux-icon>\n </button>\n </div>\n }\n\n <!-- Placeholder Item -->\n @if (showPlaceholder) {\n <!-- The Default Placeholder -->\n @if (!placeholder) {\n <div class=\"search-group-item-container placeholder-item\">\n <div class=\"search-group-item\">\n <label class=\"form-label\">New field</label>\n <div class=\"form-control\"></div>\n </div>\n </div>\n }\n <!-- Allow a custom placeholder -->\n <ng-container *ngTemplateOutlet=\"placeholder\"></ng-container>\n }\n\n </div>\n\n <button type=\"button\" uxFocusIndicator class=\"search-builder-group-add-field\" (click)=\"addField($event)\">\n <ux-icon class=\"search-builder-group-add-field-icon\" name=\"add\"></ux-icon>\n <span class=\"search-builder-group-add-field-label\">{{ addText }}</span>\n </button>\n\n</div>\n\n<hr class=\"search-builder-group-divider\">\n" }]
}], propDecorators: { id: [{
type: Input
}], header: [{
type: Input
}], operator: [{
type: Input
}], addText: [{
type: Input
}], placeholder: [{
type: Input
}], showPlaceholder: [{
type: Input
}], removeFieldButtonAriaLabel: [{
type: Input
}], add: [{
type: Output
}], remove: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLWJ1aWxkZXItZ3JvdXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc2VhcmNoLWJ1aWxkZXIvc2VhcmNoLWJ1aWxkZXItZ3JvdXAvc2VhcmNoLWJ1aWxkZXItZ3JvdXAuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc2VhcmNoLWJ1aWxkZXIvc2VhcmNoLWJ1aWxkZXItZ3JvdXAvc2VhcmNoLWJ1aWxkZXItZ3JvdXAuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFlLE1BQU0sZUFBZSxDQUFDO0FBQy9HLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDOzs7Ozs7O0FBTzNFLE1BQU0sT0FBTywyQkFBMkI7SUFMeEM7UUFNVyw4QkFBeUIsR0FBRyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUV0RCwrQkFBMEIsR0FBRyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUl2RSxhQUFRLEdBQStCLEtBQUssQ0FBQztRQUM3QyxZQUFPLEdBQVcsYUFBYSxDQUFDO1FBRWhDLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBQ2pDLCtCQUEwQixHQUFXLGNBQWMsQ0FBQztRQUVuRCxRQUFHLEdBQTZCLElBQUksWUFBWSxFQUFjLENBQUM7UUFDL0QsV0FBTSxHQUEwQyxJQUFJLFlBQVksRUFBMkIsQ0FBQztRQUV0RyxlQUFVLEdBQVcsQ0FBQyxDQUFDLENBQUM7UUFFUCxlQUFVLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztLQXVDbkQ7SUFyQ0MsUUFBUTtRQUVOLGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFFRCwrQkFBK0I7UUFDL0IsSUFBSSxDQUFDLHlCQUF5QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFN0MsbUNBQW1DO1FBQ25DLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDeEYsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxRQUFRLENBQUMsS0FBaUI7UUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkIsQ0FBQztJQUVELGtCQUFrQixDQUFDLEtBQWEsRUFBRSxLQUE4QjtRQUM5RCxJQUFJLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFFRCxRQUFRLENBQUMsS0FBYTtRQUNwQixJQUFJLENBQUMsMEJBQTBCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELFVBQVU7UUFDUixJQUFJLENBQUMsMEJBQTBCLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDL0MsQ0FBQzsrR0F4RFUsMkJBQTJCO21HQUEzQiwyQkFBMkIseVNBRjNCLENBQUMseUJBQXlCLENBQUMsMEJDVnhDLGk3REFxREE7OzRGRHpDYSwyQkFBMkI7a0JBTHZDLFNBQVM7K0JBQ0UseUJBQXlCLGFBRXhCLENBQUMseUJBQXlCLENBQUM7OEJBTzdCLEVBQUU7c0JBQVYsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLDBCQUEwQjtzQkFBbEMsS0FBSztnQkFFSSxHQUFHO3NCQUFaLE1BQU07Z0JBQ0csTUFBTTtzQkFBZixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIGluamVjdCwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBTZWFyY2hCdWlsZGVyR3JvdXBRdWVyeSB9IGZyb20gJy4uL2ludGVyZmFjZXMvZ3JvdXAtcXVlcnkuaW50ZXJmYWNlJztcbmltcG9ydCB7IFNlYXJjaEJ1aWxkZXJGb2N1c1NlcnZpY2UgfSBmcm9tICcuLi9zZWFyY2gtYnVpbGRlci1mb2N1cy5zZXJ2aWNlJztcbmltcG9ydCB7IFNlYXJjaEJ1aWxkZXJHcm91cFNlcnZpY2UgfSBmcm9tICcuL3NlYXJjaC1idWlsZGVyLWdyb3VwLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd1eC1zZWFyY2gtYnVpbGRlci1ncm91cCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9zZWFyY2gtYnVpbGRlci1ncm91cC5jb21wb25lbnQuaHRtbCcsXG4gIHByb3ZpZGVyczogW1NlYXJjaEJ1aWxkZXJHcm91cFNlcnZpY2VdXG59KVxuZXhwb3J0IGNsYXNzIFNlYXJjaEJ1aWxkZXJHcm91cENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgcmVhZG9ubHkgc2VhcmNoQnVpbGRlckdyb3VwU2VydmljZSA9IGluamVjdChTZWFyY2hCdWlsZGVyR3JvdXBTZXJ2aWNlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9zZWFyY2hCdWlsZGVyRm9jdXNTZXJ2aWNlID0gaW5qZWN0KFNlYXJjaEJ1aWxkZXJGb2N1c1NlcnZpY2UpO1xuXG4gIEBJbnB1dCgpIGlkOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGhlYWRlcjogc3RyaW5nO1xuICBASW5wdXQoKSBvcGVyYXRvcjogU2VhcmNoQnVpbGRlckdyb3VwT3BlcmF0b3IgPSAnYW5kJztcbiAgQElucHV0KCkgYWRkVGV4dDogc3RyaW5nID0gJ0FkZCBhIGZpZWxkJztcbiAgQElucHV0KCkgcGxhY2Vob2xkZXI6IFRlbXBsYXRlUmVmPHZvaWQ+O1xuICBASW5wdXQoKSBzaG93UGxhY2Vob2xkZXI6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgcmVtb3ZlRmllbGRCdXR0b25BcmlhTGFiZWw6IHN0cmluZyA9ICdSZW1vdmUgZmllbGQnO1xuXG4gIEBPdXRwdXQoKSBhZGQ6IEV2ZW50RW1pdHRlcjxNb3VzZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8TW91c2VFdmVudD4oKTtcbiAgQE91dHB1dCgpIHJlbW92ZTogRXZlbnRFbWl0dGVyPFNlYXJjaEJ1aWxkZXJHcm91cFF1ZXJ5PiA9IG5ldyBFdmVudEVtaXR0ZXI8U2VhcmNoQnVpbGRlckdyb3VwUXVlcnk+KCk7XG5cbiAgZm9jdXNJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcblxuICAgIC8vIGVuc3VyZSB3ZSBoYXZlIGEgbmFtZSBvdGhlcndpc2UgdGhyb3cgYW4gZXJyb3JcbiAgICBpZiAoIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU2VhcmNoIGJ1aWxkZXIgZ3JvdXAgbXVzdCBoYXZlIGFuIGlkIGF0dHJpYnV0ZS4nKTtcbiAgICB9XG5cbiAgICAvLyBvdGhlcndpc2UgcmVnaXN0ZXIgdGhlIGdyb3VwXG4gICAgdGhpcy5zZWFyY2hCdWlsZGVyR3JvdXBTZXJ2aWNlLmluaXQodGhpcy5pZCk7XG5cbiAgICAvLyBUcmFjayBmb2N1cyBmb3IgY2hpbGQgY29tcG9uZW50c1xuICAgIHRoaXMuX3NlYXJjaEJ1aWxkZXJGb2N1c1NlcnZpY2UuZm9jdXMkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpLnN1YnNjcmliZShmb2N1cyA9PiB7XG4gICAgICB0aGlzLmZvY3VzSW5kZXggPSAoZm9jdXMuZ3JvdXBJZCA9PT0gdGhpcy5pZCkgPyBmb2N1cy5pbmRleCA6IC0xO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcbiAgfVxuXG4gIGFkZEZpZWxkKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5hZGQuZW1pdChldmVudCk7XG4gIH1cblxuICByZW1vdmVGaWVsZEF0SW5kZXgoaW5kZXg6IG51bWJlciwgZmllbGQ6IFNlYXJjaEJ1aWxkZXJHcm91cFF1ZXJ5KTogdm9pZCB7XG4gICAgdGhpcy5zZWFyY2hCdWlsZGVyR3JvdXBTZXJ2aWNlLnJlbW92ZUF0SW5kZXgoaW5kZXgpO1xuICAgIHRoaXMucmVtb3ZlLmVtaXQoZmllbGQpO1xuICB9XG5cbiAgc2V0Rm9jdXMoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuX3NlYXJjaEJ1aWxkZXJGb2N1c1NlcnZpY2Uuc2V0Rm9jdXModGhpcy5pZCwgaW5kZXgpO1xuICB9XG5cbiAgY2xlYXJGb2N1cygpOiB2b2lkIHtcbiAgICB0aGlzLl9zZWFyY2hCdWlsZGVyRm9jdXNTZXJ2aWNlLmNsZWFyRm9jdXMoKTtcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBTZWFyY2hCdWlsZGVyR3JvdXBPcGVyYXRvciA9ICdhbmQnIHwgJ29yJyB8ICdub3QnO1xuIiwiPGg0IGNsYXNzPVwic2VhcmNoLWdyb3VwLXRpdGxlXCI+e3sgaGVhZGVyIH19PC9oND5cblxuPGRpdiBjbGFzcz1cInNlYXJjaC1ncm91cC1jb250ZW50XCI+XG5cbiAgPGRpdiBjbGFzcz1cInNlYXJjaC1ncm91cC1vcGVyYXRvciBzZWFyY2gtZ3JvdXAtb3BlcmF0b3Ite3sgb3BlcmF0b3IgfX1cIlxuICBbY2xhc3MuaGlkZGVuLW9wZXJhdG9yXT1cInNlYXJjaEJ1aWxkZXJHcm91cFNlcnZpY2UuZ2V0UXVlcnkoKS5sZW5ndGggPCAyXCI+e3sgb3BlcmF0b3IgfX08L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwic2VhcmNoLWdyb3VwLWl0ZW1zXCI+XG5cbiAgICBAZm9yIChmaWVsZCBvZiBzZWFyY2hCdWlsZGVyR3JvdXBTZXJ2aWNlLmdldFF1ZXJ5KCk7IHRyYWNrIGZpZWxkOyBsZXQgaSA9ICRpbmRleCkge1xuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cInNlYXJjaC1ncm91cC1pdGVtLWNvbnRhaW5lclwiXG4gICAgICAgIFtjbGFzcy5zZWFyY2gtZ3JvdXAtaXRlbS1mb2N1c109XCJmb2N1c0luZGV4ID09PSBpXCJcbiAgICAgICAgKHV4Rm9jdXNXaXRoaW4pPVwic2V0Rm9jdXMoaSlcIlxuICAgICAgICAodXhCbHVyV2l0aGluKT1cImNsZWFyRm9jdXMoKVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic2VhcmNoLWdyb3VwLWl0ZW1cIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICp1eFNlYXJjaEJ1aWxkZXJPdXRsZXQ9XCJmaWVsZC50eXBlOyBjb250ZXh0OiBmaWVsZDsgZ3JvdXBJZDogaWQ7IGluZGV4OiBpXCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIHV4Rm9jdXNJbmRpY2F0b3JcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInJlbW92ZUZpZWxkQnV0dG9uQXJpYUxhYmVsXCJcbiAgICAgICAgICBjbGFzcz1cInNlYXJjaC1ncm91cC1pdGVtLXJlbW92ZVwiXG4gICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUZpZWxkQXRJbmRleChpLCBmaWVsZClcIj5cbiAgICAgICAgICA8dXgtaWNvbiBuYW1lPVwiY2xvc2VcIj48L3V4LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBQbGFjZWhvbGRlciBJdGVtIC0tPlxuICAgIEBpZiAoc2hvd1BsYWNlaG9sZGVyKSB7XG4gICAgICA8IS0tIFRoZSBEZWZhdWx0IFBsYWNlaG9sZGVyIC0tPlxuICAgICAgQGlmICghcGxhY2Vob2xkZXIpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1ncm91cC1pdGVtLWNvbnRhaW5lciBwbGFjZWhvbGRlci1pdGVtXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1ncm91cC1pdGVtXCI+XG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+TmV3IGZpZWxkPC9sYWJlbD5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIj48L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8IS0tIEFsbG93IGEgY3VzdG9tIHBsYWNlaG9sZGVyIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInBsYWNlaG9sZGVyXCI+PC9uZy1jb250YWluZXI+XG4gICAgfVxuXG4gIDwvZGl2PlxuXG4gIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIHV4Rm9jdXNJbmRpY2F0b3IgY2xhc3M9XCJzZWFyY2gtYnVpbGRlci1ncm91cC1hZGQtZmllbGRcIiAoY2xpY2spPVwiYWRkRmllbGQoJGV2ZW50KVwiPlxuICAgIDx1eC1pY29uIGNsYXNzPVwic2VhcmNoLWJ1aWxkZXItZ3JvdXAtYWRkLWZpZWxkLWljb25cIiBuYW1lPVwiYWRkXCI+PC91eC1pY29uPlxuICAgIDxzcGFuIGNsYXNzPVwic2VhcmNoLWJ1aWxkZXItZ3JvdXAtYWRkLWZpZWxkLWxhYmVsXCI+e3sgYWRkVGV4dCB9fTwvc3Bhbj5cbiAgPC9idXR0b24+XG5cbjwvZGl2PlxuXG48aHIgY2xhc3M9XCJzZWFyY2gtYnVpbGRlci1ncm91cC1kaXZpZGVyXCI+XG4iXX0=