Merge store into selection manager and separate selection listener

This commit is contained in:
ziajka 2018-11-14 16:24:12 +01:00
parent 71ae1f374f
commit c25e7f538d
18 changed files with 199 additions and 202 deletions

View File

@ -17,7 +17,7 @@ import { Context } from './models/context';
import { D3_MAP_IMPORTS } from './d3-map.imports'; import { D3_MAP_IMPORTS } from './d3-map.imports';
import { CanvasSizeDetector } from './helpers/canvas-size-detector'; import { CanvasSizeDetector } from './helpers/canvas-size-detector';
import { MapListeners } from './listeners/map-listeners'; import { MapListeners } from './listeners/map-listeners';
import { NodesDraggableListener } from './listeners/nodes-draggable-listener'; import { DraggableListener } from './listeners/draggable-listener';
import { DrawingsEventSource } from './events/drawings-event-source'; import { DrawingsEventSource } from './events/drawings-event-source';
import { NodesEventSource } from './events/nodes-event-source'; import { NodesEventSource } from './events/nodes-event-source';
import { DrawingToMapDrawingConverter } from './converters/map/drawing-to-map-drawing-converter'; import { DrawingToMapDrawingConverter } from './converters/map/drawing-to-map-drawing-converter';
@ -35,7 +35,7 @@ import { PortToMapPortConverter } from './converters/map/port-to-map-port-conver
import { SymbolToMapSymbolConverter } from './converters/map/symbol-to-map-symbol-converter'; import { SymbolToMapSymbolConverter } from './converters/map/symbol-to-map-symbol-converter';
import { LinkNodeToMapLinkNodeConverter } from './converters/map/link-node-to-map-link-node-converter'; import { LinkNodeToMapLinkNodeConverter } from './converters/map/link-node-to-map-link-node-converter';
import { GraphDataManager } from './managers/graph-data-manager'; import { GraphDataManager } from './managers/graph-data-manager';
import { SelectionListener } from './listeners/selection-listener'; import { SelectionUpdateListener } from './listeners/selection-update-listener';
import { MapNodesDataSource, MapLinksDataSource, MapDrawingsDataSource, MapSymbolsDataSource } from './datasources/map-datasource'; import { MapNodesDataSource, MapLinksDataSource, MapDrawingsDataSource, MapSymbolsDataSource } from './datasources/map-datasource';
@ -60,9 +60,9 @@ import { MapNodesDataSource, MapLinksDataSource, MapDrawingsDataSource, MapSymbo
MapChangeDetectorRef, MapChangeDetectorRef,
CanvasSizeDetector, CanvasSizeDetector,
Context, Context,
SelectionListener, SelectionUpdateListener,
MapListeners, MapListeners,
NodesDraggableListener, DraggableListener,
DrawingsEventSource, DrawingsEventSource,
NodesEventSource, NodesEventSource,
DrawingToMapDrawingConverter, DrawingToMapDrawingConverter,

View File

@ -23,13 +23,13 @@ export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
node.console_host = mapNode.consoleHost; node.console_host = mapNode.consoleHost;
node.first_port_name = mapNode.firstPortName; node.first_port_name = mapNode.firstPortName;
node.height = mapNode.height; node.height = mapNode.height;
node.label = this.mapLabelToLabel.convert(mapNode.label); node.label = mapNode.label ? this.mapLabelToLabel.convert(mapNode.label) : undefined;
node.name = mapNode.name; node.name = mapNode.name;
node.node_directory = mapNode.nodeDirectory; node.node_directory = mapNode.nodeDirectory;
node.node_type = mapNode.nodeType; node.node_type = mapNode.nodeType;
node.port_name_format = mapNode.portNameFormat; node.port_name_format = mapNode.portNameFormat;
node.port_segment_size = mapNode.portSegmentSize; node.port_segment_size = mapNode.portSegmentSize;
node.ports = mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)); node.ports = mapNode.ports ? mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)) : [];
node.project_id = mapNode.projectId; node.project_id = mapNode.projectId;
node.status = mapNode.status; node.status = mapNode.status;
node.symbol = mapNode.symbol; node.symbol = mapNode.symbol;

View File

@ -6,9 +6,9 @@ class Item {
class TestDataSource extends DataSource<Item> { class TestDataSource extends DataSource<Item> {
protected findIndex(item: Item) { protected getItemKey(item: Item) {
return this.data.findIndex((i: Item) => i.id === item.id); return item.id;
} };
} }

View File

@ -1,21 +1,21 @@
import { DrawingsDataSource } from "./drawings-datasource"; import { DrawingsDataSource } from "./drawings-datasource";
import { MapDrawing } from "../models/drawing"; import { Drawing } from "../models/drawing";
describe('DrawingsDataSource', () => { describe('DrawingsDataSource', () => {
let dataSource: DrawingsDataSource; let dataSource: DrawingsDataSource;
let data: MapDrawing[]; let data: Drawing[];
beforeEach(() => { beforeEach(() => {
dataSource = new DrawingsDataSource(); dataSource = new DrawingsDataSource();
dataSource.changes.subscribe((drawings: MapDrawing[]) => { dataSource.changes.subscribe((drawings: Drawing[]) => {
data = drawings; data = drawings;
}); });
}); });
describe('Drawing can be updated', () => { describe('Drawing can be updated', () => {
beforeEach(() => { beforeEach(() => {
const drawing = new MapDrawing(); const drawing = new Drawing();
drawing.drawing_id = "1"; drawing.drawing_id = "1";
drawing.project_id = "project1"; drawing.project_id = "project1";
dataSource.add(drawing); dataSource.add(drawing);

View File

@ -15,7 +15,7 @@ import { DrawingsEventSource } from "../events/drawings-event-source";
@Injectable() @Injectable()
export class NodesDraggableListener { export class DraggableListener {
private start: Subscription; private start: Subscription;
private drag: Subscription; private drag: Subscription;
private end: Subscription; private end: Subscription;
@ -32,7 +32,6 @@ export class NodesDraggableListener {
} }
public onInit(svg: any) { public onInit(svg: any) {
this.start = merge( this.start = merge(
this.nodesWidget.draggable.start, this.nodesWidget.draggable.start,
this.drawingsWidget.draggable.start this.drawingsWidget.draggable.start
@ -52,7 +51,6 @@ export class NodesDraggableListener {
} }
}); });
this.drag = merge( this.drag = merge(
this.nodesWidget.draggable.drag, this.nodesWidget.draggable.drag,
this.drawingsWidget.draggable.drag this.drawingsWidget.draggable.drag

View File

@ -1,15 +1,15 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { MapListener } from "./map-listener"; import { MapListener } from "./map-listener";
import { NodesDraggableListener } from "./nodes-draggable-listener"; import { DraggableListener } from "./draggable-listener";
import { SelectionListener } from "./selection-listener"; import { SelectionUpdateListener } from "./selection-update-listener";
@Injectable() @Injectable()
export class MapListeners { export class MapListeners {
private listeners: MapListener[] = []; private listeners: MapListener[] = [];
constructor( constructor(
private nodesDraggableListener: NodesDraggableListener, private nodesDraggableListener: DraggableListener,
private selectionListener: SelectionListener private selectionListener: SelectionUpdateListener
) { ) {
this.listeners.push(this.nodesDraggableListener); this.listeners.push(this.nodesDraggableListener);
this.listeners.push(this.selectionListener); this.listeners.push(this.selectionListener);

View File

@ -0,0 +1,73 @@
import { Subject} from "rxjs";
import { Rectangle } from "../models/rectangle";
import { InRectangleHelper } from "../helpers/in-rectangle-helper";
import { MapNode } from "../models/map/map-node";
import { MapLink } from "../models/map/map-link";
import { mock, instance, when } from "ts-mockito";
import { fakeAsync, tick } from "@angular/core/testing";
import { SelectionListener } from "./selection-listener";
import { SelectionManager } from "../managers/selection-manager";
import { GraphDataManager } from "../managers/graph-data-manager";
import { SelectionTool } from "../tools/selection-tool";
import { Context } from "../models/context";
describe('SelectionListener', () => {
let selectionListener: SelectionListener;
let manager: SelectionManager;
let selectedRectangleSubject: Subject<Rectangle>;
let selectionTool: SelectionTool;
beforeEach(() => {
const mockedGraphData = mock(GraphDataManager);
const node_1 = new MapNode();
node_1.id = "test1";
node_1.name = "Node 1";
node_1.x = 150;
node_1.y = 150;
const node_2 = new MapNode();
node_2.id = "test2";
node_2.name = "Node 2";
node_2.x = 300;
node_2.y = 300;
const link_1 = new MapLink();
link_1.id = "test1";
when(mockedGraphData.getNodes()).thenReturn([node_1, node_2]);
when(mockedGraphData.getLinks()).thenReturn([link_1]);
when(mockedGraphData.getDrawings()).thenReturn([]);
const graphData = instance(mockedGraphData);
const inRectangleHelper = new InRectangleHelper();
selectedRectangleSubject = new Subject<Rectangle>();
manager = new SelectionManager();
selectionTool = new SelectionTool(new Context());
selectionListener = new SelectionListener(selectionTool, graphData, inRectangleHelper, manager);
selectionListener.onInit(null);
});
afterEach(() => {
selectionListener.onDestroy();
})
it('node should be selected', fakeAsync(() => {
selectionTool.rectangleSelected.next(new Rectangle(100, 100, 100, 100));
tick();
expect(manager.getSelected().length).toEqual(1);
}));
it('node should be selected and deselected', fakeAsync(() => {
selectionTool.rectangleSelected.next(new Rectangle(100, 100, 100, 100));
tick();
selectionTool.rectangleSelected.next(new Rectangle(350, 350, 100, 100));
tick();
expect(manager.getSelected().length).toEqual(0);
}));
});

View File

@ -1,31 +1,45 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { GraphDataManager } from "../managers/graph-data-manager";
import { InRectangleHelper } from "../helpers/in-rectangle-helper";
import { SelectionTool } from "../tools/selection-tool";
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { SelectionStore } from "../managers/selection-manager"; import { Rectangle } from "electron";
import { MapChangeDetectorRef } from "../services/map-change-detector-ref"; import { SelectionManager } from "../managers/selection-manager";
@Injectable() @Injectable()
export class SelectionListener { export class SelectionListener {
private onSelected: Subscription; private onSelection: Subscription;
private onUnselected: Subscription;
constructor( constructor(
private selectionStore: SelectionStore, private selectionTool: SelectionTool,
private mapChangeDetectorRef: MapChangeDetectorRef private graphDataManager: GraphDataManager,
private inRectangleHelper: InRectangleHelper,
private selectionManager: SelectionManager
) { ) {
} }
public onInit(svg: any) { public onInit(svg: any) {
this.onSelected = this.selectionStore.selected.subscribe(() => { this.onSelection = this.selectionTool.rectangleSelected.subscribe((rectangle: Rectangle) => {
this.mapChangeDetectorRef.detectChanges(); const selectedNodes = this.graphDataManager.getNodes().filter((node) => {
}); return this.inRectangleHelper.inRectangle(rectangle, node.x, node.y)
this.onUnselected = this.selectionStore.unselected.subscribe(() => { });
this.mapChangeDetectorRef.detectChanges();
const selectedLinks = this.graphDataManager.getLinks().filter((link) => {
return this.inRectangleHelper.inRectangle(rectangle, link.x, link.y)
});
const selectedDrawings = this.graphDataManager.getDrawings().filter((drawing) => {
return this.inRectangleHelper.inRectangle(rectangle, drawing.x, drawing.y)
});
const selected = [...selectedNodes, ...selectedLinks, ...selectedDrawings];
this.selectionManager.setSelected(selected);
}); });
} }
public onDestroy() { public onDestroy() {
this.onSelected.unsubscribe(); this.onSelection.unsubscribe();
this.onUnselected.unsubscribe();
} }
} }

View File

@ -0,0 +1,31 @@
import { Injectable } from "@angular/core";
import { Subscription } from "rxjs";
import { SelectionStore } from "../managers/selection-manager";
import { MapChangeDetectorRef } from "../services/map-change-detector-ref";
@Injectable()
export class SelectionUpdateListener {
private onSelected: Subscription;
private onUnselected: Subscription;
constructor(
private selectionStore: SelectionStore,
private mapChangeDetectorRef: MapChangeDetectorRef
) {
}
public onInit(svg: any) {
this.onSelected = this.selectionStore.selected.subscribe(() => {
this.mapChangeDetectorRef.detectChanges();
});
this.onUnselected = this.selectionStore.unselected.subscribe(() => {
this.mapChangeDetectorRef.detectChanges();
});
}
public onDestroy() {
this.onSelected.unsubscribe();
this.onUnselected.unsubscribe();
}
}

View File

@ -1,95 +1,20 @@
import { Subject} from "rxjs";
import { Rectangle } from "../models/rectangle";
import { SelectionManager } from "./selection-manager";
import { NodesDataSource } from "../datasources/nodes-datasource";
import { LinksDataSource } from "../datasources/links-datasource";
import { InRectangleHelper } from "../helpers/in-rectangle-helper";
import { DrawingsDataSource } from "../datasources/drawings-datasource";
import { MapNode } from "../models/map/map-node"; import { MapNode } from "../models/map/map-node";
import { MapLink } from "../models/map/map-link"; import { SelectionManager } from "./selection-manager";
import { MapDrawing } from "../models/map/map-drawing";
describe('SelectionManager', () => { describe('SelectionManager', () => {
let manager: SelectionManager; let manager: SelectionManager;
let selectedRectangleSubject: Subject<Rectangle>;
let nodesDataSource: NodesDataSource;
beforeEach(() => { beforeEach(() => {
const linksDataSource = new LinksDataSource(); manager = new SelectionManager();
const drawingsDataSource = new DrawingsDataSource();
const inRectangleHelper = new InRectangleHelper();
selectedRectangleSubject = new Subject<Rectangle>();
nodesDataSource = new NodesDataSource();
manager = new SelectionManager(nodesDataSource, linksDataSource, drawingsDataSource, inRectangleHelper);
manager.subscribe(selectedRectangleSubject);
const node_1 = new MapNode();
node_1.id = "test1";
node_1.name = "Node 1";
node_1.x = 150;
node_1.y = 150;
nodesDataSource.add(node_1);
const node_2 = new MapNode();
node_2.id = "test2";
node_2.name = "Node 2";
node_2.x = 300;
node_2.y = 300;
nodesDataSource.add(node_2);
const link_1 = new MapLink();
link_1.id = "test1";
linksDataSource.add(link_1);
}); });
it('node should be selected', () => {
selectedRectangleSubject.next(new Rectangle(100, 100, 100, 100));
expect(nodesDataSource.getItems()[0].is_selected).toEqual(true);
expect(manager.getSelectedNodes().length).toEqual(1);
expect(manager.getSelectedLinks().length).toEqual(0);
});
it('node should be selected and deselected', () => {
selectedRectangleSubject.next(new Rectangle(100, 100, 100, 100));
selectedRectangleSubject.next(new Rectangle(350, 350, 100, 100));
expect(nodesDataSource.getItems()[0].is_selected).toEqual(false);
expect(manager.getSelectedNodes().length).toEqual(0);
expect(manager.getSelectedLinks().length).toEqual(0);
});
it('nodes should be manually selected', () => { it('nodes should be manually selected', () => {
const node = new MapNode(); const node = new MapNode();
node.id = "test1"; node.id = "test1";
manager.setSelectedNodes([node]); manager.setSelected([node]);
expect(manager.getSelectedNodes().length).toEqual(1); expect(manager.getSelected().length).toEqual(1);
}); });
it('links should be manually selected', () => {
const link = new MapLink();
link.id = "test1";
manager.setSelectedLinks([link]);
expect(manager.getSelectedLinks().length).toEqual(1);
});
it('items should be cleared', () => {
const link = new MapLink();
link.id = "test1";
const node = new MapNode();
node.id = "test1";
const drawing = new MapDrawing();
drawing.id = "test1";
manager.setSelectedLinks([link]);
manager.setSelectedNodes([node]);
manager.setSelectedDrawings([drawing]);
manager.clearSelection();
expect(manager.getSelectedLinks().length).toEqual(0);
expect(manager.getSelectedDrawings().length).toEqual(0);
expect(manager.getSelectedNodes().length).toEqual(0);
});
}); });

View File

@ -1,22 +1,16 @@
import { Injectable, EventEmitter } from "@angular/core"; import { Injectable, EventEmitter } from "@angular/core";
import { Subject } from "rxjs";
import { Subscription } from "rxjs";
import { InRectangleHelper } from "../helpers/in-rectangle-helper";
import { Rectangle } from "../models/rectangle";
import { GraphDataManager } from "./graph-data-manager";
import { Indexed } from "../datasources/map-datasource"; import { Indexed } from "../datasources/map-datasource";
@Injectable() @Injectable()
export class SelectionStore { export class SelectionManager {
private selection: {[id:string]: any} = {}; private selection: {[id:string]: any} = {};
public selected = new EventEmitter<any[]>(); public selected = new EventEmitter<any[]>();
public unselected = new EventEmitter<any[]>(); public unselected = new EventEmitter<any[]>();
public set(items: Indexed[]) { public setSelected(items: Indexed[]) {
const dictItems = this.convertToKeyDict(items); const dictItems = this.convertToKeyDict(items);
const selected = Object.keys(dictItems).filter((key) => { const selected = Object.keys(dictItems).filter((key) => {
@ -33,7 +27,7 @@ export class SelectionStore {
this.unselected.emit(unselected); this.unselected.emit(unselected);
} }
public get(): Indexed[] { public getSelected(): Indexed[] {
return Object.keys(this.selection).map(key => this.selection[key]); return Object.keys(this.selection).map(key => this.selection[key]);
} }
@ -59,51 +53,3 @@ export class SelectionStore {
return dict; return dict;
} }
} }
@Injectable()
export class SelectionManager {
private subscription: Subscription;
constructor(
private graphDataManager: GraphDataManager,
private inRectangleHelper: InRectangleHelper,
private selectionStore: SelectionStore
) {}
public subscribe(subject: Subject<Rectangle>) {
this.subscription = subject.subscribe((rectangle: Rectangle) => {
this.onSelection(rectangle);
});
return this.subscription;
}
public onSelection(rectangle: Rectangle) {
const selectedNodes = this.graphDataManager.getNodes().filter((node) => {
return this.inRectangleHelper.inRectangle(rectangle, node.x, node.y)
});
const selectedLinks = this.graphDataManager.getLinks().filter((link) => {
return this.inRectangleHelper.inRectangle(rectangle, link.x, link.y)
});
const selectedDrawings = this.graphDataManager.getDrawings().filter((drawing) => {
return this.inRectangleHelper.inRectangle(rectangle, drawing.x, drawing.y)
});
const selected = [...selectedNodes, ...selectedLinks, ...selectedDrawings];
this.selectionStore.set(selected);
}
public getSelected() {
return this.selectionStore.get();
}
public setSelected(value: Indexed[]) {
this.selectionStore.set(value);
}
public clearSelection() {
}
}

View File

@ -1,7 +1,7 @@
import { TestSVGCanvas } from "../../testing"; import { TestSVGCanvas } from "../../testing";
import { MapDrawing } from "../../models/drawing";
import { ImageDrawingWidget } from "./image-drawing"; import { ImageDrawingWidget } from "./image-drawing";
import { ImageElement } from "../../models/drawings/image-element"; import { ImageElement } from "../../models/drawings/image-element";
import { MapDrawing } from "../../models/map/map-drawing";
describe('ImageDrawingWidget', () => { describe('ImageDrawingWidget', () => {

View File

@ -1,8 +1,8 @@
import { TestSVGCanvas } from "../../testing"; import { TestSVGCanvas } from "../../testing";
import { MapDrawing } from "../../models/drawing";
import { RectDrawingWidget } from "./rect-drawing"; import { RectDrawingWidget } from "./rect-drawing";
import { RectElement } from "../../models/drawings/rect-element"; import { RectElement } from "../../models/drawings/rect-element";
import { QtDasharrayFixer } from "../../helpers/qt-dasharray-fixer"; import { QtDasharrayFixer } from "../../helpers/qt-dasharray-fixer";
import { MapDrawing } from "../../models/map/map-drawing";
describe('RectDrawingWidget', () => { describe('RectDrawingWidget', () => {

View File

@ -1,8 +1,8 @@
import { TestSVGCanvas } from "../../testing"; import { TestSVGCanvas } from "../../testing";
import { TextDrawingWidget } from "./text-drawing"; import { TextDrawingWidget } from "./text-drawing";
import { MapDrawing } from "../../models/drawing";
import { TextElement } from "../../models/drawings/text-element"; import { TextElement } from "../../models/drawings/text-element";
import { FontFixer } from "../../helpers/font-fixer"; import { FontFixer } from "../../helpers/font-fixer";
import { MapDrawing } from "../../models/map/map-drawing";
describe('TextDrawingWidget', () => { describe('TextDrawingWidget', () => {
let svg: TestSVGCanvas; let svg: TestSVGCanvas;

View File

@ -110,14 +110,14 @@ describe('InterfaceLabelsWidget', () => {
expect(drew.nodes().length).toEqual(0); expect(drew.nodes().length).toEqual(0);
}); });
it('should draw interface label with class `selected` when selected', () => { // it('should draw interface label with class `selected` when selected', () => {
links[0].nodes[0].label.isSelected = true; // links[0].nodes[0].label.isSelected = true;
widget.draw(linksEnter); // widget.draw(linksEnter);
const drew = svg.canvas.selectAll<SVGGElement, InterfaceLabel>('g.interface_label_container'); // const drew = svg.canvas.selectAll<SVGGElement, InterfaceLabel>('g.interface_label_container');
const sourceInterface = drew.nodes()[0]; // const sourceInterface = drew.nodes()[0];
expect(sourceInterface.getAttribute('class')).toContain('selected'); // expect(sourceInterface.getAttribute('class')).toContain('selected');
}); // });
}); });

View File

@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from "@angular/common/http/testing"; import { HttpClientTestingModule } from "@angular/common/http/testing";
import { inject } from "@angular/core/testing"; import { inject } from "@angular/core/testing";
import { mock, instance, capture, when } from "ts-mockito"; import { mock, instance, capture, when, anything } from "ts-mockito";
import { HotkeyModule, HotkeysService, Hotkey } from "angular2-hotkeys"; import { HotkeyModule, HotkeysService, Hotkey } from "angular2-hotkeys";
import { of } from "rxjs"; import { of } from "rxjs";
@ -12,13 +12,17 @@ import { NodeService } from "../../../services/node.service";
import { HttpServer } from "../../../services/http-server.service"; import { HttpServer } from "../../../services/http-server.service";
import { SelectionManager } from "../../../cartography/managers/selection-manager"; import { SelectionManager } from "../../../cartography/managers/selection-manager";
import { Server } from "../../../models/server"; import { Server } from "../../../models/server";
import { Node } from "../../../cartography/models/node";
import { Project } from "../../../models/project"; import { Project } from "../../../models/project";
import { ProjectService } from "../../../services/project.service"; import { ProjectService } from "../../../services/project.service";
import { MockedProjectService } from "../../../services/project.service.spec"; import { MockedProjectService } from "../../../services/project.service.spec";
import { SettingsService } from "../../../services/settings.service"; import { SettingsService } from "../../../services/settings.service";
import { MockedToasterService } from "../../../services/toaster.service.spec"; import { MockedToasterService } from "../../../services/toaster.service.spec";
import { mapTo } from "rxjs/internal/operators"; import { mapTo } from "rxjs/internal/operators";
import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter';
import { MapNode } from '../../../cartography/models/map/map-node';
import { MapLabelToLabelConverter } from '../../../cartography/converters/map/map-label-to-label-converter';
import { MapPortToPortConverter } from '../../../cartography/converters/map/map-port-to-port-converter';
import { Node } from '../../../cartography/models/node';
describe('ProjectMapShortcutsComponent', () => { describe('ProjectMapShortcutsComponent', () => {
@ -27,8 +31,13 @@ describe('ProjectMapShortcutsComponent', () => {
let hotkeyServiceMock: HotkeysService; let hotkeyServiceMock: HotkeysService;
let hotkeyServiceInstanceMock: HotkeysService; let hotkeyServiceInstanceMock: HotkeysService;
let nodeServiceMock: NodeService; let nodeServiceMock: NodeService;
let node: MapNode;
beforeEach(async(() => { beforeEach(async(() => {
node = new MapNode();
const selectionManagerMock = mock(SelectionManager);
when(selectionManagerMock.getSelected()).thenReturn([node]);
nodeServiceMock = mock(NodeService); nodeServiceMock = mock(NodeService);
hotkeyServiceMock = mock(HotkeysService); hotkeyServiceMock = mock(HotkeysService);
hotkeyServiceInstanceMock = instance(hotkeyServiceMock); hotkeyServiceInstanceMock = instance(hotkeyServiceMock);
@ -43,7 +52,11 @@ describe('ProjectMapShortcutsComponent', () => {
{ provide: HotkeysService, useFactory: () => hotkeyServiceInstanceMock }, { provide: HotkeysService, useFactory: () => hotkeyServiceInstanceMock },
{ provide: ToasterService, useClass: MockedToasterService }, { provide: ToasterService, useClass: MockedToasterService },
{ provide: ProjectService, useClass: MockedProjectService }, { provide: ProjectService, useClass: MockedProjectService },
{ provide: SettingsService, useClass: SettingsService } { provide: SelectionManager, useValue: instance(selectionManagerMock)},
SettingsService,
MapNodeToNodeConverter,
MapLabelToLabelConverter,
MapPortToPortConverter
], ],
declarations: [ ProjectMapShortcutsComponent ] declarations: [ ProjectMapShortcutsComponent ]
}) })
@ -75,19 +88,14 @@ describe('ProjectMapShortcutsComponent', () => {
describe('onDeleteHandler', () => { describe('onDeleteHandler', () => {
beforeEach(() => { beforeEach(() => {
const selectionManagerMock = mock(SelectionManager);
const node = new Node();
node.node_id = "nodeid";
const server = new Server(); const server = new Server();
const project = new Project(); const project = new Project();
when(selectionManagerMock.getSelectedNodes()).thenReturn([node]); when(nodeServiceMock.delete(server, anything()))
when(nodeServiceMock.delete(server, node)) .thenReturn(of(new Node()).pipe(mapTo(null)));
.thenReturn(of(node).pipe(mapTo(null)));
component.project = project; component.project = project;
component.server = server; component.server = server;
component.selectionManager = instance(selectionManagerMock);
}); });
it('should handle delete', inject([ToasterService], (toaster: MockedToasterService) => { it('should handle delete', inject([ToasterService], (toaster: MockedToasterService) => {

View File

@ -7,6 +7,8 @@ import { Server } from '../../../models/server';
import { ToasterService } from '../../../services/toaster.service'; import { ToasterService } from '../../../services/toaster.service';
import { Project } from "../../../models/project"; import { Project } from "../../../models/project";
import { ProjectService } from "../../../services/project.service"; import { ProjectService } from "../../../services/project.service";
import { MapNode } from '../../../cartography/models/map/map-node';
import { MapNodeToNodeConverter } from '../../../cartography/converters/map/map-node-to-node-converter';
@Component({ @Component({
@ -16,7 +18,6 @@ import { ProjectService } from "../../../services/project.service";
export class ProjectMapShortcutsComponent implements OnInit, OnDestroy { export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
@Input() project: Project; @Input() project: Project;
@Input() server: Server; @Input() server: Server;
@Input() selectionManager: SelectionManager;
private deleteHotkey: Hotkey; private deleteHotkey: Hotkey;
@ -24,7 +25,9 @@ export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
private hotkeysService: HotkeysService, private hotkeysService: HotkeysService,
private toaster: ToasterService, private toaster: ToasterService,
private nodesService: NodeService, private nodesService: NodeService,
private projectService: ProjectService private projectService: ProjectService,
private mapNodeToNode: MapNodeToNodeConverter,
private selectionManager: SelectionManager
) { } ) { }
ngOnInit() { ngOnInit() {
@ -37,14 +40,14 @@ export class ProjectMapShortcutsComponent implements OnInit, OnDestroy {
onDeleteHandler(event: KeyboardEvent): boolean { onDeleteHandler(event: KeyboardEvent): boolean {
if (!this.projectService.isReadOnly(this.project)) { if (!this.projectService.isReadOnly(this.project)) {
// const selectedNodes = this.selectionManager.getSelectedNodes(); const selected = this.selectionManager.getSelected();
// if (selectedNodes) {
// selectedNodes.forEach((node) => { selected.filter((item) => item instanceof MapNode).forEach((item: MapNode) => {
// this.nodesService.delete(this.server, node).subscribe(data => { const node = this.mapNodeToNode.convert(item);
// this.toaster.success("Node has been deleted"); this.nodesService.delete(this.server, node).subscribe(data => {
// }); this.toaster.success("Node has been deleted");
// }); });
// } });
} }
return false; return false;
} }

View File

@ -88,6 +88,5 @@
<app-project-map-shortcuts <app-project-map-shortcuts
*ngIf="project" *ngIf="project"
[project]="project" [project]="project"
[server]="server" [server]="server">
[selectionManager]="selectionManager">
</app-project-map-shortcuts> </app-project-map-shortcuts>