| /******************************************************************************** |
| * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| ********************************************************************************/ |
| |
| import { Component, OnInit, OnDestroy } from '@angular/core'; |
| import { NavigatorService } from 'src/app/navigator/navigator.service'; |
| import { MDMNotificationService } from 'src/app/core/mdm-notification.service'; |
| import { Node } from '../../../navigator/node'; |
| import { TYPE_CHANNEL, TYPE_CHANNELGROUP, TYPE_MEASUREMENT } from '../../model/constants'; |
| import { Subscription, concat, forkJoin, zip, of } from 'rxjs'; |
| import { NodeService } from 'src/app/navigator/node.service'; |
| import { map, flatMap, tap } from 'rxjs/operators'; |
| import { MDMItem } from 'src/app/core/mdm-item'; |
| import { ChartViewerService } from '../../services/chart-viewer.service'; |
| import { ArrayUtilService } from 'src/app/core/services/array-util.service'; |
| |
| @Component({ |
| selector: 'app-xy-chart-viewer-nav-card', |
| templateUrl: './xy-chart-viewer-nav-card.component.html' |
| }) |
| export class XyChartViewerNavCardComponent implements OnInit, OnDestroy { |
| |
| public channels = new Map<string, Node[]>(); |
| public channelGroups: Node[]; |
| public measurement: Node; |
| |
| // Subscriptions |
| private selectedNodeSub: Subscription; |
| private selectedNode: Node; |
| |
| constructor( |
| private navigatorService: NavigatorService, |
| private notificationService: MDMNotificationService, |
| private nodeService: NodeService, |
| private chartViewerService: ChartViewerService) {} |
| |
| ngOnInit() { |
| this.selectedNodeChanged(this.navigatorService.getSelectedNode()); |
| this.selectedNodeSub = this.navigatorService.selectedNodeChanged.subscribe( |
| node => this.selectedNodeChanged(node), |
| error => this.notificationService.notifyError('details.mdm-detail-view.cannot-update-node', error) |
| ); |
| } |
| |
| ngOnDestroy() { |
| this.selectedNodeSub.unsubscribe(); |
| } |
| |
| /** |
| * @TODO remove |
| */ |
| onClick() { |
| const item = new MDMItem('MDMCRASH', 'Measurement', '180'); |
| setTimeout(() => this.navigatorService.fireOnOpenInTree([item])); |
| } |
| |
| /** |
| * Handle node selection in navigation tree. |
| * Loads necessary data for xy chart, if not present: |
| * - Measurement: |
| * + Loaded if a channel or channelgroup is selected that is not present. |
| * + Also loads all channels and channelgroups for that measurement. |
| * - Channelgroups: |
| * + Loaded if a measurement is selected/loaded that is not present. |
| * + Also loads all channels for all newly loaded channelgroups. |
| * - Channels: |
| * + Allways loaded if some node is not present. |
| * |
| * @param node the selected node |
| */ |
| private selectedNodeChanged(node: Node) { |
| this.selectedNode = node; |
| if (node != undefined) { |
| switch (node.type) { |
| case TYPE_MEASUREMENT: |
| this.selectedMeasurement(node); |
| break; |
| case TYPE_CHANNELGROUP: |
| this.selectedChannelGroup(node); |
| break; |
| case TYPE_CHANNEL: |
| this.selectedChannel(node); |
| break; |
| } |
| } |
| } |
| |
| // reload all, if channel is not present yet. |
| private selectedChannel(node: Node) { |
| if (!this.isChannelPresent(node)) { |
| this.loadMeasurement(node); |
| } else { |
| this.chartViewerService.sendNodeMeta(this.selectedNode); |
| } |
| } |
| |
| private selectedChannelGroup(node: Node) { |
| if (this.isChannelGroupPresent(node)) { |
| this.loadMeasurement(node); |
| } else { |
| this.chartViewerService.sendNodeMeta(this.selectedNode); |
| } |
| } |
| |
| private selectedMeasurement(node: Node) { |
| if (this.measurement == undefined || this.measurement.id !== node.id) { |
| this.measurement = node; |
| this.loadChannelGroups(node); |
| } else { |
| this.chartViewerService.sendNodeMeta(this.selectedNode); |
| } |
| } |
| |
| private isChannelPresent(node: Node) { |
| if (this.channels != undefined) { |
| /** |
| * @TODO more readable code, but got the impression that performance is bad. Read up on performance topic in depth. |
| */ |
| // Array.from(this.channels.values()) |
| // .reduce((a,b) => a.concat(b), []) |
| // .findIndex(c => c.id === node.id); |
| let index = -1; |
| const iterator = this.channels.values(); |
| let res = iterator.next(); |
| while (index === -1 && !res.done) { |
| index = res.value.findIndex(c => c.id === node.id); |
| res = iterator.next(); |
| } |
| return index > -1; |
| } |
| return false; |
| } |
| |
| private isChannelGroupPresent(node: Node) { |
| if (this.channelGroups != undefined) { |
| return this.channelGroups.findIndex(channelGroup => channelGroup.id === node.id) > -1; |
| } |
| return false; |
| } |
| |
| private loadMeasurement(node: Node) { |
| this.searchNodes(node, TYPE_MEASUREMENT) |
| .pipe( |
| /** @TODO in general true? */ |
| // parent measurement must be distinct |
| map(measurements => measurements[0]), |
| ).subscribe(measurement => { |
| this.measurement = measurement; |
| this.loadChannelGroups(this.measurement); |
| }); |
| } |
| |
| private loadChannelGroups(measurement: Node) { |
| this.searchNodes(measurement, TYPE_CHANNELGROUP) |
| .subscribe(channelGroups => { |
| this.channelGroups = channelGroups; |
| if (this.channelGroups != undefined) { |
| this.loadChannels(channelGroups); |
| } |
| }); |
| } |
| |
| // private load(node: Node) { |
| // this.searchNodes(node, TYPE_MEASUREMENT) |
| // .pipe( |
| // /** @TODO in general true? */ |
| // // parent measurement must be distinct |
| // map(measurements => measurements[0]), |
| // tap(measurement => this.measurement = measurement), |
| // flatMap(measurement => this.searchNodes(measurement, TYPE_CHANNELGROUP)), |
| // tap(channelGroups => this.channelGroups = channelGroups), |
| // flatMap(channelGroups => forkJoin(channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL)))), |
| // map(n => n.map((x, i) => ({group: channelGroups[i], channels: x}))) |
| |
| // ).subscribe(measurement => { |
| // this.measurement = measurement; |
| // this.loadChannelGroups(this.measurement); |
| // }); |
| // } |
| |
| private loadChannels(channelGroups: Node[]) { |
| let obsArray = channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL)); |
| forkJoin(obsArray).pipe( |
| tap(array => array.forEach((channels, index) => this.channels.set(channelGroups[index].id, channels))) |
| ).subscribe(datasets => this.chartViewerService.sendNodeMeta(this.selectedNode)); |
| |
| // forkJoin(obsArray).pipe( |
| // map(n => n.map((x, i) => ({group: channelGroups[i], channels: x}))) |
| // ).subscribe(datasets => { |
| // datasets.forEach(data => this.channels.set(data.group.id, data.channels)); |
| // this.chartViewerService.sendNodeMeta(this.selectedNode); |
| // } |
| // ); |
| |
| // forkJoin(obsArray) |
| // .pipe( |
| // flatMap(channelsArray => zip(channelGroups, channelsArray)) |
| // ) |
| // .subscribe(([cg, channels]) => { |
| // console.log('everevver???'); |
| // console.log(cg); |
| // console.log(channels) |
| // this.channels.set(cg.id, channels)}); |
| // return forkJoin(channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL))); |
| } |
| |
| |
| // private loadChannels2(channelGroups: Node[]) { |
| // channelGroups.forEach(channelGroup => |
| // this.searchNodes(channelGroup, TYPE_CHANNEL) |
| // .subscribe(channels => this.channels.set(channelGroup.id, channels)) |
| // ); |
| // } |
| |
| private searchNodes(node: Node, targetType: string) { |
| const filter = 'filter=' + node.type + '.Id eq \"' + node.id + '\"'; |
| return this.nodeService.searchNodes(filter, node.sourceName, targetType); |
| } |
| |
| } |