@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
309 lines (300 loc) • 14.8 kB
JavaScript
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