UNPKG

@alfresco/adf-content-services

Version:
167 lines 36.2 kB
/*! * @license * Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Component, DestroyRef, EventEmitter, inject, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { MatSelect, MatSelectModule } from '@angular/material/select'; import { Node } from '@alfresco/js-api'; import { DocumentListComponent } from '../document-list/components/document-list.component'; import { CommonModule } from '@angular/common'; import { MatIconModule } from '@angular/material/icon'; import { TranslateModule } from '@ngx-translate/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/material/icon"; import * as i3 from "@ngx-translate/core"; import * as i4 from "@angular/material/select"; import * as i5 from "@angular/material/core"; export class BreadcrumbComponent { constructor() { /** Active node, builds UI based on folderNode.path.elements collection. */ this.folderNode = null; /** * Name of the root element of the breadcrumb. You can use * this property to rename "Company Home" to "Personal Files" for * example. You can use an i18n resource key for the property value. */ this.root = null; /** * The id of the root element. You can use this property * to set a custom element the breadcrumb should start with. */ this.rootId = null; /** Number of table rows that are currently selected. */ this.selectedRowItemsCount = 0; this.route = []; this.destroyRef = inject(DestroyRef); /** If true, prevents the user from navigating away from the active node. */ this.readOnly = false; /** Emitted when the user clicks on a breadcrumb. */ this.navigate = new EventEmitter(); } get hasRoot() { return !!this.root; } ngOnInit() { this.transform = this.transform ? this.transform : null; if (this.target) { this.target.$folderNode.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((folderNode) => { this.folderNode = folderNode; this.recalculateNodes(); }); } } ngOnChanges() { this.recalculateNodes(); } recalculateNodes() { const node = this.transform ? this.transform(this.folderNode) : this.folderNode; this.route = this.parseRoute(node); if (this.maxItems && this.route.length > this.maxItems) { this.lastNodes = this.route.slice(this.route.length - this.maxItems); this.previousNodes = this.route.slice(0, this.route.length - this.maxItems); this.previousNodes.reverse(); } else { this.lastNodes = this.route; this.previousNodes = null; } } open() { if (this.dropdown) { this.dropdown.open(); this.dropdown.focus(); } } hasPreviousNodes() { return !!this.previousNodes; } parseRoute(node) { if (node?.path) { const route = (node.path.elements || []).slice(); route.push({ id: node.id, name: node.name, node }); const rootPos = this.getElementPosition(route, this.rootId); if (rootPos > 0) { route.splice(0, rootPos); } if (rootPos === -1 && this.rootId) { route[0].id = this.rootId; } if (this.root) { route[0].name = this.root; } return route; } return []; } getElementPosition(route, nodeId) { let position = -1; if (route && route.length > 0 && nodeId) { position = route.findIndex((el) => el.id === nodeId); } return position; } breadcrumbItemIsAnchor(lastItem) { return !this.readOnly && !lastItem; } onRoutePathClick(route, event) { if (event && event.type === 'click') { event.preventDefault(); } this.onRouteClick(route); } onRouteClick(route) { if (route && !this.readOnly) { this.navigate.emit(route); if (this.target) { this.target.navigateTo(route.id); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: BreadcrumbComponent, isStandalone: true, selector: "adf-breadcrumb", inputs: { folderNode: "folderNode", root: "root", rootId: "rootId", target: "target", transform: "transform", maxItems: "maxItems", selectedRowItemsCount: "selectedRowItemsCount", readOnly: "readOnly" }, outputs: { navigate: "navigate" }, host: { classAttribute: "adf-breadcrumb" }, viewQueries: [{ propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<nav\n *ngIf=\"folderNode\"\n data-automation-id=\"breadcrumb\"\n class=\"adf-breadcrumb-container\"\n role=\"navigation\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate\"\n>\n <button\n *ngIf=\"hasPreviousNodes()\"\n tabindex=\"0\"\n class=\"adf-breadcrumb-dropdown-trigger\"\n (click)=\"open()\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate\"\n >\n <div class=\"adf-breadcrumb-dropdown-trigger-icon\">\n <mat-icon [class.adf-isRoot]=\"!hasPreviousNodes()\">folder</mat-icon>\n <mat-icon\n [class.adf-isRoot]=\"!hasPreviousNodes()\"\n class=\"adf-breadcrumb-dropdown-trigger-arrow\"\n >arrow_drop_down</mat-icon\n >\n </div>\n </button>\n\n <mat-select\n #dropdown\n *ngIf=\"hasPreviousNodes()\"\n class=\"adf-breadcrumb-dropdown-path\"\n tabindex=\"-1\"\n role=\"button\"\n >\n <mat-option\n *ngFor=\"let node of previousNodes\"\n (click)=\"onRoutePathClick(node, $event)\"\n (onSelectionChange)=\"onRouteClick(node)\"\n class=\"adf-breadcrumb-path-option\"\n [disabled]=\"readOnly\"\n >\n {{ node.name | translate }}\n </mat-option>\n </mat-select>\n\n <div\n *ngFor=\"let item of lastNodes; let last = last\"\n [class.adf-active]=\"last\"\n [ngSwitch]=\"breadcrumbItemIsAnchor(last)\"\n title=\"{{ item.name | translate }}\"\n class=\"adf-breadcrumb-item\">\n <a\n *ngSwitchCase=\"true\"\n href=\"#\"\n [attr.data-automation-id]=\"'breadcrumb_' + item.name\"\n class=\"adf-breadcrumb-item-anchor\"\n (click)=\"onRoutePathClick(item, $event)\"\n >\n {{ item.name | translate }}\n </a>\n\n <div *ngSwitchDefault class=\"adf-breadcrumb-item-current\" aria-current=\"location\">\n {{ (selectedRowItemsCount < 1 ? item.name : 'BREADCRUMB.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}\n </div>\n\n <mat-icon class=\"adf-breadcrumb-item-chevron\" *ngIf=\"!last\">\n chevron_right\n </mat-icon>\n </div>\n</nav>\n\n<nav\n *ngIf=\"!folderNode && hasRoot\"\n data-automation-id=\"breadcrumb\"\n role=\"navigation\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate\"\n>\n <div class=\"adf-breadcrumb-item adf-active\" role=\"group\">\n <div class=\"adf-breadcrumb-item-current\">\n {{ root | translate }}\n </div>\n </div>\n</nav>\n", styles: [".adf-breadcrumb{display:flex;flex:1;line-height:24px;font-size:var(--theme-body-1-font-size);font-weight:600;letter-spacing:-.2px;color:var(--adf-theme-foreground-text-color-054);overflow:hidden}.adf-breadcrumb-container{margin:0;padding:0;list-style-type:none;cursor:default;display:flex;overflow:hidden}.adf-breadcrumb-dropdown-path{width:0;height:0;overflow:hidden;margin-top:35px}.adf-breadcrumb-dropdown-trigger{cursor:pointer;padding:0;border:none;background:transparent;width:30px;margin-top:2px;margin-right:5px}.adf-breadcrumb-dropdown-trigger:focus{color:var(--theme-primary-color);outline:none}.adf-breadcrumb-dropdown-trigger-icon{position:relative}.adf-breadcrumb-dropdown-trigger-arrow{font-size:var(--theme-adf-icon-1-font-size);position:absolute;left:4px;top:4px;color:#fff;z-index:2}.adf-breadcrumb-dropdown-trigger-arrow.adf-isRoot{visibility:hidden}.adf-breadcrumb-dropdown-trigger-arrow.adf-focus{border:none}.adf-breadcrumb-dropdown-trigger.adf-isRoot{cursor:not-allowed}.adf-breadcrumb-item{padding-right:2px;overflow:hidden;display:flex;line-height:33px;font-size:var(--theme-body-1-font-size);font-weight:600;letter-spacing:-.2px;text-align:left;color:var(--adf-theme-foreground-text-color-054);flex:0 1 auto;min-width:35px;margin-top:auto;text-overflow:ellipsis}.adf-breadcrumb-item:hover,.adf-breadcrumb-item.adf-active{color:var(--adf-theme-foreground-text-color-064)}.adf-breadcrumb-item.adf-active{color:var(--adf-theme-foreground-text-color-087)}.adf-breadcrumb-item-chevron{opacity:1;margin-top:9px;font-size:var(--theme-adf-icon-1-font-size)}.adf-breadcrumb-item-anchor{box-sizing:border-box;color:inherit;text-decoration:none;display:inline-block;width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:0 1 auto;padding:0;text-align:start}.adf-breadcrumb-item-anchor:focus{outline:1px solid var(--theme-accent-color-a200);outline-offset:-1px}.adf-breadcrumb-item-current{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: BreadcrumbComponent, decorators: [{ type: Component, args: [{ selector: 'adf-breadcrumb', standalone: true, imports: [CommonModule, MatIconModule, TranslateModule, MatSelectModule], encapsulation: ViewEncapsulation.None, host: { class: 'adf-breadcrumb' }, template: "<nav\n *ngIf=\"folderNode\"\n data-automation-id=\"breadcrumb\"\n class=\"adf-breadcrumb-container\"\n role=\"navigation\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate\"\n>\n <button\n *ngIf=\"hasPreviousNodes()\"\n tabindex=\"0\"\n class=\"adf-breadcrumb-dropdown-trigger\"\n (click)=\"open()\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate\"\n >\n <div class=\"adf-breadcrumb-dropdown-trigger-icon\">\n <mat-icon [class.adf-isRoot]=\"!hasPreviousNodes()\">folder</mat-icon>\n <mat-icon\n [class.adf-isRoot]=\"!hasPreviousNodes()\"\n class=\"adf-breadcrumb-dropdown-trigger-arrow\"\n >arrow_drop_down</mat-icon\n >\n </div>\n </button>\n\n <mat-select\n #dropdown\n *ngIf=\"hasPreviousNodes()\"\n class=\"adf-breadcrumb-dropdown-path\"\n tabindex=\"-1\"\n role=\"button\"\n >\n <mat-option\n *ngFor=\"let node of previousNodes\"\n (click)=\"onRoutePathClick(node, $event)\"\n (onSelectionChange)=\"onRouteClick(node)\"\n class=\"adf-breadcrumb-path-option\"\n [disabled]=\"readOnly\"\n >\n {{ node.name | translate }}\n </mat-option>\n </mat-select>\n\n <div\n *ngFor=\"let item of lastNodes; let last = last\"\n [class.adf-active]=\"last\"\n [ngSwitch]=\"breadcrumbItemIsAnchor(last)\"\n title=\"{{ item.name | translate }}\"\n class=\"adf-breadcrumb-item\">\n <a\n *ngSwitchCase=\"true\"\n href=\"#\"\n [attr.data-automation-id]=\"'breadcrumb_' + item.name\"\n class=\"adf-breadcrumb-item-anchor\"\n (click)=\"onRoutePathClick(item, $event)\"\n >\n {{ item.name | translate }}\n </a>\n\n <div *ngSwitchDefault class=\"adf-breadcrumb-item-current\" aria-current=\"location\">\n {{ (selectedRowItemsCount < 1 ? item.name : 'BREADCRUMB.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}\n </div>\n\n <mat-icon class=\"adf-breadcrumb-item-chevron\" *ngIf=\"!last\">\n chevron_right\n </mat-icon>\n </div>\n</nav>\n\n<nav\n *ngIf=\"!folderNode && hasRoot\"\n data-automation-id=\"breadcrumb\"\n role=\"navigation\"\n [attr.aria-label]=\"'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate\"\n>\n <div class=\"adf-breadcrumb-item adf-active\" role=\"group\">\n <div class=\"adf-breadcrumb-item-current\">\n {{ root | translate }}\n </div>\n </div>\n</nav>\n", styles: [".adf-breadcrumb{display:flex;flex:1;line-height:24px;font-size:var(--theme-body-1-font-size);font-weight:600;letter-spacing:-.2px;color:var(--adf-theme-foreground-text-color-054);overflow:hidden}.adf-breadcrumb-container{margin:0;padding:0;list-style-type:none;cursor:default;display:flex;overflow:hidden}.adf-breadcrumb-dropdown-path{width:0;height:0;overflow:hidden;margin-top:35px}.adf-breadcrumb-dropdown-trigger{cursor:pointer;padding:0;border:none;background:transparent;width:30px;margin-top:2px;margin-right:5px}.adf-breadcrumb-dropdown-trigger:focus{color:var(--theme-primary-color);outline:none}.adf-breadcrumb-dropdown-trigger-icon{position:relative}.adf-breadcrumb-dropdown-trigger-arrow{font-size:var(--theme-adf-icon-1-font-size);position:absolute;left:4px;top:4px;color:#fff;z-index:2}.adf-breadcrumb-dropdown-trigger-arrow.adf-isRoot{visibility:hidden}.adf-breadcrumb-dropdown-trigger-arrow.adf-focus{border:none}.adf-breadcrumb-dropdown-trigger.adf-isRoot{cursor:not-allowed}.adf-breadcrumb-item{padding-right:2px;overflow:hidden;display:flex;line-height:33px;font-size:var(--theme-body-1-font-size);font-weight:600;letter-spacing:-.2px;text-align:left;color:var(--adf-theme-foreground-text-color-054);flex:0 1 auto;min-width:35px;margin-top:auto;text-overflow:ellipsis}.adf-breadcrumb-item:hover,.adf-breadcrumb-item.adf-active{color:var(--adf-theme-foreground-text-color-064)}.adf-breadcrumb-item.adf-active{color:var(--adf-theme-foreground-text-color-087)}.adf-breadcrumb-item-chevron{opacity:1;margin-top:9px;font-size:var(--theme-adf-icon-1-font-size)}.adf-breadcrumb-item-anchor{box-sizing:border-box;color:inherit;text-decoration:none;display:inline-block;width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:0 1 auto;padding:0;text-align:start}.adf-breadcrumb-item-anchor:focus{outline:1px solid var(--theme-accent-color-a200);outline-offset:-1px}.adf-breadcrumb-item-current{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}\n"] }] }], propDecorators: { folderNode: [{ type: Input, args: [{ required: true }] }], root: [{ type: Input }], rootId: [{ type: Input }], target: [{ type: Input }], transform: [{ type: Input }], dropdown: [{ type: ViewChild, args: ['dropdown'] }], maxItems: [{ type: Input }], selectedRowItemsCount: [{ type: Input }], readOnly: [{ type: Input }], navigate: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJlYWRjcnVtYi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL2JyZWFkY3J1bWIvYnJlYWRjcnVtYi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL2JyZWFkY3J1bWIvYnJlYWRjcnVtYi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM1SSxPQUFPLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxJQUFJLEVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxREFBcUQsQ0FBQztBQUM1RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7Ozs7OztBQVdoRSxNQUFNLE9BQU8sbUJBQW1CO0lBVGhDO1FBVUksMkVBQTJFO1FBRTNFLGVBQVUsR0FBUyxJQUFJLENBQUM7UUFFeEI7Ozs7V0FJRztRQUVILFNBQUksR0FBWSxJQUFJLENBQUM7UUFFckI7OztXQUdHO1FBRUgsV0FBTSxHQUFZLElBQUksQ0FBQztRQXlCdkIseURBQXlEO1FBRXpELDBCQUFxQixHQUFHLENBQUMsQ0FBQztRQUsxQixVQUFLLEdBQWtCLEVBQUUsQ0FBQztRQUVULGVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFNakQsNEVBQTRFO1FBRTVFLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFFMUIsb0RBQW9EO1FBRXBELGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO0tBdUc5QztJQWpIRyxJQUFJLE9BQU87UUFDUCxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7SUFVRCxRQUFRO1FBQ0osSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFFeEQsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsVUFBZ0IsRUFBRSxFQUFFO2dCQUM3RixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDNUIsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDUCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRVMsZ0JBQWdCO1FBQ3RCLE1BQU0sSUFBSSxHQUFTLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBRXRGLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVuQyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JFLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1RSxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pDLENBQUM7YUFBTSxDQUFDO1lBQ0osSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQzVCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBQzlCLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSTtRQUNBLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMxQixDQUFDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQjtRQUNaLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDaEMsQ0FBQztJQUVELFVBQVUsQ0FBQyxJQUFVO1FBQ2pCLElBQUksSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO1lBQ2IsTUFBTSxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUVqRCxLQUFLLENBQUMsSUFBSSxDQUFDO2dCQUNQLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDWCxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7Z0JBQ2YsSUFBSTthQUNRLENBQUMsQ0FBQztZQUVsQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM1RCxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDZCxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3QixDQUFDO1lBRUQsSUFBSSxPQUFPLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNoQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDOUIsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNaLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM5QixDQUFDO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDakIsQ0FBQztRQUVELE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVPLGtCQUFrQixDQUFDLEtBQW9CLEVBQUUsTUFBYztRQUMzRCxJQUFJLFFBQVEsR0FBVyxDQUFDLENBQUMsQ0FBQztRQUUxQixJQUFJLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUN0QyxRQUFRLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxNQUFNLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBRUQsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUVELHNCQUFzQixDQUFDLFFBQVE7UUFDM0IsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkMsQ0FBQztJQUVELGdCQUFnQixDQUFDLEtBQWtCLEVBQUUsS0FBYTtRQUM5QyxJQUFJLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ2xDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUMzQixDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQsWUFBWSxDQUFDLEtBQWtCO1FBQzNCLElBQUksS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRTFCLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNyQyxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7OEdBdEtRLG1CQUFtQjtrR0FBbkIsbUJBQW1CLGdlQ25DaEMsMnBGQWdGQSx1L0REbkRjLFlBQVksMmdCQUFFLGFBQWEsbUxBQUUsZUFBZSwyRkFBRSxlQUFlOzsyRkFNOUQsbUJBQW1CO2tCQVQvQixTQUFTOytCQUNJLGdCQUFnQixjQUNkLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLGVBQWUsQ0FBQyxpQkFHekQsaUJBQWlCLENBQUMsSUFBSSxRQUMvQixFQUFFLEtBQUssRUFBRSxnQkFBZ0IsRUFBRTs4QkFLakMsVUFBVTtzQkFEVCxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFTekIsSUFBSTtzQkFESCxLQUFLO2dCQVFOLE1BQU07c0JBREwsS0FBSztnQkFRTixNQUFNO3NCQURMLEtBQUs7Z0JBVU4sU0FBUztzQkFEUixLQUFLO2dCQUlOLFFBQVE7c0JBRFAsU0FBUzt1QkFBQyxVQUFVO2dCQUtyQixRQUFRO3NCQURQLEtBQUs7Z0JBS04scUJBQXFCO3NCQURwQixLQUFLO2dCQWdCTixRQUFRO3NCQURQLEtBQUs7Z0JBS04sUUFBUTtzQkFEUCxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IMKpIDIwMDUtMjAyNSBIeWxhbmQgU29mdHdhcmUsIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnQsIERlc3Ryb3lSZWYsIEV2ZW50RW1pdHRlciwgaW5qZWN0LCBJbnB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIE91dHB1dCwgVmlld0NoaWxkLCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWF0U2VsZWN0LCBNYXRTZWxlY3RNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xuaW1wb3J0IHsgTm9kZSwgUGF0aEVsZW1lbnQgfSBmcm9tICdAYWxmcmVzY28vanMtYXBpJztcbmltcG9ydCB7IERvY3VtZW50TGlzdENvbXBvbmVudCB9IGZyb20gJy4uL2RvY3VtZW50LWxpc3QvY29tcG9uZW50cy9kb2N1bWVudC1saXN0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nO1xuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnYWRmLWJyZWFkY3J1bWInLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgTWF0SWNvbk1vZHVsZSwgVHJhbnNsYXRlTW9kdWxlLCBNYXRTZWxlY3RNb2R1bGVdLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9icmVhZGNydW1iLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9icmVhZGNydW1iLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBob3N0OiB7IGNsYXNzOiAnYWRmLWJyZWFkY3J1bWInIH1cbn0pXG5leHBvcnQgY2xhc3MgQnJlYWRjcnVtYkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgICAvKiogQWN0aXZlIG5vZGUsIGJ1aWxkcyBVSSBiYXNlZCBvbiBmb2xkZXJOb2RlLnBhdGguZWxlbWVudHMgY29sbGVjdGlvbi4gKi9cbiAgICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxuICAgIGZvbGRlck5vZGU6IE5vZGUgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgcm9vdCBlbGVtZW50IG9mIHRoZSBicmVhZGNydW1iLiBZb3UgY2FuIHVzZVxuICAgICAqIHRoaXMgcHJvcGVydHkgdG8gcmVuYW1lIFwiQ29tcGFueSBIb21lXCIgdG8gXCJQZXJzb25hbCBGaWxlc1wiIGZvclxuICAgICAqIGV4YW1wbGUuIFlvdSBjYW4gdXNlIGFuIGkxOG4gcmVzb3VyY2Uga2V5IGZvciB0aGUgcHJvcGVydHkgdmFsdWUuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICByb290Pzogc3RyaW5nID0gbnVsbDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBpZCBvZiB0aGUgcm9vdCBlbGVtZW50LiBZb3UgY2FuIHVzZSB0aGlzIHByb3BlcnR5XG4gICAgICogdG8gc2V0IGEgY3VzdG9tIGVsZW1lbnQgdGhlIGJyZWFkY3J1bWIgc2hvdWxkIHN0YXJ0IHdpdGguXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICByb290SWQ/OiBzdHJpbmcgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogRG9jdW1lbnQgTGlzdCBjb21wb25lbnQgdG8gb3BlcmF0ZSB3aXRoLiBUaGUgbGlzdCB3aWxsXG4gICAgICogdXBkYXRlIHdoZW4gdGhlIGJyZWFkY3J1bWIgaXMgY2xpY2tlZC5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHRhcmdldD86IERvY3VtZW50TGlzdENvbXBvbmVudDtcblxuICAgIC8qKlxuICAgICAqIFRyYW5zZm9ybWF0aW9uIHRvIGJlIHBlcmZvcm1lZCBvbiB0aGUgY2hvc2VuL2ZvbGRlciBub2RlIGJlZm9yZSBidWlsZGluZ1xuICAgICAqIHRoZSBicmVhZGNydW1iIFVJLiBDYW4gYmUgdXNlZnVsIHdoZW4gY3VzdG9tIGZvcm1hdHRpbmcgaXMgbmVlZGVkIGZvciB0aGVcbiAgICAgKiBicmVhZGNydW1iLiBZb3UgY2FuIGNoYW5nZSB0aGUgcGF0aCBlbGVtZW50cyBmcm9tIHRoZSBub2RlIHRoYXQgYXJlIHVzZWQgdG9cbiAgICAgKiBidWlsZCB0aGUgYnJlYWRjcnVtYiB1c2luZyB0aGlzIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgdHJhbnNmb3JtOiAobm9kZSkgPT4gYW55O1xuXG4gICAgQFZpZXdDaGlsZCgnZHJvcGRvd24nKVxuICAgIGRyb3Bkb3duOiBNYXRTZWxlY3Q7XG5cbiAgICAvKiogTWF4aW11bSBudW1iZXIgb2Ygbm9kZXMgdG8gZGlzcGxheSBiZWZvcmUgd3JhcHBpbmcgdGhlbSB3aXRoIGEgZHJvcGRvd24gZWxlbWVudC4gICovXG4gICAgQElucHV0KClcbiAgICBtYXhJdGVtczogbnVtYmVyO1xuXG4gICAgLyoqIE51bWJlciBvZiB0YWJsZSByb3dzIHRoYXQgYXJlIGN1cnJlbnRseSBzZWxlY3RlZC4gICovXG4gICAgQElucHV0KClcbiAgICBzZWxlY3RlZFJvd0l0ZW1zQ291bnQgPSAwO1xuXG4gICAgcHJldmlvdXNOb2RlczogUGF0aEVsZW1lbnRbXTtcbiAgICBsYXN0Tm9kZXM6IFBhdGhFbGVtZW50W107XG5cbiAgICByb3V0ZTogUGF0aEVsZW1lbnRbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gICAgZ2V0IGhhc1Jvb3QoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMucm9vdDtcbiAgICB9XG5cbiAgICAvKiogSWYgdHJ1ZSwgcHJldmVudHMgdGhlIHVzZXIgZnJvbSBuYXZpZ2F0aW5nIGF3YXkgZnJvbSB0aGUgYWN0aXZlIG5vZGUuICovXG4gICAgQElucHV0KClcbiAgICByZWFkT25seTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIEVtaXR0ZWQgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYSBicmVhZGNydW1iLiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIG5hdmlnYXRlID0gbmV3IEV2ZW50RW1pdHRlcjxQYXRoRWxlbWVudD4oKTtcblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLnRyYW5zZm9ybSA9IHRoaXMudHJhbnNmb3JtID8gdGhpcy50cmFuc2Zvcm0gOiBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLnRhcmdldCkge1xuICAgICAgICAgICAgdGhpcy50YXJnZXQuJGZvbGRlck5vZGUucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSkuc3Vic2NyaWJlKChmb2xkZXJOb2RlOiBOb2RlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5mb2xkZXJOb2RlID0gZm9sZGVyTm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlY2FsY3VsYXRlTm9kZXMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVjYWxjdWxhdGVOb2RlcygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCByZWNhbGN1bGF0ZU5vZGVzKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBub2RlOiBOb2RlID0gdGhpcy50cmFuc2Zvcm0gPyB0aGlzLnRyYW5zZm9ybSh0aGlzLmZvbGRlck5vZGUpIDogdGhpcy5mb2xkZXJOb2RlO1xuXG4gICAgICAgIHRoaXMucm91dGUgPSB0aGlzLnBhcnNlUm91dGUobm9kZSk7XG5cbiAgICAgICAgaWYgKHRoaXMubWF4SXRlbXMgJiYgdGhpcy5yb3V0ZS5sZW5ndGggPiB0aGlzLm1heEl0ZW1zKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3ROb2RlcyA9IHRoaXMucm91dGUuc2xpY2UodGhpcy5yb3V0ZS5sZW5ndGggLSB0aGlzLm1heEl0ZW1zKTtcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNOb2RlcyA9IHRoaXMucm91dGUuc2xpY2UoMCwgdGhpcy5yb3V0ZS5sZW5ndGggLSB0aGlzLm1heEl0ZW1zKTtcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNOb2Rlcy5yZXZlcnNlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxhc3ROb2RlcyA9IHRoaXMucm91dGU7XG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzTm9kZXMgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb3BlbigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZHJvcGRvd24pIHtcbiAgICAgICAgICAgIHRoaXMuZHJvcGRvd24ub3BlbigpO1xuICAgICAgICAgICAgdGhpcy5kcm9wZG93bi5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaGFzUHJldmlvdXNOb2RlcygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5wcmV2aW91c05vZGVzO1xuICAgIH1cblxuICAgIHBhcnNlUm91dGUobm9kZTogTm9kZSk6IFBhdGhFbGVtZW50W10ge1xuICAgICAgICBpZiAobm9kZT8ucGF0aCkge1xuICAgICAgICAgICAgY29uc3Qgcm91dGUgPSAobm9kZS5wYXRoLmVsZW1lbnRzIHx8IFtdKS5zbGljZSgpO1xuXG4gICAgICAgICAgICByb3V0ZS5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogbm9kZS5pZCxcbiAgICAgICAgICAgICAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgICAgICAgICAgICAgbm9kZVxuICAgICAgICAgICAgfSBhcyBQYXRoRWxlbWVudCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJvb3RQb3MgPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbihyb3V0ZSwgdGhpcy5yb290SWQpO1xuICAgICAgICAgICAgaWYgKHJvb3RQb3MgPiAwKSB7XG4gICAgICAgICAgICAgICAgcm91dGUuc3BsaWNlKDAsIHJvb3RQb3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocm9vdFBvcyA9PT0gLTEgJiYgdGhpcy5yb290SWQpIHtcbiAgICAgICAgICAgICAgICByb3V0ZVswXS5pZCA9IHRoaXMucm9vdElkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5yb290KSB7XG4gICAgICAgICAgICAgICAgcm91dGVbMF0ubmFtZSA9IHRoaXMucm9vdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJvdXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0RWxlbWVudFBvc2l0aW9uKHJvdXRlOiBQYXRoRWxlbWVudFtdLCBub2RlSWQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgICAgIGxldCBwb3NpdGlvbjogbnVtYmVyID0gLTE7XG5cbiAgICAgICAgaWYgKHJvdXRlICYmIHJvdXRlLmxlbmd0aCA+IDAgJiYgbm9kZUlkKSB7XG4gICAgICAgICAgICBwb3NpdGlvbiA9IHJvdXRlLmZpbmRJbmRleCgoZWwpID0+IGVsLmlkID09PSBub2RlSWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xuICAgIH1cblxuICAgIGJyZWFkY3J1bWJJdGVtSXNBbmNob3IobGFzdEl0ZW0pOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLnJlYWRPbmx5ICYmICFsYXN0SXRlbTtcbiAgICB9XG5cbiAgICBvblJvdXRlUGF0aENsaWNrKHJvdXRlOiBQYXRoRWxlbWVudCwgZXZlbnQ/OiBFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQgJiYgZXZlbnQudHlwZSA9PT0gJ2NsaWNrJykge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub25Sb3V0ZUNsaWNrKHJvdXRlKTtcbiAgICB9XG5cbiAgICBvblJvdXRlQ2xpY2socm91dGU6IFBhdGhFbGVtZW50KSB7XG4gICAgICAgIGlmIChyb3V0ZSAmJiAhdGhpcy5yZWFkT25seSkge1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZS5lbWl0KHJvdXRlKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXQubmF2aWdhdGVUbyhyb3V0ZS5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCI8bmF2XG4gICAgKm5nSWY9XCJmb2xkZXJOb2RlXCJcbiAgICBkYXRhLWF1dG9tYXRpb24taWQ9XCJicmVhZGNydW1iXCJcbiAgICBjbGFzcz1cImFkZi1icmVhZGNydW1iLWNvbnRhaW5lclwiXG4gICAgcm9sZT1cIm5hdmlnYXRpb25cIlxuICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ0JSRUFEQ1JVTUIuQVJJQS1MQUJFTC5CUkVBRENSVU1CJyB8IHRyYW5zbGF0ZVwiXG4+XG4gICAgPGJ1dHRvblxuICAgICAgICAqbmdJZj1cImhhc1ByZXZpb3VzTm9kZXMoKVwiXG4gICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgIGNsYXNzPVwiYWRmLWJyZWFkY3J1bWItZHJvcGRvd24tdHJpZ2dlclwiXG4gICAgICAgIChjbGljayk9XCJvcGVuKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidCUkVBRENSVU1CLkFSSUEtTEFCRUwuRFJPUERPV04nIHwgdHJhbnNsYXRlXCJcbiAgICA+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhZGYtYnJlYWRjcnVtYi1kcm9wZG93bi10cmlnZ2VyLWljb25cIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbiBbY2xhc3MuYWRmLWlzUm9vdF09XCIhaGFzUHJldmlvdXNOb2RlcygpXCI+Zm9sZGVyPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDxtYXQtaWNvblxuICAgICAgICAgICAgICAgIFtjbGFzcy5hZGYtaXNSb290XT1cIiFoYXNQcmV2aW91c05vZGVzKClcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiYWRmLWJyZWFkY3J1bWItZHJvcGRvd24tdHJpZ2dlci1hcnJvd1wiXG4gICAgICAgICAgICAgICAgPmFycm93X2Ryb3BfZG93bjwvbWF0LWljb25cbiAgICAgICAgICAgID5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9idXR0b24+XG5cbiAgICA8bWF0LXNlbGVjdFxuICAgICAgICAjZHJvcGRvd25cbiAgICAgICAgKm5nSWY9XCJoYXNQcmV2aW91c05vZGVzKClcIlxuICAgICAgICBjbGFzcz1cImFkZi1icmVhZGNydW1iLWRyb3Bkb3duLXBhdGhcIlxuICAgICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICAgICAgcm9sZT1cImJ1dHRvblwiXG4gICAgPlxuICAgICAgICA8bWF0LW9wdGlvblxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IG5vZGUgb2YgcHJldmlvdXNOb2Rlc1wiXG4gICAgICAgICAgICAoY2xpY2spPVwib25Sb3V0ZVBhdGhDbGljayhub2RlLCAkZXZlbnQpXCJcbiAgICAgICAgICAgIChvblNlbGVjdGlvbkNoYW5nZSk9XCJvblJvdXRlQ2xpY2sobm9kZSlcIlxuICAgICAgICAgICAgY2xhc3M9XCJhZGYtYnJlYWRjcnVtYi1wYXRoLW9wdGlvblwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwicmVhZE9ubHlcIlxuICAgICAgICA+XG4gICAgICAgICAgICB7eyBub2RlLm5hbWUgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgIDwvbWF0LXNlbGVjdD5cblxuICAgIDxkaXZcbiAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2YgbGFzdE5vZGVzOyBsZXQgbGFzdCA9IGxhc3RcIlxuICAgICAgICBbY2xhc3MuYWRmLWFjdGl2ZV09XCJsYXN0XCJcbiAgICAgICAgW25nU3dpdGNoXT1cImJyZWFkY3J1bWJJdGVtSXNBbmNob3IobGFzdClcIlxuICAgICAgICB0aXRsZT1cInt7IGl0ZW0ubmFtZSB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgIGNsYXNzPVwiYWRmLWJyZWFkY3J1bWItaXRlbVwiPlxuICAgICAgICA8YVxuICAgICAgICAgICAgKm5nU3dpdGNoQ2FzZT1cInRydWVcIlxuICAgICAgICAgICAgaHJlZj1cIiNcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hdXRvbWF0aW9uLWlkXT1cIidicmVhZGNydW1iXycgKyBpdGVtLm5hbWVcIlxuICAgICAgICAgICAgY2xhc3M9XCJhZGYtYnJlYWRjcnVtYi1pdGVtLWFuY2hvclwiXG4gICAgICAgICAgICAoY2xpY2spPVwib25Sb3V0ZVBhdGhDbGljayhpdGVtLCAkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICAgICAge3sgaXRlbS5uYW1lIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYT5cblxuICAgICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQgY2xhc3M9XCJhZGYtYnJlYWRjcnVtYi1pdGVtLWN1cnJlbnRcIiBhcmlhLWN1cnJlbnQ9XCJsb2NhdGlvblwiPlxuICAgICAgICAgICAge3sgKHNlbGVjdGVkUm93SXRlbXNDb3VudCA8IDEgPyBpdGVtLm5hbWUgOiAnQlJFQURDUlVNQi5IRUFERVIuU0VMRUNURUQnKSB8IHRyYW5zbGF0ZTogeyBjb3VudDogc2VsZWN0ZWRSb3dJdGVtc0NvdW50IH0gfX1cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiYWRmLWJyZWFkY3J1bWItaXRlbS1jaGV2cm9uXCIgKm5nSWY9XCIhbGFzdFwiPlxuICAgICAgICAgICAgY2hldnJvbl9yaWdodFxuICAgICAgICA8L21hdC1pY29uPlxuICAgIDwvZGl2PlxuPC9uYXY+XG5cbjxuYXZcbiAgICAqbmdJZj1cIiFmb2xkZXJOb2RlICYmIGhhc1Jvb3RcIlxuICAgIGRhdGEtYXV0b21hdGlvbi1pZD1cImJyZWFkY3J1bWJcIlxuICAgIHJvbGU9XCJuYXZpZ2F0aW9uXCJcbiAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidCUkVBRENSVU1CLkFSSUEtTEFCRUwuQlJFQURDUlVNQicgfCB0cmFuc2xhdGVcIlxuPlxuICAgIDxkaXYgY2xhc3M9XCJhZGYtYnJlYWRjcnVtYi1pdGVtIGFkZi1hY3RpdmVcIiByb2xlPVwiZ3JvdXBcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFkZi1icmVhZGNydW1iLWl0ZW0tY3VycmVudFwiPlxuICAgICAgICAgICAge3sgcm9vdCB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvbmF2PlxuIl19