UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

75 lines 26.3 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, inject, Input, Renderer2, ViewChild } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { ResizeService } from '../../../directives/resize/index'; import { HierarchyBarService } from '../hierarchy-bar.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-indicator/focus-indicator-origin/focus-indicator-origin.directive"; import * as i3 from "@angular/common"; import * as i4 from "../../icon/icon.component"; import * as i5 from "../../popover/popover.directive"; import * as i6 from "../hierarchy-bar-node/hierarchy-bar-node.component"; import * as i7 from "../hierarchy-bar-popover/hierarchy-bar-popover.component"; export class HierarchyBarCollapsedComponent { constructor() { this.hierarchyBar = inject(HierarchyBarService); this._renderer = inject(Renderer2); this._resizeService = inject(ResizeService); this._elementRef = inject(ElementRef); this._changeDetector = inject(ChangeDetectorRef); /** Unsubscribe from all observables on destroy */ this._onDestroy = new Subject(); } /** Get all the sibling nodes */ get _siblings() { return this.hierarchyBar.getSiblings(this._last); } /** Get all the nodes between the first and last nodes */ get _parents() { return this._nodes.filter(node => node !== this._first && node !== this._last); } /** Get the nodes as an array */ get _nodes() { return this.hierarchyBar.nodes$.value; } ngAfterViewInit() { // Update the UI when the selected nodes change this.hierarchyBar.nodes$.pipe(takeUntil(this._onDestroy)).subscribe(this.update.bind(this)); // watch for the host element size changing this._resizeService.addResizeListener(this._elementRef.nativeElement).pipe(takeUntil(this._onDestroy)) .subscribe(() => this.updateOverflow()); } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); // remove the resize event listener this._resizeService.removeResizeListener(this._elementRef.nativeElement); } update(nodes) { this._first = nodes[0]; this._last = nodes.length > 1 ? nodes[nodes.length - 1] : null; this.updateOverflow(); this._changeDetector.detectChanges(); } updateOverflow() { // remove the class if it is present this._renderer.removeClass(this.nodeContainer.nativeElement, 'hierarchy-bar-nodes-overflow'); // check if there is overflow if (this.nodeContainer.nativeElement.scrollWidth > this.nodeContainer.nativeElement.offsetWidth) { this._renderer.addClass(this.nodeContainer.nativeElement, 'hierarchy-bar-nodes-overflow'); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: HierarchyBarCollapsedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: HierarchyBarCollapsedComponent, selector: "ux-hierarchy-bar-collapsed", inputs: { readonly: "readonly" }, viewQueries: [{ propertyName: "nodeContainer", first: true, predicate: ["nodes"], descendants: true, static: true }], ngImport: i0, template: "<!-- Allow content to be placed on the left of the items -->\n<div class=\"hierarchy-bar-addons\">\n <ng-content select=\"left-addons\"></ng-content>\n</div>\n\n<div #nodes class=\"hierarchy-bar-nodes\">\n\n @if (_first) {\n <ux-hierarchy-bar-node\n [readonly]=\"readonly\"\n [popoverTemplate]=\"content\"\n [node]=\"_first\"\n (selected)=\"hierarchyBar.selectNode($event)\">\n </ux-hierarchy-bar-node>\n }\n\n @if (_parents.length > 0) {\n <div class=\"hierarchy-bar-overflow\">\n <div class=\"hierarchy-bar-overflow-container\">\n <ng-container [ngTemplateOutlet]=\"hierarchyBar.overflowTemplate || defaultOverflowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _parents }\">\n </ng-container>\n </div>\n <button [attr.aria-label]=\"hierarchyBar.showSiblingsAriaLabel\"\n uxFocusIndicator\n uxFocusIndicatorOrigin\n class=\"hierarchy-bar-node-arrow\"\n placement=\"bottom\"\n [uxPopover]=\"siblingsTemplate\"\n popoverClass=\"hierarchy-bar-popover\"\n role=\"button\"\n tabindex=\"0\"\n [disabled]=\"readonly\"\n #popover=\"ux-popover\"\n [popoverContext]=\"{ popover: popover }\"\n [showTriggers]=\"hierarchyBar.popoverShowTriggers\"\n [hideTriggers]=\"hierarchyBar.popoverHideTriggers\"\n type=\"button\">\n <ux-icon name=\"next\" class=\"hierarchy-bar-node-arrow-icon\"></ux-icon>\n </button>\n </div>\n }\n\n\n @if (_last) {\n <ux-hierarchy-bar-node\n [readonly]=\"readonly\"\n [popoverTemplate]=\"content\"\n [node]=\"_last\"\n (selected)=\"hierarchyBar.selectNode($event)\">\n </ux-hierarchy-bar-node>\n }\n\n <!-- Allow content to be placed after the last node -->\n <div class=\"hierarchy-bar-addons\">\n <ng-content select=\"trailing-addons\"></ng-content>\n </div>\n\n</div>\n\n<!-- Allow content to be placed on the right of the items -->\n<div class=\"hierarchy-bar-addons\">\n <ng-content select=\"right-addons\"></ng-content>\n</div>\n\n<!-- Template for the popover list -->\n<ng-template #content let-node=\"node\" let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [loading]=\"(hierarchyBar.getChildren(node) | async)?.loading\"\n [nodes]=\"(hierarchyBar.getChildren(node) | async)?.children\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Template for the siblings popover list -->\n<ng-template #siblingsTemplate let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [nodes]=\"(_siblings | async)?.children\"\n [loading]=\"(_siblings | async)?.loading\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Template for the parents popover list -->\n<ng-template #parentsTemplate let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [nodes]=\"_parents\"\n [separator]=\"true\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Default Overflow Template -->\n<ng-template #defaultOverflowTemplate>\n <button uxFocusIndicator\n uxFocusIndicatorOrigin\n [disabled]=\"readonly\"\n class=\"overflow-button\"\n aria-label=\"Show parents\"\n [uxPopover]=\"parentsTemplate\"\n popoverClass=\"hierarchy-bar-popover\"\n role=\"button\"\n tabindex=\"0\"\n #popover=\"ux-popover\"\n [popoverContext]=\"{ popover: popover }\"\n [showTriggers]=\"hierarchyBar.popoverShowTriggers\"\n [hideTriggers]=\"hierarchyBar.popoverHideTriggers\"\n placement=\"bottom\"\n type=\"button\">\n <ux-icon name=\"more\"></ux-icon>\n </button>\n</ng-template>\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.FocusIndicatorOriginDirective, selector: "[uxFocusIndicatorOrigin]" }, { 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.PopoverDirective, selector: "[uxPopover]", inputs: ["uxPopover", "popoverTitle", "popoverDisabled", "popoverClass", "popoverRole", "popoverContext", "popoverDelay", "showTriggers", "hideTriggers"], exportAs: ["ux-popover"] }, { kind: "component", type: i6.HierarchyBarNodeComponent, selector: "ux-hierarchy-bar-node", inputs: ["node", "popoverTemplate", "mode", "readonly", "offset"], outputs: ["selected"] }, { kind: "component", type: i7.HierarchyBarPopoverComponent, selector: "ux-hierarchy-bar-popover", inputs: ["nodes", "loading", "separator"], outputs: ["selected"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: HierarchyBarCollapsedComponent, decorators: [{ type: Component, args: [{ selector: 'ux-hierarchy-bar-collapsed', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Allow content to be placed on the left of the items -->\n<div class=\"hierarchy-bar-addons\">\n <ng-content select=\"left-addons\"></ng-content>\n</div>\n\n<div #nodes class=\"hierarchy-bar-nodes\">\n\n @if (_first) {\n <ux-hierarchy-bar-node\n [readonly]=\"readonly\"\n [popoverTemplate]=\"content\"\n [node]=\"_first\"\n (selected)=\"hierarchyBar.selectNode($event)\">\n </ux-hierarchy-bar-node>\n }\n\n @if (_parents.length > 0) {\n <div class=\"hierarchy-bar-overflow\">\n <div class=\"hierarchy-bar-overflow-container\">\n <ng-container [ngTemplateOutlet]=\"hierarchyBar.overflowTemplate || defaultOverflowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: _parents }\">\n </ng-container>\n </div>\n <button [attr.aria-label]=\"hierarchyBar.showSiblingsAriaLabel\"\n uxFocusIndicator\n uxFocusIndicatorOrigin\n class=\"hierarchy-bar-node-arrow\"\n placement=\"bottom\"\n [uxPopover]=\"siblingsTemplate\"\n popoverClass=\"hierarchy-bar-popover\"\n role=\"button\"\n tabindex=\"0\"\n [disabled]=\"readonly\"\n #popover=\"ux-popover\"\n [popoverContext]=\"{ popover: popover }\"\n [showTriggers]=\"hierarchyBar.popoverShowTriggers\"\n [hideTriggers]=\"hierarchyBar.popoverHideTriggers\"\n type=\"button\">\n <ux-icon name=\"next\" class=\"hierarchy-bar-node-arrow-icon\"></ux-icon>\n </button>\n </div>\n }\n\n\n @if (_last) {\n <ux-hierarchy-bar-node\n [readonly]=\"readonly\"\n [popoverTemplate]=\"content\"\n [node]=\"_last\"\n (selected)=\"hierarchyBar.selectNode($event)\">\n </ux-hierarchy-bar-node>\n }\n\n <!-- Allow content to be placed after the last node -->\n <div class=\"hierarchy-bar-addons\">\n <ng-content select=\"trailing-addons\"></ng-content>\n </div>\n\n</div>\n\n<!-- Allow content to be placed on the right of the items -->\n<div class=\"hierarchy-bar-addons\">\n <ng-content select=\"right-addons\"></ng-content>\n</div>\n\n<!-- Template for the popover list -->\n<ng-template #content let-node=\"node\" let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [loading]=\"(hierarchyBar.getChildren(node) | async)?.loading\"\n [nodes]=\"(hierarchyBar.getChildren(node) | async)?.children\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Template for the siblings popover list -->\n<ng-template #siblingsTemplate let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [nodes]=\"(_siblings | async)?.children\"\n [loading]=\"(_siblings | async)?.loading\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Template for the parents popover list -->\n<ng-template #parentsTemplate let-popover=\"popover\">\n <ux-hierarchy-bar-popover\n [nodes]=\"_parents\"\n [separator]=\"true\"\n (selected)=\"hierarchyBar.selectNode($event); popover.hide()\">\n </ux-hierarchy-bar-popover>\n</ng-template>\n\n<!-- Default Overflow Template -->\n<ng-template #defaultOverflowTemplate>\n <button uxFocusIndicator\n uxFocusIndicatorOrigin\n [disabled]=\"readonly\"\n class=\"overflow-button\"\n aria-label=\"Show parents\"\n [uxPopover]=\"parentsTemplate\"\n popoverClass=\"hierarchy-bar-popover\"\n role=\"button\"\n tabindex=\"0\"\n #popover=\"ux-popover\"\n [popoverContext]=\"{ popover: popover }\"\n [showTriggers]=\"hierarchyBar.popoverShowTriggers\"\n [hideTriggers]=\"hierarchyBar.popoverHideTriggers\"\n placement=\"bottom\"\n type=\"button\">\n <ux-icon name=\"more\"></ux-icon>\n </button>\n</ng-template>\n" }] }], propDecorators: { readonly: [{ type: Input }], nodeContainer: [{ type: ViewChild, args: ['nodes', { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGllcmFyY2h5LWJhci1jb2xsYXBzZWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvaGllcmFyY2h5LWJhci9oaWVyYXJjaHktYmFyLWNvbGxhcHNlZC9oaWVyYXJjaHktYmFyLWNvbGxhcHNlZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9oaWVyYXJjaHktYmFyL2hpZXJhcmNoeS1iYXItY29sbGFwc2VkL2hpZXJhcmNoeS1iYXItY29sbGFwc2VkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFhLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakssT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDOzs7Ozs7Ozs7QUFTL0QsTUFBTSxPQUFPLDhCQUE4QjtJQUwzQztRQU1hLGlCQUFZLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFFbkMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU5QixtQkFBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUV2QyxnQkFBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVqQyxvQkFBZSxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBMEI3RCxrREFBa0Q7UUFDakMsZUFBVSxHQUFHLElB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b25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgaW5qZWN0LCBJbnB1dCwgT25EZXN0cm95LCBSZW5kZXJlcjIsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgUmVzaXplU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2RpcmVjdGl2ZXMvcmVzaXplL2luZGV4JztcbmltcG9ydCB7IEhpZXJhcmNoeUJhclNlcnZpY2UgfSBmcm9tICcuLi9oaWVyYXJjaHktYmFyLnNlcnZpY2UnO1xuaW1wb3J0IHsgSGllcmFyY2h5QmFyTm9kZUNoaWxkcmVuIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9oaWVyYXJjaHktYmFyLW5vZGUtY2hpbGRyZW4uaW50ZXJmYWNlJztcbmltcG9ydCB7IEhpZXJhcmNoeUJhck5vZGUgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2hpZXJhcmNoeS1iYXItbm9kZS5pbnRlcmZhY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3V4LWhpZXJhcmNoeS1iYXItY29sbGFwc2VkJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vaGllcmFyY2h5LWJhci1jb2xsYXBzZWQuY29tcG9uZW50Lmh0bWwnLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEhpZXJhcmNoeUJhckNvbGxhcHNlZENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gICAgcmVhZG9ubHkgaGllcmFyY2h5QmFyID0gaW5qZWN0KEhpZXJhcmNoeUJhclNlcnZpY2UpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3Jlc2l6ZVNlcnZpY2UgPSBpbmplY3QoUmVzaXplU2VydmljZSk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gICAgLyoqIERldGVybWluZSByZWFkIG9ubHkgc3RhdGUgKi9cbiAgICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbjtcblxuICAgIC8qKiBHZXQgdGhlIGZpcnN0IG5vZGUgdG8gZGlzcGxheSAqL1xuICAgIF9maXJzdDogSGllcmFyY2h5QmFyTm9kZTtcblxuICAgIC8qKiBHZXQgdGhlIGxhc3Qgbm9kZSB0byBkaXNwbGF5ICovXG4gICAgX2xhc3Q6IEhpZXJhcmNoeUJhck5vZGU7XG5cbiAgICAvKiogR2V0IGFsbCB0aGUgc2libGluZyBub2RlcyAqL1xuICAgIGdldCBfc2libGluZ3MoKTogT2JzZXJ2YWJsZTxIaWVyYXJjaHlCYXJOb2RlQ2hpbGRyZW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGllcmFyY2h5QmFyLmdldFNpYmxpbmdzKHRoaXMuX2xhc3QpO1xuICAgIH1cblxuICAgIC8qKiBHZXQgYWxsIHRoZSBub2RlcyBiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgbGFzdCBub2RlcyAqL1xuICAgIGdldCBfcGFyZW50cygpOiBIaWVyYXJjaHlCYXJOb2RlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbm9kZXMuZmlsdGVyKG5vZGUgPT4gbm9kZSAhPT0gdGhpcy5fZmlyc3QgJiYgbm9kZSAhPT0gdGhpcy5fbGFzdCk7XG4gICAgfVxuXG4gICAgLyoqIEdldCB0aGUgbm9kZXMgYXMgYW4gYXJyYXkgKi9cbiAgICBwcml2YXRlIGdldCBfbm9kZXMoKTogSGllcmFyY2h5QmFyTm9kZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGllcmFyY2h5QmFyLm5vZGVzJC52YWx1ZTtcbiAgICB9XG5cbiAgICAvKiogVW5zdWJzY3JpYmUgZnJvbSBhbGwgb2JzZXJ2YWJsZXMgb24gZGVzdHJveSAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICAvKiogQWNjZXNzIHRoZSBub2RlIGNvbnRhaW5lciAqL1xuICAgIEBWaWV3Q2hpbGQoJ25vZGVzJywgeyBzdGF0aWM6IHRydWUgfSkgbm9kZUNvbnRhaW5lcjogRWxlbWVudFJlZjtcblxuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBVSSB3aGVuIHRoZSBzZWxlY3RlZCBub2RlcyBjaGFuZ2VcbiAgICAgICAgdGhpcy5oaWVyYXJjaHlCYXIubm9kZXMkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpLnN1YnNjcmliZSh0aGlzLnVwZGF0ZS5iaW5kKHRoaXMpKTtcblxuICAgICAgICAvLyB3YXRjaCBmb3IgdGhlIGhvc3QgZWxlbWVudCBzaXplIGNoYW5naW5nXG4gICAgICAgIHRoaXMuX3Jlc2l6ZVNlcnZpY2UuYWRkUmVzaXplTGlzdGVuZXIodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KS5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLnVwZGF0ZU92ZXJmbG93KCkpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kubmV4dCgpO1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcblxuICAgICAgICAvLyByZW1vdmUgdGhlIHJlc2l6ZSBldmVudCBsaXN0ZW5lclxuICAgICAgICB0aGlzLl9yZXNpemVTZXJ2aWNlLnJlbW92ZVJlc2l6ZUxpc3RlbmVyKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGUobm9kZXM6IEhpZXJhcmNoeUJhck5vZGVbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLl9maXJzdCA9IG5vZGVzWzBdO1xuICAgICAgICB0aGlzLl9sYXN0ID0gbm9kZXMubGVuZ3RoID4gMSA/IG5vZGVzW25vZGVzLmxlbmd0aCAtIDFdIDogbnVsbDtcbiAgICAgICAgdGhpcy51cGRhdGVPdmVyZmxvdygpO1xuXG4gICAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG5cbiAgICB1cGRhdGVPdmVyZmxvdygpOiB2b2lkIHtcblxuICAgICAgICAvLyByZW1vdmUgdGhlIGNsYXNzIGlmIGl0IGlzIHByZXNlbnRcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5ub2RlQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQsICdoaWVyYXJjaHktYmFyLW5vZGVzLW92ZXJmbG93Jyk7XG5cbiAgICAgICAgLy8gY2hlY2sgaWYgdGhlcmUgaXMgb3ZlcmZsb3dcbiAgICAgICAgaWYgKHRoaXMubm9kZUNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnNjcm9sbFdpZHRoID4gdGhpcy5ub2RlQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGgpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLmFkZENsYXNzKHRoaXMubm9kZUNvbnRhaW5lci5uYXRpdmVFbGVtZW50LCAnaGllcmFyY2h5LWJhci1ub2Rlcy1vdmVyZmxvdycpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiPCEtLSBBbGxvdyBjb250ZW50IHRvIGJlIHBsYWNlZCBvbiB0aGUgbGVmdCBvZiB0aGUgaXRlbXMgLS0+XG48ZGl2IGNsYXNzPVwiaGllcmFyY2h5LWJhci1hZGRvbnNcIj5cbiAgPG5nLWNvbnRlbnQgc2VsZWN0PVwibGVmdC1hZGRvbnNcIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cblxuPGRpdiAjbm9kZXMgY2xhc3M9XCJoaWVyYXJjaHktYmFyLW5vZGVzXCI+XG5cbiAgQGlmIChfZmlyc3QpIHtcbiAgICA8dXgtaGllcmFyY2h5LWJhci1ub2RlXG4gICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgW3BvcG92ZXJUZW1wbGF0ZV09XCJjb250ZW50XCJcbiAgICAgIFtub2RlXT1cIl9maXJzdFwiXG4gICAgICAoc2VsZWN0ZWQpPVwiaGllcmFyY2h5QmFyLnNlbGVjdE5vZGUoJGV2ZW50KVwiPlxuICAgIDwvdXgtaGllcmFyY2h5LWJhci1ub2RlPlxuICB9XG5cbiAgQGlmIChfcGFyZW50cy5sZW5ndGggPiAwKSB7XG4gICAgPGRpdiBjbGFzcz1cImhpZXJhcmNoeS1iYXItb3ZlcmZsb3dcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJoaWVyYXJjaHktYmFyLW92ZXJmbG93LWNvbnRhaW5lclwiPlxuICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImhpZXJhcmNoeUJhci5vdmVyZmxvd1RlbXBsYXRlIHx8IGRlZmF1bHRPdmVyZmxvd1RlbXBsYXRlXCJcbiAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IF9wYXJlbnRzIH1cIj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxidXR0b24gW2F0dHIuYXJpYS1sYWJlbF09XCJoaWVyYXJjaHlCYXIuc2hvd1NpYmxpbmdzQXJpYUxhYmVsXCJcbiAgICAgICAgdXhGb2N1c0luZGljYXRvclxuICAgICAgICB1eEZvY3VzSW5kaWNhdG9yT3JpZ2luXG4gICAgICAgIGNsYXNzPVwiaGllcmFyY2h5LWJhci1ub2RlLWFycm93XCJcbiAgICAgICAgcGxhY2VtZW50PVwiYm90dG9tXCJcbiAgICAgICAgW3V4UG9wb3Zlcl09XCJzaWJsaW5nc1RlbXBsYXRlXCJcbiAgICAgICAgcG9wb3ZlckNsYXNzPVwiaGllcmFyY2h5LWJhci1wb3BvdmVyXCJcbiAgICAgICAgcm9sZT1cImJ1dHRvblwiXG4gICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJyZWFkb25seVwiXG4gICAgICAgICNwb3BvdmVyPVwidXgtcG9wb3ZlclwiXG4gICAgICAgIFtwb3BvdmVyQ29udGV4dF09XCJ7IHBvcG92ZXI6IHBvcG92ZXIgfVwiXG4gICAgICAgIFtzaG93VHJpZ2dlcnNdPVwiaGllcmFyY2h5QmFyLnBvcG92ZXJTaG93VHJpZ2dlcnNcIlxuICAgICAgICBbaGlkZVRyaWdnZXJzXT1cImhpZXJhcmNoeUJhci5wb3BvdmVySGlkZVRyaWdnZXJzXCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiPlxuICAgICAgICA8dXgtaWNvbiBuYW1lPVwibmV4dFwiIGNsYXNzPVwiaGllcmFyY2h5LWJhci1ub2RlLWFycm93LWljb25cIj48L3V4LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgfVxuXG5cbiAgQGlmIChfbGFzdCkge1xuICAgIDx1eC1oaWVyYXJjaHktYmFyLW5vZGVcbiAgICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICBbcG9wb3ZlclRlbXBsYXRlXT1cImNvbnRlbnRcIlxuICAgICAgW25vZGVdPVwiX2xhc3RcIlxuICAgICAgKHNlbGVjdGVkKT1cImhpZXJhcmNoeUJhci5zZWxlY3ROb2RlKCRldmVudClcIj5cbiAgICA8L3V4LWhpZXJhcmNoeS1iYXItbm9kZT5cbiAgfVxuXG4gIDwhLS0gQWxsb3cgY29udGVudCB0byBiZSBwbGFjZWQgYWZ0ZXIgdGhlIGxhc3Qgbm9kZSAtLT5cbiAgPGRpdiBjbGFzcz1cImhpZXJhcmNoeS1iYXItYWRkb25zXCI+XG4gICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwidHJhaWxpbmctYWRkb25zXCI+PC9uZy1jb250ZW50PlxuICA8L2Rpdj5cblxuPC9kaXY+XG5cbjwhLS0gQWxsb3cgY29udGVudCB0byBiZSBwbGFjZWQgb24gdGhlIHJpZ2h0IG9mIHRoZSBpdGVtcyAtLT5cbjxkaXYgY2xhc3M9XCJoaWVyYXJjaHktYmFyLWFkZG9uc1wiPlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJyaWdodC1hZGRvbnNcIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cblxuPCEtLSBUZW1wbGF0ZSBmb3IgdGhlIHBvcG92ZXIgbGlzdCAtLT5cbjxuZy10ZW1wbGF0ZSAjY29udGVudCBsZXQtbm9kZT1cIm5vZGVcIiBsZXQtcG9wb3Zlcj1cInBvcG92ZXJcIj5cbiAgPHV4LWhpZXJhcmNoeS1iYXItcG9wb3ZlclxuICAgIFtsb2FkaW5nXT1cIihoaWVyYXJjaHlCYXIuZ2V0Q2hpbGRyZW4obm9kZSkgfCBhc3luYyk/LmxvYWRpbmdcIlxuICAgIFtub2Rlc109XCIoaGllcmFyY2h5QmFyLmdldENoaWxkcmVuKG5vZGUpIHwgYXN5bmMpPy5jaGlsZHJlblwiXG4gICAgKHNlbGVjdGVkKT1cImhpZXJhcmNoeUJhci5zZWxlY3ROb2RlKCRldmVudCk7IHBvcG92ZXIuaGlkZSgpXCI+XG4gIDwvdXgtaGllcmFyY2h5LWJhci1wb3BvdmVyPlxuPC9uZy10ZW1wbGF0ZT5cblxuPCEtLSBUZW1wbGF0ZSBmb3IgdGhlIHNpYmxpbmdzIHBvcG92ZXIgbGlzdCAtLT5cbjxuZy10ZW1wbGF0ZSAjc2libGluZ3NUZW1wbGF0ZSBsZXQtcG9wb3Zlcj1cInBvcG92ZXJcIj5cbiAgPHV4LWhpZXJhcmNoeS1iYXItcG9wb3ZlclxuICAgIFtub2Rlc109XCIoX3NpYmxpbmdzIHwgYXN5bmMpPy5jaGlsZHJlblwiXG4gICAgW2xvYWRpbmddPVwiKF9zaWJsaW5ncyB8IGFzeW5jKT8ubG9hZGluZ1wiXG4gICAgKHNlbGVjdGVkKT1cImhpZXJhcmNoeUJhci5zZWxlY3ROb2RlKCRldmVudCk7IHBvcG92ZXIuaGlkZSgpXCI+XG4gIDwvdXgtaGllcmFyY2h5LWJhci1wb3BvdmVyPlxuPC9uZy10ZW1wbGF0ZT5cblxuPCEtLSBUZW1wbGF0ZSBmb3IgdGhlIHBhcmVudHMgcG9wb3ZlciBsaXN0IC0tPlxuPG5nLXRlbXBsYXRlICNwYXJlbnRzVGVtcGxhdGUgbGV0LXBvcG92ZXI9XCJwb3BvdmVyXCI+XG4gIDx1eC1oaWVyYXJjaHktYmFyLXBvcG92ZXJcbiAgICBbbm9kZXNdPVwiX3BhcmVudHNcIlxuICAgIFtzZXBhcmF0b3JdPVwidHJ1ZVwiXG4gICAgKHNlbGVjdGVkKT1cImhpZXJhcmNoeUJhci5zZWxlY3ROb2RlKCRldmVudCk7IHBvcG92ZXIuaGlkZSgpXCI+XG4gIDwvdXgtaGllcmFyY2h5LWJhci1wb3BvdmVyPlxuPC9uZy10ZW1wbGF0ZT5cblxuPCEtLSBEZWZhdWx0IE92ZXJmbG93IFRlbXBsYXRlIC0tPlxuPG5nLXRlbXBsYXRlICNkZWZhdWx0T3ZlcmZsb3dUZW1wbGF0ZT5cbiAgPGJ1dHRvbiB1eEZvY3VzSW5kaWNhdG9yXG4gICAgdXhGb2N1c0luZGljYXRvck9yaWdpblxuICAgIFtkaXNhYmxlZF09XCJyZWFkb25seVwiXG4gICAgY2xhc3M9XCJvdmVyZmxvdy1idXR0b25cIlxuICAgIGFyaWEtbGFiZWw9XCJTaG93IHBhcmVudHNcIlxuICAgIFt1eFBvcG92ZXJdPVwicGFyZW50c1RlbXBsYXRlXCJcbiAgICBwb3BvdmVyQ2xhc3M9XCJoaWVyYXJjaHktYmFyLXBvcG92ZXJcIlxuICAgIHJvbGU9XCJidXR0b25cIlxuICAgIHRhYmluZGV4PVwiMFwiXG4gICAgI3BvcG92ZXI9XCJ1eC1wb3BvdmVyXCJcbiAgICBbcG9wb3ZlckNvbnRleHRdPVwieyBwb3BvdmVyOiBwb3BvdmVyIH1cIlxuICAgIFtzaG93VHJpZ2dlcnNdPVwiaGllcmFyY2h5QmFyLnBvcG92ZXJTaG93VHJpZ2dlcnNcIlxuICAgIFtoaWRlVHJpZ2dlcnNdPVwiaGllcmFyY2h5QmFyLnBvcG92ZXJIaWRlVHJpZ2dlcnNcIlxuICAgIHBsYWNlbWVudD1cImJvdHRvbVwiXG4gICAgdHlwZT1cImJ1dHRvblwiPlxuICAgIDx1eC1pY29uIG5hbWU9XCJtb3JlXCI+PC91eC1pY29uPlxuICA8L2J1dHRvbj5cbjwvbmctdGVtcGxhdGU+XG4iXX0=