UNPKG

truly-ui

Version:

Web Components for Desktop Applications.

227 lines (225 loc) 29.9 kB
/* 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, ContentChildren, EventEmitter, Input, Output, ViewChild } from '@angular/core'; import { TlDatatableColumn } from './parts/column/datatable-column'; import { FilterOptionsService } from './services/datatable-filter-options.service'; import { TlDatatableFilterService } from './services/datatable-filter.service'; import { DatatableDataSource } from './services/datatable-datasource.service'; import { TlDatatableColumnService } from './services/datatable-column.service'; import { TlDatatableFilterConstraints } from './services/datatable-filter-constraints.service'; import { Subject } from 'rxjs'; import { TlDatatableSortService } from './services/datatable-sort.service'; import { DatatableHelpersService } from './services/datatable-helpers.service'; import { TlDatatableContent } from './parts/content/datatable-content'; import * as i0 from "@angular/core"; import * as i1 from "./services/datatable-column.service"; import * as i2 from "./services/datatable-filter.service"; import * as i3 from "./services/datatable-sort.service"; import * as i4 from "@angular/common"; import * as i5 from "./parts/header/datatable-header"; import * as i6 from "./parts/content/datatable-content"; export class TlDatatable { set loading(value) { this._loading = value; this.loadingSubject.next(value); } get loading() { return this._loading; } constructor(columnService, filterService, sortService) { this.columnService = columnService; this.filterService = filterService; this.sortService = sortService; this.recordsCount = -1; this.mode = 'scrollable'; this.rowModel = 'inmemory'; this.allowResize = false; this.allowSortColumn = true; this.initializeFocus = true; this.allowFilterColumn = false; this.rowsPage = 30; this.rowHeight = 25; this.rowsClient = 12; this.height = 300; this.width = 300; this.rowSelect = new EventEmitter(); this.rowClick = new EventEmitter(); this.rowDblclick = new EventEmitter(); this.pageChange = new EventEmitter(); this.sortData = new EventEmitter(); this.filterData = new EventEmitter(); this.loadData = new EventEmitter(); this.endRow = new EventEmitter(); this.dataSource = new DatatableDataSource(this); this.columns = []; this.heightViewPort = 0; this.tabindex = 0; this.scrollingHorizontalSubject = new Subject(); this.loadingSubject = new Subject(); this._loading = false; } ngAfterContentInit() { this.calcDimensionsHeight(); this.columnService.onInitColumnService(this); this.filterService.onInicializeFilterService(this); this.sortService.onInicializeSortService(this); this.columnService.setColumns(); } ngOnChanges(changes) { this.dataSource.changes(changes); } calcDimensionsHeight() { this.heightViewPort = this.allowFilterColumn ? this.height - 32 : this.height; this.heightViewPort -= 25; this.rowHeight = this.heightViewPort / this.rowsClient; } onRowClick(row, index) { this.rowClick.emit(this.getObjectRow(row, index)); } onRowSelect(row, index) { this.rowSelect.emit(this.getObjectRow(row, index)); } onChangeFilter(value) { this.filterService.setFilter(value); } onChangeSort(sort) { this.sortService.setSort(sort); } onKeydownFilter(event) { this.filterService.keydownFilter.next(event); } onRowDblclick(row, index) { this.rowDblclick.emit(this.getObjectRow(row, index)); } setFocus() { this.datatableContent.setSelectedItem(); } getScrollingHorizontal() { return this.scrollingHorizontalSubject.asObservable(); } getObjectRow(row, index) { return { data: row, index: index }; } } /** @nocollapse */ TlDatatable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDatatable, deps: [{ token: i1.TlDatatableColumnService }, { token: i2.TlDatatableFilterService }, { token: i3.TlDatatableSortService }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ TlDatatable.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlDatatable, selector: "tl-datatable", inputs: { data: "data", recordsCount: "recordsCount", mode: "mode", rowModel: "rowModel", contextMenuItems: "contextMenuItems", allowResize: "allowResize", allowSortColumn: "allowSortColumn", initializeFocus: "initializeFocus", allowFilterColumn: "allowFilterColumn", rowsPage: "rowsPage", rowHeight: "rowHeight", rowsClient: "rowsClient", height: "height", width: "width", globalFilter: "globalFilter", globalFilterOptions: "globalFilterOptions" }, outputs: { rowSelect: "rowSelect", rowClick: "rowClick", rowDblclick: "rowDblclick", pageChange: "pageChange", sortData: "sortData", filterData: "filterData", loadData: "loadData", endRow: "endRow" }, providers: [ TlDatatableColumnService, TlDatatableFilterConstraints, TlDatatableFilterService, TlDatatableSortService, FilterOptionsService, DatatableHelpersService ], queries: [{ propertyName: "datatableColumns", predicate: TlDatatableColumn }], viewQueries: [{ propertyName: "tbody", first: true, predicate: ["tbody"], descendants: true, static: true }, { propertyName: "datatableBox", first: true, predicate: ["datatableBox"], descendants: true, static: true }, { propertyName: "datatableContent", first: true, predicate: TlDatatableContent, descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"tl-datatable-box\" #datatableBox\n [ngClass]=\"{'-borderleft': true}\"\n [ngStyle]=\"{width: width}\">\n <tl-datatable-header [dt]=\"this\"\n (filterEvent)=\"onChangeFilter($event)\"\n (sortEvent)=\"onChangeSort($event)\"\n (keydownFilterEvent)=\"onKeydownFilter($event)\"\n >\n </tl-datatable-header>\n <tl-datatable-content\n [dataSource]=\"dataSource\"\n [data]=\"data\"\n [rowHeight]=\"rowHeight\"\n [heightViewPort]=\"heightViewPort\"\n [columns]=\"columns\"\n [contextMenuItems]=\"contextMenuItems\"\n (rowSelect)=\"onRowSelect( $event.row, $event.index )\"\n (rowDbClick)=\"onRowDblclick( $event.row, $event.index )\"\n (rowClick)=\"onRowClick( $event.row, $event.index )\">\n </tl-datatable-content>\n</div>\n\n", styles: [".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: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i5.TlDatatableHeader, selector: "tl-datatable-header", inputs: ["dt"], outputs: ["keydownFilter", "filterEvent", "sortEvent", "keydownFilterEvent"] }, { kind: "component", type: i6.TlDatatableContent, selector: "tl-datatable-content", inputs: ["dataSource", "data", "rowHeight", "heightViewPort", "columns", "contextMenuItems"], outputs: ["rowClick", "rowDbClick", "rowSelect"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlDatatable, decorators: [{ type: Component, args: [{ selector: 'tl-datatable', providers: [ TlDatatableColumnService, TlDatatableFilterConstraints, TlDatatableFilterService, TlDatatableSortService, FilterOptionsService, DatatableHelpersService ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tl-datatable-box\" #datatableBox\n [ngClass]=\"{'-borderleft': true}\"\n [ngStyle]=\"{width: width}\">\n <tl-datatable-header [dt]=\"this\"\n (filterEvent)=\"onChangeFilter($event)\"\n (sortEvent)=\"onChangeSort($event)\"\n (keydownFilterEvent)=\"onKeydownFilter($event)\"\n >\n </tl-datatable-header>\n <tl-datatable-content\n [dataSource]=\"dataSource\"\n [data]=\"data\"\n [rowHeight]=\"rowHeight\"\n [heightViewPort]=\"heightViewPort\"\n [columns]=\"columns\"\n [contextMenuItems]=\"contextMenuItems\"\n (rowSelect)=\"onRowSelect( $event.row, $event.index )\"\n (rowDbClick)=\"onRowDblclick( $event.row, $event.index )\"\n (rowClick)=\"onRowClick( $event.row, $event.index )\">\n </tl-datatable-content>\n</div>\n\n", styles: [".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.TlDatatableColumnService }, { type: i2.TlDatatableFilterService }, { type: i3.TlDatatableSortService }]; }, propDecorators: { data: [{ type: Input, args: ['data'] }], recordsCount: [{ type: Input, args: ['recordsCount'] }], mode: [{ type: Input, args: ['mode'] }], rowModel: [{ type: Input, args: ['rowModel'] }], contextMenuItems: [{ type: Input, args: ['contextMenuItems'] }], allowResize: [{ type: Input, args: ['allowResize'] }], allowSortColumn: [{ type: Input, args: ['allowSortColumn'] }], initializeFocus: [{ type: Input, args: ['initializeFocus'] }], allowFilterColumn: [{ type: Input, args: ['allowFilterColumn'] }], rowsPage: [{ type: Input, args: ['rowsPage'] }], rowHeight: [{ type: Input, args: ['rowHeight'] }], rowsClient: [{ type: Input, args: ['rowsClient'] }], height: [{ type: Input, args: ['height'] }], width: [{ type: Input, args: ['width'] }], globalFilter: [{ type: Input, args: ['globalFilter'] }], globalFilterOptions: [{ type: Input, args: ['globalFilterOptions'] }], rowSelect: [{ type: Output, args: ['rowSelect'] }], rowClick: [{ type: Output, args: ['rowClick'] }], rowDblclick: [{ type: Output, args: ['rowDblclick'] }], pageChange: [{ type: Output, args: ['pageChange'] }], sortData: [{ type: Output, args: ['sortData'] }], filterData: [{ type: Output, args: ['filterData'] }], loadData: [{ type: Output, args: ['loadData'] }], endRow: [{ type: Output, args: ['endRow'] }], datatableColumns: [{ type: ContentChildren, args: [TlDatatableColumn] }], tbody: [{ type: ViewChild, args: ['tbody', { static: true }] }], datatableBox: [{ type: ViewChild, args: ['datatableBox', { static: true }] }], datatableContent: [{ type: ViewChild, args: [TlDatatableContent, { static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXRhYmxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdHJ1bHktdWkvc3JjL2NvbXBvbmVudHMvZGF0YXRhYmxlL2RhdGF0YWJsZS50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2RhdGF0YWJsZS9kYXRhdGFibGUuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxlQUFlLEVBRWYsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBR04sU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXBFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ25GLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQzlFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQy9FLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLGlEQUFpRCxDQUFDO0FBQy9GLE9BQU8sRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDM0UsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDL0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7Ozs7Ozs7O0FBaUJ2RSxNQUFNLE9BQU8sV0FBVztJQXVFdEIsSUFBSSxPQUFPLENBQUUsS0FBSztRQUNoQixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztR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QkFFSyxVQUFVO3NCQUFqQyxNQUFNO3VCQUFFLFlBQVk7Z0JBRUMsUUFBUTtzQkFBN0IsTUFBTTt1QkFBRSxVQUFVO2dCQUVDLE1BQU07c0JBQXpCLE1BQU07dUJBQUUsUUFBUTtnQkFFcUIsZ0JBQWdCO3NCQUFyRCxlQUFlO3VCQUFFLGlCQUFpQjtnQkFFSyxLQUFLO3NCQUE1QyxTQUFTO3VCQUFFLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRVUsWUFBWTtzQkFBMUQsU0FBUzt1QkFBRSxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUVPLGdCQUFnQjtzQkFBbEUsU0FBUzt1QkFBRSxrQkFBa0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuIE1JVCBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMTkgVGVtYWluZm8gU29mdHdhcmVcblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cbmltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZHJlbixcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NoaWxkXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVGxEYXRhdGFibGVDb2x1bW4gfSBmcm9tICcuL3BhcnRzL2NvbHVtbi9kYXRhdGFibGUtY29sdW1uJztcbmltcG9ydCB7IERhdGF0YWJsZUZpbHRlck9wdGlvbnMgfSBmcm9tICcuL2NvbmZpZ3MvZGF0YXRhYmxlLWZpbHRlci1vcHRpb25zJztcbmltcG9ydCB7IEZpbHRlck9wdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9kYXRhdGFibGUtZmlsdGVyLW9wdGlvbnMuc2VydmljZSc7XG5pbXBvcnQgeyBUbERhdGF0YWJsZUZpbHRlclNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2RhdGF0YWJsZS1maWx0ZXIuc2VydmljZSc7XG5pbXBvcnQgeyBEYXRhdGFibGVEYXRhU291cmNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9kYXRhdGFibGUtZGF0YXNvdXJjZS5zZXJ2aWNlJztcbmltcG9ydCB7IFRsRGF0YXRhYmxlQ29sdW1uU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvZGF0YXRhYmxlLWNvbHVtbi5zZXJ2aWNlJztcbmltcG9ydCB7IFRsRGF0YXRhYmxlRmlsdGVyQ29uc3RyYWludHMgfSBmcm9tICcuL3NlcnZpY2VzL2RhdGF0YWJsZS1maWx0ZXItY29uc3RyYWludHMuc2VydmljZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUbERhdGF0YWJsZVNvcnRTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9kYXRhdGFibGUtc29ydC5zZXJ2aWNlJztcbmltcG9ydCB7IERhdGF0YWJsZUhlbHBlcnNTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9kYXRhdGFibGUtaGVscGVycy5zZXJ2aWNlJztcbmltcG9ydCB7IFRsRGF0YXRhYmxlQ29udGVudCB9IGZyb20gJy4vcGFydHMvY29udGVudC9kYXRhdGFibGUtY29udGVudCc7XG5pbXBvcnQgeyBDb250ZXh0TWVudUludGVyZmFjZSB9IGZyb20gJy4uL2NvbnRleHRtZW51L2ludGVyZmFjZXMvY29udGV4dC1tZW51LmludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoIHtcbiAgc2VsZWN0b3I6ICd0bC1kYXRhdGFibGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vZGF0YXRhYmxlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsgJy4vZGF0YXRhYmxlLnNjc3MnIF0sXG4gIHByb3ZpZGVyczogW1xuICAgIFRsRGF0YXRhYmxlQ29sdW1uU2VydmljZSxcbiAgICBUbERhdGF0YWJsZUZpbHRlckNvbnN0cmFpbnRzLFxuICAgIFRsRGF0YXRhYmxlRmlsdGVyU2VydmljZSxcbiAgICBUbERhdGF0YWJsZVNvcnRTZXJ2aWNlLFxuICAgIEZpbHRlck9wdGlvbnNTZXJ2aWNlLFxuICAgIERhdGF0YWJsZUhlbHBlcnNTZXJ2aWNlXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSApXG5leHBvcnQgY2xhc3MgVGxEYXRhdGFibGUgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0LCBPbkNoYW5nZXMge1xuXG4gIEBJbnB1dCggJ2RhdGEnICkgZGF0YTogQXJyYXk8YW55PjtcblxuICBASW5wdXQoICdyZWNvcmRzQ291bnQnICkgcmVjb3Jkc0NvdW50ID0gLTE7XG5cbiAgQElucHV0KCAnbW9kZScgKSBtb2RlOiAnc2Nyb2xsYWJsZScgfCAncGFnaW5hdG9yJyA9ICdzY3JvbGxhYmxlJztcblxuICBASW5wdXQoICdyb3dNb2RlbCcgKSByb3dNb2RlbDogJ2lubWVtb3J5JyB8ICdpbmZpbml0ZScgPSAnaW5tZW1vcnknO1xuXG4gIEBJbnB1dCggJ2NvbnRleHRNZW51SXRlbXMnICkgY29udGV4dE1lbnVJdGVtczogQ29udGV4dE1lbnVJbnRlcmZhY2VbXTtcblxuICBASW5wdXQoICdhbGxvd1Jlc2l6ZScgKSBhbGxvd1Jlc2l6ZSA9IGZhbHNlO1xuXG4gIEBJbnB1dCggJ2FsbG93U29ydENvbHVtbicgKSBhbGxvd1NvcnRDb2x1bW4gPSB0cnVlO1xuXG4gIEBJbnB1dCggJ2luaXRpYWxpemVGb2N1cycgKSBpbml0aWFsaXplRm9jdXMgPSB0cnVlO1xuXG4gIEBJbnB1dCggJ2FsbG93RmlsdGVyQ29sdW1uJyApIGFsbG93RmlsdGVyQ29sdW1uID0gZmFsc2U7XG5cbiAgQElucHV0KCAncm93c1BhZ2UnICkgcm93c1BhZ2UgPSAzMDtcblxuICBASW5wdXQoICdyb3dIZWlnaHQnICkgcm93SGVpZ2h0ID0gMjU7XG5cbiAgQElucHV0KCAncm93c0NsaWVudCcgKSByb3dzQ2xpZW50ID0gMTI7XG5cbiAgQElucHV0KCAnaGVpZ2h0JyApIGhlaWdodCA9IDMwMDtcblxuICBASW5wdXQoICd3aWR0aCcgKSB3aWR0aCA9IDMwMDtcblxuICBASW5wdXQoICdnbG9iYWxGaWx0ZXInICkgZ2xvYmFsRmlsdGVyOiBhbnk7XG5cbiAgQElucHV0KCAnZ2xvYmFsRmlsdGVyT3B0aW9ucycgKSBnbG9iYWxGaWx0ZXJPcHRpb25zOiBEYXRhdGFibGVGaWx0ZXJPcHRpb25zO1xuXG4gIEBPdXRwdXQoICdyb3dTZWxlY3QnICkgcm93U2VsZWN0OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCAncm93Q2xpY2snICkgcm93Q2xpY2s6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoICdyb3dEYmxjbGljaycgKSByb3dEYmxjbGljazogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCggJ3BhZ2VDaGFuZ2UnICkgcGFnZUNoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCggJ3NvcnREYXRhJyApIHNvcnREYXRhOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCAnZmlsdGVyRGF0YScgKSBmaWx0ZXJEYXRhOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCAnbG9hZERhdGEnICkgbG9hZERhdGE6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoICdlbmRSb3cnICkgZW5kUm93OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAQ29udGVudENoaWxkcmVuKCBUbERhdGF0YWJsZUNvbHVtbiApIGRhdGF0YWJsZUNvbHVtbnM6IFF1ZXJ5TGlzdDxUbERhdGF0YWJsZUNvbHVtbj47XG5cbiAgQFZpZXdDaGlsZCggJ3Rib2R5JywgeyBzdGF0aWM6IHRydWUgfSApIHRib2R5OiBFbGVtZW50UmVmO1xuXG4gIEBWaWV3Q2hpbGQoICdkYXRhdGFibGVCb3gnLCB7IHN0YXRpYzogdHJ1ZSB9ICkgZGF0YXRhYmxlQm94OiBFbGVtZW50UmVmO1xuXG4gIEBWaWV3Q2hpbGQoIFRsRGF0YXRhYmxlQ29udGVudCwgeyBzdGF0aWM6IHRydWUgfSApIGRhdGF0YWJsZUNvbnRlbnQ6IFRsRGF0YXRhYmxlQ29udGVudDtcblxuICBwdWJsaWMgZGF0YVNvdXJjZSA9IG5ldyBEYXRhdGFibGVEYXRhU291cmNlKCB0aGlzICk7XG5cbiAgcHVibGljIGNvbHVtbnM6IGFueVtdID0gW107XG5cbiAgcHVibGljIGhlaWdodFZpZXdQb3J0ID0gMDtcblxuICBwdWJsaWMgdGFiaW5kZXggPSAwO1xuXG4gIHB1YmxpYyBzY3JvbGxpbmdIb3Jpem9udGFsU3ViamVjdCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICBwcml2YXRlIGxvYWRpbmdTdWJqZWN0ID0gbmV3IFN1YmplY3Q8YW55PigpO1xuXG4gIHByaXZhdGUgX2xvYWRpbmcgPSBmYWxzZTtcbiAgc2V0IGxvYWRpbmcoIHZhbHVlICkge1xuICAgIHRoaXMuX2xvYWRpbmcgPSB2YWx1ZTtcbiAgICB0aGlzLmxvYWRpbmdTdWJqZWN0Lm5leHQoIHZhbHVlICk7XG4gIH1cblxuICBnZXQgbG9hZGluZygpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9hZGluZztcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKCBwdWJsaWMgY29sdW1uU2VydmljZTogVGxEYXRhdGFibGVDb2x1bW5TZXJ2aWNlLFxuICAgICAgICAgICAgICAgcHVibGljIGZpbHRlclNlcnZpY2U6IFRsRGF0YXRhYmxlRmlsdGVyU2VydmljZSxcbiAgICAgICAgICAgICAgIHB1YmxpYyBzb3J0U2VydmljZTogVGxEYXRhdGFibGVTb3J0U2VydmljZVxuICApIHt9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIHRoaXMuY2FsY0RpbWVuc2lvbnNIZWlnaHQoKTtcbiAgICB0aGlzLmNvbHVtblNlcnZpY2Uub25Jbml0Q29sdW1uU2VydmljZSggdGhpcyApO1xuICAgIHRoaXMuZmlsdGVyU2VydmljZS5vbkluaWNpYWxpemVGaWx0ZXJTZXJ2aWNlKCB0aGlzICk7XG4gICAgdGhpcy5zb3J0U2VydmljZS5vbkluaWNpYWxpemVTb3J0U2VydmljZSggdGhpcyApO1xuICAgIHRoaXMuY29sdW1uU2VydmljZS5zZXRDb2x1bW5zKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyggY2hhbmdlczogU2ltcGxlQ2hhbmdlcyApIHtcbiAgICAoIHRoaXMuZGF0YVNvdXJjZSBhcyBEYXRhdGFibGVEYXRhU291cmNlICkuY2hhbmdlcyggY2hhbmdlcyApO1xuICB9XG5cbiAgY2FsY0RpbWVuc2lvbnNIZWlnaHQoKSB7XG4gICAgdGhpcy5oZWlnaHRWaWV3UG9ydCA9IHRoaXMuYWxsb3dGaWx0ZXJDb2x1bW4gPyB0aGlzLmhlaWdodCAtIDMyIDogdGhpcy5oZWlnaHQ7XG4gICAgdGhpcy5oZWlnaHRWaWV3UG9ydCAtPSAyNTtcbiAgICB0aGlzLnJvd0hlaWdodCA9IHRoaXMuaGVpZ2h0Vmlld1BvcnQgLyB0aGlzLnJvd3NDbGllbnQ7XG4gIH1cblxuICBvblJvd0NsaWNrKCByb3csIGluZGV4ICkge1xuICAgIHRoaXMucm93Q2xpY2suZW1pdCggdGhpcy5nZXRPYmplY3RSb3coIHJvdywgaW5kZXggKSApO1xuICB9XG5cbiAgb25Sb3dTZWxlY3QoIHJvdywgaW5kZXggKSB7XG4gICAgdGhpcy5yb3dTZWxlY3QuZW1pdCggdGhpcy5nZXRPYmplY3RSb3coIHJvdywgaW5kZXggKSApO1xuICB9XG5cbiAgb25DaGFuZ2VGaWx0ZXIoIHZhbHVlICkge1xuICAgIHRoaXMuZmlsdGVyU2VydmljZS5zZXRGaWx0ZXIoIHZhbHVlICk7XG4gIH1cblxuICBvbkNoYW5nZVNvcnQoIHNvcnQgKSB7XG4gICAgdGhpcy5zb3J0U2VydmljZS5zZXRTb3J0KCBzb3J0KTtcbiAgfVxuXG4gIG9uS2V5ZG93bkZpbHRlciggZXZlbnQgKSB7XG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlLmtleWRvd25GaWx0ZXIubmV4dChldmVudCk7XG4gIH1cblxuICBvblJvd0RibGNsaWNrKCByb3csIGluZGV4ICkge1xuICAgIHRoaXMucm93RGJsY2xpY2suZW1pdCggdGhpcy5nZXRPYmplY3RSb3coIHJvdywgaW5kZXggKSApO1xuICB9XG5cbiAgc2V0Rm9jdXMoKSB7XG4gICAgdGhpcy5kYXRhdGFibGVDb250ZW50LnNldFNlbGVjdGVkSXRlbSgpO1xuICB9XG5cbiAgZ2V0U2Nyb2xsaW5nSG9yaXpvbnRhbCgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLnNjcm9sbGluZ0hvcml6b250YWxTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0T2JqZWN0Um93KCByb3csIGluZGV4ICkge1xuICAgIHJldHVybiB7IGRhdGE6IHJvdywgaW5kZXg6IGluZGV4IH07XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJ0bC1kYXRhdGFibGUtYm94XCIgI2RhdGF0YWJsZUJveFxuICAgICBbbmdDbGFzc109XCJ7Jy1ib3JkZXJsZWZ0JzogdHJ1ZX1cIlxuICAgICBbbmdTdHlsZV09XCJ7d2lkdGg6IHdpZHRofVwiPlxuICAgIDx0bC1kYXRhdGFibGUtaGVhZGVyIFtkdF09XCJ0aGlzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAoZmlsdGVyRXZlbnQpPVwib25DaGFuZ2VGaWx0ZXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgKHNvcnRFdmVudCk9XCJvbkNoYW5nZVNvcnQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgKGtleWRvd25GaWx0ZXJFdmVudCk9XCJvbktleWRvd25GaWx0ZXIoJGV2ZW50KVwiXG4gICAgPlxuICAgIDwvdGwtZGF0YXRhYmxlLWhlYWRlcj5cbiAgICA8dGwtZGF0YXRhYmxlLWNvbnRlbnRcbiAgICAgIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2VcIlxuICAgICAgW2RhdGFdPVwiZGF0YVwiXG4gICAgICBbcm93SGVpZ2h0XT1cInJvd0hlaWdodFwiXG4gICAgICBbaGVpZ2h0Vmlld1BvcnRdPVwiaGVpZ2h0Vmlld1BvcnRcIlxuICAgICAgW2NvbHVtbnNdPVwiY29sdW1uc1wiXG4gICAgICBbY29udGV4dE1lbnVJdGVtc109XCJjb250ZXh0TWVudUl0ZW1zXCJcbiAgICAgIChyb3dTZWxlY3QpPVwib25Sb3dTZWxlY3QoICRldmVudC5yb3csICRldmVudC5pbmRleCApXCJcbiAgICAgIChyb3dEYkNsaWNrKT1cIm9uUm93RGJsY2xpY2soICRldmVudC5yb3csICRldmVudC5pbmRleCApXCJcbiAgICAgIChyb3dDbGljayk9XCJvblJvd0NsaWNrKCAkZXZlbnQucm93LCAkZXZlbnQuaW5kZXggKVwiPlxuICAgIDwvdGwtZGF0YXRhYmxlLWNvbnRlbnQ+XG48L2Rpdj5cblxuIl19