UNPKG

@angular-generic-table/column-settings

Version:

angular-generic-table extension that makes it easy to toggle column visibility and reoder columns.

338 lines (332 loc) 33.7 kB
import { __assign, __spread, __read } from 'tslib'; import { Component, Input, ViewChild, Pipe, ChangeDetectorRef, HostListener, Output, EventEmitter, NgModule } from '@angular/core'; import { GenericTableModule } from '@angular-generic-table/core'; import { DragulaService, DragulaModule } from 'ng2-dragula'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var GtColumnPipe = /** @class */ (function () { function GtColumnPipe() { } /** * Sort by column order * @param {?} a * @param {?} b * @return {?} */ GtColumnPipe.prototype.getColumnOrder = /** * Sort by column order * @param {?} a * @param {?} b * @return {?} */ function (a, b) { if (a.columnOrder < b.columnOrder) { return -1; } if (a.columnOrder > b.columnOrder || typeof a.columnOrder === 'undefined') { return 1; } return 0; }; /** * return enabled columns that are not locked for editing * @param {?} column * @return {?} */ GtColumnPipe.prototype.getEnabled = /** * return enabled columns that are not locked for editing * @param {?} column * @return {?} */ function (column) { return column.enabled !== false && column.lockSettings !== true ? column : null; }; /** * @param {?} settings * @return {?} */ GtColumnPipe.prototype.transform = /** * @param {?} settings * @return {?} */ function (settings) { return settings.filter(this.getEnabled).sort(this.getColumnOrder); }; GtColumnPipe.decorators = [ { type: Pipe, args: [{ name: 'gtColumn' },] }, ]; return GtColumnPipe; }()); var GtColumnSettingsComponent = /** @class */ (function () { function GtColumnSettingsComponent(dragulaService, changeDetectorRef) { var _this = this; this.dragulaService = dragulaService; this.changeDetectorRef = changeDetectorRef; this.gtHeaderClasses = 'px-3 pt-3 pb-2 table-bordered border-left-0 border-right-0 border-bottom-0 alert-info'; this.gtWrapperClasses = 'px-3 pb-3 table-bordered border-left-0 border-right-0 border-top-0 alert-info'; this.overlay = true; this.gtDefaultTexts = { title: 'Columns', help: 'Double click to toggle visibility, drag and drop to reorder.' }; this.gtTexts = this.gtDefaultTexts; this.gtEvent = new EventEmitter(); this.active = false; this.reordered = false; /** * Extend object function. */ this.extend = function (a, b) { for (var /** @type {?} */ key in b) { if (b.hasOwnProperty(key)) { a[key] = b[key]; } } return a; }; dragulaService.drop.subscribe(function (value) { if (value[0] === _this.bagId) { _this._onDrop(value.slice(1)); } }); } Object.defineProperty(GtColumnSettingsComponent.prototype, "genericTable", { get: /** * @return {?} */ function () { return this._genericTable; }, set: /** * @param {?} value * @return {?} */ function (value) { this._genericTable = value; }, enumerable: true, configurable: true }); /** * Check offset height on window resize. * @return {?} */ GtColumnSettingsComponent.prototype.onResize = /** * Check offset height on window resize. * @return {?} */ function () { this.offset = this._getTableHeadHeight(); this.heightAdjust = this._getColumnSettingsHeaderHeight(); }; /** * @return {?} */ GtColumnSettingsComponent.prototype.ngOnInit = /** * @return {?} */ function () { this.bagId = this.generateId(); // setup texts this.gtTexts = /** @type {?} */ (this.extend(this.gtDefaultTexts, this.gtTexts)); }; /** * Toggle column settings visibility. * @return {?} */ GtColumnSettingsComponent.prototype.toggleColumnSettings = /** * Toggle column settings visibility. * @return {?} */ function () { var _this = this; this.active = !this.active; if (this.active) { this.offset = this._getTableHeadHeight(); // check and adjust height offset setTimeout(function () { _this.heightAdjust = _this._getColumnSettingsHeaderHeight(); }, 0); } }; /** * Toggle column visibility. * @param {?} column - column object. * @return {?} */ GtColumnSettingsComponent.prototype.toggleColumnVisibility = /** * Toggle column visibility. * @param {?} column - column object. * @return {?} */ function (column) { var _this = this; // toggle column visibility column.visible = typeof column.visible === 'undefined' ? false : !column.visible; // redraw table this._genericTable.redraw(); // emit event this.gtEvent.emit({ name: 'gt-column-visibility-change', value: { column: __assign({}, column), settings: __spread(this._genericTable.gtSettings) } }); // check and reset offset setTimeout(function () { _this.offset = _this._getTableHeadHeight(); }, 0); }; /** * Order table by object key. * @param {?} args - name of key to sort on. * @return {?} */ GtColumnSettingsComponent.prototype._onDrop = /** * Order table by object key. * @param {?} args - name of key to sort on. * @return {?} */ function (args) { this.reordered = true; var _a = __read(args, 2), e = _a[0], target = _a[1]; var /** @type {?} */ order = {}; for (var /** @type {?} */ i = 0; i < target.children.length; i++) { order[target.children[i].getAttribute('data-object-key')] = i; } for (var /** @type {?} */ i = 0; i < this._genericTable.gtSettings.length; i++) { this._genericTable.gtSettings[i].columnOrder = order[this._genericTable.gtSettings[i].objectKey]; } // reset array to trigger change detection this._genericTable.gtSettings = __spread(this._genericTable.gtSettings); this.changeDetectorRef.markForCheck(); this._genericTable.redraw(); this.gtEvent.emit({ name: 'gt-column-order-change', value: { settings: __spread(this._genericTable.gtSettings) } }); }; /** * Get height of table head element ie. first row containing table headers. * @return {?} offset height for table header in px. */ GtColumnSettingsComponent.prototype._getTableHeadHeight = /** * Get height of table head element ie. first row containing table headers. * @return {?} offset height for table header in px. */ function () { try { if (this.elementView.elementRef.nativeElement.nextElementSibling .firstElementChild.firstElementChild.tagName === 'THEAD') { return (this.elementView.elementRef.nativeElement.nextElementSibling .firstElementChild.firstElementChild.offsetHeight + 'px'); } if (this.elementView.elementRef.nativeElement.nextElementSibling .firstElementChild.firstElementChild.firstElementChild.tagName === 'THEAD') { return (this.elementView.elementRef.nativeElement.nextElementSibling .firstElementChild.firstElementChild.firstElementChild .offsetHeight + 'px'); } return '0px'; } catch (/** @type {?} */ error) { return '0px'; } }; /** * Get height of table head element ie. first row containing table headers. * @return {?} offset height for table header in px. */ GtColumnSettingsComponent.prototype._getColumnSettingsHeaderHeight = /** * Get height of table head element ie. first row containing table headers. * @return {?} offset height for table header in px. */ function () { try { return this.gtColumnSettingsHeader.nativeElement.offsetHeight + 'px'; } catch (/** @type {?} */ error) { return '0px'; } }; /** * generate a unique id for dragula instance i.e. a unique bag name * @return {?} */ GtColumnSettingsComponent.prototype.generateId = /** * generate a unique id for dragula instance i.e. a unique bag name * @return {?} */ function () { var /** @type {?} */ d = new Date().getTime(); return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var /** @type {?} */ r = ((d + Math.random() * 16) % 16) | 0; d = Math.floor(d / 16); return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16); }); }; GtColumnSettingsComponent.decorators = [ { type: Component, args: [{ selector: 'gt-column-settings', template: "\n <ng-template #columnItem let-column let-index=\"index\">\n <span class=\"badge badge-secondary\">{{index}}</span>\n <span (dblclick)=\"toggleColumnVisibility(column)\" class=\"badge\" [ngClass]=\"{'badge-success':column.visible !== false, 'badge-danger':column.visible === false}\">{{genericTable.gtFields | gtProperty:column.objectKey:'name'}}</span>\n </ng-template>\n <div class=\"gt-column-settings\">\n <div class=\"gt-column-settings-panel\" *ngIf=\"active\" [style.padding-top]=\"offset\" [style.height]=\"'calc(100% - '+offset+')'\">\n <div #gtColumnSettingsHeader class=\"gt-column-settings-header border-bottom-0\" [ngClass]=\"gtHeaderClasses\">\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"toggleColumnSettings()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n <h6 class=\"gt-column-settings-title\" *ngIf=\"gtTexts.title\">{{gtTexts.title}}</h6>\n <small class=\"gt-column-settings-help form-text text-muted\" *ngIf=\"gtTexts.help\">{{gtTexts.help}}</small>\n </div>\n <div class=\"gt-column-settings-item-wrapper\" [ngClass]=\"gtWrapperClasses\" [dragula]='bagId' data-visible=\"true\" [style.max-height]=\"'calc(100% - '+heightAdjust+')'\">\n <div class=\"gt-column-settings-item pr-0 pr-sm-4\" *ngFor=\"let i = index;let column of genericTable.gtSettings | gtColumn\" [attr.data-object-key]=\"column.objectKey\">\n <ng-template [ngTemplateOutlet]=\"gtColumnItem ? gtColumnItem:columnItem\" [ngTemplateOutletContext]=\"{$implicit: column,index: this.reordered ? column.columnOrder+1:i+1, name: (genericTable.gtFields | gtProperty:column.objectKey:'name')}\"></ng-template>\n </div>\n </div>\n <div class=\"gt-overlay\" *ngIf=\"active && overlay\" (click)=\"toggleColumnSettings()\" [style.height]=\"'calc(100% - -'+offset+')'\"></div>\n </div>\n <ng-template #genericTableElement [ngIf]=\"genericTable\">\n <ng-content></ng-content>\n </ng-template>\n </div>\n " },] }, ]; /* tslint:enable */ /** @nocollapse */ GtColumnSettingsComponent.ctorParameters = function () { return [ { type: DragulaService, }, { type: ChangeDetectorRef, }, ]; }; GtColumnSettingsComponent.propDecorators = { "genericTable": [{ type: Input },], "elementView": [{ type: ViewChild, args: ['genericTableElement',] },], "gtColumnSettingsHeader": [{ type: ViewChild, args: ['gtColumnSettingsHeader',] },], "gtHeaderClasses": [{ type: Input },], "gtWrapperClasses": [{ type: Input },], "overlay": [{ type: Input },], "gtColumnItem": [{ type: Input },], "gtTexts": [{ type: Input },], "gtEvent": [{ type: Output },], "onResize": [{ type: HostListener, args: ['window:resize', [],] },], }; return GtColumnSettingsComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var ColumnSettingsModule = /** @class */ (function () { function ColumnSettingsModule() { } ColumnSettingsModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, GenericTableModule, DragulaModule], declarations: [GtColumnSettingsComponent, GtColumnPipe], exports: [GtColumnSettingsComponent, GtColumnPipe] },] }, ]; return ColumnSettingsModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { ColumnSettingsModule, GtColumnPipe as ɵa, GtColumnSettingsComponent as ɵb }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1nZW5lcmljLXRhYmxlLWNvbHVtbi1zZXR0aW5ncy5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGFuZ3VsYXItZ2VuZXJpYy10YWJsZS9jb2x1bW4tc2V0dGluZ3MvY29tcG9uZW50cy9ndC1jb2x1bW4tc2V0dGluZ3MuY29tcG9uZW50LnRzIiwibmc6Ly9AYW5ndWxhci1nZW5lcmljLXRhYmxlL2NvbHVtbi1zZXR0aW5ncy9jb2x1bW4tc2V0dGluZ3MubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0SW5wdXQsXG5cdFZpZXdDaGlsZCxcblx0VGVtcGxhdGVSZWYsXG5cdEVsZW1lbnRSZWYsXG5cdFBpcGUsXG5cdFBpcGVUcmFuc2Zvcm0sXG5cdE9uSW5pdCxcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdEhvc3RMaXN0ZW5lcixcblx0T3V0cHV0LFxuXHRFdmVudEVtaXR0ZXJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuXHRHZW5lcmljVGFibGVDb21wb25lbnQsXG5cdEd0Um93LFxuXHRHdENvbmZpZ1NldHRpbmdcbn0gZnJvbSAnQGFuZ3VsYXItZ2VuZXJpYy10YWJsZS9jb3JlJztcbmltcG9ydCB7IERyYWd1bGFTZXJ2aWNlIH0gZnJvbSAnbmcyLWRyYWd1bGEnO1xuaW1wb3J0IHsgR3RDb2x1bW5TZXR0aW5nc1RleHRzIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9ndC1jb2x1bW4tc2V0dGluZ3MtdGV4dHMnO1xuXG5AUGlwZSh7XG5cdG5hbWU6ICdndENvbHVtbidcbn0pXG5leHBvcnQgY2xhc3MgR3RDb2x1bW5QaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG5cdC8vIFRPRE86IG1vdmUgdG8gaGVscGVyIGZ1bmN0aW9uc1xuXHQvKiogU29ydCBieSBjb2x1bW4gb3JkZXIgKi9cblx0cHJpdmF0ZSBnZXRDb2x1bW5PcmRlcihhOiBhbnksIGI6IGFueSkge1xuXHRcdGlmIChhLmNvbHVtbk9yZGVyIDwgYi5jb2x1bW5PcmRlcikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH1cblx0XHRpZiAoYS5jb2x1bW5PcmRlciA+IGIuY29sdW1uT3JkZXIgfHwgdHlwZW9mIGEuY29sdW1uT3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdFx0cmV0dXJuIDA7XG5cdH1cblxuXHQvKiogcmV0dXJuIGVuYWJsZWQgY29sdW1ucyB0aGF0IGFyZSBub3QgbG9ja2VkIGZvciBlZGl0aW5nICovXG5cdHByaXZhdGUgZ2V0RW5hYmxlZChjb2x1bW46IEd0Q29uZmlnU2V0dGluZykge1xuXHRcdHJldHVybiBjb2x1bW4uZW5hYmxlZCAhPT0gZmFsc2UgJiYgY29sdW1uLmxvY2tTZXR0aW5ncyAhPT0gdHJ1ZVxuXHRcdFx0PyBjb2x1bW5cblx0XHRcdDogbnVsbDtcblx0fVxuXG5cdHRyYW5zZm9ybShzZXR0aW5nczogQXJyYXk8R3RDb25maWdTZXR0aW5nPik6IEFycmF5PEd0Q29uZmlnU2V0dGluZz4ge1xuXHRcdHJldHVybiBzZXR0aW5ncy5maWx0ZXIodGhpcy5nZXRFbmFibGVkKS5zb3J0KHRoaXMuZ2V0Q29sdW1uT3JkZXIpO1xuXHR9XG59XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ2d0LWNvbHVtbi1zZXR0aW5ncycsXG5cdHRlbXBsYXRlOiBgXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjY29sdW1uSXRlbSBsZXQtY29sdW1uIGxldC1pbmRleD1cImluZGV4XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJhZGdlLXNlY29uZGFyeVwiPnt7aW5kZXh9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIChkYmxjbGljayk9XCJ0b2dnbGVDb2x1bW5WaXNpYmlsaXR5KGNvbHVtbilcIiBjbGFzcz1cImJhZGdlXCIgW25nQ2xhc3NdPVwieydiYWRnZS1zdWNjZXNzJzpjb2x1bW4udmlzaWJsZSAhPT0gZmFsc2UsICdiYWRnZS1kYW5nZXInOmNvbHVtbi52aXNpYmxlID09PSBmYWxzZX1cIj57e2dlbmVyaWNUYWJsZS5ndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZSd9fTwvc3Bhbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5nc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy1wYW5lbFwiICAqbmdJZj1cImFjdGl2ZVwiIFtzdHlsZS5wYWRkaW5nLXRvcF09XCJvZmZzZXRcIiBbc3R5bGUuaGVpZ2h0XT1cIidjYWxjKDEwMCUgLSAnK29mZnNldCsnKSdcIj5cbiAgICAgICAgICAgICAgICA8ZGl2ICNndENvbHVtblNldHRpbmdzSGVhZGVyIGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLWhlYWRlciBib3JkZXItYm90dG9tLTBcIiBbbmdDbGFzc109XCJndEhlYWRlckNsYXNzZXNcIj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjbG9zZVwiIGFyaWEtbGFiZWw9XCJDbG9zZVwiIChjbGljayk9XCJ0b2dnbGVDb2x1bW5TZXR0aW5ncygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4mdGltZXM7PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGg2IGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLXRpdGxlXCIgKm5nSWY9XCJndFRleHRzLnRpdGxlXCI+e3tndFRleHRzLnRpdGxlfX08L2g2PlxuICAgICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtaGVscCBmb3JtLXRleHQgdGV4dC1tdXRlZFwiICpuZ0lmPVwiZ3RUZXh0cy5oZWxwXCI+e3tndFRleHRzLmhlbHB9fTwvc21hbGw+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy1pdGVtLXdyYXBwZXJcIiBbbmdDbGFzc109XCJndFdyYXBwZXJDbGFzc2VzXCIgW2RyYWd1bGFdPSdiYWdJZCcgIGRhdGEtdmlzaWJsZT1cInRydWVcIiBbc3R5bGUubWF4LWhlaWdodF09XCInY2FsYygxMDAlIC0gJytoZWlnaHRBZGp1c3QrJyknXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtaXRlbSBwci0wIHByLXNtLTRcIiAqbmdGb3I9XCJsZXQgaSA9IGluZGV4O2xldCBjb2x1bW4gb2YgZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3MgfCBndENvbHVtblwiIFthdHRyLmRhdGEtb2JqZWN0LWtleV09XCJjb2x1bW4ub2JqZWN0S2V5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwiZ3RDb2x1bW5JdGVtID8gZ3RDb2x1bW5JdGVtOmNvbHVtbkl0ZW1cIiBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyRpbXBsaWNpdDogY29sdW1uLGluZGV4OiB0aGlzLnJlb3JkZXJlZCA/IGNvbHVtbi5jb2x1bW5PcmRlcisxOmkrMSwgbmFtZTogKGdlbmVyaWNUYWJsZS5ndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZScpfVwiPjwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1vdmVybGF5XCIgKm5nSWY9XCJhY3RpdmUgJiYgb3ZlcmxheVwiIChjbGljayk9XCJ0b2dnbGVDb2x1bW5TZXR0aW5ncygpXCIgW3N0eWxlLmhlaWdodF09XCInY2FsYygxMDAlIC0gLScrb2Zmc2V0KycpJ1wiPjwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgI2dlbmVyaWNUYWJsZUVsZW1lbnQgW25nSWZdPVwiZ2VuZXJpY1RhYmxlXCI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9kaXY+XG4gICAgYFxufSlcbmV4cG9ydCBjbGFzcyBHdENvbHVtblNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblx0Z2V0IGdlbmVyaWNUYWJsZSgpOiBHZW5lcmljVGFibGVDb21wb25lbnQ8YW55LCBhbnk+IHtcblx0XHRyZXR1cm4gdGhpcy5fZ2VuZXJpY1RhYmxlO1xuXHR9XG5cblx0QElucHV0KClcblx0c2V0IGdlbmVyaWNUYWJsZSh2YWx1ZTogR2VuZXJpY1RhYmxlQ29tcG9uZW50PGFueSwgYW55Pikge1xuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZSA9IHZhbHVlO1xuXHR9XG5cblx0QFZpZXdDaGlsZCgnZ2VuZXJpY1RhYmxlRWxlbWVudCcpIGVsZW1lbnRWaWV3OiBUZW1wbGF0ZVJlZjxFbGVtZW50UmVmPjtcblx0QFZpZXdDaGlsZCgnZ3RDb2x1bW5TZXR0aW5nc0hlYWRlcicpIGd0Q29sdW1uU2V0dGluZ3NIZWFkZXI6IEVsZW1lbnRSZWY7XG5cblx0cHJpdmF0ZSBfZ2VuZXJpY1RhYmxlOiBHZW5lcmljVGFibGVDb21wb25lbnQ8R3RSb3csIGFueT47XG5cdEBJbnB1dCgpXG5cdGd0SGVhZGVyQ2xhc3NlcyA9ICdweC0zIHB0LTMgcGItMiB0YWJsZS1ib3JkZXJlZCBib3JkZXItbGVmdC0wIGJvcmRlci1yaWdodC0wIGJvcmRlci1ib3R0b20tMCBhbGVydC1pbmZvJztcblx0QElucHV0KClcblx0Z3RXcmFwcGVyQ2xhc3NlcyA9ICdweC0zIHBiLTMgdGFibGUtYm9yZGVyZWQgYm9yZGVyLWxlZnQtMCBib3JkZXItcmlnaHQtMCBib3JkZXItdG9wLTAgYWxlcnQtaW5mbyc7XG5cdEBJbnB1dCgpIG92ZXJsYXkgPSB0cnVlO1xuXHRASW5wdXQoKSBndENvbHVtbkl0ZW06IFRlbXBsYXRlUmVmPEVsZW1lbnRSZWY+O1xuXHRwdWJsaWMgZ3REZWZhdWx0VGV4dHM6IEd0Q29sdW1uU2V0dGluZ3NUZXh0cyA9IHtcblx0XHR0aXRsZTogJ0NvbHVtbnMnLFxuXHRcdGhlbHA6ICdEb3VibGUgY2xpY2sgdG8gdG9nZ2xlIHZpc2liaWxpdHksIGRyYWcgYW5kIGRyb3AgdG8gcmVvcmRlci4nXG5cdH07XG5cdEBJbnB1dCgpIGd0VGV4dHM6IEd0Q29sdW1uU2V0dGluZ3NUZXh0cyA9IHRoaXMuZ3REZWZhdWx0VGV4dHM7XG5cblx0QE91dHB1dCgpIHB1YmxpYyBndEV2ZW50OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG5cdHB1YmxpYyBhY3RpdmUgPSBmYWxzZTtcblx0cHVibGljIG9mZnNldDogc3RyaW5nO1xuXHRwdWJsaWMgaGVpZ2h0QWRqdXN0OiBzdHJpbmc7XG5cdHB1YmxpYyByZW9yZGVyZWQgPSBmYWxzZTtcblx0cHVibGljIGJhZ0lkOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIENoZWNrIG9mZnNldCBoZWlnaHQgb24gd2luZG93IHJlc2l6ZS5cblx0ICovXG5cdEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbXSlcblx0cHVibGljIG9uUmVzaXplKCkge1xuXHRcdHRoaXMub2Zmc2V0ID0gdGhpcy5fZ2V0VGFibGVIZWFkSGVpZ2h0KCk7XG5cdFx0dGhpcy5oZWlnaHRBZGp1c3QgPSB0aGlzLl9nZXRDb2x1bW5TZXR0aW5nc0hlYWRlckhlaWdodCgpO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSBkcmFndWxhU2VydmljZTogRHJhZ3VsYVNlcnZpY2UsXG5cdFx0cHJpdmF0ZSBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWZcblx0KSB7XG5cdFx0ZHJhZ3VsYVNlcnZpY2UuZHJvcC5zdWJzY3JpYmUoKHZhbHVlOiBBcnJheTxhbnk+KSA9PiB7XG5cdFx0XHRpZiAodmFsdWVbMF0gPT09IHRoaXMuYmFnSWQpIHtcblx0XHRcdFx0dGhpcy5fb25Ecm9wKHZhbHVlLnNsaWNlKDEpKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdG5nT25Jbml0KCkge1xuXHRcdHRoaXMuYmFnSWQgPSB0aGlzLmdlbmVyYXRlSWQoKTtcblx0XHQvLyBzZXR1cCB0ZXh0c1xuXHRcdHRoaXMuZ3RUZXh0cyA9IDxHdENvbHVtblNldHRpbmdzVGV4dHM+dGhpcy5leHRlbmQoXG5cdFx0XHR0aGlzLmd0RGVmYXVsdFRleHRzLFxuXHRcdFx0dGhpcy5ndFRleHRzXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiAgRXh0ZW5kIG9iamVjdCBmdW5jdGlvbi5cblx0ICovXG5cdHByaXZhdGUgZXh0ZW5kID0gZnVuY3Rpb24oYTogT2JqZWN0LCBiOiBPYmplY3QpIHtcblx0XHRmb3IgKGNvbnN0IGtleSBpbiBiKSB7XG5cdFx0XHRpZiAoYi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG5cdFx0XHRcdGFba2V5XSA9IGJba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGE7XG5cdH07XG5cblx0LyoqXG5cdCAqIFRvZ2dsZSBjb2x1bW4gc2V0dGluZ3MgdmlzaWJpbGl0eS5cblx0ICovXG5cdHB1YmxpYyB0b2dnbGVDb2x1bW5TZXR0aW5ncygpIHtcblx0XHR0aGlzLmFjdGl2ZSA9ICF0aGlzLmFjdGl2ZTtcblxuXHRcdGlmICh0aGlzLmFjdGl2ZSkge1xuXHRcdFx0dGhpcy5vZmZzZXQgPSB0aGlzLl9nZXRUYWJsZUhlYWRIZWlnaHQoKTtcblxuXHRcdFx0Ly8gY2hlY2sgYW5kIGFkanVzdCBoZWlnaHQgb2Zmc2V0XG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0dGhpcy5oZWlnaHRBZGp1c3QgPSB0aGlzLl9nZXRDb2x1bW5TZXR0aW5nc0hlYWRlckhlaWdodCgpO1xuXHRcdFx0fSwgMCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRvZ2dsZSBjb2x1bW4gdmlzaWJpbGl0eS5cblx0ICogQHBhcmFtIGNvbHVtbiAtIGNvbHVtbiBvYmplY3QuXG5cdCAqL1xuXHRwdWJsaWMgdG9nZ2xlQ29sdW1uVmlzaWJpbGl0eShjb2x1bW46IGFueSkge1xuXHRcdC8vIHRvZ2dsZSBjb2x1bW4gdmlzaWJpbGl0eVxuXHRcdGNvbHVtbi52aXNpYmxlID1cblx0XHRcdHR5cGVvZiBjb2x1bW4udmlzaWJsZSA9PT0gJ3VuZGVmaW5lZCcgPyBmYWxzZSA6ICFjb2x1bW4udmlzaWJsZTtcblxuXHRcdC8vIHJlZHJhdyB0YWJsZVxuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5yZWRyYXcoKTtcblxuXHRcdC8vIGVtaXQgZXZlbnRcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtY29sdW1uLXZpc2liaWxpdHktY2hhbmdlJyxcblx0XHRcdHZhbHVlOiB7XG5cdFx0XHRcdGNvbHVtbjogeyAuLi5jb2x1bW4gfSxcblx0XHRcdFx0c2V0dGluZ3M6IFsuLi50aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc11cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIGNoZWNrIGFuZCByZXNldCBvZmZzZXRcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMub2Zmc2V0ID0gdGhpcy5fZ2V0VGFibGVIZWFkSGVpZ2h0KCk7XG5cdFx0fSwgMCk7XG5cdH1cblxuXHQvKipcblx0ICogT3JkZXIgdGFibGUgYnkgb2JqZWN0IGtleS5cblx0ICogQHBhcmFtIGFyZ3MgLSBuYW1lIG9mIGtleSB0byBzb3J0IG9uLlxuXHQgKi9cblx0cHJpdmF0ZSBfb25Ecm9wKGFyZ3M6IEFycmF5PGFueT4pIHtcblx0XHR0aGlzLnJlb3JkZXJlZCA9IHRydWU7XG5cdFx0Y29uc3QgW2UsIHRhcmdldF0gPSBhcmdzO1xuXHRcdGNvbnN0IG9yZGVyID0ge307XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXQuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcblx0XHRcdG9yZGVyW3RhcmdldC5jaGlsZHJlbltpXS5nZXRBdHRyaWJ1dGUoJ2RhdGEtb2JqZWN0LWtleScpXSA9IGk7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzW2ldLmNvbHVtbk9yZGVyID1cblx0XHRcdFx0b3JkZXJbdGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3NbaV0ub2JqZWN0S2V5XTtcblx0XHR9XG5cblx0XHQvLyByZXNldCBhcnJheSB0byB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb25cblx0XHR0aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5ncyA9IFsuLi50aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc107XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblxuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5yZWRyYXcoKTtcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtY29sdW1uLW9yZGVyLWNoYW5nZScsXG5cdFx0XHR2YWx1ZToge1xuXHRcdFx0XHRzZXR0aW5nczogWy4uLnRoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzXVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBoZWlnaHQgb2YgdGFibGUgaGVhZCBlbGVtZW50IGllLiBmaXJzdCByb3cgY29udGFpbmluZyB0YWJsZSBoZWFkZXJzLlxuXHQgKiBAcmV0dXJucyBvZmZzZXQgaGVpZ2h0IGZvciB0YWJsZSBoZWFkZXIgaW4gcHguXG5cdCAqL1xuXHRwcml2YXRlIF9nZXRUYWJsZUhlYWRIZWlnaHQoKTogc3RyaW5nIHtcblx0XHR0cnkge1xuXHRcdFx0aWYgKFxuXHRcdFx0XHR0aGlzLmVsZW1lbnRWaWV3LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmdcblx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQudGFnTmFtZSA9PT0gJ1RIRUFEJ1xuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiAoXG5cdFx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQub2Zmc2V0SGVpZ2h0ICsgJ3B4J1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKFxuXHRcdFx0XHR0aGlzLmVsZW1lbnRWaWV3LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmdcblx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQudGFnTmFtZSA9PT1cblx0XHRcdFx0J1RIRUFEJ1xuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiAoXG5cdFx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGRcblx0XHRcdFx0XHRcdC5vZmZzZXRIZWlnaHQgKyAncHgnXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gJzBweCc7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdHJldHVybiAnMHB4Jztcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGhlaWdodCBvZiB0YWJsZSBoZWFkIGVsZW1lbnQgaWUuIGZpcnN0IHJvdyBjb250YWluaW5nIHRhYmxlIGhlYWRlcnMuXG5cdCAqIEByZXR1cm5zIG9mZnNldCBoZWlnaHQgZm9yIHRhYmxlIGhlYWRlciBpbiBweC5cblx0ICovXG5cdHByaXZhdGUgX2dldENvbHVtblNldHRpbmdzSGVhZGVySGVpZ2h0KCk6IHN0cmluZyB7XG5cdFx0dHJ5IHtcblx0XHRcdHJldHVybiB0aGlzLmd0Q29sdW1uU2V0dGluZ3NIZWFkZXIubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQgKyAncHgnO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRyZXR1cm4gJzBweCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqIGdlbmVyYXRlIGEgdW5pcXVlIGlkIGZvciBkcmFndWxhIGluc3RhbmNlIGkuZS4gYSB1bmlxdWUgYmFnIG5hbWUqL1xuXHQvKiB0c2xpbnQ6ZGlzYWJsZSAqL1xuXHRwcml2YXRlIGdlbmVyYXRlSWQoKSB7XG5cdFx0bGV0IGQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblx0XHRyZXR1cm4gJ3h4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eCcucmVwbGFjZSgvW3h5XS9nLCBmdW5jdGlvbihjKSB7XG5cdFx0XHRjb25zdCByID0gKChkICsgTWF0aC5yYW5kb20oKSAqIDE2KSAlIDE2KSB8IDA7XG5cdFx0XHRkID0gTWF0aC5mbG9vcihkIC8gMTYpO1xuXHRcdFx0cmV0dXJuIChjID09PSAneCcgPyByIDogKHIgJiAweDMpIHwgMHg4KS50b1N0cmluZygxNik7XG5cdFx0fSk7XG5cdH1cblx0LyogdHNsaW50OmVuYWJsZSAqL1xufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuXHRHdENvbHVtblBpcGUsXG5cdEd0Q29sdW1uU2V0dGluZ3NDb21wb25lbnRcbn0gZnJvbSAnLi9jb21wb25lbnRzL2d0LWNvbHVtbi1zZXR0aW5ncy5jb21wb25lbnQnO1xuaW1wb3J0IHsgR2VuZXJpY1RhYmxlTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXItZ2VuZXJpYy10YWJsZS9jb3JlJztcbmltcG9ydCB7IERyYWd1bGFNb2R1bGUgfSBmcm9tICduZzItZHJhZ3VsYSc7XG5cbkBOZ01vZHVsZSh7XG5cdGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEdlbmVyaWNUYWJsZU1vZHVsZSwgRHJhZ3VsYU1vZHVsZV0sXG5cdGRlY2xhcmF0aW9uczogW0d0Q29sdW1uU2V0dGluZ3NDb21wb25lbnQsIEd0Q29sdW1uUGlwZV0sXG5cdGV4cG9ydHM6IFtHdENvbHVtblNldHRpbmdzQ29tcG9uZW50LCBHdENvbHVtblBpcGVdXG59KVxuZXhwb3J0IGNsYXNzIENvbHVtblNldHRpbmdzTW9kdWxlIHt9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztJQTRCUyxxQ0FBYzs7Ozs7O2NBQUMsQ0FBTSxFQUFFLENBQU07UUFDcEMsSUFBSSxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUU7WUFDbEMsT0FBTyxDQUFDLENBQUMsQ0FBQztTQUNWO1FBQ0QsSUFBSSxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLElBQUksT0FBTyxDQUFDLENBQUMsV0FBVyxLQUFLLFdBQVcsRUFBRTtZQUMxRSxPQUFPLENBQUMsQ0FBQztTQUNUO1FBQ0QsT0FBTyxDQUFDLENBQUM7Ozs7Ozs7SUFJRixpQ0FBVTs7Ozs7Y0FBQyxNQUF1QjtRQUN6QyxPQUFPLE1BQU0sQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUFJLE1BQU0sQ0FBQyxZQUFZLEtBQUssSUFBSTtjQUM1RCxNQUFNO2NBQ04sSUFBSSxDQUFDOzs7Ozs7SUFHVCxnQ0FBUzs7OztJQUFULFVBQVUsUUFBZ0M7UUFDekMsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0tBQ2xFOztnQkF6QkQs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