mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-02-07 03:40:11 +00:00
Node actions
This commit is contained in:
parent
055dde4ea5
commit
935b0b93e6
@ -41,6 +41,8 @@ import { MapComponent } from './cartography/map/map.component';
|
|||||||
import { CreateSnapshotDialogComponent, ProjectMapComponent } from './project-map/project-map.component';
|
import { CreateSnapshotDialogComponent, ProjectMapComponent } from './project-map/project-map.component';
|
||||||
import { ServersComponent, AddServerDialogComponent } from './servers/servers.component';
|
import { ServersComponent, AddServerDialogComponent } from './servers/servers.component';
|
||||||
import { NodeContextMenuComponent } from './shared/node-context-menu/node-context-menu.component';
|
import { NodeContextMenuComponent } from './shared/node-context-menu/node-context-menu.component';
|
||||||
|
import {NodeService} from "./shared/services/node.service";
|
||||||
|
import { StartNodeActionComponent } from './shared/node-context-menu/actions/start-node-action/start-node-action.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -55,6 +57,7 @@ import { NodeContextMenuComponent } from './shared/node-context-menu/node-contex
|
|||||||
DefaultLayoutComponent,
|
DefaultLayoutComponent,
|
||||||
ProgressDialogComponent,
|
ProgressDialogComponent,
|
||||||
NodeContextMenuComponent,
|
NodeContextMenuComponent,
|
||||||
|
StartNodeActionComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
@ -82,6 +85,7 @@ import { NodeContextMenuComponent } from './shared/node-context-menu/node-contex
|
|||||||
ProjectService,
|
ProjectService,
|
||||||
SymbolService,
|
SymbolService,
|
||||||
ServerService,
|
ServerService,
|
||||||
|
NodeService,
|
||||||
IndexedDbService,
|
IndexedDbService,
|
||||||
HttpServer,
|
HttpServer,
|
||||||
SnapshotService,
|
SnapshotService,
|
||||||
|
@ -94,9 +94,12 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.graphLayout = new GraphLayout();
|
this.graphLayout = new GraphLayout();
|
||||||
this.graphLayout.draw(this.svg, this.graphContext);
|
this.graphLayout.draw(this.svg, this.graphContext);
|
||||||
|
|
||||||
|
|
||||||
this.graphLayout.getNodesWidget().setOnContextMenuCallback((event: any, node: Node) => {
|
this.graphLayout.getNodesWidget().setOnContextMenuCallback((event: any, node: Node) => {
|
||||||
this.nodeContextMenu.open(node, event.clientY, event.clientX);
|
this.nodeContextMenu.open(node, event.clientY, event.clientX);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,9 @@ import { ProgressDialogService } from "../shared/progress-dialog/progress-dialog
|
|||||||
import { ProgressDialogComponent } from "../shared/progress-dialog/progress-dialog.component";
|
import { ProgressDialogComponent } from "../shared/progress-dialog/progress-dialog.component";
|
||||||
import { ToastyService } from "ng2-toasty";
|
import { ToastyService } from "ng2-toasty";
|
||||||
import {Drawing} from "../cartography/shared/models/drawing.model";
|
import {Drawing} from "../cartography/shared/models/drawing.model";
|
||||||
|
import {StartNodeAction} from "../shared/node-context-menu/actions/start-node-action";
|
||||||
|
import {NodeService} from "../shared/services/node.service";
|
||||||
|
import {StopNodeAction} from "../shared/node-context-menu/actions/stop-node-action";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -52,6 +55,7 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
private projectService: ProjectService,
|
private projectService: ProjectService,
|
||||||
private symbolService: SymbolService,
|
private symbolService: SymbolService,
|
||||||
private snapshotService: SnapshotService,
|
private snapshotService: SnapshotService,
|
||||||
|
private nodeService: NodeService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private progressDialogService: ProgressDialogService,
|
private progressDialogService: ProgressDialogService,
|
||||||
private toastyService: ToastyService) {
|
private toastyService: ToastyService) {
|
||||||
@ -105,6 +109,7 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
n.icon = this.symbolService.get(n.symbol);
|
n.icon = this.symbolService.get(n.symbol);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.setUpNodeActions();
|
||||||
this.setUpWS(project);
|
this.setUpWS(project);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -166,6 +171,16 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUpNodeActions() {
|
||||||
|
this.mapChild.nodeContextMenu.clearActions();
|
||||||
|
|
||||||
|
const start_node_action = new StartNodeAction(this.server, this.nodeService);
|
||||||
|
this.mapChild.nodeContextMenu.registerAction(start_node_action);
|
||||||
|
|
||||||
|
const stop_node_action = new StopNodeAction(this.server, this.nodeService);
|
||||||
|
this.mapChild.nodeContextMenu.registerAction(stop_node_action);
|
||||||
|
}
|
||||||
|
|
||||||
public createSnapshotModal() {
|
public createSnapshotModal() {
|
||||||
const dialogRef = this.dialog.open(CreateSnapshotDialogComponent, {
|
const dialogRef = this.dialog.open(CreateSnapshotDialogComponent, {
|
||||||
width: '250px',
|
width: '250px',
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import {NodeContextMenuAction} from "../node-context-menu-action";
|
||||||
|
import {Node} from "../../../cartography/shared/models/node.model";
|
||||||
|
import {Server} from "../../models/server";
|
||||||
|
import {NodeService} from "../../services/node.service";
|
||||||
|
|
||||||
|
|
||||||
|
export class StartNodeAction implements NodeContextMenuAction {
|
||||||
|
constructor(private server: Server, private nodeService: NodeService) {}
|
||||||
|
|
||||||
|
icon(node: Node) {
|
||||||
|
return "play_arrow";
|
||||||
|
}
|
||||||
|
|
||||||
|
label(node: Node) {
|
||||||
|
return "Start";
|
||||||
|
}
|
||||||
|
|
||||||
|
isVisible(node: Node) {
|
||||||
|
return node.status === 'stopped';
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(node: Node) {
|
||||||
|
this.nodeService.start()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
<p>
|
||||||
|
start-node-action works!
|
||||||
|
</p>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StartNodeActionComponent } from './start-node-action.component';
|
||||||
|
|
||||||
|
describe('StartNodeActionComponent', () => {
|
||||||
|
let component: StartNodeActionComponent;
|
||||||
|
let fixture: ComponentFixture<StartNodeActionComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ StartNodeActionComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StartNodeActionComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-start-node-action',
|
||||||
|
templateUrl: './start-node-action.component.html',
|
||||||
|
styleUrls: ['./start-node-action.component.scss']
|
||||||
|
})
|
||||||
|
export class StartNodeActionComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/app/shared/node-context-menu/actions/stop-node-action.ts
Normal file
26
src/app/shared/node-context-menu/actions/stop-node-action.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {NodeContextMenuAction} from "../node-context-menu-action";
|
||||||
|
import {Node} from "../../../cartography/shared/models/node.model";
|
||||||
|
import {Server} from "../../models/server";
|
||||||
|
import {Project} from "../../models/project";
|
||||||
|
import {NodeService} from "../../services/node.service";
|
||||||
|
|
||||||
|
|
||||||
|
export class StopNodeAction implements NodeContextMenuAction {
|
||||||
|
constructor(server: Server, nodeService: NodeService) {}
|
||||||
|
|
||||||
|
icon(node: Node) {
|
||||||
|
return "stop";
|
||||||
|
}
|
||||||
|
|
||||||
|
label(node: Node) {
|
||||||
|
return "Stop";
|
||||||
|
}
|
||||||
|
|
||||||
|
isVisible(node: Node) {
|
||||||
|
return node.status === 'started';
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(node: Node) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import {Node} from "../../cartography/shared/models/node.model";
|
||||||
|
|
||||||
|
export interface NodeContextMenuAction {
|
||||||
|
icon(node: Node): string;
|
||||||
|
label(node: Node): string;
|
||||||
|
isVisible(node: Node): boolean;
|
||||||
|
onClick(node: Node);
|
||||||
|
}
|
@ -1,13 +1,17 @@
|
|||||||
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node">
|
<div class="context-menu" [style.left]="leftPosition" [style.top]="topPosition" *ngIf="node">
|
||||||
<span [matMenuTriggerFor]="contextMenu"></span>
|
<span [matMenuTriggerFor]="contextMenu"></span>
|
||||||
<mat-menu #contextMenu="matMenu">
|
<mat-menu #contextMenu="matMenu">
|
||||||
<button mat-menu-item *ngIf="node.status == 'stopped'">
|
<!--<button mat-menu-item *ngIf="node.status == 'stopped'">-->
|
||||||
<mat-icon>play_arrow</mat-icon>
|
<!--<mat-icon>play_arrow</mat-icon>-->
|
||||||
<span>Start</span>
|
<!--<span>Start</span>-->
|
||||||
</button>
|
<!--</button>-->
|
||||||
<button mat-menu-item *ngIf="node.status == 'started'">
|
<!--<ng-container *ngFor="let action of actions">-->
|
||||||
<mat-icon>stop</mat-icon>
|
<!--<button mat-menu-item *ngIf="action.isVisible(node)" (click)="action.onClick(node)">-->
|
||||||
<span>Stop</span>
|
<!--<mat-icon>{{ action.icon(node) }}</mat-icon>-->
|
||||||
</button>
|
<!--<span>{{ action.label(node) }}</span>-->
|
||||||
|
<!--</button>-->
|
||||||
|
<!--</ng-container>-->
|
||||||
|
|
||||||
|
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,7 @@ import {ChangeDetectorRef, Component, Input, OnInit, ViewChild} from '@angular/c
|
|||||||
import {MatMenuTrigger} from "@angular/material";
|
import {MatMenuTrigger} from "@angular/material";
|
||||||
import {DomSanitizer} from "@angular/platform-browser";
|
import {DomSanitizer} from "@angular/platform-browser";
|
||||||
import {Node} from "../../cartography/shared/models/node.model";
|
import {Node} from "../../cartography/shared/models/node.model";
|
||||||
|
import {NodeContextMenuAction} from "./node-context-menu-action";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -15,6 +16,7 @@ export class NodeContextMenuComponent implements OnInit {
|
|||||||
private topPosition;
|
private topPosition;
|
||||||
private leftPosition;
|
private leftPosition;
|
||||||
private node: Node;
|
private node: Node;
|
||||||
|
private actions: NodeContextMenuAction[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private sanitizer: DomSanitizer,
|
private sanitizer: DomSanitizer,
|
||||||
@ -36,4 +38,12 @@ export class NodeContextMenuComponent implements OnInit {
|
|||||||
this.contextMenu.openMenu();
|
this.contextMenu.openMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public registerAction(action: NodeContextMenuAction) {
|
||||||
|
this.actions.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearActions() {
|
||||||
|
this.actions = [];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
15
src/app/shared/services/node.service.spec.ts
Normal file
15
src/app/shared/services/node.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NodeService } from './node.service';
|
||||||
|
|
||||||
|
describe('NodeService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [NodeService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([NodeService], (service: NodeService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
28
src/app/shared/services/node.service.ts
Normal file
28
src/app/shared/services/node.service.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Project } from '../models/project';
|
||||||
|
import { Node } from '../../cartography/shared/models/node.model';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import { Server } from "../models/server";
|
||||||
|
import { HttpServer } from "./http-server.service";
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NodeService {
|
||||||
|
|
||||||
|
constructor(private httpServer: HttpServer) { }
|
||||||
|
|
||||||
|
start(server: Server, node: Node): Observable<Node> {
|
||||||
|
return this.httpServer
|
||||||
|
.post(server, `/projects/${node.project_id}/nodes/${node.node_id}/start`, {})
|
||||||
|
.map(response => response.json() as Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop(server: Server, node: Node): Observable<Node> {
|
||||||
|
return this.httpServer
|
||||||
|
.post(server, `/projects/${node.project_id}/nodes/${node.node_id}/stop`, {})
|
||||||
|
.map(response => response.json() as Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user