From 01d2fc2d438180d1397dfbf86630352e2bcfbb86 Mon Sep 17 00:00:00 2001 From: Piotr Pekala Date: Mon, 18 Nov 2019 04:25:54 -0800 Subject: [PATCH 1/3] Initial implementation added --- .../import-config-action.component.html | 8 ++++++- .../import-config-action.component.scss | 3 +++ .../import-config-action.component.ts | 24 +++++++++++++++---- .../context-menu/context-menu.component.html | 6 ++--- 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.scss diff --git a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html index a8cc1358..66661e83 100644 --- a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html +++ b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html @@ -1,4 +1,10 @@ - diff --git a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.scss b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.scss new file mode 100644 index 00000000..0f602793 --- /dev/null +++ b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.scss @@ -0,0 +1,3 @@ +.non-visible { + display: none; +} diff --git a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts index 5adba173..056eb5df 100644 --- a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts +++ b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts @@ -2,18 +2,34 @@ import { Component, Input } 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'; @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; - constructor() {} + constructor( + private nodeService: NodeService, + private toasterService: ToasterService + ) {} - importConfig() { - //needs implementation + 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(); + } + this.nodeService.saveConfiguration(this.server, this.node, content).subscribe(() => { + this.toasterService.success(`Configuration for node ${this.node.name} imported.`); + }); + }; + fileReader.readAsText(file); } } diff --git a/src/app/components/project-map/context-menu/context-menu.component.html b/src/app/components/project-map/context-menu/context-menu.component.html index 397b7bf7..d696b14d 100644 --- a/src/app/components/project-map/context-menu/context-menu.component.html +++ b/src/app/components/project-map/context-menu/context-menu.component.html @@ -59,14 +59,14 @@ [project]="project" [node]="nodes[0]" > - - + > Date: Mon, 18 Nov 2019 05:47:44 -0800 Subject: [PATCH 2/3] Dialog to choose config type to export --- src/app/app.module.ts | 7 +++-- .../export-config-action.component.ts | 30 ++++++++++++++++--- .../config-dialog.component.html | 16 ++++++++++ .../config-dialog.component.scss | 5 ++++ .../config-dialog.component.spec.ts | 0 .../config-dialog/config-dialog.component.ts | 17 +++++++++++ 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.html create mode 100644 src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.scss create mode 100644 src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.spec.ts create mode 100644 src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index f6452a5a..d702ab43 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -249,6 +249,7 @@ import { PageNotFoundComponent } from './components/page-not-found/page-not-foun import { AlignHorizontallyActionComponent } from './components/project-map/context-menu/actions/align-horizontally/align-horizontally.component'; 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 { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component'; if (environment.production) { Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', { @@ -420,7 +421,8 @@ if (environment.production) { PageNotFoundComponent, AlignHorizontallyActionComponent, AlignVerticallyActionComponent, - ConfirmationBottomSheetComponent + ConfirmationBottomSheetComponent, + ConfigDialogComponent ], imports: [ BrowserModule, @@ -544,7 +546,8 @@ if (environment.production) { ChooseNameDialogComponent, NavigationDialogComponent, ScreenshotDialogComponent, - ConfirmationBottomSheetComponent + ConfirmationBottomSheetComponent, + ConfigDialogComponent ], bootstrap: [AppComponent] }) diff --git a/src/app/components/project-map/context-menu/actions/export-config/export-config-action.component.ts b/src/app/components/project-map/context-menu/actions/export-config/export-config-action.component.ts index 204a6ee1..edc77de2 100644 --- a/src/app/components/project-map/context-menu/actions/export-config/export-config-action.component.ts +++ b/src/app/components/project-map/context-menu/actions/export-config/export-config-action.component.ts @@ -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) { diff --git a/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.html b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.html new file mode 100644 index 00000000..86ff530d --- /dev/null +++ b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.html @@ -0,0 +1,16 @@ +

Choose configuration file

+ + diff --git a/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.scss b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.scss new file mode 100644 index 00000000..655685b5 --- /dev/null +++ b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.scss @@ -0,0 +1,5 @@ +.container { + width: 100%; + display: flex; + justify-content: space-between; +} diff --git a/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.spec.ts b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.ts b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.ts new file mode 100644 index 00000000..e156e5d1 --- /dev/null +++ b/src/app/components/project-map/context-menu/dialogs/config-dialog/config-dialog.component.ts @@ -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, + ) {} + + close(fileType: string) { + this.dialogRef.close(fileType); + } +} From ff5d79f38f1fef1f9ad47305638033b831af8fde Mon Sep 17 00:00:00 2001 From: Piotr Pekala Date: Mon, 18 Nov 2019 07:21:17 -0800 Subject: [PATCH 3/3] Dialog for im porting private config added --- .../import-config-action.component.html | 4 +- .../import-config-action.component.ts | 39 ++++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html index 66661e83..6325dabc 100644 --- a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html +++ b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.html @@ -2,9 +2,9 @@ type="file" accept=".txt, .vpc" class="non-visible" - #file + #fileInput (change)="importConfig($event)"/> - diff --git a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts index 056eb5df..830d02ee 100644 --- a/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts +++ b/src/app/components/project-map/context-menu/actions/import-config/import-config-action.component.ts @@ -1,8 +1,10 @@ -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', @@ -12,12 +14,32 @@ import { ToasterService } from '../../../../../services/toaster.service'; export class ImportConfigActionComponent { @Input() server: Server; @Input() node: Node; + @ViewChild('fileInput', {static: false}) fileInput: ElementRef; + configType: string; constructor( private nodeService: NodeService, - private toasterService: ToasterService + private toasterService: ToasterService, + private dialog: MatDialog ) {} + 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(); @@ -26,9 +48,16 @@ export class ImportConfigActionComponent { if (typeof content !== 'string'){ content = content.toString(); } - this.nodeService.saveConfiguration(this.server, this.node, content).subscribe(() => { - this.toasterService.success(`Configuration for node ${this.node.name} imported.`); - }); + + 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); }