UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

270 lines (263 loc) 21.6 kB
import * as i0 from '@angular/core'; import { Injectable, Component, NgModule } from '@angular/core'; import * as i1 from '@c8y/client'; import { OperationStatus } from '@c8y/client'; import { gettext } from '@c8y/ngx-components/gettext'; import * as i2 from '@c8y/ngx-components'; import { operationStatusIcons, operationStatusClasses, ActionBarItemComponent, IconDirective, C8yTranslateDirective, ListGroupComponent, ForOfDirective, ListItemTimelineComponent, ListItemComponent, ListItemIconComponent, ListItemBodyComponent, ListItemActionComponent, EmptyStateComponent, C8yTranslatePipe, DatePipe, CoreModule, ListGroupModule, hookRoute, ViewContext } from '@c8y/ngx-components'; import { assign } from 'lodash-es'; import { switchMap, map } from 'rxjs/operators'; import * as i1$1 from '@angular/router'; import { RouterModule } from '@angular/router'; import { BehaviorSubject, pipe } from 'rxjs'; import { NgIf, NgClass, CommonModule } from '@angular/common'; import { TooltipDirective, TooltipModule } from 'ngx-bootstrap/tooltip'; import { FileDownloadComponent, SharedRepositoryModule } from '@c8y/ngx-components/repository/shared'; import { BsDropdownModule, BsDropdownConfig } from 'ngx-bootstrap/dropdown'; class DiagnosticsService { constructor(operationService, inventoryBinary, modalService, alertService) { this.operationService = operationService; this.inventoryBinary = inventoryBinary; this.modalService = modalService; this.alertService = alertService; this.fragment = 'c8y_DiagnosticReport'; } isSupportedDevice(device) { const supportedOperations = (device && device.c8y_SupportedOperations) || []; return supportedOperations.includes(this.fragment); } getOperations$(device$) { return device$.pipe(switchMap(device => this.operationService.list({ deviceId: device.id, fragmentType: this.fragment, dateFrom: new Date(0).toISOString(), dateTo: new Date(Date.now()).toISOString(), revert: true, pageSize: 10, withTotalPages: true }))); } async createOperation(deviceId) { const operation = { deviceId, description: gettext('Diagnostic file request'), [this.fragment]: {} }; try { await this.operationService.create(operation); this.alertService.success(gettext('Diagnostic file request sent.')); } catch (error) { this.alertService.addServerFailure(error); } } async deleteOperation(operation) { try { const result = await this.modalService.confirm(gettext('Delete diagnostic file'), gettext('You are about to delete this diagnostic file. Do you want to proceed?'), 'danger', { ok: gettext('Delete'), cancel: gettext('Cancel') }); if (result) { this.deleteDiagnosticsBinary(operation); } } catch (error) { // Do nothing } } async cancelOperation(operation) { try { const operationAfterUpdate = (await this.operationService.update({ id: operation.id, status: OperationStatus.FAILED, failureReason: gettext('Operation cancelled by user.') })).data; assign(operation, operationAfterUpdate); this.alertService.success(gettext('Diagnostic file request cancelled.')); } catch (ex) { this.alertService.addServerFailure(ex); } } getOperation(op) { if (!op) { return null; } return op && op[this.fragment]; } async deleteDiagnosticsBinary(op) { const operation = this.getOperation(op); if (operation && operation.file) { const { file } = operation; try { const binaryId = this.inventoryBinary.getIdFromUrl(file); const result = await this.inventoryBinary.delete(binaryId); if (result) { this.deleteDiagnosticsFragment(op); } } catch (err) { if (err.res.status === 404) { // In case the file is already deleted via other means we want to delete the fragment this.deleteDiagnosticsFragment(op); } else { const msg = gettext('Could not delete the diagnostic file.'); this.alertService.danger(msg); } } } } async deleteDiagnosticsFragment(op) { const deleteOp = { id: op.id, status: op.status, [this.fragment]: null }; try { const operationAfterUpdate = (await this.operationService.update(deleteOp)).data; assign(op, operationAfterUpdate); this.alertService.success(gettext('Diagnostic file deleted.')); } catch (error) { this.alertService.addServerFailure(error); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsService, deps: [{ token: i1.OperationService }, { token: i1.InventoryBinaryService }, { token: i2.ModalService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.OperationService }, { type: i1.InventoryBinaryService }, { type: i2.ModalService }, { type: i2.AlertService }] }); class DiagnosticsTabGuard { constructor(diagnosticsService) { this.diagnosticsService = diagnosticsService; } canActivate(route) { const device = route.data.contextData || route.parent.data.contextData; return this.diagnosticsService.isSupportedDevice(device); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsTabGuard, deps: [{ token: DiagnosticsService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsTabGuard }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsTabGuard, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: DiagnosticsService }] }); class DiagnosticsComponent { constructor(route, diagnosticService, operationRealtime) { this.route = route; this.diagnosticService = diagnosticService; this.operationRealtime = operationRealtime; this.statusIcons = operationStatusIcons; this.statusClasses = operationStatusClasses; this.deviceId = this.route.snapshot.parent.data.contextData.id; this.device$ = new BehaviorSubject(this.route.snapshot.parent.data.contextData); this.operations$ = this.diagnosticService.getOperations$(this.device$); this.operationsPipe = pipe(map(ops => ops.filter(op => op[this.diagnosticService.fragment]))); this.realtimeOptions = { entityOrId: this.deviceId, removeOnUpdate: true, insertOnUpdate: true }; } onDiagnosticRequest() { this.diagnosticService.createOperation(this.deviceId); } onDelete(operation) { this.diagnosticService.deleteOperation(operation); } onCancel(operation) { this.diagnosticService.cancelOperation(operation); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: DiagnosticsService }, { token: i2.OperationRealtimeService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DiagnosticsComponent, isStandalone: true, selector: "c8y-diagnostics", ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Request diagnostic file' | translate }}\"\n (click)=\"onDiagnosticRequest()\"\n >\n <i c8yIcon=\"stethoscope\"></i>\n <span translate>Request diagnostic file</span>\n </button>\n</c8y-action-bar-item>\n\n<div\n class=\"page-sticky-header hidden-xs c8y-list__item c8y-list--timeline\"\n *ngIf=\"operationCount > 0\"\n>\n <div class=\"d-flex\">\n <div class=\"c8y-list--timeline__item__date a-s-center\">\n <label>{{ 'Date' | translate }}</label>\n </div>\n <div class=\"c8y-list__item__block flex-grow\">\n <div class=\"c8y-list__item__icon\">\n <i class=\"p-l-24\"></i>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-40\">\n <div class=\"col-4\">{{ 'Event' | translate }}</div>\n <div class=\"col-5 m-l-8\">{{ 'File' | translate }}</div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<c8y-list-group>\n <ng-template\n c8yFor\n let-operation\n [c8yForOf]=\"operations$\"\n [c8yForPipe]=\"operationsPipe\"\n [c8yForRealtime]=\"operationRealtime\"\n [c8yForRealtimeOptions]=\"realtimeOptions\"\n (c8yForCount)=\"operationCount = $event\"\n >\n <c8y-li-timeline>\n {{ operation.creationTime | c8yDate }}\n <c8y-li>\n <c8y-li-icon>\n <i\n [c8yIcon]=\"statusIcons[operation.status]\"\n [ngClass]=\"statusClasses[operation.status]\"\n [tooltip]=\"operation.status?.toString() | translate\"\n ></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-4\">\n <p class=\"text-truncate-wrap\" title=\"{{ operation.description | translate }}\">\n {{ operation.description | translate }}\n </p>\n </div>\n <div class=\"col-5\" *ngIf=\"operation.c8y_DiagnosticReport?.file\">\n <div class=\"text-truncate-wrap m-t-xs-8\">\n <span class=\"text-label-small visible-xs\" translate>File</span>\n <span title=\"{{ operation.c8y_DiagnosticReport.file }}\">\n <c8y-file-download\n url=\"{{ operation.c8y_DiagnosticReport.file }}\"\n ></c8y-file-download>\n </span>\n </div>\n </div>\n </c8y-li-body>\n <c8y-li-action\n (click)=\"onCancel(operation)\"\n *ngIf=\"operation.status === 'PENDING'\"\n icon=\"times\"\n label=\"{{ 'Cancel' | translate }}\"\n ></c8y-li-action>\n <c8y-li-action\n (click)=\"onDelete(operation)\"\n *ngIf=\"operation.status === 'SUCCESSFUL'\"\n icon=\"delete\"\n label=\"{{ 'Delete' | translate }}\"\n ></c8y-li-action>\n </c8y-li>\n </c8y-li-timeline>\n </ng-template>\n</c8y-list-group>\n\n<!-- EMPTY STATE -->\n\n<c8y-ui-empty-state\n *ngIf=\"operationCount === 0\"\n [icon]=\"'stethoscope'\"\n [title]=\"'No diagnostic files available.' | translate\"\n></c8y-ui-empty-state>\n", dependencies: [{ kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: 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: ListItemTimelineComponent, selector: "c8y-list-item-timeline, c8y-li-timeline" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: FileDownloadComponent, selector: "c8y-file-download", inputs: ["url"] }, { kind: "component", type: ListItemActionComponent, selector: "c8y-list-item-action, c8y-li-action", inputs: ["label", "icon", "disabled"], outputs: ["click"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-diagnostics', imports: [ ActionBarItemComponent, IconDirective, C8yTranslateDirective, NgIf, ListGroupComponent, ForOfDirective, ListItemTimelineComponent, ListItemComponent, ListItemIconComponent, NgClass, TooltipDirective, ListItemBodyComponent, FileDownloadComponent, ListItemActionComponent, EmptyStateComponent, C8yTranslatePipe, DatePipe ], template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n type=\"button\"\n title=\"{{ 'Request diagnostic file' | translate }}\"\n (click)=\"onDiagnosticRequest()\"\n >\n <i c8yIcon=\"stethoscope\"></i>\n <span translate>Request diagnostic file</span>\n </button>\n</c8y-action-bar-item>\n\n<div\n class=\"page-sticky-header hidden-xs c8y-list__item c8y-list--timeline\"\n *ngIf=\"operationCount > 0\"\n>\n <div class=\"d-flex\">\n <div class=\"c8y-list--timeline__item__date a-s-center\">\n <label>{{ 'Date' | translate }}</label>\n </div>\n <div class=\"c8y-list__item__block flex-grow\">\n <div class=\"c8y-list__item__icon\">\n <i class=\"p-l-24\"></i>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"content-flex-40\">\n <div class=\"col-4\">{{ 'Event' | translate }}</div>\n <div class=\"col-5 m-l-8\">{{ 'File' | translate }}</div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<c8y-list-group>\n <ng-template\n c8yFor\n let-operation\n [c8yForOf]=\"operations$\"\n [c8yForPipe]=\"operationsPipe\"\n [c8yForRealtime]=\"operationRealtime\"\n [c8yForRealtimeOptions]=\"realtimeOptions\"\n (c8yForCount)=\"operationCount = $event\"\n >\n <c8y-li-timeline>\n {{ operation.creationTime | c8yDate }}\n <c8y-li>\n <c8y-li-icon>\n <i\n [c8yIcon]=\"statusIcons[operation.status]\"\n [ngClass]=\"statusClasses[operation.status]\"\n [tooltip]=\"operation.status?.toString() | translate\"\n ></i>\n </c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-4\">\n <p class=\"text-truncate-wrap\" title=\"{{ operation.description | translate }}\">\n {{ operation.description | translate }}\n </p>\n </div>\n <div class=\"col-5\" *ngIf=\"operation.c8y_DiagnosticReport?.file\">\n <div class=\"text-truncate-wrap m-t-xs-8\">\n <span class=\"text-label-small visible-xs\" translate>File</span>\n <span title=\"{{ operation.c8y_DiagnosticReport.file }}\">\n <c8y-file-download\n url=\"{{ operation.c8y_DiagnosticReport.file }}\"\n ></c8y-file-download>\n </span>\n </div>\n </div>\n </c8y-li-body>\n <c8y-li-action\n (click)=\"onCancel(operation)\"\n *ngIf=\"operation.status === 'PENDING'\"\n icon=\"times\"\n label=\"{{ 'Cancel' | translate }}\"\n ></c8y-li-action>\n <c8y-li-action\n (click)=\"onDelete(operation)\"\n *ngIf=\"operation.status === 'SUCCESSFUL'\"\n icon=\"delete\"\n label=\"{{ 'Delete' | translate }}\"\n ></c8y-li-action>\n </c8y-li>\n </c8y-li-timeline>\n </ng-template>\n</c8y-list-group>\n\n<!-- EMPTY STATE -->\n\n<c8y-ui-empty-state\n *ngIf=\"operationCount === 0\"\n [icon]=\"'stethoscope'\"\n [title]=\"'No diagnostic files available.' | translate\"\n></c8y-ui-empty-state>\n" }] }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: DiagnosticsService }, { type: i2.OperationRealtimeService }] }); class DiagnosticsModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsModule, imports: [CoreModule, RouterModule, CommonModule, ListGroupModule, SharedRepositoryModule, BsDropdownModule, TooltipModule, DiagnosticsComponent], exports: [DiagnosticsComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsModule, providers: [ DiagnosticsService, BsDropdownConfig, DiagnosticsTabGuard, hookRoute({ context: ViewContext.Device, path: 'diagnostics', component: DiagnosticsComponent, label: gettext('Diagnostics'), icon: 'stethoscope', canActivate: [DiagnosticsTabGuard], priority: 200 }) ], imports: [CoreModule, RouterModule, CommonModule, ListGroupModule, SharedRepositoryModule, BsDropdownModule, TooltipModule, DiagnosticsComponent] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DiagnosticsModule, decorators: [{ type: NgModule, args: [{ imports: [ CoreModule, RouterModule, CommonModule, ListGroupModule, SharedRepositoryModule, BsDropdownModule, TooltipModule, DiagnosticsComponent ], exports: [DiagnosticsComponent], providers: [ DiagnosticsService, BsDropdownConfig, DiagnosticsTabGuard, hookRoute({ context: ViewContext.Device, path: 'diagnostics', component: DiagnosticsComponent, label: gettext('Diagnostics'), icon: 'stethoscope', canActivate: [DiagnosticsTabGuard], priority: 200 }) ] }] }] }); /** * Generated bundle index. Do not edit. */ export { DiagnosticsComponent, DiagnosticsModule, DiagnosticsService, DiagnosticsTabGuard }; //# sourceMappingURL=c8y-ngx-components-diagnostics.mjs.map