import { Component, Input, OnChanges, SimpleChanges, OnInit, ViewChild } from '@angular/core'; import { InfraService, InfraHost, InfraZone, Infra } from '@overflow/commons-typescript/model/infra'; import { Observable, of } from 'rxjs'; import { catchError, exhaustMap, map, tap, take } from 'rxjs/operators'; import { TreeNode, MenuItem, ContextMenu } from 'primeng/primeng'; import { PageParams, Page } from '@overflow/commons-typescript/core/model'; import { ProbeHost, MetaInfraTypeEnum } from '@overflow/commons-typescript'; import { InfraService as InfraCRUDService } from '../service/infra.service'; @Component({ selector: 'of-infra-tree', templateUrl: './infra-tree.component.html', }) export class InfraTreeComponent implements OnInit, OnChanges { @Input() probeHost: ProbeHost; infras: Infra[]; pending$: Observable; error$: Observable; zoneNode: TreeNode[]; hostNode: TreeNode[]; contextMenuZone: MenuItem[]; contextMenuHost: MenuItem[]; contextMenuService: MenuItem[]; selectedNode: TreeNode; @ViewChild('cmZone') cmZone: ContextMenu; @ViewChild('cmHost') cmHost: ContextMenu; @ViewChild('cmService') cmService: ContextMenu; constructor( private infraService: InfraCRUDService, ) { } ngOnInit(): void { this.initContextMenu(); } initContextMenu() { this.contextMenuZone = [ { label: 'Zone Menu', command: (event) => this.cmZone.hide() }, { separator: true }, { label: 'Discovery', icon: 'fa-plus', command: (event) => alert('Discovery') }, ]; this.contextMenuHost = [ { label: 'Host Menu', command: (event) => this.cmHost.hide() }, { separator: true }, { label: 'Add sensor', icon: 'fa-plus', command: (event) => alert('Add sensor') }, { label: 'Traceroute', icon: 'fa-plus' }, { label: 'ARP Test', icon: 'fa-plus' }, ]; this.contextMenuService = [ { label: 'Service Menu', command: (event) => this.cmService.hide() }, { separator: true }, { label: 'Add sensor', icon: 'fa-plus', command: (event) => alert('Add sensor') }, ]; } ngOnChanges(changes: SimpleChanges): void { if (changes['probeHost'].isFirstChange) { this.zoneNode = []; this.hostNode = []; this.getInfras(); } } getInfras() { const pageParams: PageParams = { pageNo: 0, countPerPage: 99999, sortCol: 'id', sortDirection: 'descending' }; this.infraService.readAllByProbeID(this.probeHost.probe.id, pageParams) .pipe( tap(() => { this.pending$ = of(true); }), map((infraPage: Page) => { this.infras = infraPage.content; console.log(this.infras); this.generateTreeData(this.infras); }), catchError(error => { this.error$ = of(error); return of(); }), tap(() => { this.pending$ = of(false); }), take(1), ).subscribe(); } generateTreeData(infras: Infra[]) { infras.forEach(infra => { switch (infra.metaInfraType.key) { case MetaInfraTypeEnum.ZONE: this.addZone(infra); break; case MetaInfraTypeEnum.HOST: this.addHost(infra); break; case MetaInfraTypeEnum.HOST: this.addService(infra); break; default: break; } }); } addZone(infraZone: InfraZone) { this.zoneNode.push({ label: infraZone.network + '(' + infraZone.iface + ')', type: 'ZONE', data: { target: infraZone, subLabel: 'Something to display' }, children: this.hostNode, expanded: true }); } addHost(infraHost: InfraHost) { let ipAddr = infraHost.infraHostIPs[0].address.split('/')[0]; if (infraHost.infraHostOS && infraHost.infraHostOS.name) { ipAddr += '(' + infraHost.infraHostOS.name + ')'; } this.hostNode.push({ type: 'HOST', label: ipAddr, data: { target: infraHost, }, expanded: true, children: [] }); } addService(infraService: InfraService) { const idx = this.findHostIndex(infraService); if (idx === -1) { // this.addHost(infraService.infraHost); // this.addService(infraService); return; } this.hostNode[idx].children.push({ type: 'SERVICE', label: 'TODO', data: { target: infraService }, }); } findHostIndex(infraService: InfraService): number { let idx = -1; this.hostNode.forEach((node, index) => { const infraHost: InfraHost = node.data.target; for (const infraHostIP of infraHost.infraHostIPs) { if (infraHostIP.id === infraService.infraHostPort.infraHostIP.id) { idx = index; return; } } }); return idx; } showContextMenu(event: MouseEvent, node: any) { this.selectedNode = node; this.cmZone.hide(); this.cmHost.hide(); this.cmService.hide(); if (node.type === 'ZONE') { this.cmZone.show(event); } else if (node.type === 'HOST') { this.cmHost.show(event); } else if (node.type === 'SERVICE') { this.cmService.show(event); } return false; } }