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, map, tap, take } from 'rxjs/operators'; import { TreeNode, MenuItem, ContextMenu } from 'primeng/primeng'; import { ProbeHost, MetaInfraTypeEnum, toMetaInfraType } from '@overflow/commons-typescript'; import { InfraService as InfraManageService } from '../service/infra.service'; @Component({ selector: 'of-infra-tree', templateUrl: './infra-tree.component.html', }) export class InfraTreeComponent implements OnInit, OnChanges { @Input() probeHost: ProbeHost; infraZones: InfraZone[]; infraHosts: InfraHost[]; infraServices: InfraService[]; 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: InfraManageService, ) { } 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.getInfraWithInfraTypeKey(toMetaInfraType(MetaInfraTypeEnum.ZONE).key); this.getInfraWithInfraTypeKey(toMetaInfraType(MetaInfraTypeEnum.HOST).key); this.getInfraWithInfraTypeKey(toMetaInfraType(MetaInfraTypeEnum.SERVICE).key); } } getInfraWithInfraTypeKey(metaInfraTypeKey: string) { this.infraService.readAllByMetaInfraTypeKeyAndProbeID( metaInfraTypeKey, this.probeHost.probe.id) .pipe( tap(() => { this.pending$ = of(true); }), map((infras: Infra[]) => { switch (metaInfraTypeKey) { case toMetaInfraType(MetaInfraTypeEnum.ZONE).key: this.infraZones = infras; break; case toMetaInfraType(MetaInfraTypeEnum.HOST).key: this.infraHosts = infras; break; case toMetaInfraType(MetaInfraTypeEnum.SERVICE).key: this.infraServices = infras; break; default: break; } if (this.infraZones && this.infraHosts && this.infraServices) { this.generateTreeData(); } }), catchError(error => { this.error$ = of(error); return of(); }), tap(() => { this.pending$ = of(false); }), take(1), ).subscribe(); } generateTreeData() { if (null === this.infraZones) { return; } this.infraZones.forEach(infraZone => { this.addZone(infraZone); }); if (null === this.infraHosts) { return; } this.infraHosts.forEach(infraHost => { this.addHost(infraHost); }); if (null === this.infraServices) { return; } this.infraServices.forEach(infraService => { this.addService(infraService); }); } 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; } }