This commit is contained in:
crusader 2018-10-12 19:36:02 +09:00
parent 4c630efc84
commit fcd7d9f1b8
3 changed files with 203 additions and 54 deletions

View File

@ -1,5 +1,6 @@
import { Host } from './Host'; import { Host } from './Host';
import { MetaPortType, MetaDiscovererType } from '../meta'; import { MetaPortType, MetaDiscovererType } from '../meta';
import { Service } from './Service';
export interface Port { export interface Port {
metaPortType?: MetaPortType; metaPortType?: MetaPortType;
@ -10,5 +11,5 @@ export interface Port {
discoveredDate?: Date; discoveredDate?: Date;
host?: Host; host?: Host;
// serviceList?: Service[]; serviceList?: Service[];
} }

View File

@ -96,4 +96,10 @@ export class DisplayComponent implements OnInit, AfterContentInit, OnDestroy {
this.store.dispatch(new InfraStore.ChangeSelectedInfra(null)); this.store.dispatch(new InfraStore.ChangeSelectedInfra(null));
} }
otherHostSelected(host: Host) {
this.store.dispatch(new InfraStore.ChangeSelectedInfra({
group: 'host',
infra: host,
}));
}
} }

View File

@ -29,6 +29,7 @@ import * as UILayoutStore from '../../../store/ui/layout';
import { DiscoverySession } from '../../../core/discovery/discovery-session'; import { DiscoverySession } from '../../../core/discovery/discovery-session';
import { DiscoveryMessageType } from 'src/app/core/type'; import { DiscoveryMessageType } from 'src/app/core/type';
import { ConfirmationService } from 'primeng/primeng'; import { ConfirmationService } from 'primeng/primeng';
import { MetaServiceTypeEnum, toMetaServiceTypeEnum } from '@overflow/model/meta/MetaServiceType';
export class DisplaySummary { export class DisplaySummary {
totalHosts: number; totalHosts: number;
@ -91,6 +92,8 @@ export class DisplaySummary {
} }
} }
const FIRE_CLICK_DETAIL = -99999;
@Component({ @Component({
selector: 'app-infra-display-map', selector: 'app-infra-display-map',
templateUrl: './map.component.html', templateUrl: './map.component.html',
@ -106,6 +109,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
zoneNode: Node | null = null; zoneNode: Node | null = null;
nodes: Node[]; nodes: Node[];
links: Link[]; links: Link[];
nodeElements: Map<string, Element>;
selectedNode: Node | null = null; selectedNode: Node | null = null;
@ -209,6 +213,26 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
break; break;
case DiscoveryMessageType.DiscoveryStop: { case DiscoveryMessageType.DiscoveryStop: {
__this.zone.hostList = [];
__this.hosts.forEach(_host => {
if (_host.zone.network === __this.zone.network) {
__this.zone.hostList.push(_host);
}
_host.portList = [];
if (__this.ports.has(_host.address)) {
__this.ports.get(_host.address).forEach(_port => {
_host.portList.push(_port);
_port.serviceList = [];
if (__this.services.has(_host.address) && __this.services.get(_host.address).has(_port.portNumber)) {
__this.services.get(_host.address).get(_port.portNumber).forEach(_service => {
_port.serviceList.push(_service);
});
}
});
}
});
__this.simulationRestart(true); __this.simulationRestart(true);
__this.zoomToFit(0.95, 500); __this.zoomToFit(0.95, 500);
@ -265,7 +289,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
__this.onHideDetail(); __this.onHideDetail();
return; return;
} else { } else {
__this.onInfraSelected(selectedInfra);
} }
}), }),
).subscribe(); ).subscribe();
@ -325,6 +349,7 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
this.nodes = []; this.nodes = [];
this.links = []; this.links = [];
this.nodeElements = new Map();
this.hosts = new Map(); this.hosts = new Map();
this.ports = new Map(); this.ports = new Map();
this.services = new Map(); this.services = new Map();
@ -406,7 +431,8 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
function getNodeFromElement(element: Element): Node | null { function getNodeFromElement(element: Element): Node | null {
const container = d3.select(element); const container = d3.select(element);
const nodeId = container.attr('nodeId'); const nodeId = container.attr('nodeId');
return __this.getNode(nodeId); const { node } = __this.getNode(nodeId);
return node;
} }
// drag // drag
@ -474,13 +500,22 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
return false; return false;
} }
nodeElements.each(function (d) {
const nodeElement = this as Element;
const node = getNodeFromElement(nodeElement);
__this.nodeElements.set(node.id, nodeElement);
});
nodeElements.on('click', function () { nodeElements.on('click', function () {
d3.event.stopPropagation(); d3.event.stopPropagation();
const nodeElement = this as Element; const nodeElement = this as Element;
const node = getNodeFromElement(nodeElement); const node = getNodeFromElement(nodeElement);
if (null === node || 'zone' === node.group) { if (null === node || 'zone' === node.group) {
clearSelection();
if (FIRE_CLICK_DETAIL !== d3.event.detail) {
__this.onInfraClick(node); __this.onInfraClick(node);
}
return; return;
} }
@ -535,16 +570,13 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
}); });
if (FIRE_CLICK_DETAIL !== d3.event.detail) {
__this.onInfraClick(node); __this.onInfraClick(node);
}
}); });
// Highlight // Highlight
const displayInfra = d3.select(this.displayInfraRef.nativeElement); function clearSelection() {
displayInfra.on('click', function () {
__this.selectedNode = null;
__this.store.dispatch(new InfraStore.ChangeSelectedInfra(null));
nodeElements.each(function () { nodeElements.each(function () {
const _thisElement = this as Element; const _thisElement = this as Element;
d3.select(_thisElement).classed('semi-unselected', false); d3.select(_thisElement).classed('semi-unselected', false);
@ -556,6 +588,14 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
d3.select(_thisElement).classed('semi-unselected', false); d3.select(_thisElement).classed('semi-unselected', false);
d3.select(_thisElement).classed('unselected', false); d3.select(_thisElement).classed('unselected', false);
}); });
}
const displayInfra = d3.select(this.displayInfraRef.nativeElement);
displayInfra.on('click', function () {
__this.selectedNode = null;
__this.store.dispatch(new InfraStore.ChangeSelectedInfra(null));
clearSelection();
}); });
nodeElements nodeElements
@ -681,33 +721,63 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
.call(this.zoomBehavior.transform, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale)); .call(this.zoomBehavior.transform, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale));
} }
onInfraClick(node: Node) { onInfraSelected({ group, infra }: { group: string, infra: Host | Port | Service }) {
console.log(node); switch (group) {
case 'zone': {
switch (node.group) { const id = this.getZoneId(infra);
case 'zone': this.fireClickOnNodeElement(id);
const zone: Zone = node.target;
zone.hostList = [];
this.hosts.forEach(_host => {
if (_host.zone.network === zone.network) {
zone.hostList.push(_host);
} }
});
break; break;
case 'host': case 'host': {
const host: Host = node.target; const id = this.getHostId(infra);
host.portList = []; this.fireClickOnNodeElement(id);
if (this.ports.has(host.address)) {
this.ports.get(host.address).forEach(port => {
host.portList.push(port);
});
} }
break;
case 'service': {
const id = this.getServiceId(infra);
this.fireClickOnNodeElement(id);
}
break; break;
default: default:
break; break;
} }
}
fireClickOnNodeElement(nodeId: string) {
const nodeElement = this.nodeElements.get(nodeId);
if (null === nodeElement || (null !== this.selectedNode && nodeId === this.selectedNode.id)) {
return;
}
nodeElement.dispatchEvent(new CustomEvent('click', { detail: FIRE_CLICK_DETAIL }));
}
onInfraClick(node: Node) {
// switch (node.group) {
// case 'zone':
// const zone: Zone = node.target;
// zone.hostList = [];
// this.hosts.forEach(_host => {
// if (_host.zone.network === zone.network) {
// zone.hostList.push(_host);
// }
// });
// break;
// case 'host':
// const host: Host = node.target;
// host.portList = [];
// if (this.ports.has(host.address)) {
// this.ports.get(host.address).forEach(port => {
// host.portList.push(port);
// });
// }
// break;
// default:
// break;
// }
this.store.dispatch(new InfraStore.ChangeSelectedInfra({ this.store.dispatch(new InfraStore.ChangeSelectedInfra({
group: node.group, group: node.group,
@ -739,29 +809,60 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
private getNode(id: string): Node | null { private getNode(id: string): { index: number, node: Node } {
let _n: Node = null; let _n: Node = null;
let _idx = -1;
this.nodes.some((node): boolean => { this.nodes.some((node): boolean => {
_idx++;
if (node.id === id) { if (node.id === id) {
_n = node; _n = node;
return true; return true;
} }
return false; return false;
}); });
return _n; return { index: null === _n ? -1 : _idx, node: _n };
} }
private getLink(source: Node, target: Node): { index: number, link: Link } | null {
let _l: Link = null;
let _idx = -1;
this.links.some((link): boolean => {
_idx++;
if (link.source.id === source.id && link.target.id === target.id) {
_l = link;
return true;
}
return false;
});
return { index: null === _l ? -1 : _idx, link: _l };
}
refreshInfraDisplay(zone: Zone, hosts: Host[], services: Service[]) { refreshInfraDisplay(zone: Zone, hosts: Host[], services: Service[]) {
} }
getZoneId(zone: Zone): string {
return `${zone.network}`;
}
getHostId(host: Host): string {
return `${this.getZoneId(host.zone)}-${host.address}`;
}
getPortId(port: Port): string {
return `${this.getHostId(port.host)}-${port.portNumber}-${port.metaPortType.key}`;
}
getServiceId(service: Service): string {
return `${this.getPortId(service.port)}-${service.serviceType}`;
}
getUnknownServiceId(service: Service): string {
return `${this.getPortId(service.port)}-${MetaServiceTypeEnum.UNKNOWN}`;
}
setZone(zone: Zone, requireRefresh: boolean = false) { setZone(zone: Zone, requireRefresh: boolean = false) {
if (null === zone) { if (null === zone) {
return; return;
} }
this.zone = zone; this.zone = zone;
this.zoneNode = new Node(zone.network); this.zoneNode = new Node(this.getZoneId(zone));
this.zoneNode.group = 'zone'; this.zoneNode.group = 'zone';
this.zoneNode.target = zone; this.zoneNode.target = zone;
this.zoneNode.fx = this.displayInfraWidth / 2; this.zoneNode.fx = this.displayInfraWidth / 2;
@ -783,21 +884,21 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
} }
this.hosts.set(host.address, host); this.hosts.set(host.address, host);
const hostId = `${host.address}`; const hostId = this.getHostId(host);
let hostNode = this.getNode(hostId); let { node } = this.getNode(hostId);
if (null !== hostNode) { if (null !== node) {
hostNode.target = host; node.target = host;
} else { } else {
hostNode = new Node(hostId); node = new Node(hostId);
hostNode.target = host; node.target = host;
hostNode.group = 'host'; node.group = 'host';
hostNode.r = 40; node.r = 40;
hostNode.x = this.zoneNode.x; node.x = this.zoneNode.x;
hostNode.y = this.zoneNode.y; node.y = this.zoneNode.y;
this.nodes.push(hostNode); this.nodes.push(node);
this.links.push(new Link(this.zoneNode, hostNode)); this.links.push(new Link(this.zoneNode, node));
this.displaySummary.increaseHost(); this.displaySummary.increaseHost();
@ -837,14 +938,55 @@ export class MapComponent implements OnInit, AfterContentInit, OnDestroy {
return; return;
} }
const hostId = `${service.port.host.address}`; const hostId = this.getHostId(service.port.host);
const serviceId = `${service.port.host.address}-${service.port.portNumber}-${service.port.metaPortType.key}`; const { node: hostNode } = this.getNode(hostId);
const hostNode = this.getNode(hostId); const unknownServiceId = this.getUnknownServiceId(service);
let serviceNode = this.getNode(serviceId); const { index: unknownServiceNodeIdx, node: unknownServiceNode } = this.getNode(unknownServiceId);
const serviceId = this.getServiceId(service);
let { node: serviceNode } = this.getNode(serviceId);
let newNode = false;
if (MetaServiceTypeEnum.UNKNOWN === MetaServiceTypeEnum[service.serviceType]) {
if (null !== unknownServiceNode) {
unknownServiceNode.target = service;
} else {
newNode = true;
}
} else {
if (null !== serviceNode) { if (null !== serviceNode) {
serviceNode.target = service; serviceNode.target = service;
} else { } else {
if (null !== unknownServiceNode) {
const { index: linkIdx } = this.getLink(hostNode, unknownServiceNode);
delete this.links[linkIdx];
delete this.nodes[unknownServiceNodeIdx];
}
newNode = true;
}
}
let _servicesMap: Map<number, Map<string, Service>>;
if (!this.services.has(service.port.host.address)) {
_servicesMap = new Map();
this.services.set(service.port.host.address, _servicesMap);
} else {
_servicesMap = this.services.get(service.port.host.address);
}
let _services: Map<string, Service>;
if (!_servicesMap.has(service.port.portNumber)) {
_services = new Map();
_servicesMap.set(service.port.portNumber, _services);
} else {
_services = _servicesMap.get(service.port.portNumber);
}
_services.set(service.serviceType, service);
if (newNode) {
serviceNode = new Node(serviceId); serviceNode = new Node(serviceId);
serviceNode.target = service; serviceNode.target = service;
serviceNode.group = 'service'; serviceNode.group = 'service';