UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

63 lines 29.3 kB
import { Component, Output, EventEmitter } from '@angular/core'; import { BehaviorSubject, combineLatest, from } from 'rxjs'; import { switchMap, shareReplay, debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { isEqual, uniqWith, get } from 'lodash-es'; import { gettext } from '@c8y/ngx-components'; import { TranslateService } from '@ngx-translate/core'; import { DeviceProfileService } from '@c8y/ngx-components/device-profile'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components/device-profile"; import * as i2 from "@ngx-translate/core"; import * as i3 from "@c8y/ngx-components"; import * as i4 from "@angular/common"; import * as i5 from "@angular/forms"; import * as i6 from "@c8y/ngx-components/operations/stepper-frames"; export class SelectDeviceProfileStepComponent { constructor(deviceProfileService, translate) { this.deviceProfileService = deviceProfileService; this.translate = translate; this.deviceProfile = new EventEmitter(); this.textFilter$ = new BehaviorSubject(''); this.deviceType$ = new BehaviorSubject(''); this.DEVICE_TYPE_NOT_DEFINED = gettext('Device type not defined'); this.deviceTypes = []; this.selectedDeviceType = { name: '' }; this.deviceProfile$ = combineLatest(this.textFilter$, this.deviceType$).pipe(switchMap(([name, deviceType]) => this.getDeviceProfiles(name, deviceType)), shareReplay(1)); this.loadDeviceTypes(); } loadDeviceTypes() { this.deviceTypeSubscription = this.deviceType$ .pipe(debounceTime(300), distinctUntilChanged(), switchMap(searchStr => { const query = { 'c8y_Filter.type': `*${searchStr}*` }; return from(this.deviceProfileService.getDeviceProfiles(query)); })) .subscribe(({ data }) => { this.deviceTypes = uniqWith(data.map(val => ({ name: val.c8y_Filter.type })).filter(val => val.name), isEqual); }); } ngOnDestroy() { this.deviceTypeSubscription.unsubscribe(); } selectDeviceProfile(deviceProfile) { this.deviceProfile.emit(deviceProfile); } getDeviceTypeTitle(deviceProfile) { return get(deviceProfile, 'c8y_Filter.type', this.translate.instant(this.DEVICE_TYPE_NOT_DEFINED)); } getDeviceProfiles(name, deviceType) { const query = deviceType ? { 'c8y_Filter.type': deviceType } : {}; if (name) { query.name = `*${name}*`; } return this.deviceProfileService.getDeviceProfiles(query); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectDeviceProfileStepComponent, deps: [{ token: i1.DeviceProfileService }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectDeviceProfileStepComponent, selector: "c8y-select-device-profile-step", outputs: { deviceProfile: "deviceProfile" }, ngImport: i0, template: "<c8y-select-step-frame\n [header]=\"'Select device profile' | translate\"\n [noResults]=\"\n ((textFilter$ | async)?.length || (deviceType$ | async)?.length) &&\n (deviceProfile$ | async)?.data.length === 0\n \"\n>\n <div\n class=\"row\"\n filters\n >\n <div class=\"col-md-6 m-b-xs-8 m-b-sm-8\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n title=\"{{ 'Filter\u2026' | translate }}\"\n placeholder=\"{{ 'Filter\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"textFilter$ | async\"\n (ngModelChange)=\"textFilter$.next($event)\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"(textFilter$ | async).length === 0\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"(textFilter$ | async).length\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n </div>\n <div class=\"col-md-6 m-b-xs-8 m-b-sm-8\">\n <c8y-form-group class=\"m-0\">\n <c8y-typeahead\n placeholder=\"{{ 'Type to filter device types\u2026' | translate }}\"\n name=\"deviceType\"\n [(ngModel)]=\"selectedDeviceType\"\n (onSearch)=\"deviceType$.next($event)\"\n [allowFreeEntries]=\"false\"\n >\n <c8y-li\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n (click)=\"selectedDeviceType = { name: '' }; deviceType$.next('')\"\n >\n <span>{{ 'All device types' | translate }}</span>\n </c8y-li>\n <c8y-li\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n *ngFor=\"let deviceType of deviceTypes\"\n (click)=\"selectedDeviceType = deviceType; deviceType$.next(deviceType.name)\"\n [active]=\"selectedDeviceType === deviceType\"\n >\n <c8y-highlight\n [text]=\"deviceType.name\"\n [pattern]=\"deviceType$ | async\"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages>\n <c8y-message\n name=\"notExisting\"\n [text]=\"'Select one of the existing device types.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n <c8y-li\n class=\"hidden-sm hidden-xs m-r-8 m-l-8\"\n header\n >\n <c8y-li-icon><i class=\"p-l-32 p-r-40\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-5\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Name' | translate }} \"\n >\n {{ 'Name' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li *c8yFor=\"let deviceProfile of deviceProfile$ | async; loadMore: 'auto'\">\n <c8y-li-radio (onSelect)=\"selectDeviceProfile(deviceProfile)\"></c8y-li-radio>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-device-profile\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-5 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ deviceProfile.name }}\"\n >\n {{ deviceProfile.name }}\n </div>\n </div>\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(deviceProfile) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Device type\n </span>\n <span *ngIf=\"deviceProfile.c8y_Filter?.type; else noType\">\n {{ deviceProfile.c8y_Filter?.type }}\n </span>\n <ng-template #noType>\n <small>\n <em\n class=\"text-muted\"\n translate\n >\n Undefined`device type`\n </em>\n </small>\n </ng-template>\n </div>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-select-step-frame>\n", dependencies: [{ kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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.HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: i3.TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i3.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i3.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { 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: "component", type: i3.ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "component", type: i6.SelectStepFrameComponent, selector: "c8y-select-step-frame", inputs: ["header", "noResults"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectDeviceProfileStepComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-select-device-profile-step', template: "<c8y-select-step-frame\n [header]=\"'Select device profile' | translate\"\n [noResults]=\"\n ((textFilter$ | async)?.length || (deviceType$ | async)?.length) &&\n (deviceProfile$ | async)?.data.length === 0\n \"\n>\n <div\n class=\"row\"\n filters\n >\n <div class=\"col-md-6 m-b-xs-8 m-b-sm-8\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n title=\"{{ 'Filter\u2026' | translate }}\"\n placeholder=\"{{ 'Filter\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"textFilter$ | async\"\n (ngModelChange)=\"textFilter$.next($event)\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"(textFilter$ | async).length === 0\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"(textFilter$ | async).length\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n </div>\n <div class=\"col-md-6 m-b-xs-8 m-b-sm-8\">\n <c8y-form-group class=\"m-0\">\n <c8y-typeahead\n placeholder=\"{{ 'Type to filter device types\u2026' | translate }}\"\n name=\"deviceType\"\n [(ngModel)]=\"selectedDeviceType\"\n (onSearch)=\"deviceType$.next($event)\"\n [allowFreeEntries]=\"false\"\n >\n <c8y-li\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n (click)=\"selectedDeviceType = { name: '' }; deviceType$.next('')\"\n >\n <span>{{ 'All device types' | translate }}</span>\n </c8y-li>\n <c8y-li\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n *ngFor=\"let deviceType of deviceTypes\"\n (click)=\"selectedDeviceType = deviceType; deviceType$.next(deviceType.name)\"\n [active]=\"selectedDeviceType === deviceType\"\n >\n <c8y-highlight\n [text]=\"deviceType.name\"\n [pattern]=\"deviceType$ | async\"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages>\n <c8y-message\n name=\"notExisting\"\n [text]=\"'Select one of the existing device types.' | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n <c8y-li\n class=\"hidden-sm hidden-xs m-r-8 m-l-8\"\n header\n >\n <c8y-li-icon><i class=\"p-l-32 p-r-40\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-5\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Name' | translate }} \"\n >\n {{ 'Name' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li *c8yFor=\"let deviceProfile of deviceProfile$ | async; loadMore: 'auto'\">\n <c8y-li-radio (onSelect)=\"selectDeviceProfile(deviceProfile)\"></c8y-li-radio>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-device-profile\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-5 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ deviceProfile.name }}\"\n >\n {{ deviceProfile.name }}\n </div>\n </div>\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(deviceProfile) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Device type\n </span>\n <span *ngIf=\"deviceProfile.c8y_Filter?.type; else noType\">\n {{ deviceProfile.c8y_Filter?.type }}\n </span>\n <ng-template #noType>\n <small>\n <em\n class=\"text-muted\"\n translate\n >\n Undefined`device type`\n </em>\n </small>\n </ng-template>\n </div>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-select-step-frame>\n" }] }], ctorParameters: () => [{ type: i1.DeviceProfileService }, { type: i2.TranslateService }], propDecorators: { deviceProfile: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LWRldmljZS1wcm9maWxlLXN0ZXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vb3BlcmF0aW9ucy9zdGVwcGVyLWJ1bGstdHlwZS1kZXZpY2UtcHJvZmlsZS9zZWxlY3QtZGV2aWNlLXByb2ZpbGUtc3RlcC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9vcGVyYXRpb25zL3N0ZXBwZXItYnVsay10eXBlLWRldmljZS1wcm9maWxlL3NlbGVjdC1kZXZpY2UtcHJvZmlsZS1zdGVwLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRSxPQUFPLEVBQWMsZUFBZSxFQUFFLGFBQWEsRUFBZ0IsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTVGLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNuRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7Ozs7Ozs7O0FBTTFFLE1BQU0sT0FBTyxnQ0FBZ0M7SUFnQjNDLFlBQ1Usb0JBQTBDLEVBQzFDLFNBQTJCO1FBRDNCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUFqQjNCLGtCQUFhLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDO1FBQzNGLGdCQUFXLEdBQTRCLElBQUksZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELGdCQUFXLEdBQTRCLElBQUksZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELDRCQUF1QixHQUFHLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3RFLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLHVCQUFrQixHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ2xDLG1CQUFjLEdBQTRDLGFBQWEsQ0FDckUsSUFBSSxDQUFDLFdBQVcsRUFDaEIsSUFBSSxDQUFDLFdBQVcsQ0FDakIsQ0FBQyxJQUFJLENBQ0osU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsRUFDM0UsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUNmLENBQUM7UUFPQSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLFdBQVc7YUFDM0MsSUFBSSxDQUNILFlBQVksQ0FBQyxHQUFHLENBQUMsRUFDakIsb0JBQW9CLEVBQUUsRUFDdEIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ3BCLE1BQU0sS0FBSyxHQUFHLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxTQUFTLEdBQUcsRUFBRSxDQUFDO1lBQ3RELE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLENBQUMsQ0FBQyxDQUNIO2FBQ0EsU0FBUyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFO1lBQ3RCLElBQUksQ0FBQyxXQUFXLEdBQUcsUUFBUSxDQUN6QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQ3hFLE9BQU8sQ0FDUixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1QyxDQUFDO0lBRUQsbUJBQW1CLENBQUMsYUFBNkI7UUFDL0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELGtCQUFrQixDQUFDLGFBQTZCO1FBQzlDLE9BQU8sR0FBRyxDQUNSLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQ3JELENBQUM7SUFDSixDQUFDO0lBRU8saUJBQWlCLENBQUMsSUFBYSxFQUFFLFVBQW1CO1FBQzFELE1BQU0sS0FBSyxHQUFRLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3ZFLElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksSUFBSSxHQUFHLENBQUM7UUFDM0IsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVELENBQUM7K0dBL0RVLGdDQUFnQzttR0FBaEMsZ0NBQWdDLG1IQ2I3Qyx5K0lBNElBOzs0RkQvSGEsZ0NBQWdDO2tCQUo1QyxTQUFTOytCQUNFLGdDQUFnQzt3SEFJaEMsYUFBYTtzQkFBdEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgU3Vic2NyaXB0aW9uLCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHNoYXJlUmVwbGF5LCBkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSVJlc3VsdExpc3QsIElNYW5hZ2VkT2JqZWN0IH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgaXNFcXVhbCwgdW5pcVdpdGgsIGdldCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBnZXR0ZXh0IH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBEZXZpY2VQcm9maWxlU2VydmljZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvZGV2aWNlLXByb2ZpbGUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktc2VsZWN0LWRldmljZS1wcm9maWxlLXN0ZXAnLFxuICB0ZW1wbGF0ZVVybDogJ3NlbGVjdC1kZXZpY2UtcHJvZmlsZS1zdGVwLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3REZXZpY2VQcm9maWxlU3RlcENvbXBvbmVudCB7XG4gIEBPdXRwdXQoKSBkZXZpY2VQcm9maWxlOiBFdmVudEVtaXR0ZXI8SU1hbmFnZWRPYmplY3Q+ID0gbmV3IEV2ZW50RW1pdHRlcjxJTWFuYWdlZE9iamVjdD4oKTtcbiAgdGV4dEZpbHRlciQ6IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+ID0gbmV3IEJlaGF2aW9yU3ViamVjdCgnJyk7XG4gIGRldmljZVR5cGUkOiBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoJycpO1xuICByZWFkb25seSBERVZJQ0VfVFlQRV9OT1RfREVGSU5FRCA9IGdldHRleHQoJ0RldmljZSB0eXBlIG5vdCBkZWZpbmVkJyk7XG4gIGRldmljZVR5cGVzID0gW107XG4gIHNlbGVjdGVkRGV2aWNlVHlwZSA9IHsgbmFtZTogJycgfTtcbiAgZGV2aWNlUHJvZmlsZSQ6IE9ic2VydmFibGU8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiA9IGNvbWJpbmVMYXRlc3QoXG4gICAgdGhpcy50ZXh0RmlsdGVyJCxcbiAgICB0aGlzLmRldmljZVR5cGUkXG4gICkucGlwZShcbiAgICBzd2l0Y2hNYXAoKFtuYW1lLCBkZXZpY2VUeXBlXSkgPT4gdGhpcy5nZXREZXZpY2VQcm9maWxlcyhuYW1lLCBkZXZpY2VUeXBlKSksXG4gICAgc2hhcmVSZXBsYXkoMSlcbiAgKTtcbiAgcHJpdmF0ZSBkZXZpY2VUeXBlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBkZXZpY2VQcm9maWxlU2VydmljZTogRGV2aWNlUHJvZmlsZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5sb2FkRGV2aWNlVHlwZXMoKTtcbiAgfVxuXG4gIGxvYWREZXZpY2VUeXBlcygpIHtcbiAgICB0aGlzLmRldmljZVR5cGVTdWJzY3JpcHRpb24gPSB0aGlzLmRldmljZVR5cGUkXG4gICAgICAucGlwZShcbiAgICAgICAgZGVib3VuY2VUaW1lKDMwMCksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICAgIHN3aXRjaE1hcChzZWFyY2hTdHIgPT4ge1xuICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0geyAnYzh5X0ZpbHRlci50eXBlJzogYCoke3NlYXJjaFN0cn0qYCB9O1xuICAgICAgICAgIHJldHVybiBmcm9tKHRoaXMuZGV2aWNlUHJvZmlsZVNlcnZpY2UuZ2V0RGV2aWNlUHJvZmlsZXMocXVlcnkpKTtcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKHsgZGF0YSB9KSA9PiB7XG4gICAgICAgIHRoaXMuZGV2aWNlVHlwZXMgPSB1bmlxV2l0aChcbiAgICAgICAgICBkYXRhLm1hcCh2YWwgPT4gKHsgbmFtZTogdmFsLmM4eV9GaWx0ZXIudHlwZSB9KSkuZmlsdGVyKHZhbCA9PiB2YWwubmFtZSksXG4gICAgICAgICAgaXNFcXVhbFxuICAgICAgICApO1xuICAgICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmRldmljZVR5cGVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHNlbGVjdERldmljZVByb2ZpbGUoZGV2aWNlUHJvZmlsZTogSU1hbmFnZWRPYmplY3QpIHtcbiAgICB0aGlzLmRldmljZVByb2ZpbGUuZW1pdChkZXZpY2VQcm9maWxlKTtcbiAgfVxuXG4gIGdldERldmljZVR5cGVUaXRsZShkZXZpY2VQcm9maWxlOiBJTWFuYWdlZE9iamVjdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldChcbiAgICAgIGRldmljZVByb2ZpbGUsXG4gICAgICAnYzh5X0ZpbHRlci50eXBlJyxcbiAgICAgIHRoaXMudHJhbnNsYXRlLmluc3RhbnQodGhpcy5ERVZJQ0VfVFlQRV9OT1RfREVGSU5FRClcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREZXZpY2VQcm9maWxlcyhuYW1lPzogc3RyaW5nLCBkZXZpY2VUeXBlPzogc3RyaW5nKSB7XG4gICAgY29uc3QgcXVlcnk6IGFueSA9IGRldmljZVR5cGUgPyB7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2VUeXBlIH0gOiB7fTtcbiAgICBpZiAobmFtZSkge1xuICAgICAgcXVlcnkubmFtZSA9IGAqJHtuYW1lfSpgO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kZXZpY2VQcm9maWxlU2VydmljZS5nZXREZXZpY2VQcm9maWxlcyhxdWVyeSk7XG4gIH1cbn1cbiIsIjxjOHktc2VsZWN0LXN0ZXAtZnJhbWVcbiAgW2hlYWRlcl09XCInU2VsZWN0IGRldmljZSBwcm9maWxlJyB8IHRyYW5zbGF0ZVwiXG4gIFtub1Jlc3VsdHNdPVwiXG4gICAgKCh0ZXh0RmlsdGVyJCB8IGFzeW5jKT8ubGVuZ3RoIHx8IChkZXZpY2VUeXBlJCB8IGFzeW5jKT8ubGVuZ3RoKSAmJlxuICAgIChkZXZpY2VQcm9maWxlJCB8IGFzeW5jKT8uZGF0YS5sZW5ndGggPT09IDBcbiAgXCJcbj5cbiAgPGRpdlxuICAgIGNsYXNzPVwicm93XCJcbiAgICBmaWx0ZXJzXG4gID5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTYgbS1iLXhzLTggbS1iLXNtLThcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cCBpbnB1dC1ncm91cC1zZWFyY2hcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgIHRpdGxlPVwie3sgJ0ZpbHRlcuKApicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ0ZpbHRlcuKApicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgIHR5cGU9XCJzZWFyY2hcIlxuICAgICAgICAgIFtuZ01vZGVsXT1cInRleHRGaWx0ZXIkIHwgYXN5bmNcIlxuICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRleHRGaWx0ZXIkLm5leHQoJGV2ZW50KVwiXG4gICAgICAgIC8+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiaW5wdXQtZ3JvdXAtYWRkb25cIj5cbiAgICAgICAgICA8aVxuICAgICAgICAgICAgYzh5SWNvbj1cInNlYXJjaFwiXG4gICAgICAgICAgICAqbmdJZj1cIih0ZXh0RmlsdGVyJCB8IGFzeW5jKS5sZW5ndGggPT09IDBcIlxuICAgICAgICAgID48L2k+XG4gICAgICAgICAgPGlcbiAgICAgICAgICAgIGNsYXNzPVwidGV4dC1tdXRlZFwiXG4gICAgICAgICAgICBjOHlJY29uPVwidGltZXNcIlxuICAgICAgICAgICAgKm5nSWY9XCIodGV4dEZpbHRlciQgfCBhc3luYykubGVuZ3RoXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ0ZXh0RmlsdGVyJC5uZXh0KCcnKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNvbC1tZC02IG0tYi14cy04IG0tYi1zbS04XCI+XG4gICAgICA8Yzh5LWZvcm0tZ3JvdXAgY2xhc3M9XCJtLTBcIj5cbiAgICAgICAgPGM4eS10eXBlYWhlYWRcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdUeXBlIHRvIGZpbHRlciBkZXZpY2UgdHlwZXPigKYnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICBuYW1lPVwiZGV2aWNlVHlwZVwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWxlY3RlZERldmljZVR5cGVcIlxuICAgICAgICAgIChvblNlYXJjaCk9XCJkZXZpY2VUeXBlJC5uZXh0KCRldmVudClcIlxuICAgICAgICAgIFthbGxvd0ZyZWVFbnRyaWVzXT1cImZhbHNlXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxjOHktbGlcbiAgICAgICAgICAgIGNsYXNzPVwicC1sLTggcC1yLTggYzh5LWxpc3RfX2l0ZW0tLWxpbmtcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdGVkRGV2aWNlVHlwZSA9IHsgbmFtZTogJycgfTsgZGV2aWNlVHlwZSQubmV4dCgnJylcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzcGFuPnt7ICdBbGwgZGV2aWNlIHR5cGVzJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICA8L2M4eS1saT5cbiAgICAgICAgICA8Yzh5LWxpXG4gICAgICAgICAgICBjbGFzcz1cInAtbC04IHAtci04IGM4eS1saXN0X19pdGVtLS1saW5rXCJcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBkZXZpY2VUeXBlIG9mIGRldmljZVR5cGVzXCJcbiAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RlZERldmljZVR5cGUgPSBkZXZpY2VUeXBlOyBkZXZpY2VUeXBlJC5uZXh0KGRldmljZVR5cGUubmFtZSlcIlxuICAgICAgICAgICAgW2FjdGl2ZV09XCJzZWxlY3RlZERldmljZVR5cGUgPT09IGRldmljZVR5cGVcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxjOHktaGlnaGxpZ2h0XG4gICAgICAgICAgICAgIFt0ZXh0XT1cImRldmljZVR5cGUubmFtZVwiXG4gICAgICAgICAgICAgIFtwYXR0ZXJuXT1cImRldmljZVR5cGUkIHwgYXN5bmNcIlxuICAgICAgICAgICAgPjwvYzh5LWhpZ2hsaWdodD5cbiAgICAgICAgICA8L2M4eS1saT5cbiAgICAgICAgPC9jOHktdHlwZWFoZWFkPlxuICAgICAgICA8Yzh5LW1lc3NhZ2VzPlxuICAgICAgICAgIDxjOHktbWVzc2FnZVxuICAgICAgICAgICAgbmFtZT1cIm5vdEV4aXN0aW5nXCJcbiAgICAgICAgICAgIFt0ZXh0XT1cIidTZWxlY3Qgb25lIG9mIHRoZSBleGlzdGluZyBkZXZpY2UgdHlwZXMuJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgPjwvYzh5LW1lc3NhZ2U+XG4gICAgICAgIDwvYzh5LW1lc3NhZ2VzPlxuICAgICAgPC9jOHktZm9ybS1ncm91cD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxjOHktbGlcbiAgICBjbGFzcz1cImhpZGRlbi1zbSBoaWRkZW4teHMgbS1yLTggbS1sLThcIlxuICAgIGhlYWRlclxuICA+XG4gICAgPGM4eS1saS1pY29uPjxpIGNsYXNzPVwicC1sLTMyIHAtci00MFwiPjwvaT48L2M4eS1saS1pY29uPlxuICAgIDxjOHktbGktYm9keSBjbGFzcz1cImNvbnRlbnQtZmxleC00MFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC01XCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICB0aXRsZT1cIiB7eyAnTmFtZScgfCB0cmFuc2xhdGUgfX0gXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7ICdOYW1lJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtM1wiPlxuICAgICAgICA8c3BhblxuICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgdGl0bGU9XCJ7eyAnRGV2aWNlIHR5cGUnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7ICdEZXZpY2UgdHlwZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9jOHktbGktYm9keT5cbiAgPC9jOHktbGk+XG4gIDxjOHktbGlzdC1ncm91cCBsaXN0PlxuICAgIDxjOHktbGkgKmM4eUZvcj1cImxldCBkZXZpY2VQcm9maWxlIG9mIGRldmljZVByb2ZpbGUkIHwgYXN5bmM7IGxvYWRNb3JlOiAnYXV0bydcIj5cbiAgICAgIDxjOHktbGktcmFkaW8gKG9uU2VsZWN0KT1cInNlbGVjdERldmljZVByb2ZpbGUoZGV2aWNlUHJvZmlsZSlcIj48L2M4eS1saS1yYWRpbz5cbiAgICAgIDxjOHktbGktaWNvbj5cbiAgICAgICAgPGkgYzh5SWNvbj1cImM4eS1kZXZpY2UtcHJvZmlsZVwiPjwvaT5cbiAgICAgIDwvYzh5LWxpLWljb24+XG4gICAgICA8Yzh5LWxpLWJvZHkgY2xhc3M9XCJjb250ZW50LWZsZXgtNDBcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC01IG0tYi14cy04XCI+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICAgIHRpdGxlPVwie3sgZGV2aWNlUHJvZmlsZS5uYW1lIH19XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7eyBkZXZpY2VQcm9maWxlLm5hbWUgfX1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMyBtLWIteHMtOFwiPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgICB0aXRsZT1cInt7ICdEZXZpY2UgdHlwZScgfCB0cmFuc2xhdGUgfX06IHt7IGdldERldmljZVR5cGVUaXRsZShkZXZpY2VQcm9maWxlKSB9fVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci04IHZpc2libGUteHMgdmlzaWJsZS1zbVwiXG4gICAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBEZXZpY2UgdHlwZVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJkZXZpY2VQcm9maWxlLmM4eV9GaWx0ZXI/LnR5cGU7IGVsc2Ugbm9UeXBlXCI+XG4gICAgICAgICAgICAgIHt7IGRldmljZVByb2ZpbGUuYzh5X0ZpbHRlcj8udHlwZSB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNub1R5cGU+XG4gICAgICAgICAgICAgIDxzbWFsbD5cbiAgICAgICAgICAgICAgICA8ZW1cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1tdXRlZFwiXG4gICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICBVbmRlZmluZWRgZGV2aWNlIHR5cGVgXG4gICAgICAgICAgICAgICAgPC9lbT5cbiAgICAgICAgICAgICAgPC9zbWFsbD5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9jOHktbGktYm9keT5cbiAgICA8L2M4eS1saT5cbiAgPC9jOHktbGlzdC1ncm91cD5cbjwvYzh5LXNlbGVjdC1zdGVwLWZyYW1lPlxuIl19