Merge pull request #481 from GNS3/Show-node-information-by-context-menu

Show node information by context menu
This commit is contained in:
piotrpekala7 2019-08-21 11:35:23 +02:00 committed by GitHub
commit d8e1486692
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 179 additions and 2 deletions

View File

@ -191,6 +191,9 @@ import { DuplicateActionComponent } from './components/project-map/context-menu/
import { MapSettingService } from './services/mapsettings.service';
import { ProjectMapMenuComponent } from './components/project-map/project-map-menu/project-map-menu.component';
import { HelpComponent } from './components/help/help.component';
import { ShowNodeActionComponent } from './components/project-map/context-menu/actions/show-node-action/show-node-action.component';
import { InfoDialogComponent } from './components/project-map/info-dialog/info-dialog.component';
import { InfoService } from './services/info.service';
import { BringToFrontActionComponent } from './components/project-map/context-menu/actions/bring-to-front-action/bring-to-front-action.component';
if (environment.production) {
@ -310,10 +313,12 @@ if (environment.production) {
NodesMenuComponent,
AdbutlerComponent,
ConsoleDeviceActionComponent,
ShowNodeActionComponent,
ConsoleComponent,
NodesMenuComponent,
ProjectMapMenuComponent,
HelpComponent,
InfoDialogComponent,
BringToFrontActionComponent
],
imports: [
@ -390,7 +395,8 @@ if (environment.production) {
NodeCreatedLabelStylesFixer,
NonNegativeValidator,
RotationValidator,
MapSettingService
MapSettingService,
InfoService
],
entryComponents: [
AddServerDialogComponent,
@ -406,7 +412,8 @@ if (environment.production) {
SymbolsComponent,
DeleteConfirmationDialogComponent,
HelpDialogComponent,
StartCaptureDialogComponent
StartCaptureDialogComponent,
InfoDialogComponent
],
bootstrap: [AppComponent]
})

View File

@ -0,0 +1,4 @@
<button mat-menu-item (click)="showNode()">
<mat-icon>info</mat-icon>
<span>Show node information</span>
</button>

View File

@ -0,0 +1,26 @@
import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { Node } from '../../../../../cartography/models/node';
import { MatDialog } from '@angular/material';
import { InfoDialogComponent } from '../../../info-dialog/info-dialog.component';
import { Server } from '../../../../../models/server';
@Component({
selector: 'app-show-node-action',
templateUrl: './show-node-action.component.html'
})
export class ShowNodeActionComponent {
@Input() node: Node;
@Input() server: Server
constructor(private dialog: MatDialog) {}
showNode() {
const dialogRef = this.dialog.open(InfoDialogComponent, {
width: '600px',
autoFocus: false
});
let instance = dialogRef.componentInstance;
instance.node = this.node;
instance.server = this.server;
}
}

View File

@ -1,6 +1,10 @@
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition">
<span [matMenuTriggerFor]="contextMenu"></span>
<mat-menu #contextMenu="matMenu" class="context-menu-items">
<app-show-node-action *ngIf="nodes.length===1"
[server]="server"
[node]="nodes[0]"
></app-show-node-action>
<app-start-node-action *ngIf="nodes.length && labels.length===0" [server]="server" [nodes]="nodes"></app-start-node-action>
<app-stop-node-action *ngIf="nodes.length && labels.length===0" [server]="server" [nodes]="nodes"></app-stop-node-action>
<app-console-device-action

View File

@ -0,0 +1,25 @@
<h1 mat-dialog-title>{{node.name}}</h1>
<div class="modal-form-container">
<mat-tab-group>
<mat-tab label="General information">
<div class='textBox'>
<div *ngFor="let info of infoList">
{{info}}
</div>
</div>
</mat-tab>
<mat-tab label="Command line">
<div *ngIf="node.status !== 'started'" class='textBox'>
Please start the node in order to get the command line information.
</div>
<div class="textBox">
{{commandLine}}
</div>
</mat-tab>
</mat-tab-group>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onCloseClick()" color="accent">Close</button>
</div>

View File

@ -0,0 +1,3 @@
.textBox {
margin-top: 10px;
}

View File

@ -0,0 +1,31 @@
import { Component, Input, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material';
import { Node } from '../../../cartography/models/node';
import { InfoService } from '../../../services/info.service';
import { Server } from '../../../models/server';
@Component({
selector: 'app-info-dialog',
templateUrl: './info-dialog.component.html',
styleUrls: ['./info-dialog.component.scss']
})
export class InfoDialogComponent implements OnInit {
@Input() server: Server;
@Input() node: Node;
infoList: string[] = [];
commandLine: string = '';
constructor(
public dialogRef: MatDialogRef<InfoDialogComponent>,
private infoService: InfoService
) {}
ngOnInit() {
this.infoList = this.infoService.getInfoAboutNode(this.node, this.server);
this.commandLine = this.infoService.getCommandLine(this.node);
}
onCloseClick() {
this.dialogRef.close();
}
}

View File

@ -0,0 +1,77 @@
import { Injectable } from "@angular/core";
import { Node } from '../cartography/models/node';
import { Port } from '../models/port';
import { Server } from '../models/server';
@Injectable()
export class InfoService {
getInfoAboutNode(node: Node, server: Server): string[] {
let infoList: string[] = [];
if (node.node_type === 'cloud') {
infoList.push(`Cloud ${node.name} is always on.`);
} else if (node.node_type === 'nat') {
infoList.push(`NAT ${node.name} is always on.`);
} else if (node.node_type === 'ethernet-hub') {
infoList.push(`Ethernet hub ${node.name} is always on.`);
} else if (node.node_type === 'ethernet_switch') {
infoList.push(`Ethernet switch ${node.name} is always on.`);
} else if (node.node_type === 'frame_relay_switch') {
infoList.push(`Frame relay switch ${node.name} is always on.`);
} else if (node.node_type === 'atm_switch') {
infoList.push(`ATM switch ${node.name} is always on.`);
} else if (node.node_type === 'docker') {
infoList.push(`Docker ${node.name} is ${node.status}.`);
} else if (node.node_type === 'dynamips') {
infoList.push(`Dynamips ${node.name} is always on.`);
} else if (node.node_type === 'traceng') {
infoList.push(`TraceNG ${node.name} is always on.`);
} else if (node.node_type === 'virtualbox') {
infoList.push(`VirtualBox VM ${node.name} is ${node.status}.`);
} else if (node.node_type === 'vmware') {
infoList.push(`VMware VM ${node.name} is ${node.status}.`);
} else if (node.node_type === 'qemu') {
infoList.push(`QEMU VM ${node.name} is ${node.status}.`);
} else if (node.node_type === 'iou') {
infoList.push(`IOU ${node.name} is always on.`);
} else if (node.node_type === 'vpcs') {
infoList.push(`Node ${node.name} is ${node.status}.`);
}
infoList.push(`Running on server ${server.name} with port ${server.port}.`);
infoList.push(`Server ID is ${server.id}.`);
if (node.console_type !== 'none' && node.console_type !== 'null') {
infoList.push(`Console is on port ${node.console} and type is ${node.console_type}.`);
}
infoList = infoList.concat(this.getInfoAboutPorts(node.ports));
return infoList;
}
getInfoAboutPorts(ports: Port[]): string {
let response: string = `Ports: `
ports.forEach(port => {
response += `link_type: ${port.link_type},
name: ${port.name}; `
});
response = response.substring(0, response.length - 2);
return response;
}
getCommandLine(node: Node): string {
if (node.node_type === "cloud" ||
node.node_type === "nat" ||
node.node_type === "ethernet_hub" ||
node.node_type === "ethernet_switch" ||
node.node_type === "frame_relay_switch" ||
node.node_type === "atm_switch" ||
node.node_type === "dynamips" ||
node.node_type === "traceng" ||
node.node_type === "iou") {
return 'Command line information is not supported for this type of node.';
} else {
if (node.status === 'started') {
return node.command_line;
} else {
return 'Please start the node in order to get the command line information.';
}
}
}
}