@angular-generic-table/column-settings
Version:
angular-generic-table extension that makes it easy to toggle column visibility and reoder columns.
335 lines (334 loc) • 32.6 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Component, Input, ViewChild, TemplateRef, ElementRef, Pipe, ChangeDetectorRef, HostListener, Output, EventEmitter } from '@angular/core';
import { GenericTableComponent } from '@angular-generic-table/core';
import { DragulaService } from 'ng2-dragula';
export class GtColumnPipe {
/**
* Sort by column order
* @param {?} a
* @param {?} b
* @return {?}
*/
getColumnOrder(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 {?}
*/
getEnabled(column) {
return column.enabled !== false && column.lockSettings !== true
? column
: null;
}
/**
* @param {?} settings
* @return {?}
*/
transform(settings) {
return settings.filter(this.getEnabled).sort(this.getColumnOrder);
}
}
GtColumnPipe.decorators = [
{ type: Pipe, args: [{
name: 'gtColumn'
},] },
];
function GtColumnPipe_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
GtColumnPipe.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
GtColumnPipe.ctorParameters;
}
export class GtColumnSettingsComponent {
/**
* @param {?} dragulaService
* @param {?} changeDetectorRef
*/
constructor(dragulaService, changeDetectorRef) {
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 (const /** @type {?} */ key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
};
dragulaService.drop.subscribe((value) => {
if (value[0] === this.bagId) {
this._onDrop(value.slice(1));
}
});
}
/**
* @return {?}
*/
get genericTable() {
return this._genericTable;
}
/**
* @param {?} value
* @return {?}
*/
set genericTable(value) {
this._genericTable = value;
}
/**
* Check offset height on window resize.
* @return {?}
*/
onResize() {
this.offset = this._getTableHeadHeight();
this.heightAdjust = this._getColumnSettingsHeaderHeight();
}
/**
* @return {?}
*/
ngOnInit() {
this.bagId = this.generateId();
// setup texts
this.gtTexts = /** @type {?} */ (this.extend(this.gtDefaultTexts, this.gtTexts));
}
/**
* Toggle column settings visibility.
* @return {?}
*/
toggleColumnSettings() {
this.active = !this.active;
if (this.active) {
this.offset = this._getTableHeadHeight();
// check and adjust height offset
setTimeout(() => {
this.heightAdjust = this._getColumnSettingsHeaderHeight();
}, 0);
}
}
/**
* Toggle column visibility.
* @param {?} column - column object.
* @return {?}
*/
toggleColumnVisibility(column) {
// 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: Object.assign({}, column),
settings: [...this._genericTable.gtSettings]
}
});
// check and reset offset
setTimeout(() => {
this.offset = this._getTableHeadHeight();
}, 0);
}
/**
* Order table by object key.
* @param {?} args - name of key to sort on.
* @return {?}
*/
_onDrop(args) {
this.reordered = true;
const [e, target] = args;
const /** @type {?} */ order = {};
for (let /** @type {?} */ i = 0; i < target.children.length; i++) {
order[target.children[i].getAttribute('data-object-key')] = i;
}
for (let /** @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 = [...this._genericTable.gtSettings];
this.changeDetectorRef.markForCheck();
this._genericTable.redraw();
this.gtEvent.emit({
name: 'gt-column-order-change',
value: {
settings: [...this._genericTable.gtSettings]
}
});
}
/**
* Get height of table head element ie. first row containing table headers.
* @return {?} offset height for table header in px.
*/
_getTableHeadHeight() {
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.
*/
_getColumnSettingsHeaderHeight() {
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 {?}
*/
generateId() {
let /** @type {?} */ d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const /** @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: `
<ng-template #columnItem let-column let-index="index">
<span class="badge badge-secondary">{{index}}</span>
<span (dblclick)="toggleColumnVisibility(column)" class="badge" [ngClass]="{'badge-success':column.visible !== false, 'badge-danger':column.visible === false}">{{genericTable.gtFields | gtProperty:column.objectKey:'name'}}</span>
</ng-template>
<div class="gt-column-settings">
<div class="gt-column-settings-panel" *ngIf="active" [style.padding-top]="offset" [style.height]="'calc(100% - '+offset+')'">
<div #gtColumnSettingsHeader class="gt-column-settings-header border-bottom-0" [ngClass]="gtHeaderClasses">
<button type="button" class="close" aria-label="Close" (click)="toggleColumnSettings()">
<span aria-hidden="true">×</span>
</button>
<h6 class="gt-column-settings-title" *ngIf="gtTexts.title">{{gtTexts.title}}</h6>
<small class="gt-column-settings-help form-text text-muted" *ngIf="gtTexts.help">{{gtTexts.help}}</small>
</div>
<div class="gt-column-settings-item-wrapper" [ngClass]="gtWrapperClasses" [dragula]='bagId' data-visible="true" [style.max-height]="'calc(100% - '+heightAdjust+')'">
<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">
<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>
</div>
</div>
<div class="gt-overlay" *ngIf="active && overlay" (click)="toggleColumnSettings()" [style.height]="'calc(100% - -'+offset+')'"></div>
</div>
<ng-template #genericTableElement [ngIf]="genericTable">
<ng-content></ng-content>
</ng-template>
</div>
`
},] },
];
/* tslint:enable */
/** @nocollapse */
GtColumnSettingsComponent.ctorParameters = () => [
{ 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', [],] },],
};
function GtColumnSettingsComponent_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
GtColumnSettingsComponent.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
GtColumnSettingsComponent.ctorParameters;
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
GtColumnSettingsComponent.propDecorators;
/** @type {?} */
GtColumnSettingsComponent.prototype.elementView;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtColumnSettingsHeader;
/** @type {?} */
GtColumnSettingsComponent.prototype._genericTable;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtHeaderClasses;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtWrapperClasses;
/** @type {?} */
GtColumnSettingsComponent.prototype.overlay;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtColumnItem;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtDefaultTexts;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtTexts;
/** @type {?} */
GtColumnSettingsComponent.prototype.gtEvent;
/** @type {?} */
GtColumnSettingsComponent.prototype.active;
/** @type {?} */
GtColumnSettingsComponent.prototype.offset;
/** @type {?} */
GtColumnSettingsComponent.prototype.heightAdjust;
/** @type {?} */
GtColumnSettingsComponent.prototype.reordered;
/** @type {?} */
GtColumnSettingsComponent.prototype.bagId;
/**
* Extend object function.
* @type {?}
*/
GtColumnSettingsComponent.prototype.extend;
/** @type {?} */
GtColumnSettingsComponent.prototype.dragulaService;
/** @type {?} */
GtColumnSettingsComponent.prototype.changeDetectorRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3QtY29sdW1uLXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Bhbmd1bGFyLWdlbmVyaWMtdGFibGUvY29sdW1uLXNldHRpbmdzLyIsInNvdXJjZXMiOlsiY29tcG9uZW50cy9ndC1jb2x1bW4tc2V0dGluZ3MuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFDTCxTQUFTLEVBQ1QsV0FBVyxFQUNYLFVBQVUsRUFDVixJQUFJLEVBR0osaUJBQWlCLEVBQ2pCLFlBQVksRUFDWixNQUFNLEVBQ04sWUFBWSxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTixxQkFBcUIsRUFHckIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBTTdDLE1BQU07Ozs7Ozs7SUFHRyxjQUFjLENBQUMsQ0FBTSxFQUFFLENBQU07UUFDcEMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUNuQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDVjtRQUNELEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsQ0FBQyxXQUFXLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQztZQUMzRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ1Q7UUFDRCxNQUFNLENBQUMsQ0FBQyxDQUFDOzs7Ozs7O0lBSUYsVUFBVSxDQUFDLE1BQXVCO1FBQ3pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxLQUFLLEtBQUssSUFBSSxNQUFNLENBQUMsWUFBWSxLQUFLLElBQUk7WUFDOUQsQ0FBQyxDQUFDLE1BQU07WUFDUixDQUFDLENBQUMsSUFBSSxDQUFDOzs7Ozs7SUFHVCxTQUFTLENBQUMsUUFB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QUFLOzZCQUNMLEtBQUs7d0JBS0wsS0FBSzt3QkFFTCxNQUFNO3lCQVdOLFlBQVksU0FBQyxlQUFlLEVBQUUsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0SW5wdXQsXG5cdFZpZXdDaGlsZCxcblx0VGVtcGxhdGVSZWYsXG5cdEVsZW1lbnRSZWYsXG5cdFBpcGUsXG5cdFBpcGVUcmFuc2Zvcm0sXG5cdE9uSW5pdCxcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdEhvc3RMaXN0ZW5lcixcblx0T3V0cHV0LFxuXHRFdmVudEVtaXR0ZXJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuXHRHZW5lcmljVGFibGVDb21wb25lbnQsXG5cdEd0Um93LFxuXHRHdENvbmZpZ1NldHRpbmdcbn0gZnJvbSAnQGFuZ3VsYXItZ2VuZXJpYy10YWJsZS9jb3JlJztcbmltcG9ydCB7IERyYWd1bGFTZXJ2aWNlIH0gZnJvbSAnbmcyLWRyYWd1bGEnO1xuaW1wb3J0IHsgR3RDb2x1bW5TZXR0aW5nc1RleHRzIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9ndC1jb2x1bW4tc2V0dGluZ3MtdGV4dHMnO1xuXG5AUGlwZSh7XG5cdG5hbWU6ICdndENvbHVtbidcbn0pXG5leHBvcnQgY2xhc3MgR3RDb2x1bW5QaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG5cdC8vIFRPRE86IG1vdmUgdG8gaGVscGVyIGZ1bmN0aW9uc1xuXHQvKiogU29ydCBieSBjb2x1bW4gb3JkZXIgKi9cblx0cHJpdmF0ZSBnZXRDb2x1bW5PcmRlcihhOiBhbnksIGI6IGFueSkge1xuXHRcdGlmIChhLmNvbHVtbk9yZGVyIDwgYi5jb2x1bW5PcmRlcikge1xuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH1cblx0XHRpZiAoYS5jb2x1bW5PcmRlciA+IGIuY29sdW1uT3JkZXIgfHwgdHlwZW9mIGEuY29sdW1uT3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyZXR1cm4gMTtcblx0XHR9XG5cdFx0cmV0dXJuIDA7XG5cdH1cblxuXHQvKiogcmV0dXJuIGVuYWJsZWQgY29sdW1ucyB0aGF0IGFyZSBub3QgbG9ja2VkIGZvciBlZGl0aW5nICovXG5cdHByaXZhdGUgZ2V0RW5hYmxlZChjb2x1bW46IEd0Q29uZmlnU2V0dGluZykge1xuXHRcdHJldHVybiBjb2x1bW4uZW5hYmxlZCAhPT0gZmFsc2UgJiYgY29sdW1uLmxvY2tTZXR0aW5ncyAhPT0gdHJ1ZVxuXHRcdFx0PyBjb2x1bW5cblx0XHRcdDogbnVsbDtcblx0fVxuXG5cdHRyYW5zZm9ybShzZXR0aW5nczogQXJyYXk8R3RDb25maWdTZXR0aW5nPik6IEFycmF5PEd0Q29uZmlnU2V0dGluZz4ge1xuXHRcdHJldHVybiBzZXR0aW5ncy5maWx0ZXIodGhpcy5nZXRFbmFibGVkKS5zb3J0KHRoaXMuZ2V0Q29sdW1uT3JkZXIpO1xuXHR9XG59XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ2d0LWNvbHVtbi1zZXR0aW5ncycsXG5cdHRlbXBsYXRlOiBgXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjY29sdW1uSXRlbSBsZXQtY29sdW1uIGxldC1pbmRleD1cImluZGV4XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJhZGdlLXNlY29uZGFyeVwiPnt7aW5kZXh9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIChkYmxjbGljayk9XCJ0b2dnbGVDb2x1bW5WaXNpYmlsaXR5KGNvbHVtbilcIiBjbGFzcz1cImJhZGdlXCIgW25nQ2xhc3NdPVwieydiYWRnZS1zdWNjZXNzJzpjb2x1bW4udmlzaWJsZSAhPT0gZmFsc2UsICdiYWRnZS1kYW5nZXInOmNvbHVtbi52aXNpYmxlID09PSBmYWxzZX1cIj57e2dlbmVyaWNUYWJsZS5ndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZSd9fTwvc3Bhbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5nc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy1wYW5lbFwiICAqbmdJZj1cImFjdGl2ZVwiIFtzdHlsZS5wYWRkaW5nLXRvcF09XCJvZmZzZXRcIiBbc3R5bGUuaGVpZ2h0XT1cIidjYWxjKDEwMCUgLSAnK29mZnNldCsnKSdcIj5cbiAgICAgICAgICAgICAgICA8ZGl2ICNndENvbHVtblNldHRpbmdzSGVhZGVyIGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLWhlYWRlciBib3JkZXItYm90dG9tLTBcIiBbbmdDbGFzc109XCJndEhlYWRlckNsYXNzZXNcIj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjbG9zZVwiIGFyaWEtbGFiZWw9XCJDbG9zZVwiIChjbGljayk9XCJ0b2dnbGVDb2x1bW5TZXR0aW5ncygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4mdGltZXM7PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGg2IGNsYXNzPVwiZ3QtY29sdW1uLXNldHRpbmdzLXRpdGxlXCIgKm5nSWY9XCJndFRleHRzLnRpdGxlXCI+e3tndFRleHRzLnRpdGxlfX08L2g2PlxuICAgICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtaGVscCBmb3JtLXRleHQgdGV4dC1tdXRlZFwiICpuZ0lmPVwiZ3RUZXh0cy5oZWxwXCI+e3tndFRleHRzLmhlbHB9fTwvc21hbGw+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImd0LWNvbHVtbi1zZXR0aW5ncy1pdGVtLXdyYXBwZXJcIiBbbmdDbGFzc109XCJndFdyYXBwZXJDbGFzc2VzXCIgW2RyYWd1bGFdPSdiYWdJZCcgIGRhdGEtdmlzaWJsZT1cInRydWVcIiBbc3R5bGUubWF4LWhlaWdodF09XCInY2FsYygxMDAlIC0gJytoZWlnaHRBZGp1c3QrJyknXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1jb2x1bW4tc2V0dGluZ3MtaXRlbSBwci0wIHByLXNtLTRcIiAqbmdGb3I9XCJsZXQgaSA9IGluZGV4O2xldCBjb2x1bW4gb2YgZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3MgfCBndENvbHVtblwiIFthdHRyLmRhdGEtb2JqZWN0LWtleV09XCJjb2x1bW4ub2JqZWN0S2V5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwiZ3RDb2x1bW5JdGVtID8gZ3RDb2x1bW5JdGVtOmNvbHVtbkl0ZW1cIiBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyRpbXBsaWNpdDogY29sdW1uLGluZGV4OiB0aGlzLnJlb3JkZXJlZCA/IGNvbHVtbi5jb2x1bW5PcmRlcisxOmkrMSwgbmFtZTogKGdlbmVyaWNUYWJsZS5ndEZpZWxkcyB8IGd0UHJvcGVydHk6Y29sdW1uLm9iamVjdEtleTonbmFtZScpfVwiPjwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJndC1vdmVybGF5XCIgKm5nSWY9XCJhY3RpdmUgJiYgb3ZlcmxheVwiIChjbGljayk9XCJ0b2dnbGVDb2x1bW5TZXR0aW5ncygpXCIgW3N0eWxlLmhlaWdodF09XCInY2FsYygxMDAlIC0gLScrb2Zmc2V0KycpJ1wiPjwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgI2dlbmVyaWNUYWJsZUVsZW1lbnQgW25nSWZdPVwiZ2VuZXJpY1RhYmxlXCI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9kaXY+XG4gICAgYFxufSlcbmV4cG9ydCBjbGFzcyBHdENvbHVtblNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblx0Z2V0IGdlbmVyaWNUYWJsZSgpOiBHZW5lcmljVGFibGVDb21wb25lbnQ8YW55LCBhbnk+IHtcblx0XHRyZXR1cm4gdGhpcy5fZ2VuZXJpY1RhYmxlO1xuXHR9XG5cblx0QElucHV0KClcblx0c2V0IGdlbmVyaWNUYWJsZSh2YWx1ZTogR2VuZXJpY1RhYmxlQ29tcG9uZW50PGFueSwgYW55Pikge1xuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZSA9IHZhbHVlO1xuXHR9XG5cblx0QFZpZXdDaGlsZCgnZ2VuZXJpY1RhYmxlRWxlbWVudCcpIGVsZW1lbnRWaWV3OiBUZW1wbGF0ZVJlZjxFbGVtZW50UmVmPjtcblx0QFZpZXdDaGlsZCgnZ3RDb2x1bW5TZXR0aW5nc0hlYWRlcicpIGd0Q29sdW1uU2V0dGluZ3NIZWFkZXI6IEVsZW1lbnRSZWY7XG5cblx0cHJpdmF0ZSBfZ2VuZXJpY1RhYmxlOiBHZW5lcmljVGFibGVDb21wb25lbnQ8R3RSb3csIGFueT47XG5cdEBJbnB1dCgpXG5cdGd0SGVhZGVyQ2xhc3NlcyA9ICdweC0zIHB0LTMgcGItMiB0YWJsZS1ib3JkZXJlZCBib3JkZXItbGVmdC0wIGJvcmRlci1yaWdodC0wIGJvcmRlci1ib3R0b20tMCBhbGVydC1pbmZvJztcblx0QElucHV0KClcblx0Z3RXcmFwcGVyQ2xhc3NlcyA9ICdweC0zIHBiLTMgdGFibGUtYm9yZGVyZWQgYm9yZGVyLWxlZnQtMCBib3JkZXItcmlnaHQtMCBib3JkZXItdG9wLTAgYWxlcnQtaW5mbyc7XG5cdEBJbnB1dCgpIG92ZXJsYXkgPSB0cnVlO1xuXHRASW5wdXQoKSBndENvbHVtbkl0ZW06IFRlbXBsYXRlUmVmPEVsZW1lbnRSZWY+O1xuXHRwdWJsaWMgZ3REZWZhdWx0VGV4dHM6IEd0Q29sdW1uU2V0dGluZ3NUZXh0cyA9IHtcblx0XHR0aXRsZTogJ0NvbHVtbnMnLFxuXHRcdGhlbHA6ICdEb3VibGUgY2xpY2sgdG8gdG9nZ2xlIHZpc2liaWxpdHksIGRyYWcgYW5kIGRyb3AgdG8gcmVvcmRlci4nXG5cdH07XG5cdEBJbnB1dCgpIGd0VGV4dHM6IEd0Q29sdW1uU2V0dGluZ3NUZXh0cyA9IHRoaXMuZ3REZWZhdWx0VGV4dHM7XG5cblx0QE91dHB1dCgpIHB1YmxpYyBndEV2ZW50OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG5cdHB1YmxpYyBhY3RpdmUgPSBmYWxzZTtcblx0cHVibGljIG9mZnNldDogc3RyaW5nO1xuXHRwdWJsaWMgaGVpZ2h0QWRqdXN0OiBzdHJpbmc7XG5cdHB1YmxpYyByZW9yZGVyZWQgPSBmYWxzZTtcblx0cHVibGljIGJhZ0lkOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIENoZWNrIG9mZnNldCBoZWlnaHQgb24gd2luZG93IHJlc2l6ZS5cblx0ICovXG5cdEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbXSlcblx0cHVibGljIG9uUmVzaXplKCkge1xuXHRcdHRoaXMub2Zmc2V0ID0gdGhpcy5fZ2V0VGFibGVIZWFkSGVpZ2h0KCk7XG5cdFx0dGhpcy5oZWlnaHRBZGp1c3QgPSB0aGlzLl9nZXRDb2x1bW5TZXR0aW5nc0hlYWRlckhlaWdodCgpO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSBkcmFndWxhU2VydmljZTogRHJhZ3VsYVNlcnZpY2UsXG5cdFx0cHJpdmF0ZSBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWZcblx0KSB7XG5cdFx0ZHJhZ3VsYVNlcnZpY2UuZHJvcC5zdWJzY3JpYmUoKHZhbHVlOiBBcnJheTxhbnk+KSA9PiB7XG5cdFx0XHRpZiAodmFsdWVbMF0gPT09IHRoaXMuYmFnSWQpIHtcblx0XHRcdFx0dGhpcy5fb25Ecm9wKHZhbHVlLnNsaWNlKDEpKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdG5nT25Jbml0KCkge1xuXHRcdHRoaXMuYmFnSWQgPSB0aGlzLmdlbmVyYXRlSWQoKTtcblx0XHQvLyBzZXR1cCB0ZXh0c1xuXHRcdHRoaXMuZ3RUZXh0cyA9IDxHdENvbHVtblNldHRpbmdzVGV4dHM+dGhpcy5leHRlbmQoXG5cdFx0XHR0aGlzLmd0RGVmYXVsdFRleHRzLFxuXHRcdFx0dGhpcy5ndFRleHRzXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiAgRXh0ZW5kIG9iamVjdCBmdW5jdGlvbi5cblx0ICovXG5cdHByaXZhdGUgZXh0ZW5kID0gZnVuY3Rpb24oYTogT2JqZWN0LCBiOiBPYmplY3QpIHtcblx0XHRmb3IgKGNvbnN0IGtleSBpbiBiKSB7XG5cdFx0XHRpZiAoYi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG5cdFx0XHRcdGFba2V5XSA9IGJba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGE7XG5cdH07XG5cblx0LyoqXG5cdCAqIFRvZ2dsZSBjb2x1bW4gc2V0dGluZ3MgdmlzaWJpbGl0eS5cblx0ICovXG5cdHB1YmxpYyB0b2dnbGVDb2x1bW5TZXR0aW5ncygpIHtcblx0XHR0aGlzLmFjdGl2ZSA9ICF0aGlzLmFjdGl2ZTtcblxuXHRcdGlmICh0aGlzLmFjdGl2ZSkge1xuXHRcdFx0dGhpcy5vZmZzZXQgPSB0aGlzLl9nZXRUYWJsZUhlYWRIZWlnaHQoKTtcblxuXHRcdFx0Ly8gY2hlY2sgYW5kIGFkanVzdCBoZWlnaHQgb2Zmc2V0XG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0dGhpcy5oZWlnaHRBZGp1c3QgPSB0aGlzLl9nZXRDb2x1bW5TZXR0aW5nc0hlYWRlckhlaWdodCgpO1xuXHRcdFx0fSwgMCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFRvZ2dsZSBjb2x1bW4gdmlzaWJpbGl0eS5cblx0ICogQHBhcmFtIGNvbHVtbiAtIGNvbHVtbiBvYmplY3QuXG5cdCAqL1xuXHRwdWJsaWMgdG9nZ2xlQ29sdW1uVmlzaWJpbGl0eShjb2x1bW46IGFueSkge1xuXHRcdC8vIHRvZ2dsZSBjb2x1bW4gdmlzaWJpbGl0eVxuXHRcdGNvbHVtbi52aXNpYmxlID1cblx0XHRcdHR5cGVvZiBjb2x1bW4udmlzaWJsZSA9PT0gJ3VuZGVmaW5lZCcgPyBmYWxzZSA6ICFjb2x1bW4udmlzaWJsZTtcblxuXHRcdC8vIHJlZHJhdyB0YWJsZVxuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5yZWRyYXcoKTtcblxuXHRcdC8vIGVtaXQgZXZlbnRcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtY29sdW1uLXZpc2liaWxpdHktY2hhbmdlJyxcblx0XHRcdHZhbHVlOiB7XG5cdFx0XHRcdGNvbHVtbjogeyAuLi5jb2x1bW4gfSxcblx0XHRcdFx0c2V0dGluZ3M6IFsuLi50aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc11cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIGNoZWNrIGFuZCByZXNldCBvZmZzZXRcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMub2Zmc2V0ID0gdGhpcy5fZ2V0VGFibGVIZWFkSGVpZ2h0KCk7XG5cdFx0fSwgMCk7XG5cdH1cblxuXHQvKipcblx0ICogT3JkZXIgdGFibGUgYnkgb2JqZWN0IGtleS5cblx0ICogQHBhcmFtIGFyZ3MgLSBuYW1lIG9mIGtleSB0byBzb3J0IG9uLlxuXHQgKi9cblx0cHJpdmF0ZSBfb25Ecm9wKGFyZ3M6IEFycmF5PGFueT4pIHtcblx0XHR0aGlzLnJlb3JkZXJlZCA9IHRydWU7XG5cdFx0Y29uc3QgW2UsIHRhcmdldF0gPSBhcmdzO1xuXHRcdGNvbnN0IG9yZGVyID0ge307XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0YXJnZXQuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcblx0XHRcdG9yZGVyW3RhcmdldC5jaGlsZHJlbltpXS5nZXRBdHRyaWJ1dGUoJ2RhdGEtb2JqZWN0LWtleScpXSA9IGk7XG5cdFx0fVxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzW2ldLmNvbHVtbk9yZGVyID1cblx0XHRcdFx0b3JkZXJbdGhpcy5fZ2VuZXJpY1RhYmxlLmd0U2V0dGluZ3NbaV0ub2JqZWN0S2V5XTtcblx0XHR9XG5cblx0XHQvLyByZXNldCBhcnJheSB0byB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb25cblx0XHR0aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5ncyA9IFsuLi50aGlzLl9nZW5lcmljVGFibGUuZ3RTZXR0aW5nc107XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblxuXHRcdHRoaXMuX2dlbmVyaWNUYWJsZS5yZWRyYXcoKTtcblx0XHR0aGlzLmd0RXZlbnQuZW1pdCh7XG5cdFx0XHRuYW1lOiAnZ3QtY29sdW1uLW9yZGVyLWNoYW5nZScsXG5cdFx0XHR2YWx1ZToge1xuXHRcdFx0XHRzZXR0aW5nczogWy4uLnRoaXMuX2dlbmVyaWNUYWJsZS5ndFNldHRpbmdzXVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBoZWlnaHQgb2YgdGFibGUgaGVhZCBlbGVtZW50IGllLiBmaXJzdCByb3cgY29udGFpbmluZyB0YWJsZSBoZWFkZXJzLlxuXHQgKiBAcmV0dXJucyBvZmZzZXQgaGVpZ2h0IGZvciB0YWJsZSBoZWFkZXIgaW4gcHguXG5cdCAqL1xuXHRwcml2YXRlIF9nZXRUYWJsZUhlYWRIZWlnaHQoKTogc3RyaW5nIHtcblx0XHR0cnkge1xuXHRcdFx0aWYgKFxuXHRcdFx0XHR0aGlzLmVsZW1lbnRWaWV3LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmdcblx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQudGFnTmFtZSA9PT0gJ1RIRUFEJ1xuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiAoXG5cdFx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQub2Zmc2V0SGVpZ2h0ICsgJ3B4J1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKFxuXHRcdFx0XHR0aGlzLmVsZW1lbnRWaWV3LmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmdcblx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQudGFnTmFtZSA9PT1cblx0XHRcdFx0J1RIRUFEJ1xuXHRcdFx0KSB7XG5cdFx0XHRcdHJldHVybiAoXG5cdFx0XHRcdFx0dGhpcy5lbGVtZW50Vmlldy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nXG5cdFx0XHRcdFx0XHQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGQuZmlyc3RFbGVtZW50Q2hpbGRcblx0XHRcdFx0XHRcdC5vZmZzZXRIZWlnaHQgKyAncHgnXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gJzBweCc7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdHJldHVybiAnMHB4Jztcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGhlaWdodCBvZiB0YWJsZSBoZWFkIGVsZW1lbnQgaWUuIGZpcnN0IHJvdyBjb250YWluaW5nIHRhYmxlIGhlYWRlcnMuXG5cdCAqIEByZXR1cm5zIG9mZnNldCBoZWlnaHQgZm9yIHRhYmxlIGhlYWRlciBpbiBweC5cblx0ICovXG5cdHByaXZhdGUgX2dldENvbHVtblNldHRpbmdzSGVhZGVySGVpZ2h0KCk6IHN0cmluZyB7XG5cdFx0dHJ5IHtcblx0XHRcdHJldHVybiB0aGlzLmd0Q29sdW1uU2V0dGluZ3NIZWFkZXIubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQgKyAncHgnO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRyZXR1cm4gJzBweCc7XG5cdFx0fVxuXHR9XG5cblx0LyoqIGdlbmVyYXRlIGEgdW5pcXVlIGlkIGZvciBkcmFndWxhIGluc3RhbmNlIGkuZS4gYSB1bmlxdWUgYmFnIG5hbWUqL1xuXHQvKiB0c2xpbnQ6ZGlzYWJsZSAqL1xuXHRwcml2YXRlIGdlbmVyYXRlSWQoKSB7XG5cdFx0bGV0IGQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblx0XHRyZXR1cm4gJ3h4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eCcucmVwbGFjZSgvW3h5XS9nLCBmdW5jdGlvbihjKSB7XG5cdFx0XHRjb25zdCByID0gKChkICsgTWF0aC5yYW5kb20oKSAqIDE2KSAlIDE2KSB8IDA7XG5cdFx0XHRkID0gTWF0aC5mbG9vcihkIC8gMTYpO1xuXHRcdFx0cmV0dXJuIChjID09PSAneCcgPyByIDogKHIgJiAweDMpIHwgMHg4KS50b1N0cmluZygxNik7XG5cdFx0fSk7XG5cdH1cblx0LyogdHNsaW50OmVuYWJsZSAqL1xufVxuIl19