mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-16 22:08:08 +00:00
Capturing packets visible on map
This commit is contained in:
@ -169,10 +169,14 @@ import { DateFilter } from './filters/dateFilter.pipe';
|
|||||||
import { NameFilter } from './filters/nameFilter.pipe';
|
import { NameFilter } from './filters/nameFilter.pipe';
|
||||||
import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component';
|
import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component';
|
||||||
import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component';
|
import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component';
|
||||||
|
import { PacketFiltersActionComponent } from './components/project-map/context-menu/actions/packet-filters-action/packet-filters-action.component';
|
||||||
import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component';
|
import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component';
|
||||||
import { HelpDialogComponent } from './components/project-map/help-dialog/help-dialog.component';
|
import { HelpDialogComponent } from './components/project-map/help-dialog/help-dialog.component';
|
||||||
import { StartCaptureActionComponent } from './components/project-map/context-menu/actions/start-capture/start-capture-action.component';
|
import { StartCaptureActionComponent } from './components/project-map/context-menu/actions/start-capture/start-capture-action.component';
|
||||||
import { StartCaptureDialogComponent } from './components/project-map/packet-capturing/start-capture/start-capture.component';
|
import { StartCaptureDialogComponent } from './components/project-map/packet-capturing/start-capture/start-capture.component';
|
||||||
|
import { SuspendLinkActionComponent } from './components/project-map/context-menu/actions/suspend-link/suspend-link-action.component';
|
||||||
|
import { ResumeLinkActionComponent } from './components/project-map/context-menu/actions/resume-link-action/resume-link-action.component';
|
||||||
|
import { StopCaptureActionComponent } from './components/project-map/context-menu/actions/stop-capture/stop-capture-action.component';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
||||||
@ -209,6 +213,9 @@ if (environment.production) {
|
|||||||
DeleteActionComponent,
|
DeleteActionComponent,
|
||||||
PacketFiltersActionComponent,
|
PacketFiltersActionComponent,
|
||||||
StartCaptureActionComponent,
|
StartCaptureActionComponent,
|
||||||
|
StopCaptureActionComponent,
|
||||||
|
ResumeLinkActionComponent,
|
||||||
|
SuspendLinkActionComponent,
|
||||||
ProjectMapShortcutsComponent,
|
ProjectMapShortcutsComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
PreferencesComponent,
|
PreferencesComponent,
|
||||||
|
@ -19,6 +19,7 @@ export class LinkToMapLinkConverter implements Converter<Link, MapLink> {
|
|||||||
mapLink.linkType = link.link_type;
|
mapLink.linkType = link.link_type;
|
||||||
mapLink.nodes = link.nodes.map(linkNode => this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id }));
|
mapLink.nodes = link.nodes.map(linkNode => this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id }));
|
||||||
mapLink.projectId = link.project_id;
|
mapLink.projectId = link.project_id;
|
||||||
|
mapLink.suspend = link.suspend;
|
||||||
return mapLink;
|
return mapLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ export class MapLinkToLinkConverter implements Converter<MapLink, Link> {
|
|||||||
link.link_type = mapLink.linkType;
|
link.link_type = mapLink.linkType;
|
||||||
link.nodes = mapLink.nodes.map(mapLinkNode => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
|
link.nodes = mapLink.nodes.map(mapLinkNode => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
|
||||||
link.project_id = mapLink.projectId;
|
link.project_id = mapLink.projectId;
|
||||||
|
link.suspend = mapLink.suspend;
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ export class MapLink implements Indexed {
|
|||||||
linkType: string;
|
linkType: string;
|
||||||
nodes: MapLinkNode[];
|
nodes: MapLinkNode[];
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
suspend: boolean;
|
||||||
|
|
||||||
distance: number; // this is not from server
|
distance: number; // this is not from server
|
||||||
length: number; // this is not from server
|
length: number; // this is not from server
|
||||||
|
@ -32,12 +32,12 @@ export class LinkWidget implements Widget {
|
|||||||
return `translate (${translation.dx}, ${translation.dy})`;
|
return `translate (${translation.dx}, ${translation.dy})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
link_body.select('.svg-icon').remove();
|
link_body.select('.capture-icon').remove();
|
||||||
|
|
||||||
link_body
|
link_body
|
||||||
.filter(l => { return l.filters.frequency_drop })
|
.filter(l => { return l.capturing })
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.attr('class', 'svg-icon')
|
.attr('class', 'capture-icon')
|
||||||
.attr('transform', link => {
|
.attr('transform', link => {
|
||||||
return `translate (${(link.source.x + link.target.x)/2}, ${(link.source.y + link.target.y)/2})`
|
return `translate (${(link.source.x + link.target.x)/2}, ${(link.source.y + link.target.y)/2})`
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<button mat-menu-item *ngIf="link.suspend" (click)="resumeLink()">
|
||||||
|
<mat-icon>play_arrow</mat-icon>
|
||||||
|
<span>Resume</span>
|
||||||
|
</button>
|
@ -0,0 +1,22 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { Link } from '../../../../../models/link';
|
||||||
|
import { LinkService } from '../../../../../services/link.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-resume-link-action',
|
||||||
|
templateUrl: './resume-link-action.component.html'
|
||||||
|
})
|
||||||
|
export class ResumeLinkActionComponent {
|
||||||
|
@Input() server: Server;
|
||||||
|
@Input() link: Link;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private linkService: LinkService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
resumeLink() {
|
||||||
|
this.link.suspend = false;
|
||||||
|
this.linkService.updateLink(this.server, this.link).subscribe(() => {});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<button mat-menu-item *ngIf="link.capturing" (click)="stopCapture()">
|
||||||
|
<mat-icon>pause_circle_filled</mat-icon>
|
||||||
|
<span>Stop capture</span>
|
||||||
|
</button>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { Link } from '../../../../../models/link';
|
||||||
|
import { LinkService } from '../../../../../services/link.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-stop-capture-action',
|
||||||
|
templateUrl: './stop-capture-action.component.html'
|
||||||
|
})
|
||||||
|
export class StopCaptureActionComponent {
|
||||||
|
@Input() server: Server;
|
||||||
|
@Input() link: Link;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private linkService: LinkService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
stopCapture() {
|
||||||
|
this.linkService.stopCaptureOnLink(this.server, this.link).subscribe(() => {});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
<button mat-menu-item *ngIf="!link.suspend" (click)="suspendLink()">
|
||||||
|
<mat-icon>pause</mat-icon>
|
||||||
|
<span>Suspend</span>
|
||||||
|
</button>
|
@ -0,0 +1,22 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { Link } from '../../../../../models/link';
|
||||||
|
import { LinkService } from '../../../../../services/link.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-suspend-link-action',
|
||||||
|
templateUrl: './suspend-link-action.component.html'
|
||||||
|
})
|
||||||
|
export class SuspendLinkActionComponent {
|
||||||
|
@Input() server: Server;
|
||||||
|
@Input() link: Link;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private linkService: LinkService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
suspendLink() {
|
||||||
|
this.link.suspend = true;
|
||||||
|
this.linkService.updateLink(this.server, this.link).subscribe(() => {});
|
||||||
|
}
|
||||||
|
}
|
@ -31,12 +31,27 @@
|
|||||||
[server]="server"
|
[server]="server"
|
||||||
[link]="links[0]"
|
[link]="links[0]"
|
||||||
></app-start-capture-action>
|
></app-start-capture-action>
|
||||||
|
<app-stop-capture-action
|
||||||
|
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
|
||||||
|
[server]="server"
|
||||||
|
[link]="links[0]"
|
||||||
|
></app-stop-capture-action>
|
||||||
<app-packet-filters-action
|
<app-packet-filters-action
|
||||||
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
|
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
[project]="project"
|
[project]="project"
|
||||||
[link]="links[0]"
|
[link]="links[0]"
|
||||||
></app-packet-filters-action>
|
></app-packet-filters-action>
|
||||||
|
<app-resume-link-action
|
||||||
|
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
|
||||||
|
[server]="server"
|
||||||
|
[link]="links[0]"
|
||||||
|
></app-resume-link-action>
|
||||||
|
<app-suspend-link-action
|
||||||
|
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1"
|
||||||
|
[server]="server"
|
||||||
|
[link]="links[0]"
|
||||||
|
></app-suspend-link-action>
|
||||||
<app-delete-action
|
<app-delete-action
|
||||||
*ngIf="!projectService.isReadOnly(project)"
|
*ngIf="!projectService.isReadOnly(project)"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<h1 mat-dialog-title>Packet filters</h1>
|
<h1 mat-dialog-title>Packet filters</h1>
|
||||||
|
|
||||||
<div class="modal-form-container">
|
<div class="modal-form-container" class="content">
|
||||||
<mat-tab-group *ngIf="this.filters">
|
<mat-tab-group *ngIf="this.filters">
|
||||||
<mat-tab label="Frequency drop">
|
<mat-tab label="Frequency drop">
|
||||||
<mat-form-field class="input-field">
|
<mat-form-field class="input-field">
|
||||||
@ -32,11 +32,13 @@
|
|||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="bottom-bar">
|
||||||
<div mat-dialog-actions>
|
<div class="spacer"></div>
|
||||||
|
<div mat-dialog-actions layout="row" class="dialog-actions">
|
||||||
<button mat-button (click)="onNoClick()" color="accent">Cancel</button>
|
<button mat-button (click)="onNoClick()" color="accent">Cancel</button>
|
||||||
<button mat-button (click)="onResetClick()" color="accent">Reset</button>
|
<button mat-button (click)="onResetClick()" color="accent">Reset</button>
|
||||||
<button mat-button (click)="onYesClick()" tabindex="2" mat-raised-button color="primary">Apply</button>
|
<button mat-button (click)="onYesClick()" tabindex="2" mat-raised-button color="primary">Apply</button>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<button mat-button (click)="onHelpClick()" color="accent">Help</button>
|
<button mat-button (click)="onHelpClick()" color="accent">Help</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
.spacer {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
height: 25px;
|
height: 25px;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<h1 mat-dialog-title>Packet capture</h1>
|
<h1 mat-dialog-title>Packet capture</h1>
|
||||||
|
|
||||||
<div class="modal-form-container">
|
<div class="modal-form-container">
|
||||||
|
<form [formGroup]="inputForm">
|
||||||
<mat-form-field class="input-field">
|
<mat-form-field class="input-field">
|
||||||
<mat-select
|
<mat-select
|
||||||
placeholder="Link type"
|
placeholder="Link type"
|
||||||
[(ngModel)]="linkType">
|
formControlName="linkType">
|
||||||
<mat-option *ngFor="let type of linkTypes" [value]="type[1]">
|
<mat-option *ngFor="let type of linkTypes" [value]="type[1]">
|
||||||
{{type[0]}}
|
{{type[0]}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
@ -13,9 +14,10 @@
|
|||||||
<mat-form-field class="input-field">
|
<mat-form-field class="input-field">
|
||||||
<input
|
<input
|
||||||
placeholder="File name"
|
placeholder="File name"
|
||||||
matInput type="text"
|
formControlName="fileName"
|
||||||
[(ngModel)]="filename" >
|
matInput type="text">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div mat-dialog-actions>
|
<div mat-dialog-actions>
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
.input-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
@ -5,6 +5,8 @@ import { MatDialogRef } from '@angular/material';
|
|||||||
import { PacketFiltersDialogComponent } from '../packet-filters/packet-filters.component';
|
import { PacketFiltersDialogComponent } from '../packet-filters/packet-filters.component';
|
||||||
import { LinkService } from '../../../../services/link.service';
|
import { LinkService } from '../../../../services/link.service';
|
||||||
import { CapturingSettings } from '../../../../models/capturingSettings';
|
import { CapturingSettings } from '../../../../models/capturingSettings';
|
||||||
|
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
|
import { ToasterService } from '../../../../services/toaster.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-start-capture',
|
selector: 'app-start-capture',
|
||||||
@ -15,14 +17,19 @@ export class StartCaptureDialogComponent implements OnInit {
|
|||||||
server: Server;
|
server: Server;
|
||||||
link: Link;
|
link: Link;
|
||||||
linkTypes = [];
|
linkTypes = [];
|
||||||
|
inputForm: FormGroup;
|
||||||
linkType: string;
|
|
||||||
fileName: string;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dialogRef: MatDialogRef<PacketFiltersDialogComponent>,
|
private dialogRef: MatDialogRef<PacketFiltersDialogComponent>,
|
||||||
private linkService: LinkService
|
private linkService: LinkService,
|
||||||
) {}
|
private formBuilder: FormBuilder,
|
||||||
|
private toasterService: ToasterService
|
||||||
|
) {
|
||||||
|
this.inputForm = this.formBuilder.group({
|
||||||
|
linkType: new FormControl('', Validators.required),
|
||||||
|
fileName: new FormControl('', Validators.required)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (this.link.link_type === 'ethernet') {
|
if (this.link.link_type === 'ethernet') {
|
||||||
@ -40,15 +47,19 @@ export class StartCaptureDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onYesClick() {
|
onYesClick() {
|
||||||
|
if (this.inputForm.invalid) {
|
||||||
|
this.toasterService.error(`Fill all required fields`);
|
||||||
|
} else {
|
||||||
let captureSettings: CapturingSettings = {
|
let captureSettings: CapturingSettings = {
|
||||||
capture_file_name: this.fileName,
|
capture_file_name: this.inputForm.get('fileName').value,
|
||||||
data_link_type: this.linkType
|
data_link_type: this.inputForm.get('linkType').value
|
||||||
};
|
};
|
||||||
|
|
||||||
this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => {
|
this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onNoClick() {
|
onNoClick() {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
|
@ -11,6 +11,7 @@ export class Link {
|
|||||||
link_type: string;
|
link_type: string;
|
||||||
nodes: LinkNode[];
|
nodes: LinkNode[];
|
||||||
project_id: string;
|
project_id: string;
|
||||||
|
suspend: boolean;
|
||||||
|
|
||||||
distance: number; // this is not from server
|
distance: number; // this is not from server
|
||||||
length: number; // this is not from server
|
length: number; // this is not from server
|
||||||
|
Reference in New Issue
Block a user