UNPKG

@ux-aspects/ux-aspects

Version:

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

121 lines 22.1 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, EventEmitter, HostBinding, inject, Input, Output, ViewChild } from '@angular/core'; import { Subject } from 'rxjs'; import { map, takeUntil, tap } from 'rxjs/operators'; import { DashboardService, defaultOptions } from './dashboard.service'; import { DashboardGrabHandleDirective } from './grab-handle/grab-handle.directive'; import { DashboardGrabHandleService } from './grab-handle/grab-handle.service'; import * as i0 from "@angular/core"; import * as i1 from "../../directives/resize/resize.directive"; import * as i2 from "@angular/common"; export class DashboardComponent { /** If defined or changed this will set the positions of the widgets within the dashboard. This is a two way binding that will be updated with the current layout when it changes. */ set layout(layout) { if (layout) { this.dashboardService.layout$.next(layout); } } /** Configures the options for the dashboard, if an option is not specified the default value will be used. */ set options(options) { this.dashboardService.options$.next({ ...defaultOptions, ...options }); } constructor() { this.dashboardService = inject(DashboardService); this._changeDetector = inject(ChangeDetectorRef); this.isGrabbing = false; this.customAriaLabel = this.getDefaultAriaLabel; /** Emits when layout has been changed. */ this.layoutChange = new EventEmitter(); this.role = 'region'; /** Ensure we unsubscribe from all observables */ this._onDestroy = new Subject(); this.dashboardService.layout$.pipe(takeUntil(this._onDestroy), tap(() => this.ariaLabel = this.getAriaLabel())) .subscribe(() => this._changeDetector.markForCheck()); this.dashboardService.userLayoutChange$.pipe(takeUntil(this._onDestroy)).subscribe(data => this.layoutChange.emit(data)); // subscribe to changes to the grab mode this.dashboardService.isGrabbing$.pipe(takeUntil(this._onDestroy), map(widget => !!widget)) .subscribe(isGrabbing => this.isGrabbing = isGrabbing); } /** * Set the initial dimensions */ ngAfterViewInit() { // set the initial dimensions this.dashboardService.setDimensions(this.dashboardElement.nativeElement.offsetWidth, this.dashboardElement.nativeElement.offsetHeight); } ngAfterContentInit() { this.dashboardService.initialized$.next(true); } ngOnChanges() { this.dashboardService.renderDashboard(); } ngOnDestroy() { this._onDestroy.next(); this._onDestroy.complete(); } onResize(event) { this.dashboardService.setDimensions(event.width, event.height); } getAriaLabel() { if (this.customAriaLabel && typeof this.customAriaLabel === 'string') { return this.customAriaLabel; } else if (this.customAriaLabel && typeof this.customAriaLabel === 'function') { return this.customAriaLabel(this.dashboardService.widgets, this.dashboardService.options); } return this.ariaLabel; } /** Shift widgets up where possible to fill any available space to optimize the dashboard layout */ refreshLayout() { const didChangeLayout = this.dashboardService.shiftWidgetsUp(); if (didChangeLayout) { // if widgets have shifted up the dashboard may no longer occupy the same // height. We should remove any unneeded whitespace below widgets too. this.dashboardService.setDashboardHeight(); // emit information about the layout this.dashboardService.layout$.next(this.dashboardService.getLayoutData()); this.layoutChange.emit(this.dashboardService.layout$.value); } } getDefaultAriaLabel(widgets, options) { return `Dashboard with ${options.columns} columns, containing ${widgets.length} panels. ${widgets.map(this.getWidgetAriaLabel).join(' ')}`; } getWidgetAriaLabel(widget) { return `${widget.name} panel in row ${widget.getRow()}, column ${widget.getColumn()}, is ${widget.getColumnSpan()} columns wide and ${widget.getRowSpan()} rows high.`; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: DashboardComponent, selector: "ux-dashboard", inputs: { customAriaLabel: ["aria-label", "customAriaLabel"], layout: "layout", options: "options", role: "role" }, outputs: { layoutChange: "layoutChange" }, host: { properties: { "attr.aria-label": "this.ariaLabel", "attr.role": "this.role" } }, providers: [ DashboardService, DashboardGrabHandleService ], queries: [{ propertyName: "handles", predicate: DashboardGrabHandleDirective, descendants: true }], viewQueries: [{ propertyName: "dashboardElement", first: true, predicate: ["dashboard"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #dashboard class=\"dashboard-container\" [style.height.px]=\"dashboardService.height$ | async\">\n <div (uxResize)=\"onResize($event)\" [throttle]=\"16\" class=\"dashboard\">\n <ng-content></ng-content>\n </div>\n\n <!-- Wrap with ngIf so we only have one subscription rather than one for each property -->\n @if (dashboardService.placeholder$ | async; as placeholder) {\n @if (placeholder.visible) {\n <div class=\"position-indicator\"\n [style.left.px]=\"placeholder.x\"\n [style.top.px]=\"placeholder.y\"\n [style.width.px]=\"placeholder.width\"\n [style.height.px]=\"placeholder.height\">\n </div>\n }\n }\n</div>", dependencies: [{ kind: "directive", type: i1.ResizeDirective, selector: "[uxResize]", inputs: ["throttle"], outputs: ["uxResize"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: DashboardComponent, decorators: [{ type: Component, args: [{ selector: 'ux-dashboard', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ DashboardService, DashboardGrabHandleService ], template: "<div #dashboard class=\"dashboard-container\" [style.height.px]=\"dashboardService.height$ | async\">\n <div (uxResize)=\"onResize($event)\" [throttle]=\"16\" class=\"dashboard\">\n <ng-content></ng-content>\n </div>\n\n <!-- Wrap with ngIf so we only have one subscription rather than one for each property -->\n @if (dashboardService.placeholder$ | async; as placeholder) {\n @if (placeholder.visible) {\n <div class=\"position-indicator\"\n [style.left.px]=\"placeholder.x\"\n [style.top.px]=\"placeholder.y\"\n [style.width.px]=\"placeholder.width\"\n [style.height.px]=\"placeholder.height\">\n </div>\n }\n }\n</div>" }] }], ctorParameters: () => [], propDecorators: { customAriaLabel: [{ type: Input, args: ['aria-label'] }], layout: [{ type: Input }], options: [{ type: Input }], layoutChange: [{ type: Output }], ariaLabel: [{ type: HostBinding, args: ['attr.aria-label'] }], role: [{ type: HostBinding, args: ['attr.role'] }, { type: Input }], dashboardElement: [{ type: ViewChild, args: ['dashboard', { static: true }] }], handles: [{ type: ContentChildren, args: [DashboardGrabHandleDirective, { descendants: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFzaGJvYXJkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2Rhc2hib2FyZC9kYXNoYm9hcmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvZGFzaGJvYXJkL2Rhc2hib2FyZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQW1DLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQWMsWUFBWSxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUF3QixNQUFNLEVBQWEsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xQLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFckQsT0FBTyxFQUF1QixnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM1RixPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNuRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQzs7OztBQVkvRSxNQUFNLE9BQU8sa0JBQWtCO0lBVTNCLHFMQUFxTDtJQUNyTCxJQUFhLE1BQU0sQ0FBQyxNQUE2QjtRQUM3QyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0MsQ0FBQztJQUNMLENBQUM7SUFFRCw4R0FBOEc7SUFDOUcsSUFBYSxPQUFPLENBQUMsT0FBeUI7UUFDMUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLGNBQWMsRUFBRSxHQUFH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QUNJLGNBQWMsbUJBRVAsdUJBQXVCLENBQUMsTUFBTSxhQUNwQzt3QkFDUCxnQkFBZ0I7d0JBQ2hCLDBCQUEwQjtxQkFDN0I7d0RBVW9CLGVBQWU7c0JBQW5DLEtBQUs7dUJBQUMsWUFBWTtnQkFHTixNQUFNO3NCQUFsQixLQUFLO2dCQU9PLE9BQU87c0JBQW5CLEtBQUs7Z0JBS0ksWUFBWTtzQkFBckIsTUFBTTtnQkFFeUIsU0FBUztzQkFBeEMsV0FBVzt1QkFBQyxpQkFBaUI7Z0JBQ0ssSUFBSTtzQkFBdEMsV0FBVzt1QkFBQyxXQUFXOztzQkFBRyxLQUFLO2dCQUVVLGdCQUFnQjtzQkFBekQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUc4QixPQUFPO3NCQUE1RSxlQUFlO3VCQUFDLDRCQUE0QixFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyQ29udGVudEluaXQsIEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGRyZW4sIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIGluamVjdCwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPdXRwdXQsIFF1ZXJ5TGlzdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIHRha2VVbnRpbCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgUmVzaXplRGltZW5zaW9ucyB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvcmVzaXplL3Jlc2l6ZS5zZXJ2aWNlJztcbmltcG9ydCB7IERhc2hib2FyZExheW91dERhdGEsIERhc2hib2FyZFNlcnZpY2UsIGRlZmF1bHRPcHRpb25zIH0gZnJvbSAnLi9kYXNoYm9hcmQuc2VydmljZSc7XG5pbXBvcnQgeyBEYXNoYm9hcmRHcmFiSGFuZGxlRGlyZWN0aXZlIH0gZnJvbSAnLi9ncmFiLWhhbmRsZS9ncmFiLWhhbmRsZS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgRGFzaGJvYXJkR3JhYkhhbmRsZVNlcnZpY2UgfSBmcm9tICcuL2dyYWItaGFuZGxlL2dyYWItaGFuZGxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50IH0gZnJvbSAnLi93aWRnZXQvZGFzaGJvYXJkLXdpZGdldC5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3V4LWRhc2hib2FyZCcsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2Rhc2hib2FyZC5jb21wb25lbnQuaHRtbCcsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIERhc2hib2FyZFNlcnZpY2UsXG4gICAgICAgIERhc2hib2FyZEdyYWJIYW5kbGVTZXJ2aWNlXG4gICAgXVxufSlcbmV4cG9ydCBjbGFzcyBEYXNoYm9hcmRDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBBZnRlckNvbnRlbnRJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XG5cbiAgICByZWFkb25seSBkYXNoYm9hcmRTZXJ2aWNlID0gaW5qZWN0KERhc2hib2FyZFNlcnZpY2UpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gICAgaXNHcmFiYmluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgQElucHV0KCdhcmlhLWxhYmVsJykgY3VzdG9tQXJpYUxhYmVsOiAod2lkZ2V0czogRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50W10sIG9wdGlvbnM6IERhc2hib2FyZE9wdGlvbnMpID0+IHN0cmluZyB8IHN0cmluZyA9IHRoaXMuZ2V0RGVmYXVsdEFyaWFMYWJlbDtcblxuICAgIC8qKiBJZiBkZWZpbmVkIG9yIGNoYW5nZWQgdGhpcyB3aWxsIHNldCB0aGUgcG9zaXRpb25zIG9mIHRoZSB3aWRnZXRzIHdpdGhpbiB0aGUgZGFzaGJvYXJkLiBUaGlzIGlzIGEgdHdvIHdheSBiaW5kaW5nIHRoYXQgd2lsbCBiZSB1cGRhdGVkIHdpdGggdGhlIGN1cnJlbnQgbGF5b3V0IHdoZW4gaXQgY2hhbmdlcy4gKi9cbiAgICBASW5wdXQoKSBzZXQgbGF5b3V0KGxheW91dDogRGFzaGJvYXJkTGF5b3V0RGF0YVtdKSB7XG4gICAgICAgIGlmIChsYXlvdXQpIHtcbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5sYXlvdXQkLm5leHQobGF5b3V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBDb25maWd1cmVzIHRoZSBvcHRpb25zIGZvciB0aGUgZGFzaGJvYXJkLCBpZiBhbiBvcHRpb24gaXMgbm90IHNwZWNpZmllZCB0aGUgZGVmYXVsdCB2YWx1ZSB3aWxsIGJlIHVzZWQuICovXG4gICAgQElucHV0KCkgc2V0IG9wdGlvbnMob3B0aW9uczogRGFzaGJvYXJkT3B0aW9ucykge1xuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2Uub3B0aW9ucyQubmV4dCh7IC4uLmRlZmF1bHRPcHRpb25zLCAuLi5vcHRpb25zIH0pO1xuICAgIH1cblxuICAgIC8qKiBFbWl0cyB3aGVuIGxheW91dCBoYXMgYmVlbiBjaGFuZ2VkLiAqL1xuICAgIEBPdXRwdXQoKSBsYXlvdXRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPERhc2hib2FyZExheW91dERhdGFbXT4oKTtcblxuICAgIEBIb3N0QmluZGluZygnYXR0ci5hcmlhLWxhYmVsJykgYXJpYUxhYmVsOiBzdHJpbmc7XG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLnJvbGUnKSBASW5wdXQoKSByb2xlOiBzdHJpbmcgPSAncmVnaW9uJztcblxuICAgIEBWaWV3Q2hpbGQoJ2Rhc2hib2FyZCcsIHsgc3RhdGljOiB0cnVlIH0pIGRhc2hib2FyZEVsZW1lbnQ6IEVsZW1lbnRSZWY7XG5cbiAgICAvKiogRmluZCBhbGwgZ3JhYiBoYW5kbGVzIHVzZWQgaW4gdGhlIGRhc2hib2FyZCAqL1xuICAgIEBDb250ZW50Q2hpbGRyZW4oRGFzaGJvYXJkR3JhYkhhbmRsZURpcmVjdGl2ZSwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBoYW5kbGVzOiBRdWVyeUxpc3Q8RGFzaGJvYXJkR3JhYkhhbmRsZURpcmVjdGl2ZT47XG5cbiAgICAvKiogRW5zdXJlIHdlIHVuc3Vic2NyaWJlIGZyb20gYWxsIG9ic2VydmFibGVzICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuXG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5sYXlvdXQkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSksIHRhcCgoKSA9PiB0aGlzLmFyaWFMYWJlbCA9IHRoaXMuZ2V0QXJpYUxhYmVsKCkpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKSk7XG5cbiAgICAgICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS51c2VyTGF5b3V0Q2hhbmdlJC5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKS5zdWJzY3JpYmUoZGF0YSA9PiB0aGlzLmxheW91dENoYW5nZS5lbWl0KGRhdGEpKTtcblxuICAgICAgICAvLyBzdWJzY3JpYmUgdG8gY2hhbmdlcyB0byB0aGUgZ3JhYiBtb2RlXG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5pc0dyYWJiaW5nJC5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpLCBtYXAod2lkZ2V0ID0+ICEhd2lkZ2V0KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoaXNHcmFiYmluZyA9PiB0aGlzLmlzR3JhYmJpbmcgPSBpc0dyYWJiaW5nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGluaXRpYWwgZGltZW5zaW9uc1xuICAgICAqL1xuICAgIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgLy8gc2V0IHRoZSBpbml0aWFsIGRpbWVuc2lvbnNcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLnNldERpbWVuc2lvbnModGhpcy5kYXNoYm9hcmRFbGVtZW50Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGgsIHRoaXMuZGFzaGJvYXJkRWxlbWVudC5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCk7XG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2UuaW5pdGlhbGl6ZWQkLm5leHQodHJ1ZSk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGFzaGJvYXJkU2VydmljZS5yZW5kZXJEYXNoYm9hcmQoKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgb25SZXNpemUoZXZlbnQ6IFJlc2l6ZURpbWVuc2lvbnMpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLnNldERpbWVuc2lvbnMoZXZlbnQud2lkdGgsIGV2ZW50LmhlaWdodCk7XG4gICAgfVxuXG4gICAgZ2V0QXJpYUxhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0aGlzLmN1c3RvbUFyaWFMYWJlbCAmJiB0eXBlb2YgdGhpcy5jdXN0b21BcmlhTGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jdXN0b21BcmlhTGFiZWw7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jdXN0b21BcmlhTGFiZWwgJiYgdHlwZW9mIHRoaXMuY3VzdG9tQXJpYUxhYmVsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jdXN0b21BcmlhTGFiZWwodGhpcy5kYXNoYm9hcmRTZXJ2aWNlLndpZGdldHMsIHRoaXMuZGFzaGJvYXJkU2VydmljZS5vcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmFyaWFMYWJlbDtcbiAgICB9XG5cbiAgICAvKiogU2hpZnQgd2lkZ2V0cyB1cCB3aGVyZSBwb3NzaWJsZSB0byBmaWxsIGFueSBhdmFpbGFibGUgc3BhY2UgdG8gb3B0aW1pemUgdGhlIGRhc2hib2FyZCBsYXlvdXQgKi9cbiAgICByZWZyZXNoTGF5b3V0KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBkaWRDaGFuZ2VMYXlvdXQgPSB0aGlzLmRhc2hib2FyZFNlcnZpY2Uuc2hpZnRXaWRnZXRzVXAoKTtcblxuICAgICAgICBpZiAoZGlkQ2hhbmdlTGF5b3V0KSB7XG4gICAgICAgICAgICAvLyBpZiB3aWRnZXRzIGhhdmUgc2hpZnRlZCB1cCB0aGUgZGFzaGJvYXJkIG1heSBubyBsb25nZXIgb2NjdXB5IHRoZSBzYW1lXG4gICAgICAgICAgICAvLyBoZWlnaHQuIFdlIHNob3VsZCByZW1vdmUgYW55IHVubmVlZGVkIHdoaXRlc3BhY2UgYmVsb3cgd2lkZ2V0cyB0b28uXG4gICAgICAgICAgICB0aGlzLmRhc2hib2FyZFNlcnZpY2Uuc2V0RGFzaGJvYXJkSGVpZ2h0KCk7XG5cbiAgICAgICAgICAgIC8vIGVtaXQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGxheW91dFxuICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRTZXJ2aWNlLmxheW91dCQubmV4dCh0aGlzLmRhc2hib2FyZFNlcnZpY2UuZ2V0TGF5b3V0RGF0YSgpKTtcbiAgICAgICAgICAgIHRoaXMubGF5b3V0Q2hhbmdlLmVtaXQodGhpcy5kYXNoYm9hcmRTZXJ2aWNlLmxheW91dCQudmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXREZWZhdWx0QXJpYUxhYmVsKHdpZGdldHM6IERhc2hib2FyZFdpZGdldENvbXBvbmVudFtdLCBvcHRpb25zOiBEYXNoYm9hcmRPcHRpb25zKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGBEYXNoYm9hcmQgd2l0aCAkeyBvcHRpb25zLmNvbHVtbnMgfSBjb2x1bW5zLCBjb250YWluaW5nICR7IHdpZGdldHMubGVuZ3RoIH0gcGFuZWxzLiAkeyB3aWRnZXRzLm1hcCh0aGlzLmdldFdpZGdldEFyaWFMYWJlbCkuam9pbignICcpIH1gO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0V2lkZ2V0QXJpYUxhYmVsKHdpZGdldDogRGFzaGJvYXJkV2lkZ2V0Q29tcG9uZW50KTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGAkeyB3aWRnZXQubmFtZSB9IHBhbmVsIGluIHJvdyAkeyB3aWRnZXQuZ2V0Um93KCkgfSwgY29sdW1uICR7IHdpZGdldC5nZXRDb2x1bW4oKSB9LCBpcyAkeyB3aWRnZXQuZ2V0Q29sdW1uU3BhbigpIH0gY29sdW1ucyB3aWRlIGFuZCAkeyB3aWRnZXQuZ2V0Um93U3BhbigpIH0gcm93cyBoaWdoLmA7XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhc2hib2FyZE9wdGlvbnMge1xuICAgIGNvbHVtbnM/OiBudW1iZXI7XG4gICAgcGFkZGluZz86IG51bWJlcjtcbiAgICBtaW5XaWR0aD86IG51bWJlcjtcbiAgICBtaW5IZWlnaHQ/OiBudW1iZXI7XG4gICAgcm93SGVpZ2h0PzogbnVtYmVyO1xuICAgIGVtcHR5Um93PzogYm9vbGVhbjtcbn1cbiIsIjxkaXYgI2Rhc2hib2FyZCBjbGFzcz1cImRhc2hib2FyZC1jb250YWluZXJcIiBbc3R5bGUuaGVpZ2h0LnB4XT1cImRhc2hib2FyZFNlcnZpY2UuaGVpZ2h0JCB8IGFzeW5jXCI+XG4gIDxkaXYgKHV4UmVzaXplKT1cIm9uUmVzaXplKCRldmVudClcIiBbdGhyb3R0bGVdPVwiMTZcIiBjbGFzcz1cImRhc2hib2FyZFwiPlxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgPC9kaXY+XG5cbiAgPCEtLSBXcmFwIHdpdGggbmdJZiBzbyB3ZSBvbmx5IGhhdmUgb25lIHN1YnNjcmlwdGlvbiByYXRoZXIgdGhhbiBvbmUgZm9yIGVhY2ggcHJvcGVydHkgLS0+XG4gIEBpZiAoZGFzaGJvYXJkU2VydmljZS5wbGFjZWhvbGRlciQgfCBhc3luYzsgYXMgcGxhY2Vob2xkZXIpIHtcbiAgICBAaWYgKHBsYWNlaG9sZGVyLnZpc2libGUpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJwb3NpdGlvbi1pbmRpY2F0b3JcIlxuICAgICAgICBbc3R5bGUubGVmdC5weF09XCJwbGFjZWhvbGRlci54XCJcbiAgICAgICAgW3N0eWxlLnRvcC5weF09XCJwbGFjZWhvbGRlci55XCJcbiAgICAgICAgW3N0eWxlLndpZHRoLnB4XT1cInBsYWNlaG9sZGVyLndpZHRoXCJcbiAgICAgICAgW3N0eWxlLmhlaWdodC5weF09XCJwbGFjZWhvbGRlci5oZWlnaHRcIj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgfVxuPC9kaXY+Il19