@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
200 lines • 32.8 kB
JavaScript
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