UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

309 lines (300 loc) 14.8 kB
import * as i0 from '@angular/core'; import { Injectable, NgModule } from '@angular/core'; import * as i1 from '@c8y/ngx-components'; import { gettext, CoreModule, ManagedObjectRealtimeService, DeviceBootstrapRealtimeService } from '@c8y/ngx-components'; import * as i2 from '@c8y/client'; import { DeviceRegistrationStatus } from '@c8y/client'; import { set, pick, get } from 'lodash-es'; import { BehaviorSubject, Subject, merge, interval } from 'rxjs'; import { filter, switchMap, map, takeUntil, tap, distinctUntilChanged } from 'rxjs/operators'; import { downgradeInjectable } from '@angular/upgrade/static'; import * as angular from 'angular'; import { registerNgModule } from '@c8y/ng1-modules'; var DataBrokerConnectorStatus; (function (DataBrokerConnectorStatus) { DataBrokerConnectorStatus["ACTIVE"] = "ACTIVE"; DataBrokerConnectorStatus["SUSPENDED"] = "SUSPENDED"; DataBrokerConnectorStatus["WAITING"] = "WAITING"; })(DataBrokerConnectorStatus || (DataBrokerConnectorStatus = {})); class SubscriptionStatusViewModelFactory { build(status) { let statusViewModel = null; switch (status) { case DataBrokerConnectorStatus.ACTIVE: // dataBrokerConnectorsSvc.STATUS.ACTIVE.value statusViewModel = { icon: 'check-circle', textClass: 'text-success', text: gettext('Active`data broker subscription`') }; break; case DataBrokerConnectorStatus.SUSPENDED: // dataBrokerConnectorsSvc.STATUS.SUSPENDED.value statusViewModel = { icon: 'exclamation-triangle', textClass: 'text-warning', text: gettext('Inactive`data broker subscription`') }; break; case DataBrokerConnectorStatus.WAITING: // dataBrokerConnectorsSvc.STATUS.WAITING.value statusViewModel = { icon: 'spinner', iconClass: 'icon-spin', textClass: 'text-warning', text: gettext('Waiting`data broker subscription`') }; break; default: break; } return statusViewModel; } } class NewDeviceRequestStatusFactory { build(status) { let result = null; switch (status) { case DeviceRegistrationStatus.WAITING_FOR_CONNECTION: result = { name: DeviceRegistrationStatus.WAITING_FOR_CONNECTION, label: gettext('Waiting for connection`data broker subscription`'), value: DeviceRegistrationStatus.WAITING_FOR_CONNECTION }; break; case DeviceRegistrationStatus.PENDING_ACCEPTANCE: result = { name: DeviceRegistrationStatus.PENDING_ACCEPTANCE, label: gettext('Pending acceptance`data broker subscription`'), value: DeviceRegistrationStatus.PENDING_ACCEPTANCE }; break; case DeviceRegistrationStatus.ACCEPTED: result = { name: DeviceRegistrationStatus.ACCEPTED, label: gettext('Accepted`data broker subscription`'), value: DeviceRegistrationStatus.ACCEPTED }; case DeviceRegistrationStatus.BLOCKED: result = { name: DeviceRegistrationStatus.BLOCKED, label: gettext('Blocked`data broker subscription`'), value: DeviceRegistrationStatus.BLOCKED }; break; } return result; } } class DataBrokerSubscriptionsService { constructor(moRealtimeService, deviceBootstrapRealtimeService, inventoryService, userService, deviceRegistrationService, appStateService) { this.moRealtimeService = moRealtimeService; this.deviceBootstrapRealtimeService = deviceBootstrapRealtimeService; this.inventoryService = inventoryService; this.userService = userService; this.deviceRegistrationService = deviceRegistrationService; this.appStateService = appStateService; this.FRAGMENT_TYPE = 'c8y_BrokerSource'; this.NEW_DEVICE_REQUEST_TYPE = 'c8y_DataBroker'; /** * inventory polling interval */ this.POLL_INTERVAL_FOR_SUBSCRIPTIONS = 15000; this.moRealtimeSubscriptionsMap = new Map(); this.refreshPendingTrigger$ = new BehaviorSubject(null); this.filters = { fragmentType: this.FRAGMENT_TYPE, pageSize: 2000 }; this.subscriptionStatusViewModelFactory = new SubscriptionStatusViewModelFactory(); this.newDeviceRequestStatusViewModelFactory = new NewDeviceRequestStatusFactory(); // Build legacy enum structure for ng1 component this.NEW_DEVICE_REQUEST_STATUS = this.generateDeviceRequestStatusEnum(this.newDeviceRequestStatusViewModelFactory); } async getBrokerSubscriptionsList() { return (await this.inventoryService.list(this.filters)).data; } /** * User status text (legacy compatibility) */ getVisibleUserStatusText(user) { return user.enabled ? gettext('active`subscription`') : gettext('inactive`subscription`'); } async remove(subscription) { // handle realtime unsubsribe if (this.moRealtimeSubscriptionsMap.has(subscription.id)) { this.moRealtimeSubscriptionsMap.get(subscription.id).unsubscribe(); this.moRealtimeSubscriptionsMap.delete(subscription.id); } // handle removal const brokerSourceRenamed = `_${this.FRAGMENT_TYPE}`; set(subscription, this.FRAGMENT_TYPE, null); return await this.inventoryService.update(pick(subscription, ['id', this.FRAGMENT_TYPE, brokerSourceRenamed])); } async setStatus(subscription, enabled) { const userData = (await this.userService.update({ id: subscription.userId, enabled })).data; subscription.userEnabled = userData.enabled; subscription.visibleUserStatus = this.getVisibleUserStatusText(userData); return subscription; } /** * List of pending subscriptions */ async listPendingBrokerSubscriptions() { return (await this.deviceRegistrationService.list({ pageSize: 2000, withTotalPages: true })).data; } /** * Accept subscription */ async accept(code) { return (await this.deviceRegistrationService.accept(code)).data; } /** * Discard subscription */ async discard(code) { return await this.deviceRegistrationService.delete(code); } /** * Add new subscription */ async create(code) { return (await this.deviceRegistrationService.create({ id: code, type: this.NEW_DEVICE_REQUEST_TYPE })).data; } getForNg1({ pollingInterval, onPendingSubscriptions, onExistingSubscriptions, onMoUpdate }) { const reload$ = new Subject(); const destroy$ = new Subject(); const ready$ = new Subject(); const unsubscribeRealtime = () => { const moRealtimeSubscriptionIterator = this.moRealtimeSubscriptionsMap.keys(); let key = moRealtimeSubscriptionIterator.next().value; while (this.moRealtimeSubscriptionsMap.has(key)) { this.moRealtimeSubscriptionsMap.get(key).unsubscribe(); this.moRealtimeSubscriptionsMap.delete(key); key = moRealtimeSubscriptionIterator.next().value; } }; const userInitialized$ = this.appStateService.currentUser.pipe(filter(currentUser => currentUser !== null)); const triggers = merge(reload$, ready$); const pendingSubscriptions$ = merge(triggers, this.deviceBootstrapRealtimeService.onAll$(), this.refreshPendingTrigger$).pipe(switchMap(() => userInitialized$), switchMap(() => this.listPendingBrokerSubscriptions()), map(pendingSubscriptions => this.convertDeviceRegistrationsToSubscriptionViewModels(pendingSubscriptions)), takeUntil(destroy$)); const existingSubscriptions$ = merge(triggers, interval(pollingInterval)).pipe(switchMap(() => userInitialized$), switchMap(() => this.getBrokerSubscriptionsList()), tap(mos => { if (this.subscriptionsCount !== mos.length) { this.refreshPendingTrigger$.next(); this.subscriptionsCount = mos.length; } mos.forEach(mo => { if (!this.moRealtimeSubscriptionsMap.has(mo.id)) { const mortObservable = this.moRealtimeService .onUpdate$(mo.id) .pipe(switchMap(mo => this.convertToViewModel([mo]))); this.moRealtimeSubscriptionsMap.set(mo.id, mortObservable.subscribe(onMoUpdate)); } }); }), distinctUntilChanged(), switchMap(mos => this.convertToViewModel(mos)), takeUntil(destroy$)); return { init() { pendingSubscriptions$.subscribe(onPendingSubscriptions); existingSubscriptions$.subscribe(onExistingSubscriptions); setTimeout(() => { ready$.next(); }, 1000); }, reload() { reload$.next(); }, destroy() { destroy$.next(); destroy$.complete(); unsubscribeRealtime(); } }; } convertDeviceRegistrationsToSubscriptionViewModels(pendingSubscriptions) { const convertedToViewModel = pendingSubscriptions .filter(deviceRequest => deviceRequest.type === this.NEW_DEVICE_REQUEST_TYPE) .map(deviceRequest => { return Object.assign({}, get(deviceRequest, 'customProperties.c8y_BrokerSource'), { status: this.newDeviceRequestStatusViewModelFactory.build(deviceRequest.status), type: deviceRequest.type, id: deviceRequest.id }); }); return convertedToViewModel; } generateDeviceRequestStatusEnum(newDeviceRequestViewModelFactory) { const result = {}; for (const status in DeviceRegistrationStatus) { Object.defineProperty(result, status, { enumerable: true, writable: false, configurable: false, value: newDeviceRequestViewModelFactory.build(status) }); } return result; } // Function maps data in suitable manner to have it easier to display. Used in service mainly for compatibility async convertToViewModel(subscriptions) { const viewModelSubscriptions = subscriptions.map(async (subscription) => { const { data: userDetails } = await this.userService.detail(subscription.owner); return { userEnabled: userDetails.enabled, visibleUserStatus: this.getVisibleUserStatusText(userDetails), //TODO:IIAR should be extracted to ngx pipe when the rest of data-broker is migrated userId: userDetails.id, status: this.getStatusViewModel(subscription.c8y_BrokerSource.status), //TODO:IIAR should be extracted to ngx pipe when the rest of data-broker is migrated id: subscription.id, _c8y_BrokerSource: subscription.c8y_BrokerSource }; }); return Promise.all(viewModelSubscriptions); } // Status decoration (legacy compatibility) getStatusViewModel(status) { return this.subscriptionStatusViewModelFactory.build(status); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerSubscriptionsService, deps: [{ token: i1.ManagedObjectRealtimeService }, { token: i1.DeviceBootstrapRealtimeService }, { token: i2.InventoryService }, { token: i2.UserService }, { token: i2.DeviceRegistrationService }, { token: i1.AppStateService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerSubscriptionsService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerSubscriptionsService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.ManagedObjectRealtimeService }, { type: i1.DeviceBootstrapRealtimeService }, { type: i2.InventoryService }, { type: i2.UserService }, { type: i2.DeviceRegistrationService }, { type: i1.AppStateService }] }); class DataBrokerModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerModule, imports: [CoreModule] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerModule, providers: [ DataBrokerSubscriptionsService, ManagedObjectRealtimeService, DeviceBootstrapRealtimeService ], imports: [CoreModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DataBrokerModule, decorators: [{ type: NgModule, args: [{ declarations: [], imports: [CoreModule], providers: [ DataBrokerSubscriptionsService, ManagedObjectRealtimeService, DeviceBootstrapRealtimeService ], exports: [] }] }] }); const dataBrokerSubscriptionsServiceDowngradedInjectable = downgradeInjectable(DataBrokerSubscriptionsService); const NAME_DATA_BROKER = 'c8y.upgrade.dataBroker'; angular .module(NAME_DATA_BROKER, []) .service('c8yDataBrokerSubscriptionsService', dataBrokerSubscriptionsServiceDowngradedInjectable); const ng1ModulesDataBroker = [NAME_DATA_BROKER]; registerNgModule(ng1ModulesDataBroker); /** * Generated bundle index. Do not edit. */ export { DataBrokerModule, dataBrokerSubscriptionsServiceDowngradedInjectable, ng1ModulesDataBroker }; //# sourceMappingURL=c8y-ngx-components-data-broker.mjs.map