mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-11 11:41:35 +00:00
Draw line menu
This commit is contained in:
parent
e19503d1a3
commit
0b61093dff
@ -46,6 +46,7 @@ import { StartNodeActionComponent } from './shared/node-context-menu/actions/sta
|
|||||||
import { StopNodeActionComponent } from './shared/node-context-menu/actions/stop-node-action/stop-node-action.component';
|
import { StopNodeActionComponent } from './shared/node-context-menu/actions/stop-node-action/stop-node-action.component';
|
||||||
import { ApplianceComponent } from './appliance/appliance.component';
|
import { ApplianceComponent } from './appliance/appliance.component';
|
||||||
import { ApplianceListDialogComponent } from './appliance/appliance-list-dialog/appliance-list-dialog.component';
|
import { ApplianceListDialogComponent } from './appliance/appliance-list-dialog/appliance-list-dialog.component';
|
||||||
|
import { NodeSelectInterfaceComponent } from './shared/node-select-interface/node-select-interface.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -64,6 +65,7 @@ import { ApplianceListDialogComponent } from './appliance/appliance-list-dialog/
|
|||||||
StopNodeActionComponent,
|
StopNodeActionComponent,
|
||||||
ApplianceComponent,
|
ApplianceComponent,
|
||||||
ApplianceListDialogComponent,
|
ApplianceListDialogComponent,
|
||||||
|
NodeSelectInterfaceComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {Label} from "./label.model";
|
import {Label} from "./label.model";
|
||||||
|
import {Port} from "../../../shared/models/port";
|
||||||
|
|
||||||
export class Node {
|
export class Node {
|
||||||
command_line: string;
|
command_line: string;
|
||||||
@ -15,7 +16,7 @@ export class Node {
|
|||||||
node_type: string;
|
node_type: string;
|
||||||
port_name_format: string;
|
port_name_format: string;
|
||||||
port_segment_size: number;
|
port_segment_size: number;
|
||||||
ports: number[];
|
ports: Port[];
|
||||||
project_id: string;
|
project_id: string;
|
||||||
status: string;
|
status: string;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
|
@ -10,6 +10,7 @@ export class NodesWidget implements Widget {
|
|||||||
private debug = false;
|
private debug = false;
|
||||||
|
|
||||||
private onContextMenuCallback: (event: any, node: Node) => void;
|
private onContextMenuCallback: (event: any, node: Node) => void;
|
||||||
|
private onNodeClickedCallback: (event: any, node: Node) => void;
|
||||||
private onNodeDraggedCallback: (event: any, node: Node) => void;
|
private onNodeDraggedCallback: (event: any, node: Node) => void;
|
||||||
private onNodeDraggingCallbacks: ((event: any, node: Node) => void)[] = [];
|
private onNodeDraggingCallbacks: ((event: any, node: Node) => void)[] = [];
|
||||||
|
|
||||||
@ -21,6 +22,10 @@ export class NodesWidget implements Widget {
|
|||||||
this.onContextMenuCallback = onContextMenuCallback;
|
this.onContextMenuCallback = onContextMenuCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setOnNodeClickedCallback(onNodeClickedCallback: (event: any, node: Node) => void) {
|
||||||
|
this.onNodeClickedCallback = onNodeClickedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
public setOnNodeDraggedCallback(onNodeDraggedCallback: (event: any, node: Node) => void) {
|
public setOnNodeDraggedCallback(onNodeDraggedCallback: (event: any, node: Node) => void) {
|
||||||
this.onNodeDraggedCallback = onNodeDraggedCallback;
|
this.onNodeDraggedCallback = onNodeDraggedCallback;
|
||||||
}
|
}
|
||||||
@ -102,13 +107,20 @@ export class NodesWidget implements Widget {
|
|||||||
.attr('y', '0');
|
.attr('y', '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
const node_merge = node.merge(node_enter)
|
const node_merge = node
|
||||||
.on("contextmenu", function (n: Node, i: number) {
|
.merge(node_enter)
|
||||||
event.preventDefault();
|
.on("contextmenu", function (n: Node, i: number) {
|
||||||
if (self.onContextMenuCallback !== null) {
|
event.preventDefault();
|
||||||
self.onContextMenuCallback(event, n);
|
if (self.onContextMenuCallback !== null) {
|
||||||
}
|
self.onContextMenuCallback(event, n);
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.on('click', (n: Node) => {
|
||||||
|
if (self.onNodeClickedCallback) {
|
||||||
|
self.onNodeClickedCallback(event, n);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
this.revise(node_merge);
|
this.revise(node_merge);
|
||||||
|
|
||||||
|
@ -19,6 +19,16 @@
|
|||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-toolbar-row>
|
||||||
|
<button mat-icon-button (click)="turnOnDrawLineMode()" *ngIf="!drawLineMode">
|
||||||
|
<mat-icon>timeline</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button mat-icon-button color="primary" (click)="turnOffDrawLineMode()" *ngIf="drawLineMode">
|
||||||
|
<mat-icon>timeline</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-toolbar-row>
|
||||||
|
|
||||||
<mat-toolbar-row>
|
<mat-toolbar-row>
|
||||||
<button mat-icon-button (click)="createSnapshotModal()">
|
<button mat-icon-button (click)="createSnapshotModal()">
|
||||||
<mat-icon>snooze</mat-icon>
|
<mat-icon>snooze</mat-icon>
|
||||||
@ -33,6 +43,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-node-context-menu [server]="server"></app-node-context-menu>
|
<app-node-context-menu [server]="server"></app-node-context-menu>
|
||||||
|
<app-node-select-interface></app-node-select-interface>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import { NodeContextMenuComponent } from "../shared/node-context-menu/node-conte
|
|||||||
import {Appliance} from "../shared/models/appliance";
|
import {Appliance} from "../shared/models/appliance";
|
||||||
import {NodeService} from "../shared/services/node.service";
|
import {NodeService} from "../shared/services/node.service";
|
||||||
import {Symbol} from "../shared/models/symbol";
|
import {Symbol} from "../shared/models/symbol";
|
||||||
|
import {NodeSelectInterfaceComponent} from "../shared/node-select-interface/node-select-interface.component";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -48,10 +49,13 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
public server: Server;
|
public server: Server;
|
||||||
|
|
||||||
private ws: Subject<any>;
|
private ws: Subject<any>;
|
||||||
|
private drawLineMode = false;
|
||||||
|
|
||||||
|
|
||||||
@ViewChild(MapComponent) mapChild: MapComponent;
|
@ViewChild(MapComponent) mapChild: MapComponent;
|
||||||
|
|
||||||
@ViewChild(NodeContextMenuComponent) nodeContextMenu: NodeContextMenuComponent;
|
@ViewChild(NodeContextMenuComponent) nodeContextMenu: NodeContextMenuComponent;
|
||||||
|
@ViewChild(NodeSelectInterfaceComponent) nodeSelectInterfaceMenu: NodeSelectInterfaceComponent;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -182,6 +186,13 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
this.nodeContextMenu.open(node, event.clientY, event.clientX);
|
this.nodeContextMenu.open(node, event.clientY, event.clientX);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.mapChild.graphLayout.getNodesWidget().setOnNodeClickedCallback((event: any, node: Node) => {
|
||||||
|
if (this.drawLineMode) {
|
||||||
|
this.nodeSelectInterfaceMenu.open(node, event.clientY, event.clientX);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
this.mapChild.graphLayout.getNodesWidget().setOnNodeDraggedCallback((event: any, node: Node) => {
|
this.mapChild.graphLayout.getNodesWidget().setOnNodeDraggedCallback((event: any, node: Node) => {
|
||||||
const index = this.nodes.findIndex((n: Node) => n.node_id === node.node_id);
|
const index = this.nodes.findIndex((n: Node) => n.node_id === node.node_id);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -245,6 +256,14 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public turnOnDrawLineMode() {
|
||||||
|
this.drawLineMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public turnOffDrawLineMode() {
|
||||||
|
this.drawLineMode = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
7
src/app/shared/models/port.ts
Normal file
7
src/app/shared/models/port.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export class Port {
|
||||||
|
adapter_number: number;
|
||||||
|
link_type: string;
|
||||||
|
name: string;
|
||||||
|
port_number: number;
|
||||||
|
short_name: string;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node">
|
||||||
|
<span [matMenuTriggerFor]="selectInterfaceMenu"></span>
|
||||||
|
<mat-menu #selectInterfaceMenu="matMenu">
|
||||||
|
<button mat-menu-item *ngFor="let port of node.ports">
|
||||||
|
<mat-icon>info</mat-icon>
|
||||||
|
<span>{{ port.name }}</span>
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
@ -0,0 +1,3 @@
|
|||||||
|
.context-menu {
|
||||||
|
position: absolute;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NodeSelectInterfaceComponent } from './node-select-interface.component';
|
||||||
|
|
||||||
|
describe('NodeSelectInterfaceComponent', () => {
|
||||||
|
let component: NodeSelectInterfaceComponent;
|
||||||
|
let fixture: ComponentFixture<NodeSelectInterfaceComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ NodeSelectInterfaceComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(NodeSelectInterfaceComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,40 @@
|
|||||||
|
import {ChangeDetectorRef, Component, Input, OnInit, ViewChild} from '@angular/core';
|
||||||
|
import {MatMenuTrigger} from "@angular/material";
|
||||||
|
import {DomSanitizer} from "@angular/platform-browser";
|
||||||
|
import {Node} from "../../cartography/shared/models/node.model";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-node-select-interface',
|
||||||
|
templateUrl: './node-select-interface.component.html',
|
||||||
|
styleUrls: ['./node-select-interface.component.scss']
|
||||||
|
})
|
||||||
|
export class NodeSelectInterfaceComponent implements OnInit {
|
||||||
|
|
||||||
|
@ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger;
|
||||||
|
|
||||||
|
private topPosition;
|
||||||
|
private leftPosition;
|
||||||
|
private node: Node;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
private changeDetector: ChangeDetectorRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.setPosition(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPosition(top: number, left: number) {
|
||||||
|
this.topPosition = this.sanitizer.bypassSecurityTrustStyle(top + "px");
|
||||||
|
this.leftPosition = this.sanitizer.bypassSecurityTrustStyle(left + "px");
|
||||||
|
this.changeDetector.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public open(node: Node, top: number, left: number) {
|
||||||
|
this.node = node;
|
||||||
|
this.setPosition(top, left);
|
||||||
|
this.contextMenu.openMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user