UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

112 lines 19.7 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, Input, Output } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { ColumnSortingDirective, ColumnSortingState } from './column-sorting.directive'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "../icon/icon.component"; export class ColumnSortingComponent { constructor() { this._sorter = inject(ColumnSortingDirective); this._changeDetector = inject(ChangeDetectorRef); /** Defines the sorting order of a column: `NoSort`, `Ascending` or `Descending`. */ this.state = ColumnSortingState.NoSort; /** Determine if a column can have a `NoSort` state */ this.allowNoSort = true; /** Specifies name of the ascending icon */ this.ascendingIcon = 'ascend'; /** Specifies name of the descending icon */ this.descendingIcon = 'descend'; /** * Changes the state of the sorting on the column between `NoSort`, `Ascending` and `Descending`. * This returns an array of objects for each column being sorted containing `key: string` and `state: ColumnSortingState`. * State can be used to find the current sorting state of the column eg. `(state === ColumnSortingState.Ascending)`. * The `ColumnSortingOrder` interface has been provided for objects in the array. */ this.stateChange = new EventEmitter(); /** Emit whenever the order changes */ this.orderChange = new EventEmitter(); /** Expose the sorting state enum to the view */ this.ColumnSortingState = ColumnSortingState; /** Unsubscribe from all observables on component destroy */ this._onDestroy$ = new Subject(); } /** Access the custom sort indicator if one was provided */ get _sortIndicator() { return this._sorter.sortIndicator; } ngOnInit() { // listen for changes triggered by the directive this._sorter.events.pipe(takeUntil(this._onDestroy$)) .subscribe(columns => this.updateState(columns)); } ngOnChanges(changes) { // if the state input is changed then apply the change if (changes.state && changes.state.currentValue !== changes.state.previousValue) { this._sorter.setColumnState(this.key, this.state); } } ngOnDestroy() { this._onDestroy$.next(); this._onDestroy$.complete(); } /** Toggle the sorting state of a column - this is designed to be programmatically called by the consuming component */ changeState() { switch (this.state) { case ColumnSortingState.Ascending: this.state = ColumnSortingState.Descending; break; case ColumnSortingState.Descending: this.state = this.allowNoSort ? ColumnSortingState.NoSort : ColumnSortingState.Ascending; break; default: this.state = ColumnSortingState.Ascending; } // change detection should be run this._changeDetector.markForCheck(); // inform parent (internally we use a ReadonlyArray but are returning a standard array to prevent breaking changes to the public API) return this._sorter.toggleColumn({ key: this.key, state: this.state }); } /** Update the state based on column order */ updateState(columns) { // if we are sorting this column then find the matching data const columnIdx = columns.findIndex(_column => _column.key === this.key); // if we are not sorting this column then mark it as NoSort if (columnIdx === -1) { this.state = ColumnSortingState.NoSort; } // only store the number if we have 2 or more columns being sorted this.order = columns.length < 2 || columnIdx === -1 ? null : columnIdx + 1; // emit the latest order value if (typeof this.order === 'number') { this.orderChange.emit(this.order); } // change detection should be run this._changeDetector.markForCheck(); // Emit the latest change this.stateChange.emit(this.state); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ColumnSortingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: ColumnSortingComponent, selector: "ux-column-sorting", inputs: { state: "state", key: "key", order: "order", allowNoSort: "allowNoSort", ascendingIcon: "ascendingIcon", descendingIcon: "descendingIcon" }, outputs: { stateChange: "stateChange", orderChange: "orderChange" }, exportAs: ["ux-column-sorting"], usesOnChanges: true, ngImport: i0, template: "<div class=\"ux-column-sorting\"\n [class.ux-column-sorting-hidden]=\"state === ColumnSortingState.NoSort\">\n\n <!-- The default sort indicator -->\n @if (!_sortIndicator) {\n <ux-icon\n class=\"ux-column-sorting-icon\"\n [class.column-sorting-icon-hidden]=\"state === ColumnSortingState.NoSort\"\n [name]=\"state === ColumnSortingState.Descending ? descendingIcon : ascendingIcon\">\n </ux-icon>\n <p class=\"ux-column-sorting-number\" aria-hidden=\"true\">{{ order }}</p>\n }\n\n <!-- Custom sort indicator -->\n @if (_sortIndicator) {\n <ng-container\n [ngTemplateOutlet]=\"_sortIndicator\"\n [ngTemplateOutletContext]=\"{ state: state, order: order }\">\n </ng-container>\n }\n\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ColumnSortingComponent, decorators: [{ type: Component, args: [{ selector: 'ux-column-sorting', exportAs: 'ux-column-sorting', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ux-column-sorting\"\n [class.ux-column-sorting-hidden]=\"state === ColumnSortingState.NoSort\">\n\n <!-- The default sort indicator -->\n @if (!_sortIndicator) {\n <ux-icon\n class=\"ux-column-sorting-icon\"\n [class.column-sorting-icon-hidden]=\"state === ColumnSortingState.NoSort\"\n [name]=\"state === ColumnSortingState.Descending ? descendingIcon : ascendingIcon\">\n </ux-icon>\n <p class=\"ux-column-sorting-number\" aria-hidden=\"true\">{{ order }}</p>\n }\n\n <!-- Custom sort indicator -->\n @if (_sortIndicator) {\n <ng-container\n [ngTemplateOutlet]=\"_sortIndicator\"\n [ngTemplateOutletContext]=\"{ state: state, order: order }\">\n </ng-container>\n }\n\n</div>\n" }] }], propDecorators: { state: [{ type: Input }], key: [{ type: Input }], order: [{ type: Input }], allowNoSort: [{ type: Input }], ascendingIcon: [{ type: Input }], descendingIcon: [{ type: Input }], stateChange: [{ type: Output }], orderChange: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sdW1uLXNvcnRpbmcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvY29sdW1uLXNvcnRpbmcvY29sdW1uLXNvcnRpbmcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvY29sdW1uLXNvcnRpbmcvY29sdW1uLXNvcnRpbmcuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBZ0MsTUFBTSxFQUE4QixNQUFNLGVBQWUsQ0FBQztBQUNyTCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsc0JBQXNCLEVBQXFELGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7QUFRM0ksTUFBTSxPQUFPLHNCQUFzQjtJQU5uQztRQVFxQixZQUFPLEdBQUcsTUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFFekMsb0JBQWUsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUU3RCxvRkFBb0Y7UUFDM0UsVUFBSyxHQUF1QixrQkFBa0IsQ0FBQyxNQUFNLENBQUM7UUFRL0Qsc0RBQXNEO1FBQzdDLGdCQUFXLEdBQVksSUFBSSxDQUFDO1FBRXJDLDJDQUEyQztRQUNsQyxrQkFBYSxHQUFXLFFBQVEsQ0FBQztRQUUxQyw0Q0FBNEM7UUFDbkMsbUJBQWMsR0FBVyxTQUFTLENBQUM7UUFFNUM7Ozs7O1dBS0c7UUFDTyxnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFzQixDQUFDO1FBRS9ELHNDQUFzQztRQUM1QixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFFbkQs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RUQsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFcEMseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxDQUFDOytHQS9HUSxzQkFBc0I7bUdBQXRCLHNCQUFzQiwwVUNYbkMscXVCQXNCQTs7NEZEWGEsc0JBQXNCO2tCQU5sQyxTQUFTOytCQUNJLG1CQUFtQixZQUVuQixtQkFBbUIsbUJBQ1osdUJBQXVCLENBQUMsTUFBTTs4QkFTdEMsS0FBSztzQkFBYixLQUFLO2dCQUdHLEdBQUc7c0JBQVgsS0FBSztnQkFHRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0csV0FBVztzQkFBbkIsS0FBSztnQkFHRyxhQUFhO3NCQUFyQixLQUFLO2dCQUdHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBUUksV0FBVztzQkFBcEIsTUFBTTtnQkFHRyxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgaW5qZWN0LCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQ29sdW1uU29ydGluZ0RpcmVjdGl2ZSwgQ29sdW1uU29ydGluZ0luZGljYXRvckNvbnRleHQsIENvbHVtblNvcnRpbmdPcmRlciwgQ29sdW1uU29ydGluZ1N0YXRlIH0gZnJvbSAnLi9jb2x1bW4tc29ydGluZy5kaXJlY3RpdmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3V4LWNvbHVtbi1zb3J0aW5nJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vY29sdW1uLXNvcnRpbmcuY29tcG9uZW50Lmh0bWwnLFxuICAgIGV4cG9ydEFzOiAndXgtY29sdW1uLXNvcnRpbmcnLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIENvbHVtblNvcnRpbmdDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3NvcnRlciA9IGluamVjdChDb2x1bW5Tb3J0aW5nRGlyZWN0aXZlKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYW5nZURldGVjdG9yID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICAgIC8qKiBEZWZpbmVzIHRoZSBzb3J0aW5nIG9yZGVyIG9mIGEgY29sdW1uOiBgTm9Tb3J0YCwgYEFzY2VuZGluZ2Agb3IgYERlc2NlbmRpbmdgLiAqL1xuICAgIEBJbnB1dCgpIHN0YXRlOiBDb2x1bW5Tb3J0aW5nU3RhdGUgPSBDb2x1bW5Tb3J0aW5nU3RhdGUuTm9Tb3J0O1xuXG4gICAgLyoqIERlZmluZXMgYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGNvbHVtbiB0aGF0IGNhbiBiZSB1c2VkIHdoZW4gc29ydGluZy4gKi9cbiAgICBASW5wdXQoKSBrZXk6IHN0cmluZztcblxuICAgIC8qKiBTdG9yZSB0aGUgb3JkZXIgb2YgdGhlIHNvcnRpbmcgLSB1c2VkIHdoZW4gbXVsdGlwbGUgY29sdW1ucyBhcmUgYmVpbmcgc29ydGVkIGF0IG9uY2UgKi9cbiAgICBASW5wdXQoKSBvcmRlcjogbnVtYmVyO1xuXG4gICAgLyoqIERldGVybWluZSBpZiBhIGNvbHVtbiBjYW4gaGF2ZSBhIGBOb1NvcnRgIHN0YXRlICovXG4gICAgQElucHV0KCkgYWxsb3dOb1NvcnQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFNwZWNpZmllcyBuYW1lIG9mIHRoZSBhc2NlbmRpbmcgaWNvbiAqL1xuICAgIEBJbnB1dCgpIGFzY2VuZGluZ0ljb246IHN0cmluZyA9ICdhc2NlbmQnO1xuXG4gICAgLyoqIFNwZWNpZmllcyBuYW1lIG9mIHRoZSBkZXNjZW5kaW5nIGljb24gKi9cbiAgICBASW5wdXQoKSBkZXNjZW5kaW5nSWNvbjogc3RyaW5nID0gJ2Rlc2NlbmQnO1xuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgc3RhdGUgb2YgdGhlIHNvcnRpbmcgb24gdGhlIGNvbHVtbiBiZXR3ZWVuIGBOb1NvcnRgLCBgQXNjZW5kaW5nYCBhbmQgYERlc2NlbmRpbmdgLlxuICAgICAqIFRoaXMgcmV0dXJucyBhbiBhcnJheSBvZiBvYmplY3RzIGZvciBlYWNoIGNvbHVtbiBiZWluZyBzb3J0ZWQgY29udGFpbmluZyBga2V5OiBzdHJpbmdgIGFuZCBgc3RhdGU6IENvbHVtblNvcnRpbmdTdGF0ZWAuXG4gICAgICogU3RhdGUgY2FuIGJlIHVzZWQgdG8gZmluZCB0aGUgY3VycmVudCBzb3J0aW5nIHN0YXRlIG9mIHRoZSBjb2x1bW4gZWcuIGAoc3RhdGUgPT09IENvbHVtblNvcnRpbmdTdGF0ZS5Bc2NlbmRpbmcpYC5cbiAgICAgKiBUaGUgYENvbHVtblNvcnRpbmdPcmRlcmAgaW50ZXJmYWNlIGhhcyBiZWVuIHByb3ZpZGVkIGZvciBvYmplY3RzIGluIHRoZSBhcnJheS5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgc3RhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENvbHVtblNvcnRpbmdTdGF0ZT4oKTtcblxuICAgIC8qKiBFbWl0IHdoZW5ldmVyIHRoZSBvcmRlciBjaGFuZ2VzICovXG4gICAgQE91dHB1dCgpIG9yZGVyQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cbiAgICAvKiogRXhwb3NlIHRoZSBzb3J0aW5nIHN0YXRlIGVudW0gdG8gdGhlIHZpZXcgKi9cbiAgICBDb2x1bW5Tb3J0aW5nU3RhdGUgPSBDb2x1bW5Tb3J0aW5nU3RhdGU7XG5cbiAgICAvKiogQWNjZXNzIHRoZSBjdXN0b20gc29ydCBpbmRpY2F0b3IgaWYgb25lIHdhcyBwcm92aWRlZCAqL1xuICAgIGdldCBfc29ydEluZGljYXRvcigpOiBUZW1wbGF0ZVJlZjxDb2x1bW5Tb3J0aW5nSW5kaWNhdG9yQ29udGV4dD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fc29ydGVyLnNvcnRJbmRpY2F0b3I7XG4gICAgfVxuXG4gICAgLyoqIFVuc3Vic2NyaWJlIGZyb20gYWxsIG9ic2VydmFibGVzIG9uIGNvbXBvbmVudCBkZXN0cm95ICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gbGlzdGVuIGZvciBjaGFuZ2VzIHRyaWdnZXJlZCBieSB0aGUgZGlyZWN0aXZlXG4gICAgICAgIHRoaXMuX3NvcnRlci5ldmVudHMucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95JCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKGNvbHVtbnMgPT4gdGhpcy51cGRhdGVTdGF0ZShjb2x1bW5zKSk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICAvLyBpZiB0aGUgc3RhdGUgaW5wdXQgaXMgY2hhbmdlZCB0aGVuIGFwcGx5IHRoZSBjaGFuZ2VcbiAgICAgICAgaWYgKGNoYW5nZXMuc3RhdGUgJiYgY2hhbmdlcy5zdGF0ZS5jdXJyZW50VmFsdWUgIT09IGNoYW5nZXMuc3RhdGUucHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fc29ydGVyLnNldENvbHVtblN0YXRlKHRoaXMua2V5LCB0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIC8qKiBUb2dnbGUgdGhlIHNvcnRpbmcgc3RhdGUgb2YgYSBjb2x1bW4gLSB0aGlzIGlzIGRlc2lnbmVkIHRvIGJlIHByb2dyYW1tYXRpY2FsbHkgY2FsbGVkIGJ5IHRoZSBjb25zdW1pbmcgY29tcG9uZW50ICovXG4gICAgY2hhbmdlU3RhdGUoKTogQ29sdW1uU29ydGluZ09yZGVyW10ge1xuXG4gICAgICAgIHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuXG4gICAgICAgICAgICBjYXNlIENvbHVtblNvcnRpbmdTdGF0ZS5Bc2NlbmRpbmc6XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IENvbHVtblNvcnRpbmdTdGF0ZS5EZXNjZW5kaW5nO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIENvbHVtblNvcnRpbmdTdGF0ZS5EZXNjZW5kaW5nOlxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLmFsbG93Tm9Tb3J0ID8gQ29sdW1uU29ydGluZ1N0YXRlLk5vU29ydCA6IENvbHVtblNvcnRpbmdTdGF0ZS5Bc2NlbmRpbmc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IENvbHVtblNvcnRpbmdTdGF0ZS5Bc2NlbmRpbmc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGFuZ2UgZGV0ZWN0aW9uIHNob3VsZCBiZSBydW5cbiAgICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG5cbiAgICAgICAgLy8gaW5mb3JtIHBhcmVudCAoaW50ZXJuYWxseSB3ZSB1c2UgYSBSZWFkb25seUFycmF5IGJ1dCBhcmUgcmV0dXJuaW5nIGEgc3RhbmRhcmQgYXJyYXkgdG8gcHJldmVudCBicmVha2luZyBjaGFuZ2VzIHRvIHRoZSBwdWJsaWMgQVBJKVxuICAgICAgICByZXR1cm4gdGhpcy5fc29ydGVyLnRvZ2dsZUNvbHVtbih7IGtleTogdGhpcy5rZXksIHN0YXRlOiB0aGlzLnN0YXRlIH0pIGFzIENvbHVtblNvcnRpbmdPcmRlcltdO1xuICAgIH1cblxuICAgIC8qKiBVcGRhdGUgdGhlIHN0YXRlIGJhc2VkIG9uIGNvbHVtbiBvcmRlciAqL1xuICAgIHByaXZhdGUgdXBkYXRlU3RhdGUoY29sdW1uczogUmVhZG9ubHlBcnJheTxDb2x1bW5Tb3J0aW5nT3JkZXI+KTogdm9pZCB7XG4gICAgICAgIC8vIGlmIHdlIGFyZSBzb3J0aW5nIHRoaXMgY29sdW1uIHRoZW4gZmluZCB0aGUgbWF0Y2hpbmcgZGF0YVxuICAgICAgICBjb25zdCBjb2x1bW5JZHggPSBjb2x1bW5zLmZpbmRJbmRleChfY29sdW1uID0+IF9jb2x1bW4ua2V5ID09PSB0aGlzLmtleSk7XG5cbiAgICAgICAgLy8gaWYgd2UgYXJlIG5vdCBzb3J0aW5nIHRoaXMgY29sdW1uIHRoZW4gbWFyayBpdCBhcyBOb1NvcnRcbiAgICAgICAgaWYgKGNvbHVtbklkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBDb2x1bW5Tb3J0aW5nU3RhdGUuTm9Tb3J0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb25seSBzdG9yZSB0aGUgbnVtYmVyIGlmIHdlIGhhdmUgMiBvciBtb3JlIGNvbHVtbnMgYmVpbmcgc29ydGVkXG4gICAgICAgIHRoaXMub3JkZXIgPSBjb2x1bW5zLmxlbmd0aCA8IDIgfHwgY29sdW1uSWR4ID09PSAtMSA/IG51bGwgOiBjb2x1bW5JZHggKyAxO1xuXG4gICAgICAgIC8vIGVtaXQgdGhlIGxhdGVzdCBvcmRlciB2YWx1ZVxuICAgICAgICBpZiAodHlwZW9mIHRoaXMub3JkZXIgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aGlzLm9yZGVyQ2hhbmdlLmVtaXQodGhpcy5vcmRlcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGFuZ2UgZGV0ZWN0aW9uIHNob3VsZCBiZSBydW5cbiAgICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG5cbiAgICAgICAgLy8gRW1pdCB0aGUgbGF0ZXN0IGNoYW5nZVxuICAgICAgICB0aGlzLnN0YXRlQ2hhbmdlLmVtaXQodGhpcy5zdGF0ZSk7XG4gICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cInV4LWNvbHVtbi1zb3J0aW5nXCJcbiAgW2NsYXNzLnV4LWNvbHVtbi1zb3J0aW5nLWhpZGRlbl09XCJzdGF0ZSA9PT0gQ29sdW1uU29ydGluZ1N0YXRlLk5vU29ydFwiPlxuXG4gIDwhLS0gVGhlIGRlZmF1bHQgc29ydCBpbmRpY2F0b3IgLS0+XG4gIEBpZiAoIV9zb3J0SW5kaWNhdG9yKSB7XG4gICAgPHV4LWljb25cbiAgICAgIGNsYXNzPVwidXgtY29sdW1uLXNvcnRpbmctaWNvblwiXG4gICAgICBbY2xhc3MuY29sdW1uLXNvcnRpbmctaWNvbi1oaWRkZW5dPVwic3RhdGUgPT09IENvbHVtblNvcnRpbmdTdGF0ZS5Ob1NvcnRcIlxuICAgICAgW25hbWVdPVwic3RhdGUgPT09IENvbHVtblNvcnRpbmdTdGF0ZS5EZXNjZW5kaW5nID8gZGVzY2VuZGluZ0ljb24gOiBhc2NlbmRpbmdJY29uXCI+XG4gICAgPC91eC1pY29uPlxuICAgIDxwIGNsYXNzPVwidXgtY29sdW1uLXNvcnRpbmctbnVtYmVyXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+e3sgb3JkZXIgfX08L3A+XG4gIH1cblxuICA8IS0tIEN1c3RvbSBzb3J0IGluZGljYXRvciAtLT5cbiAgQGlmIChfc29ydEluZGljYXRvcikge1xuICAgIDxuZy1jb250YWluZXJcbiAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIl9zb3J0SW5kaWNhdG9yXCJcbiAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHN0YXRlOiBzdGF0ZSwgb3JkZXI6IG9yZGVyIH1cIj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgfVxuXG48L2Rpdj5cbiJdfQ==