@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
100 lines • 54.2 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, EventEmitter, Output, QueryList, ViewChildren } from '@angular/core';
import { gettext, ListItemRadioComponent, memoize } from '@c8y/ngx-components';
import { RepositoryService, RepositoryType } from '@c8y/ngx-components/repository/shared';
import { TranslateService } from '@ngx-translate/core';
import { get, isEqual, property, uniqWith } from 'lodash-es';
import { BehaviorSubject, combineLatest, from, Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, shareReplay, switchMap } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components/repository/shared";
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 SelectSoftwareStepComponent {
constructor(repositoryService, translate) {
this.repositoryService = repositoryService;
this.translate = translate;
this.software = new EventEmitter();
this.textFilter$ = new BehaviorSubject('');
this.deviceType$ = new BehaviorSubject('');
this.softwareTypeFilter$ = new BehaviorSubject('');
this.deviceTypes = [];
this.selectedDeviceType = { name: '' };
this.isLegacy = this.repositoryService.isLegacyEntry.bind(this.repositoryService);
this.software$ = combineLatest(this.textFilter$, this.deviceType$, this.softwareTypeFilter$).pipe(switchMap(([name, deviceType, softwareType]) => this.getSoftware(name, deviceType, softwareType)), shareReplay(1));
this.NO_DEVICE_TYPE_AVAILABLE = gettext('No device type available');
this.loadDeviceTypes();
}
getBaseVersionsCount$(software) {
return this.repositoryService.getBaseVersionsCount$(software).pipe(shareReplay(1));
}
getVersions(software) {
return this.repositoryService.listAllVersions(software);
}
getDeviceTypeTitle(software) {
return get(software, 'c8y_Filter.type', this.translate.instant(this.NO_DEVICE_TYPE_AVAILABLE));
}
loadDeviceTypes() {
this.deviceTypeSubscription = this.deviceType$
.pipe(debounceTime(300), distinctUntilChanged(), switchMap(searchStr => {
const query = { 'c8y_Filter.type': `*${searchStr}*` };
return from(this.repositoryService.listRepositoryEntries(RepositoryType.SOFTWARE, { query }));
}))
.subscribe(result => {
const { data } = result;
this.deviceTypes = uniqWith(data.map(val => ({ name: val.c8y_Filter.type })), isEqual);
});
}
ngOnDestroy() {
this.deviceTypeSubscription.unsubscribe();
}
resetSelection() {
this.radioButtons.map(radio => radio.reset());
}
selectSoftware({ option, software }) {
software.selectedId = option.id;
option.action = 'install';
this.emitSoftware({ option, software });
}
emitSoftware({ option, software }) {
const emitData = Object.assign({}, { software }, { version: option }, { action: option.action });
this.software.emit(emitData);
}
getSoftware(name, deviceType, softwareType) {
const query = name ? { name: `*${name}*` } : {};
if (deviceType) {
query.__or = [{ 'c8y_Filter.type': deviceType }, { __not: { __has: `c8y_Filter.type` } }];
}
if (softwareType) {
query.__or = { softwareType };
}
return this.repositoryService.listRepositoryEntries(RepositoryType.SOFTWARE, { query });
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectSoftwareStepComponent, deps: [{ token: i1.RepositoryService }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectSoftwareStepComponent, selector: "c8y-select-software-step", outputs: { software: "software" }, viewQueries: [{ propertyName: "radioButtons", predicate: ListItemRadioComponent, descendants: true }], ngImport: i0, template: "<c8y-select-step-frame\n [header]=\"'Select software' | translate\"\n [noResults]=\"\n ((textFilter$ | async)?.length ||\n (deviceType$ | async)?.length ||\n (softwareTypeFilter$ | async)?.length) &&\n (software$ | async)?.data.length === 0\n \"\n>\n <div\n class=\"row\"\n filters\n >\n <div class=\"col-md-4 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 > 0\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n </div>\n <div class=\"col-md-4 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 [active]=\"!selectedDeviceType?.name\"\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 class=\"col-md-4\">\n <c8y-form-group class=\"m-0\">\n <c8y-software-type\n [required]=\"false\"\n [emitResultsOnly]=\"true\"\n [showBtnInNotFoundMessage]=\"false\"\n [allowFreeEntries]=\"false\"\n [placeholder]=\"'Type to filter software types\u2026' | translate\"\n [showClearSelectionOption]=\"true\"\n (onSelectSoftware)=\"softwareTypeFilter$.next($event?.softwareType)\"\n ></c8y-software-type>\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-24\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40 p-r-32\">\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-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Software type' | translate }}\"\n >\n {{ 'Software type' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Versions' | translate }}\"\n >\n {{ 'Versions' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li\n *c8yFor=\"let software of software$ | async; loadMore: 'auto'\"\n #li\n >\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <div class=\"content-flex-40\">\n <div class=\"col-5 m-b-xs-8\">\n <button\n class=\"btn-clean\"\n title=\"{{ software.name }}\"\n type=\"button\"\n (click)=\"li.collapsed = !li.collapsed\"\n >\n <c8y-highlight\n [text]=\"software.name\"\n [pattern]=\"textFilter$ | async\"\n ></c8y-highlight>\n </button>\n </div>\n <div class=\"col-2 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(software) }}\"\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=\"software.c8y_Filter?.type; else noType\">\n {{ software.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 <div class=\"col-3 m-b-xs-8\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Software type\n </span>\n <span\n class=\"label label-info\"\n *ngIf=\"software.softwareType; else emptyText\"\n >\n {{ software.softwareType }}\n </span>\n <ng-template #emptyText>\n <small class=\"text-muted\">\n <em translate>Undefined`software type`</em>\n </small>\n </ng-template>\n </div>\n <div class=\"col-2\">\n <span\n class=\"label label-warning m-l-auto-sm\"\n *ngIf=\"isLegacy(software)\"\n >\n <span translate>Legacy</span>\n </span>\n <span *ngIf=\"!isLegacy(software)\">\n <span *ngIf=\"(getBaseVersionsCount$(software) | async) === null\">\n <span class=\"label label-info\">\n <i\n class=\"icon-spin\"\n c8yIcon=\"circle-o-notch\"\n ></i>\n </span>\n </span>\n <span *ngIf=\"(getBaseVersionsCount$(software) | async) !== null\">\n <span [ngPlural]=\"getBaseVersionsCount$(software) | async\">\n <ng-template ngPluralCase=\"=1\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n version\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">1</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n versions\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">\n {{ getBaseVersionsCount$(software) | async }}\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </div>\n <c8y-li-collapse>\n <c8y-list-group>\n <c8y-li *c8yFor=\"let option of getVersions(software) | async\">\n <c8y-li-radio\n [name]=\"software.id\"\n (onSelect)=\"selectSoftware({ option: option, software: software })\"\n ></c8y-li-radio>\n <c8y-li-body class=\"content-flex-40 p-r-16\">\n <div class=\"col-4\">\n {{ option.c8y_Software.version }}\n </div>\n <div class=\"col-5\">\n <div\n class=\"text-truncate\"\n title=\"{{ option.c8y_Software.url }}\"\n >\n <span\n class=\"text-label-small m-r-4\"\n translate\n >\n File\n </span>\n <span>{{ option.c8y_Software.url }}</span>\n </div>\n </div>\n <div\n class=\"col-3 d-flex\"\n *ngIf=\"option.id === software.selectedId\"\n >\n <div\n class=\"c8y-select-wrapper d-inline-block m-l-auto\"\n style=\"margin: -4px 0\"\n >\n <select\n class=\"form-control input-sm\"\n id=\"action\"\n [(ngModel)]=\"option.action\"\n (change)=\"emitSoftware({ option: option, software: software })\"\n >\n <option [ngValue]=\"'install'\">\n {{ 'Install/update`software`' | translate }}\n </option>\n <option [ngValue]=\"'delete'\">{{ 'Remove`software`' | translate }}</option>\n </select>\n <span></span>\n </div>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\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: i4.NgPlural, selector: "[ngPlural]", inputs: ["ngPlural"] }, { kind: "directive", type: i4.NgPluralCase, selector: "[ngPluralCase]" }, { 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.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { 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.ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: i3.ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "component", type: i1.SoftwareTypeComponent, selector: "c8y-software-type", inputs: ["softwareTypeMO", "disabled", "style", "required", "placeholder", "emitResultsOnly", "showBtnInNotFoundMessage", "allowFreeEntries", "showClearSelectionOption", "clearSelectionOptionLabel", "presetSoftwareTypes"], outputs: ["onSelectSoftware"] }, { 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" }] }); }
}
__decorate([
memoize(property('id')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Observable)
], SelectSoftwareStepComponent.prototype, "getBaseVersionsCount$", null);
__decorate([
memoize(property('id')),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], SelectSoftwareStepComponent.prototype, "getVersions", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectSoftwareStepComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-select-software-step', template: "<c8y-select-step-frame\n [header]=\"'Select software' | translate\"\n [noResults]=\"\n ((textFilter$ | async)?.length ||\n (deviceType$ | async)?.length ||\n (softwareTypeFilter$ | async)?.length) &&\n (software$ | async)?.data.length === 0\n \"\n>\n <div\n class=\"row\"\n filters\n >\n <div class=\"col-md-4 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 > 0\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n </div>\n <div class=\"col-md-4 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 [active]=\"!selectedDeviceType?.name\"\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 class=\"col-md-4\">\n <c8y-form-group class=\"m-0\">\n <c8y-software-type\n [required]=\"false\"\n [emitResultsOnly]=\"true\"\n [showBtnInNotFoundMessage]=\"false\"\n [allowFreeEntries]=\"false\"\n [placeholder]=\"'Type to filter software types\u2026' | translate\"\n [showClearSelectionOption]=\"true\"\n (onSelectSoftware)=\"softwareTypeFilter$.next($event?.softwareType)\"\n ></c8y-software-type>\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-24\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40 p-r-32\">\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-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Software type' | translate }}\"\n >\n {{ 'Software type' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Versions' | translate }}\"\n >\n {{ 'Versions' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li\n *c8yFor=\"let software of software$ | async; loadMore: 'auto'\"\n #li\n >\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <div class=\"content-flex-40\">\n <div class=\"col-5 m-b-xs-8\">\n <button\n class=\"btn-clean\"\n title=\"{{ software.name }}\"\n type=\"button\"\n (click)=\"li.collapsed = !li.collapsed\"\n >\n <c8y-highlight\n [text]=\"software.name\"\n [pattern]=\"textFilter$ | async\"\n ></c8y-highlight>\n </button>\n </div>\n <div class=\"col-2 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(software) }}\"\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=\"software.c8y_Filter?.type; else noType\">\n {{ software.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 <div class=\"col-3 m-b-xs-8\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Software type\n </span>\n <span\n class=\"label label-info\"\n *ngIf=\"software.softwareType; else emptyText\"\n >\n {{ software.softwareType }}\n </span>\n <ng-template #emptyText>\n <small class=\"text-muted\">\n <em translate>Undefined`software type`</em>\n </small>\n </ng-template>\n </div>\n <div class=\"col-2\">\n <span\n class=\"label label-warning m-l-auto-sm\"\n *ngIf=\"isLegacy(software)\"\n >\n <span translate>Legacy</span>\n </span>\n <span *ngIf=\"!isLegacy(software)\">\n <span *ngIf=\"(getBaseVersionsCount$(software) | async) === null\">\n <span class=\"label label-info\">\n <i\n class=\"icon-spin\"\n c8yIcon=\"circle-o-notch\"\n ></i>\n </span>\n </span>\n <span *ngIf=\"(getBaseVersionsCount$(software) | async) !== null\">\n <span [ngPlural]=\"getBaseVersionsCount$(software) | async\">\n <ng-template ngPluralCase=\"=1\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n version\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">1</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n versions\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">\n {{ getBaseVersionsCount$(software) | async }}\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </div>\n <c8y-li-collapse>\n <c8y-list-group>\n <c8y-li *c8yFor=\"let option of getVersions(software) | async\">\n <c8y-li-radio\n [name]=\"software.id\"\n (onSelect)=\"selectSoftware({ option: option, software: software })\"\n ></c8y-li-radio>\n <c8y-li-body class=\"content-flex-40 p-r-16\">\n <div class=\"col-4\">\n {{ option.c8y_Software.version }}\n </div>\n <div class=\"col-5\">\n <div\n class=\"text-truncate\"\n title=\"{{ option.c8y_Software.url }}\"\n >\n <span\n class=\"text-label-small m-r-4\"\n translate\n >\n File\n </span>\n <span>{{ option.c8y_Software.url }}</span>\n </div>\n </div>\n <div\n class=\"col-3 d-flex\"\n *ngIf=\"option.id === software.selectedId\"\n >\n <div\n class=\"c8y-select-wrapper d-inline-block m-l-auto\"\n style=\"margin: -4px 0\"\n >\n <select\n class=\"form-control input-sm\"\n id=\"action\"\n [(ngModel)]=\"option.action\"\n (change)=\"emitSoftware({ option: option, software: software })\"\n >\n <option [ngValue]=\"'install'\">\n {{ 'Install/update`software`' | translate }}\n </option>\n <option [ngValue]=\"'delete'\">{{ 'Remove`software`' | translate }}</option>\n </select>\n <span></span>\n </div>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\n </c8y-li>\n </c8y-list-group>\n</c8y-select-step-frame>\n" }]
}], ctorParameters: () => [{ type: i1.RepositoryService }, { type: i2.TranslateService }], propDecorators: { software: [{
type: Output
}], radioButtons: [{
type: ViewChildren,
args: [ListItemRadioComponent]
}], getBaseVersionsCount$: [], getVersions: [] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LXNvZnR3YXJlLXN0ZXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vb3BlcmF0aW9ucy9zdGVwcGVyLWJ1bGstdHlwZS1zb2Z0d2FyZS9zZWxlY3Qtc29mdHdhcmUtc3RlcC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9vcGVyYXRpb25zL3N0ZXBwZXItYnVsay10eXBlLXNvZnR3YXJlL3NlbGVjdC1zb2Z0d2FyZS1zdGVwLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUV6RixPQUFPLEVBQUUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUMxRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdELE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7OztBQU81RixNQUFNLE9BQU8sMkJBQTJCO0lBdUJ0QyxZQUFvQixpQkFBb0MsRUFBVSxTQUEyQjtRQUF6RSxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUF0Qm5GLGFBQVEsR0FBb0MsSUFBSSxZQUFZLEVBQXFCLENB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OytHQS9GVSwyQkFBMkI7bUdBQTNCLDJCQUEyQixvSUFtQnhCLHNCQUFzQixnRENqQ3RDLDY1VEF5U0E7O0FEL1BFO0lBREMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQzs7O29DQUN5QixVQUFVO3dFQUUxRDtBQUdEO0lBREMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQzs7Ozs4REFHdkI7NEZBbkNVLDJCQUEyQjtrQkFKdkMsU0FBUzsrQkFDRSwwQkFBMEI7cUhBSTFCLFFBQVE7c0JBQWpCLE1BQU07Z0JBa0IrQixZQUFZO3NCQUFqRCxZQUFZO3VCQUFDLHNCQUFzQjtnQkFTcEMscUJBQXFCLE1BS3JCLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBRdWVyeUxpc3QsIFZpZXdDaGlsZHJlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSU1hbmFnZWRPYmplY3QsIElSZXN1bHRMaXN0IH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgZ2V0dGV4dCwgTGlzdEl0ZW1SYWRpb0NvbXBvbmVudCwgbWVtb2l6ZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgUmVwb3NpdG9yeVNlcnZpY2UsIFJlcG9zaXRvcnlUeXBlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9yZXBvc2l0b3J5L3NoYXJlZCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBnZXQsIGlzRXF1YWwsIHByb3BlcnR5LCB1bmlxV2l0aCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIGZyb20sIE9ic2VydmFibGUsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgc2hhcmVSZXBsYXksIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElTZWxlY3RlZFNvZnR3YXJlIH0gZnJvbSAnLi9zZWxlY3Qtc29mdHdhcmUubW9kZWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktc2VsZWN0LXNvZnR3YXJlLXN0ZXAnLFxuICB0ZW1wbGF0ZVVybDogJ3NlbGVjdC1zb2Z0d2FyZS1zdGVwLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3RTb2Z0d2FyZVN0ZXBDb21wb25lbnQge1xuICBAT3V0cHV0KCkgc29mdHdhcmU6IEV2ZW50RW1pdHRlcjxJU2VsZWN0ZWRTb2Z0d2FyZT4gPSBuZXcgRXZlbnRFbWl0dGVyPElTZWxlY3RlZFNvZnR3YXJlPigpO1xuICB0ZXh0RmlsdGVyJDogQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KCcnKTtcbiAgZGV2aWNlVHlwZSQ6IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+ID0gbmV3IEJlaGF2aW9yU3ViamVjdCgnJyk7XG4gIHNvZnR3YXJlVHlwZUZpbHRlciQ6IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+ID0gbmV3IEJlaGF2aW9yU3ViamVjdCgnJyk7XG4gIGRldmljZVR5cGVzID0gW107XG4gIHNlbGVjdGVkRGV2aWNlVHlwZSA9IHsgbmFtZTogJycgfTtcbiAgaXNMZWdhY3kgPSB0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlLmlzTGVnYWN5RW50cnkuYmluZCh0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlKTtcbiAgc29mdHdhcmUkOiBPYnNlcnZhYmxlPElSZXN1bHRMaXN0PElNYW5hZ2VkT2JqZWN0Pj4gPSBjb21iaW5lTGF0ZXN0KFxuICAgIHRoaXMudGV4dEZpbHRlciQsXG4gICAgdGhpcy5kZXZpY2VUeXBlJCxcbiAgICB0aGlzLnNvZnR3YXJlVHlwZUZpbHRlciRcbiAgKS5waXBlKFxuICAgIHN3aXRjaE1hcCgoW25hbWUsIGRldmljZVR5cGUsIHNvZnR3YXJlVHlwZV0pID0+XG4gICAgICB0aGlzLmdldFNvZnR3YXJlKG5hbWUsIGRldmljZVR5cGUsIHNvZnR3YXJlVHlwZSlcbiAgICApLFxuICAgIHNoYXJlUmVwbGF5KDEpXG4gICk7XG4gIHJlYWRvbmx5IE5PX0RFVklDRV9UWVBFX0FWQUlMQUJMRSA9IGdldHRleHQoJ05vIGRldmljZSB0eXBlIGF2YWlsYWJsZScpO1xuICBAVmlld0NoaWxkcmVuKExpc3RJdGVtUmFkaW9Db21wb25lbnQpIHJhZGlvQnV0dG9uczogUXVlcnlMaXN0PExpc3RJdGVtUmFkaW9Db21wb25lbnQ+O1xuXG4gIHByaXZhdGUgZGV2aWNlVHlwZVN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVwb3NpdG9yeVNlcnZpY2U6IFJlcG9zaXRvcnlTZXJ2aWNlLCBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSkge1xuICAgIHRoaXMubG9hZERldmljZVR5cGVzKCk7XG4gIH1cblxuICBAbWVtb2l6ZShwcm9wZXJ0eSgnaWQnKSlcbiAgZ2V0QmFzZVZlcnNpb25zQ291bnQkKHNvZnR3YXJlOiBJTWFuYWdlZE9iamVjdCk6IE9ic2VydmFibGU8bnVtYmVyPiB7XG4gICAgcmV0dXJuIHRoaXMucmVwb3NpdG9yeVNlcnZpY2UuZ2V0QmFzZVZlcnNpb25zQ291bnQkKHNvZnR3YXJlKS5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgfVxuXG4gIEBtZW1vaXplKHByb3BlcnR5KCdpZCcpKVxuICBnZXRWZXJzaW9ucyhzb2Z0d2FyZTogSU1hbmFnZWRPYmplY3QpIHtcbiAgICByZXR1cm4gdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0QWxsVmVyc2lvbnMoc29mdHdhcmUpO1xuICB9XG5cbiAgZ2V0RGV2aWNlVHlwZVRpdGxlKHNvZnR3YXJlOiBJTWFuYWdlZE9iamVjdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldChzb2Z0d2FyZSwgJ2M4eV9GaWx0ZXIudHlwZScsIHRoaXMudHJhbnNsYXRlLmluc3RhbnQodGhpcy5OT19ERVZJQ0VfVFlQRV9BVkFJTEFCTEUpKTtcbiAgfVxuXG4gIGxvYWREZXZpY2VUeXBlcygpIHtcbiAgICB0aGlzLmRldmljZVR5cGVTdWJzY3JpcHRpb24gPSB0aGlzLmRldmljZVR5cGUkXG4gICAgICAucGlwZShcbiAgICAgICAgZGVib3VuY2VUaW1lKDMwMCksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICAgIHN3aXRjaE1hcChzZWFyY2hTdHIgPT4ge1xuICAgICAgICAgIGNvbnN0IHF1ZXJ5ID0geyAnYzh5X0ZpbHRlci50eXBlJzogYCoke3NlYXJjaFN0cn0qYCB9O1xuICAgICAgICAgIHJldHVybiBmcm9tKFxuICAgICAgICAgICAgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuU09GVFdBUkUsIHsgcXVlcnkgfSlcbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZShyZXN1bHQgPT4ge1xuICAgICAgICBjb25zdCB7IGRhdGEgfSA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5kZXZpY2VUeXBlcyA9IHVuaXFXaXRoKFxuICAgICAgICAgIGRhdGEubWFwKHZhbCA9PiAoeyBuYW1lOiB2YWwuYzh5X0ZpbHRlci50eXBlIH0pKSxcbiAgICAgICAgICBpc0VxdWFsXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuZGV2aWNlVHlwZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcmVzZXRTZWxlY3Rpb24oKSB7XG4gICAgdGhpcy5yYWRpb0J1dHRvbnMubWFwKHJhZGlvID0+IHJhZGlvLnJlc2V0KCkpO1xuICB9XG5cbiAgc2VsZWN0U29mdHdhcmUoeyBvcHRpb24sIHNvZnR3YXJlIH0pIHtcbiAgICBzb2Z0d2FyZS5zZWxlY3RlZElkID0gb3B0aW9uLmlkO1xuICAgIG9wdGlvbi5hY3Rpb24gPSAnaW5zdGFsbCc7XG4gICAgdGhpcy5lbWl0U29mdHdhcmUoeyBvcHRpb24sIHNvZnR3YXJlIH0pO1xuICB9XG5cbiAgZW1pdFNvZnR3YXJlKHsgb3B0aW9uLCBzb2Z0d2FyZSB9KSB7XG4gICAgY29uc3QgZW1pdERhdGEgPSBPYmplY3QuYXNzaWduKFxuICAgICAge30sXG4gICAgICB7IHNvZnR3YXJlIH0sXG4gICAgICB7IHZlcnNpb246IG9wdGlvbiB9LFxuICAgICAgeyBhY3Rpb246IG9wdGlvbi5hY3Rpb24gfVxuICAgICk7XG4gICAgdGhpcy5zb2Z0d2FyZS5lbWl0KGVtaXREYXRhKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U29mdHdhcmUobmFtZT86IHN0cmluZywgZGV2aWNlVHlwZT86IHN0cmluZywgc29mdHdhcmVUeXBlPzogc3RyaW5nKSB7XG4gICAgY29uc3QgcXVlcnk6IGFueSA9IG5hbWUgPyB7IG5hbWU6IGAqJHtuYW1lfSpgIH0gOiB7fTtcbiAgICBpZiAoZGV2aWNlVHlwZSkge1xuICAgICAgcXVlcnkuX19vciA9IFt7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2VUeXBlIH0sIHsgX19ub3Q6IHsgX19oYXM6IGBjOHlfRmlsdGVyLnR5cGVgIH0gfV07XG4gICAgfVxuICAgIGlmIChzb2Z0d2FyZVR5cGUpIHtcbiAgICAgIHF1ZXJ5Ll9fb3IgPSB7IHNvZnR3YXJlVHlwZSB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuU09GVFdBUkUsIHsgcXVlcnkgfSk7XG4gIH1cbn1cbiIsIjxjOHktc2VsZWN0LXN0ZXAtZnJhbWVcbiAgW2hlYWRlcl09XCInU2VsZWN0IHNvZnR3YXJlJyB8IHRyYW5zbGF0ZVwiXG4gIFtub1Jlc3VsdHNdPVwiXG4gICAgKCh0ZXh0RmlsdGVyJCB8IGFzeW5jKT8ubGVuZ3RoIHx8XG4gICAgICAoZGV2aWNlVHlwZSQgfCBhc3luYyk/Lmxlbmd0aCB8fFxuICAgICAgKHNvZnR3YXJlVHlwZUZpbHRlciQgfCBhc3luYyk/Lmxlbmd0aCkgJiZcbiAgICAoc29mdHdhcmUkIHwgYXN5bmMpPy5kYXRhLmxlbmd0aCA9PT0gMFxuICBcIlxuPlxuICA8ZGl2XG4gICAgY2xhc3M9XCJyb3dcIlxuICAgIGZpbHRlcnNcbiAgPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNCBtLWIteHMtOCBtLWItc20tOFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwIGlucHV0LWdyb3VwLXNlYXJjaFwiPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgdGl0bGU9XCJ7eyAnRmlsdGVy4oCmJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgcGxhY2Vob2xkZXI9XCJ7eyAnRmlsdGVy4oCmJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgdHlwZT1cInNlYXJjaFwiXG4gICAgICAgICAgW25nTW9kZWxdPVwidGV4dEZpbHRlciQgfCBhc3luY1wiXG4gICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwidGV4dEZpbHRlciQubmV4dCgkZXZlbnQpXCJcbiAgICAgICAgLz5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJpbnB1dC1ncm91cC1hZGRvblwiPlxuICAgICAgICAgIDxpXG4gICAgICAgICAgICBjOHlJY29uPVwic2VhcmNoXCJcbiAgICAgICAgICAgICpuZ0lmPVwiKHRleHRGaWx0ZXIkIHwgYXN5bmMpLmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgICA8aVxuICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LW11dGVkXCJcbiAgICAgICAgICAgIGM4eUljb249XCJ0aW1lc1wiXG4gICAgICAgICAgICAqbmdJZj1cIih0ZXh0RmlsdGVyJCB8IGFzeW5jKS5sZW5ndGggPiAwXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ0ZXh0RmlsdGVyJC5uZXh0KCcnKVwiXG4gICAgICAgICAgPjwvaT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNvbC1tZC00IG0tYi14cy04IG0tYi1zbS04XCI+XG4gICAgICA8Yzh5LWZvcm0tZ3JvdXAgY2xhc3M9XCJtLTBcIj5cbiAgICAgICAgPGM4eS10eXBlYWhlYWRcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdUeXBlIHRvIGZpbHRlciBkZXZpY2UgdHlwZXPigKYnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICBuYW1lPVwiZGV2aWNlVHlwZVwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWxlY3RlZERldmljZVR5cGVcIlxuICAgICAgICAgIChvblNlYXJjaCk9XCJkZXZpY2VUeXBlJC5uZXh0KCRldmVudClcIlxuICAgICAgICAgIFthbGxvd0ZyZWVFbnRyaWVzXT1cImZhbHNlXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxjOHktbGlcbiAgICAgICAgICAgIGNsYXNzPVwicC1sLTggcC1yLTggYzh5LWxpc3RfX2l0ZW0tLWxpbmtcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdGVkRGV2aWNlVHlwZSA9IHsgbmFtZTogJycgfTsgZGV2aWNlVHlwZSQubmV4dCgnJylcIlxuICAgICAgICAgICAgW2FjdGl2ZV09XCIhc2VsZWN0ZWREZXZpY2VUeXBlPy5uYW1lXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c3Bhbj57eyAnQWxsIGRldmljZSB0eXBlcycgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgICAgPC9jOHktbGk+XG4gICAgICAgICAgPGM4eS1saVxuICAgICAgICAgICAgY2xhc3M9XCJwLWwtOCBwLXItOCBjOHktbGlzdF9faXRlbS0tbGlua1wiXG4gICAgICAgICAgICAqbmdGb3I9XCJsZXQgZGV2aWNlVHlwZSBvZiBkZXZpY2VUeXBlc1wiXG4gICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0ZWREZXZpY2VUeXBlID0gZGV2aWNlVHlwZTsgZGV2aWNlVHlwZSQubmV4dChkZXZpY2VUeXBlLm5hbWUpXCJcbiAgICAgICAgICAgIFthY3RpdmVdPVwic2VsZWN0ZWREZXZpY2VUeXBlID09PSBkZXZpY2VUeXBlXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8Yzh5LWhpZ2hsaWdodFxuICAgICAgICAgICAgICBbdGV4dF09XCJkZXZpY2VUeXBlLm5hbWVcIlxuICAgICAgICAgICAgICBbcGF0dGVybl09XCJkZXZpY2VUeXBlJCB8IGFzeW5jXCJcbiAgICAgICAgICAgID48L2M4eS1oaWdobGlnaHQ+XG4gICAgICAgICAgPC9jOHktbGk+XG4gICAgICAgIDwvYzh5LXR5cGVhaGVhZD5cbiAgICAgICAgPGM4eS1tZXNzYWdlcz5cbiAgICAgICAgICA8Yzh5LW1lc3NhZ2VcbiAgICAgICAgICAgIG5hbWU9XCJub3RFeGlzdGluZ1wiXG4gICAgICAgICAgICBbdGV4dF09XCInU2VsZWN0IG9uZSBvZiB0aGUgZXhpc3RpbmcgZGV2aWNlIHR5cGVzLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgID48L2M4eS1tZXNzYWdlPlxuICAgICAgICA8L2M4eS1tZXNzYWdlcz5cbiAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNvbC1tZC00XCI+XG4gICAgICA8Yzh5LWZvcm0tZ3JvdXAgY2xhc3M9XCJtLTBcIj5cbiAgICAgICAgPGM4eS1zb2Z0d2FyZS10eXBlXG4gICAgICAgICAgW3JlcXVpcmVkXT1cImZhbHNlXCJcbiAgICAgICAgICBbZW1pdFJlc3VsdHNPbmx5XT1cInRydWVcIlxuICAgICAgICAgIFtzaG93QnRuSW5Ob3RGb3VuZE1lc3NhZ2VdPVwiZmFsc2VcIlxuICAgICAgICAgIFthbGxvd0ZyZWVFbnRyaWVzXT1cImZhbHNlXCJcbiAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1R5cGUgdG8gZmlsdGVyIHNvZnR3YXJlIHR5cGVz4oCmJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgW3Nob3dDbGVhclNlbGVjdGlvbk9wdGlvbl09XCJ0cnVlXCJcbiAgICAgICAgICAob25TZWxlY3RTb2Z0d2FyZSk9XCJzb2Z0d2FyZVR5cGVGaWx0ZXIkLm5leHQoJGV2ZW50Py5zb2Z0d2FyZVR5cGUpXCJcbiAgICAgICAgPjwvYzh5LXNvZnR3YXJlLXR5cGU+XG4gICAgICAgIDxjOHktbWVzc2FnZXM+XG4gICAgICAgICAgPGM4eS1tZXNzYWdlXG4gICAgICAgICAgICBuYW1lPVwibm90RXhpc3RpbmdcIlxuICAgICAgICAgICAgW3RleHRdPVwiJ1NlbGVjdCBvbmUgb2YgdGhlIGV4aXN0aW5nIGRldmljZSB0eXBlcy4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICA+PC9jOHktbWVzc2FnZT5cbiAgICAgICAgPC9jOHktbWVzc2FnZXM+XG4gICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGM4eS1saVxuICAgIGNsYXNzPVwiaGlkZGVuLXNtIGhpZGRlbi14cyBtLXItOCBtLWwtOFwiXG4gICAgaGVhZGVyXG4gID5cbiAgICA8Yzh5LWxpLWljb24+PGkgY2xhc3M9XCJwLWwtMjRcIj48L2k+PC9jOHktbGktaWNvbj5cbiAgICA8Yzh5LWxpLWJvZHkgY2xhc3M9XCJjb250ZW50LWZsZXgtNDAgcC1yLTMyXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTVcIj5cbiAgICAgICAgPHNwYW5cbiAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgIHRpdGxlPVwiIHt7ICdOYW1lJyB8IHRyYW5zbGF0ZSB9fSBcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ05hbWUnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC0yXCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICB0aXRsZT1cInt7ICdEZXZpY2UgdHlwZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ0RldmljZSB0eXBlJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtM1wiPlxuICAgICAgICA8c3BhblxuICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgdGl0bGU9XCJ7eyAnU29mdHdhcmUgdHlwZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ1NvZnR3YXJlIHR5cGUnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC0yXCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICB0aXRsZT1cInt7ICdWZXJzaW9ucycgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ1ZlcnNpb25zJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2M4eS1saS1ib2R5PlxuICA8L2M4eS1saT5cbiAgPGM4eS1saXN0LWdyb3VwIGxpc3Q+XG4gICAgPGM4eS1saVxuICAgICAgKmM4eUZvcj1cImxldCBzb2Z0d2FyZSBvZiBzb2Z0d2FyZSQgfCBhc3luYzsgbG9hZE1vcmU6ICdhdXRvJ1wiXG4gICAgICAjbGlcbiAgICA+XG4gICAgICA8Yzh5LWxpLWljb24+XG4gICAgICAgIDxpIGM4eUljb249XCJjOHktdG9vbHNcIj48L2k+XG4gICAgICA8L2M4eS1saS1pY29uPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbnRlbnQtZmxleC00MFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTUgbS1iLXhzLThcIj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBjbGFzcz1cImJ0bi1jbGVhblwiXG4gICAgICAgICAgICB0aXRsZT1cInt7IHNvZnR3YXJlLm5hbWUgfX1cIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAoY2xpY2spPVwibGkuY29sbGFwc2VkID0gIWxpLmNvbGxhcHNlZFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGM4eS1oaWdobGlnaHRcbiAgICAgICAgICAgICAgW3RleHRdPVwic29mdHdhcmUubmFtZVwiXG4gICAgICAgICAgICAgIFtwYXR0ZXJuXT1cInRleHRGaWx0ZXIkIHwgYXN5bmNcIlxuICAgICAgICAgICAgPjwvYzh5LWhpZ2hsaWdodD5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMiBtLWIteHMtOFwiPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgICB0aXRsZT1cInt7ICdEZXZpY2UgdHlwZScgfCB0cmFuc2xhdGUgfX06IHt7IGdldERldmljZVR5cGVUaXRsZShzb2Z0d2FyZSkgfX1cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1sYWJlbC1zbWFsbCBtLXItOCB2aXNpYmxlLXhzIHZpc2libGUtc21cIlxuICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgRGV2aWNlIHR5cGVcbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwic29mdHdhcmUuYzh5X0ZpbHRlcj8udHlwZTsgZWxzZSBub1R5cGVcIj5cbiAgICAgICAgICAgICAge3sgc29mdHdhcmUuYzh5X0ZpbHRlcj8udHlwZSB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNub1R5cGU+XG4gICAgICAgICAgICAgIDxzbWFsbD5cbiAgICAgICAgICAgICAgICA8ZW1cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1tdXRlZFwiXG4gICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICBVbmRlZmluZWRgZGV2aWNlIHR5cGVgXG4gICAgICAgICAgICAgICAgPC9lbT5cbiAgICAgICAgICAgICAgPC9zbWFsbD5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTMgbS1iLXhzLThcIj5cbiAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci04IHZpc2libGUteHMgdmlzaWJsZS1zbVwiXG4gICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICA+XG4gICAgICAgICAgICBTb2Z0d2FyZSB0eXBlXG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICBjbGFzcz1cImxhYmVsIGxhYmVsLWluZm9cIlxuICAgICAgICAgICAgKm5nSWY9XCJzb2Z0d2FyZS5zb2Z0d2FyZVR5cGU7IGVsc2UgZW1wdHlUZXh0XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7eyBzb2Z0d2FyZS5zb2Z0d2FyZVR5cGUgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNlbXB0eVRleHQ+XG4gICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgICAgICAgICAgIDxlbSB0cmFuc2xhdGU+VW5kZWZpbmVkYHNvZnR3YXJlIHR5cGVgPC9lbT5cbiAgICAgICAgICAgIDwvc21hbGw+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMlwiPlxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICBjbGFzcz1cImxhYmVsIGxhYmVsLXdhcm5pbmcgbS1sLWF1dG8tc21cIlxuICAgICAgICAgICAgKm5nSWY9XCJpc0xlZ2FjeShzb2Z0d2FyZSlcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5MZWdhY3k8L3NwYW4+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiIWlzTGVnYWN5KHNvZnR3YXJlKVwiPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIoZ2V0QmFzZVZlcnNpb25zQ291bnQkKHNvZnR3YXJlKSB8IGFzeW5jKSA9PT0gbnVsbFwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsIGxhYmVsLWluZm9cIj5cbiAgICAgICAgICAgICAgICA8aVxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpY29uLXNwaW5cIlxuICAgICAgICAgICAgICAgICAgYzh5SWNvbj1cImNpcmNsZS1vLW5vdGNoXCJcbiAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICA8L3NwYW4+XG