UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

282 lines (275 loc) 47.8 kB
import { __decorate, __metadata } from 'tslib'; import * as i0 from '@angular/core'; import { EventEmitter, ViewChildren, Output, Component, Input, ViewChild, NgModule } from '@angular/core'; import * as i3 from '@c8y/ngx-components'; import { gettext, ListItemRadioComponent, memoize, Status, CoreModule, FormsModule } from '@c8y/ngx-components'; import * as i1 from '@c8y/ngx-components/repository/shared'; import { RepositoryType, SharedRepositoryModule } from '@c8y/ngx-components/repository/shared'; import * as i2 from '@ngx-translate/core'; import { get, uniqWith, isEqual, property, uniq, has } from 'lodash-es'; import { BehaviorSubject, combineLatest, from, Observable } from 'rxjs'; import { switchMap, shareReplay, debounceTime, distinctUntilChanged } from 'rxjs/operators'; import * as i4 from '@angular/common'; import * as i5 from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms'; import * as i3$1 from '@c8y/ngx-components/operations/stepper-frames'; import { StepperFramesModule } from '@c8y/ngx-components/operations/stepper-frames'; import * as i3$2 from '@c8y/ngx-components/operations/bulk-operation-stepper'; import { BaseStepperComponent, BulkOperationStepperModule } from '@c8y/ngx-components/operations/bulk-operation-stepper'; import { BulkOperationType, hookListBulkType, baseUrl } from '@c8y/ngx-components/operations/bulk-operations-service'; 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: "19.2.14", 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: "19.2.14", type: SelectSoftwareStepComponent, isStandalone: false, 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 <p class=\"text-truncate\">\n <span\n class=\"text-label-small m-r-8\"\n translate\n >\n File\n </span>\n <ng-container *ngIf=\"option.c8y_Software.url === '$PROVIDED'; else fileDownload\">\n <span title=\"{{ 'Provided by device' | translate }}\">\n {{ 'Provided by device' | translate }}\n </span>\n </ng-container>\n <ng-template #fileDownload>\n <span title=\"{{ option.c8y_Software.url }}\">\n {{ option.c8y_Software.url }}\n </span>\n </ng-template>\n </p>\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: i3$1.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: "19.2.14", ngImport: i0, type: SelectSoftwareStepComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-select-software-step', standalone: false, 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 <p class=\"text-truncate\">\n <span\n class=\"text-label-small m-r-8\"\n translate\n >\n File\n </span>\n <ng-container *ngIf=\"option.c8y_Software.url === '$PROVIDED'; else fileDownload\">\n <span title=\"{{ 'Provided by device' | translate }}\">\n {{ 'Provided by device' | translate }}\n </span>\n </ng-container>\n <ng-template #fileDownload>\n <span title=\"{{ option.c8y_Software.url }}\">\n {{ option.c8y_Software.url }}\n </span>\n </ng-template>\n </p>\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: [] } }); class ConfirmSoftwareSelectionStepComponent { ngOnChanges(changes) { if (changes.selectedItems) { const deviceTypes = this.deviceTypes; this.title = deviceTypes && deviceTypes.length ? deviceTypes.join(', ') : gettext('Undefined`device type`'); } } get selectedToInstall() { return this.selectedItems.filter(software => software.action === 'install'); } get selectedToDelete() { return this.selectedItems.filter(software => software.action === 'delete'); } get deviceTypes() { return uniq(this.selectedItems .filter(val => has(val, ['software', 'c8y_Filter', 'type'])) .map(val => val.software.c8y_Filter.type) .filter(val => !!val)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfirmSoftwareSelectionStepComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ConfirmSoftwareSelectionStepComponent, isStandalone: false, selector: "c8y-confirm-software-selection-step", inputs: { selectedItems: "selectedItems" }, usesOnChanges: true, ngImport: i0, template: "<c8y-preview-selection-frame [header]=\"'Confirm selection' | translate\">\n <ng-container *previewBlock=\"'Device type' | translate\">\n <ng-container *ngIf=\"deviceTypes.length > 0; else noType\">\n <span *ngFor=\"let deviceType of deviceTypes; let last = last\"\n >{{ deviceType }}{{ last ? '' : ', ' }}</span\n >\n </ng-container>\n <ng-template #noType>\n <em class=\"text-muted\" translate>Undefined`device type`</em>\n </ng-template>\n </ng-container>\n <c8y-list-group\n *previewBlock=\"'Installations/updates`software`' | translate; if: !!selectedToInstall.length\"\n >\n <c8y-li *ngFor=\"let selectedItem of selectedToInstall\">\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-10\">\n <div class=\"col-6 text-truncate\" title=\"{{ selectedItem.software.name }}\">\n {{ selectedItem.software.name }}\n </div>\n <div class=\"col-6 text-right\" *ngIf=\"!!selectedItem?.version?.c8y_Software?.version\">\n <span class=\"text-label-small m-r-4\" translate> Version </span>\n <span>\n {{ selectedItem.version.c8y_Software.version }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n <c8y-list-group *previewBlock=\"'Removals`software`' | translate; if: !!selectedToDelete.length\">\n <c8y-li *ngFor=\"let selectedItem of selectedToDelete\">\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-10\">\n <div class=\"col-6\">\n {{ selectedItem.software.name }}\n </div>\n <div class=\"col-6 text-right\">\n <span class=\"text-label-small m-r-8\" translate> Version </span>\n <span>\n {{ selectedItem.version.c8y_Software.version }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-preview-selection-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: "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$1.PreviewSelectionFrameComponent, selector: "c8y-preview-selection-frame", inputs: ["header", "name", "description", "type"] }, { kind: "directive", type: i3$1.PreviewBlockDirective, selector: "[previewBlock]", inputs: ["previewBlock", "previewBlockIf"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConfirmSoftwareSelectionStepComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-confirm-software-selection-step', standalone: false, template: "<c8y-preview-selection-frame [header]=\"'Confirm selection' | translate\">\n <ng-container *previewBlock=\"'Device type' | translate\">\n <ng-container *ngIf=\"deviceTypes.length > 0; else noType\">\n <span *ngFor=\"let deviceType of deviceTypes; let last = last\"\n >{{ deviceType }}{{ last ? '' : ', ' }}</span\n >\n </ng-container>\n <ng-template #noType>\n <em class=\"text-muted\" translate>Undefined`device type`</em>\n </ng-template>\n </ng-container>\n <c8y-list-group\n *previewBlock=\"'Installations/updates`software`' | translate; if: !!selectedToInstall.length\"\n >\n <c8y-li *ngFor=\"let selectedItem of selectedToInstall\">\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-10\">\n <div class=\"col-6 text-truncate\" title=\"{{ selectedItem.software.name }}\">\n {{ selectedItem.software.name }}\n </div>\n <div class=\"col-6 text-right\" *ngIf=\"!!selectedItem?.version?.c8y_Software?.version\">\n <span class=\"text-label-small m-r-4\" translate> Version </span>\n <span>\n {{ selectedItem.version.c8y_Software.version }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n <c8y-list-group *previewBlock=\"'Removals`software`' | translate; if: !!selectedToDelete.length\">\n <c8y-li *ngFor=\"let selectedItem of selectedToDelete\">\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-10\">\n <div class=\"col-6\">\n {{ selectedItem.software.name }}\n </div>\n <div class=\"col-6 text-right\">\n <span class=\"text-label-small m-r-8\" translate> Version </span>\n <span>\n {{ selectedItem.version.c8y_Software.version }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-preview-selection-frame>\n" }] }], propDecorators: { selectedItems: [{ type: Input }] } }); class StepperBulkTypeSoftwareComponent extends BaseStepperComponent { constructor(modal, translate) { super(); this.modal = modal; this.translate = translate; this.type = BulkOperationType.SOFTWARE; this.descriptionTemplateSingle = gettext('Update software to: {{ name }} (version {{ version }})'); this.descriptionTemplateOneOther = gettext('Update software to: {{ name }} (version {{ version }}) and one other'); this.descriptionTemplateMultiple = gettext('Update software to: {{ name }} (version {{ version }}) and {{ count }} others'); this.selectedSoftware = []; } onSoftwareSelected(selectedItem) { this.selectedSoftware = this.selectedSoftware.filter(item => item.software.id !== selectedItem.software.id); this.selectedSoftware.push(selectedItem); } async confirmSoftwareSelection($event) { const deviceTypes = this.getUniqueDeviceTypes(); this.deviceTypes = deviceTypes; if (deviceTypes.length > 1) { try { await this.modal.confirm(gettext('Selected software for various device types'), gettext('Operation may fail due to unsupported software. Do you want to proceed?'), Status.WARNING, { ok: gettext('Confirm'), cancel: gettext('Cancel') }); $event.stepper.next(); } catch (ex) { this.selectedSoftware = []; this.selectSoftware.resetSelection(); } } else { $event.stepper.next(); } } retrieveOperationPrototype() { const softwareList = this.selectedSoftware.map(item => ({ name: item.software.name, version: item.version.c8y_Software.version, url: item.version.c8y_Software.url, action: item.action })); const interpolationParams = { name: softwareList[0].name, version: softwareList[0].version, count: softwareList.length - 1 }; let description; switch (softwareList.length) { case 1: description = this.translate.instant(this.descriptionTemplateSingle, interpolationParams); break; case 2: description = this.translate.instant(this.descriptionTemplateOneOther, interpolationParams); break; default: description = this.translate.instant(this.descriptionTemplateMultiple, interpolationParams); } return { name: gettext('Software update'), prototype: { description, c8y_SoftwareUpdate: softwareList } }; } getUniqueDeviceTypes() { return uniq(this.selectedSoftware .map(item => item.software.c8y_Filter && item.software.c8y_Filter.type) .filter(type => !!type)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareComponent, deps: [{ token: i3.ModalService }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: StepperBulkTypeSoftwareComponent, isStandalone: false, selector: "c8y-stepper-bulk-type-software", viewQueries: [{ propertyName: "selectSoftware", first: true, predicate: SelectSoftwareStepComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<c8y-bulk-operation-stepper [type]=\"type\">\n <ng-container\n *customStep=\"\n 'Select software' | translate;\n completed: !!selectedSoftware.length;\n buttonsDisabled: !selectedSoftware.length;\n onNext: confirmSoftwareSelection.bind(this)\n \"\n >\n <c8y-select-software-step\n (software)=\"onSoftwareSelected($event)\"\n class=\"d-contents\"\n ></c8y-select-software-step>\n </ng-container>\n <ng-container *customStep=\"'Confirm selected software' | translate\">\n <c8y-confirm-software-selection-step\n class=\"d-contents\"\n [selectedItems]=\"selectedSoftware\"\n ></c8y-confirm-software-selection-step>\n </ng-container>\n</c8y-bulk-operation-stepper>\n", dependencies: [{ kind: "component", type: i3$2.BulkOperationStepper, selector: "c8y-bulk-operation-stepper", inputs: ["type"], outputs: ["selectionChange"] }, { kind: "directive", type: i3$2.CustomStep, selector: "[customStep]", inputs: ["customStep", "customStepCompleted", "customStepButtonsDisabled", "customStepOnNext"] }, { kind: "component", type: ConfirmSoftwareSelectionStepComponent, selector: "c8y-confirm-software-selection-step", inputs: ["selectedItems"] }, { kind: "component", type: SelectSoftwareStepComponent, selector: "c8y-select-software-step", outputs: ["software"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-stepper-bulk-type-software', standalone: false, template: "<c8y-bulk-operation-stepper [type]=\"type\">\n <ng-container\n *customStep=\"\n 'Select software' | translate;\n completed: !!selectedSoftware.length;\n buttonsDisabled: !selectedSoftware.length;\n onNext: confirmSoftwareSelection.bind(this)\n \"\n >\n <c8y-select-software-step\n (software)=\"onSoftwareSelected($event)\"\n class=\"d-contents\"\n ></c8y-select-software-step>\n </ng-container>\n <ng-container *customStep=\"'Confirm selected software' | translate\">\n <c8y-confirm-software-selection-step\n class=\"d-contents\"\n [selectedItems]=\"selectedSoftware\"\n ></c8y-confirm-software-selection-step>\n </ng-container>\n</c8y-bulk-operation-stepper>\n" }] }], ctorParameters: () => [{ type: i3.ModalService }, { type: i2.TranslateService }], propDecorators: { selectSoftware: [{ type: ViewChild, args: [SelectSoftwareStepComponent, { static: false }] }] } }); /** Module for the 'Software update' operation type stepper */ class StepperBulkTypeSoftwareModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareModule, declarations: [StepperBulkTypeSoftwareComponent, ConfirmSoftwareSelectionStepComponent, SelectSoftwareStepComponent], imports: [CoreModule, FormsModule, ReactiveFormsModule, BulkOperationStepperModule, SharedRepositoryModule, StepperFramesModule], exports: [StepperBulkTypeSoftwareComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareModule, providers: [ hookListBulkType({ type: BulkOperationType.SOFTWARE, c8yIcon: 'c8y-tools', name: gettext('Software update'), path: `${baseUrl}software`, component: StepperBulkTypeSoftwareComponent, fragments: ['c8y_SoftwareList', 'c8y_SoftwareUpdate'], selected: false }) ], imports: [CoreModule, FormsModule, ReactiveFormsModule, BulkOperationStepperModule, SharedRepositoryModule, StepperFramesModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: StepperBulkTypeSoftwareModule, decorators: [{ type: NgModule, args: [{ declarations: [ StepperBulkTypeSoftwareComponent, ConfirmSoftwareSelectionStepComponent, SelectSoftwareStepComponent ], imports: [ CoreModule, FormsModule, ReactiveFormsModule, BulkOperationStepperModule, SharedRepositoryModule, StepperFramesModule ], providers: [ hookListBulkType({ type: BulkOperationType.SOFTWARE, c8yIcon: 'c8y-tools', name: gettext('Software update'), path: `${baseUrl}software`, component: StepperBulkTypeSoftwareComponent, fragments: ['c8y_SoftwareList', 'c8y_SoftwareUpdate'], selected: false }) ], exports: [StepperBulkTypeSoftwareComponent] }] }] }); /** * Generated bundle index. Do not edit. */ export { ConfirmSoftwareSelectionStepComponent, SelectSoftwareStepComponent, StepperBulkTypeSoftwareComponent, StepperBulkTypeSoftwareModule }; //# sourceMappingURL=c8y-ngx-components-operations-stepper-bulk-type-software.mjs.map