diff --git a/src/app/components/project-map/project-map.component.ts b/src/app/components/project-map/project-map.component.ts
index afa251ec..1df3040d 100644
--- a/src/app/components/project-map/project-map.component.ts
+++ b/src/app/components/project-map/project-map.component.ts
@@ -181,6 +181,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
}),
mergeMap((project: Project) => {
this.project = project;
+ this.projectService.open(this.server, this.project.project_id);
this.title.setTitle(this.project.name);
if (this.mapSettingsService.interfaceLabels.has(project.project_id)) {
diff --git a/src/app/components/template/template.component.html b/src/app/components/template/template.component.html
index a5b2a19b..da726c73 100644
--- a/src/app/components/template/template.component.html
+++ b/src/app/components/template/template.component.html
@@ -1 +1,63 @@
-
+
+
+
+
+
+
+
+
+
+
+
+ {{type}}
+
+
+
+
+
+
diff --git a/src/app/components/template/template.component.scss b/src/app/components/template/template.component.scss
index e69de29b..78753b14 100644
--- a/src/app/components/template/template.component.scss
+++ b/src/app/components/template/template.component.scss
@@ -0,0 +1,55 @@
+::ng-deep .mat-menu-panel {
+ max-width: 400px;
+ max-height: 500px;
+}
+
+.menu {
+ width: 100%;
+ overflow-y: scroll;
+ scrollbar-color: darkgrey #263238;
+ scrollbar-width: thin;
+}
+
+::-webkit-scrollbar {
+ width: 0.5em;
+}
+
+::-webkit-scrollbar-track {
+ -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
+}
+
+::-webkit-scrollbar-thumb {
+ background-color: darkgrey;
+ outline: 1px solid #263238;
+}
+
+.form-field {
+ width: 90%;
+ margin-left: 5%;
+ margin-right: 5%;
+}
+
+.image {
+ width: 65px;
+ height: 65px;
+ filter: invert(0);
+ --webkit-filter: invert(0)!important;
+}
+
+.templateList {
+ width: 100%;
+}
+
+.templateRow {
+ display: flex;
+ margin-bottom: 10px;
+}
+
+.templateText {
+ text-overflow: ellipsis;
+}
+
+.templateIcon {
+ width: 80px!important;
+ padding: 10px;
+}
diff --git a/src/app/components/template/template.component.ts b/src/app/components/template/template.component.ts
index 3814b1a2..cd8d29dd 100644
--- a/src/app/components/template/template.component.ts
+++ b/src/app/components/template/template.component.ts
@@ -5,6 +5,9 @@ import { TemplateListDialogComponent, NodeAddedEvent } from './template-list-dia
import { Server } from '../../models/server';
import { Template } from '../../models/template';
import { Project } from '../../models/project';
+import { TemplateService } from '../../services/template.service';
+import { MapScaleService } from '../../services/mapScale.service';
+import { SymbolService } from '../../services/symbol.service';
@Component({
selector: 'app-template',
@@ -16,11 +19,72 @@ export class TemplateComponent implements OnInit {
@Input() project: Project;
@Output() onNodeCreation = new EventEmitter();
- constructor(private dialog: MatDialog) {}
+ templates: Template[] = [];
+ filteredTemplates: Template[] = [];
+ searchText: string = '';
+ templateTypes: string[] = ['all', 'cloud', 'ethernet_hub', 'ethernet_switch', 'docker', 'dynamips', 'vpcs', 'traceng', 'virtualbox', 'vmware', 'iou', 'qemu'];
+ selectedType: string;
- ngOnInit() {}
+ movementX: number;
+ movementY: number;
- listTemplatesModal() {
+ startX: number;
+ startY: number;
+
+ constructor(
+ private dialog: MatDialog,
+ private templateService: TemplateService,
+ private scaleService: MapScaleService,
+ private symbolService: SymbolService
+ ) {}
+
+ ngOnInit() {
+ this.templateService.list(this.server).subscribe((listOfTemplates: Template[]) => {
+ this.filteredTemplates = listOfTemplates;
+ this.templates = listOfTemplates;
+ });
+ this.symbolService.list(this.server);
+ }
+
+ filterTemplates(event) {
+ let temporaryTemplates = this.templates.filter(item => {
+ return item.name.toLowerCase().includes(this.searchText.toLowerCase());
+ });
+
+ if (this.selectedType === 'all') {
+ this.filteredTemplates = temporaryTemplates;
+ } else {
+ this.filteredTemplates = temporaryTemplates.filter(t => t.template_type === this.selectedType);
+ }
+ }
+
+ dragStart(ev) {
+ let elemRect = (event.target as HTMLElement).getBoundingClientRect();
+
+ this.startX = (event as MouseEvent).clientX;
+ this.startY = (event as MouseEvent).clientY;
+
+ this.movementY = elemRect.top - (event as MouseEvent).clientY;
+ this.movementX = elemRect.left - (event as MouseEvent).clientX;
+ }
+
+ dragEnd(ev, template: Template) {
+ this.symbolService.raw(this.server, template.symbol.substring(1)).subscribe((symbolSvg: string) => {
+ let width = +symbolSvg.split("width=\"")[1].split("\"")[0] ? +symbolSvg.split("width=\"")[1].split("\"")[0] : 0;
+ let scale = this.scaleService.getScale();
+
+ let nodeAddedEvent: NodeAddedEvent = {
+ template: template,
+ server: 'local',
+ numberOfNodes: 1,
+ x: (this.startX + ev.x - this.project.scene_width/2 - (width/2)) * scale + window.scrollX ,
+ y: (this.startY + ev.y - this.project.scene_height/2) * scale + window.scrollY
+ };
+ this.onNodeCreation.emit(nodeAddedEvent);
+ });
+ }
+
+ openDialog() {
const dialogRef = this.dialog.open(TemplateListDialogComponent, {
width: '600px',
data: {
@@ -37,4 +101,8 @@ export class TemplateComponent implements OnInit {
}
});
}
+
+ getImageSourceForTemplate(template: Template) {
+ return `http://${this.server.host}:${this.server.port}/v2${template.symbol.substring(1)}/raw`;
+ }
}
diff --git a/src/app/services/symbol.service.ts b/src/app/services/symbol.service.ts
index cba041d0..b5476d6b 100644
--- a/src/app/services/symbol.service.ts
+++ b/src/app/services/symbol.service.ts
@@ -19,6 +19,10 @@ export class SymbolService {
return this.symbols.getValue().find((symbol: Symbol) => symbol.symbol_id === symbol_id);
}
+ getByFilename(symbol_filename: string) {
+ return this.symbols.getValue().find((symbol: Symbol) => symbol.filename === symbol_filename);
+ }
+
add(server: Server, symbolName: string, symbol: string) {
this.cache = null;
return this.httpServer.post(server, `/symbols/${symbolName}/raw`, symbol)