UNPKG

ngx-tree-dnd

Version:

Angular 7 support tree with drag-and-drop sortable data tree. It`s fast and smart.

296 lines 26.6 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* Copyright (C) 2018 Yaroslav Kikot This project is licensed under the terms of the MIT license. https://github.com/Zicrael/ngx-tree-dnd */ import { Component, Input } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; import { NgxTreeService } from '../ngx-tree-dnd.service'; export class NgxTreeChildrenComponent { /** * @param {?} treeService * @param {?} fb */ constructor(treeService, fb) { this.treeService = treeService; this.fb = fb; } // get item from parent component /** * @param {?} data * @return {?} */ set setItem(data) { this.element = data; this.itemOptions = { href: '#', hidden: false, hideChildrens: false, position: this.treeService.getItemPosition(this.element), draggable: true, edit: false, showActionButtons: true, currentlyDragging: false, destenationTop: false, destenationBottom: false, disabled: false, showExpandButton: true, showDeleteButton: true }; if (this.element.options) { this.setOptions(this.element.options); this.element.options = this.itemOptions; } else { this.element.options = this.itemOptions; } // enable subscribers this.enableSubscribers(); // create form this.createForm(); } // enable subscribe to config /** * @return {?} */ enableSubscribers() { this.treeService.config.subscribe((config) => { if (config !== null) { this.config = config; } else { this.config = this.treeService.defaulConfig; } if (this.element.options.draggable) { this.element.options.draggable = this.config.enableDragging; } }); } // set options to item /** * @param {?} options * @return {?} */ setOptions(options) { for (const key of Object.keys(options)) { this.setValue(key, options); } } // set value to options keys /** * @param {?} item * @param {?} options * @return {?} */ setValue(item, options) { this.itemOptions[item] = options[item]; } // create edit form /** * @return {?} */ createForm() { this.renameForm = this.fb.group({ name: [this.element.name || '', [ Validators.required, Validators.minLength(this.config.minCharacterLength) ]], }); } /* Event: onStartRenameItem; Enable rename mode in element Call onStartRenameItem() from tree service. */ /** * @param {?} element * @return {?} */ enableRenameMode(element) { element.options.edit = true; this.treeService.startRenameItem(element); } /* Event: onadditem; Generate id by new Date() by 'full year + day + time'. Call addNewItem() from tree service. */ /** * @param {?} name * @param {?} item * @return {?} */ submitAdd(name, item) { /** @type {?} */ const d = `${new Date().getFullYear()}${new Date().getDay()}${new Date().getTime()}`; /** @type {?} */ const elemId = parseInt(d, null); this.treeService.addNewItem(elemId, name, item); this.element.options.hideChildrens = false; } /* Event: onFinishRenameItem; Check is form valid. Call addNewItem() from tree service. */ /** * @param {?} item * @return {?} */ submitRename(item) { if (this.renameForm.valid) { this.showError = false; this.treeService.finishRenameItem(this.renameForm.value.name, item.id); this.element.options.edit = false; } else { this.showError = true; } } /* Events: onStartDeleteItem, onFinishDeleteItem, onCancelDeleteItem. Check is item edit, then if name empty delete item. Call deleteItem() from tree service. */ /** * @param {?} item * @return {?} */ onSubmitDelete(item) { if (!this.element.options.edit) { this.treeService.deleteItem(item.id); } else { if (item.name === null) { this.treeService.deleteItem(item.id); } else { this.element.options.edit = false; } } } // after view init /** * @return {?} */ ngAfterViewInit() { } } NgxTreeChildrenComponent.decorators = [ { type: Component, args: [{ selector: 'lib-ngx-tree-children', template: `<div class='tree-child' id={{element.id}} libDragElement [draggableValue]='element.options.draggable' [item]='element' [ngClass]="{disabled : element.options.disabled}"> <div *ngIf="element && element.options" class='d-flex'> <div *ngIf='config' [ngClass]="{hidden : element.options.hidden}"> <div class='tree-title d-inline-flex pos-relative' [ngClass]="{destenationTop : element.options.destenationTop, destenationBottom: element.options.destenationBottom}" *ngIf="!element.options.edit;else onEdit"> <div *ngIf="!config.setItemsAsLinks; else link" [ngClass]="{addOpacity : element.options.currentlyDragging}" libDropElement [item]='element' class='draggable-item'> {{element.name}} </div> <ng-template #link> <div [ngClass]="{addOpacity : element.options.currentlyDragging}" libDropElement [item]='element' class='draggable-item'> <a [href]="element.options.href" class='tree-link'>{{element.name}}</a> </div> </ng-template> <div class='d-flex buttons-bar' *ngIf="config.showActionButtons && element.options.showActionButtons && !element.options.disabled"> <div class='d-flex'> <button class="tree-btn add-btn" *ngIf="config.showAddButtons" (click)="submitAdd(null, element)"> <fa-icon icon="plus" [style.font-size.px]='config.setIconSize'></fa-icon> </button> </div> <div class='d-flex'> <button class="tree-btn edit-btn" *ngIf="config.showRenameButtons" (click)="enableRenameMode(element)"> <fa-icon icon="edit" [style.font-size.px]='config.setIconSize'></fa-icon> </button> </div> <div class='d-flex'> <button class="tree-btn delete-btn" *ngIf="config.showDeleteButtons && element.options.showDeleteButton" (click)="onSubmitDelete( element )"> <fa-icon icon="times" [style.font-size.px]='config.setIconSize'></fa-icon> </button> </div> </div> <div class='child-drop-place' [attr.data-id]='element.id' libDropElement *ngIf='element.options.showDropChildZone && !element.options.disabled'> <fa-icon icon="arrow-down" [style.font-size.px]='config.setIconSize'></fa-icon> </div> <div class='show-hide-switch' *ngIf="config.enableExpandButtons && element.options.showExpandButton && element.childrens.length > 0 && !element.options.disabled"> <div *ngIf="element.options.hideChildrens; else visible"> <button class='tree-btn show-btn' (click)='element.options.hideChildrens = false'> <fa-icon icon="plus" [style.font-size.px]='config.setIconSize'></fa-icon> </button> </div> <ng-template #visible> <button class='tree-btn hide-btn' (click)='element.options.hideChildrens = true'> <fa-icon icon="minus" [style.font-size.px]='config.setIconSize'></fa-icon> </button> </ng-template> </div> </div> <ng-template #onEdit> <div class='tree-title d-inline-flex'> <form [formGroup]="renameForm" class='d-flex' (submit)='submitRename(element)'> <input type="text" class='input-rename' formControlName="name" libAutoFocus="true" [style.font-size.px]='config.setFontSize'> </form> <div class='d-flex'> <button class='tree-btn submit-btn' (click)='submitRename(element)'> <fa-icon icon="check" [style.font-size.px]='config.setIconSize'></fa-icon> </button> <button class='tree-btn delete-btn' (click)='onSubmitDelete(element)'> <fa-icon icon="times" [style.font-size.px]='config.setIconSize'></fa-icon> </button> <div class='error-edit-wrap' *ngIf="showError"> {{config.validationText}} </div> </div> </div> </ng-template> <div class="tree-content" *ngIf="element.childrens && !element.options.hideChildrens"> <lib-ngx-tree-children [setItem]="child" *ngFor='let child of element.childrens'></lib-ngx-tree-children> </div> </div> </div> </div> ` },] }, ]; /** @nocollapse */ NgxTreeChildrenComponent.ctorParameters = () => [ { type: NgxTreeService }, { type: FormBuilder } ]; NgxTreeChildrenComponent.propDecorators = { setItem: [{ type: Input }] }; if (false) { /** @type {?} */ NgxTreeChildrenComponent.prototype.showError; /** @type {?} */ NgxTreeChildrenComponent.prototype.config; /** @type {?} */ NgxTreeChildrenComponent.prototype.element; /** @type {?} */ NgxTreeChildrenComponent.prototype.dragable; /** @type {?} */ NgxTreeChildrenComponent.prototype.itemOptions; /** @type {?} */ NgxTreeChildrenComponent.prototype.childrensArray; /** @type {?} */ NgxTreeChildrenComponent.prototype.renameForm; /** * @type {?} * @private */ NgxTreeChildrenComponent.prototype.treeService; /** * @type {?} * @private */ NgxTreeChildrenComponent.prototype.fb; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRyZWUtZG5kLWNoaWxkcmVuLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC10cmVlLWRuZC8iLCJzb3VyY2VzIjpbImxpYi9uZ3gtdHJlZS1kbmQtY2hpbGRyZW4vbmd4LXRyZWUtZG5kLWNoaWxkcmVuLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFNQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDaEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUE4RXpELE1BQU0sT0FBTyx3QkFBd0I7Ozs7O0lBeUNuQyxZQUFvQixXQUEyQixFQUFVLEVBQWU7UUFBcEQsZ0JBQVcsR0FBWCxXQUFXLENBQWdCO1FBQVUsT0FBRSxHQUFGLEVBQUUsQ0FBYTtJQUFHLENBQUM7Ozs7OztJQS9CNUUsSUFDSSxPQUFPLENBQUMsSUFBZTtRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsV0FBVyxHQUFHO1lBQ2pCLElBQUksRUFBRSxHQUFHO1lBQ1QsTUFBTSxFQUFFLEtBQUs7WUFDYixhQUFhLEVBQUUsS0FBSztZQUNwQixRQUFRLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztZQUN4RCxTQUFTLEVBQUUsSUFBSTtZQUNmLElBQUksRUFBRSxLQUFLO1lBQ1gsaUJBQWlCLEVBQUUsSUFBSTtZQUN2QixpQkFBaUIsRUFBRSxLQUFLO1lBQ3hCLGNBQWMsRUFBRSxLQUFLO1lBQ3JCLGlCQUFpQixFQUFFLEtBQUs7WUFDeEIsUUFBUSxFQUFFLEtBQUs7WUFDZixnQkFBZ0IsRUFBRSxJQUFJO1lBQ3RCLGdCQUFnQixFQUFFLElBQUk7U0FDdkIsQ0FBQztRQUNGLElB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QW1DOzs7OztJQUFFLHNDQUF1QiIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gQ29weXJpZ2h0IChDKSAyMDE4IFlhcm9zbGF2IEtpa290XG4gVGhpcyBwcm9qZWN0IGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTUlUIGxpY2Vuc2UuXG4gaHR0cHM6Ly9naXRodWIuY29tL1ppY3JhZWwvbmd4LXRyZWUtZG5kXG4gKi9cblxuaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgQWZ0ZXJWaWV3SW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE5neFRyZWVTZXJ2aWNlIH0gZnJvbSAnLi4vbmd4LXRyZWUtZG5kLnNlcnZpY2UnO1xuaW1wb3J0IHsgVHJlZU1vZGVsLCBUcmVlQ29uZmlnLCBUcmVlSXRlbU9wdGlvbnMgfSBmcm9tICcuLi9tb2RlbHMvdHJlZS12aWV3Lm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLW5neC10cmVlLWNoaWxkcmVuJyxcbiAgdGVtcGxhdGU6IGA8ZGl2IGNsYXNzPSd0cmVlLWNoaWxkJyBpZD17e2VsZW1lbnQuaWR9fSBsaWJEcmFnRWxlbWVudCBbZHJhZ2dhYmxlVmFsdWVdPSdlbGVtZW50Lm9wdGlvbnMuZHJhZ2dhYmxlJyBbaXRlbV09J2VsZW1lbnQnIFtuZ0NsYXNzXT1cIntkaXNhYmxlZCA6IGVsZW1lbnQub3B0aW9ucy5kaXNhYmxlZH1cIj5cbiAgPGRpdiAqbmdJZj1cImVsZW1lbnQgJiYgZWxlbWVudC5vcHRpb25zXCIgY2xhc3M9J2QtZmxleCc+XG4gICAgPGRpdiAqbmdJZj0nY29uZmlnJyBbbmdDbGFzc109XCJ7aGlkZGVuIDogZWxlbWVudC5vcHRpb25zLmhpZGRlbn1cIj5cbiAgICAgIDxkaXYgY2xhc3M9J3RyZWUtdGl0bGUgZC1pbmxpbmUtZmxleCBwb3MtcmVsYXRpdmUnIFtuZ0NsYXNzXT1cIntkZXN0ZW5hdGlvblRvcCA6IGVsZW1lbnQub3B0aW9ucy5kZXN0ZW5hdGlvblRvcCwgZGVzdGVuYXRpb25Cb3R0b206IGVsZW1lbnQub3B0aW9ucy5kZXN0ZW5hdGlvbkJvdHRvbX1cIiAqbmdJZj1cIiFlbGVtZW50Lm9wdGlvbnMuZWRpdDtlbHNlIG9uRWRpdFwiPlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbmZpZy5zZXRJdGVtc0FzTGlua3M7IGVsc2UgbGlua1wiIFtuZ0NsYXNzXT1cInthZGRPcGFjaXR5IDogZWxlbWVudC5vcHRpb25zLmN1cnJlbnRseURyYWdnaW5nfVwiIGxpYkRyb3BFbGVtZW50XG4gICAgICAgICAgW2l0ZW1dPSdlbGVtZW50JyBjbGFzcz0nZHJhZ2dhYmxlLWl0ZW0nPlxuICAgICAgICAgIHt7ZWxlbWVudC5uYW1lfX1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjbGluaz5cbiAgICAgICAgICA8ZGl2IFtuZ0NsYXNzXT1cInthZGRPcGFjaXR5IDogZWxlbWVudC5vcHRpb25zLmN1cnJlbnRseURyYWdnaW5nfVwiIGxpYkRyb3BFbGVtZW50XG4gICAgICAgICAgW2l0ZW1dPSdlbGVtZW50JyBjbGFzcz0nZHJhZ2dhYmxlLWl0ZW0nPlxuICAgICAgICAgICAgPGEgW2hyZWZdPVwiZWxlbWVudC5vcHRpb25zLmhyZWZcIiBjbGFzcz0ndHJlZS1saW5rJz57e2VsZW1lbnQubmFtZX19PC9hPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8ZGl2IGNsYXNzPSdkLWZsZXggYnV0dG9ucy1iYXInICpuZ0lmPVwiY29uZmlnLnNob3dBY3Rpb25CdXR0b25zICYmIGVsZW1lbnQub3B0aW9ucy5zaG93QWN0aW9uQnV0dG9ucyAmJiAhZWxlbWVudC5vcHRpb25zLmRpc2FibGVkXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz0nZC1mbGV4Jz5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJ0cmVlLWJ0biBhZGQtYnRuXCIgKm5nSWY9XCJjb25maWcuc2hvd0FkZEJ1dHRvbnNcIiAoY2xpY2spPVwic3VibWl0QWRkKG51bGwsIGVsZW1lbnQpXCI+XG4gICAgICAgICAgICAgIDxmYS1pY29uIGljb249XCJwbHVzXCIgW3N0eWxlLmZvbnQtc2l6ZS5weF09J2NvbmZpZy5zZXRJY29uU2l6ZSc+PC9mYS1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz0nZC1mbGV4Jz5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJ0cmVlLWJ0biBlZGl0LWJ0blwiICpuZ0lmPVwiY29uZmlnLnNob3dSZW5hbWVCdXR0b25zXCIgKGNsaWNrKT1cImVuYWJsZVJlbmFtZU1vZGUoZWxlbWVudClcIj5cbiAgICAgICAgICAgICAgPGZhLWljb24gaWNvbj1cImVkaXRcIiBbc3R5bGUuZm9udC1zaXplLnB4XT0nY29uZmlnLnNldEljb25TaXplJz48L2ZhLWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPSdkLWZsZXgnPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInRyZWUtYnRuIGRlbGV0ZS1idG5cIiAqbmdJZj1cImNvbmZpZy5zaG93RGVsZXRlQnV0dG9ucyAmJiBlbGVtZW50Lm9wdGlvbnMuc2hvd0RlbGV0ZUJ1dHRvblwiIChjbGljayk9XCJvblN1Ym1pdERlbGV0ZSggZWxlbWVudCApXCI+XG4gICAgICAgICAgICAgIDxmYS1pY29uIGljb249XCJ0aW1lc1wiIFtzdHlsZS5mb250LXNpemUucHhdPSdjb25maWcuc2V0SWNvblNpemUnPjwvZmEtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz0nY2hpbGQtZHJvcC1wbGFjZScgW2F0dHIuZGF0YS1pZF09J2VsZW1lbnQuaWQnICBsaWJEcm9wRWxlbWVudCAqbmdJZj0nZWxlbWVudC5vcHRpb25zLnNob3dEcm9wQ2hpbGRab25lICYmICFlbGVtZW50Lm9wdGlvbnMuZGlzYWJsZWQnPlxuICAgICAgICAgIDxmYS1pY29uIGljb249XCJhcnJvdy1kb3duXCIgW3N0eWxlLmZvbnQtc2l6ZS5weF09J2NvbmZpZy5zZXRJY29uU2l6ZSc+PC9mYS1pY29uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz0nc2hvdy1oaWRlLXN3aXRjaCcgKm5nSWY9XCJjb25maWcuZW5hYmxlRXhwYW5kQnV0dG9ucyAmJiBlbGVtZW50Lm9wdGlvbnMuc2hvd0V4cGFuZEJ1dHRvbiAmJiBlbGVtZW50LmNoaWxkcmVucy5sZW5ndGggPiAwICYmICFlbGVtZW50Lm9wdGlvbnMuZGlzYWJsZWRcIj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZWxlbWVudC5vcHRpb25zLmhpZGVDaGlsZHJlbnM7IGVsc2UgdmlzaWJsZVwiPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndHJlZS1idG4gc2hvdy1idG4nIChjbGljayk9J2VsZW1lbnQub3B0aW9ucy5oaWRlQ2hpbGRyZW5zID0gZmFsc2UnPlxuICAgICAgICAgICAgICA8ZmEtaWNvbiBpY29uPVwicGx1c1wiIFtzdHlsZS5mb250LXNpemUucHhdPSdjb25maWcuc2V0SWNvblNpemUnPjwvZmEtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjdmlzaWJsZT5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9J3RyZWUtYnRuIGhpZGUtYnRuJyAoY2xpY2spPSdlbGVtZW50Lm9wdGlvbnMuaGlkZUNoaWxkcmVucyA9IHRydWUnPlxuICAgICAgICAgICAgICA8ZmEtaWNvbiBpY29uPVwibWludXNcIiBbc3R5bGUuZm9udC1zaXplLnB4XT0nY29uZmlnLnNldEljb25TaXplJz48L2ZhLWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPG5nLXRlbXBsYXRlICNvbkVkaXQ+XG4gICAgICAgIDxkaXYgY2xhc3M9J3RyZWUtdGl0bGUgZC1pbmxpbmUtZmxleCc+XG4gICAgICAgICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJyZW5hbWVGb3JtXCIgY2xhc3M9J2QtZmxleCcgKHN1Ym1pdCk9J3N1Ym1pdFJlbmFtZShlbGVtZW50KSc+XG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz0naW5wdXQtcmVuYW1lJyBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCIgbGliQXV0b0ZvY3VzPVwidHJ1ZVwiIFtzdHlsZS5mb250LXNpemUucHhdPSdjb25maWcuc2V0Rm9udFNpemUnPlxuICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPSdkLWZsZXgnPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ndHJlZS1idG4gc3VibWl0LWJ0bicgKGNsaWNrKT0nc3VibWl0UmVuYW1lKGVsZW1lbnQpJz5cbiAgICAgICAgICAgICAgPGZhLWljb24gaWNvbj1cImNoZWNrXCIgW3N0eWxlLmZvbnQtc2l6ZS5weF09J2NvbmZpZy5zZXRJY29uU2l6ZSc+PC9mYS1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPSd0cmVlLWJ0biBkZWxldGUtYnRuJyAoY2xpY2spPSdvblN1Ym1pdERlbGV0ZShlbGVtZW50KSc+XG4gICAgICAgICAgICAgIDxmYS1pY29uIGljb249XCJ0aW1lc1wiIFtzdHlsZS5mb250LXNpemUucHhdPSdjb25maWcuc2V0SWNvblNpemUnPjwvZmEtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz0nZXJyb3ItZWRpdC13cmFwJyAqbmdJZj1cInNob3dFcnJvclwiPlxuICAgICAgICAgICAgICB7e2NvbmZpZy52YWxpZGF0aW9uVGV4dH19XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPGRpdiBjbGFzcz1cInRyZWUtY29udGVudFwiICpuZ0lmPVwiZWxlbWVudC5jaGlsZHJlbnMgJiYgIWVsZW1lbnQub3B0aW9ucy5oaWRlQ2hpbGRyZW5zXCI+XG4gICAgICAgIDxsaWItbmd4LXRyZWUtY2hpbGRyZW4gW3NldEl0ZW1dPVwiY2hpbGRcIiAqbmdGb3I9J2xldCBjaGlsZCBvZiBlbGVtZW50LmNoaWxkcmVucyc+PC9saWItbmd4LXRyZWUtY2hpbGRyZW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbmBcbn0pXG5leHBvcnQgY2xhc3MgTmd4VHJlZUNoaWxkcmVuQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCB7XG4gIHNob3dFcnJvcjogYm9vbGVhbjtcbiAgY29uZmlnOiBUcmVlQ29uZmlnO1xuICBlbGVtZW50OiBUcmVlTW9kZWw7XG4gIGRyYWdhYmxlOiBib29sZWFuO1xuICBpdGVtT3B0aW9uczogVHJlZUl0ZW1PcHRpb25zO1xuICBjaGlsZHJlbnNBcnJheTogVHJlZU1vZGVsW107XG4gIHJlbmFtZUZvcm07XG5cbiAgLy8gZ2V0IGl0ZW0gZnJvbSBwYXJlbnQgY29tcG9uZW50XG4gIEBJbnB1dCgpXG4gIHNldCBzZXRJdGVtKGRhdGE6IFRyZWVNb2RlbCkge1xuICAgIHRoaXMuZWxlbWVudCA9IGRhdGE7XG4gICAgdGhpcy5pdGVtT3B0aW9ucyA9IHtcbiAgICAgIGhyZWY6ICcjJyxcbiAgICAgIGhpZGRlbjogZmFsc2UsXG4gICAgICBoaWRlQ2hpbGRyZW5zOiBmYWxzZSxcbiAgICAgIHBvc2l0aW9uOiB0aGlzLnRyZWVTZXJ2aWNlLmdldEl0ZW1Qb3NpdGlvbih0aGlzLmVsZW1lbnQpLFxuICAgICAgZHJhZ2dhYmxlOiB0cnVlLFxuICAgICAgZWRpdDogZmFsc2UsXG4gICAgICBzaG93QWN0aW9uQnV0dG9uczogdHJ1ZSxcbiAgICAgIGN1cnJlbnRseURyYWdnaW5nOiBmYWxzZSxcbiAgICAgIGRlc3RlbmF0aW9uVG9wOiBmYWxzZSxcbiAgICAgIGRlc3RlbmF0aW9uQm90dG9tOiBmYWxzZSxcbiAgICAgIGRpc2FibGVkOiBmYWxzZSxcbiAgICAgIHNob3dFeHBhbmRCdXR0b246IHRydWUsXG4gICAgICBzaG93RGVsZXRlQnV0dG9uOiB0cnVlXG4gICAgfTtcbiAgICBpZiAodGhpcy5lbGVtZW50Lm9wdGlvbnMpIHtcbiAgICAgIHRoaXMuc2V0T3B0aW9ucyh0aGlzLmVsZW1lbnQub3B0aW9ucyk7XG4gICAgICB0aGlzLmVsZW1lbnQub3B0aW9ucyA9IHRoaXMuaXRlbU9wdGlvbnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZWxlbWVudC5vcHRpb25zID0gdGhpcy5pdGVtT3B0aW9ucztcbiAgICB9XG5cbiAgICAvLyBlbmFibGUgc3Vic2NyaWJlcnNcbiAgICB0aGlzLmVuYWJsZVN1YnNjcmliZXJzKCk7XG4gICAgLy8gY3JlYXRlIGZvcm1cbiAgICB0aGlzLmNyZWF0ZUZvcm0oKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgdHJlZVNlcnZpY2U6IE5neFRyZWVTZXJ2aWNlLCBwcml2YXRlIGZiOiBGb3JtQnVpbGRlcikge31cblxuICAvLyBlbmFibGUgc3Vic2NyaWJlIHRvIGNvbmZpZ1xuICBlbmFibGVTdWJzY3JpYmVycygpIHtcbiAgICB0aGlzLnRyZWVTZXJ2aWNlLmNvbmZpZy5zdWJzY3JpYmUoXG4gICAgICAoY29uZmlnKSA9PiB7XG4gICAgICAgIGlmICggY29uZmlnICE9PSBudWxsICkge1xuICAgICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuY29uZmlnID0gdGhpcy50cmVlU2VydmljZS5kZWZhdWxDb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZWxlbWVudC5vcHRpb25zLmRyYWdnYWJsZSkge1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5vcHRpb25zLmRyYWdnYWJsZSA9IHRoaXMuY29uZmlnLmVuYWJsZURyYWdnaW5nO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8vIHNldCBvcHRpb25zIHRvIGl0ZW1cbiAgc2V0T3B0aW9ucyhvcHRpb25zKSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob3B0aW9ucykpIHtcbiAgICAgIHRoaXMuc2V0VmFsdWUoa2V5LCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvLyBzZXQgdmFsdWUgdG8gb3B0aW9ucyBrZXlzXG4gIHNldFZhbHVlKGl0ZW0sIG9wdGlvbnMpIHtcbiAgICB0aGlzLml0ZW1PcHRpb25zW2l0ZW1dID0gb3B0aW9uc1tpdGVtXTtcbiAgfVxuXG4gIC8vIGNyZWF0ZSBlZGl0IGZvcm1cbiAgY3JlYXRlRm9ybSgpIHtcbiAgICB0aGlzLnJlbmFtZUZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIG5hbWU6IFt0aGlzLmVsZW1lbnQubmFtZSB8fCAnJyAsIFtcbiAgICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCxcbiAgICAgICAgVmFsaWRhdG9ycy5taW5MZW5ndGgoIHRoaXMuY29uZmlnLm1pbkNoYXJhY3Rlckxlbmd0aCApXG4gICAgICBdXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qXG4gICAgRXZlbnQ6IG9uU3RhcnRSZW5hbWVJdGVtO1xuICAgIEVuYWJsZSByZW5hbWUgbW9kZSBpbiBlbGVtZW50XG4gICAgQ2FsbCBvblN0YXJ0UmVuYW1lSXRlbSgpIGZyb20gdHJlZSBzZXJ2aWNlLlxuICAqL1xuICBlbmFibGVSZW5hbWVNb2RlKGVsZW1lbnQpIHtcbiAgICBlbGVtZW50Lm9wdGlvbnMuZWRpdCA9IHRydWU7XG4gICAgdGhpcy50cmVlU2VydmljZS5zdGFydFJlbmFtZUl0ZW0oZWxlbWVudCk7XG4gIH1cblxuICAvKlxuICAgIEV2ZW50OiBvbmFkZGl0ZW07XG4gICAgR2VuZXJhdGUgaWQgYnkgbmV3IERhdGUoKSBieSAnZnVsbCB5ZWFyICsgZGF5ICsgdGltZScuXG4gICAgQ2FsbCBhZGROZXdJdGVtKCkgZnJvbSB0cmVlIHNlcnZpY2UuXG4gICovXG4gIHN1Ym1pdEFkZChuYW1lLCBpdGVtICkge1xuICAgICAgY29uc3QgZCA9IGAke25ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKX0ke25ldyBEYXRlKCkuZ2V0RGF5KCl9JHtuZXcgRGF0ZSgpLmdldFRpbWUoKX1gO1xuICAgICAgY29uc3QgZWxlbUlkID0gIHBhcnNlSW50KGQsIG51bGwpO1xuICAgICAgdGhpcy50cmVlU2VydmljZS5hZGROZXdJdGVtKGVsZW1JZCwgbmFtZSwgaXRlbSk7XG4gICAgICB0aGlzLmVsZW1lbnQub3B0aW9ucy5oaWRlQ2hpbGRyZW5zID0gZmFsc2U7XG4gIH1cblxuICAvKlxuICAgIEV2ZW50OiBvbkZpbmlzaFJlbmFtZUl0ZW07XG4gICAgQ2hlY2sgaXMgZm9ybSB2YWxpZC5cbiAgICBDYWxsIGFkZE5ld0l0ZW0oKSBmcm9tIHRyZWUgc2VydmljZS5cbiAgKi9cbiAgc3VibWl0UmVuYW1lKGl0ZW0pIHtcbiAgICBpZiAodGhpcy5yZW5hbWVGb3JtLnZhbGlkKSB7XG4gICAgICB0aGlzLnNob3dFcnJvciA9IGZhbHNlO1xuICAgICAgdGhpcy50cmVlU2VydmljZS5maW5pc2hSZW5hbWVJdGVtKHRoaXMucmVuYW1lRm9ybS52YWx1ZS5uYW1lLCBpdGVtLmlkKTtcbiAgICAgIHRoaXMuZWxlbWVudC5vcHRpb25zLmVkaXQgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zaG93RXJyb3IgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qXG4gICAgRXZlbnRzOlxuICAgIG9uU3RhcnREZWxldGVJdGVtLFxuICAgIG9uRmluaXNoRGVsZXRlSXRlbSwgICAgXG4gICAgb25DYW5jZWxEZWxldGVJdGVtLlxuICAgIENoZWNrIGlzIGl0ZW0gZWRpdCwgdGhlbiBpZiBuYW1lIGVtcHR5IGRlbGV0ZSBpdGVtLlxuICAgIENhbGwgZGVsZXRlSXRlbSgpIGZyb20gdHJlZSBzZXJ2aWNlLlxuICAqL1xuICBvblN1Ym1pdERlbGV0ZShpdGVtKSB7XG4gICAgaWYgKCF0aGlzLmVsZW1lbnQub3B0aW9ucy5lZGl0KSB7XG4gICAgICB0aGlzLnRyZWVTZXJ2aWNlLmRlbGV0ZUl0ZW0oaXRlbS5pZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICggaXRlbS5uYW1lID09PSBudWxsICkge1xuICAgICAgICB0aGlzLnRyZWVTZXJ2aWNlLmRlbGV0ZUl0ZW0oaXRlbS5pZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmVsZW1lbnQub3B0aW9ucy5lZGl0ID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYWZ0ZXIgdmlldyBpbml0XG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHt9XG59XG4iXX0=