UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

474 lines (463 loc) 44.7 kB
import * as i0 from '@angular/core'; import { InjectionToken, Directive, ViewChild, Input, Optional, Inject, Component, Injectable, HostListener, EventEmitter, Output, NgModule } from '@angular/core'; import { OperationBulkGeneralStatus } from '@c8y/client'; import { gettext } from '@c8y/ngx-components/gettext'; import * as i3 from '@c8y/ngx-components'; import { C8yTranslatePipe, IconDirective, ProductExperienceDirective, C8yTranslateDirective, Status, ListItemComponent, ListItemIconComponent, ListItemActionComponent, ListItemCollapseComponent, DatePipe, NumberPipe } from '@c8y/ngx-components'; import * as i1 from '@c8y/ngx-components/operations/bulk-operations-service'; import { BULK_OPERATION_EVENT } from '@c8y/ngx-components/operations/product-experience'; import { assign, values, find, cloneDeep } from 'lodash-es'; import * as i2 from 'ngx-bootstrap/modal'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { OperationSchedulerComponent } from '@c8y/ngx-components/operations/bulk-operation-scheduler'; import { OperationSummaryComponent } from '@c8y/ngx-components/operations/operation-summary'; import * as i4 from '@angular/forms'; import { FormsModule } from '@angular/forms'; import { NgClass, NgIf } from '@angular/common'; import { TooltipDirective } from 'ngx-bootstrap/tooltip'; import { PopoverDirective } from 'ngx-bootstrap/popover'; import { OperationDetailsTabsComponent } from '@c8y/ngx-components/operations/operations-list-item-details'; const BULK_OPERATION_STATUS_LABELS = { SCHEDULED: gettext('Scheduled'), EXECUTING: gettext('Executing'), CANCELED: gettext('Canceled'), FAILED: gettext('Completed with failures'), SUCCESSFUL: gettext('Completed successfully'), DELETED: gettext('Deleted') }; const BULK_OPERATION_STATUS_OPTIONS = { SCHEDULED: { label: BULK_OPERATION_STATUS_LABELS.SCHEDULED, generalStatuses: [OperationBulkGeneralStatus.SCHEDULED], icon: 'calendar', styleClass: 'text-info' }, EXECUTING: { label: BULK_OPERATION_STATUS_LABELS.EXECUTING, generalStatuses: [ OperationBulkGeneralStatus.EXECUTING, OperationBulkGeneralStatus.EXECUTING_WITH_ERROR ], icon: 'refresh', styleClass: 'text-primary' }, DELETED: { label: BULK_OPERATION_STATUS_LABELS.DELETED, generalStatuses: [OperationBulkGeneralStatus.DELETED], icon: 'delete-document', styleClass: 'text-muted' }, CANCELED: { label: BULK_OPERATION_STATUS_LABELS.CANCELED, generalStatuses: [OperationBulkGeneralStatus.CANCELED], icon: 'ban', styleClass: 'text-primary' }, FAILED: { label: BULK_OPERATION_STATUS_LABELS.FAILED, generalStatuses: [OperationBulkGeneralStatus.FAILED], icon: 'exclamation-circle', styleClass: 'text-danger' }, SUCCESSFUL: { label: BULK_OPERATION_STATUS_LABELS.SUCCESSFUL, generalStatuses: [OperationBulkGeneralStatus.SUCCESSFUL], icon: 'check-circle', styleClass: 'text-success' } }; const BULK_OPERATION_WRAPPER_MODAL_BODY_COMPONENT = new InjectionToken('BulkOperationWrapperModalBodyComponent'); class ModalBodyHostDirective { constructor(viewContainerRef) { this.viewContainerRef = viewContainerRef; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ModalBodyHostDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: ModalBodyHostDirective, isStandalone: true, selector: "[modalBodyHost]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ModalBodyHostDirective, decorators: [{ type: Directive, args: [{ selector: '[modalBodyHost]' }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }] }); class BulkOperationWrapperComponent { constructor(bulkOperationsService, modalRef, modalService, modalBodyConfig) { this.bulkOperationsService = bulkOperationsService; this.modalRef = modalRef; this.modalService = modalService; this.modalBodyConfig = modalBodyConfig; this.destroyed$ = new Subject(); } ngOnInit() { if (this.modalBodyConfig) { const componentRef = this.modalBodyHost.viewContainerRef.createComponent(this.modalBodyConfig.component); assign(componentRef.instance, this.modalBodyConfig.config); componentRef.instance.bulkOperation = this.bulkOperation; componentRef.instance.showFailedOperation .pipe(takeUntil(this.destroyed$)) .subscribe(event => this.openDetails(event)); } } ngOnDestroy() { this.destroyed$.next(); this.destroyed$.complete(); } // openDetails function needs to be defined in the both places (component and the service) to avoid circular dependency. async openDetails(bulkOperationId) { const bulkOperation = (await this.bulkOperationsService.getBulkOperationById(bulkOperationId)).data; const initialState = { bulkOperation }; this.modalService.show(BulkOperationWrapperComponent, { initialState, class: 'modal-lg', ariaDescribedby: 'modal-body', ariaLabelledBy: 'modal-title' }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationWrapperComponent, deps: [{ token: i1.BulkOperationsService }, { token: i2.BsModalRef }, { token: i2.BsModalService }, { token: BULK_OPERATION_WRAPPER_MODAL_BODY_COMPONENT, optional: true }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: BulkOperationWrapperComponent, isStandalone: true, selector: "c8y-bulk-operations-wrapper", inputs: { bulkOperation: "bulkOperation" }, viewQueries: [{ propertyName: "modalBodyHost", first: true, predicate: ModalBodyHostDirective, descendants: true, static: true }], ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header\">\n <h3 id=\"modal-title\">{{ 'Bulk operation details' | translate }}</h3>\n </div>\n\n <div class=\"modal-inner-scroll\" id=\"modal-body\">\n <ng-container modalBodyHost></ng-container>\n </div>\n\n <div class=\"modal-footer\">\n <button\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n (click)=\"modalRef.hide()\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: ModalBodyHostDirective, selector: "[modalBodyHost]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationWrapperComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-bulk-operations-wrapper', imports: [ModalBodyHostDirective, C8yTranslatePipe], template: "<div class=\"viewport-modal\">\n <div class=\"modal-header\">\n <h3 id=\"modal-title\">{{ 'Bulk operation details' | translate }}</h3>\n </div>\n\n <div class=\"modal-inner-scroll\" id=\"modal-body\">\n <ng-container modalBodyHost></ng-container>\n </div>\n\n <div class=\"modal-footer\">\n <button\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n (click)=\"modalRef.hide()\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.BulkOperationsService }, { type: i2.BsModalRef }, { type: i2.BsModalService }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [BULK_OPERATION_WRAPPER_MODAL_BODY_COMPONENT] }] }], propDecorators: { bulkOperation: [{ type: Input }], modalBodyHost: [{ type: ViewChild, args: [ModalBodyHostDirective, { static: true }] }] } }); class BulkOperationListItemService { constructor(bulkOperationsService, modalService) { this.bulkOperationsService = bulkOperationsService; this.modalService = modalService; } async openDetails(bulkOperationId) { const bulkOperation = (await this.bulkOperationsService.getBulkOperationById(bulkOperationId)).data; const initialState = { bulkOperation }; this.modalService.show(BulkOperationWrapperComponent, { initialState, class: 'modal-lg', ariaDescribedby: 'modal-body', ariaLabelledBy: 'modal-title' }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemService, deps: [{ token: i1.BulkOperationsService }, { token: i2.BsModalService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.BulkOperationsService }, { type: i2.BsModalService }] }); class BulkOperationsRescheduleModalComponent { constructor(bsModalRef, bulkOperationsService, alert, gainsightService) { this.bsModalRef = bsModalRef; this.bulkOperationsService = bulkOperationsService; this.alert = alert; this.gainsightService = gainsightService; this.BULK_OPERATION_EVENT = BULK_OPERATION_EVENT; this.closeSubject = new Subject(); this.CARRIAGE_RETURN_CODE = 'Escape'; } onKeyUp(event) { if (event.code === this.CARRIAGE_RETURN_CODE) { this.gainsightService.triggerEvent('modalDialog', { title: this.modalTitle, result: 'Cancel' }); } } ngOnInit() { this.modalTitle = this.getTitle(); } onDateAndDelaySelect($event) { this.dateAndDelay = $event; } getTitle() { return this.isRetryOperation ? gettext('Retry operation') : gettext('Edit schedule'); } onCancel() { this.bsModalRef.hide(); } async onSave() { let newBulkOperation; this.bulkOperation.startDate = this.dateAndDelay.scheduledDate.toISOString(); this.bulkOperation.creationRamp = this.dateAndDelay.delayInSeconds; if (this.isRetryOperation) { try { newBulkOperation = await this.bulkOperationsService.createBulkOperation(this.bulkOperation); this.alert.success(gettext('Successfully rescheduled for a retry.')); } catch (er) { this.alert.addServerFailure(er); } } else { try { newBulkOperation = await this.bulkOperationsService.updateBulkOperation(this.bulkOperation); this.alert.success(gettext('Successfully rescheduled.')); } catch (er) { this.alert.addServerFailure(er); } } // send back to component from which modal was called this.closeSubject.next(newBulkOperation.data); this.bsModalRef.hide(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationsRescheduleModalComponent, deps: [{ token: i2.BsModalRef }, { token: i1.BulkOperationsService }, { token: i3.AlertService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: BulkOperationsRescheduleModalComponent, isStandalone: true, selector: "c8y-bulk-operations-reschedule-modal", host: { listeners: { "window:keyup": "onKeyUp($event)" } }, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i c8yIcon=\"c8y-energy\"></i>\n <h4 id=\"modal-title\">{{ modalTitle | translate }}</h4>\n </div>\n <div class=\"modal-inner-scroll\" id=\"modal-body\">\n <div class=\"modal-body\">\n <div class=\"text-center\">\n <c8y-operation-summary\n [description]=\"bulkOperation.operationPrototype.description\"\n ></c8y-operation-summary>\n </div>\n <div class=\"p-t-16 center-block\" style=\"max-width: 300px\">\n <c8y-operation-scheduler\n [(ngModel)]=\"dateAndDelay\"\n #scheduler=\"ngModel\"\n ></c8y-operation-scheduler>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n (click)=\"onCancel()\"\n type=\"button\"\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ title: modalTitle, result: 'Cancel' }\"\n >\n <span translate>Cancel</span>\n </button>\n <button\n id=\"save-btn\"\n (click)=\"onSave()\"\n type=\"button\"\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n [disabled]=\"scheduler?.control?.errors\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ title: modalTitle, result: 'Save' }\"\n >\n <span translate>Save</span>\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: OperationSummaryComponent, selector: "c8y-operation-summary", inputs: ["name", "description", "deviceQueryString"] }, { kind: "component", type: OperationSchedulerComponent, selector: "c8y-operation-scheduler", inputs: ["minutesAhead"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationsRescheduleModalComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-bulk-operations-reschedule-modal', imports: [ IconDirective, OperationSummaryComponent, OperationSchedulerComponent, FormsModule, ProductExperienceDirective, C8yTranslateDirective, C8yTranslatePipe ], template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i c8yIcon=\"c8y-energy\"></i>\n <h4 id=\"modal-title\">{{ modalTitle | translate }}</h4>\n </div>\n <div class=\"modal-inner-scroll\" id=\"modal-body\">\n <div class=\"modal-body\">\n <div class=\"text-center\">\n <c8y-operation-summary\n [description]=\"bulkOperation.operationPrototype.description\"\n ></c8y-operation-summary>\n </div>\n <div class=\"p-t-16 center-block\" style=\"max-width: 300px\">\n <c8y-operation-scheduler\n [(ngModel)]=\"dateAndDelay\"\n #scheduler=\"ngModel\"\n ></c8y-operation-scheduler>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n (click)=\"onCancel()\"\n type=\"button\"\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ title: modalTitle, result: 'Cancel' }\"\n >\n <span translate>Cancel</span>\n </button>\n <button\n id=\"save-btn\"\n (click)=\"onSave()\"\n type=\"button\"\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n [disabled]=\"scheduler?.control?.errors\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ title: modalTitle, result: 'Save' }\"\n >\n <span translate>Save</span>\n </button>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i2.BsModalRef }, { type: i1.BulkOperationsService }, { type: i3.AlertService }, { type: i3.GainsightService }], propDecorators: { onKeyUp: [{ type: HostListener, args: ['window:keyup', ['$event']] }] } }); class BulkOperationListItemComponent { constructor(bulkOperationListItemService, bulkOperationsService, modal, alert, bsModalService) { this.bulkOperationListItemService = bulkOperationListItemService; this.bulkOperationsService = bulkOperationsService; this.modal = modal; this.alert = alert; this.bsModalService = bsModalService; this.BULK_OPERATION_EVENT = BULK_OPERATION_EVENT; this.detailsCollapsed = true; this.readOnly = false; this.showFailedOperation = new EventEmitter(); this.reload = new EventEmitter(); this.refreshLoading = false; this.bulkOperationGeneralStatus = OperationBulkGeneralStatus; this.BULK_OPERATION_STATUS_OPTIONS = BULK_OPERATION_STATUS_OPTIONS; this.finishDatePopoverText = gettext('Approximate date, estimated based on the bulk operation settings.'); this.progressBarClass = 'progress'; this.progressBarStatus = 0; } ngOnInit() { this.finishDate = this.calculateFinishDateMs(); this.setProgressBar(); } getOperationStatusOptions() { const statusOptions = values(BULK_OPERATION_STATUS_OPTIONS); return find(statusOptions, options => options.generalStatuses.includes(this.bulkOperation.generalStatus)); } ngOnChanges(changes) { if (changes.bulkOperation && !changes.bulkOperation.firstChange) { this.setProgressBar(); } } calculateFinishDateMs() { const startDateMs = new Date(this.bulkOperation.startDate).getTime(); const creationRampMs = this.bulkOperation.creationRamp * 1000; return startDateMs + creationRampMs * this.bulkOperation.progress.all; } progressBarProgressFn() { return (((this.bulkOperation.progress.successful + this.bulkOperation.progress.failed) / this.bulkOperation.progress.all) * 100); } setProgressBar() { const staticContentOfClass = 'progress-bar progress-striped active progress-bar'; const progressBarState = { EXECUTING: { progressBarClass: 'progress progress-striped active', progressBarColor: `${staticContentOfClass}-primary`, progressBarStatus: this.progressBarProgressFn() }, EXECUTING_WITH_ERROR: { progressBarClass: 'progress progress-striped active', progressBarColor: `${staticContentOfClass}-danger`, progressBarStatus: this.progressBarProgressFn() }, FAILED: { progressBarClass: 'progress', progressBarColor: `${staticContentOfClass}-danger`, progressBarStatus: 100 }, SUCCESSFUL: { progressBarClass: 'progress', progressBarColor: `${staticContentOfClass}-success`, progressBarStatus: 100 } }; assign(this, progressBarState[this.bulkOperation.generalStatus]); } editSchedule() { const rescheduledOperation = cloneDeep(this.bulkOperation); const initialState = { bulkOperation: rescheduledOperation }; const modalOptions = { initialState, class: 'modal-sm', ariaDescribedby: 'modal-body', ariaLabelledBy: 'modal-title', backdrop: 'static' }; this.bsModalRef = this.bsModalService.show(BulkOperationsRescheduleModalComponent, modalOptions); } async cancelBulkOperation() { try { await this.modal.confirm(gettext('Cancel bulk operation'), gettext('You are about to cancel the bulk operation. Do you want to proceed?'), Status.DANGER, {}, {}, { eventName: BULK_OPERATION_EVENT }); await this.bulkOperationsService.deleteBulkOperation(this.bulkOperation.id); this.reload.emit(); this.alert.success(gettext('Operation canceled.')); } catch (er) { this.alert.addServerFailure(er); } } retryFailedOperation() { const clonedBulk = cloneDeep(this.bulkOperation); // change the id to failedparentId similar to the logic in deviceBulkControl.service.js delete clonedBulk.groupId; clonedBulk.failedParentId = this.bulkOperation.id; // show reschdedule modal: const initialState = { bulkOperation: clonedBulk, isRetryOperation: true }; const modalOptions = { initialState, class: 'modal-sm', backdrop: 'static' }; this.bsModalRef = this.bsModalService.show(BulkOperationsRescheduleModalComponent, modalOptions); this.bsModalRef.content.closeSubject.subscribe(() => { this.reload.emit(); }); } async setToSuccessful() { try { await this.modal.confirm(gettext('Set manually bulk operation to SUCCESSFUL'), gettext('You are about to change the bulk operation status to SUCCESSFUL. Do you want to proceed?'), Status.DANGER, {}, {}, { eventName: BULK_OPERATION_EVENT }); await this.bulkOperationsService.updateBulkOperation({ id: this.bulkOperation.id, generalStatus: OperationBulkGeneralStatus.SUCCESSFUL }); this.reload.emit(); this.alert.success(gettext('Operation status changed to SUCCESSFUL.')); } catch (er) { this.alert.addServerFailure(er); } } openFailedOperation(failedParentId) { this.showFailedOperation.emit(failedParentId); } isStatusScheduled() { return this.bulkOperation.generalStatus === this.bulkOperationGeneralStatus.SCHEDULED; } isStatusExecutingOrExecutingWithError() { return (this.bulkOperation.generalStatus === this.bulkOperationGeneralStatus.EXECUTING || this.bulkOperation.generalStatus === this.bulkOperationGeneralStatus.EXECUTING_WITH_ERROR); } allOperationsCreated() { return (this.bulkOperation.progress.all === this.bulkOperation.progress.executing + this.bulkOperation.progress.failed + this.bulkOperation.progress.pending + this.bulkOperation.progress.successful); } isStatusCanceled() { return this.bulkOperation.generalStatus === this.bulkOperationGeneralStatus.CANCELED; } isStatusFailed() { return this.bulkOperation.generalStatus === this.bulkOperationGeneralStatus.FAILED; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemComponent, deps: [{ token: BulkOperationListItemService }, { token: i1.BulkOperationsService }, { token: i3.ModalService }, { token: i3.AlertService }, { token: i2.BsModalService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: BulkOperationListItemComponent, isStandalone: true, selector: "c8y-bulk-operation-list-item", inputs: { bulkOperation: "bulkOperation", detailsCollapsed: "detailsCollapsed", readOnly: "readOnly" }, outputs: { showFailedOperation: "showFailedOperation", reload: "reload" }, viewQueries: [{ propertyName: "listItem", first: true, predicate: ["listItem"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<c8y-li\n class=\"c8y-list__item--double-actions\"\n [ngClass]=\"{ 'c8y-list__item--no-expand': !detailsCollapsed }\"\n [collapsed]=\"detailsCollapsed\"\n #listItem\n id=\"{{ bulkOperation.id }}\"\n>\n <c8y-li-icon>\n <i\n [c8yIcon]=\"getOperationStatusOptions().icon\"\n [ngClass]=\"getOperationStatusOptions().styleClass\"\n [tooltip]=\"getOperationStatusOptions().label | translate\"\n ></i>\n </c8y-li-icon>\n <div [ngClass]=\"{ 'content-flex-58': !readOnly, 'content-flex-50': readOnly }\">\n <div class=\"col-5\">\n <button\n class=\"btn-clean\"\n type=\"button\"\n title=\"{{ bulkOperation.id }} - {{\n bulkOperation.operationPrototype.description | translate\n }}\"\n (click)=\"listItem.toggleCollapsed()\"\n >\n <span class=\"text-truncate\">\n <strong class=\"text-muted m-r-4\">{{ bulkOperation.id }}</strong>\n {{ bulkOperation.operationPrototype.description | translate }}\n </span>\n </button>\n </div>\n <div class=\"flex-grow\">\n <div class=\"m-t-8 visible-xs\"></div>\n <hr *ngIf=\"isStatusCanceled(); else statusNotCanceled\" class=\"m-t-16 m-b-0 visible-xs\" />\n <ng-template #statusNotCanceled>\n <div\n [class]=\"progressBarClass\"\n title=\"{{ progressBarStatus | c8yNumber: 'floor':'1.0-0' }}%\"\n >\n <div\n [class]=\"progressBarColor\"\n role=\"progressbar\"\n [attr.aria-label]=\"'Progress' | translate\"\n aria-valuenow=\"0\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [style.width.%]=\"progressBarStatus\"\n >\n <span *ngIf=\"progressBarStatus !== 0\">\n {{ progressBarStatus | c8yNumber: 'floor':'1.0-0' }}%\n </span>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"col-4\">\n <div class=\"p-t-8 visible-xs\"></div>\n <small *ngIf=\"bulkOperation.progress.successful > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"check-circle\" class=\"text-success m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountSuccessful: bulkOperation.progress.successful }\"\n >\n {{ bulkOperationsCountSuccessful }} successful\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.failed > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"warning\" class=\"text-danger m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountFailed: bulkOperation.progress.failed }\"\n >\n {{ bulkOperationsCountFailed }} failed\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.executing > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"refresh\" class=\"text-primary m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountExecuting: bulkOperation.progress.executing }\"\n >\n {{ bulkOperationsCountExecuting }} executing\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.pending > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"clock-o\" class=\"text-primary m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountPending: bulkOperation.progress.pending }\"\n >\n {{ bulkOperationsCountPending }} pending\n </span>\n </small>\n </div>\n </div>\n <div class=\"c8y-list__item__footer\">\n <div class=\"m-r-16\">\n <span class=\"text-label-small m-r-4\" translate>Start</span>\n <small class=\"icon-flex\">\n <i c8yIcon=\"calendar\" class=\"m-r-4\"></i>\n <span>\n {{ bulkOperation.startDate | c8yDate }}\n </span>\n </small>\n </div>\n <div class=\"m-r-16\" *ngIf=\"bulkOperationGeneralStatus.CANCELED !== bulkOperation.generalStatus\">\n <span class=\"text-label-small m-r-4\" translate>Finish</span>\n\n <small class=\"icon-flex\">\n <i c8yIcon=\"calendar\" class=\"m-r-4\"></i>\n <span>{{ finishDate | c8yDate }}</span>\n </small>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ finishDatePopoverText | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n *ngIf=\"isStatusScheduled() || isStatusExecutingOrExecutingWithError()\"\n ></button>\n </div>\n </div>\n <ng-container *ngIf=\"!readOnly\">\n <c8y-li-action\n *ngIf=\"isStatusScheduled()\"\n label=\"{{ 'Edit schedule' | translate }}\"\n (click)=\"editSchedule()\"\n icon=\"pencil\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"\n isStatusScheduled() || (isStatusExecutingOrExecutingWithError() && !allOperationsCreated())\n \"\n label=\"{{ 'Cancel bulk operation' | translate }}\"\n (click)=\"cancelBulkOperation()\"\n icon=\"remove\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"isStatusFailed()\"\n label=\"{{ 'Retry failed operations' | translate }}\"\n (click)=\"retryFailedOperation()\"\n icon=\"repeat\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"isStatusFailed()\"\n label=\"{{ 'Set operation to SUCCESSFUL' | translate }}\"\n (click)=\"setToSuccessful()\"\n icon=\"check-circle\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n </ng-container>\n <c8y-li-collapse class=\"m-b-16\">\n <c8y-operation-details-tabs\n *ngIf=\"!listItem.collapsed\"\n [operation]=\"bulkOperation\"\n [readOnly]=\"readOnly\"\n (onRetryFailedOperations)=\"retryFailedOperation()\"\n (showFailedOperation)=\"openFailedOperation($event)\"\n [bulkOperationModalDetailsService]=\"bulkOperationListItemService\"\n ></c8y-operation-details-tabs>\n </c8y-li-collapse>\n</c8y-li>\n", dependencies: [{ kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: 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: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: ListItemActionComponent, selector: "c8y-list-item-action, c8y-li-action", inputs: ["label", "icon", "disabled"], outputs: ["click"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: OperationDetailsTabsComponent, selector: "c8y-operation-details-tabs", inputs: ["operation", "readOnly", "bulkOperationModalDetailsService"], outputs: ["onRetryFailedOperations", "showFailedOperation"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: NumberPipe, name: "c8yNumber" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-bulk-operation-list-item', imports: [ ListItemComponent, NgClass, ListItemIconComponent, IconDirective, TooltipDirective, NgIf, C8yTranslateDirective, PopoverDirective, ListItemActionComponent, ProductExperienceDirective, ListItemCollapseComponent, OperationDetailsTabsComponent, C8yTranslatePipe, DatePipe, NumberPipe ], template: "<c8y-li\n class=\"c8y-list__item--double-actions\"\n [ngClass]=\"{ 'c8y-list__item--no-expand': !detailsCollapsed }\"\n [collapsed]=\"detailsCollapsed\"\n #listItem\n id=\"{{ bulkOperation.id }}\"\n>\n <c8y-li-icon>\n <i\n [c8yIcon]=\"getOperationStatusOptions().icon\"\n [ngClass]=\"getOperationStatusOptions().styleClass\"\n [tooltip]=\"getOperationStatusOptions().label | translate\"\n ></i>\n </c8y-li-icon>\n <div [ngClass]=\"{ 'content-flex-58': !readOnly, 'content-flex-50': readOnly }\">\n <div class=\"col-5\">\n <button\n class=\"btn-clean\"\n type=\"button\"\n title=\"{{ bulkOperation.id }} - {{\n bulkOperation.operationPrototype.description | translate\n }}\"\n (click)=\"listItem.toggleCollapsed()\"\n >\n <span class=\"text-truncate\">\n <strong class=\"text-muted m-r-4\">{{ bulkOperation.id }}</strong>\n {{ bulkOperation.operationPrototype.description | translate }}\n </span>\n </button>\n </div>\n <div class=\"flex-grow\">\n <div class=\"m-t-8 visible-xs\"></div>\n <hr *ngIf=\"isStatusCanceled(); else statusNotCanceled\" class=\"m-t-16 m-b-0 visible-xs\" />\n <ng-template #statusNotCanceled>\n <div\n [class]=\"progressBarClass\"\n title=\"{{ progressBarStatus | c8yNumber: 'floor':'1.0-0' }}%\"\n >\n <div\n [class]=\"progressBarColor\"\n role=\"progressbar\"\n [attr.aria-label]=\"'Progress' | translate\"\n aria-valuenow=\"0\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [style.width.%]=\"progressBarStatus\"\n >\n <span *ngIf=\"progressBarStatus !== 0\">\n {{ progressBarStatus | c8yNumber: 'floor':'1.0-0' }}%\n </span>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"col-4\">\n <div class=\"p-t-8 visible-xs\"></div>\n <small *ngIf=\"bulkOperation.progress.successful > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"check-circle\" class=\"text-success m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountSuccessful: bulkOperation.progress.successful }\"\n >\n {{ bulkOperationsCountSuccessful }} successful\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.failed > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"warning\" class=\"text-danger m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountFailed: bulkOperation.progress.failed }\"\n >\n {{ bulkOperationsCountFailed }} failed\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.executing > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"refresh\" class=\"text-primary m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountExecuting: bulkOperation.progress.executing }\"\n >\n {{ bulkOperationsCountExecuting }} executing\n </span>\n </small>\n <small *ngIf=\"bulkOperation.progress.pending > 0\" class=\"m-r-8 icon-flex\">\n <i c8yIcon=\"clock-o\" class=\"text-primary m-r-4\"></i>\n <span\n ngNonBindable\n translate\n [translateParams]=\"{ bulkOperationsCountPending: bulkOperation.progress.pending }\"\n >\n {{ bulkOperationsCountPending }} pending\n </span>\n </small>\n </div>\n </div>\n <div class=\"c8y-list__item__footer\">\n <div class=\"m-r-16\">\n <span class=\"text-label-small m-r-4\" translate>Start</span>\n <small class=\"icon-flex\">\n <i c8yIcon=\"calendar\" class=\"m-r-4\"></i>\n <span>\n {{ bulkOperation.startDate | c8yDate }}\n </span>\n </small>\n </div>\n <div class=\"m-r-16\" *ngIf=\"bulkOperationGeneralStatus.CANCELED !== bulkOperation.generalStatus\">\n <span class=\"text-label-small m-r-4\" translate>Finish</span>\n\n <small class=\"icon-flex\">\n <i c8yIcon=\"calendar\" class=\"m-r-4\"></i>\n <span>{{ finishDate | c8yDate }}</span>\n </small>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ finishDatePopoverText | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n *ngIf=\"isStatusScheduled() || isStatusExecutingOrExecutingWithError()\"\n ></button>\n </div>\n </div>\n <ng-container *ngIf=\"!readOnly\">\n <c8y-li-action\n *ngIf=\"isStatusScheduled()\"\n label=\"{{ 'Edit schedule' | translate }}\"\n (click)=\"editSchedule()\"\n icon=\"pencil\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"\n isStatusScheduled() || (isStatusExecutingOrExecutingWithError() && !allOperationsCreated())\n \"\n label=\"{{ 'Cancel bulk operation' | translate }}\"\n (click)=\"cancelBulkOperation()\"\n icon=\"remove\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"isStatusFailed()\"\n label=\"{{ 'Retry failed operations' | translate }}\"\n (click)=\"retryFailedOperation()\"\n icon=\"repeat\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n <c8y-li-action\n *ngIf=\"isStatusFailed()\"\n label=\"{{ 'Set operation to SUCCESSFUL' | translate }}\"\n (click)=\"setToSuccessful()\"\n icon=\"check-circle\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n ></c8y-li-action>\n </ng-container>\n <c8y-li-collapse class=\"m-b-16\">\n <c8y-operation-details-tabs\n *ngIf=\"!listItem.collapsed\"\n [operation]=\"bulkOperation\"\n [readOnly]=\"readOnly\"\n (onRetryFailedOperations)=\"retryFailedOperation()\"\n (showFailedOperation)=\"openFailedOperation($event)\"\n [bulkOperationModalDetailsService]=\"bulkOperationListItemService\"\n ></c8y-operation-details-tabs>\n </c8y-li-collapse>\n</c8y-li>\n" }] }], ctorParameters: () => [{ type: BulkOperationListItemService }, { type: i1.BulkOperationsService }, { type: i3.ModalService }, { type: i3.AlertService }, { type: i2.BsModalService }], propDecorators: { bulkOperation: [{ type: Input }], detailsCollapsed: [{ type: Input }], readOnly: [{ type: Input }], showFailedOperation: [{ type: Output }], reload: [{ type: Output }], listItem: [{ type: ViewChild, args: ['listItem', { static: true }] }] } }); /** * This module allows for displaying the list item of a bulk operation with its details. */ class BulkOperationListItemModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemModule, imports: [BulkOperationListItemComponent, BulkOperationsRescheduleModalComponent, BulkOperationWrapperComponent, ModalBodyHostDirective], exports: [BulkOperationListItemComponent, BulkOperationsRescheduleModalComponent, BulkOperationWrapperComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemModule, providers: [ BulkOperationListItemService, { provide: BULK_OPERATION_WRAPPER_MODAL_BODY_COMPONENT, useValue: { component: BulkOperationListItemComponent, config: { detailsCollapsed: false, readOnly: true } } } ], imports: [BulkOperationListItemComponent, BulkOperationsRescheduleModalComponent] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: BulkOperationListItemModule, decorators: [{ type: NgModule, args: [{ imports: [ BulkOperationListItemComponent, BulkOperationsRescheduleModalComponent, BulkOperationWrapperComponent, ModalBodyHostDirective ], providers: [ BulkOperationListItemService, { provide: BULK_OPERATION_WRAPPER_MODAL_BODY_COMPONENT, useValue: { component: BulkOperationListItemComponent, config: { detailsCollapsed: false, readOnly: true } } } ], exports: [ BulkOperationListItemComponent, BulkOperationsRescheduleModalComponent, BulkOperationWrapperComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { BULK_OPERATION_STATUS_LABELS, BULK_OPERATION_STATUS_OPTIONS, BulkOperationListItemComponent, BulkOperationListItemModule, BulkOperationListItemService, BulkOperationWrapperComponent, BulkOperationsRescheduleModalComponent }; //# sourceMappingURL=c8y-ngx-components-operations-bulk-operation-list-item.mjs.map