UNPKG

dynamic-mat-table

Version:

dynamic-mat-table is an Angular component for presenting large and complex data with a lightning fast performance (at least 10x faster) and excellent level of control over the presentation.

181 lines 36.8 kB
import { ChangeDetectionStrategy, Component, Output, Input, EventEmitter, ViewChild, ElementRef, } from '@angular/core'; import { moveItemInArray } from '@angular/cdk/drag-drop'; import { TableService } from '../../dynamic-mat-table.service'; import { TableSetting } from '../../../models/table-setting.model'; import { TableIntl } from '../../../international/table-Intl'; import { deepClone, isNullorUndefined } from '../../../cores/type'; export class TableMenuComponent { constructor(languagePack, tableService) { this.languagePack = languagePack; this.tableService = tableService; this.menuActionChange = new EventEmitter(); this.tableSettingChange = new EventEmitter(); this.newSettingName = ''; this.showNewSetting = false; this.currentColumn = null; this.reverseDirection = null; } get tableSetting() { return this.currentTableSetting; } set tableSetting(value) { value.settingList = value.settingList === undefined ? [] : value.settingList; this.originalTableSetting = value; this.reverseDirection = value.direction === 'rtl' ? 'ltr' : 'rtl'; this.currentTableSetting = value; } get isSaveDataActive() { var _a; if (!((_a = this.tableSetting) === null || _a === void 0 ? void 0 : _a.visibleActionMenu)) { return false; } else { return (this.tableSetting.visibleActionMenu.csv !== false) || (this.tableSetting.visibleActionMenu.json !== false) || (this.tableSetting.visibleActionMenu.print !== false); } } screenMode_onClick() { this.menuActionChange.emit({ type: 'FullScreenMode', data: this.currentTableSetting, }); } /***** Column Setting ******/ columnMenuDropped(event) { moveItemInArray(this.currentTableSetting.columnSetting, event.item.data.columnIndex, event.currentIndex); } toggleSelectedColumn(column) { // const colFound = this.currentTableSetting.columnSetting.find(c => c === column); column.display = column.display === 'visible' ? 'hidden' : 'visible'; } apply_onClick(e) { e.stopPropagation(); e.preventDefault(); this.menuActionChange.emit({ type: 'TableSetting', data: this.currentTableSetting, }); this.tableService.saveColumnInfo(this.currentTableSetting.columnSetting); // setTimeout(() => { // this.menuActionChange.emit({ // type: 'TableSetting', // data: this.currentTableSetting, // }); // this.tableService.saveColumnInfo(this.currentTableSetting.columnSetting); // }); } setting_onClick(i) { this.currentColumn = i; } cancel_onClick() { this.currentTableSetting = deepClone(this.originalTableSetting); } isVisible(visible) { return isNullorUndefined(visible) ? true : visible; } /***** Save ********/ saveSetting_onClick(e, setting) { e.stopPropagation(); this.menuActionChange.emit({ type: 'SaveSetting', data: setting.settingName, }); } newSetting_onClick(e) { this.showNewSetting = true; this.newSettingName = ''; window.requestAnimationFrame(() => { this.newSettingElement.nativeElement.focus(); }); e.stopPropagation(); } selectSetting_onClick(e, setting) { e.stopPropagation(); this.menuActionChange.emit({ type: 'SelectSetting', data: setting.settingName, }); } resetDefault_onClick(e) { e.stopPropagation(); this.menuActionChange.emit({ type: 'SelectSetting', data: null, }); } default_onClick(e, setting) { e.stopPropagation(); this.menuActionChange.emit({ type: 'DefaultSetting', data: setting.settingName, }); } applySaveSetting_onClick(e) { e.stopPropagation(); this.menuActionChange.emit({ type: 'SaveSetting', data: this.newSettingName, }); this.showNewSetting = false; } cancelSaveSetting_onClick(e) { e.stopPropagation(); this.newSettingName = ''; this.showNewSetting = false; } deleteSetting_onClick(e, setting) { e.stopPropagation(); this.menuActionChange.emit({ type: 'DeleteSetting', data: setting }); this.newSettingName = ''; this.showNewSetting = false; } /***** Filter ********/ clearFilter_onClick() { setTimeout(() => { this.menuActionChange.emit({ type: 'FilterClear' }); }); } /******* Save File (JSON, CSV, Print)***********/ download_onClick(type) { setTimeout(() => { this.menuActionChange.emit({ type: 'Download', data: type }); }); } print_onClick(menu) { menu._overlayRef._host.parentElement.click(); setTimeout(() => { this.menuActionChange.emit({ type: 'Print', data: null }); }); } } /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */ TableMenuComponent.decorators = [ { type: Component, args: [{ // tslint:disable-next-line: component-selector selector: 'table-menu', template: "<button class=\"clear\" type=\"button\" mat-icon-button #menuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"menu\"\r\n [dir]=\"reverseDirection\">\r\n <mat-icon class=\"main-menu\">more_vert</mat-icon>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" [overlapTrigger]=\"false\" [dir]=\"reverseDirection\">\r\n <button mat-menu-item type=\"button\" *ngIf=\"tableSetting?.visibleActionMenu?.fullscreen!= false\" (click)=\"screenMode_onClick()\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>fullscreen</mat-icon>\r\n <span>{{ languagePack.menuLabels.fullScreen }}</span>\r\n </button>\r\n <button mat-menu-item type=\"button\" color=\"primary\" [matMenuTriggerFor]=\"convertMenu\" *ngIf=\"isSaveDataActive\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>save</mat-icon>\r\n <span>{{ languagePack.menuLabels.saveData }}</span>\r\n </button>\r\n <button mat-menu-item type=\"button\" color=\"primary\" [matMenuTriggerFor]=\"columnMenu\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>view_column</mat-icon>\r\n <span>{{ languagePack.menuLabels.columnSetting }}</span>\r\n </button>\r\n\r\n <button mat-menu-item type=\"button\" *ngIf=\"currentTableSetting?.saveSettingMode === 'simple'\"\r\n (click)=\"saveSetting_onClick($event, null)\" [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>grading</mat-icon>\r\n <span>{{ languagePack.menuLabels.saveTableSetting }}</span>\r\n </button>\r\n <button mat-menu-item *ngIf=\"currentTableSetting?.saveSettingMode === 'multi'\" [matMenuTriggerFor]=\"saveTableSetting\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>grading</mat-icon>\r\n <span>{{ languagePack.menuLabels.saveTableSetting }}</span>\r\n </button>\r\n <button mat-menu-item type=\"button\" (click)=\"clearFilter_onClick()\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>clear</mat-icon>\r\n <span>{{ languagePack.menuLabels.clearFilter }}</span>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Save Table Config Menu -->\r\n\r\n<mat-menu #saveTableSetting=\"matMenu\">\r\n <button mat-menu-item type=\"button\" (click)=\"newSetting_onClick($event)\" *ngIf=\"showNewSetting === false\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>tune</mat-icon>\r\n <span>{{languagePack.menuLabels.newSetting }}</span>\r\n </button>\r\n <section *ngIf=\"showNewSetting === true\" class=\"new-setting\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"input-container\">\r\n <input matInput type=\"text\" #newSetting [placeholder]=\"languagePack.menuLabels.newSetting\"\r\n [(ngModel)]=\"newSettingName\" (keydown.enter)=\"applySaveSetting_onClick($event)\">\r\n </div>\r\n <div class=\"save-table-setting\">\r\n <mat-icon (click)=\"cancelSaveSetting_onClick($event)\">close</mat-icon>\r\n <mat-icon (click)=\"applySaveSetting_onClick($event)\">done</mat-icon>\r\n </div>\r\n </section>\r\n <mat-divider></mat-divider>\r\n\r\n <button mat-menu-item type=\"button\" (click)=\"resetDefault_onClick($event)\" [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <mat-icon>settings_backup_restore</mat-icon>\r\n {{ languagePack.menuLabels.defaultSetting }}\r\n </button>\r\n\r\n <section *ngFor=\"let setting of tableSetting?.settingList\" class=\"setting-item\"\r\n [class.setting-item-active]=\"setting?.isCurrentSetting == true\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <button mat-icon-button type=\"button\" (click)=\"default_onClick($event, setting)\">\r\n <mat-icon style=\"color: #dcc48f;\">{{ (setting?.isDefaultSetting == true) ? 'star' : 'star_outline'}} </mat-icon>\r\n </button>\r\n <span (click)=\"selectSetting_onClick($event, setting)\">{{setting.settingName}}</span>\r\n <mat-icon (click)=\"saveSetting_onClick($event, setting)\">save</mat-icon>\r\n <mat-icon style=\"color: #ff4081;\" (click)=\"deleteSetting_onClick($event, setting)\">delete</mat-icon>\r\n </section>\r\n <section *ngIf=\"tableSetting?.settingList?.length === 0\" mat-menu-item (click)=\"$event.stopPropagation()\">\r\n <mat-icon style=\"color: #dcc48f;\">lightbulb</mat-icon>\r\n {{languagePack.menuLabels.noSetting}}\r\n </section>\r\n</mat-menu>\r\n\r\n<!-- Convert Sub Menu -->\r\n\r\n<mat-menu #convertMenu=\"matMenu\">\r\n <button mat-menu-item type=\"button\" *ngIf=\"tableSetting?.visibleActionMenu?.json != false\" (click)=\"download_onClick('JSON')\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <span>{{ languagePack.menuLabels.jsonFile }}</span>\r\n </button>\r\n <button mat-menu-item type=\"button\" *ngIf=\"tableSetting?.visibleActionMenu?.csv != false\" (click)=\"download_onClick('CSV')\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <span>{{ languagePack.menuLabels.csvFile }}</span>\r\n </button>\r\n <button mat-menu-item type=\"button\" *ngIf=\"tableSetting?.visibleActionMenu?.print != false\" (click)=\"print_onClick(menuTrigger)\"\r\n [class.ltr-menu]=\"currentTableSetting.direction !== 'rtl'\">\r\n <span>{{ languagePack.menuLabels.printTable }}</span>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Column Setting Sub Menu -->\r\n\r\n<mat-menu #columnMenu=\"matMenu\">\r\n <ng-container *ngIf=\"currentTableSetting?.columnSetting?.length > 0; else noColumns\">\r\n <div class=\"va-mat-table-dragable-container\" cdkDropList dkDropListLockAxis=\"y\" cdkDropListOrientation=\"vertical\"\r\n dir=\"ltr\">\r\n <div *ngFor=\"let column of currentTableSetting?.columnSetting; let i = index\"\r\n (click)=\"$event.stopPropagation(); $event.preventDefault()\" class=\"dragable-row\" cdkDrag\r\n [cdkDragData]=\"{ columnIndex: i, columnTitle: column.header }\" (cdkDragDropped)=\"columnMenuDropped($event)\">\r\n <mat-icon cdkDragHandle>drag_indicator</mat-icon>\r\n <mat-checkbox class=\"column-config\" [disabled]=\"column?.display === 'prevent-hidden'\"\r\n [checked]=\"column?.display === 'visible' || column?.display === 'prevent-hidden'\"\r\n (click)=\"$event.stopPropagation()\" (change)=\"toggleSelectedColumn(column)\">\r\n {{ column.header }}\r\n </mat-checkbox>\r\n <mat-icon class=\"column-setting-button\" (click)=\"setting_onClick(i)\" #menuTrigger=\"matMenuTrigger\"\r\n [matMenuTriggerFor]=\"columnSettingMenu\">settings</mat-icon>\r\n <div class=\"va-mat-table-drag-preview\" *cdkDragPreview>\r\n <mat-icon>drag_indicator</mat-icon>\r\n <mat-checkbox [checked]=\"column?.display === 'visible'\">\r\n {{ column.header }}\r\n </mat-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"column-config-apply\">\r\n <button mat-menu-item type=\"button\" color=\"primary\" class=\"done-setting\" (click)=\"apply_onClick($event)\">\r\n <mat-icon color=\"primary\">done</mat-icon>\r\n </button>\r\n <button mat-menu-item type=\"button\" color=\"primary\" class=\"done-setting\" (click)=\"cancel_onClick()\">\r\n <mat-icon color=\"primary\">clear</mat-icon>\r\n </button>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #noColumns>\r\n <div mat-menu-item>\r\n {{ languagePack.menuLabels.thereIsNoColumn }}\r\n </div>\r\n </ng-template>\r\n</mat-menu>\r\n\r\n<mat-menu #columnSettingMenu=\"matMenu\" [overlapTrigger]=\"false\" style=\"padding: 10px !important\">\r\n <div *ngIf=\"currentColumn !== null\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\r\n class=\"column-setting\">\r\n <ng-container *ngIf=\"isVisible(currentTableSetting?.visibleActionMenu?.columnSettingFilter)\">\r\n <div class=\"column-setting-header column-setting-header-first\">\r\n <mat-icon color=\"primary\">filter_alt</mat-icon>{{ languagePack.menuLabels.filterMode }}\r\n </div>\r\n <mat-radio-group class=\"radio\" [(ngModel)]=\"currentTableSetting.columnSetting[currentColumn].filter\">\r\n <mat-radio-button value='client-side' (click)=\"$event.stopPropagation()\">{{\r\n languagePack.menuLabels.filterLocalMode }}</mat-radio-button>\r\n <mat-radio-button value='server-side' (click)=\"$event.stopPropagation()\">{{\r\n languagePack.menuLabels.filterServerMode }}</mat-radio-button>\r\n </mat-radio-group>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"isVisible(currentTableSetting?.visibleActionMenu?.columnSettingSort)\">\r\n <div class=\"column-setting-header\">\r\n <mat-icon color=\"primary\">sort</mat-icon>{{ languagePack.menuLabels.sortMode }}\r\n </div>\r\n <mat-radio-group class=\"radio\" [(ngModel)]=\"currentTableSetting.columnSetting[currentColumn].sort\">\r\n <mat-radio-button value='client-side' (click)=\"$event.stopPropagation()\">{{\r\n languagePack.menuLabels.sortLocalMode }}</mat-radio-button>\r\n <mat-radio-button value='server-side' (click)=\"$event.stopPropagation()\">{{\r\n languagePack.menuLabels.sortServerMode }}</mat-radio-button>\r\n </mat-radio-group>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"isVisible(currentTableSetting?.visibleActionMenu?.columnSettingFilter)\">\r\n <div class=\"column-setting-header\">\r\n <mat-icon color=\"primary\">print</mat-icon>{{ languagePack.menuLabels.printMode }}\r\n </div>\r\n <mat-radio-group class=\"radio\" [(ngModel)]=\"currentTableSetting.columnSetting[currentColumn].printable\">\r\n <mat-radio-button [value]=\"true\" (click)=\"$event.stopPropagation()\">{{ languagePack.menuLabels.printYesMode }}\r\n </mat-radio-button>\r\n <mat-radio-button [value]=\"false\" (click)=\"$event.stopPropagation()\">{{ languagePack.menuLabels.printNoMode }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"isVisible(currentTableSetting?.visibleActionMenu?.columnSettingPin)\">\r\n <div class=\"column-setting-header\">\r\n <mat-icon color=\"primary\">push_pin</mat-icon>{{ languagePack.menuLabels.pinMode }}\r\n </div>\r\n <mat-radio-group class=\"radio\" [(ngModel)]=\"currentTableSetting.columnSetting[currentColumn].sticky\">\r\n <mat-radio-button value='none' (click)=\"$event.stopPropagation()\">{{ languagePack.menuLabels.pinNoneMode }}\r\n </mat-radio-button>\r\n <mat-radio-button value='start' (click)=\"$event.stopPropagation()\">{{ languagePack.menuLabels.pinStartMode }}\r\n </mat-radio-button>\r\n <mat-radio-button value='end' (click)=\"$event.stopPropagation()\">{{ languagePack.menuLabels.pinEndMode }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n </ng-container>\r\n </div>\r\n</mat-menu>\r\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;align-items:center;justify-content:space-between}.ltr-menu span{float:left}.main-menu{width:38px!important;line-height:24px!important}.va-mat-button-no-input{border:none;background-color:transparent;outline:none}.va-mat-table-dragable-container{min-width:200px;padding:8px 0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.va-mat-table-dragable-container:dir(rtl){background-color:green!important}.dragable-row mat-checkbox{width:calc(100% - 54px);line-height:28px;display:inline-flex}.va-mat-table-dragable-container .dragable-row{background-color:#fff;display:flex;width:100%;height:30px;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.column-setting-button{cursor:pointer!important;font-size:24px;margin-right:5px}.new-setting{text-align:center;margin-left:0;margin-top:0;align-items:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none;border:none;line-height:48px;height:48px;display:flex;flex-wrap:nowrap;width:100%;padding:0 16px;box-sizing:border-box}.new-setting .input-container{overflow:hidden}.new-setting input{line-height:33px;background-color:#fff;border:none;padding-left:5px;border-radius:4px;outline:none;text-align:center;direction:ltr}.setting-item{line-height:48px;display:inline-flex;flex-direction:row;align-items:center;width:100%;font-size:14px}.setting-item mat-icon{width:38px;height:38px;line-height:38px;color:#0000008a;cursor:pointer;text-align:center;border-radius:50%}.setting-item mat-icon:hover{background-color:#dbdbdb}.setting-item span{cursor:pointer;width:154px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:list-item}.setting-item-active{background-color:#fdd78a}::ng-deep .mat-menu-panel{min-height:auto!important}.save-table-setting{display:flex;min-width:70px}.save-table-setting mat-icon{width:32px;height:32px;line-height:32px;cursor:pointer}.delete-table-setting{position:absolute;cursor:pointer;line-height:38px!important;height:38px;width:38px;border-radius:100%;text-align:center;pointer-events:none;margin-top:5px}.delete-table-setting:hover{color:#fff;background-color:#afafaf}.va-mat-table-dragable-container .dragable-row mat-icon{line-height:30px;opacity:.15;transition:opacity .5s;color:#616161;cursor:grab;background-color:#fff}.va-mat-table-dragable-container .dragable-row:hover mat-icon{opacity:1}.va-mat-table-drag-preview{direction:ltr;background-color:#ececec;padding:4px 8px 4px 4px!important;cursor:grabbing!important;margin-top:-4px;margin-left:-4px;font-size:14px;border-radius:5px}.va-mat-table-drag-preview mat-icon,.va-mat-table-drag-preview mat-checkbox{vertical-align:top}.va-mat-table-drag-preview mat-icon{padding-left:4px;color:#616161}.cdk-drop-list-dragging .cdk-drag{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-animating{transition:transform .3s cubic-bezier(0,0,.2,1)}.done-setting{width:50%!important;display:inline-flex;text-align:center;height:42px}.done-setting mat-icon{line-height:38px!important;opacity:.6;transition:opacity .5s;color:#616161;width:100%;text-align:center;margin:0}.done-setting mat-icon:hover{opacity:1}.column-setting{font-family:Roboto,\"Helvetica Neue\",sans-serif;padding:10px}.column-setting .radio{width:100%;display:flex;font-size:12px;margin-top:-2px}.column-setting .radio mat-radio-button{padding:5px;width:50%}.column-setting .radio mat-radio-button:last-child{margin-right:10px}.column-setting .column-setting-header{line-height:30px;padding:5px 5px 0;font-size:14px;border-top:1px solid #f3f3f3;margin-top:5px}.column-setting .column-setting-header mat-icon{opacity:.7;font-size:22px;line-height:30px;float:right;color:#616161}.column-setting-header:first-child{border-top:none!important;padding:0 5px!important;margin-top:-5px!important}.first-menu-item{width:100px;display:inline-block;text-align:left}::ng-deep [dir=rtl] .mat-checkbox-inner-container{margin-left:auto!important;margin-right:5px!important}.mat-menu-item{display:inline-flex;width:100%;box-sizing:border-box}.mat-menu-item span{width:100%}.mat-menu-item mat-icon{line-height:48px!important;height:48px}::ng-deep .column-config .mat-checkbox-layout{width:100%}::ng-deep .column-config .mat-checkbox-layout .mat-checkbox-label{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.column-config-apply{border-top:1px solid #e7e7e7;position:sticky;bottom:0px;z-index:2147483647;background-color:#fff}\n"] },] } ]; /** * @type {function(): !Array<(null|{ * type: ?, * decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>), * })>} * @nocollapse */ TableMenuComponent.ctorParameters = () => [ { type: TableIntl }, { type: TableService } ]; /** @type {!Object<string, !Array<{type: !Function, args: (undefined|!Array<?>)}>>} */ TableMenuComponent.propDecorators = { menuActionChange: [{ type: Output }], tableSetting: [{ type: Input }], tableSettingChange: [{ type: Output }], newSettingElement: [{ type: ViewChild, args: ['newSetting', { static: false },] }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtbWVudS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9keW5hbWljLW1hdC10YWJsZS9zcmMvbGliL2R5bmFtaWMtbWF0LXRhYmxlL2V4dGVuc2lvbnMvdGFibGUtbWVudS90YWJsZS1tZW51LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUNBLEVBQ0UsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxNQUFNLEVBQ04sS0FBSyxFQUNMLFlBQVksRUFDWixTQUFTLEVBQ1QsVUFBVSxHQUNYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxlQUFlLEVBQWMsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRSxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0saUNBQWlDLENBQUM7QUFDN0QsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLHFDQUFxQyxDQUFDO0FBQ2pFLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUM1RCxPQUFPLEVBQUMsU0FBUyxFQUFFLGlCQUFpQixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFVakUsTUFBTSxPQUFPLGtCQUFrQjtJQXNDN0IsWUFDUyxZQUF1QixFQUN2QixZQUEwQjtRQUQxQixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN2QixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQXZDekIscUJBQWdCLEdBQ3hCLElBQUksWUFBWSxFQUF5QixDQUFDO1FBeUJsQyx1QkFBa0IsR0FBRyxJQUFJLFlBQVksRUFBZ0IsQ0FBQztRQUdoRSxtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUNwQixtQkFBYyxHQUFHLEtBQUssQ0FBQztRQUV2QixrQkFBYSxHQUFXLElBQUksQ0FBQztRQUM3QixxQkFBZ0IsR0FBVyxJQUFJLENBQUM7SUFRaEMsQ0FBQztJQXRDRCxJQUNJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxtQkFBbUIs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YSxDQUFDLElBQUk7UUFDaEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzdDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztRQUMxRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Ozs7WUF4TEYsU0FBUyxTQUFDO2dCQUNULCtDQUErQztnQkFDL0MsUUFBUSxFQUFFLFlBQVk7Z0JBQ3RCLHN4VkFBMEM7Z0JBRTFDLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNOzthQUNoRDs7Ozs7Ozs7OztZQVZPLFNBQVM7WUFGVCxZQUFZOzs7OytCQWNqQixNQUFNOzJCQUdOLEtBQUs7aUNBdUJMLE1BQU07Z0NBQ04sU0FBUyxTQUFDLFlBQVksRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnRcclxue1xyXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxyXG4gIENvbXBvbmVudCxcclxuICBPdXRwdXQsXHJcbiAgSW5wdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge21vdmVJdGVtSW5BcnJheSwgQ2RrRHJhZ0Ryb3B9IGZyb20gJ0Bhbmd1bGFyL2Nkay9kcmFnLWRyb3AnO1xyXG5pbXBvcnQge1RhYmxlU2VydmljZX0gZnJvbSAnLi4vLi4vZHluYW1pYy1tYXQtdGFibGUuc2VydmljZSc7XHJcbmltcG9ydCB7VGFibGVTZXR0aW5nfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvdGFibGUtc2V0dGluZy5tb2RlbCc7XHJcbmltcG9ydCB7VGFibGVJbnRsfSBmcm9tICcuLi8uLi8uLi9pbnRlcm5hdGlvbmFsL3RhYmxlLUludGwnO1xyXG5pbXBvcnQge2RlZXBDbG9uZSwgaXNOdWxsb3JVbmRlZmluZWR9IGZyb20gJy4uLy4uLy4uL2NvcmVzL3R5cGUnO1xyXG5pbXBvcnQge0Fic3RyYWN0RmllbGR9IGZyb20gJy4uLy4uLy4uL21vZGVscy90YWJsZS1maWVsZC5tb2RlbCc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IGNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAndGFibGUtbWVudScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RhYmxlLW1lbnUuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RhYmxlLW1lbnUuY29tcG9uZW50LnNjc3MnXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIFRhYmxlTWVudUNvbXBvbmVudCB7XHJcbiAgQE91dHB1dCgpIG1lbnVBY3Rpb25DaGFuZ2U6IEV2ZW50RW1pdHRlcjxUYWJsZU1lbnVBY3Rpb25DaGFuZ2U+ID1cclxuICAgIG5ldyBFdmVudEVtaXR0ZXI8VGFibGVNZW51QWN0aW9uQ2hhbmdlPigpO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGdldCB0YWJsZVNldHRpbmcoKTogVGFibGVTZXR0aW5nIHtcclxuICAgIHJldHVybiB0aGlzLmN1cnJlbnRUYWJsZVNldHRpbmc7XHJcbiAgfVxyXG5cclxuICBzZXQgdGFibGVTZXR0aW5nKHZhbHVlOiBUYWJsZVNldHRpbmcpIHtcclxuICAgIHZhbHVlLnNldHRpbmdMaXN0ID1cclxuICAgICAgdmFsdWUuc2V0dGluZ0xpc3QgPT09IHVuZGVmaW5lZCA/IFtdIDogdmFsdWUuc2V0dGluZ0xpc3Q7XHJcbiAgICB0aGlzLm9yaWdpbmFsVGFibGVTZXR0aW5nID0gdmFsdWU7XHJcbiAgICB0aGlzLnJldmVyc2VEaXJlY3Rpb24gPSB2YWx1ZS5kaXJlY3Rpb24gPT09ICdydGwnID8gJ2x0cicgOiAncnRsJztcclxuICAgIHRoaXMuY3VycmVudFRhYmxlU2V0dGluZyA9IHZhbHVlO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGlzU2F2ZURhdGFBY3RpdmUoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIXRoaXMudGFibGVTZXR0aW5nPy52aXNpYmxlQWN0aW9uTWVudSkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gKHRoaXMudGFibGVTZXR0aW5nLnZpc2libGVBY3Rpb25NZW51LmNzdiAhPT0gZmFsc2UpXHJcbiAgICAgICAgfHwgKHRoaXMudGFibGVTZXR0aW5nLnZpc2libGVBY3Rpb25NZW51Lmpzb24gIT09IGZhbHNlKVxyXG4gICAgICAgIHx8ICh0aGlzLnRhYmxlU2V0dGluZy52aXNpYmxlQWN0aW9uTWVudS5wcmludCAhPT0gZmFsc2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQE91dHB1dCgpIHRhYmxlU2V0dGluZ0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8VGFibGVTZXR0aW5nPigpO1xyXG4gIEBWaWV3Q2hpbGQoJ25ld1NldHRpbmcnLCB7c3RhdGljOiBmYWxzZX0pIG5ld1NldHRpbmdFbGVtZW50OiBFbGVtZW50UmVmO1xyXG5cclxuICBuZXdTZXR0aW5nTmFtZSA9ICcnO1xyXG4gIHNob3dOZXdTZXR0aW5nID0gZmFsc2U7XHJcblxyXG4gIGN1cnJlbnRDb2x1bW46IG51bWJlciA9IG51bGw7XHJcbiAgcmV2ZXJzZURpcmVjdGlvbjogc3RyaW5nID0gbnVsbDtcclxuICBvcmlnaW5hbFRhYmxlU2V0dGluZzogVGFibGVTZXR0aW5nO1xyXG4gIGN1cnJlbnRUYWJsZVNldHRpbmc6IFRhYmxlU2V0dGluZztcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwdWJsaWMgbGFuZ3VhZ2VQYWNrOiBUYWJsZUludGwsXHJcbiAgICBwdWJsaWMgdGFibGVTZXJ2aWNlOiBUYWJsZVNlcnZpY2VcclxuICApIHtcclxuICB9XHJcblxyXG4gIHNjcmVlbk1vZGVfb25DbGljaygpIHtcclxuICAgIHRoaXMubWVudUFjdGlvbkNoYW5nZS5lbWl0KHtcclxuICAgICAgdHlwZTogJ0Z1bGxTY3JlZW5Nb2RlJyxcclxuICAgICAgZGF0YTogdGhpcy5jdXJyZW50VGFibGVTZXR0aW5nLFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKioqKiogQ29sdW1uIFNldHRpbmcgKioqKioqL1xyXG4gIGNvbHVtbk1lbnVEcm9wcGVkKGV2ZW50OiBDZGtEcmFnRHJvcDxhbnk+KTogdm9pZCB7XHJcbiAgICBtb3ZlSXRlbUluQXJyYXkoXHJcbiAgICAgIHRoaXMuY3VycmVudFRhYmxlU2V0dGluZy5jb2x1bW5TZXR0aW5nLFxyXG4gICAgICBldmVudC5pdGVtLmRhdGEuY29sdW1uSW5kZXgsXHJcbiAgICAgIGV2ZW50LmN1cnJlbnRJbmRleFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHRvZ2dsZVNlbGVjdGVkQ29sdW1uKGNvbHVtbjogQWJzdHJhY3RGaWVsZCkge1xyXG4gICAgLy8gY29uc3QgY29sRm91bmQgPSB0aGlzLmN1cnJlbnRUYWJsZVNldHRpbmcuY29sdW1uU2V0dGluZy5maW5kKGMgPT4gYyA9PT0gY29sdW1uKTtcclxuICAgIGNvbHVtbi5kaXNwbGF5ID0gY29sdW1uLmRpc3BsYXkgPT09ICd2aXNpYmxlJyA/ICdoaWRkZW4nIDogJ3Zpc2libGUnO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlfb25DbGljayhlKSB7XHJcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgdGhpcy5tZW51QWN0aW9uQ2hhbmdlLmVtaXQoe1xyXG4gICAgICB0eXBlOiAnVGFibGVTZXR0aW5nJyxcclxuICAgICAgZGF0YTogdGhpcy5jdXJyZW50VGFibGVTZXR0aW5nLFxyXG4gICAgfSk7XHJcbiAgICB0aGlzLnRhYmxlU2VydmljZS5zYXZlQ29sdW1uSW5mbyh0aGlzLmN1cnJlbnRUYWJsZVNldHRpbmcuY29sdW1uU2V0dGluZyk7XHJcbiAgICAvLyBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgIC8vICAgdGhpcy5tZW51QWN0aW9uQ2hhbmdlLmVtaXQoe1xyXG4gICAgLy8gICAgIHR5cGU6ICdUYWJsZVNldHRpbmcnLFxyXG4gICAgLy8gICAgIGRhdGE6IHRoaXMuY3VycmVudFRhYmxlU2V0dGluZyxcclxuICAgIC8vICAgfSk7XHJcbiAgICAvLyAgIHRoaXMudGFibGVTZXJ2aWNlLnNhdmVDb2x1bW5JbmZvKHRoaXMuY3VycmVudFRhYmxlU2V0dGluZy5jb2x1bW5TZXR0aW5nKTtcclxuICAgIC8vIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0dGluZ19vbkNsaWNrKGkpIHtcclxuICAgIHRoaXMuY3VycmVudENvbHVtbiA9IGk7XHJcbiAgfVxyXG5cclxuICBjYW5jZWxfb25DbGljaygpIHtcclxuICAgIHRoaXMuY3VycmVudFRhYmxlU2V0dGluZyA9IGRlZXBDbG9uZSh0aGlzLm9yaWdpbmFsVGFibGVTZXR0aW5nKTtcclxuICB9XHJcblxyXG4gIGlzVmlzaWJsZSh2aXNpYmxlOiBib29sZWFuKSB7XHJcbiAgICByZXR1cm4gaXNOdWxsb3JVbmRlZmluZWQodmlzaWJsZSkgPyB0cnVlIDogdmlzaWJsZTtcclxuICB9XHJcblxyXG4gIC8qKioqKiAgU2F2ZSAqKioqKioqKi9cclxuICBzYXZlU2V0dGluZ19vbkNsaWNrKGUsIHNldHRpbmcpIHtcclxuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICB0aGlzLm1lbnVBY3Rpb25DaGFuZ2UuZW1pdCh7XHJcbiAgICAgIHR5cGU6ICdTYXZlU2V0dGluZycsXHJcbiAgICAgIGRhdGE6IHNldHRpbmcuc2V0dGluZ05hbWUsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG5ld1NldHRpbmdfb25DbGljayhlKSB7XHJcbiAgICB0aGlzLnNob3dOZXdTZXR0aW5nID0gdHJ1ZTtcclxuICAgIHRoaXMubmV3U2V0dGluZ05hbWUgPSAnJztcclxuICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG4gICAgICB0aGlzLm5ld1NldHRpbmdFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICAgIH0pO1xyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICB9XHJcblxyXG4gIHNlbGVjdFNldHRpbmdfb25DbGljayhlLCBzZXR0aW5nOiBUYWJsZVNldHRpbmcpIHtcclxuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICB0aGlzLm1lbnVBY3Rpb25DaGFuZ2UuZW1pdCh7XHJcbiAgICAgIHR5cGU6ICdTZWxlY3RTZXR0aW5nJyxcclxuICAgICAgZGF0YTogc2V0dGluZy5zZXR0aW5nTmFtZSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmVzZXREZWZhdWx0X29uQ2xpY2soZSkge1xyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMubWVudUFjdGlvbkNoYW5nZS5lbWl0KHtcclxuICAgICAgdHlwZTogJ1NlbGVjdFNldHRpbmcnLFxyXG4gICAgICBkYXRhOiBudWxsLFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBkZWZhdWx0X29uQ2xpY2soZSwgc2V0dGluZykge1xyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMubWVudUFjdGlvbkNoYW5nZS5lbWl0KHtcclxuICAgICAgdHlwZTogJ0RlZmF1bHRTZXR0aW5nJyxcclxuICAgICAgZGF0YTogc2V0dGluZy5zZXR0aW5nTmFtZSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlTYXZlU2V0dGluZ19vbkNsaWNrKGUpIHtcclxuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICB0aGlzLm1lbnVBY3Rpb25DaGFuZ2UuZW1pdCh7XHJcbiAgICAgIHR5cGU6ICdTYXZlU2V0dGluZycsXHJcbiAgICAgIGRhdGE6IHRoaXMubmV3U2V0dGluZ05hbWUsXHJcbiAgICB9KTtcclxuICAgIHRoaXMuc2hvd05ld1NldHRpbmcgPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIGNhbmNlbFNhdmVTZXR0aW5nX29uQ2xpY2soZSkge1xyXG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMubmV3U2V0dGluZ05hbWUgPSAnJztcclxuICAgIHRoaXMuc2hvd05ld1NldHRpbmcgPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIGRlbGV0ZVNldHRpbmdfb25DbGljayhlLCBzZXR0aW5nKSB7XHJcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgdGhpcy5tZW51QWN0aW9uQ2hhbmdlLmVtaXQoe3R5cGU6ICdEZWxldGVTZXR0aW5nJywgZGF0YTogc2V0dGluZ30pO1xyXG4gICAgdGhpcy5uZXdTZXR0aW5nTmFtZSA9ICcnO1xyXG4gICAgdGhpcy5zaG93TmV3U2V0dGluZyA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqKioqICBGaWx0ZXIgKioqKioqKiovXHJcbiAgY2xlYXJGaWx0ZXJfb25DbGljaygpIHtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLm1lbnVBY3Rpb25DaGFuZ2UuZW1pdCh7dHlwZTogJ0ZpbHRlckNsZWFyJ30pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKioqKioqKiBTYXZlIEZpbGUgKEpTT04sIENTViwgUHJpbnQpKioqKioqKioqKiovXHJcbiAgZG93bmxvYWRfb25DbGljayh0eXBlOiBzdHJpbmcpIHtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLm1lbnVBY3Rpb25DaGFuZ2UuZW1pdCh7dHlwZTogJ0Rvd25sb2FkJywgZGF0YTogdHlwZX0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcmludF9vbkNsaWNrKG1lbnUpIHtcclxuICAgIG1lbnUuX292ZXJsYXlSZWYuX2hvc3QucGFyZW50RWxlbWVudC5jbGljaygpO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMubWVudUFjdGlvbkNoYW5nZS5lbWl0KHt0eXBlOiAnUHJpbnQnLCBkYXRhOiBudWxsfSk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVNZW51QWN0aW9uQ2hhbmdlIHtcclxuICB0eXBlOlxyXG4gICAgfCAnRmlsdGVyQ2xlYXInXHJcbiAgICB8ICdUYWJsZVNldHRpbmcnXHJcbiAgICB8ICdEb3dubG9hZCdcclxuICAgIHwgJ1NhdmVTZXR0aW5nJ1xyXG4gICAgfCAnRGVsZXRlU2V0dGluZydcclxuICAgIHwgJ1NlbGVjdFNldHRpbmcnXHJcbiAgICB8ICdEZWZhdWx0U2V0dGluZydcclxuICAgIHwgJ1ByaW50J1xyXG4gICAgfCAnRnVsbFNjcmVlbk1vZGUnO1xyXG4gIGRhdGE/OiBhbnk7XHJcbn1cclxuIl19