@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
82 lines • 27.8 kB
JavaScript
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { gettext } from '@c8y/ngx-components';
import { PRODUCT_EXPERIENCE_REPOSITORY_SHARED } from '@c8y/ngx-components/repository/shared';
import { filter, get } from 'lodash-es';
import { BehaviorSubject, combineLatest, Observable, of, Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, share, switchMap, takeUntil, tap } from 'rxjs/operators';
import { DeviceSoftwareService } from './device-software.service';
import * as i0 from "@angular/core";
import * as i1 from "./device-software.service";
import * as i2 from "@angular/common";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "ngx-bootstrap/tooltip";
export class DeviceSoftwareListComponent {
set softwareList(softwareList) {
if (softwareList !== null) {
this.legacySoftwareList$.next(softwareList);
}
}
constructor(deviceSoftwareService) {
this.deviceSoftwareService = deviceSoftwareService;
this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_REPOSITORY_SHARED;
this.filterCriteria$ = of(null);
this.update = new EventEmitter();
this.remove = new EventEmitter();
this.onListEmpty = new EventEmitter();
this.alreadyInstalledMessage = gettext('This software is already installed on the device');
this.supportsSoftwareOperations = false;
this.operationTypes = ['c8y_SoftwareUpdate', 'c8y_SoftwareList', 'c8y_Software'];
this.legacySoftwareList$ = new BehaviorSubject([]);
this.destroyed$ = new Subject();
}
ngOnInit() {
this.softwareItems$ = combineLatest([
this.filterCriteria$.pipe(debounceTime(300), distinctUntilChanged()),
this.legacySoftwareList$
]).pipe(switchMap(([filterCriteria, legacySoftwareList]) => this.deviceSoftwareService
.getSoftwareList(this.device?.id, filterCriteria, legacySoftwareList)
.pipe(map(resultList => ({ resultList, filterCriteria })))), tap(({ resultList, filterCriteria }) => {
this.notifyListEmpty(!resultList?.paging?.totalPages && !filterCriteria);
this.noSearchResults = !resultList?.paging?.totalPages && !!filterCriteria;
}), map(({ resultList }) => resultList), share(), takeUntil(this.destroyed$));
const supportedOperations = get(this.device, 'c8y_SupportedOperations', []);
this.supportsSoftwareOperations = this.operationTypes.some(operationType => supportedOperations.indexOf(operationType) > -1);
}
ngAfterContentInit() {
this.showUpdate = this.update.observers.length > 0;
this.showRemove = this.remove.observers.length > 0;
}
isSoftwareGoingToBeChanged(software) {
const relevantChanges = filter(this.deviceSoftwareChanges, software);
return relevantChanges.length > 0;
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
notifyListEmpty(isEmpty) {
this.emptyList = isEmpty;
this.onListEmpty.emit(isEmpty);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceSoftwareListComponent, deps: [{ token: i1.DeviceSoftwareService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DeviceSoftwareListComponent, selector: "c8y-device-software-list", inputs: { softwareList: "softwareList", device: "device", deviceSoftwareChanges: "deviceSoftwareChanges", filterCriteria$: "filterCriteria$" }, outputs: { update: "update", remove: "remove", onListEmpty: "onListEmpty" }, ngImport: i0, template: "<c8y-list-group class=\"no-border-2nd-last\">\n <c8y-li\n [ngClass]=\"{ disabled: isSoftwareGoingToBeChanged(software) }\"\n *c8yFor=\"let software of softwareItems$\"\n >\n <!-- SOFTWARE ICON -->\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-20\">\n <div title=\"{{ software.name }}\" class=\"col-9\">\n <p class=\"d-flex\">\n <!-- SOFTWARE NAME -->\n <span class=\"text-truncate\">\n {{ software.name }}\n </span>\n <!-- SOFTWARE TYPE-->\n <span class=\"text-truncate\">\n <span class=\"label label-primary m-l-8\">{{ software.softwareType }}</span>\n </span>\n </p>\n <!-- SOFTWARE VERSION -->\n <p class=\"d-flex a-i-center\">\n <span class=\"text-truncate text-label-small m-r-4\" translate>Version</span>\n <span class=\"text-truncate m-r-4\" title=\"{{ software.version }}\">\n {{ software.version }}\n </span>\n <i\n *ngIf=\"software.installed\"\n c8yIcon=\"warning\"\n class=\"text-warning a-s-center\"\n [tooltip]=\"\n alreadyInstalledMessage\n | translate: { name: software.name, version: software.version }\n \"\n container=\"body\"\n placement=\"top\"\n [delay]=\"500\"\n ></i>\n </p>\n </div>\n\n <div\n *ngIf=\"supportsSoftwareOperations && (showUpdate || showRemove)\"\n class=\"col-3 text-right m-0 flex-grow d-flex a-i-center\"\n >\n <!-- UPDATE SOFTWARE -->\n <button\n class=\"btn btn-default btn-xs m-l-auto m-r-4\"\n type=\"button\"\n title=\"{{ 'Update`software,verb`' | translate }}\"\n *ngIf=\"showUpdate && !isSoftwareGoingToBeChanged(software)\"\n (click)=\"update.emit(software)\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.SOFTWARE.EVENTS.DEVICE_TAB\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.SOFTWARE.COMPONENTS.DEVICE_SOFTWARE_LIST,\n action: PRODUCT_EXPERIENCE.SOFTWARE.ACTIONS.OPEN_UPDATE_SOFTWARE\n }\"\n >\n {{ 'Update`software,verb`' | translate }}\n </button>\n\n <!-- REMOVE SOFTWARE -->\n <button\n class=\"btn btn-dot btn-dot--danger m-l-4\"\n type=\"button\"\n [attr.aria-label]=\"'Remove`software,verb`' | translate\"\n tooltip=\"{{ 'Remove`software,verb`' | translate }}\"\n placement=\"bottom\"\n container=\"body\"\n [delay]=\"500\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.SOFTWARE.EVENTS.DEVICE_TAB\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.SOFTWARE.COMPONENTS.DEVICE_SOFTWARE_LIST,\n action: PRODUCT_EXPERIENCE.SOFTWARE.ACTIONS.DELETE_SOFTWARE\n }\"\n *ngIf=\"showRemove && !isSoftwareGoingToBeChanged(software)\"\n (click)=\"remove.emit(software)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n<!-- NO SEARCH RESULTS STATE -->\n<div class=\"card-block\" *ngIf=\"noSearchResults || emptyList\">\n <ng-content *ngIf=\"emptyList\" select=\".c8y-empty-state:not(.c8y-no-results-state)\"></ng-content>\n <ng-content *ngIf=\"noSearchResults\" select=\".c8y-no-results-state\"></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: i3.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i3.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i3.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i3.ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "directive", type: i3.ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: i4.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceSoftwareListComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-device-software-list', template: "<c8y-list-group class=\"no-border-2nd-last\">\n <c8y-li\n [ngClass]=\"{ disabled: isSoftwareGoingToBeChanged(software) }\"\n *c8yFor=\"let software of softwareItems$\"\n >\n <!-- SOFTWARE ICON -->\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-20\">\n <div title=\"{{ software.name }}\" class=\"col-9\">\n <p class=\"d-flex\">\n <!-- SOFTWARE NAME -->\n <span class=\"text-truncate\">\n {{ software.name }}\n </span>\n <!-- SOFTWARE TYPE-->\n <span class=\"text-truncate\">\n <span class=\"label label-primary m-l-8\">{{ software.softwareType }}</span>\n </span>\n </p>\n <!-- SOFTWARE VERSION -->\n <p class=\"d-flex a-i-center\">\n <span class=\"text-truncate text-label-small m-r-4\" translate>Version</span>\n <span class=\"text-truncate m-r-4\" title=\"{{ software.version }}\">\n {{ software.version }}\n </span>\n <i\n *ngIf=\"software.installed\"\n c8yIcon=\"warning\"\n class=\"text-warning a-s-center\"\n [tooltip]=\"\n alreadyInstalledMessage\n | translate: { name: software.name, version: software.version }\n \"\n container=\"body\"\n placement=\"top\"\n [delay]=\"500\"\n ></i>\n </p>\n </div>\n\n <div\n *ngIf=\"supportsSoftwareOperations && (showUpdate || showRemove)\"\n class=\"col-3 text-right m-0 flex-grow d-flex a-i-center\"\n >\n <!-- UPDATE SOFTWARE -->\n <button\n class=\"btn btn-default btn-xs m-l-auto m-r-4\"\n type=\"button\"\n title=\"{{ 'Update`software,verb`' | translate }}\"\n *ngIf=\"showUpdate && !isSoftwareGoingToBeChanged(software)\"\n (click)=\"update.emit(software)\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.SOFTWARE.EVENTS.DEVICE_TAB\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.SOFTWARE.COMPONENTS.DEVICE_SOFTWARE_LIST,\n action: PRODUCT_EXPERIENCE.SOFTWARE.ACTIONS.OPEN_UPDATE_SOFTWARE\n }\"\n >\n {{ 'Update`software,verb`' | translate }}\n </button>\n\n <!-- REMOVE SOFTWARE -->\n <button\n class=\"btn btn-dot btn-dot--danger m-l-4\"\n type=\"button\"\n [attr.aria-label]=\"'Remove`software,verb`' | translate\"\n tooltip=\"{{ 'Remove`software,verb`' | translate }}\"\n placement=\"bottom\"\n container=\"body\"\n [delay]=\"500\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.SOFTWARE.EVENTS.DEVICE_TAB\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.SOFTWARE.COMPONENTS.DEVICE_SOFTWARE_LIST,\n action: PRODUCT_EXPERIENCE.SOFTWARE.ACTIONS.DELETE_SOFTWARE\n }\"\n *ngIf=\"showRemove && !isSoftwareGoingToBeChanged(software)\"\n (click)=\"remove.emit(software)\"\n >\n <i c8yIcon=\"minus-circle\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n<!-- NO SEARCH RESULTS STATE -->\n<div class=\"card-block\" *ngIf=\"noSearchResults || emptyList\">\n <ng-content *ngIf=\"emptyList\" select=\".c8y-empty-state:not(.c8y-no-results-state)\"></ng-content>\n <ng-content *ngIf=\"noSearchResults\" select=\".c8y-no-results-state\"></ng-content>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.DeviceSoftwareService }], propDecorators: { softwareList: [{
type: Input
}], device: [{
type: Input
}], deviceSoftwareChanges: [{
type: Input
}], filterCriteria$: [{
type: Input
}], update: [{
type: Output
}], remove: [{
type: Output
}], onListEmpty: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLXNvZnR3YXJlLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcmVwb3NpdG9yeS9zb2Z0d2FyZS9kZXZpY2UtdGFiL2RldmljZS1zb2Z0d2FyZS1saXN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3JlcG9zaXRvcnkvc29mdHdhcmUvZGV2aWNlLXRhYi9kZXZpY2Utc29mdHdhcmUtbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxFQUNQLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM5QyxPQUFPLEVBSUwsb0NBQW9DLEVBQ3JDLE1BQU0sdUNBQXVDLENBQUM7QUFDL0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDeEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0UsT0FBTyxFQUNMLFlBQVksRUFDWixvQkFBb0IsRUFDcEIsR0FBRyxFQUNILEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxFQUNULEdBQUcsRUFDSixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7QUFNbEUsTUFBTSxPQUFPLDJCQUEyQjtJQUV0QyxJQUFhLFlBQVksQ0FBQyxZQUE4QjtRQUN0RCxJQUFJLFlBQVksS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzlDLENBQUM7SUFDSCxDQUFDO0lBb0JELFlBQW9CLHFCQUE0QztR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QUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRU8sZUFBZSxDQUFDLE9BQWdCO1FBQ3RDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pDLENBQUM7K0dBdEVVLDJCQUEyQjttR0FBM0IsMkJBQTJCLDZSQ2xDeEMscWdIQTZGQTs7NEZEM0RhLDJCQUEyQjtrQkFKdkMsU0FBUzsrQkFDRSwwQkFBMEI7MEZBS3ZCLFlBQVk7c0JBQXhCLEtBQUs7Z0JBS0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNJLE1BQU07c0JBQWYsTUFBTTtnQkFDRyxNQUFNO3NCQUFmLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElNYW5hZ2VkT2JqZWN0LCBJUmVzdWx0TGlzdCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIERldmljZVNvZnR3YXJlLFxuICBEZXZpY2VTb2Z0d2FyZUNoYW5nZSxcbiAgRmlsdGVyQ3JpdGVyaWEsXG4gIFBST0RVQ1RfRVhQRVJJRU5DRV9SRVBPU0lUT1JZX1NIQVJFRFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL3JlcG9zaXRvcnkvc2hhcmVkJztcbmltcG9ydCB7IGZpbHRlciwgZ2V0IH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgT2JzZXJ2YWJsZSwgb2YsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIGRlYm91bmNlVGltZSxcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQsXG4gIG1hcCxcbiAgc2hhcmUsXG4gIHN3aXRjaE1hcCxcbiAgdGFrZVVudGlsLFxuICB0YXBcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRGV2aWNlU29mdHdhcmVTZXJ2aWNlIH0gZnJvbSAnLi9kZXZpY2Utc29mdHdhcmUuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1kZXZpY2Utc29mdHdhcmUtbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnZGV2aWNlLXNvZnR3YXJlLWxpc3QuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIERldmljZVNvZnR3YXJlTGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95IHtcbiAgUFJPRFVDVF9FWFBFUklFTkNFID0gUFJPRFVDVF9FWFBFUklFTkNFX1JFUE9TSVRPUllfU0hBUkVEO1xuICBASW5wdXQoKSBzZXQgc29mdHdhcmVMaXN0KHNvZnR3YXJlTGlzdDogRGV2aWNlU29mdHdhcmVbXSkge1xuICAgIGlmIChzb2Z0d2FyZUxpc3QgIT09IG51bGwpIHtcbiAgICAgIHRoaXMubGVnYWN5U29mdHdhcmVMaXN0JC5uZXh0KHNvZnR3YXJlTGlzdCk7XG4gICAgfVxuICB9XG4gIEBJbnB1dCgpIGRldmljZTogSU1hbmFnZWRPYmplY3Q7XG4gIEBJbnB1dCgpIGRldmljZVNvZnR3YXJlQ2hhbmdlczogRGV2aWNlU29mdHdhcmVDaGFuZ2VbXTtcbiAgQElucHV0KCkgZmlsdGVyQ3JpdGVyaWEkOiBPYnNlcnZhYmxlPEZpbHRlckNyaXRlcmlhPiA9IG9mKG51bGwpO1xuICBAT3V0cHV0KCkgdXBkYXRlID0gbmV3IEV2ZW50RW1pdHRlcjxEZXZpY2VTb2Z0d2FyZT4oKTtcbiAgQE91dHB1dCgpIHJlbW92ZSA9IG5ldyBFdmVudEVtaXR0ZXI8RGV2aWNlU29mdHdhcmU+KCk7XG4gIEBPdXRwdXQoKSBvbkxpc3RFbXB0eTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBzb2Z0d2FyZUl0ZW1zJDogT2JzZXJ2YWJsZTxJUmVzdWx0TGlzdDxEZXZpY2VTb2Z0d2FyZT4+O1xuICBzaG93VXBkYXRlOiBib29sZWFuO1xuICBzaG93UmVtb3ZlOiBib29sZWFuO1xuICBlbXB0eUxpc3Q6IGJvb2xlYW47XG4gIG5vU2VhcmNoUmVzdWx0czogYm9vbGVhbjtcbiAgYWxyZWFkeUluc3RhbGxlZE1lc3NhZ2UgPSBnZXR0ZXh0KCdUaGlzIHNvZnR3YXJlIGlzIGFscmVhZHkgaW5zdGFsbGVkIG9uIHRoZSBkZXZpY2UnKTtcbiAgc3VwcG9ydHNTb2Z0d2FyZU9wZXJhdGlvbnMgPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IG9wZXJhdGlvblR5cGVzID0gWydjOHlfU29mdHdhcmVVcGRhdGUnLCAnYzh5X1NvZnR3YXJlTGlzdCcsICdjOHlfU29mdHdhcmUnXTtcblxuICBwcml2YXRlIGxlZ2FjeVNvZnR3YXJlTGlzdCQ6IEJlaGF2aW9yU3ViamVjdDxEZXZpY2VTb2Z0d2FyZVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoW10pO1xuICBwcml2YXRlIGRlc3Ryb3llZCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZGV2aWNlU29mdHdhcmVTZXJ2aWNlOiBEZXZpY2VTb2Z0d2FyZVNlcnZpY2UpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zb2Z0d2FyZUl0ZW1zJCA9IGNvbWJpbmVMYXRlc3QoW1xuICAgICAgdGhpcy5maWx0ZXJDcml0ZXJpYSQucGlwZShkZWJvdW5jZVRpbWUoMzAwKSwgZGlzdGluY3RVbnRpbENoYW5nZWQoKSksXG4gICAgICB0aGlzLmxlZ2FjeVNvZnR3YXJlTGlzdCRcbiAgICBdKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKChbZmlsdGVyQ3JpdGVyaWEsIGxlZ2FjeVNvZnR3YXJlTGlzdF0pID0+XG4gICAgICAgIHRoaXMuZGV2aWNlU29mdHdhcmVTZXJ2aWNlXG4gICAgICAgICAgLmdldFNvZnR3YXJlTGlzdCh0aGlzLmRldmljZT8uaWQsIGZpbHRlckNyaXRlcmlhLCBsZWdhY3lTb2Z0d2FyZUxpc3QpXG4gICAgICAgICAgLnBpcGUobWFwKHJlc3VsdExpc3QgPT4gKHsgcmVzdWx0TGlzdCwgZmlsdGVyQ3JpdGVyaWEgfSkpKVxuICAgICAgKSxcbiAgICAgIHRhcCgoeyByZXN1bHRMaXN0LCBmaWx0ZXJDcml0ZXJpYSB9KSA9PiB7XG4gICAgICAgIHRoaXMubm90aWZ5TGlzdEVtcHR5KCFyZXN1bHRMaXN0Py5wYWdpbmc/LnRvdGFsUGFnZXMgJiYgIWZpbHRlckNyaXRlcmlhKTtcbiAgICAgICAgdGhpcy5ub1NlYXJjaFJlc3VsdHMgPSAhcmVzdWx0TGlzdD8ucGFnaW5nPy50b3RhbFBhZ2VzICYmICEhZmlsdGVyQ3JpdGVyaWE7XG4gICAgICB9KSxcbiAgICAgIG1hcCgoeyByZXN1bHRMaXN0IH0pID0+IHJlc3VsdExpc3QpLFxuICAgICAgc2hhcmUoKSxcbiAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3llZCQpXG4gICAgKTtcbiAgICBjb25zdCBzdXBwb3J0ZWRPcGVyYXRpb25zID0gZ2V0KHRoaXMuZGV2aWNlLCAnYzh5X1N1cHBvcnRlZE9wZXJhdGlvbnMnLCBbXSk7XG4gICAgdGhpcy5zdXBwb3J0c1NvZnR3YXJlT3BlcmF0aW9ucyA9IHRoaXMub3BlcmF0aW9uVHlwZXMuc29tZShcbiAgICAgIG9wZXJhdGlvblR5cGUgPT4gc3VwcG9ydGVkT3BlcmF0aW9ucy5pbmRleE9mKG9wZXJhdGlvblR5cGUpID4gLTFcbiAgICApO1xuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIHRoaXMuc2hvd1VwZGF0ZSA9IHRoaXMudXBkYXRlLm9ic2VydmVycy5sZW5ndGggPiAwO1xuICAgIHRoaXMuc2hvd1JlbW92ZSA9IHRoaXMucmVtb3ZlLm9ic2VydmVycy5sZW5ndGggPiAwO1xuICB9XG5cbiAgaXNTb2Z0d2FyZUdvaW5nVG9CZUNoYW5nZWQoc29mdHdhcmU6IERldmljZVNvZnR3YXJlKTogYm9vbGVhbiB7XG4gICAgY29uc3QgcmVsZXZhbnRDaGFuZ2VzID0gZmlsdGVyKHRoaXMuZGV2aWNlU29mdHdhcmVDaGFuZ2VzLCBzb2Z0d2FyZSk7XG4gICAgcmV0dXJuIHJlbGV2YW50Q2hhbmdlcy5sZW5ndGggPiAwO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95ZWQkLm5leHQoKTtcbiAgICB0aGlzLmRlc3Ryb3llZCQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHByaXZhdGUgbm90aWZ5TGlzdEVtcHR5KGlzRW1wdHk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmVtcHR5TGlzdCA9IGlzRW1wdHk7XG4gICAgdGhpcy5vbkxpc3RFbXB0eS5lbWl0KGlzRW1wdHkpO1xuICB9XG59XG4iLCI8Yzh5LWxpc3QtZ3JvdXAgY2xhc3M9XCJuby1ib3JkZXItMm5kLWxhc3RcIj5cbiAgPGM4eS1saVxuICAgIFtuZ0NsYXNzXT1cInsgZGlzYWJsZWQ6IGlzU29mdHdhcmVHb2luZ1RvQmVDaGFuZ2VkKHNvZnR3YXJlKSB9XCJcbiAgICAqYzh5Rm9yPVwibGV0IHNvZnR3YXJlIG9mIHNvZnR3YXJlSXRlbXMkXCJcbiAgPlxuICAgIDwhLS0gU09GVFdBUkUgSUNPTiAtLT5cbiAgICA8Yzh5LWxpLWljb24+XG4gICAgICA8aSBjOHlJY29uPVwiYzh5LXRvb2xzXCI+PC9pPlxuICAgIDwvYzh5LWxpLWljb24+XG5cbiAgICA8Yzh5LWxpLWJvZHkgY2xhc3M9XCJjb250ZW50LWZsZXgtMjBcIj5cbiAgICAgIDxkaXYgdGl0bGU9XCJ7eyBzb2Z0d2FyZS5uYW1lIH19XCIgY2xhc3M9XCJjb2wtOVwiPlxuICAgICAgICA8cCBjbGFzcz1cImQtZmxleFwiPlxuICAgICAgICAgIDwhLS0gU09GVFdBUkUgTkFNRSAtLT5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIj5cbiAgICAgICAgICAgIHt7IHNvZnR3YXJlLm5hbWUgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPCEtLSBTT0ZUV0FSRSBUWVBFLS0+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsIGxhYmVsLXByaW1hcnkgbS1sLThcIj57eyBzb2Z0d2FyZS5zb2Z0d2FyZVR5cGUgfX08L3NwYW4+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3A+XG4gICAgICAgIDwhLS0gU09GVFdBUkUgVkVSU0lPTiAtLT5cbiAgICAgICAgPHAgY2xhc3M9XCJkLWZsZXggYS1pLWNlbnRlclwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC10cnVuY2F0ZSB0ZXh0LWxhYmVsLXNtYWxsIG0tci00XCIgdHJhbnNsYXRlPlZlcnNpb248L3NwYW4+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXRydW5jYXRlIG0tci00XCIgdGl0bGU9XCJ7eyBzb2Z0d2FyZS52ZXJzaW9uIH19XCI+XG4gICAgICAgICAgICB7eyBzb2Z0d2FyZS52ZXJzaW9uIH19XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDxpXG4gICAgICAgICAgICAqbmdJZj1cInNvZnR3YXJlLmluc3RhbGxlZFwiXG4gICAgICAgICAgICBjOHlJY29uPVwid2FybmluZ1wiXG4gICAgICAgICAgICBjbGFzcz1cInRleHQtd2FybmluZyBhLXMtY2VudGVyXCJcbiAgICAgICAgICAgIFt0b29sdGlwXT1cIlxuICAgICAgICAgICAgICBhbHJlYWR5SW5zdGFsbGVkTWVzc2FnZVxuICAgICAgICAgICAgICAgIHwgdHJhbnNsYXRlOiB7IG5hbWU6IHNvZnR3YXJlLm5hbWUsIHZlcnNpb246IHNvZnR3YXJlLnZlcnNpb24gfVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgICAgICAgICAgcGxhY2VtZW50PVwidG9wXCJcbiAgICAgICAgICAgIFtkZWxheV09XCI1MDBcIlxuICAgICAgICAgID48L2k+XG4gICAgICAgIDwvcD5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2XG4gICAgICAgICpuZ0lmPVwic3VwcG9ydHNTb2Z0d2FyZU9wZXJhdGlvbnMgJiYgKHNob3dVcGRhdGUgfHwgc2hvd1JlbW92ZSlcIlxuICAgICAgICBjbGFzcz1cImNvbC0zIHRleHQtcmlnaHQgbS0wIGZsZXgtZ3JvdyBkLWZsZXggYS1pLWNlbnRlclwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gVVBEQVRFIFNPRlRXQVJFIC0tPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHQgYnRuLXhzIG0tbC1hdXRvIG0tci00XCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICB0aXRsZT1cInt7ICdVcGRhdGVgc29mdHdhcmUsdmVyYmAnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICAqbmdJZj1cInNob3dVcGRhdGUgJiYgIWlzU29mdHdhcmVHb2luZ1RvQmVDaGFuZ2VkKHNvZnR3YXJlKVwiXG4gICAgICAgICAgKGNsaWNrKT1cInVwZGF0ZS5lbWl0KHNvZnR3YXJlKVwiXG4gICAgICAgICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICAgICAgICBbYWN0aW9uTmFtZV09XCJQUk9EVUNUX0VYUEVSSUVOQ0UuU09GVFdBUkUuRVZFTlRTLkRFVklDRV9UQUJcIlxuICAgICAgICAgIFthY3Rpb25EYXRhXT1cIntcbiAgICAgICAgICAgIGNvbXBvbmVudDogUFJPRFVDVF9FWFBFUklFTkNFLlNPRlRXQVJFLkNPTVBPTkVOVFMuREVWSUNFX1NPRlRXQVJFX0xJU1QsXG4gICAgICAgICAgICBhY3Rpb246IFBST0RVQ1RfRVhQRVJJRU5DRS5TT0ZUV0FSRS5BQ1RJT05TLk9QRU5fVVBEQVRFX1NPRlRXQVJFXG4gICAgICAgICAgfVwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyAnVXBkYXRlYHNvZnR3YXJlLHZlcmJgJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICA8IS0tIFJFTU9WRSBTT0ZUV0FSRSAtLT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kb3QgYnRuLWRvdC0tZGFuZ2VyIG0tbC00XCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidSZW1vdmVgc29mdHdhcmUsdmVyYmAnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICB0b29sdGlwPVwie3sgJ1JlbW92ZWBzb2Z0d2FyZSx2ZXJiYCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgIHBsYWNlbWVudD1cImJvdHRvbVwiXG4gICAgICAgICAgY29udGFpbmVyPVwiYm9keVwiXG4gICAgICAgICAgW2RlbGF5XT1cIjUwMFwiXG4gICAgICAgICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICAgICAgICBbYWN0aW9uTmFtZV09XCJQUk9EVUNUX0VYUEVSSUVOQ0UuU09GVFdBUkUuRVZFTlRTLkRFVklDRV9UQUJcIlxuICAgICAgICAgIFthY3Rpb25EYXRhXT1cIntcbiAgICAgICAgICAgIGNvbXBvbmVudDogUFJPRFVDVF9FWFBFUklFTkNFLlNPRlRXQVJFLkNPTVBPTkVOVFMuREVWSUNFX1NPRlRXQVJFX0xJU1QsXG4gICAgICAgICAgICBhY3Rpb246IFBST0RVQ1RfRVhQRVJJRU5DRS5TT0ZUV0FSRS5BQ1RJT05TLkRFTEVURV9TT0ZUV0FSRVxuICAgICAgICAgIH1cIlxuICAgICAgICAgICpuZ0lmPVwic2hvd1JlbW92ZSAmJiAhaXNTb2Z0d2FyZUdvaW5nVG9CZUNoYW5nZWQoc29mdHdhcmUpXCJcbiAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlLmVtaXQoc29mdHdhcmUpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxpIGM4eUljb249XCJtaW51cy1jaXJjbGVcIj48L2k+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9jOHktbGktYm9keT5cbiAgPC9jOHktbGk+XG48L2M4eS1saXN0LWdyb3VwPlxuPCEtLSBOTyBTRUFSQ0ggUkVTVUxUUyBTVEFURSAtLT5cbjxkaXYgY2xhc3M9XCJjYXJkLWJsb2NrXCIgKm5nSWY9XCJub1NlYXJjaFJlc3VsdHMgfHwgZW1wdHlMaXN0XCI+XG4gIDxuZy1jb250ZW50ICpuZ0lmPVwiZW1wdHlMaXN0XCIgc2VsZWN0PVwiLmM4eS1lbXB0eS1zdGF0ZTpub3QoLmM4eS1uby1yZXN1bHRzLXN0YXRlKVwiPjwvbmctY29udGVudD5cbiAgPG5nLWNvbnRlbnQgKm5nSWY9XCJub1NlYXJjaFJlc3VsdHNcIiBzZWxlY3Q9XCIuYzh5LW5vLXJlc3VsdHMtc3RhdGVcIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbiJdfQ==