UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

139 lines 71 kB
import { __decorate, __metadata } from "tslib"; import { Component, ViewChild } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { InventoryService } from '@c8y/client'; import { AlertService, GainsightService, gettext, memoize, ModalService, Status } from '@c8y/ngx-components'; import { PRODUCT_EXPERIENCE_REPOSITORY_SHARED, RepositoryService, SoftwareTypeComponent } from '@c8y/ngx-components/repository/shared'; import { TranslateService } from '@ngx-translate/core'; import { BsModalService } from 'ngx-bootstrap/modal'; import { BehaviorSubject, from, merge, Subject } from 'rxjs'; import { distinctUntilKeyChanged, map, shareReplay, switchMap, take, takeUntil, tap, withLatestFrom } from 'rxjs/operators'; import { AddSoftwareModalComponent } from './add-software-modal.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@c8y/client"; import * as i3 from "@c8y/ngx-components/repository/shared"; import * as i4 from "@c8y/ngx-components"; import * as i5 from "@ngx-translate/core"; import * as i6 from "ngx-bootstrap/modal"; import * as i7 from "@angular/common"; import * as i8 from "@angular/forms"; import * as i9 from "ngx-bootstrap/popover"; import * as i10 from "ngx-bootstrap/tooltip"; export class SoftwareDetailsComponent { constructor(activatedRoute, inventoryService, repositoryService, alertService, translateService, modalService, bsModalService, gainsightService, router) { this.activatedRoute = activatedRoute; this.inventoryService = inventoryService; this.repositoryService = repositoryService; this.alertService = alertService; this.translateService = translateService; this.modalService = modalService; this.bsModalService = bsModalService; this.gainsightService = gainsightService; this.router = router; this.reload$ = new Subject(); this.reloading$ = new BehaviorSubject(false); this.isSoftwareTypeChanged = false; this.updateSoftware$ = new Subject(); this.softwareUpdated$ = new Subject(); this.baseVersionsUpdated$ = new Subject(); this.software$ = merge(this.activatedRoute.params.pipe(map(params => params.id), switchMap(id => from(this.inventoryService.detail(id).then(result => result.data)))), this.reload$.pipe(tap(() => this.reloading$.next(true)), switchMap(() => this.activatedRoute.params), map(params => params.id), switchMap(id => from(this.inventoryService.detail(id).then(result => result.data))), tap(() => this.reloading$.next(false))), this.softwareUpdated$).pipe(shareReplay(1)); this.baseVersions$ = merge(this.software$.pipe(distinctUntilKeyChanged('id')), this.baseVersionsUpdated$, this.reload$).pipe(switchMap(() => this.software$), switchMap(software => this.repositoryService.listBaseVersions(software)), shareReplay(1)); this.isLegacy$ = this.software$.pipe(map(software => this.repositoryService.isLegacyEntry(software)), shareReplay(1)); this.destroy$ = new Subject(); } ngOnInit() { this.updateSoftware$ .pipe(withLatestFrom(this.software$), switchMap(([softwarePartial, software]) => this.inventoryService.update({ id: software.id, ...softwarePartial })), map(({ data }) => data), tap(software => this.softwareUpdated$.next(software)), tap(() => this.alertService.success(gettext('Saved.'))), tap(() => this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_REPOSITORY_SHARED.SOFTWARE.EVENTS.REPOSITORY, { result: PRODUCT_EXPERIENCE_REPOSITORY_SHARED.SOFTWARE.RESULTS.EDIT_SOFTWARE })), takeUntil(this.destroy$)) .subscribe(); this.software$.subscribe(software => { this.softwareTypeObject = software; }); } getBinaryName$(binaryUrl) { return this.repositoryService.getBinaryName$(binaryUrl); } addBaseVersion() { this.software$ .pipe(take(1), switchMap(software => { const initialState = { model: { selected: software, description: software.description } }; const config = { class: 'modal-sm', ariaDescribedby: 'addSoftwareModalDescription', ariaLabelledBy: 'addSoftwareModalTitle', ignoreBackdropClick: true, keyboard: false, initialState }; const modalRef = this.bsModalService.show(AddSoftwareModalComponent, config); return modalRef.content.saved; })) .subscribe(() => this.baseVersionsUpdated$.next()); } async deleteBaseVersion(baseVersion) { try { const title = gettext('Delete software'); const body = ` ${this.translateService.instant(gettext('You are about to delete software {{ version }}.'), { version: baseVersion.c8y_Software.version })} ${this.translateService.instant(gettext('This operation is irreversible.'))} ${this.translateService.instant(gettext('Do you want to proceed?'))} `; const labels = { ok: gettext('Delete') }; await this.modalService.confirm(title, body, Status.DANGER, labels); const isLastVersion = await this.baseVersions$ .pipe(map(versions => versions?.data?.length === 1), take(1)) .toPromise(); if (isLastVersion) { await this.repositoryService.delete(this.softwareTypeObject); this.router.navigateByUrl('/software'); } else { await this.repositoryService.delete(baseVersion); this.baseVersionsUpdated$.next(); } this.alertService.success(gettext('Software deleted.')); } catch (ex) { // only if not cancel from modal if (ex) { this.alertService.addServerFailure(ex); } } } onSelectSoftwareType(software) { this.isSoftwareTypeChanged = !(this.softwareTypeObject?.softwareType === software?.softwareType); this.softwareTypeObject = software; } ngOnDestroy() { this.destroy$.next(true); this.destroy$.unsubscribe(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareDetailsComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.InventoryService }, { token: i3.RepositoryService }, { token: i4.AlertService }, { token: i5.TranslateService }, { token: i4.ModalService }, { token: i6.BsModalService }, { token: i4.GainsightService }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SoftwareDetailsComponent, selector: "c8y-software-details", viewQueries: [{ propertyName: "softwareType", first: true, predicate: SoftwareTypeComponent, descendants: true, static: true }], ngImport: i0, template: "<c8y-title>\n {{ (software$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n label=\"{{ 'Management' | translate }}\"\n icon=\"c8y-management\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n path=\"#/software\"\n label=\"{{ 'Software repository' | translate }}\"\n icon=\"c8y-tools\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n label=\"{{ (software$ | async)?.name }}\"\n icon=\"c8y-tools\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Add software' | translate }}\"\n (click)=\"addBaseVersion()\"\n *ngIf=\"!(isLegacy$ | async)\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add software' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"reload$.next()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading$ | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <div class=\"card card--fullpage\">\n <div class=\"card-block bg-level-1 flex-no-shrink p-t-24 p-b-24 overflow-visible\">\n <div class=\"content-flex-70\">\n <div class=\"text-center\">\n <i class=\"c8y-icon-duocolor icon-48 c8y-icon c8y-icon-tools\"></i>\n <p>\n <small class=\"label label-info\">Software</small>\n </p>\n </div>\n <div class=\"flex-grow col-10\">\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Name' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #nameInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.name\"\n #nameModel=\"ngModel\"\n placeholder=\"{{ 'e.g. My software' | translate }}\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.name?.length + 2 || 31 }\"\n required\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"updateSoftware$.next({ name: nameInput.value }); nameModel.reset()\"\n [disabled]=\"nameInput.value.length === 0\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Description' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #descriptionInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.description\"\n #descriptionModel=\"ngModel\"\n placeholder=\"{{ 'e.g. Cloud connectivity software' | translate }}\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.description?.length + 2 || 31 }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"\n updateSoftware$.next({ description: descriptionInput.value });\n descriptionModel.reset()\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Device type' | translate }}\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.'\n | translate\n }}\"\n triggers=\"focus\"\n container=\"body\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #deviceTypeInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.c8y_Filter?.type\"\n #deviceTypeModel=\"ngModel\"\n placeholder=\"{{ 'e.g.' | translate }} c8y_Linux\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.type?.length + 2 || 31 }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"\n updateSoftware$.next({ c8y_Filter: { type: deviceTypeInput.value } });\n deviceTypeModel.reset()\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Software type' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <c8y-software-type\n [softwareTypeMO]=\"softwareTypeObject\"\n [style]=\"{ 'width.ch': softwareTypeObject?.softwareType?.length + 2 || 31 }\"\n (onSelectSoftware)=\"onSelectSoftwareType($event)\"\n ></c8y-software-type>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n [ngClass]=\"isSoftwareTypeChanged ? '' : 'hidden'\"\n [disabled]=\"softwareTypeObject?.softwareType === ''\"\n (click)=\"\n updateSoftware$.next({ softwareType: softwareTypeObject.softwareType });\n softwareType.resetInput();\n isSoftwareTypeChanged = false\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"inner-scroll\">\n <div class=\"card-header separator-top-bottom sticky-top bg-component\">\n <div\n class=\"card-title\"\n translate\n >\n Versions\n </div>\n </div>\n\n <div class=\"card-block p-t-0 p-b-24\">\n <c8y-ui-empty-state\n *ngIf=\"(baseVersions$ | async)?.data.length === 0\"\n [icon]=\"'c8y-tools'\"\n [title]=\"'No versions to display.' | translate\"\n [subtitle]=\"'Add a new version by clicking below.' | translate\"\n >\n <p>\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Add software' | translate }}\"\n (click)=\"addBaseVersion()\"\n >\n {{ 'Add software' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n\n <c8y-list-group *ngIf=\"(baseVersions$ | async)?.data.length > 0\">\n <c8y-li\n *c8yFor=\"let baseVersion of baseVersions$ | async; let i = index; loadMore: 'auto'\"\n >\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-50\">\n <div class=\"col-4\">\n <p\n class=\"text-truncate-wrap\"\n title=\"{{ baseVersion.c8y_Software.version }}\"\n >\n {{ baseVersion.c8y_Software.version }}\n </p>\n </div>\n <div class=\"col-5\">\n <p class=\"text-truncate-wrap\">\n <span\n class=\"text-label-small m-r-8\"\n translate\n >\n File\n </span>\n <span title=\" {{ getBinaryName$(baseVersion.c8y_Software.url) | async }}\">\n <c8y-file-download\n url=\"{{ baseVersion.c8y_Software.url }}\"\n ></c8y-file-download>\n </span>\n </p>\n </div>\n <div class=\"col-2 d-flex a-i-start\">\n <span\n *ngIf=\"isLegacy$ | async\"\n class=\"label label-warning m-l-auto-sm\"\n >\n {{ 'Legacy' | translate }}\n </span>\n\n <div\n class=\"fit-h-20\"\n *ngIf=\"!(isLegacy$ | async)\"\n >\n <button\n class=\"btn btn-danger btn-xs visible-xs m-l-auto m-r-8 m-t-8\"\n type=\"button\"\n title=\"{{ 'Delete' | translate }}\"\n (click)=\"deleteBaseVersion(baseVersion)\"\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n </div>\n </div>\n <div\n *ngIf=\"!(isLegacy$ | async)\"\n class=\"m-l-auto fit-h-20 hidden-xs\"\n >\n <button\n class=\"btn btn-dot text-danger showOnHover\"\n type=\"button\"\n data-cy=\"software-details-component--Delete-button\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n [delay]=\"500\"\n (click)=\"deleteBaseVersion(baseVersion)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i7.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i4.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i4.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i4.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i4.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i4.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.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: i4.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i4.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: i4.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i4.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i4.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i4.ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "directive", type: i9.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: i10.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: i3.FileDownloadComponent, selector: "c8y-file-download", inputs: ["url"] }, { kind: "component", type: i3.SoftwareTypeComponent, selector: "c8y-software-type", inputs: ["softwareTypeMO", "disabled", "style", "required", "placeholder", "emitResultsOnly", "showBtnInNotFoundMessage", "allowFreeEntries", "showClearSelectionOption", "clearSelectionOptionLabel", "presetSoftwareTypes"], outputs: ["onSelectSoftware"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }] }); } } __decorate([ memoize(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", void 0) ], SoftwareDetailsComponent.prototype, "getBinaryName$", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareDetailsComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-software-details', template: "<c8y-title>\n {{ (software$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n label=\"{{ 'Management' | translate }}\"\n icon=\"c8y-management\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n path=\"#/software\"\n label=\"{{ 'Software repository' | translate }}\"\n icon=\"c8y-tools\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n label=\"{{ (software$ | async)?.name }}\"\n icon=\"c8y-tools\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Add software' | translate }}\"\n (click)=\"addBaseVersion()\"\n *ngIf=\"!(isLegacy$ | async)\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add software' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"reload$.next()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading$ | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"row\">\n <div class=\"col-lg-12 col-lg-max\">\n <div class=\"card card--fullpage\">\n <div class=\"card-block bg-level-1 flex-no-shrink p-t-24 p-b-24 overflow-visible\">\n <div class=\"content-flex-70\">\n <div class=\"text-center\">\n <i class=\"c8y-icon-duocolor icon-48 c8y-icon c8y-icon-tools\"></i>\n <p>\n <small class=\"label label-info\">Software</small>\n </p>\n </div>\n <div class=\"flex-grow col-10\">\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Name' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #nameInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.name\"\n #nameModel=\"ngModel\"\n placeholder=\"{{ 'e.g. My software' | translate }}\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.name?.length + 2 || 31 }\"\n required\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"updateSoftware$.next({ name: nameInput.value }); nameModel.reset()\"\n [disabled]=\"nameInput.value.length === 0\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Description' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #descriptionInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.description\"\n #descriptionModel=\"ngModel\"\n placeholder=\"{{ 'e.g. Cloud connectivity software' | translate }}\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.description?.length + 2 || 31 }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"\n updateSoftware$.next({ description: descriptionInput.value });\n descriptionModel.reset()\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Device type' | translate }}\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.'\n | translate\n }}\"\n triggers=\"focus\"\n container=\"body\"\n >\n <i c8yIcon=\"question-circle-o\"></i>\n </button>\n </label>\n <div class=\"input-group input-group-editable\">\n <input\n #deviceTypeInput\n type=\"text\"\n class=\"form-control\"\n [ngModel]=\"(software$ | async)?.c8y_Filter?.type\"\n #deviceTypeModel=\"ngModel\"\n placeholder=\"{{ 'e.g.' | translate }} c8y_Linux\"\n [ngStyle]=\"{ 'width.ch': (software$ | async)?.type?.length + 2 || 31 }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n (click)=\"\n updateSoftware$.next({ c8y_Filter: { type: deviceTypeInput.value } });\n deviceTypeModel.reset()\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label class=\"control-label\">\n {{ 'Software type' | translate }}\n </label>\n <div class=\"input-group input-group-editable\">\n <c8y-software-type\n [softwareTypeMO]=\"softwareTypeObject\"\n [style]=\"{ 'width.ch': softwareTypeObject?.softwareType?.length + 2 || 31 }\"\n (onSelectSoftware)=\"onSelectSoftwareType($event)\"\n ></c8y-software-type>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Save' | translate }}\"\n [ngClass]=\"isSoftwareTypeChanged ? '' : 'hidden'\"\n [disabled]=\"softwareTypeObject?.softwareType === ''\"\n (click)=\"\n updateSoftware$.next({ softwareType: softwareTypeObject.softwareType });\n softwareType.resetInput();\n isSoftwareTypeChanged = false\n \"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"inner-scroll\">\n <div class=\"card-header separator-top-bottom sticky-top bg-component\">\n <div\n class=\"card-title\"\n translate\n >\n Versions\n </div>\n </div>\n\n <div class=\"card-block p-t-0 p-b-24\">\n <c8y-ui-empty-state\n *ngIf=\"(baseVersions$ | async)?.data.length === 0\"\n [icon]=\"'c8y-tools'\"\n [title]=\"'No versions to display.' | translate\"\n [subtitle]=\"'Add a new version by clicking below.' | translate\"\n >\n <p>\n <button\n class=\"btn btn-primary\"\n type=\"button\"\n title=\"{{ 'Add software' | translate }}\"\n (click)=\"addBaseVersion()\"\n >\n {{ 'Add software' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n\n <c8y-list-group *ngIf=\"(baseVersions$ | async)?.data.length > 0\">\n <c8y-li\n *c8yFor=\"let baseVersion of baseVersions$ | async; let i = index; loadMore: 'auto'\"\n >\n <c8y-li-icon>\n <i c8yIcon=\"c8y-tools\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-50\">\n <div class=\"col-4\">\n <p\n class=\"text-truncate-wrap\"\n title=\"{{ baseVersion.c8y_Software.version }}\"\n >\n {{ baseVersion.c8y_Software.version }}\n </p>\n </div>\n <div class=\"col-5\">\n <p class=\"text-truncate-wrap\">\n <span\n class=\"text-label-small m-r-8\"\n translate\n >\n File\n </span>\n <span title=\" {{ getBinaryName$(baseVersion.c8y_Software.url) | async }}\">\n <c8y-file-download\n url=\"{{ baseVersion.c8y_Software.url }}\"\n ></c8y-file-download>\n </span>\n </p>\n </div>\n <div class=\"col-2 d-flex a-i-start\">\n <span\n *ngIf=\"isLegacy$ | async\"\n class=\"label label-warning m-l-auto-sm\"\n >\n {{ 'Legacy' | translate }}\n </span>\n\n <div\n class=\"fit-h-20\"\n *ngIf=\"!(isLegacy$ | async)\"\n >\n <button\n class=\"btn btn-danger btn-xs visible-xs m-l-auto m-r-8 m-t-8\"\n type=\"button\"\n title=\"{{ 'Delete' | translate }}\"\n (click)=\"deleteBaseVersion(baseVersion)\"\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Delete' | translate }}\n </button>\n </div>\n </div>\n <div\n *ngIf=\"!(isLegacy$ | async)\"\n class=\"m-l-auto fit-h-20 hidden-xs\"\n >\n <button\n class=\"btn btn-dot text-danger showOnHover\"\n type=\"button\"\n data-cy=\"software-details-component--Delete-button\"\n [attr.aria-label]=\"'Delete' | translate\"\n tooltip=\"{{ 'Delete' | translate }}\"\n [delay]=\"500\"\n (click)=\"deleteBaseVersion(baseVersion)\"\n >\n <i c8yIcon=\"delete\"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.InventoryService }, { type: i3.RepositoryService }, { type: i4.AlertService }, { type: i5.TranslateService }, { type: i4.ModalService }, { type: i6.BsModalService }, { type: i4.GainsightService }, { type: i1.Router }], propDecorators: { softwareType: [{ type: ViewChild, args: [SoftwareTypeComponent, { static: true }] }], getBinaryName$: [] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29mdHdhcmUtZGV0YWlscy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2xpc3Qvc29mdHdhcmUtZGV0YWlscy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2xpc3Qvc29mdHdhcmUtZGV0YWlscy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFrQixnQkFBZ0IsRUFBZSxNQUFNLGFBQWEsQ0FBQztBQUM1RSxPQUFPLEVBQ0wsWUFBWSxFQUNaLGdCQUFnQixFQUNoQixPQUFPLEVBQ1AsT0FBTyxFQUNQLFlBQVksRUFDWixNQUFNLEVBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsb0NBQW9DLEVBQ3BDLGlCQUFpQixFQUNqQixxQkFBcUIsRUFDdEIsTUFBTSx1Q0FBdUMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFnQixNQUFNLHFCQUFxQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekUsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixHQUFHLEVBQ0gsV0FBVyxFQUNYLFNBQVMsRUFDVCxJQUFJLEVBQ0osU0FBUyxFQUNULEdBQUcsRUFDSCxjQUFjLEVBQ2YsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7Ozs7Ozs7Ozs7O0FB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QUFtQixDQUFDLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztZQUNaLGdDQUFnQztZQUNoQyxJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUNQLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsb0JBQW9CLENBQUMsUUFBUTtRQUMzQixJQUFJLENBQUMscUJBQXFCLEdBQUcsQ0FBQyxDQUM1QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsWUFBWSxLQUFLLFFBQVEsRUFBRSxZQUFZLENBQ2pFLENBQUM7UUFDRixJQUFJLENBQUMsa0JBQWtCLEdBQUcsUUFBUSxDQUFDO0lBQ3JDLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM5QixDQUFDOytHQXJLVSx3QkFBd0I7bUdBQXhCLHdCQUF3QiwwR0FDeEIscUJBQXFCLDhEQ3BDbEMsK2xZQXlUQTs7QUQ5TEU7SUFEQyxPQUFPLEVBQUU7Ozs7OERBR1Q7NEZBMUZVLHdCQUF3QjtrQkFKcEMsU0FBUzsrQkFDRSxzQkFBc0I7d1RBS2hDLFlBQVk7c0JBRFgsU0FBUzt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBdUZsRCxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkRlc3Ryb3ksIE9uSW5pdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IElNYW5hZ2VkT2JqZWN0LCBJbnZlbnRvcnlTZXJ2aWNlLCBJUmVzdWx0TGlzdCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7XG4gIEFsZXJ0U2VydmljZSxcbiAgR2FpbnNpZ2h0U2VydmljZSxcbiAgZ2V0dGV4dCxcbiAgbWVtb2l6ZSxcbiAgTW9kYWxTZXJ2aWNlLFxuICBTdGF0dXNcbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQge1xuICBQUk9EVUNUX0VYUEVSSUVOQ0VfUkVQT1NJVE9SWV9TSEFSRUQsXG4gIFJlcG9zaXRvcnlTZXJ2aWNlLFxuICBTb2Z0d2FyZVR5cGVDb21wb25lbnRcbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9yZXBvc2l0b3J5L3NoYXJlZCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBCc01vZGFsU2VydmljZSwgTW9kYWxPcHRpb25zIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGZyb20sIG1lcmdlLCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBkaXN0aW5jdFVudGlsS2V5Q2hhbmdlZCxcbiAgbWFwLFxuICBzaGFyZVJlcGxheSxcbiAgc3dpdGNoTWFwLFxuICB0YWtlLFxuICB0YWtlVW50aWwsXG4gIHRhcCxcbiAgd2l0aExhdGVzdEZyb21cbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQWRkU29mdHdhcmVNb2RhbENvbXBvbmVudCB9IGZyb20gJy4vYWRkLXNvZnR3YXJlLW1vZGFsLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1zb2Z0d2FyZS1kZXRhaWxzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NvZnR3YXJlLWRldGFpbHMuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIFNvZnR3YXJlRGV0YWlsc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQFZpZXdDaGlsZChTb2Z0d2FyZVR5cGVDb21wb25lbnQsIHsgc3RhdGljOiB0cnVlIH0pXG4gIHNvZnR3YXJlVHlwZTogU29mdHdhcmVUeXBlQ29tcG9uZW50O1xuXG4gIHJlbG9hZCQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuICByZWxvYWRpbmckOiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgc29mdHdhcmVUeXBlT2JqZWN0OiBJTWFuYWdlZE9iamVjdDtcbiAgaXNTb2Z0d2FyZVR5cGVDaGFuZ2VkID0gZmFsc2U7XG5cbiAgdXBkYXRlU29mdHdhcmUkOiBTdWJqZWN0PFBhcnRpYWw8SU1hbmFnZWRPYmplY3Q+PiA9IG5ldyBTdWJqZWN0KCk7XG4gIHNvZnR3YXJlVXBkYXRlZCQ6IFN1YmplY3Q8SU1hbmFnZWRPYmplY3Q+ID0gbmV3IFN1YmplY3QoKTtcbiAgYmFzZVZlcnNpb25zVXBkYXRlZCQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuXG4gIHNvZnR3YXJlJDogT2JzZXJ2YWJsZTxJTWFuYWdlZE9iamVjdD4gPSBtZXJnZShcbiAgICB0aGlzLmFjdGl2YXRlZFJvdXRlLnBhcmFtcy5waXBlKFxuICAgICAgbWFwKHBhcmFtcyA9PiBwYXJhbXMuaWQpLFxuICAgICAgc3dpdGNoTWFwKGlkID0+IGZyb20odGhpcy5pbnZlbnRvcnlTZXJ2aWNlLmRldGFpbChpZCkudGhlbihyZXN1bHQgPT4gcmVzdWx0LmRhdGEpKSlcbiAgICApLFxuICAgIHRoaXMucmVsb2FkJC5waXBlKFxuICAgICAgdGFwKCgpID0+IHRoaXMucmVsb2FkaW5nJC5uZXh0KHRydWUpKSxcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLmFjdGl2YXRlZFJvdXRlLnBhcmFtcyksXG4gICAgICBtYXAocGFyYW1zID0+IHBhcmFtcy5pZCksXG4gICAgICBzd2l0Y2hNYXAoaWQgPT4gZnJvbSh0aGlzLmludmVudG9yeVNlcnZpY2UuZGV0YWlsKGlkKS50aGVuKHJlc3VsdCA9PiByZXN1bHQuZGF0YSkpKSxcbiAgICAgIHRhcCgoKSA9PiB0aGlzLnJlbG9hZGluZyQubmV4dChmYWxzZSkpXG4gICAgKSxcbiAgICB0aGlzLnNvZnR3YXJlVXBkYXRlZCRcbiAgKS5waXBlKHNoYXJlUmVwbGF5KDEpKTtcblxuICBiYXNlVmVyc2lvbnMkOiBPYnNlcnZhYmxlPElSZXN1bHRMaXN0PElNYW5hZ2VkT2JqZWN0Pj4gPSBtZXJnZShcbiAgICB0aGlzLnNvZnR3YXJlJC5waXBlKGRpc3RpbmN0VW50aWxLZXlDaGFuZ2VkKCdpZCcpKSxcbiAgICB0aGlzLmJhc2VWZXJzaW9uc1VwZGF0ZWQkLFxuICAgIHRoaXMucmVsb2FkJFxuICApLnBpcGUoXG4gICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuc29mdHdhcmUkKSxcbiAgICBzd2l0Y2hNYXAoc29mdHdhcmUgPT4gdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0QmFzZVZlcnNpb25zKHNvZnR3YXJlKSksXG4gICAgc2hhcmVSZXBsYXkoMSlcbiAgKTtcblxuICBpc0xlZ2FjeSQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLnNvZnR3YXJlJC5waXBlKFxuICAgIG1hcChzb2Z0d2FyZSA9PiB0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlLmlzTGVnYWN5RW50cnkoc29mdHdhcmUpKSxcbiAgICBzaGFyZVJlcGxheSgxKVxuICApO1xuXG4gIGRlc3Ryb3kkOiBTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIGludmVudG9yeVNlcnZpY2U6IEludmVudG9yeVNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZXBvc2l0b3J5U2VydmljZTogUmVwb3NpdG9yeVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhbGVydFNlcnZpY2U6IEFsZXJ0U2VydmljZSxcbiAgICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBtb2RhbFNlcnZpY2U6IE1vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIGJzTW9kYWxTZXJ2aWNlOiBCc01vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIGdhaW5zaWdodFNlcnZpY2U6IEdhaW5zaWdodFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlclxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy51cGRhdGVTb2Z0d2FyZSRcbiAgICAgIC5waXBlKFxuICAgICAgICB3aXRoTGF0ZXN0RnJvbSh0aGlzLnNvZnR3YXJlJCksXG4gICAg