diff --git a/src/app/app.module.ts b/src/app/app.module.ts index fdbce4fe..7cecaf5f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -164,6 +164,7 @@ import { SymbolsMenuComponent } from './components/preferences/common/symbols-me import { SearchFilter } from './filters/searchFilter.pipe'; import { RecentlyOpenedProjectService } from './services/recentlyOpenedProject.service'; import { ServerManagementService } from './services/server-management.service'; +import { DeleteActionComponent } from './components/project-map/context-menu/actions/delete-action/delete-action.component'; if (environment.production) { Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', { @@ -198,6 +199,7 @@ if (environment.production) { MoveLayerUpActionComponent, EditStyleActionComponent, EditTextActionComponent, + DeleteActionComponent, ProjectMapShortcutsComponent, SettingsComponent, PreferencesComponent, diff --git a/src/app/cartography/components/drawing-adding/drawing-adding.component.ts b/src/app/cartography/components/drawing-adding/drawing-adding.component.ts index c4cb1e6c..4553ae81 100644 --- a/src/app/cartography/components/drawing-adding/drawing-adding.component.ts +++ b/src/app/cartography/components/drawing-adding/drawing-adding.component.ts @@ -25,8 +25,8 @@ export class DrawingAddingComponent implements OnInit, OnDestroy { activate() { let listener = (event: MouseEvent) => { - let x = event.clientX - this.context.getZeroZeroTransformationPoint().x; - let y = event.clientY - this.context.getZeroZeroTransformationPoint().y; + let x = event.pageX - this.context.getZeroZeroTransformationPoint().x; + let y = event.pageY - this.context.getZeroZeroTransformationPoint().y; this.drawingsEventSource.pointToAddSelected.emit(new AddedDataEvent(x, y)); this.deactivate(); diff --git a/src/app/cartography/components/text-editor/text-editor.component.ts b/src/app/cartography/components/text-editor/text-editor.component.ts index f8b9fa8e..10549b48 100644 --- a/src/app/cartography/components/text-editor/text-editor.component.ts +++ b/src/app/cartography/components/text-editor/text-editor.component.ts @@ -45,8 +45,8 @@ export class TextEditorComponent implements OnInit, OnDestroy { activateTextAdding() { let addTextListener = (event: MouseEvent) => { - this.leftPosition = event.clientX.toString() + 'px'; - this.topPosition = (event.clientY + window.pageYOffset).toString() + 'px'; + this.leftPosition = event.pageX.toString() + 'px'; + this.topPosition = event.pageY.toString() + 'px'; this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial'); this.temporaryTextElement.nativeElement.focus(); @@ -54,8 +54,8 @@ export class TextEditorComponent implements OnInit, OnDestroy { this.drawingsEventSource.textAdded.emit( new TextAddedDataEvent( this.temporaryTextElement.nativeElement.innerText.replace(/\n$/, ''), - event.clientX, - event.clientY + event.pageX, + event.pageY ) ); this.deactivateTextAdding(); diff --git a/src/app/cartography/widgets/drawings.ts b/src/app/cartography/widgets/drawings.ts index 819bb828..aa240980 100644 --- a/src/app/cartography/widgets/drawings.ts +++ b/src/app/cartography/widgets/drawings.ts @@ -111,15 +111,15 @@ export class DrawingsWidget implements Widget { } } } else { - dy = y - (evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y); - y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y; + dy = y - (evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y); + y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y; if (datum.element.height + dy < 0) { isReflectedVertical = false; y = topEdge; datum.element.height = Math.abs(datum.element.height + evt.dy); } else { - datum.y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y; + datum.y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y; datum.element.height += dy; if (datum.element instanceof EllipseElement) { (datum.element as EllipseElement).cy = @@ -143,7 +143,7 @@ export class DrawingsWidget implements Widget { let top = drag() .on('start', (datum: MapDrawing) => { - y = event.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y; + y = event.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y; bottomEdge = y + datum.element.height; document.body.style.cursor = 'ns-resize'; }) @@ -151,15 +151,15 @@ export class DrawingsWidget implements Widget { const evt = event; if (!isReflectedVertical) { - dy = y - (evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y); - y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y; + dy = y - (evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y); + y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y; if (datum.element.height + dy < 0) { y = bottomEdge; isReflectedVertical = true; datum.element.height = Math.abs(datum.element.height + evt.dy); } else { - datum.y = evt.sourceEvent.clientY - this.context.getZeroZeroTransformationPoint().y; + datum.y = evt.sourceEvent.pageY - this.context.getZeroZeroTransformationPoint().y; datum.element.height += dy; if (datum.element instanceof EllipseElement) { (datum.element as EllipseElement).cy = @@ -207,7 +207,7 @@ export class DrawingsWidget implements Widget { let isReflectedHorizontal: boolean = false; let right = drag() .on('start', (datum: MapDrawing) => { - x = event.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x; + x = event.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x; leftEdge = x + datum.element.width; document.body.style.cursor = 'ew-resize'; }) @@ -215,15 +215,15 @@ export class DrawingsWidget implements Widget { const evt = event; if (!isReflectedHorizontal) { - dx = x - (evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x); - x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x; + dx = x - (evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x); + x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x; if (datum.element.width + dx < 0) { x = leftEdge; isReflectedHorizontal = true; datum.element.width = Math.abs(datum.element.width + evt.dx); } else { - datum.x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x; + datum.x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x; datum.element.width += dx; if (datum.element instanceof EllipseElement) { (datum.element as EllipseElement).cx = @@ -290,15 +290,15 @@ export class DrawingsWidget implements Widget { datum.element.width = datum.element.width + evt.dx < 0 ? 1 : (datum.element.width += evt.dx); } } else { - dx = x - (evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x); - x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x; + dx = x - (evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x); + x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x; if (datum.element.width + dx < 0) { x = rightEdge; isReflectedHorizontal = false; datum.element.width = Math.abs(datum.element.width + evt.dx); } else { - datum.x = evt.sourceEvent.clientX - this.context.getZeroZeroTransformationPoint().x; + datum.x = evt.sourceEvent.pageX - this.context.getZeroZeroTransformationPoint().x; datum.element.width += dx; if (datum.element instanceof EllipseElement) { (datum.element as EllipseElement).cx = diff --git a/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.html b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.html new file mode 100644 index 00000000..a0819a60 --- /dev/null +++ b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.html @@ -0,0 +1,4 @@ + diff --git a/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.spec.ts b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.spec.ts new file mode 100644 index 00000000..ec6a8f5c --- /dev/null +++ b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.spec.ts @@ -0,0 +1,86 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { DeleteActionComponent } from './delete-action.component'; +import { MatIconModule, MatMenuModule } from '@angular/material'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource'; +import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource'; +import { NodeService } from '../../../../../services/node.service'; +import { DrawingService } from '../../../../../services/drawing.service'; +import { MockedDrawingService, MockedNodeService, MockedLinkService } from '../../../project-map.component.spec'; +import { Node } from '../../../../../cartography/models/node'; +import { Drawing } from '../../../../../cartography/models/drawing'; +import { of } from 'rxjs'; +import { LinksDataSource } from '../../../../../cartography/datasources/links-datasource'; +import { LinkService } from '../../../../../services/link.service'; +import { Link } from '../../../../../models/link'; + +describe('DeleteActionComponent', () => { + let component: DeleteActionComponent; + let fixture: ComponentFixture; + let mockedNodeService: MockedNodeService = new MockedNodeService(); + let mockedDrawingService: MockedDrawingService = new MockedDrawingService(); + let mockedLinkService: MockedLinkService = new MockedLinkService(); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [MatIconModule, MatMenuModule, NoopAnimationsModule], + providers: [ + { provide: NodesDataSource, useClass: NodesDataSource }, + { provide: DrawingsDataSource, useClass: DrawingsDataSource }, + { provide: LinksDataSource, useClass: LinksDataSource }, + { provide: NodeService, useValue: mockedNodeService }, + { provide: DrawingService, useValue: mockedDrawingService }, + { provide: LinkService, useValue: mockedLinkService } + ], + declarations: [DeleteActionComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DeleteActionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should call delete action in drawing service', () => { + let node = { node_id: '1' } as Node; + component.nodes = [node]; + let drawing = { drawing_id: '1' } as Drawing; + component.drawings = [drawing]; + component.links = []; + spyOn(mockedDrawingService, 'delete').and.returnValue(of()); + + component.delete(); + + expect(mockedDrawingService.delete).toHaveBeenCalled(); + }); + + it('should call delete action in node service', () => { + let node = { node_id: '1' } as Node; + component.nodes = [node]; + let drawing = { drawing_id: '1' } as Drawing; + component.drawings = [drawing]; + component.links = []; + spyOn(mockedNodeService, 'delete').and.returnValue(of()); + + component.delete(); + + expect(mockedNodeService.delete).toHaveBeenCalled(); + }); + + it('should call delete action in link service', () => { + component.nodes = []; + component.drawings = []; + let link = { link_id: '1', project_id: '1' } as Link; + component.links = [link]; + spyOn(mockedLinkService, 'deleteLink').and.returnValue(of()); + + component.delete(); + + expect(mockedLinkService.deleteLink).toHaveBeenCalled(); + }); +}); diff --git a/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.ts b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.ts new file mode 100644 index 00000000..26629dfc --- /dev/null +++ b/src/app/components/project-map/context-menu/actions/delete-action/delete-action.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Server } from '../../../../../models/server'; +import { Node } from '../../../../../cartography/models/node'; +import { NodesDataSource } from '../../../../../cartography/datasources/nodes-datasource'; +import { NodeService } from '../../../../../services/node.service'; +import { Drawing } from '../../../../../cartography/models/drawing'; +import { DrawingsDataSource } from '../../../../../cartography/datasources/drawings-datasource'; +import { DrawingService } from '../../../../../services/drawing.service'; +import { Link } from '../../../../../models/link'; +import { LinkService } from '../../../../../services/link.service'; +import { LinksDataSource } from '../../../../../cartography/datasources/links-datasource'; + +@Component({ + selector: 'app-delete-action', + templateUrl: './delete-action.component.html' +}) +export class DeleteActionComponent implements OnInit { + @Input() server: Server; + @Input() nodes: Node[]; + @Input() drawings: Drawing[]; + @Input() links: Link[]; + + constructor( + private nodesDataSource: NodesDataSource, + private drawingsDataSource: DrawingsDataSource, + private linksDataSource: LinksDataSource, + private nodeService: NodeService, + private drawingService: DrawingService, + private linkService: LinkService + ) {} + + ngOnInit() {} + + delete() { + this.nodes.forEach((node) => { + this.nodesDataSource.remove(node); + + this.nodeService.delete(this.server, node).subscribe((node: Node) => {}); + }); + + this.drawings.forEach((drawing) => { + this.drawingsDataSource.remove(drawing); + + this.drawingService.delete(this.server, drawing).subscribe((drawing: Drawing) => {}); + }); + + this.links.forEach((link) => { + this.linksDataSource.remove(link); + + this.linkService.deleteLink(this.server, link).subscribe(() => {}); + }); + } +} 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 3146bbbc..0060c9f1 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 @@ -15,16 +15,23 @@ [drawing]="drawings[0]" > + diff --git a/src/app/components/project-map/context-menu/context-menu.component.spec.ts b/src/app/components/project-map/context-menu/context-menu.component.spec.ts index 30c60aef..7832fb7e 100644 --- a/src/app/components/project-map/context-menu/context-menu.component.spec.ts +++ b/src/app/components/project-map/context-menu/context-menu.component.spec.ts @@ -70,7 +70,7 @@ describe('ContextMenuComponent', () => { component.contextMenu = { openMenu() {} } as MatMenuTrigger; var spy = spyOn(component, 'resetCapabilities'); spyOn(component, 'setPosition').and.callFake(() => {}); - component.openMenuForListOfElements([], [], [], 0, 0); + component.openMenuForListOfElements([], [], [], [], 0, 0); expect(spy.calls.any()).toBeTruthy(); }); diff --git a/src/app/components/project-map/context-menu/context-menu.component.ts b/src/app/components/project-map/context-menu/context-menu.component.ts index 45da4d2f..ed34f146 100644 --- a/src/app/components/project-map/context-menu/context-menu.component.ts +++ b/src/app/components/project-map/context-menu/context-menu.component.ts @@ -8,6 +8,7 @@ import { ProjectService } from '../../../services/project.service'; import { Drawing } from '../../../cartography/models/drawing'; import { TextElement } from '../../../cartography/models/drawings/text-element'; import { Label } from '../../../cartography/models/label'; +import { Link } from '../../../models/link'; @Component({ @@ -27,6 +28,7 @@ export class ContextMenuComponent implements OnInit { drawings: Drawing[] = []; nodes: Node[] = []; labels: Label[] = []; + links: Link[] = []; hasTextCapabilities: boolean = false; @@ -74,12 +76,13 @@ export class ContextMenuComponent implements OnInit { this.contextMenu.openMenu(); } - public openMenuForListOfElements(drawings: Drawing[], nodes: Node[], labels: Label[], top: number, left: number) { + public openMenuForListOfElements(drawings: Drawing[], nodes: Node[], labels: Label[], links: Link[], top: number, left: number) { this.resetCapabilities(); this.drawings = drawings; this.nodes = nodes; this.labels = labels; + this.links = links; this.setPosition(top, left); this.contextMenu.openMenu(); diff --git a/src/app/components/project-map/draw-link-tool/draw-link-tool.component.html b/src/app/components/project-map/draw-link-tool/draw-link-tool.component.html index 9bbaf0d3..72be0c62 100644 --- a/src/app/components/project-map/draw-link-tool/draw-link-tool.component.html +++ b/src/app/components/project-map/draw-link-tool/draw-link-tool.component.html @@ -1 +1 @@ - + diff --git a/src/app/components/project-map/draw-link-tool/draw-link-tool.component.ts b/src/app/components/project-map/draw-link-tool/draw-link-tool.component.ts index 55cab9cf..63adb2f9 100644 --- a/src/app/components/project-map/draw-link-tool/draw-link-tool.component.ts +++ b/src/app/components/project-map/draw-link-tool/draw-link-tool.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, Input } from '@angular/core'; import { Subscription } from 'rxjs'; import { NodeSelectInterfaceComponent } from '../../../components/project-map/node-select-interface/node-select-interface.component'; import { DrawingLineWidget } from '../../../cartography/widgets/drawing-line'; @@ -7,6 +7,8 @@ import { LinksEventSource } from '../../../cartography/events/links-event-source import { MapNode } from '../../../cartography/models/map/map-node'; import { MapPort } from '../../../cartography/models/map/map-port'; import { MapLinkCreated } from '../../../cartography/events/links'; +import { Link } from '../../../models/link'; +import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter'; @Component({ selector: 'app-draw-link-tool', @@ -14,6 +16,7 @@ import { MapLinkCreated } from '../../../cartography/events/links'; styleUrls: ['./draw-link-tool.component.scss'] }) export class DrawLinkToolComponent implements OnInit, OnDestroy { + @Input() links: Link[]; @ViewChild(NodeSelectInterfaceComponent) nodeSelectInterfaceMenu: NodeSelectInterfaceComponent; private nodeClicked$: Subscription; @@ -21,12 +24,14 @@ export class DrawLinkToolComponent implements OnInit, OnDestroy { constructor( private drawingLineTool: DrawingLineWidget, private nodesEventSource: NodesEventSource, - private linksEventSource: LinksEventSource + private linksEventSource: LinksEventSource, + private mapNodeToNode: MapNodeToNodeConverter ) {} ngOnInit() { this.nodeClicked$ = this.nodesEventSource.clicked.subscribe(clickedEvent => { - this.nodeSelectInterfaceMenu.open(clickedEvent.datum, clickedEvent.y, clickedEvent.x); + let node = this.mapNodeToNode.convert(clickedEvent.datum); + this.nodeSelectInterfaceMenu.open(node, clickedEvent.y, clickedEvent.x); }); } diff --git a/src/app/components/project-map/node-select-interface/node-select-interface.component.html b/src/app/components/project-map/node-select-interface/node-select-interface.component.html index b4321348..33d07113 100644 --- a/src/app/components/project-map/node-select-interface/node-select-interface.component.html +++ b/src/app/components/project-map/node-select-interface/node-select-interface.component.html @@ -1,7 +1,7 @@
- diff --git a/src/app/components/project-map/node-select-interface/node-select-interface.component.ts b/src/app/components/project-map/node-select-interface/node-select-interface.component.ts index fd5daace..4253fc3c 100644 --- a/src/app/components/project-map/node-select-interface/node-select-interface.component.ts +++ b/src/app/components/project-map/node-select-interface/node-select-interface.component.ts @@ -3,6 +3,8 @@ import { MatMenuTrigger } from '@angular/material'; import { DomSanitizer } from '@angular/platform-browser'; import { Node } from '../../../cartography/models/node'; import { Port } from '../../../models/port'; +import { Link } from '../../../models/link'; +import { LinkNode } from '../../../models/link-node'; @Component({ selector: 'app-node-select-interface', @@ -10,6 +12,7 @@ import { Port } from '../../../models/port'; styleUrls: ['./node-select-interface.component.scss'] }) export class NodeSelectInterfaceComponent implements OnInit { + @Input() links: Link[]; @Output() onChooseInterface = new EventEmitter(); @ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger; @@ -17,8 +20,12 @@ export class NodeSelectInterfaceComponent implements OnInit { protected topPosition; protected leftPosition; public node: Node; + public availablePorts: Port[]; - constructor(private sanitizer: DomSanitizer, private changeDetector: ChangeDetectorRef) {} + constructor( + private sanitizer: DomSanitizer, + private changeDetector: ChangeDetectorRef + ) {} ngOnInit() { this.setPosition(0, 0); @@ -32,10 +39,29 @@ export class NodeSelectInterfaceComponent implements OnInit { public open(node: Node, top: number, left: number) { this.node = node; + this.filterNodePorts(); this.setPosition(top, left); this.contextMenu.openMenu(); } + public filterNodePorts() { + let linkNodes: LinkNode[] = []; + this.links.forEach((link: Link) => { + link.nodes.forEach((linkNode: LinkNode) => { + if(linkNode.node_id === this.node.node_id) { + linkNodes.push(linkNode); + } + }); + }); + + this.availablePorts = []; + this.node.ports.forEach((port: Port) => { + if(linkNodes.filter((linkNode: LinkNode) => linkNode.port_number === port.port_number).length === 0){ + this.availablePorts.push(port); + } + }); + } + public chooseInterface(port: Port) { this.onChooseInterface.emit({ node: this.node, diff --git a/src/app/components/project-map/project-map.component.html b/src/app/components/project-map/project-map.component.html index 4dbbede1..c79bad23 100644 --- a/src/app/components/project-map/project-map.component.html +++ b/src/app/components/project-map/project-map.component.html @@ -141,7 +141,7 @@ - + { return of(this.node); } + + delete(server: Server, node: Node) { + return of(); + } } export class MockedDrawingService { @@ -87,6 +93,10 @@ export class MockedDrawingService { export class MockedLinkService { constructor() {} + deleteLink(_server: Server, link: Link){ + return of({}) + } + createLink() { return of({}); } @@ -144,6 +154,7 @@ describe('ProjectMapComponent', () => { { provide: MapNodeToNodeConverter }, { provide: MapDrawingToDrawingConverter }, { provide: MapLabelToLabelConverter }, + { provide: MapLinkToLinkConverter }, { provide: NodesDataSource }, { provide: LinksDataSource }, { provide: DrawingsDataSource, useValue: drawingsDataSource }, diff --git a/src/app/components/project-map/project-map.component.ts b/src/app/components/project-map/project-map.component.ts index 7d5b7a4c..05b15f80 100644 --- a/src/app/components/project-map/project-map.component.ts +++ b/src/app/components/project-map/project-map.component.ts @@ -40,6 +40,8 @@ import { Label } from '../../cartography/models/label'; import { MapNode } from '../../cartography/models/map/map-node'; import { MapLabelToLabelConverter } from '../../cartography/converters/map/map-label-to-label-converter'; import { RecentlyOpenedProjectService } from '../../services/recentlyOpenedProject.service'; +import { MapLink } from '../../cartography/models/map/map-link'; +import { MapLinkToLinkConverter } from '../../cartography/converters/map/map-link-to-link-converter'; @Component({ @@ -96,6 +98,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy { private mapNodeToNode: MapNodeToNodeConverter, private mapDrawingToDrawing: MapDrawingToDrawingConverter, private mapLabelToLabel: MapLabelToLabelConverter, + private mapLinkToLink: MapLinkToLinkConverter, private nodesDataSource: NodesDataSource, private linksDataSource: LinksDataSource, private drawingsDataSource: DrawingsDataSource, @@ -218,12 +221,12 @@ export class ProjectMapComponent implements OnInit, OnDestroy { const onNodeContextMenu = this.nodeWidget.onContextMenu.subscribe((eventNode: NodeContextMenu) => { const node = this.mapNodeToNode.convert(eventNode.node); - this.contextMenu.openMenuForNode(node, eventNode.event.clientY, eventNode.event.clientX); + this.contextMenu.openMenuForNode(node, eventNode.event.pageY, eventNode.event.pageX); }); const onDrawingContextMenu = this.drawingsWidget.onContextMenu.subscribe((eventDrawing: DrawingContextMenu) => { const drawing = this.mapDrawingToDrawing.convert(eventDrawing.drawing); - this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.clientY, eventDrawing.event.clientX); + this.contextMenu.openMenuForDrawing(drawing, eventDrawing.event.pageY, eventDrawing.event.pageX); }); const onContextMenu = this.selectionTool.contextMenuOpened.subscribe((event) => { @@ -233,6 +236,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy { let drawings: Drawing[] = []; let nodes: Node[] = []; let labels: Label[] = []; + let links: Link[] = []; selectedItems.forEach((elem) => { if (elem instanceof MapDrawing) { @@ -241,10 +245,12 @@ export class ProjectMapComponent implements OnInit, OnDestroy { nodes.push(this.mapNodeToNode.convert(elem)); } else if (elem instanceof MapLabel) { labels.push(this.mapLabelToLabel.convert(elem)); + } else if (elem instanceof MapLink) { + links.push(this.mapLinkToLink.convert(elem)) } }); - this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, event.clientY, event.clientX); + this.contextMenu.openMenuForListOfElements(drawings, nodes, labels, links, event.pageY, event.pageX); }); this.subscriptions.push(onNodeContextMenu); diff --git a/src/app/components/projects/projects.component.html b/src/app/components/projects/projects.component.html index 46248aa1..945b2663 100644 --- a/src/app/components/projects/projects.component.html +++ b/src/app/components/projects/projects.component.html @@ -43,9 +43,9 @@ - - - + diff --git a/src/app/components/projects/projects.component.spec.ts b/src/app/components/projects/projects.component.spec.ts index 976b948a..29e82cec 100644 --- a/src/app/components/projects/projects.component.spec.ts +++ b/src/app/components/projects/projects.component.spec.ts @@ -25,6 +25,7 @@ describe('ProjectsComponent', () => { let serverService: ServerService; let server: Server; let progressService: ProgressService; + let mockedProjectService: MockedProjectService = new MockedProjectService(); beforeEach(async(() => { TestBed.configureTestingModule({ @@ -39,7 +40,7 @@ describe('ProjectsComponent', () => { ], providers: [ { provide: ServerService, useClass: MockedServerService }, - { provide: ProjectService, useClass: MockedProjectService }, + { provide: ProjectService, useValue: mockedProjectService }, { provide: SettingsService, useClass: MockedSettingsService }, ProgressService ], @@ -74,6 +75,16 @@ describe('ProjectsComponent', () => { expect(component).toBeTruthy(); }); + it('should remove item after delete action', () => { + spyOn(mockedProjectService, 'delete').and.returnValue(of()); + let project = new Project(); + project.project_id = '1'; + + component.delete(project); + + expect(mockedProjectService.delete).toHaveBeenCalled(); + }); + describe('ProjectComponent open', () => { let project: Project; diff --git a/src/app/services/link.service.ts b/src/app/services/link.service.ts index 479697a2..37d2ebfa 100644 --- a/src/app/services/link.service.ts +++ b/src/app/services/link.service.ts @@ -12,6 +12,11 @@ import { LinkNode } from '../models/link-node'; export class LinkService { constructor(private httpServer: HttpServer) {} + deleteLink(server: Server, link: Link) { + //return this.httpServer.delete(server, `/compute/projects/${link.project_id}/vpcs/nodes/${link.nodes[0].node_id}/adapters/0/ports/0/nio`) + return this.httpServer.delete(server, `/projects/${link.project_id}/links/${link.link_id}`) + } + createLink(server: Server, source_node: Node, source_port: Port, target_node: Node, target_port: Port) { return this.httpServer.post(server, `/projects/${source_node.project_id}/links`, { nodes: [ diff --git a/src/app/services/project.service.spec.ts b/src/app/services/project.service.spec.ts index 69d47f14..2752923a 100644 --- a/src/app/services/project.service.spec.ts +++ b/src/app/services/project.service.spec.ts @@ -8,9 +8,9 @@ import { getTestServer } from './testing'; import { ProjectService } from './project.service'; import { SettingsService } from './settings.service'; import { MockedSettingsService } from './settings.service.spec'; -import { Observable, of } from 'rxjs'; import { Project } from '../models/project'; import { AppTestingModule } from '../testing/app-testing/app-testing.module'; +import { of } from 'rxjs'; /** * Mocks ProjectsService so it's not based on settings @@ -37,6 +37,10 @@ export class MockedProjectService { links(server: Server, project_id: string) { return of([]); } + + delete(server: Server, project_id: string) { + return of(project_id); + } } describe('ProjectService', () => {