UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

200 lines 32.8 kB
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, Output, QueryList, ViewChild, ViewChildren, forwardRef } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { InventoryService } from '@c8y/client'; import { of } from 'rxjs'; import { first, startWith, map, switchMap } from 'rxjs/operators'; import { AssetSelectorBase } from './asset-selector-base'; import { AssetSelectorComponent } from './asset-selector.component'; import { AssetSelectorService } from './asset-selector.service'; import { GroupNode } from './group-node'; import { GroupNodeService } from './group-node.service'; import { gettext } from '@c8y/ngx-components'; import * as i0 from "@angular/core"; import * as i1 from "./group-node.service"; import * as i2 from "@c8y/client"; import * as i3 from "./asset-selector.service"; import * as i4 from "@c8y/ngx-components"; import * as i5 from "@angular/common"; import * as i6 from "./asset-selector.component"; export class MillerViewComponent extends AssetSelectorBase { constructor(groupNodeService, inventory, assetSelectorService, cd) { super(groupNodeService, inventory, assetSelectorService); this.groupNodeService = groupNodeService; this.inventory = inventory; this.assetSelectorService = assetSelectorService; this.cd = cd; /** * Config object containing all options for the asset selector. */ this.config = {}; /** * The asset to use as root. */ this.asset = undefined; /** * The selected devices. */ this.selectedDevice = undefined; /** * Emits if the selection changes */ this.onSelected = new EventEmitter(); /** * Emits if the currently selected asset is cleared. */ this.onClearSelected = new EventEmitter(); /** * The column array will contain all currently selected nodes * which will form the miller view columns (only one per level). */ this.columns = []; /** * The current filter applied. Used for the empty state text in the view. */ this.filterText = ''; this.container = 'body'; this.configOptionsDefault = { view: 'miller', singleColumn: false, label: gettext('Asset selection') }; /** * The height of the first asset selector header. */ this.assetSelectorHeaderHeight$ = of('0px'); } /** * @ignore */ async ngOnInit() { this.config = { ...this.configOptionsDefault, ...this.config }; const isAnyNodeDefined = !this.rootNode && (!this.asset || Object.keys(this.asset).length === 0); if (isAnyNodeDefined) { this.rootNode = this.createDefaultRootNode(); } const isOnlyAssetNodeDefined = this.asset && Object.keys(this.asset).length !== 0; if (isOnlyAssetNodeDefined) { this.rootNode = await this.createManagedObjectRootNode(this.asset); this.rootNode.click(); const selected = this.selectedDevice || this.asset; this.selected = [selected]; this.emitChange(this.selected, selected, true); } this.columns.push(this.rootNode); } /** * @ignore */ async ngOnChanges(changes) { if (changes.asset && changes.asset.currentValue && !this.asset) { this.columns = []; this.columns.push(await this.createManagedObjectRootNode(changes.asset.currentValue)); } if (changes.selectedDevice && changes.selectedDevice.currentValue) { this.selected = [this.selectedDevice]; this.emitChange(this.selected, this.selectedDevice, true); } } /** * @ignore */ ngAfterViewInit() { requestAnimationFrame(() => { this.assetSelectorHeaderHeight$ = this.assetSelectors.changes.pipe(startWith(this.assetSelectors.toArray()), first(), switchMap(assetSelector => assetSelector[0] ? assetSelector[0].getHeaderHeight$ : of('0')), map(height => height + 'px')); }); } /** * Create a new column with the selected node as root. */ addNewColumn(node) { const level = node.index; this.selectedDevice = node.selectedDevices || undefined; if (node.root) { window.requestAnimationFrame(() => (this.millerViewWrapper.nativeElement.scrollLeft = 0)); this.columns.length = 1; } const isLevelLowerThanColumnNumber = level < this.columns.length - 1; let goBack = false; if (isLevelLowerThanColumnNumber) { this.columns.length = level + 1; goBack = true; } if (!node.root && !(this.config.singleColumn && goBack)) { this.columns.push(node.nodeCopy); // eslint-disable-next-line @typescript-eslint/no-this-alias const col = this; window.requestAnimationFrame(() => (col.millerViewWrapper.nativeElement.scrollLeft = 50000)); /* triggered twice with a small delay as a workaround for dealing with Safari's bug: "Safari doesn’t update the scrollTop / scrollLeft properties of an element its any of its ancestors has overflow set to hidden." This was reported on customer portal with the ticket SI-488573 */ setTimeout(function () { window.requestAnimationFrame(() => (col.millerViewWrapper.nativeElement.scrollLeft = 55000)); }, 700); } } /** * Change the loading state of the asset selector. */ onLoad(event) { this.isLoading = event.loading; this.filterText = event.filterText; this.columnIndex = event.index; this.selectedDevice = event.selectedDevice; this.cd.detectChanges(); } /** * Add the selected node to the selected array. */ onSelectionChange(event) { if (!this.config.multi) { this.deselectAll(event.change.item); return; } if (event.change.isSelected) { this.select(event.change.item); return; } this.deselect(event.change.item); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MillerViewComponent, deps: [{ token: i1.GroupNodeService }, { token: i2.InventoryService }, { token: i3.AssetSelectorService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: { config: "config", asset: "asset", selectedDevice: "selectedDevice", rootNode: "rootNode", container: "container" }, outputs: { onSelected: "onSelected", onClearSelected: "onClearSelected" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MillerViewComponent), multi: true } ], viewQueries: [{ propertyName: "millerViewWrapper", first: true, predicate: ["millerViewWrapper"], descendants: true }, { propertyName: "assetSelectors", predicate: AssetSelectorComponent, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"miller-view-wrapper {{ config.label }}\"\n [ngStyle]=\"{\n 'padding-top': selectedDevice ? '0px' : (assetSelectorHeaderHeight$ | async)\n }\"\n #millerViewWrapper\n [ngClass]=\"{\n 'single-column': config.singleColumn,\n }\"\n>\n <div\n class=\"miller-column bg-inherit\"\n *ngFor=\"let column of columns; index as i\"\n >\n <c8y-asset-selector\n class=\"bg-inherit\"\n #assetSelector\n [config]=\"config\"\n [index]=\"i\"\n [active]=\"columns[i + 1]\"\n [rootNode]=\"column\"\n [selected]=\"selected || []\"\n [selectedDevice]=\"selectedDevice\"\n (onSelected)=\"onSelectionChange($event)\"\n (onClearSelected)=\"onClearSelected.emit()\"\n (onRowSelected)=\"addNewColumn($event)\"\n (onLoad)=\"onLoad($event)\"\n [container]=\"container\"\n ></c8y-asset-selector>\n <div\n class=\"p-relative p-b-64\"\n *ngIf=\"isLoading && columnIndex === i && !selectedDevice\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"p-l-8 p-r-8\"\n *ngIf=\"!column.children.length && !isLoading\"\n >\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No results to display.' | translate\"\n [subtitle]=\"'The selected asset has no children.' | translate\"\n *ngIf=\"!filterText; else noSearchResults\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-template #noSearchResults>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No results to display for the current filter.' | translate\"\n [subtitle]=\"'There are no assets matching the filter.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </ng-template>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: i4.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i4.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i6.AssetSelectorComponent, selector: "c8y-asset-selector", inputs: ["config", "active", "index", "asset", "selectedDevice", "selected", "rootNode", "selectedItems", "container", "isNodeSelectable", "disabled"], outputs: ["onSelected", "onClearSelected", "onRowSelected", "onLoad"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MillerViewComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-asset-selector-miller', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MillerViewComponent), multi: true } ], template: "<div\n class=\"miller-view-wrapper {{ config.label }}\"\n [ngStyle]=\"{\n 'padding-top': selectedDevice ? '0px' : (assetSelectorHeaderHeight$ | async)\n }\"\n #millerViewWrapper\n [ngClass]=\"{\n 'single-column': config.singleColumn,\n }\"\n>\n <div\n class=\"miller-column bg-inherit\"\n *ngFor=\"let column of columns; index as i\"\n >\n <c8y-asset-selector\n class=\"bg-inherit\"\n #assetSelector\n [config]=\"config\"\n [index]=\"i\"\n [active]=\"columns[i + 1]\"\n [rootNode]=\"column\"\n [selected]=\"selected || []\"\n [selectedDevice]=\"selectedDevice\"\n (onSelected)=\"onSelectionChange($event)\"\n (onClearSelected)=\"onClearSelected.emit()\"\n (onRowSelected)=\"addNewColumn($event)\"\n (onLoad)=\"onLoad($event)\"\n [container]=\"container\"\n ></c8y-asset-selector>\n <div\n class=\"p-relative p-b-64\"\n *ngIf=\"isLoading && columnIndex === i && !selectedDevice\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"p-l-8 p-r-8\"\n *ngIf=\"!column.children.length && !isLoading\"\n >\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No results to display.' | translate\"\n [subtitle]=\"'The selected asset has no children.' | translate\"\n *ngIf=\"!filterText; else noSearchResults\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-template #noSearchResults>\n <c8y-ui-empty-state\n [icon]=\"'folder-open'\"\n [title]=\"'No results to display for the current filter.' | translate\"\n [subtitle]=\"'There are no assets matching the filter.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n </ng-template>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.GroupNodeService }, { type: i2.InventoryService }, { type: i3.AssetSelectorService }, { type: i0.ChangeDetectorRef }], propDecorators: { config: [{ type: Input }], asset: [{ type: Input }], selectedDevice: [{ type: Input }], rootNode: [{ type: Input }], onSelected: [{ type: Output }], onClearSelected: [{ type: Output }], millerViewWrapper: [{ type: ViewChild, args: ['millerViewWrapper'] }], container: [{ type: Input }], assetSelectors: [{ type: ViewChildren, args: [AssetSelectorComponent] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlsbGVyLXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXNzZXRzLW5hdmlnYXRvci9hc3NldC1zZWxlY3Rvci9taWxsZXItdmlldy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9hc3NldHMtbmF2aWdhdG9yL2Fzc2V0LXNlbGVjdG9yL21pbGxlci12aWV3LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEVBRVQsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUErQixnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1RSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFCLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVwRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7Ozs7Ozs7QUFhOUMsTUFBTSxPQUFPLG1CQUFvQixTQUFRLGlCQUFpQjtJQTBEeEQsWUFDWSxnQkFB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RSxJQUFJO3lCQUNaO3FCQUNGO3VMQU1RLE1BQU07c0JBQWQsS0FBSztnQkFJRyxLQUFLO3NCQUFiLEtBQUs7Z0JBSUcsY0FBYztzQkFBdEIsS0FBSztnQkFJRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlJLFVBQVU7c0JBQW5CLE1BQU07Z0JBSUcsZUFBZTtzQkFBeEIsTUFBTTtnQkFJeUIsaUJBQWlCO3NCQUFoRCxTQUFTO3VCQUFDLG1CQUFtQjtnQkFjckIsU0FBUztzQkFBakIsS0FBSztnQkFjRSxjQUFjO3NCQURyQixZQUFZO3VCQUFDLHNCQUFzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBmb3J3YXJkUmVmXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBJSWRlbnRpZmllZCwgSU1hbmFnZWRPYmplY3QsIEludmVudG9yeVNlcnZpY2UgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlyc3QsIHN0YXJ0V2l0aCwgbWFwLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBc3NldFNlbGVjdG9yQmFzZSB9IGZyb20gJy4vYXNzZXQtc2VsZWN0b3ItYmFzZSc7XG5pbXBvcnQgeyBBc3NldFNlbGVjdG9yQ29tcG9uZW50IH0gZnJvbSAnLi9hc3NldC1zZWxlY3Rvci5jb21wb25lbnQnO1xuaW1wb3J0IHsgQXNzZXRTZWxlY3Rpb25DaGFuZ2VFdmVudCwgQXNzZXRTZWxlY3Rvck9wdGlvbnMgfSBmcm9tICcuL2Fzc2V0LXNlbGVjdG9yLm1vZGVsJztcbmltcG9ydCB7IEFzc2V0U2VsZWN0b3JTZXJ2aWNlIH0gZnJvbSAnLi9hc3NldC1zZWxlY3Rvci5zZXJ2aWNlJztcbmltcG9ydCB7IEdyb3VwTm9kZSB9IGZyb20gJy4vZ3JvdXAtbm9kZSc7XG5pbXBvcnQgeyBHcm91cE5vZGVTZXJ2aWNlIH0gZnJvbSAnLi9ncm91cC1ub2RlLnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktYXNzZXQtc2VsZWN0b3ItbWlsbGVyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL21pbGxlci12aWV3LmNvbXBvbmVudC5odG1sJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBNaWxsZXJWaWV3Q29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIE1pbGxlclZpZXdDb21wb25lbnQgZXh0ZW5kcyBBc3NldFNlbGVjdG9yQmFzZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8qKlxuICAgKiBDb25maWcgb2JqZWN0IGNvbnRhaW5pbmcgYWxsIG9wdGlvbnMgZm9yIHRoZSBhc3NldCBzZWxlY3Rvci5cbiAgICovXG4gIEBJbnB1dCgpIGNvbmZpZzogQXNzZXRTZWxlY3Rvck9wdGlvbnMgPSB7fTtcbiAgLyoqXG4gICAqIFRoZSBhc3NldCB0byB1c2UgYXMgcm9vdC5cbiAgICovXG4gIEBJbnB1dCgpIGFzc2V0OiBJSWRlbnRpZmllZCA9IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIFRoZSBzZWxlY3RlZCBkZXZpY2VzLlxuICAgKi9cbiAgQElucHV0KCkgc2VsZWN0ZWREZXZpY2U6IElNYW5hZ2VkT2JqZWN0ID0gdW5kZWZpbmVkO1xuICAvKipcbiAgICogVGhlIG5vZGUgdG8gdXNlIGFzIHJvb3QuIFlvdSBjYW4gZWl0aGVyIHNldCB0aGlzLCBvciB0aGUgYXNzZXQgdG8gc3RhcnQgZnJvbS5cbiAgICovXG4gIEBJbnB1dCgpIHJvb3ROb2RlOiBHcm91cE5vZGU7XG4gIC8qKlxuICAgKiBFbWl0cyBpZiB0aGUgc2VsZWN0aW9uIGNoYW5nZXNcbiAgICovXG4gIEBPdXRwdXQoKSBvblNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxBc3NldFNlbGVjdGlvbkNoYW5nZUV2ZW50PigpO1xuICAvKipcbiAgICogRW1pdHMgaWYgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBhc3NldCBpcyBjbGVhcmVkLlxuICAgKi9cbiAgQE91dHB1dCgpIG9uQ2xlYXJTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIEBWaWV3Q2hpbGQoJ21pbGxlclZpZXdXcmFwcGVyJykgbWlsbGVyVmlld1dyYXBwZXI6IEVsZW1lbnRSZWY7XG4gIC8qKlxuICAgKiBUaGUgY29sdW1uIGFycmF5IHdpbGwgY29udGFpbiBhbGwgY3VycmVudGx5IHNlbGVjdGVkIG5vZGVzXG4gICAqICB3aGljaCB3aWxsIGZvcm0gdGhlIG1pbGxlciB2aWV3IGNvbHVtbnMgKG9ubHkgb25lIHBlciBsZXZlbCkuXG4gICAqL1xuICBjb2x1bW5zID0gW107XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBmaWx0ZXIgYXBwbGllZC4gVXNlZCBmb3IgdGhlIGVtcHR5IHN0YXRlIHRleHQgaW4gdGhlIHZpZXcuXG4gICAqL1xuICBmaWx0ZXJUZXh0ID0gJyc7XG4gIC8qKlxuICAgKiBJbmRleCBvZiB0aGUgY29sdW1uIHVzZWQgdG8gY2hlY2sgd2hlcmUgdG8gc2hvdyB0aGUgbG9hZGluZyBzdGF0ZS5cbiAgICovXG4gIGNvbHVtbkluZGV4OiBudW1iZXI7XG4gIEBJbnB1dCgpIGNvbnRhaW5lcjogJycgfCAnYm9keScgPSAnYm9keSc7XG5cbiAgY29uZmlnT3B0aW9uc0RlZmF1bHQ6IEFzc2V0U2VsZWN0b3JPcHRpb25zID0ge1xuICAgIHZpZXc6ICdtaWxsZXInLFxuICAgIHNpbmdsZUNvbHVtbjogZmFsc2UsXG4gICAgbGFiZWw6IGdldHRleHQoJ0Fzc2V0IHNlbGVjdGlvbicpXG4gIH07XG5cbiAgLyoqXG4gICAqIFRoZSBoZWlnaHQgb2YgdGhlIGZpcnN0IGFzc2V0IHNlbGVjdG9yIGhlYWRlci5cbiAgICovXG4gIGFzc2V0U2VsZWN0b3JIZWFkZXJIZWlnaHQkID0gb2YoJzBweCcpO1xuXG4gIEBWaWV3Q2hpbGRyZW4oQXNzZXRTZWxlY3RvckNvbXBvbmVudClcbiAgcHJpdmF0ZSBhc3NldFNlbGVjdG9yczogUXVlcnlMaXN0PEFzc2V0U2VsZWN0b3JDb21wb25lbnQ+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBncm91cE5vZGVTZXJ2aWNlOiBHcm91cE5vZGVTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBpbnZlbnRvcnk6IEludmVudG9yeVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGFzc2V0U2VsZWN0b3JTZXJ2aWNlOiBBc3NldFNlbGVjdG9yU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICAgIHN1cGVyKGdyb3VwTm9kZVNlcnZpY2UsIGludmVudG9yeSwgYXNzZXRTZWxlY3RvclNlcnZpY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIGFzeW5jIG5nT25Jbml0KCkge1xuICAgIHRoaXMuY29uZmlnID0geyAuLi50aGlzLmNvbmZpZ09wdGlvbnNEZWZhdWx0LCAuLi50aGlzLmNvbmZpZyB9O1xuXG4gICAgY29uc3QgaXNBbnlOb2RlRGVmaW5lZCA9XG4gICAgICAhdGhpcy5yb290Tm9kZSAmJiAoIXRoaXMuYXNzZXQgfHwgT2JqZWN0LmtleXModGhpcy5hc3NldCkubGVuZ3RoID09PSAwKTtcbiAgICBpZiAoaXNBbnlOb2RlRGVmaW5lZCkge1xuICAgICAgdGhpcy5yb290Tm9kZSA9IHRoaXMuY3JlYXRlRGVmYXVsdFJvb3ROb2RlKCk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNPbmx5QXNzZXROb2RlRGVmaW5lZCA9IHRoaXMuYXNzZXQgJiYgT2JqZWN0LmtleXModGhpcy5hc3NldCkubGVuZ3RoICE9PSAwO1xuICAgIGlmIChpc09ubHlBc3NldE5vZGVEZWZpbmVkKSB7XG4gICAgICB0aGlzLnJvb3ROb2RlID0gYXdhaXQgdGhpcy5jcmVhdGVNYW5hZ2VkT2JqZWN0Um9vdE5vZGUodGhpcy5hc3NldCk7XG4gICAgICB0aGlzLnJvb3ROb2RlLmNsaWNrKCk7XG4gICAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMuc2VsZWN0ZWREZXZpY2UgfHwgdGhpcy5hc3NldDtcbiAgICAgIHRoaXMuc2VsZWN0ZWQgPSBbc2VsZWN0ZWRdO1xuICAgICAgdGhpcy5lbWl0Q2hhbmdlKHRoaXMuc2VsZWN0ZWQsIHNlbGVjdGVkIGFzIElNYW5hZ2VkT2JqZWN0LCB0cnVlKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvbHVtbnMucHVzaCh0aGlzLnJvb3ROb2RlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBhc3luYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXMuYXNzZXQgJiYgY2hhbmdlcy5hc3NldC5jdXJyZW50VmFsdWUgJiYgIXRoaXMuYXNzZXQpIHtcbiAgICAgIHRoaXMuY29sdW1ucyA9IFtdO1xuICAgICAgdGhpcy5jb2x1bW5zLnB1c2goYXdhaXQgdGhpcy5jcmVhdGVNYW5hZ2VkT2JqZWN0Um9vdE5vZGUoY2hhbmdlcy5hc3NldC5jdXJyZW50VmFsdWUpKTtcbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlcy5zZWxlY3RlZERldmljZSAmJiBjaGFuZ2VzLnNlbGVjdGVkRGV2aWNlLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZCA9IFt0aGlzLnNlbGVjdGVkRGV2aWNlXTtcbiAgICAgIHRoaXMuZW1pdENoYW5nZSh0aGlzLnNlbGVjdGVkLCB0aGlzLnNlbGVjdGVkRGV2aWNlIGFzIElNYW5hZ2VkT2JqZWN0LCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICB0aGlzLmFzc2V0U2VsZWN0b3JIZWFkZXJIZWlnaHQkID0gdGhpcy5hc3NldFNlbGVjdG9ycy5jaGFuZ2VzLnBpcGUoXG4gICAgICAgIHN0YXJ0V2l0aCh0aGlzLmFzc2V0U2VsZWN0b3JzLnRvQXJyYXkoKSksXG4gICAgICAgIGZpcnN0KCksXG4gICAgICAgIHN3aXRjaE1hcChhc3NldFNlbGVjdG9yID0+XG4gICAgICAgICAgYXNzZXRTZWxlY3RvclswXSA/IGFzc2V0U2VsZWN0b3JbMF0uZ2V0SGVhZGVySGVpZ2h0JCA6IG9mKCcwJylcbiAgICAgICAgKSxcbiAgICAgICAgbWFwKGhlaWdodCA9PiBoZWlnaHQgKyAncHgnKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgY29sdW1uIHdpdGggdGhlIHNlbGVjdGVkIG5vZGUgYXMgcm9vdC5cbiAgICovXG4gIGFkZE5ld0NvbHVtbihub2RlKTogdm9pZCB7XG4gICAgY29uc3QgbGV2ZWwgPSBub2RlLmluZGV4O1xuICAgIHRoaXMuc2VsZWN0ZWREZXZpY2UgPSBub2RlLnNlbGVjdGVkRGV2aWNlcyB8fCB1bmRlZmluZWQ7XG4gICAgaWYgKG5vZGUucm9vdCkge1xuICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiAodGhpcy5taWxsZXJWaWV3V3JhcHBlci5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSAwKSk7XG4gICAgICB0aGlzLmNvbHVtbnMubGVuZ3RoID0gMTtcbiAgICB9XG5cbiAgICBjb25zdCBpc0xldmVsTG93ZXJUaGFuQ29sdW1uTnVtYmVyID0gbGV2ZWwgPCB0aGlzLmNvbHVtbnMubGVuZ3RoIC0gMTtcbiAgICBsZXQgZ29CYWNrID0gZmFsc2U7XG4gICAgaWYgKGlzTGV2ZWxMb3dlclRoYW5Db2x1bW5OdW1iZXIpIHtcbiAgICAgIHRoaXMuY29sdW1ucy5sZW5ndGggPSBsZXZlbCArIDE7XG4gICAgICBnb0JhY2sgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoIW5vZGUucm9vdCAmJiAhKHRoaXMuY29uZmlnLnNpbmdsZUNvbHVtbiAmJiBnb0JhY2spKSB7XG4gICAgICB0aGlzLmNvbHVtbnMucHVzaChub2RlLm5vZGVDb3B5KTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdGhpcy1hbGlhc1xuICAgICAgY29uc3QgY29sID0gdGhpcztcbiAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gKGNvbC5taWxsZXJWaWV3V3JhcHBlci5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSA1MDAwMCkpO1xuICAgICAgLyogdHJpZ2dlcmVkIHR3aWNlIHdpdGggYSBzbWFsbCBkZWxheSBhcyBhIHdvcmthcm91bmQgZm9yIGRlYWxpbmcgd2l0aCBTYWZhcmkncyBidWc6XG4gICAgICAgXCJTYWZhcmkgZG9lc27igJl0IHVwZGF0ZSB0aGUgc2Nyb2xsVG9wIC8gc2Nyb2xsTGVmdCBwcm9wZXJ0aWVzIG9mIGFuIGVsZW1lbnQgaXRzIGFueSBvZiBpdHNcbiAgICAgICAgYW5jZXN0b3JzIGhhcyBvdmVyZmxvdyBzZXQgdG8gaGlkZGVuLlwiXG4gICAgICAgIFRoaXMgd2FzIHJlcG9ydGVkIG9uIGN1c3RvbWVyIHBvcnRhbCB3aXRoIHRoZSB0aWNrZXQgU0ktNDg4NTczXG4gICAgICAqL1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoXG4gICAgICAgICAgKCkgPT4gKGNvbC5taWxsZXJWaWV3V3JhcHBlci5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSA1NTAwMClcbiAgICAgICAgKTtcbiAgICAgIH0sIDcwMCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoYW5nZSB0aGUgbG9hZGluZyBzdGF0ZSBvZiB0aGUgYXNzZXQgc2VsZWN0b3IuXG4gICAqL1xuICBvbkxvYWQoZXZlbnQpIHtcbiAgICB0aGlzLmlzTG9hZGluZyA9IGV2ZW50LmxvYWRpbmc7XG4gICAgdGhpcy5maWx0ZXJUZXh0ID0gZXZlbnQuZmlsdGVyVGV4dDtcbiAgICB0aGlzLmNvbHVtbkluZGV4ID0gZXZlbnQuaW5kZXg7XG4gICAgdGhpcy5zZWxlY3RlZERldmljZSA9IGV2ZW50LnNlbGVjdGVkRGV2aWNlO1xuICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCB0aGUgc2VsZWN0ZWQgbm9kZSB0byB0aGUgc2VsZWN0ZWQgYXJyYXkuXG4gICAqL1xuICBvblNlbGVjdGlvbkNoYW5nZShldmVudDogQXNzZXRTZWxlY3Rpb25DaGFuZ2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWcubXVsdGkpIHtcbiAgICAgIHRoaXMuZGVzZWxlY3RBbGwoZXZlbnQuY2hhbmdlLml0ZW0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZXZlbnQuY2hhbmdlLmlzU2VsZWN0ZWQpIHtcbiAgICAgIHRoaXMuc2VsZWN0KGV2ZW50LmNoYW5nZS5pdGVtKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5kZXNlbGVjdChldmVudC5jaGFuZ2UuaXRlbSk7XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJtaWxsZXItdmlldy13cmFwcGVyIHt7IGNvbmZpZy5sYWJlbCB9fVwiXG4gIFtuZ1N0eWxlXT1cIntcbiAgICAncGFkZGluZy10b3AnOiBzZWxlY3RlZERldmljZSA/ICcwcHgnIDogKGFzc2V0U2VsZWN0b3JIZWFkZXJIZWlnaHQkIHwgYXN5bmMpXG4gIH1cIlxuICAjbWlsbGVyVmlld1dyYXBwZXJcbiAgW25nQ2xhc3NdPVwie1xuICAgICdzaW5nbGUtY29sdW1uJzogY29uZmlnLnNpbmdsZUNvbHVtbixcbiAgfVwiXG4+XG4gIDxkaXZcbiAgICBjbGFzcz1cIm1pbGxlci1jb2x1bW4gYmctaW5oZXJpdFwiXG4gICAgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBjb2x1bW5zOyBpbmRleCBhcyBpXCJcbiAgPlxuICAgIDxjOHktYXNzZXQtc2VsZWN0b3JcbiAgICAgIGNsYXNzPVwiYmctaW5oZXJpdFwiXG4gICAgICAjYXNzZXRTZWxlY3RvclxuICAgICAgW2NvbmZpZ109XCJjb25maWdcIlxuICAgICAgW2luZGV4XT1cImlcIlxuICAgICAgW2FjdGl2ZV09XCJjb2x1bW5zW2kgKyAxXVwiXG4gICAgICBbcm9vdE5vZGVdPVwiY29sdW1uXCJcbiAgICAgIFtzZWxlY3RlZF09XCJzZWxlY3RlZCB8fCBbXVwiXG4gICAgICBbc2VsZWN0ZWREZXZpY2VdPVwic2VsZWN0ZWREZXZpY2VcIlxuICAgICAgKG9uU2VsZWN0ZWQpPVwib25TZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAob25DbGVhclNlbGVjdGVkKT1cIm9uQ2xlYXJTZWxlY3RlZC5lbWl0KClcIlxuICAgICAgKG9uUm93U2VsZWN0ZWQpPVwiYWRkTmV3Q29sdW1uKCRldmVudClcIlxuICAgICAgKG9uTG9hZCk9XCJvbkxvYWQoJGV2ZW50KVwiXG4gICAgICBbY29udGFpbmVyXT1cImNvbnRhaW5lclwiXG4gICAgPjwvYzh5LWFzc2V0LXNlbGVjdG9yPlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwicC1yZWxhdGl2ZSBwLWItNjRcIlxuICAgICAgKm5nSWY9XCJpc0xvYWRpbmcgJiYgY29sdW1uSW5kZXggPT09IGkgJiYgIXNlbGVjdGVkRGV2aWNlXCJcbiAgICA+XG4gICAgICA8Yzh5LWxvYWRpbmc+PC9jOHktbG9hZGluZz5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwicC1sLTggcC1yLThcIlxuICAgICAgKm5nSWY9XCIhY29sdW1uLmNoaWxkcmVuLmxlbmd0aCAmJiAhaXNMb2FkaW5nXCJcbiAgICA+XG4gICAgICA8Yzh5LXVpLWVtcHR5LXN0YXRlXG4gICAgICAgIFtpY29uXT1cIidmb2xkZXItb3BlbidcIlxuICAgICAgICBbdGl0bGVdPVwiJ05vIHJlc3VsdHMgdG8gZGlzcGxheS4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgW3N1YnRpdGxlXT1cIidUaGUgc2VsZWN0ZWQgYXNzZXQgaGFzIG5vIGNoaWxkcmVuLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAqbmdJZj1cIiFmaWx0ZXJUZXh0OyBlbHNlIG5vU2VhcmNoUmVzdWx0c1wiXG4gICAgICAgIFtob3Jpem9udGFsXT1cInRydWVcIlxuICAgICAgPjwvYzh5LXVpLWVtcHR5LXN0YXRlPlxuICAgICAgPG5nLXRlbXBsYXRlICNub1NlYXJjaFJlc3VsdHM+XG4gICAgICAgIDxjOHktdWktZW1wdHktc3RhdGVcbiAgICAgICAgICBbaWNvbl09XCInZm9sZGVyLW9wZW4nXCJcbiAgICAgICAgICBbdGl0bGVdPVwiJ05vIHJlc3VsdHMgdG8gZGlzcGxheSBmb3IgdGhlIGN1cnJlbnQgZmlsdGVyLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIFtzdWJ0aXRsZV09XCInVGhlcmUgYXJlIG5vIGFzc2V0cyBtYXRjaGluZyB0aGUgZmlsdGVyLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIFtob3Jpem9udGFsXT1cInRydWVcIlxuICAgICAgICA+PC9jOHktdWktZW1wdHktc3RhdGU+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19