UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

321 lines 69.3 kB
import { __decorate, __metadata } from "tslib"; import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core'; import { TenantUiService, gettext, memoize, GainsightService } from '@c8y/ngx-components'; import { FormGroup } from '@angular/forms'; import { from, Observable, Subject, defer, BehaviorSubject } from 'rxjs'; import { filter, shareReplay, switchMap, takeUntil, tap } from 'rxjs/operators'; import { DeviceRegistrationBulkService, FeatureService, InventoryService, TenantService } from '@c8y/client'; import { RegisterDeviceService } from '../register-device.service'; import { BsModalRef } from 'ngx-bootstrap/modal'; import { ESTCsvHeaders } from '../bulk/bulk-device-registration-modal.component'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components"; import * as i2 from "@c8y/client"; import * as i3 from "../register-device.service"; import * as i4 from "ngx-bootstrap/modal"; import * as i5 from "ngx-bootstrap/popover"; import * as i6 from "@angular/common"; import * as i7 from "@angular/forms"; import * as i8 from "@angular/cdk/stepper"; import * as i9 from "@ngx-formly/core"; export class GeneralDeviceRegistrationComponent { constructor(tenantUIService, tenantService, registerDeviceService, inventoryService, cd, bsModalRef, gainsightService, deviceRegistrationService, featureService) { this.tenantUIService = tenantUIService; this.tenantService = tenantService; this.registerDeviceService = registerDeviceService; this.inventoryService = inventoryService; this.cd = cd; this.bsModalRef = bsModalRef; this.gainsightService = gainsightService; this.deviceRegistrationService = deviceRegistrationService; this.featureService = featureService; this.MANAGEMENT = 'management'; this.FILTER = { withTotalPages: true, pageSize: 25 }; this.useEST$ = new BehaviorSubject(false); this.certificateAuthorityFeatureEnabled = this.featureService .detail('certificate-authority') .then(({ data }) => data.active); this.form = new FormGroup({}); this.model = { devicesToCreate: [{}] }; this.options = { formState: { canLoadTenants: true, useEST: this.useEST$.getValue() } }; this.PRODUCT_EXPERIENCE = { EVENT: 'deviceRegistration', COMPONENT: 'single-general-registration', RESULT: { SUCCESS: 'registrationSuccess', FAILURE: 'registrationFailure' } }; this.success = []; this.failed = []; this.fields = [ { type: 'array', key: 'devicesToCreate', props: { addText: gettext('Add device'), addTextDataCy: 'add-device' }, fieldArray: { fieldGroup: [ { key: 'id', type: 'string', focus: true, props: { placeholder: '0123ab32fcd', label: gettext('Device ID'), required: true }, validators: { unique: { expression: (control) => { const found = control.root.get('devicesToCreate').controls .map(el => el.controls.id) .find(el => el !== control && el.value === control.value); return !found; }, message: () => gettext('Device ID duplicates are not allowed') } } }, { key: 'tenant', type: 'typeahead', expressions: { hide: field => { const formState = field.options?.formState; if (!formState?.canLoadTenants) { field.formControl.setValue(null); } return !formState?.canLoadTenants || false; } }, defaultValue: { id: this.MANAGEMENT }, props: { label: gettext('Add to tenant'), required: true, c8yForOptions: this.canLoadTenants$().pipe(filter(canLoad => canLoad), switchMap(() => this.getTenants$())), container: 'body', displayProperty: 'id', valueProperties: ['id'] }, hooks: { onInit: _field => this.canLoadTenants$().pipe(tap(canLoad => { this.options.formState.canLoadTenants = canLoad; this.cd.detectChanges(); })) } }, { key: 'group', type: 'typeahead', expressions: { 'props.disabled': (field) => { const formState = field.options?.formState; const model = field.model; if (formState?.canLoadTenants) { if (model?.tenant?.id !== this.MANAGEMENT) { field.formControl.setValue(null); } return !(model?.tenant?.id === this.MANAGEMENT); } delete field?.props?.description; return false; } }, props: { disabled: false, label: gettext('Add to group'), description: gettext('You can add device to specific group for management tenant only.'), container: 'body', displayProperty: 'name', valueProperties: ['id'], c8yForOptions: this.getGroups$() }, hooks: { onInit: _field => this.canLoadTenants$().pipe(tap(canLoad => { this.options.formState.canLoadTenants = canLoad; this.cd.detectChanges(); })) } }, { key: 'oneTimePassword', type: 'string', expressions: { hide: field => !field.options?.formState?.useEST }, props: { placeholder: 'TruDN3H45L0', label: gettext('One-time password'), required: true }, hooks: { onInit: _field => this.useEST$.pipe(tap(useEST => { this.options.formState.useEST = useEST; this.cd.detectChanges(); })) } } ] } } ]; this.result = new Promise((resolve, reject) => { this.onSuccessfulClosing = resolve; this.onCancel = reject; }); this.destroy$ = new Subject(); this.lastCreatedDevices = []; this.isLoading$ = this.registerDeviceService.loading$; } ngAfterViewInit() { this.cd.detectChanges(); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } registerDevice(eventObject) { !this.useEST$.getValue() ? this.create(eventObject) : this.registerByEst(eventObject); } fixErrors(event, failedRequests) { if (failedRequests && failedRequests.length > 0) { this.options.resetModel({ devicesToCreate: [ ...this.lastCreatedDevices.filter(el => failedRequests.map(data => data.id).includes(el.id)) ] }); this.cd.detectChanges(); } event?.stepper.previous(); } close() { this.bsModalRef.hide(); this.onSuccessfulClosing(); } cancel() { this.bsModalRef.hide(); this.onCancel(); } create(eventObject) { if (this.model?.devicesToCreate?.length > 0) { this.lastCreatedDevices = [...this.model.devicesToCreate]; const dataToSend = this.model.devicesToCreate.map((el) => { const { id, tenant, group } = el; let data = { id }; if (tenant?.id) { data = { ...data, tenantId: tenant.id }; } if (group?.id) { data = { ...data, groupId: group.id }; } return data; }); this.registerDeviceService .createMultiple(dataToSend) .pipe(takeUntil(this.destroy$)) .subscribe(requests => { this.success = requests.success ?? []; if (this.success.length > 0) { this.gainsightService.triggerEvent(this.PRODUCT_EXPERIENCE.EVENT, { result: this.PRODUCT_EXPERIENCE.RESULT.SUCCESS, component: this.PRODUCT_EXPERIENCE.COMPONENT }); } this.failed = requests.failed ?? []; if (this.failed.length > 0) { this.gainsightService.triggerEvent(this.PRODUCT_EXPERIENCE.EVENT, { result: this.PRODUCT_EXPERIENCE.RESULT.FAILURE, component: this.PRODUCT_EXPERIENCE.COMPONENT }); } if (eventObject) { eventObject.stepper.next(); } }); } } registerByEst(eventObject) { this.lastCreatedDevices = [...this.model.devicesToCreate]; this.deviceRegistrationService .create(this.convertObjectToCSVFile(this.model.devicesToCreate)) .then(({ res, data }) => { if (res.status < 400) { this.failed = data.failedCreationList.map(value => { return { id: value.deviceId, message: value.failureReason }; }); const failedIds = new Set(this.failed.map(item => item.id)); this.success = this.model.devicesToCreate.filter(item => !failedIds.has(item.id)); } eventObject.stepper.next(); }) .catch(() => { eventObject.stepper.next(); }); } convertObjectToCSVFile(data) { const fullCsvHeaders = ESTCsvHeaders; const csvHeaders = fullCsvHeaders.join(';') + '\n'; const dataToSend = data.map(el => { return { ID: el.id, AUTH_TYPE: 'CERTIFICATES', ENROLLMENT_OTP: el.oneTimePassword, PATH: el.group?.id || '', TENANT: el.tenant?.id || '' }; }); const csvRows = dataToSend .map(row => fullCsvHeaders.map(header => row[header] ?? '').join(';')) .join('\n'); const csvContent = csvHeaders + csvRows; const blob = new Blob([csvContent], { type: 'text/csv' }); return new File([blob], `ESTRegistrationFile.csv`, { type: 'text/csv' }); } canLoadTenants$() { return defer(() => from(this.tenantUIService.isManagementTenant())).pipe(shareReplay(1)); } getTenants$() { return defer(() => from(this.tenantService.list(this.FILTER))).pipe(shareReplay(1)); } getGroups$() { return defer(() => from(this.inventoryService.listQuery({ __filter: { __has: 'c8y_IsDeviceGroup' }, __orderby: [{ name: 1 }] }, { ...this.FILTER }))).pipe(shareReplay(1)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GeneralDeviceRegistrationComponent, deps: [{ token: i1.TenantUiService }, { token: i2.TenantService }, { token: i3.RegisterDeviceService }, { token: i2.InventoryService }, { token: i0.ChangeDetectorRef }, { token: i4.BsModalRef }, { token: i1.GainsightService }, { token: i2.DeviceRegistrationBulkService }, { token: i2.FeatureService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GeneralDeviceRegistrationComponent, selector: "c8y-general-device-registration", ngImport: i0, template: "<c8y-modal\n [title]=\"'Register devices' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [customFooter]=\"true\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'c8y-device-connect'\"></span>\n </ng-container>\n <c8y-stepper [hideStepProgress]=\"true\" linear c8y-modal-body>\n <cdk-step [stepControl]=\"form\">\n <div class=\"text-center sticky-top bg-component\">\n <p class=\"text-medium text-16 separator-bottom p-16\" translate>Register general devices</p>\n <label\n class=\"c8y-switch m-24 a-i-center\"\n title=\"{{ 'Create device certificates during device registration' | translate }}\"\n for=\"useEST\"\n *ngIf=\"certificateAuthorityFeatureEnabled | async\"\n >\n <input\n type=\"checkbox\"\n name=\"useEST\"\n id=\"useEST\"\n [ngModel]=\"useEST$.getValue()\"\n (ngModelChange)=\"useEST$.next($event)\"\n />\n <span></span>\n <span class=\"control-label\">{{ 'Create device certificates during device registration' | translate }}</span>\n <button\n type=\"button\"\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ 'The device registration process includes creating device certificates, which are issued by the tenant\\'s Certificate Authority (CA).' | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </div>\n <div>\n <formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n class=\"formly-group-array-cols d-block p-l-24 p-b-24 min-height-fit p-r-8\"\n [ngClass]=\"{'p-t-24' : !(certificateAuthorityFeatureEnabled | async)}\"\n ></formly-form>\n </div>\n <c8y-stepper-buttons\n (onNext)=\"registerDevice($event)\"\n (onCancel)=\"cancel()\"\n [showButtons]=\"{ cancel: true, next: true }\"\n [disabled]=\"!form?.valid\"\n [pending]=\"isLoading$ | async\"\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <cdk-step state=\"final\">\n <div class=\"p-24 min-height-fit\">\n <c8y-operation-result\n *ngIf=\"success.length === 1 && failed.length === 0\"\n text=\"{{ 'Device registered' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"success\"\n class=\"lead\"\n ></c8y-operation-result>\n <c8y-operation-result\n *ngIf=\"success.length === 0 && failed.length === 1\"\n text=\"{{ 'Failed to register device' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n\n <ng-container *ngIf=\"success.length > 1 || failed.length > 1\">\n <c8y-operation-result\n *ngIf=\"failed.length === 0\"\n [text]=\"\n '{{ successfulDevicesCount }} devices registered'\n | translate: { successfulDevicesCount: success.length }\n \"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"success\"\n class=\"lead\"\n ></c8y-operation-result>\n <c8y-operation-result\n *ngIf=\"success.length === 0\"\n [text]=\"\n '{{ failedDevicesCount }} devices failed to register'\n | translate: { failedDevicesCount: failed.length }\n \"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n </ng-container>\n\n <div *ngIf=\"success.length > 0 && failed.length > 0\" class=\"p-l-24 p-r-24 text-center\">\n <c8y-operation-result\n text=\"{{ 'Several devices failed to register' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n <p\n ngNonBindable\n translate\n [translateParams]=\"{ count: failed.length, total: failed.length + success.length }\"\n class=\"p-b-16 text-danger\"\n >\n Registration failed for {{ count }} devices out of {{ total }}.\n </p>\n </div>\n\n <div class=\"m-b-8 p-l-24 p-r-24\" *ngIf=\"success.length > 0\" translate>\n Turn on the registered device(s) and wait for connection(s) to be established. Once a\n device is connected, its status will change to \"Pending acceptance\". You will need to\n approve it by clicking on the \"Accept\" button.\n </div>\n\n <c8y-list-group class=\"separator-top m-t-16\">\n <c8y-li *ngFor=\"let fail of failed\">\n <c8y-li-icon class=\"text-danger\" [icon]=\"'ban'\"></c8y-li-icon>\n <p>{{ fail?.id }}</p>\n <small>{{ fail?.message | translate }}</small>\n <c8y-li-collapse>\n <pre><code>{{ fail?.details | json }}</code></pre>\n </c8y-li-collapse>\n </c8y-li>\n\n <c8y-li *ngFor=\"let s of success\">\n <c8y-li-icon class=\"text-success\" [icon]=\"'check-circle'\"></c8y-li-icon>\n {{ s?.id }}\n </c8y-li>\n </c8y-list-group>\n </div>\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n (onCustom)=\"close()\"\n (onBack)=\"fixErrors($event, failed)\"\n [showButtons]=\"{ back: failed.length > 0, custom: true }\"\n [labels]=\"{ back: 'Fix errors', custom: 'Close' }\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n</c8y-modal>\n", dependencies: [{ kind: "directive", type: i5.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: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.OperationResultComponent, selector: "c8y-operation-result", inputs: ["text", "vertical", "size", "type"] }, { kind: "component", type: i1.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "directive", type: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i1.C8yStepper, selector: "c8y-stepper", inputs: ["disableDefaultIcons", "disableProgressButtons", "customClasses", "hideStepProgress", "useStepLabelsAsTitlesOnly"], outputs: ["onStepChange"] }, { kind: "component", type: i8.CdkStep, selector: "cdk-step", inputs: ["stepControl", "label", "errorMessage", "aria-label", "aria-labelledby", "state", "editable", "optional", "completed", "hasError"], outputs: ["interacted"], exportAs: ["cdkStep"] }, { kind: "component", type: i1.C8yStepperButtons, selector: "c8y-stepper-buttons", inputs: ["labels", "pending", "disabled", "showButtons"], outputs: ["onCancel", "onNext", "onBack", "onCustom"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i1.ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: i9.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } __decorate([ memoize(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Observable) ], GeneralDeviceRegistrationComponent.prototype, "canLoadTenants$", null); __decorate([ memoize(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Observable) ], GeneralDeviceRegistrationComponent.prototype, "getTenants$", null); __decorate([ memoize(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Observable) ], GeneralDeviceRegistrationComponent.prototype, "getGroups$", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GeneralDeviceRegistrationComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-general-device-registration', changeDetection: ChangeDetectionStrategy.OnPush, template: "<c8y-modal\n [title]=\"'Register devices' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [customFooter]=\"true\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'c8y-device-connect'\"></span>\n </ng-container>\n <c8y-stepper [hideStepProgress]=\"true\" linear c8y-modal-body>\n <cdk-step [stepControl]=\"form\">\n <div class=\"text-center sticky-top bg-component\">\n <p class=\"text-medium text-16 separator-bottom p-16\" translate>Register general devices</p>\n <label\n class=\"c8y-switch m-24 a-i-center\"\n title=\"{{ 'Create device certificates during device registration' | translate }}\"\n for=\"useEST\"\n *ngIf=\"certificateAuthorityFeatureEnabled | async\"\n >\n <input\n type=\"checkbox\"\n name=\"useEST\"\n id=\"useEST\"\n [ngModel]=\"useEST$.getValue()\"\n (ngModelChange)=\"useEST$.next($event)\"\n />\n <span></span>\n <span class=\"control-label\">{{ 'Create device certificates during device registration' | translate }}</span>\n <button\n type=\"button\"\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ 'The device registration process includes creating device certificates, which are issued by the tenant\\'s Certificate Authority (CA).' | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </div>\n <div>\n <formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n class=\"formly-group-array-cols d-block p-l-24 p-b-24 min-height-fit p-r-8\"\n [ngClass]=\"{'p-t-24' : !(certificateAuthorityFeatureEnabled | async)}\"\n ></formly-form>\n </div>\n <c8y-stepper-buttons\n (onNext)=\"registerDevice($event)\"\n (onCancel)=\"cancel()\"\n [showButtons]=\"{ cancel: true, next: true }\"\n [disabled]=\"!form?.valid\"\n [pending]=\"isLoading$ | async\"\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <cdk-step state=\"final\">\n <div class=\"p-24 min-height-fit\">\n <c8y-operation-result\n *ngIf=\"success.length === 1 && failed.length === 0\"\n text=\"{{ 'Device registered' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"success\"\n class=\"lead\"\n ></c8y-operation-result>\n <c8y-operation-result\n *ngIf=\"success.length === 0 && failed.length === 1\"\n text=\"{{ 'Failed to register device' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n\n <ng-container *ngIf=\"success.length > 1 || failed.length > 1\">\n <c8y-operation-result\n *ngIf=\"failed.length === 0\"\n [text]=\"\n '{{ successfulDevicesCount }} devices registered'\n | translate: { successfulDevicesCount: success.length }\n \"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"success\"\n class=\"lead\"\n ></c8y-operation-result>\n <c8y-operation-result\n *ngIf=\"success.length === 0\"\n [text]=\"\n '{{ failedDevicesCount }} devices failed to register'\n | translate: { failedDevicesCount: failed.length }\n \"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n </ng-container>\n\n <div *ngIf=\"success.length > 0 && failed.length > 0\" class=\"p-l-24 p-r-24 text-center\">\n <c8y-operation-result\n text=\"{{ 'Several devices failed to register' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n type=\"error\"\n class=\"lead\"\n ></c8y-operation-result>\n <p\n ngNonBindable\n translate\n [translateParams]=\"{ count: failed.length, total: failed.length + success.length }\"\n class=\"p-b-16 text-danger\"\n >\n Registration failed for {{ count }} devices out of {{ total }}.\n </p>\n </div>\n\n <div class=\"m-b-8 p-l-24 p-r-24\" *ngIf=\"success.length > 0\" translate>\n Turn on the registered device(s) and wait for connection(s) to be established. Once a\n device is connected, its status will change to \"Pending acceptance\". You will need to\n approve it by clicking on the \"Accept\" button.\n </div>\n\n <c8y-list-group class=\"separator-top m-t-16\">\n <c8y-li *ngFor=\"let fail of failed\">\n <c8y-li-icon class=\"text-danger\" [icon]=\"'ban'\"></c8y-li-icon>\n <p>{{ fail?.id }}</p>\n <small>{{ fail?.message | translate }}</small>\n <c8y-li-collapse>\n <pre><code>{{ fail?.details | json }}</code></pre>\n </c8y-li-collapse>\n </c8y-li>\n\n <c8y-li *ngFor=\"let s of success\">\n <c8y-li-icon class=\"text-success\" [icon]=\"'check-circle'\"></c8y-li-icon>\n {{ s?.id }}\n </c8y-li>\n </c8y-list-group>\n </div>\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n (onCustom)=\"close()\"\n (onBack)=\"fixErrors($event, failed)\"\n [showButtons]=\"{ back: failed.length > 0, custom: true }\"\n [labels]=\"{ back: 'Fix errors', custom: 'Close' }\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n</c8y-modal>\n" }] }], ctorParameters: () => [{ type: i1.TenantUiService }, { type: i2.TenantService }, { type: i3.RegisterDeviceService }, { type: i2.InventoryService }, { type: i0.ChangeDetectorRef }, { type: i4.BsModalRef }, { type: i1.GainsightService }, { type: i2.DeviceRegistrationBulkService }, { type: i2.FeatureService }], propDecorators: { canLoadTenants$: [], getTenants$: [], getGroups$: [] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhbC1kZXZpY2UtcmVnaXN0cmF0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3JlZ2lzdGVyLWRldmljZS9nZW5lcmFsL2dlbmVyYWwtZGV2aWNlLXJlZ2lzdHJhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9yZWdpc3Rlci1kZXZpY2UvZ2VuZXJhbC9nZW5lcmFsLWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFFVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQ0wsZUFBZSxFQUNmLE9BQU8sRUFFUCxPQUFPLEVBQ1AsZ0JBQWdCLEVBQ2pCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUEwQixTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6RSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2hGLE9BQU8sRUFDTCw2QkFBNkIsRUFDN0IsY0FBYyxFQUVkLGdCQUFnQixFQUdoQixhQUFhLEVBQ2QsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFbkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrREFBa0QsQ0FBQzs7Ozs7Ozs7Ozs7QUFjakYsTUFBTSxPQUFPLGtDQUFrQztJQWlMN0MsWUFDVSxlQUFnQyxFQUNoQyxhQUE0QixFQUM1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QyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFHTyxVQUFVO1FBQ2hCLE9BQU8sS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUNoQixJQUFJLENBQ0YsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FDN0IsRUFBRSxRQUFRLEVBQUUsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQ3RFLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQ25CLENBQ0YsQ0FDRixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixDQUFDOytHQXJWVSxrQ0FBa0M7bUdBQWxDLGtDQUFrQyx1RUM1Qy9DLDY0TEF1SkE7O0FEdU5VO0lBRFAsT0FBTyxFQUFFOzs7b0NBQ2lCLFVBQVU7eUVBRXBDO0FBR087SUFEUCxPQUFPLEVBQUU7OztvQ0FDYSxVQUFVO3FFQUVoQztBQUdPO0lBRFAsT0FBTyxFQUFFOzs7b0NBQ1ksVUFBVTtvRUFTL0I7NEZBclZVLGtDQUFrQztrQkFMOUMsU0FBUzsrQkFDRSxpQ0FBaUMsbUJBRTFCLHVCQUF1QixDQUFDLE1BQU07b1ZBb1V2QyxlQUFlLE1BS2YsV0FBVyxNQUtYLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgT25EZXN0cm95XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybWx5RmllbGRDb25maWcsIEZvcm1seUZvcm1PcHRpb25zIH0gZnJvbSAnQG5neC1mb3JtbHkvY29yZSc7XG5pbXBvcnQge1xuICBUZW5hbnRVaVNlcnZpY2UsXG4gIGdldHRleHQsXG4gIEM4eVN0ZXBwZXIsXG4gIG1lbW9pemUsXG4gIEdhaW5zaWdodFNlcnZpY2Vcbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBGb3JtQXJyYXksIEZvcm1Db250cm9sLCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBmcm9tLCBPYnNlcnZhYmxlLCBTdWJqZWN0LCBkZWZlciwgQmVoYXZpb3JTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIHNoYXJlUmVwbGF5LCBzd2l0Y2hNYXAsIHRha2VVbnRpbCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgRGV2aWNlUmVnaXN0cmF0aW9uQnVsa1NlcnZpY2UsXG4gIEZlYXR1cmVTZXJ2aWNlLFxuICBJTWFuYWdlZE9iamVjdCxcbiAgSW52ZW50b3J5U2VydmljZSxcbiAgSVJlc3VsdExpc3QsXG4gIElUZW5hbnQsXG4gIFRlbmFudFNlcnZpY2Vcbn0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgUmVnaXN0ZXJEZXZpY2VTZXJ2aWNlIH0gZnJvbSAnLi4vcmVnaXN0ZXItZGV2aWNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2RrU3RlcCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9zdGVwcGVyJztcbmltcG9ydCB7IEJzTW9kYWxSZWYgfSBmcm9tICduZ3gtYm9vdHN0cmFwL21vZGFsJztcbmltcG9ydCB7IEVTVENzdkhlYWRlcnMgfSBmcm9tICcuLi9idWxrL2J1bGstZGV2aWNlLXJlZ2lzdHJhdGlvbi1tb2RhbC5jb21wb25lbnQnO1xuXG5pbnRlcmZhY2UgR2VuZXJhbERldmljZVJlZ2lzdHJhdGlvbk1vZGVsVHlwZSB7XG4gIGlkOiBzdHJpbmc7XG4gIHRlbmFudD86IHsgaWQ6IHN0cmluZyB9O1xuICBncm91cD86IHsgaWQ6IHN0cmluZzsgbmFtZT86IHN0cmluZyB9O1xuICBvbmVUaW1lUGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1nZW5lcmFsLWRldmljZS1yZWdpc3RyYXRpb24nLFxuICB0ZW1wbGF0ZVVybDogJ2dlbmVyYWwtZGV2aWNlLXJlZ2lzdHJhdGlvbi5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEdlbmVyYWxEZXZpY2VSZWdpc3RyYXRpb25Db21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICByZWFkb25seSBNQU5BR0VNRU5UID0gJ21hbmFnZW1lbnQnO1xuICByZWFkb25seSBGSUxURVI6IG9iamVjdCA9IHtcbiAgICB3aXRoVG90YWxQYWdlczogdHJ1ZSxcbiAgICBwYWdlU2l6ZTogMjVcbiAgfTtcblxuICB1c2VFU1QkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIGNlcnRpZmljYXRlQXV0aG9yaXR5RmVhdHVyZUVuYWJsZWQgPSB0aGlzLmZlYXR1cmVTZXJ2aWNlXG4gICAgLmRldGFpbCgnY2VydGlmaWNhdGUtYXV0aG9yaXR5JylcbiAgICAudGhlbigoeyBkYXRhIH0pID0+IGRhdGEuYWN0aXZlKTtcblxuICBmb3JtID0gbmV3IEZvcm1Hcm91cCh7fSk7XG4gIG1vZGVsID0ge1xuICAgIGRldmljZXNUb0NyZWF0ZTogW3t9IGFzIEdlbmVyYWxEZXZpY2VSZWdpc3RyYXRpb25Nb2RlbFR5cGVdXG4gIH07XG4gIG9wdGlvbnM6IEZvcm1seUZvcm1PcHRpb25zID0ge1xuICAgIGZvcm1TdGF0ZToge1xuICAgICAgY2FuTG9hZFRlbmFudHM6IHRydWUsXG4gICAgICB1c2VFU1Q6IHRoaXMudXNlRVNUJC5nZXRWYWx1ZSgpXG4gICAgfVxuICB9O1xuXG4gIFBST0RVQ1RfRVhQRVJJRU5DRSA9IHtcbiAgICBFVkVOVDogJ2RldmljZVJlZ2lzdHJhdGlvbicsXG4gICAgQ09NUE9ORU5UOiAnc2luZ2xlLWdlbmVyYWwtcmVnaXN0cmF0aW9uJyxcbiAgICBSRVNVTFQ6IHsgU1VDQ0VTUzogJ3JlZ2lzdHJhdGlvblN1Y2Nlc3MnLCBGQUlMVVJFOiAncmVnaXN0cmF0aW9uRmFpbHVyZScgfVxuICB9O1xuXG4gIGlzTG9hZGluZyQ6IE9ic2VydmFibGU8Ym9vbGVhbj47XG4gIHN1Y2Nlc3M6IHsgaWQ6IHN0cmluZyB9W10gPSBbXTtcbiAgZmFpbGVkOiB7IGlkOiBzdHJpbmc7IG1lc3NhZ2U/OiBzdHJpbmc7IGRldGFpbHM/OiBhbnkgfVtdID0gW107XG5cbiAgZmllbGRzOiBGb3JtbHlGaWVsZENvbmZpZ1tdID0gW1xuICAgIHtcbiAgICAgIHR5cGU6ICdhcnJheScsXG4gICAgICBrZXk6ICdkZXZpY2VzVG9DcmVhdGUnLFxuICAgICAgcHJvcHM6IHtcbiAgICAgICAgYWRkVGV4dDogZ2V0dGV4dCgnQWRkIGRldmljZScpLFxuICAgICAgICBhZGRUZXh0RGF0YUN5OiAnYWRkLWRldmljZSdcbiAgICAgIH0sXG4gICAgICBmaWVsZEFycmF5OiB7XG4gICAgICAgIGZpZWxkR3JvdXA6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBrZXk6ICdpZCcsXG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGZvY3VzOiB0cnVlLFxuICAgICAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6ICcwMTIzYWIzMmZjZCcsXG4gICAgICAgICAgICAgIGxhYmVsOiBnZXR0ZXh0KCdEZXZpY2UgSUQnKSxcbiAgICAgICAgICAgICAgcmVxdWlyZWQ6IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWxpZGF0b3JzOiB7XG4gICAgICAgICAgICAgIHVuaXF1ZToge1xuICAgICAgICAgICAgICAgIGV4cHJlc3Npb246IChjb250cm9sOiBGb3JtQ29udHJvbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZm91bmQgPSAoXG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2wucm9vdC5nZXQoJ2RldmljZXNUb0NyZWF0ZScpIGFzIEZvcm1BcnJheTxcbiAgICAgICAgICAgICAgICAgICAgICBGb3JtR3JvdXA8eyBpZDogRm9ybUNvbnRyb2w8c3RyaW5nPiB9PlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICApLmNvbnRyb2xzXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoZWwgPT4gZWwuY29udHJvbHMuaWQpXG4gICAgICAgICAgICAgICAgICAgIC5maW5kKGVsID0+IGVsICE9PSBjb250cm9sICYmIGVsLnZhbHVlID09PSBjb250cm9sLnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAhZm91bmQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiAoKSA9PiBnZXR0ZXh0KCdEZXZpY2UgSUQgZHVwbGljYXRlcyBhcmUgbm90IGFsbG93ZWQnKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBrZXk6ICd0ZW5hbnQnLFxuICAgICAgICAgICAgdHlwZTogJ3R5cGVhaGVhZCcsXG4gICAgICAgICAgICBleHByZXNzaW9uczoge1xuICAgICAgICAgICAgICBoaWRlOiBmaWVsZCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybVN0YXRlID0gZmllbGQub3B0aW9ucz8uZm9ybVN0YXRlO1xuICAgICAgICAgICAgICAgIGlmICghZm9ybVN0YXRlPy5jYW5Mb2FkVGVuYW50cykge1xuICAgICAgICAgICAgICAgICAgZmllbGQuZm9ybUNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAhZm9ybVN0YXRlPy5jYW5Mb2FkVGVuYW50cyB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZTogeyBpZDogdGhpcy5N