UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

366 lines 66.3 kB
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, Output, ViewChild, forwardRef } from '@angular/core'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { InventoryService } from '@c8y/client'; import { BehaviorSubject, Subject } from 'rxjs'; import { takeUntil, tap } from 'rxjs/operators'; import { AssetSelectorBase } from './asset-selector-base'; import { CONFIG_OPTIONS_DEFAULT } from './asset-selector.model'; import { AssetSelectorService } from './asset-selector.service'; import { GroupNode } from './group-node'; import { GroupNodeService } from './group-node.service'; import { UnassignedDevicesNode } from './unassigned-devices-node'; 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 "@angular/forms"; import * as i7 from "./asset-selector-node.component"; /** * Displays a hierarchical tree selector for assets. */ export class AssetSelectorComponent extends AssetSelectorBase { /** * @ignore only DI */ 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 = {}; /** * Used only for miller-view, displays the column level for the current node. * E.g if the index is one, this will be second column. */ this.index = 0; /** * The asset to use as root. */ this.asset = undefined; /** * The selected device. */ this.selectedDevice = undefined; /** * An array of predefined nodes. */ this.selected = []; /** * All currently selected assets. */ this.selectedItems = []; this.container = 'body'; this.isNodeSelectable = true; this.disabled = false; /** * Emits if one item was selected (all currently selected nodes). */ this.onSelected = new EventEmitter(); /** * Emits if the currently selected asset is cleared. */ this.onClearSelected = new EventEmitter(); /** * Used only for miller view. Emit the selected node and use it as a 'rootNode' for the new column. */ this.onRowSelected = new EventEmitter(); /** * Emits the current loading state of the node. */ this.onLoad = new EventEmitter(); /** * The current filter applied. */ this.filterText = ''; /** * Displays the global search at all times if the miller view is used * on root group level. */ this.root = false; /** * @ignore */ this.unsubscribe$ = new Subject(); /** * Returns the current header hight in pixel. */ this.getHeaderHeight$ = new BehaviorSubject(0); this.ASSET_CONST = gettext('Asset {{ assetId }}'); } /** * Checks when a node was selected, if a new column needs to be added. * @param node The node that was clicked. * @param index The current index of this node. * @returns True if the click was handled and a new column was added. */ handleNextMillerViewColumn(node, index) { const nodeCopy = Object.create(node); const isSameAsRoot = this.rootNode === node; const isUnassignedDevicesNode = node.toString() === UnassignedDevicesNode.NAME; const isNewColumnNeeded = !isSameAsRoot && (node.isGroup() || isUnassignedDevicesNode || node.hasChildDevices()); if (isNewColumnNeeded) { this.onRowSelected.emit({ nodeCopy, index }); return false; } return true; } /** * @ignore */ async ngOnInit() { this.assetSelectorService.setIsNodeSelectable(this.isNodeSelectable); if (this.index === 0) { this.config = { ...CONFIG_OPTIONS_DEFAULT, ...this.config }; } const shouldResetNameFilter = this.rootNode && this.rootNode.mo && this.config.view === 'miller'; if (shouldResetNameFilter) { await this.applyFilter(''); } const isOnlyAssetNodeDefined = this.asset; if (isOnlyAssetNodeDefined) { this.rootNode = await this.createManagedObjectRootNode(this.asset); } const isAnyNodeDefined = !this.rootNode && (!this.asset || Object.keys(this.asset).length === 0); if (isAnyNodeDefined) { this.rootNode = this.createDefaultRootNode(); } if (this.config.showUnassignedDevices && (!this.asset || Object.keys(this.asset).length === 0) && this.rootNode.root) { this.rootNode.add(new UnassignedDevicesNode(this.groupNodeService, { showChildDevices: this.config.showChildDevices })); } this.root = this.rootNode.root; } async ngOnChanges(changes) { if (changes.isNodeSelectable) { this.assetSelectorService.setIsNodeSelectable(this.isNodeSelectable); } if (changes.asset && changes.asset.currentValue && Object.keys(changes.asset.currentValue).length !== 0) { this.rootNode = await this.createManagedObjectRootNode(changes.asset.currentValue); } } /** * @ignore */ ngAfterViewInit() { requestAnimationFrame(() => { if (this.header?.nativeElement) { this.getHeaderHeight$.next(this.header.nativeElement.clientHeight); } else { this.getHeaderHeight$.next(0); } }); } /** * Changes the current root to one level back. */ back() { const index = this.index - 1; const nodeCopy = Object.create(this.rootNode.parents[0]); this.onRowSelected.emit({ nodeCopy, index }); } /** * Clears the current filter. */ clearFilters() { this.filterText = ''; this.applyFilter(''); } clearSelectedDevices() { this.selectedDevice = undefined; this.applyFilter(''); this.onClearSelected.emit(); } isGroupSelected() { if (this.selected.some(selectedNode => selectedNode.id === this.rootNode.mo?.id)) { return true; } return false; } groupNameFilter(nameFilter, moId, showUnassignedDevices) { if (nameFilter) { const filterByName = showUnassignedDevices ? { __filter: { name: nameFilter }, __orderby: [{ name: 1 }] } : { __filter: { name: nameFilter, __bygroupid: moId } }; return this.assetSelectorService.queriesUtil.buildQuery(filterByName); } const defaultFilter = { __filter: { __bygroupid: moId }, __orderby: [{ name: 1 }] }; return this.assetSelectorService.queriesUtil.buildQuery(defaultFilter); } /** * Applies a filter. * @param filter The filter to apply. */ async applyFilter(filter) { this.rootNode.filterQuery$.next(this.groupNameFilter(filter, this.rootNode.mo.id, this.isUnassignedDevicesNode() ? true : false)); this.rootNode.refresh(); this.onLoad.emit({ loading: true, filterText: this.filterText, index: this.index, selectedDevice: this.selectedDevice }); this.cd.detectChanges(); } /** * Check if the UnassignedDevice node is the rootNode. */ isUnassignedDevicesNode() { return this.rootNode.toString() === UnassignedDevicesNode.NAME; } /** * Called when the user resets the search result. */ onSearchResultReset(selectedItem) { if (selectedItem) { this.rootNode = this.createDefaultRootNode(); if (this.config.showUnassignedDevices) { this.rootNode.add(new UnassignedDevicesNode(this.groupNodeService, { showChildDevices: this.config.showChildDevices })); } if (this.config.view === 'miller') { this.onRowSelected.emit({ root: true }); } this.rootNode.click({ open: true }); this.rootNode.nodesFetched .pipe(tap(() => this.cd.detectChanges()), takeUntil(this.unsubscribe$)) .subscribe(); if (this.config.view === 'tree') { this.rootNode.open = true; } } } /** * Called if the user clicks on a search result. */ async onSearchResultClick(mo) { const canSelectNode = this.config.groupsSelectable || !this.groupNodeService.isGroup(mo); if (this.config.view === 'miller') { this.rootNode = await this.createManagedObjectRootNode(mo); this.rootNode.click({ open: true }); const nodeCopy = Object.create(this.rootNode); this.onRowSelected.emit({ nodeCopy, index: 0, selectedDevices: this.selectedDevice, root: true }); } if (!this.config.multi) { this.deselectAll(); } if (canSelectNode) { this.select(mo); } } onLoading(isLoading) { this.onLoad.emit({ loading: isLoading, filterText: this.filterText }); this.cd.markForCheck(); } onSelect(mo) { this.select(mo); } onDeselect(config) { switch (config?.deselectMode) { case 'single': this.deselect(config.mo); this.cd.markForCheck(); break; case 'all': this.deselectAll(config.mo); break; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssetSelectorComponent, 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: AssetSelectorComponent, selector: "c8y-asset-selector", inputs: { config: "config", active: "active", index: "index", asset: "asset", selectedDevice: "selectedDevice", selected: "selected", rootNode: "rootNode", selectedItems: "selectedItems", container: "container", isNodeSelectable: "isNodeSelectable", disabled: "disabled" }, outputs: { onSelected: "onSelected", onClearSelected: "onClearSelected", onRowSelected: "onRowSelected", onLoad: "onLoad" }, providers: [ { provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => AssetSelectorComponent) }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => AssetSelectorComponent), multi: true }, AssetSelectorService ], viewQueries: [{ propertyName: "header", first: true, predicate: ["header"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"bg-inherit p-t-8 p-b-8 separator-bottom p-r-16 p-l-16 sticky-top\"\n [ngStyle]=\"{ 'z-index': config.singleColumn && config.search ? '30' : '20' }\"\n #header\n [ngClass]=\"{\n 'p-absolute miller-column__selection d-flex flex-wrap a-i-center': config.view === 'miller',\n 'miller-column__search': config.search,\n 'miller-column__multi': config.multi\n }\"\n *ngIf=\"\n !selectedDevice &&\n index === 0 &&\n (config.search || config.multi || config.label?.length || config.showSelected)\n \"\n>\n <p\n class=\"text-medium flex-no-shrink a-s-center\"\n [ngClass]=\"{\n 'm-b-4': config.search && root && config.singleColumn,\n 'm-r-8': !config.singleColumn && !config.search,\n 'fit-w': config.singleColumn\n }\"\n *ngIf=\"config.label?.length\"\n >\n {{ config.label | translate }}\n </p>\n <c8y-search-input\n [ngStyle]=\"{ 'min-width': !config.singleColumn && config.label.length ? '50%' : 'inherit' }\"\n *ngIf=\"config.search && root\"\n (onClick)=\"onSearchResultClick($event)\"\n (reset)=\"onSearchResultReset($event)\"\n [mode]=\"'select'\"\n [container]=\"container\"\n [groupsOnly]=\"config.groupsOnly\"\n [ngClass]=\"{\n 'm-l-auto': !config.singleColumn && config.label.length,\n 'fit-w': config.singleColumn || !config.label.length\n }\"\n ></c8y-search-input>\n <div\n class=\"bg-inherit d-flex gap-4 fit-w\"\n *ngIf=\"config.showSelected\"\n [ngClass]=\"{ 'm-t-4': config.search }\"\n >\n <span class=\"text-label-small m-r-4 a-s-center l-h-1\">{{ 'Selected' | translate }}</span>\n <div class=\"flex-grow inner-scroll d-flex gap-4 a-i-center\">\n <ng-container *ngIf=\"!selected.length\">\n <em class=\"text-12 text-muted d-flex a-i-center fit-h-20\">{{ 'None' | translate }}</em>\n </ng-container>\n <span\n class=\"tag tag--info chip\"\n *ngFor=\"let selectedItem of selected\"\n >\n <button\n class=\"btn btn-xs btn-clean text-10\"\n title=\"{{ selectedItem.name }}\"\n [disabled]=\"disabled\"\n type=\"button\"\n (click)=\"config.multi ? deselect(selectedItem) : deselectAll()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.name || (ASSET_CONST | translate: { assetId: selectedItem.id }) }}\n </span>\n </div>\n </div>\n</div>\n\n<div\n class=\"p-r-16\"\n *ngIf=\"selectedDevice\"\n>\n <div class=\"d-flex p-b-4\">\n <p\n class=\"text-medium p-t-8 m-r-8\"\n *ngIf=\"selectedDevice; else multiAssets\"\n >\n {{ 'Selected asset' | translate }}\n </p>\n <ng-template #multiAssets>\n <p class=\"text-medium m-r-8\">{{ 'Selected assets' | translate }}</p>\n </ng-template>\n <button\n class=\"btn btn-default btn-xs a-s-center m-t-4 m-l-auto\"\n title=\"{{ 'Change' | translate }}\"\n type=\"button\"\n (click)=\"clearSelectedDevices()\"\n >\n {{ 'Change' | translate }}\n </button>\n </div>\n <div class=\"d-flex\">\n <i\n class=\"text-success p-l-0 p-r-8\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <i\n class=\"m-r-4 icon-20\"\n [c8yIcon]=\"selectedDevice | getGroupIcon | async\"\n ></i>\n <span>{{ selectedDevice.name }}</span>\n </div>\n</div>\n\n<!-- miller columns header -->\n<div\n class=\"miller-column__header sticky-top bg-inherit separator-bottom\"\n *ngIf=\"\n config.view === 'miller' &&\n ((config.showFilter && !rootNode.root) || config.columnHeaders) &&\n !selectedDevice\n \"\n [ngClass]=\"{ 'p-t-8': config.search }\"\n>\n <div class=\"d-flex\" *ngIf=\"config.singleColumn && index !== 0\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"home\"\n ></i>\n <p\n class=\"text-12 text-muted text-truncate text-rtl m-b-4\"\n title=\"{{ rootNode.breadcrumb || rootNode.label | translate }}\"\n >\n {{ rootNode.breadcrumb || rootNode.label | translate }}\n </p>\n </div>\n <div\n class=\"d-flex a-i-center\"\n *ngIf=\"config.columnHeaders || config.singleColumn\"\n >\n <button\n class=\"btn btn-default btn-xs m-r-8 p-t-0 p-b-0 p-l-4 p-r-4 l-h-1\"\n title=\"{{ 'Back' | translate }}\"\n type=\"button\"\n *ngIf=\"config.singleColumn && !rootNode.root && index !== 0\"\n (click)=\"back()\"\n >\n <i c8yIcon=\"angle-left\"></i>\n </button>\n <label\n class=\"c8y-radio checkbox-inline m-r-8\"\n *ngIf=\"!rootNode.root && index === 0 && (config.groupsSelectable || !rootNode.isGroup())\"\n >\n <input\n title=\"{{ 'Select group' | translate }}\"\n type=\"radio\"\n (change)=\"select(rootNode.mo)\"\n [checked]=\"isGroupSelected()\"\n />\n <span></span>\n </label>\n\n <i\n class=\"icon-20 c8y-icon-duocolor m-r-4\"\n [c8yIcon]=\"this.rootNode.mo | getGroupIcon: true : this.rootNode.icon | async\"\n *ngIf=\"config.columnHeaders && (config.singleColumn || (!rootNode.root && index === 0))\"\n ></i>\n <p\n class=\"text-truncate\"\n title=\"{{ rootNode.label | translate }}\"\n *ngIf=\"config.columnHeaders\"\n [ngClass]=\"{\n 'text-label-small': !config.singleColumn,\n 'text-medium': config.singleColumn\n }\"\n >\n {{ rootNode.label | translate }}\n </p>\n </div>\n\n <div\n *ngIf=\"!rootNode.root && config.showFilter\"\n [ngClass]=\"{ 'p-t-4': config.columnHeaders }\"\n >\n <div class=\"input-group input-group-sm input-group-search\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Filter this column\u2026' | translate }}\"\n [(ngModel)]=\"filterText\"\n (keyup.enter)=\"applyFilter('*' + filterText + '*')\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot p-r-8 p-l-4\"\n title=\"{{ 'Apply filter' | translate }}\"\n type=\"button\"\n (click)=\"applyFilter('*' + filterText + '*')\"\n >\n <i c8yIcon=\"filter\"></i>\n </button>\n <button\n class=\"btn btn-dot p-r-8 p-l-4\"\n title=\" {{ 'Clear filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n *ngIf=\"filterText.length\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </span>\n </div>\n </div>\n</div>\n\n<c8y-asset-selector-node\n class=\"d-block bg-inherit p-relative\"\n style=\"z-index: 9\"\n *ngIf=\"rootNode && !selectedDevice\"\n [node]=\"rootNode\"\n [rootNode]=\"rootNode\"\n [preselected]=\"selected\"\n [multi]=\"config.multi\"\n [view]=\"config.view\"\n [index]=\"index\"\n [active]=\"active\"\n [disabled]=\"disabled\"\n [handleNextMillerViewColumn]=\"handleNextMillerViewColumn.bind(this)\"\n (isLoadingState)=\"onLoading($event)\"\n (onSelect)=\"onSelect($event)\"\n (onDeselect)=\"onDeselect($event)\"\n [ngClass]=\"{ 'collapse show': !rootNode.root && !rootNode.hidden && config.view !== 'miller' }\"\n></c8y-asset-selector-node>\n", dependencies: [{ kind: "directive", type: i4.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { 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.SearchInputComponent, selector: "c8y-search-input", inputs: ["mode", "enableCustomTemplatePlaceholder", "customPlaceholder", "externalTerm", "customDataQuery", "container", "groupsOnly"], outputs: ["filter", "search", "reset", "onClick"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.AssetSelectorNodeComponent, selector: "c8y-asset-selector-node", inputs: ["node", "rootNode", "preselected", "showPath", "multi", "view", "index", "active", "handleNextMillerViewColumn", "disabled"], outputs: ["isLoadingState", "onSelect", "onDeselect"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.GetGroupIconPipe, name: "getGroupIcon" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssetSelectorComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-asset-selector', providers: [ { provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => AssetSelectorComponent) }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => AssetSelectorComponent), multi: true }, AssetSelectorService ], template: "<div\n class=\"bg-inherit p-t-8 p-b-8 separator-bottom p-r-16 p-l-16 sticky-top\"\n [ngStyle]=\"{ 'z-index': config.singleColumn && config.search ? '30' : '20' }\"\n #header\n [ngClass]=\"{\n 'p-absolute miller-column__selection d-flex flex-wrap a-i-center': config.view === 'miller',\n 'miller-column__search': config.search,\n 'miller-column__multi': config.multi\n }\"\n *ngIf=\"\n !selectedDevice &&\n index === 0 &&\n (config.search || config.multi || config.label?.length || config.showSelected)\n \"\n>\n <p\n class=\"text-medium flex-no-shrink a-s-center\"\n [ngClass]=\"{\n 'm-b-4': config.search && root && config.singleColumn,\n 'm-r-8': !config.singleColumn && !config.search,\n 'fit-w': config.singleColumn\n }\"\n *ngIf=\"config.label?.length\"\n >\n {{ config.label | translate }}\n </p>\n <c8y-search-input\n [ngStyle]=\"{ 'min-width': !config.singleColumn && config.label.length ? '50%' : 'inherit' }\"\n *ngIf=\"config.search && root\"\n (onClick)=\"onSearchResultClick($event)\"\n (reset)=\"onSearchResultReset($event)\"\n [mode]=\"'select'\"\n [container]=\"container\"\n [groupsOnly]=\"config.groupsOnly\"\n [ngClass]=\"{\n 'm-l-auto': !config.singleColumn && config.label.length,\n 'fit-w': config.singleColumn || !config.label.length\n }\"\n ></c8y-search-input>\n <div\n class=\"bg-inherit d-flex gap-4 fit-w\"\n *ngIf=\"config.showSelected\"\n [ngClass]=\"{ 'm-t-4': config.search }\"\n >\n <span class=\"text-label-small m-r-4 a-s-center l-h-1\">{{ 'Selected' | translate }}</span>\n <div class=\"flex-grow inner-scroll d-flex gap-4 a-i-center\">\n <ng-container *ngIf=\"!selected.length\">\n <em class=\"text-12 text-muted d-flex a-i-center fit-h-20\">{{ 'None' | translate }}</em>\n </ng-container>\n <span\n class=\"tag tag--info chip\"\n *ngFor=\"let selectedItem of selected\"\n >\n <button\n class=\"btn btn-xs btn-clean text-10\"\n title=\"{{ selectedItem.name }}\"\n [disabled]=\"disabled\"\n type=\"button\"\n (click)=\"config.multi ? deselect(selectedItem) : deselectAll()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.name || (ASSET_CONST | translate: { assetId: selectedItem.id }) }}\n </span>\n </div>\n </div>\n</div>\n\n<div\n class=\"p-r-16\"\n *ngIf=\"selectedDevice\"\n>\n <div class=\"d-flex p-b-4\">\n <p\n class=\"text-medium p-t-8 m-r-8\"\n *ngIf=\"selectedDevice; else multiAssets\"\n >\n {{ 'Selected asset' | translate }}\n </p>\n <ng-template #multiAssets>\n <p class=\"text-medium m-r-8\">{{ 'Selected assets' | translate }}</p>\n </ng-template>\n <button\n class=\"btn btn-default btn-xs a-s-center m-t-4 m-l-auto\"\n title=\"{{ 'Change' | translate }}\"\n type=\"button\"\n (click)=\"clearSelectedDevices()\"\n >\n {{ 'Change' | translate }}\n </button>\n </div>\n <div class=\"d-flex\">\n <i\n class=\"text-success p-l-0 p-r-8\"\n [c8yIcon]=\"'check-circle'\"\n ></i>\n <i\n class=\"m-r-4 icon-20\"\n [c8yIcon]=\"selectedDevice | getGroupIcon | async\"\n ></i>\n <span>{{ selectedDevice.name }}</span>\n </div>\n</div>\n\n<!-- miller columns header -->\n<div\n class=\"miller-column__header sticky-top bg-inherit separator-bottom\"\n *ngIf=\"\n config.view === 'miller' &&\n ((config.showFilter && !rootNode.root) || config.columnHeaders) &&\n !selectedDevice\n \"\n [ngClass]=\"{ 'p-t-8': config.search }\"\n>\n <div class=\"d-flex\" *ngIf=\"config.singleColumn && index !== 0\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"home\"\n ></i>\n <p\n class=\"text-12 text-muted text-truncate text-rtl m-b-4\"\n title=\"{{ rootNode.breadcrumb || rootNode.label | translate }}\"\n >\n {{ rootNode.breadcrumb || rootNode.label | translate }}\n </p>\n </div>\n <div\n class=\"d-flex a-i-center\"\n *ngIf=\"config.columnHeaders || config.singleColumn\"\n >\n <button\n class=\"btn btn-default btn-xs m-r-8 p-t-0 p-b-0 p-l-4 p-r-4 l-h-1\"\n title=\"{{ 'Back' | translate }}\"\n type=\"button\"\n *ngIf=\"config.singleColumn && !rootNode.root && index !== 0\"\n (click)=\"back()\"\n >\n <i c8yIcon=\"angle-left\"></i>\n </button>\n <label\n class=\"c8y-radio checkbox-inline m-r-8\"\n *ngIf=\"!rootNode.root && index === 0 && (config.groupsSelectable || !rootNode.isGroup())\"\n >\n <input\n title=\"{{ 'Select group' | translate }}\"\n type=\"radio\"\n (change)=\"select(rootNode.mo)\"\n [checked]=\"isGroupSelected()\"\n />\n <span></span>\n </label>\n\n <i\n class=\"icon-20 c8y-icon-duocolor m-r-4\"\n [c8yIcon]=\"this.rootNode.mo | getGroupIcon: true : this.rootNode.icon | async\"\n *ngIf=\"config.columnHeaders && (config.singleColumn || (!rootNode.root && index === 0))\"\n ></i>\n <p\n class=\"text-truncate\"\n title=\"{{ rootNode.label | translate }}\"\n *ngIf=\"config.columnHeaders\"\n [ngClass]=\"{\n 'text-label-small': !config.singleColumn,\n 'text-medium': config.singleColumn\n }\"\n >\n {{ rootNode.label | translate }}\n </p>\n </div>\n\n <div\n *ngIf=\"!rootNode.root && config.showFilter\"\n [ngClass]=\"{ 'p-t-4': config.columnHeaders }\"\n >\n <div class=\"input-group input-group-sm input-group-search\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'Filter this column\u2026' | translate }}\"\n [(ngModel)]=\"filterText\"\n (keyup.enter)=\"applyFilter('*' + filterText + '*')\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot p-r-8 p-l-4\"\n title=\"{{ 'Apply filter' | translate }}\"\n type=\"button\"\n (click)=\"applyFilter('*' + filterText + '*')\"\n >\n <i c8yIcon=\"filter\"></i>\n </button>\n <button\n class=\"btn btn-dot p-r-8 p-l-4\"\n title=\" {{ 'Clear filters' | translate }}\"\n type=\"button\"\n (click)=\"clearFilters()\"\n *ngIf=\"filterText.length\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </span>\n </div>\n </div>\n</div>\n\n<c8y-asset-selector-node\n class=\"d-block bg-inherit p-relative\"\n style=\"z-index: 9\"\n *ngIf=\"rootNode && !selectedDevice\"\n [node]=\"rootNode\"\n [rootNode]=\"rootNode\"\n [preselected]=\"selected\"\n [multi]=\"config.multi\"\n [view]=\"config.view\"\n [index]=\"index\"\n [active]=\"active\"\n [disabled]=\"disabled\"\n [handleNextMillerViewColumn]=\"handleNextMillerViewColumn.bind(this)\"\n (isLoadingState)=\"onLoading($event)\"\n (onSelect)=\"onSelect($event)\"\n (onDeselect)=\"onDeselect($event)\"\n [ngClass]=\"{ 'collapse show': !rootNode.root && !rootNode.hidden && config.view !== 'miller' }\"\n></c8y-asset-selector-node>\n" }] }], ctorParameters: () => [{ type: i1.GroupNodeService }, { type: i2.InventoryService }, { type: i3.AssetSelectorService }, { type: i0.ChangeDetectorRef }], propDecorators: { config: [{ type: Input }], active: [{ type: Input }], index: [{ type: Input }], asset: [{ type: Input }], selectedDevice: [{ type: Input }], selected: [{ type: Input }], rootNode: [{ type: Input }], selectedItems: [{ type: Input }], container: [{ type: Input }], isNodeSelectable: [{ type: Input }], disabled: [{ type: Input }], onSelected: [{ type: Output }], onClearSelected: [{ type: Output }], onRowSelected: [{ type: Output }], onLoad: [{ type: Output }], header: [{ type: ViewChild, args: ['header'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXQtc2VsZWN0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXNzZXRzLW5hdmlnYXRvci9hc3NldC1zZWxlY3Rvci9hc3NldC1zZWxlY3Rvci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9hc3NldHMtbmF2aWdhdG9yL2Fzc2V0LXNlbGVjdG9yL2Fzc2V0LXNlbGVjdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixTQUFTLEVBQ1QsVUFBVSxFQUNYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQStCLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUdMLHNCQUFzQixFQUN2QixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDeEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7Ozs7Ozs7QUFFOUM7O0dBRUc7QUFr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QUFLO2dCQUlHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFJSSxVQUFVO3NCQUFuQixNQUFNO2dCQUlHLGVBQWU7c0JBQXhCLE1BQU07Z0JBSUcsYUFBYTtzQkFBdEIsTUFBTTtnQkFJRyxNQUFNO3NCQUFmLE1BQU07Z0JBcUJDLE1BQU07c0JBRGIsU0FBUzt1QkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbiAgZm9yd2FyZFJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5HX1ZBTElEQVRPUlMsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSUlkZW50aWZpZWQsIElNYW5hZ2VkT2JqZWN0LCBJbnZlbnRvcnlTZXJ2aWNlIH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEFzc2V0U2VsZWN0b3JCYXNlIH0gZnJvbSAnLi9hc3NldC1zZWxlY3Rvci1iYXNlJztcbmltcG9ydCB7XG4gIEFzc2V0U2VsZWN0aW9uQ2hhbmdlRXZlbnQsXG4gIEFzc2V0U2VsZWN0b3JPcHRpb25zLFxuICBDT05GSUdfT1BUSU9OU19ERUZBVUxUXG59IGZyb20gJy4vYXNzZXQtc2VsZWN0b3IubW9kZWwnO1xuaW1wb3J0IHsgQXNzZXRTZWxlY3RvclNlcnZpY2UgfSBmcm9tICcuL2Fzc2V0LXNlbGVjdG9yLnNlcnZpY2UnO1xuaW1wb3J0IHsgR3JvdXBOb2RlIH0gZnJvbSAnLi9ncm91cC1ub2RlJztcbmltcG9ydCB7IEdyb3VwTm9kZVNlcnZpY2UgfSBmcm9tICcuL2dyb3VwLW5vZGUuc2VydmljZSc7XG5pbXBvcnQgeyBVbmFzc2lnbmVkRGV2aWNlc05vZGUgfSBmcm9tICcuL3VuYXNzaWduZWQtZGV2aWNlcy1ub2RlJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcblxuLyoqXG4gKiBEaXNwbGF5cyBhIGhpZXJhcmNoaWNhbCB0cmVlIHNlbGVjdG9yIGZvciBhc3NldHMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1hc3NldC1zZWxlY3RvcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9hc3NldC1zZWxlY3Rvci5jb21wb25lbnQuaHRtbCcsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBBc3NldFNlbGVjdG9yQ29tcG9uZW50KVxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IEFzc2V0U2VsZWN0b3JDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIEFzc2V0U2VsZWN0b3JTZXJ2aWNlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgQXNzZXRTZWxlY3RvckNvbXBvbmVudCBleHRlbmRzIEFzc2V0U2VsZWN0b3JCYXNlIGltcGxlbWVudHMgT25Jbml0IHtcbiAgLyoqXG4gICAqIENvbmZpZyBvYmplY3QgY29udGFpbmluZyBhbGwgb3B0aW9ucyBmb3IgdGhlIGFzc2V0IHNlbGVjdG9yLlxuICAgKi9cbiAgQElucHV0KCkgY29uZmlnOiBBc3NldFNlbGVjdG9yT3B0aW9ucyA9IHt9O1xuICAvKipcbiAgICogRGVmaW5lcyB0aGUgbm9kZSwgd2hpY2ggc2hvdWxkIGJlIGRpc3BsYXllZCBhcyBhY3RpdmUuXG4gICAqL1xuICBASW5wdXQoKSBhY3RpdmU6IEdyb3VwTm9kZTtcbiAgLyoqXG4gICAqIFVzZWQgb25seSBmb3IgbWlsbGVyLXZpZXcsIGRpc3BsYXlzIHRoZSBjb2x1bW4gbGV2ZWwgZm9yIHRoZSBjdXJyZW50IG5vZGUuXG4gICAqIEUuZyBpZiB0aGUgaW5kZXggaXMgb25lLCB0aGlzIHdpbGwgYmUgc2Vjb25kIGNvbHVtbi5cbiAgICovXG4gIEBJbnB1dCgpIGluZGV4ID0gMDtcbiAgLyoqXG4gICAqIFRoZSBhc3NldCB0byB1c2UgYXMgcm9vdC5cbiAgICovXG4gIEBJbnB1dCgpIGFzc2V0OiBJSWRlbnRpZmllZCA9IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIFRoZSBzZWxlY3RlZCBkZXZpY2UuXG4gICAqL1xuICBASW5wdXQoKSBzZWxlY3RlZERldmljZTogSU1hbmFnZWRPYmplY3QgPSB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiBwcmVkZWZpbmVkIG5vZGVzLlxuICAgKi9cbiAgQElucHV0KCkgc2VsZWN0ZWQ6IEFycmF5PFBhcnRpYWw8SU1hbmFnZWRPYmplY3Q+PiB8IElJZGVudGlmaWVkW10gfCBJSWRlbnRpZmllZCA9IFtdO1xuICAvKipcbiAgICogVGhlIG5vZGUgdG8gdXNlIGFzIHJvb3QuIFlvdSBjYW4gZWl0aGVyIHNldCB0aGlzLCBvciB0aGUgYXNzZXQgdG8gc3RhcnQgZnJvbS5cbiAgICovXG4gIEBJbnB1dCgpIHJvb3ROb2RlOiBHcm91cE5vZGU7XG4gIC8qKlxuICAgKiBBbGwgY3VycmVudGx5IHNlbGVjdGVkIGFzc2V0cy5cbiAgICovXG4gIEBJbnB1dCgpIHNlbGVjdGVkSXRlbXM6IElJZGVudGlmaWVkW10gfCBJSWRlbnRpZmllZCA9IFtdO1xuICBASW5wdXQoKSBjb250YWluZXI6ICcnIHwgJ2JvZHknID0gJ2JvZHknO1xuICBASW5wdXQoKSBpc05vZGVTZWxlY3RhYmxlOiBib29sZWFuIHwgKChub2RlOiBJSWRlbnRpZmllZCkgPT4gYm9vbGVhbikgPSB0cnVlO1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuICAvKipcbiAgICogRW1pdHMgaWYgb25lIGl0ZW0gd2FzIHNlbGVjdGVkIChhbGwgY3VycmVudGx5IHNlbGVjdGVkIG5vZGVzKS5cbiAgICovXG4gIEBPdXRwdXQoKSBvblNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxBc3NldFNlbGVjdGlvbkNoYW5nZUV2ZW50PigpO1xuICAvKipcbiAgICogRW1pdHMgaWYgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBhc3NldCBpcyBjbGVhcmVkLlxuICAgKi9cbiAgQE91dHB1dCgpIG9uQ2xlYXJTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqXG4gICAqIFVzZWQgb25seSBmb3IgbWlsbGVyIHZpZXcuIEVtaXQgdGhlIHNlbGVjdGVkIG5vZGUgYW5kIHVzZSBpdCBhcyBhICdyb290Tm9kZScgZm9yIHRoZSBuZXcgY29sdW1uLlxuICAgKi9cbiAgQE91dHB1dCgpIG9uUm93U2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBjdXJyZW50IGxvYWRpbmcgc3RhdGUgb2YgdGhlIG5vZGUuXG4gICAqL1xuICBAT3V0cHV0KCkgb25Mb2FkID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBmaWx0ZXIgYXBwbGllZC5cbiAgICovXG4gIGZpbHRlclRleHQgPSAnJztcbiAgLyoqXG4gICAqIERpc3BsYXlzIHRoZSBnbG9iYWwgc2VhcmNoIGF0IGFsbCB0aW1lcyBpZiB0aGUgbWlsbGVyIHZpZXcgaXMgdXNlZFxuICAgKiBvbiByb290IGdyb3VwIGxldmVsLlxuICAgKi9cbiAgcm9vdCA9IGZhbHNlO1xuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgdW5zdWJzY3JpYmUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgaGVhZGVyIGhpZ2h0IGluIHBpeGVsLlxuICAgKi9cbiAgZ2V0SGVhZGVySGVpZ2h0JCA9IG5ldyBCZWhhdmlvclN1YmplY3QoMCk7XG4gIHJlYWRvbmx5IEFTU0VUX0NPTlNUID0gZ2V0dGV4dCgnQXNzZXQge3sgYXNzZXRJZCB9fScpO1xuXG4gIEBWaWV3Q2hpbGQoJ2hlYWRlcicpXG4gIHByaXZhdGUgaGVhZGVyOiBFbGVtZW50UmVmO1xuXG4gIC8qKlxuICAgKiBAaWdub3JlIG9ubHkgRElcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBncm91cE5vZGVTZXJ2aWNlOiBHcm91cE5vZGVTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBpbnZlbnRvcnk6IEludmVudG9yeVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGFzc2V0U2VsZWN0b3JTZXJ2aWNlOiBBc3NldFNlbGVjdG9yU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICAgIHN1cGVyKGdyb3VwTm9kZVNlcnZpY2UsIGludmVudG9yeSwgYXNzZXRTZWxlY3RvclNlcnZpY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyB3aGVuIGEgbm9kZSB3YXMgc2VsZWN0ZWQsIGlmIGEgbmV3IGNvbHVtbiBuZWVkcyB0byBiZSBhZGRlZC5cbiAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdGhhdCB3YXMgY2xpY2tlZC5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoaXMgbm9kZS5cbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgY2xpY2sgd2FzIGhhbmRsZWQgYW5kIGEgbmV3IGNvbHVtbiB3YXMgYWRkZWQuXG4gICAqL1xuICBoYW5kbGVOZXh0TWlsbGVyVmlld0NvbHVtbihub2RlOiBHcm91cE5vZGUsIGluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCBub2RlQ29weSA9IE9iamVjdC5jcmVhdGUobm9kZSk7XG4gICAgY29uc3QgaXNTYW1lQXNSb290ID0gdGhpcy5yb290Tm9kZSA9PT0gbm9kZTtcbiAgICBjb25zdCBpc1VuYXNzaWduZWREZXZpY2VzTm9kZSA9IG5vZGUudG9TdHJpbmcoKSA9PT0gVW5hc3NpZ25lZERldmljZXNOb2RlLk5BTUU7XG4gICAgY29uc3QgaXNOZXdDb2x1bW5OZWVkZWQgPVxuICAgICAgIWlzU2FtZUFzUm9vdCAmJiAobm9kZS5pc0dyb3VwKCkgfHwgaXNVbmFzc2lnbmVkRGV2aWNlc05vZGUgfHwgbm9kZS5oYXNDaGlsZERldmljZXMoKSk7XG5cbiAgICBpZiAoaXNOZXdDb2x1bW5OZWVkZWQpIHtcbiAgICAgIHRoaXMub25Sb3dTZWxlY3RlZC5lbWl0KHsgbm9kZUNvcHksIGluZGV4IH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmFzc2V0U2VsZWN0b3JTZXJ2aWNlLnNldElzTm9kZVNlbGVjdGFibGUodGhpcy5pc05vZGVTZWxlY3RhYmxlKTtcbiAgICBpZiAodGhpcy5pbmRleCA9PT0gMCkge1xuICAgICAgdGhpcy5jb25maWcgPSB7IC4uLkNPTkZJR19PUFRJT05TX0RFRkFVTFQsIC4uLnRoaXMuY29uZmlnIH07XG4gICAgfVxuICAgIGNvbnN0IHNob3VsZFJlc2V0TmFtZUZpbHRlciA9XG4gICAgICB0aGlzLnJvb3ROb2RlICYmIHRoaXMucm9vdE5vZGUubW8gJiYgdGhpcy5jb25maWcudmlldyA9PT0gJ21pbGxlcic7XG4gICAgaWYgKHNob3VsZFJlc2V0TmFtZUZpbHRlcikge1xuICAgICAgYXdhaXQgdGhpcy5hcHBseUZpbHRlcignJyk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNPbmx5QXNzZXROb2RlRGVmaW5lZCA9IHRoaXMuYXNzZXQ7XG4gICAgaWYgKGlzT25seUFzc2V0Tm9kZURlZmluZWQpIHtcbiAgICAgIHRoaXMucm9vdE5vZGUgPSBhd2FpdCB0aGlzLmNyZWF0ZU1hbmFnZWRPYmplY3RSb290Tm9kZSh0aGlzLmFzc2V0KTtcbiAgICB9XG5cbiAgICBjb25zdCBpc0FueU5vZGVEZWZpbmVkID1cbiAgICAgICF0aGlzLnJvb3ROb2RlICYmICghdGhpcy5hc3NldCB8fCBPYmplY3Qua2V5cyh0aGlzLmFzc2V0KS5sZW5ndGggPT09IDApO1xuICAgIGlmIChpc0FueU5vZGVEZWZpbmVkKSB7XG4gICAgICB0aGlzLnJvb3ROb2RlID0gdGhpcy5jcmVhdGVEZWZhdWx0Um9vdE5vZGUoKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICB0aGlzLmNvbmZpZy5zaG93VW5hc3NpZ25lZERldmljZXMgJiZcbiAgICAgICghdGhpcy5hc3NldCB8fCBPYmplY3Qua2V5cyh0aGlzLmFzc2V0KS5sZW5ndGggPT09IDApICYmXG4gICAgICB0aGlzLnJvb3ROb2RlLnJvb3RcbiAgICApIHtcbiAgICAgIHRoaXMucm9vdE5v