-
+
diff --git a/src/app/components/template/template-list-dialog/template-list-dialog.component.scss b/src/app/components/template/template-list-dialog/template-list-dialog.component.scss
index 6b2a2818..62ee0283 100644
--- a/src/app/components/template/template-list-dialog/template-list-dialog.component.scss
+++ b/src/app/components/template/template-list-dialog/template-list-dialog.component.scss
@@ -8,8 +8,8 @@
}
.mat-table {
- overflow: auto;
- max-height: 400px;
+ height: 200px;
+ overflow: scroll;
}
.mat-form-field {
@@ -17,11 +17,21 @@
flex-grow: 1;
}
+.form-field {
+ width: 100%;
+}
+
div {
scrollbar-color: darkgrey #263238;
scrollbar-width: thin;
}
+h6 {
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #0097a7;
+}
+
mat-table {
scrollbar-color: darkgrey #263238;
scrollbar-width: thin;
@@ -36,6 +46,17 @@ mat-table {
}
::-webkit-scrollbar-thumb {
-background-color: darkgrey;
-outline: 1px solid #263238;
+ background-color: darkgrey;
+ outline: 1px solid #263238;
+}
+
+.filterBox {
+ display: flex;
+ justify-content: space-between;
+}
+
+.title-container {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
}
diff --git a/src/app/components/template/template-list-dialog/template-list-dialog.component.ts b/src/app/components/template/template-list-dialog/template-list-dialog.component.ts
index 471305f3..37fa20e0 100644
--- a/src/app/components/template/template-list-dialog/template-list-dialog.component.ts
+++ b/src/app/components/template/template-list-dialog/template-list-dialog.component.ts
@@ -1,13 +1,14 @@
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { DataSource } from '@angular/cdk/collections';
-
import { Observable, BehaviorSubject, fromEvent, merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
-
import { Server } from '../../../models/server';
import { TemplateService } from '../../../services/template.service';
import { Template } from '../../../models/template';
+import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
+import { ToasterService } from '../../../services/toaster.service';
+import { Project } from '../../../models/project';
@Component({
selector: 'app-template-list-dialog',
@@ -16,44 +17,88 @@ import { Template } from '../../../models/template';
})
export class TemplateListDialogComponent implements OnInit {
server: Server;
- templateDatabase: TemplateDatabase;
- dataSource: TemplateDataSource;
- displayedColumns = ['name'];
-
- @ViewChild('filter', {static: true}) filter: ElementRef;
+ project: Project;
+ templateTypes: string[] = ['cloud', 'ethernet_hub', 'ethernet_switch', 'docker', 'dynamips', 'vpcs', 'traceng', 'virtualbox', 'vmware', 'iou', 'qemu'];
+ selectedType: string;
+ configurationForm: FormGroup;
+ positionForm: FormGroup;
+ templates: Template[];
+ filteredTemplates: Template[];
+ selectedTemplate: Template;
+ searchText: string = '';
constructor(
public dialogRef: MatDialogRef
,
private templateService: TemplateService,
- @Inject(MAT_DIALOG_DATA) public data: any
+ private formBuilder: FormBuilder,
+ @Inject(MAT_DIALOG_DATA) public data: any,
+ private toasterService: ToasterService
) {
this.server = data['server'];
+ this.project = data['project'];
+ this.configurationForm = this.formBuilder.group({
+ name: new FormControl('new node', Validators.required),
+ numberOfNodes: new FormControl(1, Validators.required)
+ });
+ this.positionForm = this.formBuilder.group({
+ top: new FormControl(0, Validators.required),
+ left: new FormControl(0, Validators.required)
+ });
}
ngOnInit() {
- this.templateDatabase = new TemplateDatabase(this.server, this.templateService);
- this.dataSource = new TemplateDataSource(this.templateDatabase);
-
- fromEvent(this.filter.nativeElement, 'keyup')
- .pipe(
- debounceTime(150),
- distinctUntilChanged()
- )
- .subscribe(() => {
- if (!this.dataSource) {
- return;
- }
- this.dataSource.filter = this.filter.nativeElement.value;
- });
+ this.templateService.list(this.server).subscribe((listOfTemplates: Template[]) => {
+ this.filteredTemplates = listOfTemplates;
+ this.templates = listOfTemplates;
+ });
}
onNoClick(): void {
this.dialogRef.close();
}
- addNode(template: Template): void {
- this.dialogRef.close(template);
+ filterTemplates(event) {
+ let temporaryTemplates = this.templates.filter( item => {
+ return item.name.toLowerCase().includes(this.searchText.toLowerCase());
+ });
+ this.filteredTemplates = temporaryTemplates.filter(t => t.template_type === event.value.toString());
}
+
+ chooseTemplate(event) {
+ this.selectedTemplate = event.value;
+ this.configurationForm.controls['name'].setValue(this.selectedTemplate.default_name_format);
+ }
+
+ onAddClick(): void {
+ if (!this.selectedTemplate || this.filteredTemplates.length === 0) {
+ this.toasterService.error('Please firstly choose template.');
+ } else if (!this.positionForm.valid || !this.configurationForm.valid) {
+ this.toasterService.error('Please fill all required fields.');
+ } else {
+ let x: number = this.positionForm.get('left').value;
+ let y: number = this.positionForm.get('top').value;
+ if (x>(this.project.scene_width/2) || x<-(this.project.scene_width/2) || y>(this.project.scene_height/2) || y<-(this.project.scene_height)) {
+ this.toasterService.error('Please set correct position values.')
+ } else {
+ let event: NodeAddedEvent = {
+ template: this.selectedTemplate,
+ name: this.configurationForm.get('name').value,
+ numberOfNodes: this.configurationForm.get('numberOfNodes').value,
+ x: x,
+ y: y
+ };
+ this.dialogRef.close(event);
+ }
+ }
+ }
+}
+
+export interface NodeAddedEvent {
+ template: Template,
+ name: string,
+ numberOfNodes: number;
+ x: number;
+ y: number;
}
export class TemplateDatabase {
diff --git a/src/app/components/template/template.component.html b/src/app/components/template/template.component.html
index c4fec0c6..a9535011 100644
--- a/src/app/components/template/template.component.html
+++ b/src/app/components/template/template.component.html
@@ -1 +1 @@
-
+
diff --git a/src/app/components/template/template.component.ts b/src/app/components/template/template.component.ts
index 9b6675ca..8b833e40 100644
--- a/src/app/components/template/template.component.ts
+++ b/src/app/components/template/template.component.ts
@@ -1,9 +1,10 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { MatDialog } from '@angular/material';
-import { TemplateListDialogComponent } from './template-list-dialog/template-list-dialog.component';
+import { TemplateListDialogComponent, NodeAddedEvent } from './template-list-dialog/template-list-dialog.component';
import { Server } from '../../models/server';
import { Template } from '../../models/template';
+import { Project } from '../../models/project';
@Component({
selector: 'app-template',
@@ -12,6 +13,7 @@ import { Template } from '../../models/template';
})
export class TemplateComponent implements OnInit {
@Input() server: Server;
+ @Input() project: Project;
@Output() onNodeCreation = new EventEmitter();
constructor(private dialog: MatDialog) {}
@@ -21,16 +23,16 @@ export class TemplateComponent implements OnInit {
listTemplatesModal() {
const dialogRef = this.dialog.open(TemplateListDialogComponent, {
width: '600px',
- height: '560px',
data: {
- server: this.server
+ server: this.server,
+ project: this.project
},
autoFocus: false
});
- dialogRef.afterClosed().subscribe((template: Template) => {
- if (template !== null) {
- this.onNodeCreation.emit(template);
+ dialogRef.afterClosed().subscribe((nodeAddedEvent: NodeAddedEvent) => {
+ if (nodeAddedEvent !== null) {
+ this.onNodeCreation.emit(nodeAddedEvent);
}
});
}
diff --git a/src/app/filters/templateFilter.pipe.ts b/src/app/filters/templateFilter.pipe.ts
new file mode 100644
index 00000000..7c1e30a1
--- /dev/null
+++ b/src/app/filters/templateFilter.pipe.ts
@@ -0,0 +1,18 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { Template } from '../models/template';
+
+
+@Pipe({
+ name: 'templatefilter'
+})
+export class TemplateFilter implements PipeTransform {
+ transform(items: Template[], searchText: string): any[] {
+ if(!items) return [];
+ if(!searchText) return items;
+
+ searchText = searchText.toLowerCase();
+ return items.filter( item => {
+ return item.name.toLowerCase().includes(searchText);
+ });
+ }
+}
diff --git a/src/app/models/template.ts b/src/app/models/template.ts
index 1dc03032..9a6ef23d 100644
--- a/src/app/models/template.ts
+++ b/src/app/models/template.ts
@@ -7,4 +7,5 @@ export class Template {
name: string;
node_type: string;
symbol: string;
+ template_type: string;
}
diff --git a/src/app/services/node.service.ts b/src/app/services/node.service.ts
index ff1b2bb6..2e8467ae 100644
--- a/src/app/services/node.service.ts
+++ b/src/app/services/node.service.ts
@@ -45,7 +45,7 @@ export class NodeService {
return this.httpServer.post(server, `/projects/${project.project_id}/nodes/reload`, {});
}
- createFromTemplate(server: Server, project: Project, template: Template, x: number, y: number, compute_id: string) {
+ createFromTemplate(server: Server, project: Project, template: Template, x: number, y: number, compute_id: string): Observable {
return this.httpServer.post(server, `/projects/${project.project_id}/templates/${template.template_id}`, {
x: Math.round(x),
y: Math.round(y),