mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-17 06:18:09 +00:00
Double click to open new console
This commit is contained in:
@ -37,6 +37,7 @@ import { ProjectMapComponent } from './components/project-map/project-map.compon
|
|||||||
import { ServersComponent } from './components/servers/servers.component';
|
import { ServersComponent } from './components/servers/servers.component';
|
||||||
import { AddServerDialogComponent } from './components/servers/add-server-dialog/add-server-dialog.component';
|
import { AddServerDialogComponent } from './components/servers/add-server-dialog/add-server-dialog.component';
|
||||||
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
||||||
|
import { ContextConsoleMenuComponent } from './components/project-map/context-console-menu/context-console-menu.component';
|
||||||
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
|
import { StartNodeActionComponent } from './components/project-map/context-menu/actions/start-node-action/start-node-action.component';
|
||||||
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
||||||
import { TemplateComponent } from './components/template/template.component';
|
import { TemplateComponent } from './components/template/template.component';
|
||||||
@ -299,6 +300,7 @@ import { TemplateNameDialogComponent } from './components/project-map/new-templa
|
|||||||
DefaultLayoutComponent,
|
DefaultLayoutComponent,
|
||||||
ProgressDialogComponent,
|
ProgressDialogComponent,
|
||||||
ContextMenuComponent,
|
ContextMenuComponent,
|
||||||
|
ContextConsoleMenuComponent,
|
||||||
StartNodeActionComponent,
|
StartNodeActionComponent,
|
||||||
StopNodeActionComponent,
|
StopNodeActionComponent,
|
||||||
TemplateComponent,
|
TemplateComponent,
|
||||||
|
@ -15,6 +15,7 @@ import { MapSettingsService } from '../../services/mapsettings.service';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class NodeWidget implements Widget {
|
export class NodeWidget implements Widget {
|
||||||
public onContextMenu = new EventEmitter<NodeContextMenu>();
|
public onContextMenu = new EventEmitter<NodeContextMenu>();
|
||||||
|
public onContextConsoleMenu = new EventEmitter<NodeContextMenu>();
|
||||||
public onNodeClicked = new EventEmitter<NodeClicked>();
|
public onNodeClicked = new EventEmitter<NodeClicked>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -85,6 +86,10 @@ export class NodeWidget implements Widget {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.onContextMenu.emit(new NodeContextMenu(event, n));
|
self.onContextMenu.emit(new NodeContextMenu(event, n));
|
||||||
})
|
})
|
||||||
|
.on('dblclick', function(n: MapNode, i: number) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.onContextConsoleMenu.emit(new NodeContextMenu(event, n));
|
||||||
|
})
|
||||||
.attr('xnode:href', (n: MapNode) => n.symbolUrl)
|
.attr('xnode:href', (n: MapNode) => n.symbolUrl)
|
||||||
.attr('width', (n: MapNode) => {
|
.attr('width', (n: MapNode) => {
|
||||||
if (n.nodeType === 'cloud' || n.nodeType === 'nat') return 120;
|
if (n.nodeType === 'cloud' || n.nodeType === 'nat') return 120;
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition">
|
||||||
|
<span [matMenuTriggerFor]="contextConsoleMenu"></span>
|
||||||
|
<mat-menu #contextConsoleMenu="matMenu" class="context-menu-items">
|
||||||
|
<span class="title">
|
||||||
|
Choose default behavior for double click on node
|
||||||
|
</span>
|
||||||
|
<button mat-menu-item (click)="openConsole()">
|
||||||
|
<mat-icon>web_asset</mat-icon>
|
||||||
|
<span>Open console</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="openWebConsole()">
|
||||||
|
<mat-icon>http</mat-icon>
|
||||||
|
<span>Open web console</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="openWebConsoleInNewTab()">
|
||||||
|
<mat-icon>http</mat-icon>
|
||||||
|
<span>Open web console in new tab</span>
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template [hidden]="true" #container></template>
|
@ -0,0 +1,12 @@
|
|||||||
|
.context-menu {
|
||||||
|
position: absolute;
|
||||||
|
min-height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-menu-panel ng-trigger ng-trigger-transformMenu ng-tns-c7-5 context-menu-items mat-menu-after mat-menu-below ng-star-inserted mat-elevation-z4 {
|
||||||
|
min-height: 0px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
import { ChangeDetectorRef, Component, ComponentFactory, ComponentRef, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
|
import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
import { Node } from '../../../cartography/models/node';
|
||||||
|
import { Server } from '../../../models/server';
|
||||||
|
import { Project } from '../../../models/project';
|
||||||
|
import { MapSettingsService } from '../../../services/mapsettings.service';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
import { ToasterService } from '../../../services/toaster.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { ComponentFactoryResolver } from '@angular/core';
|
||||||
|
import { ConsoleDeviceActionComponent } from '../context-menu/actions/console-device-action/console-device-action.component';
|
||||||
|
import { ConsoleDeviceActionBrowserComponent } from '../context-menu/actions/console-device-action-browser/console-device-action-browser.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-context-console-menu',
|
||||||
|
templateUrl: './context-console-menu.component.html',
|
||||||
|
styleUrls: ['./context-console-menu.component.scss']
|
||||||
|
})
|
||||||
|
export class ContextConsoleMenuComponent implements OnInit {
|
||||||
|
@Input() project: Project;
|
||||||
|
@Input() server: Server;
|
||||||
|
@ViewChild(MatMenuTrigger) contextConsoleMenu: MatMenuTrigger;
|
||||||
|
@ViewChild("container", { read: ViewContainerRef }) container;
|
||||||
|
componentRef: ComponentRef<ConsoleDeviceActionComponent>;
|
||||||
|
componentBrowserRef: ComponentRef<ConsoleDeviceActionBrowserComponent>;
|
||||||
|
|
||||||
|
topPosition;
|
||||||
|
leftPosition;
|
||||||
|
isElectronApp = false;
|
||||||
|
node: Node;;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
private mapSettingsService: MapSettingsService,
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private consoleService: NodeConsoleService,
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private router: Router,
|
||||||
|
private resolver: ComponentFactoryResolver
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.setPosition(0, 0);
|
||||||
|
this.isElectronApp = this.electronService.isElectronApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPosition(top: number, left: number) {
|
||||||
|
this.topPosition = this.sanitizer.bypassSecurityTrustStyle(top + 'px');
|
||||||
|
this.leftPosition = this.sanitizer.bypassSecurityTrustStyle(left + 'px');
|
||||||
|
this.changeDetector.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public openMenu(node: Node, top: number, left: number) {
|
||||||
|
this.node = node;
|
||||||
|
let action = this.mapSettingsService.getConsoleContextManuAction();
|
||||||
|
if (action) {
|
||||||
|
if (action === 'web console') {
|
||||||
|
this.openWebConsole();
|
||||||
|
} else if (action === 'web console in new tab') {
|
||||||
|
this.openWebConsoleInNewTab();
|
||||||
|
} else if (action === 'console') {
|
||||||
|
this.openConsole();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setPosition(top, left);
|
||||||
|
this.contextConsoleMenu.openMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openConsole() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('console');
|
||||||
|
if (this.isElectronApp) {
|
||||||
|
const factory: ComponentFactory<ConsoleDeviceActionComponent> = this.resolver.resolveComponentFactory(ConsoleDeviceActionComponent);
|
||||||
|
this.componentRef = this.container.createComponent(factory);
|
||||||
|
this.componentRef.instance.server = this.server;
|
||||||
|
this.componentRef.instance.nodes = [this.node];
|
||||||
|
|
||||||
|
this.componentRef.instance.console();
|
||||||
|
} else {
|
||||||
|
const factory: ComponentFactory<ConsoleDeviceActionBrowserComponent> = this.resolver.resolveComponentFactory(ConsoleDeviceActionBrowserComponent);
|
||||||
|
this.componentBrowserRef = this.container.createComponent(factory);
|
||||||
|
this.componentBrowserRef.instance.server = this.server;
|
||||||
|
this.componentBrowserRef.instance.node = this.node;
|
||||||
|
|
||||||
|
this.componentBrowserRef.instance.openConsole();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openWebConsole() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('web console');
|
||||||
|
if (this.node.status === 'started') {
|
||||||
|
this.mapSettingsService.logConsoleSubject.next(true);
|
||||||
|
this.consoleService.openConsoleForNode(this.node);
|
||||||
|
} else {
|
||||||
|
this.toasterService.error('To open console please start the node');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openWebConsoleInNewTab() {
|
||||||
|
this.mapSettingsService.setConsoleContextMenuAction('web console in new tab');
|
||||||
|
if (this.node.status === 'started') {
|
||||||
|
let url = this.router.url.split('/');
|
||||||
|
let urlString = `/static/web-ui/${url[1]}/${url[2]}/${url[3]}/${url[4]}/nodes/${this.node.node_id}`
|
||||||
|
window.open(urlString);
|
||||||
|
} else {
|
||||||
|
this.toasterService.error('To open console please start the node');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.componentRef.destroy();
|
||||||
|
}
|
||||||
|
}
|
@ -179,6 +179,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-context-menu [project]="project" [server]="server"></app-context-menu>
|
<app-context-menu [project]="project" [server]="server"></app-context-menu>
|
||||||
|
<app-context-console-menu [project]="project" [server]="server"></app-context-console-menu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [ngClass]="{lightTheme: isLightThemeEnabled}" class="zoom-buttons">
|
<div [ngClass]="{lightTheme: isLightThemeEnabled}" class="zoom-buttons">
|
||||||
|
@ -13,6 +13,7 @@ import { ProjectService } from '../../services/project.service';
|
|||||||
import { Server } from '../../models/server';
|
import { Server } from '../../models/server';
|
||||||
import { Drawing } from '../../cartography/models/drawing';
|
import { Drawing } from '../../cartography/models/drawing';
|
||||||
import { ContextMenuComponent } from './context-menu/context-menu.component';
|
import { ContextMenuComponent } from './context-menu/context-menu.component';
|
||||||
|
import { ContextConsoleMenuComponent } from './context-console-menu/context-console-menu.component';
|
||||||
import { Template } from '../../models/template';
|
import { Template } from '../../models/template';
|
||||||
import { NodeService } from '../../services/node.service';
|
import { NodeService } from '../../services/node.service';
|
||||||
import { Symbol } from '../../models/symbol';
|
import { Symbol } from '../../models/symbol';
|
||||||
@ -112,6 +113,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
public isLightThemeEnabled: boolean = false;
|
public isLightThemeEnabled: boolean = false;
|
||||||
|
|
||||||
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
|
@ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
|
||||||
|
@ViewChild(ContextConsoleMenuComponent) consoleContextMenu: ContextConsoleMenuComponent;
|
||||||
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
|
@ViewChild(D3MapComponent) mapChild: D3MapComponent;
|
||||||
@ViewChild(ProjectMapMenuComponent) projectMapMenuComponent: ProjectMapMenuComponent;
|
@ViewChild(ProjectMapMenuComponent) projectMapMenuComponent: ProjectMapMenuComponent;
|
||||||
|
|
||||||
@ -437,6 +439,11 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX);
|
this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onContextConsoleMenu = this.nodeWidget.onContextConsoleMenu.subscribe((eventNode: NodeContextMenu) => {
|
||||||
|
const node = this.mapNodeToNode.convert(eventNode.node);
|
||||||
|
this.consoleContextMenu.openMenu(node, eventNode.event.pageY, eventNode.event.pageX);
|
||||||
|
});
|
||||||
|
|
||||||
this.projectMapSubscription.add(onLinkContextMenu);
|
this.projectMapSubscription.add(onLinkContextMenu);
|
||||||
this.projectMapSubscription.add(onEthernetLinkContextMenu);
|
this.projectMapSubscription.add(onEthernetLinkContextMenu);
|
||||||
this.projectMapSubscription.add(onSerialLinkContextMenu);
|
this.projectMapSubscription.add(onSerialLinkContextMenu);
|
||||||
@ -445,6 +452,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
|
|||||||
this.projectMapSubscription.add(onContextMenu);
|
this.projectMapSubscription.add(onContextMenu);
|
||||||
this.projectMapSubscription.add(onLabelContextMenu);
|
this.projectMapSubscription.add(onLabelContextMenu);
|
||||||
this.projectMapSubscription.add(onInterfaceLabelContextMenu);
|
this.projectMapSubscription.add(onInterfaceLabelContextMenu);
|
||||||
|
this.projectMapSubscription.add(onContextConsoleMenu);
|
||||||
this.mapChangeDetectorRef.detectChanges();
|
this.mapChangeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,14 @@ export class MapSettingsService {
|
|||||||
this.isMapLocked.next(value);
|
this.isMapLocked.next(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setConsoleContextMenuAction(action: string) {
|
||||||
|
localStorage.setItem('consoleContextMenu', action);
|
||||||
|
}
|
||||||
|
|
||||||
|
getConsoleContextManuAction(): string {
|
||||||
|
return localStorage.getItem('consoleContextMenu');
|
||||||
|
}
|
||||||
|
|
||||||
toggleTopologySummary(value: boolean) {
|
toggleTopologySummary(value: boolean) {
|
||||||
this.isTopologySummaryVisible = value;
|
this.isTopologySummaryVisible = value;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user