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)