truly-ui
Version:
Web Components for Desktop Applications.
155 lines (153 loc) • 29.1 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewChild, ViewChildren } from '@angular/core';
import { TlDatatableRow } from '../row/datatable-row';
import { Subscription } from 'rxjs';
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
import { DatatableDataSource } from '../../services/datatable-datasource.service';
import { ContextMenuService } from '../../../contextmenu/services/contextmenu.service';
import { scrollIntoView } from '../../../core/helper/scrollIntoView';
import * as i0 from "@angular/core";
import * as i1 from "../../../i18n/i18n.service";
import * as i2 from "../../../contextmenu/services/contextmenu.service";
import * as i3 from "@angular/common";
import * as i4 from "../../../icons/icons";
import * as i5 from "@angular/cdk/scrolling";
import * as i6 from "../../directives/colgroup.directive";
import * as i7 from "../cell/datatable-cell";
import * as i8 from "../row/datatable-row";
'use strict';
export class TlDatatableContent {
constructor(i18n, changes, contextMenuService) {
this.i18n = i18n;
this.changes = changes;
this.contextMenuService = contextMenuService;
this.rowClick = new EventEmitter();
this.rowDbClick = new EventEmitter();
this.rowSelect = new EventEmitter();
this.subscription = new Subscription();
}
ngAfterViewInit() {
this.keyManager = new ActiveDescendantKeyManager(this.items).withTypeAhead();
this.setFirstItemSelected();
}
onRowClick(rowItem, row, index) {
this.rowClick.emit({ row: row, index: index });
this.keyManager.setActiveItem(rowItem);
this.setContentFocus();
}
contextmenu($event, rowItem, row, index) {
if (this.contextMenuItems && this.contextMenuItems.length > 0) {
this.contextMenuService.create($event, rowItem.element, this.contextMenuItems, { row: row, index: index });
return false;
}
}
setContentFocus() {
this.datableContent.nativeElement.focus();
}
isEmpty() {
return (this.dataSource.length === 0 ||
this.dataSource.isEmpty);
}
emptyText() {
return this.i18n.getLocale().Datatable.notFoundText;
}
mouseDown($event) {
if (this.dataSource instanceof DatatableDataSource) {
this.dataSource.setNavigating(true);
}
}
mouseUp($event) {
if (this.dataSource instanceof DatatableDataSource) {
this.dataSource.setNavigating(false);
}
}
onKeydown(event) {
this.keyManager.onKeydown(event);
if (this.keyManager.activeItem) {
scrollIntoView(this.keyManager.activeItem.element.nativeElement);
}
}
onKeyup() {
this.rowSelect.emit(this.keyManager.activeItem);
}
setFirstItemSelected() {
setTimeout(() => {
this.setContentFocus();
this.keyManager.setActiveItem(0);
this.rowSelect.emit(this.keyManager.activeItem);
this.changes.detectChanges();
}, 100);
}
setSelectedItem() {
setTimeout(() => {
this.setContentFocus();
this.keyManager.setActiveItem(this.keyManager.activeItemIndex);
this.rowSelect.emit(this.keyManager.activeItem);
this.changes.detectChanges();
}, 100);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
/** @nocollapse */ TlDatatableContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDatatableContent, deps: [{ token: i1.I18nService }, { token: i0.ChangeDetectorRef }, { token: i2.ContextMenuService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlDatatableContent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlDatatableContent, selector: "tl-datatable-content", inputs: { dataSource: "dataSource", data: "data", rowHeight: "rowHeight", heightViewPort: "heightViewPort", columns: "columns", contextMenuItems: "contextMenuItems" }, outputs: { rowClick: "rowClick", rowDbClick: "rowDbClick", rowSelect: "rowSelect" }, providers: [ContextMenuService], viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, static: true }, { propertyName: "datableContent", first: true, predicate: ["datableContent"], descendants: true }, { propertyName: "items", predicate: TlDatatableRow, descendants: true }], ngImport: i0, template: "<div class=\"ui-datatable-content\" (keydown)=\"onKeydown($event)\" (keyup)=\"onKeyup()\" tabindex=\"-1\" #datableContent>\n\n <cdk-virtual-scroll-viewport\n class=\"ui-datatable-content-wrap\"\n (mousedown)=\"mouseDown($event)\"\n (mouseup)=\"mouseUp($event)\"\n [ngStyle]=\"{'height': heightViewPort+'px' }\"\n [minBufferPx]=\"100\"\n [maxBufferPx]=\"500\"\n [itemSize]=\"rowHeight\">\n\n <table style=\"width: 100%;\" class=\"ui-datatable-table\" [class.hidden]=\"isEmpty()\" [colgroup]=\"columns\">\n <tbody class=\"ui-datatable-content-body\" >\n <ng-container *cdkVirtualFor=\"let row of dataSource; let index = index;\">\n <tl-datatable-row *ngIf=\"row;else loadingRowTemplate\" class=\"ui-row\"\n [ngStyle]=\"{'height': rowHeight+'px' }\"\n [row]=\"row\"\n #rowItem=\"rowItem\"\n [index]=\"index\"\n (click)=\"onRowClick(rowItem, row, index)\"\n (contextmenu)=\"contextmenu($event, rowItem, row, index)\"\n (dblclick)=\"rowDbClick.emit({ row:row, index: index })\">\n <tl-datatable-cell class=\"ui-cel\"\n *ngFor=\"let collumn of columns\" [collumn]=\"collumn\"\n [content]=\"row\"></tl-datatable-cell>\n </tl-datatable-row>\n <ng-template #loadingRowTemplate>\n <tl-datatable-row [ngStyle]=\"{'height': rowHeight+'px' }\" class=\"ui-row\">\n <td class=\"ui-cel\" colspan=\"5\" style=\"text-align: left;\">Loading...</td>\n </tl-datatable-row>\n </ng-template>\n </ng-container>\n </tbody>\n </table>\n\n <div [ngStyle]=\"{'height': heightViewPort+'px' }\" class=\"ui-box-notfound-records\" [class.hidden]=\"!isEmpty()\">\n <tl-icon [lib]=\"'fa'\" [style]=\"'fas'\" [size]=\"'25px'\">filter</tl-icon>\n {{emptyText()}}\n </div>\n </cdk-virtual-scroll-viewport>\n</div>\n", styles: [".ui-datatable-content{overflow:hidden;outline:none}.ui-box-notfound-records{display:flex;align-items:center;justify-content:center;flex-flow:column}.ui-datatable-content-wrap{overflow-y:scroll!important;overflow-x:auto!important}\n", ".tl-datatable-box{width:100%;box-sizing:border-box}.ui-datatable-table{font-family:RobotoRegular,Helvetica,Arial,sans-serif;text-align:center;width:100%;table-layout:fixed;border-spacing:0;border-collapse:collapse}.hidden{display:none}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i4.TlIcons, selector: "tl-icon", inputs: ["icon", "lib", "style", "size", "animation", "color", "align"] }, { kind: "directive", type: i5.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i5.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i5.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: i6.TlColgroupDirective, selector: "[colgroup]", inputs: ["colgroup"] }, { kind: "component", type: i7.TlDatatableCell, selector: "tl-datatable-cell", inputs: ["content", "collumn"] }, { kind: "component", type: i8.TlDatatableRow, selector: "tl-datatable-row", inputs: ["content", "row", "index"], exportAs: ["rowItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDatatableContent, decorators: [{
type: Component,
args: [{ selector: 'tl-datatable-content', providers: [ContextMenuService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-datatable-content\" (keydown)=\"onKeydown($event)\" (keyup)=\"onKeyup()\" tabindex=\"-1\" #datableContent>\n\n <cdk-virtual-scroll-viewport\n class=\"ui-datatable-content-wrap\"\n (mousedown)=\"mouseDown($event)\"\n (mouseup)=\"mouseUp($event)\"\n [ngStyle]=\"{'height': heightViewPort+'px' }\"\n [minBufferPx]=\"100\"\n [maxBufferPx]=\"500\"\n [itemSize]=\"rowHeight\">\n\n <table style=\"width: 100%;\" class=\"ui-datatable-table\" [class.hidden]=\"isEmpty()\" [colgroup]=\"columns\">\n <tbody class=\"ui-datatable-content-body\" >\n <ng-container *cdkVirtualFor=\"let row of dataSource; let index = index;\">\n <tl-datatable-row *ngIf=\"row;else loadingRowTemplate\" class=\"ui-row\"\n [ngStyle]=\"{'height': rowHeight+'px' }\"\n [row]=\"row\"\n #rowItem=\"rowItem\"\n [index]=\"index\"\n (click)=\"onRowClick(rowItem, row, index)\"\n (contextmenu)=\"contextmenu($event, rowItem, row, index)\"\n (dblclick)=\"rowDbClick.emit({ row:row, index: index })\">\n <tl-datatable-cell class=\"ui-cel\"\n *ngFor=\"let collumn of columns\" [collumn]=\"collumn\"\n [content]=\"row\"></tl-datatable-cell>\n </tl-datatable-row>\n <ng-template #loadingRowTemplate>\n <tl-datatable-row [ngStyle]=\"{'height': rowHeight+'px' }\" class=\"ui-row\">\n <td class=\"ui-cel\" colspan=\"5\" style=\"text-align: left;\">Loading...</td>\n </tl-datatable-row>\n </ng-template>\n </ng-container>\n </tbody>\n </table>\n\n <div [ngStyle]=\"{'height': heightViewPort+'px' }\" class=\"ui-box-notfound-records\" [class.hidden]=\"!isEmpty()\">\n <tl-icon [lib]=\"'fa'\" [style]=\"'fas'\" [size]=\"'25px'\">filter</tl-icon>\n {{emptyText()}}\n </div>\n </cdk-virtual-scroll-viewport>\n</div>\n", styles: [".ui-datatable-content{overflow:hidden;outline:none}.ui-box-notfound-records{display:flex;align-items:center;justify-content:center;flex-flow:column}.ui-datatable-content-wrap{overflow-y:scroll!important;overflow-x:auto!important}\n", ".tl-datatable-box{width:100%;box-sizing:border-box}.ui-datatable-table{font-family:RobotoRegular,Helvetica,Arial,sans-serif;text-align:center;width:100%;table-layout:fixed;border-spacing:0;border-collapse:collapse}.hidden{display:none}\n"] }]
}], ctorParameters: function () { return [{ type: i1.I18nService }, { type: i0.ChangeDetectorRef }, { type: i2.ContextMenuService }]; }, propDecorators: { dataSource: [{
type: Input,
args: ['dataSource']
}], data: [{
type: Input,
args: ['data']
}], rowHeight: [{
type: Input,
args: ['rowHeight']
}], heightViewPort: [{
type: Input,
args: ['heightViewPort']
}], columns: [{
type: Input,
args: ['columns']
}], contextMenuItems: [{
type: Input,
args: ['contextMenuItems']
}], rowClick: [{
type: Output,
args: ['rowClick']
}], rowDbClick: [{
type: Output,
args: ['rowDbClick']
}], rowSelect: [{
type: Output,
args: ['rowSelect']
}], viewport: [{
type: ViewChild,
args: ['viewport', { static: true }]
}], items: [{
type: ViewChildren,
args: [TlDatatableRow]
}], datableContent: [{
type: ViewChild,
args: ['datableContent']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXRhYmxlLWNvbnRlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90cnVseS11aS9zcmMvY29tcG9uZW50cy9kYXRhdGFibGUvcGFydHMvY29udGVudC9kYXRhdGFibGUtY29udGVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2RhdGF0YWJsZS9wYXJ0cy9jb250ZW50L2RhdGF0YWJsZS1jb250ZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBRUgsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixTQUFTLEVBQWMsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWEsU0FBUyxFQUFFLFlBQVksRUFDbEcsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBYSxZQUFZLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFFOUMsT0FBTyxFQUFDLDBCQUEwQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFLN0QsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDbEYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbURBQW1ELENBQUM7QUFFdkYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHFDQUFxQyxDQUFDOzs7Ozs7Ozs7O0FBdkNuRSxZQUFZLENBQUM7QUFnRGIsTUFBTSxPQUFPLGtCQUFrQjtJQThCN0IsWUFBb0IsSUFBaUIsRUFDakIsT0FBMEIsRUFDMUIsa0JBQXNDO1FBRnRDLFNBQUksR0FBSixJQUFJLENBQWE7UUFDakIsWUFBTyxHQUFQLE9BQU8sQ0FBbUI7UUFDMUIsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQWxCdEMsYUFBUSxHQUFHLElBQUksWUFBWSxFQUFFLENB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QU07dUJBQUUsV0FBVztnQkFFbUIsUUFBUTtzQkFBOUMsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDO2dCQUVQLEtBQUs7c0JBQWxDLFlBQVk7dUJBQUMsY0FBYztnQkFFQyxjQUFjO3NCQUExQyxTQUFTO3VCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0Jztcbi8qXG4gTUlUIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAxOSBUZW1haW5mbyBTb2Z0d2FyZVxuXG4gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25EZXN0cm95LCBPdXRwdXQsIFF1ZXJ5TGlzdCwgVmlld0NoaWxkLCBWaWV3Q2hpbGRyZW5cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBUbERhdGF0YWJsZVJvdyB9IGZyb20gJy4uL3Jvdy9kYXRhdGFibGUtcm93JztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERhdGFTb3VyY2UgfSBmcm9tICdAYW5ndWxhci9jZGsvY29sbGVjdGlvbnMnO1xuaW1wb3J0IHtBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlcn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuaW1wb3J0IHsgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3Njcm9sbGluZyc7XG5cbmltcG9ydCB7IFRsRGF0YXRhYmxlQ29sdW1uIH0gZnJvbSAnLi4vY29sdW1uL2RhdGF0YWJsZS1jb2x1bW4nO1xuaW1wb3J0IHsgSTE4blNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9pMThuL2kxOG4uc2VydmljZSc7XG5pbXBvcnQgeyBEYXRhdGFibGVEYXRhU291cmNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZGF0YXRhYmxlLWRhdGFzb3VyY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBDb250ZXh0TWVudVNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9jb250ZXh0bWVudS9zZXJ2aWNlcy9jb250ZXh0bWVudS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbnRleHRNZW51SW50ZXJmYWNlIH0gZnJvbSAnLi4vLi4vLi4vY29udGV4dG1lbnUvaW50ZXJmYWNlcy9jb250ZXh0LW1lbnUuaW50ZXJmYWNlJztcbmltcG9ydCB7c2Nyb2xsSW50b1ZpZXd9IGZyb20gJy4uLy4uLy4uL2NvcmUvaGVscGVyL3Njcm9sbEludG9WaWV3JztcblxuQENvbXBvbmVudCgge1xuICBzZWxlY3RvcjogJ3RsLWRhdGF0YWJsZS1jb250ZW50JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2RhdGF0YWJsZS1jb250ZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsgJy4vZGF0YXRhYmxlLWNvbnRlbnQuc2NzcycsICcuLi8uLi9kYXRhdGFibGUuc2NzcycgXSxcbiAgcHJvdmlkZXJzOiBbQ29udGV4dE1lbnVTZXJ2aWNlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59IClcbmV4cG9ydCBjbGFzcyBUbERhdGF0YWJsZUNvbnRlbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gIEBJbnB1dCgnZGF0YVNvdXJjZScpIGRhdGFTb3VyY2U6IEFycmF5PGFueT4gfCBPYnNlcnZhYmxlPEFycmF5PGFueT4+IHwgRGF0YVNvdXJjZTxhbnk+O1xuXG4gIEBJbnB1dCggJ2RhdGEnICkgZGF0YTogQXJyYXk8YW55PjtcblxuICBASW5wdXQoJ3Jvd0hlaWdodCcpIHJvd0hlaWdodDogbnVtYmVyO1xuXG4gIEBJbnB1dCgnaGVpZ2h0Vmlld1BvcnQnKSBoZWlnaHRWaWV3UG9ydDogbnVtYmVyO1xuXG4gIEBJbnB1dCgnY29sdW1ucycpIGNvbHVtbnM6IEFycmF5PFRsRGF0YXRhYmxlQ29sdW1uPjtcblxuICBASW5wdXQoICdjb250ZXh0TWVudUl0ZW1zJyApIGNvbnRleHRNZW51SXRlbXM6IENvbnRleHRNZW51SW50ZXJmYWNlW107XG5cbiAgQE91dHB1dCgncm93Q2xpY2snKSByb3dDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCdyb3dEYkNsaWNrJykgcm93RGJDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCAncm93U2VsZWN0JyApIHJvd1NlbGVjdDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQFZpZXdDaGlsZCgndmlld3BvcnQnLCB7c3RhdGljOiB0cnVlfSkgdmlld3BvcnQ6IENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydDtcblxuICBAVmlld0NoaWxkcmVuKFRsRGF0YXRhYmxlUm93KSBpdGVtczogUXVlcnlMaXN0PFRsRGF0YXRhYmxlUm93PjtcblxuICBAVmlld0NoaWxkKCdkYXRhYmxlQ29udGVudCcpIGRhdGFibGVDb250ZW50OiBFbGVtZW50UmVmO1xuXG4gIHByaXZhdGUga2V5TWFuYWdlcjogQWN0aXZlRGVzY2VuZGFudEtleU1hbmFnZXI8VGxEYXRhdGFibGVSb3c+O1xuXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaTE4bjogSTE4blNlcnZpY2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlczogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgICAgICAgIHByaXZhdGUgY29udGV4dE1lbnVTZXJ2aWNlOiBDb250ZXh0TWVudVNlcnZpY2UpIHt9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMua2V5TWFuYWdlciA9IG5ldyBBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlcih0aGlzLml0ZW1zKS53aXRoVHlwZUFoZWFkKCk7XG4gICAgdGhpcy5zZXRGaXJzdEl0ZW1TZWxlY3RlZCgpO1xuICB9XG5cbiAgb25Sb3dDbGljayggcm93SXRlbTogVGxEYXRhdGFibGVSb3csIHJvdywgaW5kZXggKSB7XG4gICAgdGhpcy5yb3dDbGljay5lbWl0KHsgcm93OiByb3csIGluZGV4OiBpbmRleCB9KTtcbiAgICB0aGlzLmtleU1hbmFnZXIuc2V0QWN0aXZlSXRlbShyb3dJdGVtKTtcbiAgICB0aGlzLnNldENvbnRlbnRGb2N1cygpO1xuICB9XG5cbiAgY29udGV4dG1lbnUoJGV2ZW50LCByb3dJdGVtOiBUbERhdGF0YWJsZVJvdywgcm93LCBpbmRleCApIHtcbiAgICBpZiAodGhpcy5jb250ZXh0TWVudUl0ZW1zICYmIHRoaXMuY29udGV4dE1lbnVJdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNvbnRleHRNZW51U2VydmljZS5jcmVhdGUoJGV2ZW50LCByb3dJdGVtLmVsZW1lbnQsIHRoaXMuY29udGV4dE1lbnVJdGVtcywgeyByb3c6IHJvdywgaW5kZXg6IGluZGV4IH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHNldENvbnRlbnRGb2N1cygpIHtcbiAgICB0aGlzLmRhdGFibGVDb250ZW50Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICh0aGlzLmRhdGFTb3VyY2UgYXMgQXJyYXk8YW55PikubGVuZ3RoID09PSAwIHx8XG4gICAgICAoIHRoaXMuZGF0YVNvdXJjZSBhcyBEYXRhdGFibGVEYXRhU291cmNlKS5pc0VtcHR5XG4gICAgKTtcbiAgfVxuXG4gIGVtcHR5VGV4dCgpIHtcbiAgICByZXR1cm4gdGhpcy5pMThuLmdldExvY2FsZSgpLkRhdGF0YWJsZS5ub3RGb3VuZFRleHQ7XG4gIH1cblxuICBtb3VzZURvd24oICRldmVudCApIHtcbiAgICBpZiAoIHRoaXMuZGF0YVNvdXJjZSBpbnN0YW5jZW9mIERhdGF0YWJsZURhdGFTb3VyY2UpIHtcbiAgICAgICggdGhpcy5kYXRhU291cmNlIGFzIERhdGF0YWJsZURhdGFTb3VyY2UgKS5zZXROYXZpZ2F0aW5nKCB0cnVlICk7XG4gICAgfVxuICB9XG5cbiAgbW91c2VVcCggJGV2ZW50ICkge1xuICAgIGlmICggdGhpcy5kYXRhU291cmNlIGluc3RhbmNlb2YgRGF0YXRhYmxlRGF0YVNvdXJjZSkge1xuICAgICAgKCB0aGlzLmRhdGFTb3VyY2UgYXMgRGF0YXRhYmxlRGF0YVNvdXJjZSApLnNldE5hdmlnYXRpbmcoIGZhbHNlICk7XG4gICAgfVxuICB9XG5cbiAgb25LZXlkb3duKGV2ZW50KSB7XG4gICAgdGhpcy5rZXlNYW5hZ2VyLm9uS2V5ZG93bihldmVudCk7XG4gICAgaWYgKHRoaXMua2V5TWFuYWdlci5hY3RpdmVJdGVtKSB7XG4gICAgICBzY3JvbGxJbnRvVmlldyggdGhpcy5rZXlNYW5hZ2VyLmFjdGl2ZUl0ZW0uZWxlbWVudC5uYXRpdmVFbGVtZW50ICk7XG4gICAgfVxuICB9XG5cbiAgb25LZXl1cCgpIHtcbiAgICB0aGlzLnJvd1NlbGVjdC5lbWl0KCB0aGlzLmtleU1hbmFnZXIuYWN0aXZlSXRlbSApO1xuICB9XG5cbiAgc2V0Rmlyc3RJdGVtU2VsZWN0ZWQoKSB7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNldENvbnRlbnRGb2N1cygpO1xuICAgICAgdGhpcy5rZXlNYW5hZ2VyLnNldEFjdGl2ZUl0ZW0oMCk7XG4gICAgICB0aGlzLnJvd1NlbGVjdC5lbWl0KCB0aGlzLmtleU1hbmFnZXIuYWN0aXZlSXRlbSApO1xuICAgICAgdGhpcy5jaGFuZ2VzLmRldGVjdENoYW5nZXMoKTtcbiAgICB9LCAxMDApO1xuICB9XG5cbiAgc2V0U2VsZWN0ZWRJdGVtKCkge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5zZXRDb250ZW50Rm9jdXMoKTtcbiAgICAgIHRoaXMua2V5TWFuYWdlci5zZXRBY3RpdmVJdGVtKCB0aGlzLmtleU1hbmFnZXIuYWN0aXZlSXRlbUluZGV4ICk7XG4gICAgICB0aGlzLnJvd1NlbGVjdC5lbWl0KCB0aGlzLmtleU1hbmFnZXIuYWN0aXZlSXRlbSApO1xuICAgICAgdGhpcy5jaGFuZ2VzLmRldGVjdENoYW5nZXMoKTtcbiAgICB9LCAxMDApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG59XG4iLCI8ZGl2IGNsYXNzPVwidWktZGF0YXRhYmxlLWNvbnRlbnRcIiAoa2V5ZG93bik9XCJvbktleWRvd24oJGV2ZW50KVwiIChrZXl1cCk9XCJvbktleXVwKClcIiB0YWJpbmRleD1cIi0xXCIgI2RhdGFibGVDb250ZW50PlxuXG4gIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcbiAgICBjbGFzcz1cInVpLWRhdGF0YWJsZS1jb250ZW50LXdyYXBcIlxuICAgIChtb3VzZWRvd24pPVwibW91c2VEb3duKCRldmVudClcIlxuICAgIChtb3VzZXVwKT1cIm1vdXNlVXAoJGV2ZW50KVwiXG4gICAgW25nU3R5bGVdPVwieydoZWlnaHQnOiBoZWlnaHRWaWV3UG9ydCsncHgnIH1cIlxuICAgIFttaW5CdWZmZXJQeF09XCIxMDBcIlxuICAgIFttYXhCdWZmZXJQeF09XCI1MDBcIlxuICAgIFtpdGVtU2l6ZV09XCJyb3dIZWlnaHRcIj5cblxuICAgIDx0YWJsZSBzdHlsZT1cIndpZHRoOiAxMDAlO1wiIGNsYXNzPVwidWktZGF0YXRhYmxlLXRhYmxlXCIgW2NsYXNzLmhpZGRlbl09XCJpc0VtcHR5KClcIiBbY29sZ3JvdXBdPVwiY29sdW1uc1wiPlxuICAgICAgPHRib2R5IGNsYXNzPVwidWktZGF0YXRhYmxlLWNvbnRlbnQtYm9keVwiID5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqY2RrVmlydHVhbEZvcj1cImxldCByb3cgb2YgZGF0YVNvdXJjZTsgbGV0IGluZGV4ID0gaW5kZXg7XCI+XG4gICAgICAgICAgPHRsLWRhdGF0YWJsZS1yb3cgKm5nSWY9XCJyb3c7ZWxzZSBsb2FkaW5nUm93VGVtcGxhdGVcIiBjbGFzcz1cInVpLXJvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nU3R5bGVdPVwieydoZWlnaHQnOiByb3dIZWlnaHQrJ3B4JyB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcm93XT1cInJvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgI3Jvd0l0ZW09XCJyb3dJdGVtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaW5kZXhdPVwiaW5kZXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvblJvd0NsaWNrKHJvd0l0ZW0sIHJvdywgaW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY29udGV4dG1lbnUpPVwiY29udGV4dG1lbnUoJGV2ZW50LCByb3dJdGVtLCByb3csIGluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRibGNsaWNrKT1cInJvd0RiQ2xpY2suZW1pdCh7IHJvdzpyb3csIGluZGV4OiBpbmRleCB9KVwiPlxuICAgICAgICAgICAgPHRsLWRhdGF0YWJsZS1jZWxsIGNsYXNzPVwidWktY2VsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgY29sbHVtbiBvZiBjb2x1bW5zXCIgW2NvbGx1bW5dPVwiY29sbHVtblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NvbnRlbnRdPVwicm93XCI+PC90bC1kYXRhdGFibGUtY2VsbD5cbiAgICAgICAgICA8L3RsLWRhdGF0YWJsZS1yb3c+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNsb2FkaW5nUm93VGVtcGxhdGU+XG4gICAgICAgICAgICA8dGwtZGF0YXRhYmxlLXJvdyBbbmdTdHlsZV09XCJ7J2hlaWdodCc6IHJvd0hlaWdodCsncHgnIH1cIiBjbGFzcz1cInVpLXJvd1wiPlxuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJ1aS1jZWxcIiBjb2xzcGFuPVwiNVwiIHN0eWxlPVwidGV4dC1hbGlnbjogbGVmdDtcIj5Mb2FkaW5nLi4uPC90ZD5cbiAgICAgICAgICAgIDwvdGwtZGF0YXRhYmxlLXJvdz5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvdGJvZHk+XG4gICAgPC90YWJsZT5cblxuICAgIDxkaXYgW25nU3R5bGVdPVwieydoZWlnaHQnOiBoZWlnaHRWaWV3UG9ydCsncHgnIH1cIiBjbGFzcz1cInVpLWJveC1ub3Rmb3VuZC1yZWNvcmRzXCIgW2NsYXNzLmhpZGRlbl09XCIhaXNFbXB0eSgpXCI+XG4gICAgICA8dGwtaWNvbiBbbGliXT1cIidmYSdcIiBbc3R5bGVdPVwiJ2ZhcydcIiBbc2l6ZV09XCInMjVweCdcIj5maWx0ZXI8L3RsLWljb24+XG4gICAgICB7e2VtcHR5VGV4dCgpfX1cbiAgICA8L2Rpdj5cbiAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG48L2Rpdj5cbiJdfQ==