Merge branch 'master' into Some-issues-with-projects-that-don't-exist

This commit is contained in:
Piotr Pekala 2019-11-18 07:23:55 -08:00
commit 9ade466b80
17 changed files with 1587 additions and 553 deletions

View File

@ -65,12 +65,14 @@
"ini": "^1.3.5",
"material-design-icons": "^3.0.1",
"ng2-file-upload": "^1.3.0",
"ngx-device-detector": "^1.3.16",
"ngx-electron": "^2.1.1",
"node-fetch": "^2.6.0",
"notosans-fontface": "^1.1.0",
"raven-js": "^3.27.2",
"rxjs": "^6.5.3",
"rxjs-compat": "^6.5.3",
"save-html-as-image": "^1.2.0",
"save-svg-as-png": "^1.4.14",
"svg-crowbar": "^0.2.4",
"tree-kill": "^1.2.1",
@ -118,4 +120,4 @@
"typescript"
]
}
}
}

View File

@ -250,6 +250,8 @@ import { AlignHorizontallyActionComponent } from './components/project-map/conte
import { AlignVerticallyActionComponent } from './components/project-map/context-menu/actions/align_vertically/align-vertically.component';
import { ConfirmationBottomSheetComponent } from './components/projects/confirmation-bottomsheet/confirmation-bottomsheet.component';
import { NotificationService } from './services/notification.service';
import { DeviceDetectorModule } from 'ngx-device-detector';
import { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component';
if (environment.production) {
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
@ -421,7 +423,8 @@ if (environment.production) {
PageNotFoundComponent,
AlignHorizontallyActionComponent,
AlignVerticallyActionComponent,
ConfirmationBottomSheetComponent
ConfirmationBottomSheetComponent,
ConfigDialogComponent
],
imports: [
BrowserModule,
@ -440,7 +443,8 @@ if (environment.production) {
ResizableModule,
DragAndDropModule,
DragDropModule,
MATERIAL_IMPORTS
MATERIAL_IMPORTS,
DeviceDetectorModule.forRoot()
],
providers: [
SettingsService,
@ -546,7 +550,8 @@ if (environment.production) {
ChooseNameDialogComponent,
NavigationDialogComponent,
ScreenshotDialogComponent,
ConfirmationBottomSheetComponent
ConfirmationBottomSheetComponent,
ConfigDialogComponent
],
bootstrap: [AppComponent]
})

View File

@ -1,4 +1,4 @@
<svg #svg class="map" preserveAspectRatio="none" movingCanvas zoomingCanvas>
<svg id="map" #svg class="map" preserveAspectRatio="none" movingCanvas zoomingCanvas>
<filter id="grayscale"><feColorMatrix id="feGrayscale" type="saturate" values="0" /></filter>
<defs>
<pattern id="gridDrawing" attr.width="{{project.drawing_grid_size}}" attr.height="{{project.drawing_grid_size}}" patternUnits="userSpaceOnUse">

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -28,7 +28,7 @@ export class AdbutlerComponent implements OnInit {
this.htmlCode = response['placements'].placement_1.body;
this.ad.nativeElement.insertAdjacentHTML('beforeend', this.htmlCode);
},
error => this.toasterService.error(error)
error => {}
);
}
}

View File

@ -2,6 +2,8 @@ import { Component, Input } from '@angular/core';
import { Node } from '../../../../../cartography/models/node';
import { NodeService } from '../../../../../services/node.service';
import { Server } from '../../../../../models/server';
import { MatDialog } from '@angular/material';
import { ConfigDialogComponent } from '../../dialogs/config-dialog/config-dialog.component';
@Component({
selector: 'app-export-config-action',
@ -12,13 +14,33 @@ export class ExportConfigActionComponent {
@Input() node: Node;
constructor(
private nodeService: NodeService
private nodeService: NodeService,
private dialog: MatDialog
) {}
exportConfig() {
this.nodeService.getStartupConfiguration(this.server, this.node).subscribe((config: any) => {
this.downloadByHtmlTag(config);
});
if (this.node.node_type === 'vpcs') {
this.nodeService.getStartupConfiguration(this.server, this.node).subscribe((config: any) => {
this.downloadByHtmlTag(config);
});
} else {
const dialogRef = this.dialog.open(ConfigDialogComponent, {
width: '500px',
autoFocus: false
});
let instance = dialogRef.componentInstance;
dialogRef.afterClosed().subscribe((configType: string) => {
if (configType === 'startup-config') {
this.nodeService.getStartupConfiguration(this.server, this.node).subscribe((config: any) => {
this.downloadByHtmlTag(config);
});
} else if (configType === 'private-config') {
this.nodeService.getPrivateConfiguration(this.server, this.node).subscribe((config: any) => {
this.downloadByHtmlTag(config);
});
}
});
}
}
private downloadByHtmlTag(config: string) {

View File

@ -1,4 +1,10 @@
<button mat-menu-item (click)="importConfig()">
<input
type="file"
accept=".txt, .vpc"
class="non-visible"
#fileInput
(change)="importConfig($event)"/>
<button mat-menu-item (click)="triggerClick()">
<mat-icon>call_received</mat-icon>
<span>Import config</span>
</button>

View File

@ -0,0 +1,3 @@
.non-visible {
display: none;
}

View File

@ -1,19 +1,64 @@
import { Component, Input } from '@angular/core';
import { Component, Input, ViewChild, ElementRef } from '@angular/core';
import { Node } from '../../../../../cartography/models/node';
import { NodeService } from '../../../../../services/node.service';
import { Server } from '../../../../../models/server';
import { ToasterService } from '../../../../../services/toaster.service';
import { MatDialog } from '@angular/material';
import { ConfigDialogComponent } from '../../dialogs/config-dialog/config-dialog.component';
@Component({
selector: 'app-import-config-action',
templateUrl: './import-config-action.component.html'
templateUrl: './import-config-action.component.html',
styleUrls: ['./import-config-action.component.scss']
})
export class ImportConfigActionComponent {
@Input() server: Server;
@Input() node: Node;
@ViewChild('fileInput', {static: false}) fileInput: ElementRef;
configType: string;
constructor() {}
constructor(
private nodeService: NodeService,
private toasterService: ToasterService,
private dialog: MatDialog
) {}
importConfig() {
//needs implementation
triggerClick() {
if (this.node.node_type !== 'vpcs') {
const dialogRef = this.dialog.open(ConfigDialogComponent, {
width: '500px',
autoFocus: false
});
let instance = dialogRef.componentInstance;
dialogRef.afterClosed().subscribe((configType: string) => {
this.configType = configType;
this.fileInput.nativeElement.click();
});
} else {
this.configType = 'startup-config';
this.fileInput.nativeElement.click();
}
}
importConfig(event) {
let file: File = event.target.files[0];
let fileReader: FileReader = new FileReader();
fileReader.onload = (e) => {
let content: string | ArrayBuffer = fileReader.result;
if (typeof content !== 'string'){
content = content.toString();
}
if (this.configType === 'startup-config') {
this.nodeService.saveConfiguration(this.server, this.node, content).subscribe(() => {
this.toasterService.success(`Configuration for node ${this.node.name} imported.`);
});
} else if (this.configType === 'private-config') {
this.nodeService.savePrivateConfiguration(this.server, this.node, content).subscribe(() => {
this.toasterService.success(`Configuration for node ${this.node.name} imported.`);
});
}
};
fileReader.readAsText(file);
}
}

View File

@ -59,14 +59,14 @@
[project]="project"
[node]="nodes[0]"
></app-edit-config-action>
<app-export-config-action *ngIf="nodes.length===1 && nodes[0].node_type==='vpcs'"
<app-export-config-action *ngIf="nodes.length===1 && (nodes[0].node_type==='vpcs' || nodes[0].node_type==='iou' || nodes[0].node_type==='dynamips')"
[server]="server"
[node]="nodes[0]"
></app-export-config-action>
<!-- <app-import-config-action *ngIf="nodes.length===1"
<app-import-config-action *ngIf="nodes.length===1 && (nodes[0].node_type==='vpcs' || nodes[0].node_type==='iou' || nodes[0].node_type==='dynamips')"
[server]="server"
[node]="nodes[0]"
></app-import-config-action> -->
></app-import-config-action>
<app-move-layer-up-action
*ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)"
[server]="server"

View File

@ -0,0 +1,16 @@
<h1 mat-dialog-title>Choose configuration file</h1>
<div class="modal-form-container">
<div class="container">
<div>
<button mat-raised-button color="primary" (click)="close('startup-config')">
startup configuration
</button>
</div>
<div>
<button mat-raised-button color="primary" (click)="close('private-config')">
private configuration
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,5 @@
.container {
width: 100%;
display: flex;
justify-content: space-between;
}

View File

@ -0,0 +1,17 @@
import { Component, Input } from '@angular/core';
import { MatDialogRef } from '@angular/material';
@Component({
selector: 'app-config-dialog',
templateUrl: './config-dialog.component.html',
styleUrls: ['./config-dialog.component.scss']
})
export class ConfigDialogComponent {
constructor(
public dialogRef: MatDialogRef<ConfigDialogComponent>,
) {}
close(fileType: string) {
this.dialogRef.close(fileType);
}
}

View File

@ -11,6 +11,7 @@ import downloadSvg from 'svg-crowbar';
import { ElectronService } from 'ngx-electron';
import { MatDialog } from '@angular/material';
import { ScreenshotDialogComponent, Screenshot } from '../screenshot-dialog/screenshot-dialog.component';
import { saveAsPng, saveAsJpeg } from 'save-html-as-image';
@Component({

View File

@ -1,9 +1,9 @@
<h1 mat-dialog-title>Take a screenshot</h1>
<!-- <mat-radio-group class="radio-group" aria-label="Sorting">
<mat-radio-group class="radio-group" aria-label="Sorting">
<mat-radio-button value="1" (click)="setFiletype('svg')" checked>SVG</mat-radio-button>
<mat-radio-button [disabled]="!isPngAvailable" value="2" (click)="setFiletype('png')">PNG</mat-radio-button>
</mat-radio-group> -->
</mat-radio-group>
<form [formGroup]="nameForm" class="name-form">
<mat-form-field class="name-form">

View File

@ -3,6 +3,7 @@ import { MatDialogRef } from '@angular/material';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { ToasterService } from '../../../services/toaster.service';
import { ElectronService } from 'ngx-electron';
import { DeviceDetectorService } from 'ngx-device-detector';
@Component({
@ -19,13 +20,13 @@ export class ScreenshotDialogComponent implements OnInit {
public dialogRef: MatDialogRef<ScreenshotDialogComponent>,
private toasterService: ToasterService,
private formBuilder: FormBuilder,
private electronService: ElectronService
private electronService: ElectronService,
private deviceService: DeviceDetectorService
) {
this.nameForm = this.formBuilder.group({
screenshotName: new FormControl(null, [Validators.required])
});
this.isPngAvailable = this.electronService.isWindows;
this.isPngAvailable = this.electronService.isWindows || (this.deviceService.getDeviceInfo().os==='Windows');
}
ngOnInit() {}

1969
yarn.lock

File diff suppressed because it is too large Load Diff