UNPKG

@c8y/apps

Version:

Cumulocity IoT applications

98 lines (88 loc) 3.34 kB
import { Injectable } from '@angular/core'; import { EventService } from '@c8y/client'; import { IEvent } from '@c8y/client'; import { DynamicComponentAlert, DynamicDetailsResolver, DynamicResolverService } from '@c8y/ngx-components'; import { uniq } from 'lodash'; import { Observable } from 'rxjs'; import { filter, map, mergeMap, share, take, tap } from 'rxjs/operators'; /** * A DynamicDetailsResolver responsible to resolve a configured event for dynamic components. * This service implements bulk resolving. We are sadly not able to query multiple events by * id at the same time, so we have to perform a request per id. * Still we are able to reduce the number of requests, since events with the same id in one * bulk will only be loaded once. * The SimpleDynamicEventResolver could be used as an alternative. */ @Injectable({ providedIn: 'root' }) export class DynamicEventResolver implements DynamicDetailsResolver<IEvent> { protected eventIds = new Map<number, string[]>(); protected bulkResolve: Observable<{ result: IEvent[]; bulkRequestId: number }>; constructor(protected dynamicResolver: DynamicResolverService, protected events: EventService) { this.bulkResolve = this.dynamicResolver.bulkResolvingTrigger$.pipe( map(bulkRequestId => ({ uniqIds: uniq(this.eventIds.get(bulkRequestId) || []), bulkRequestId })), tap(({ bulkRequestId }) => this.eventIds.delete(bulkRequestId)), mergeMap(({ uniqIds, bulkRequestId }) => this.loadEvents(uniqIds, bulkRequestId)), share() ); } resolve( config: any, attribute: string, bulkRequestId: number ): IEvent | Promise<IEvent> | Observable<IEvent | DynamicComponentAlert<IEvent>> { const storedEvent: IEvent = config[attribute]; if (!storedEvent) { return; } this.addEventId(bulkRequestId, `${storedEvent.id}`); return this.bulkResolve.pipe( filter(({ bulkRequestId: requestId }) => bulkRequestId === requestId), take(1), map( ({ result: updatedEvents }) => updatedEvents.find(updatedEvent => updatedEvent.id === storedEvent.id) || new DynamicComponentAlert({ text: `Unable to retrieve Event "${storedEvent.text}" (${storedEvent.id})`, type: 'danger', unresolvedData: storedEvent }) ) ); } serialize(config: any, attribute: string) { if (!config[attribute]) { return; } const { text, id } = config[attribute]; return { text, id }; } protected addEventId(bulkRequestId: number, eventId: string) { let eventIdsOfRequest = this.eventIds.get(bulkRequestId); if (!eventIdsOfRequest) { eventIdsOfRequest = []; this.eventIds.set(bulkRequestId, eventIdsOfRequest); } eventIdsOfRequest.push(eventId); } protected async loadEvents(eventIds: string[], bulkRequestId: number) { const promises = eventIds.map(eventId => this.loadSingleEvent(eventId)); const result = await Promise.all(promises); const filteredResult = result.filter(event => !!event); return { result: filteredResult, bulkRequestId }; } protected async loadSingleEvent(eventId: string) { try { const { data: event } = await this.events.detail(eventId); return event; } catch { return; } } }