Merge branch 'master' into Fit-in-view-option

This commit is contained in:
Piotr Pekala 2019-10-25 04:22:19 -07:00
commit 92b9163bf3
17 changed files with 112 additions and 19 deletions

View File

@ -1,5 +1,19 @@
<svg #svg class="map" preserveAspectRatio="none" movingCanvas zoomingCanvas>
<filter id="grayscale"><feColorMatrix id="feGrayscale" type="saturate" values="0" /></filter>
<defs>
<pattern id="gridDrawing" attr.width="{{project.drawing_grid_size}}" attr.height="{{project.drawing_grid_size}}" patternUnits="userSpaceOnUse">
<path attr.d="M {{project.drawing_grid_size}} 0 L 0 0 0 {{project.drawing_grid_size}}" fill="none" stroke="silver" attr.stroke-width="{{gridVisibility}}"/>
</pattern>
</defs>
<defs>
<pattern id="gridNode" attr.width="{{project.grid_size}}" attr.height="{{project.grid_size}}" patternUnits="userSpaceOnUse">
<path attr.d="M {{project.grid_size}} 0 L 0 0 0 {{project.grid_size}}" fill="none" stroke="DarkSlateGray" attr.stroke-width="{{gridVisibility}}"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#gridDrawing)" />
<rect width="100%" height="100%" fill="url(#gridNode)" />
</svg>
<app-drawing-adding [svg]="svg"></app-drawing-adding>

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -32,6 +32,7 @@ import { Server } from '../../../models/server';
import { ToolsService } from '../../../services/tools.service';
import { TextEditorComponent } from '../text-editor/text-editor.component';
import { MapScaleService } from '../../../services/mapScale.service';
import { Project } from '../../../models/project';
@Component({
selector: 'app-d3-map',
@ -43,6 +44,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
@Input() links: Link[] = [];
@Input() drawings: Drawing[] = [];
@Input() symbols: Symbol[] = [];
@Input() project: Project;
@Input() server: Server;
@Input() width = 1500;
@ -53,14 +55,13 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
private parentNativeElement: any;
private svg: Selection<SVGSVGElement, any, null, undefined>;
private onChangesDetected: Subscription;
private subscriptions: Subscription[] = [];
private drawLinkTool: boolean;
protected settings = {
show_interface_labels: true
};
public gridVisibility: number = 0;
constructor(
private graphDataManager: GraphDataManager,
@ -142,6 +143,8 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
this.drawLinkTool = value;
})
);
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? 1 : 0;
}
ngOnDestroy() {

View File

@ -31,6 +31,7 @@ export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
node.status = mapNode.status;
node.symbol = mapNode.symbol;
node.symbol_url = mapNode.symbolUrl;
node.usage = mapNode.usage;
node.width = mapNode.width;
node.x = mapNode.x;
node.y = mapNode.y;

View File

@ -40,6 +40,7 @@ export class NodeToMapNodeConverter implements Converter<Node, MapNode> {
mapNode.status = node.status;
mapNode.symbol = node.symbol;
mapNode.symbolUrl = node.symbol_url;
mapNode.usage = node.usage;
mapNode.width = node.width;
mapNode.x = node.x;
mapNode.y = node.y;

View File

@ -23,6 +23,7 @@ export class MapNode implements Indexed {
status: string;
symbol: string;
symbolUrl: string;
usage?: string;
width: number;
x: number;
y: number;

View File

@ -82,6 +82,7 @@ export class Node {
status: string;
symbol: string;
symbol_url: string; // @TODO: full URL to symbol, move to MapNode once converters are moved to app module
usage?: string;
width: number;
x: number;
y: number;

View File

@ -7,6 +7,7 @@ import { DraggedDataEvent } from '../../../cartography/events/event-source';
import { MapDrawing } from '../../../cartography/models/map/map-drawing';
import { Drawing } from '../../../cartography/models/drawing';
import { DrawingsEventSource } from '../../../cartography/events/drawings-event-source';
import { Project } from '../../../models/project';
@Component({
selector: 'app-drawing-dragged',
@ -15,6 +16,7 @@ import { DrawingsEventSource } from '../../../cartography/events/drawings-event-
})
export class DrawingDraggedComponent implements OnInit, OnDestroy {
@Input() server: Server;
@Input() project: Project;
private drawingDragged: Subscription;
constructor(
@ -33,7 +35,7 @@ export class DrawingDraggedComponent implements OnInit, OnDestroy {
drawing.y += draggedEvent.dy;
this.drawingService
.updatePosition(this.server, drawing, drawing.x, drawing.y)
.updatePosition(this.server, this.project, drawing, drawing.x, drawing.y)
.subscribe((serverDrawing: Drawing) => {
this.drawingsDataSource.update(serverDrawing);
});

View File

@ -7,6 +7,7 @@ import { Server } from '../../../models/server';
import { NodesEventSource } from '../../../cartography/events/nodes-event-source';
import { MapNode } from '../../../cartography/models/map/map-node';
import { Subscription } from 'rxjs';
import { Project } from '../../../models/project';
@Component({
selector: 'app-node-dragged',
@ -15,6 +16,7 @@ import { Subscription } from 'rxjs';
})
export class NodeDraggedComponent implements OnInit, OnDestroy {
@Input() server: Server;
@Input() project: Project
private nodeDragged: Subscription;
constructor(
@ -32,7 +34,7 @@ export class NodeDraggedComponent implements OnInit, OnDestroy {
node.x += draggedEvent.dx;
node.y += draggedEvent.dy;
this.nodeService.updatePosition(this.server, node, node.x, node.y).subscribe((serverNode: Node) => {
this.nodeService.updatePosition(this.server, this.project, node, node.x, node.y).subscribe((serverNode: Node) => {
this.nodesDataSource.update(serverNode);
});
}

View File

@ -9,6 +9,11 @@
</div>
</div>
</mat-tab>
<mat-tab label="Usage instructions">
<div class="textBox">
{{usage}}
</div>
</mat-tab>
<mat-tab label="Command line">
<div class="textBox">
{{commandLine}}

View File

@ -13,6 +13,7 @@ export class InfoDialogComponent implements OnInit {
@Input() server: Server;
@Input() node: Node;
infoList: string[] = [];
usage: string = '';
commandLine: string = '';
constructor(
@ -23,6 +24,7 @@ export class InfoDialogComponent implements OnInit {
ngOnInit() {
this.infoList = this.infoService.getInfoAboutNode(this.node, this.server);
this.commandLine = this.infoService.getCommandLine(this.node);
this.usage = this.node.usage ? this.node.usage : `No usage information has been provided for this node.`;
}
onCloseClick() {

View File

@ -2,6 +2,7 @@
<app-d3-map
*ngIf="!settings.angular_map"
[server]="server"
[project]="project"
[symbols]="symbols"
[nodes]="nodes"
[links]="links"
@ -96,6 +97,12 @@
</mat-checkbox>
<mat-checkbox [ngModel]="layersVisibility" (change)="toggleLayers($event.checked)">
Show layers
</mat-checkbox><br/>
<mat-checkbox [ngModel]="gridVisibility" (change)="toggleGrid($event.checked)">
Show grid
</mat-checkbox><br/>
<mat-checkbox [ngModel]="project.snap_to_grid" (change)="toggleSnapToGrid($event.checked)">
Snap to grid
</mat-checkbox>
</div>
</mat-menu>
@ -158,11 +165,11 @@
<app-project-map-shortcuts *ngIf="project" [project]="project" [server]="server"></app-project-map-shortcuts>
<app-draw-link-tool [links]="links" *ngIf="tools.draw_link"></app-draw-link-tool>
<app-drawing-dragged [server]="server"></app-drawing-dragged>
<app-drawing-dragged [server]="server" [project]="project"></app-drawing-dragged>
<app-drawing-resized [server]="server"></app-drawing-resized>
<app-interface-label-dragged [server]="server"></app-interface-label-dragged>
<app-link-created [server]="server" [project]="project"></app-link-created>
<app-node-dragged [server]="server"></app-node-dragged>
<app-node-dragged [server]="server" [project]="project"></app-node-dragged>
<app-node-label-dragged [server]="server"></app-node-label-dragged>
<app-text-added [server]="server" [project]="project" (drawingSaved)="onDrawingSaved()"> </app-text-added>
<app-text-edited [server]="server"></app-text-edited>

View File

@ -144,7 +144,7 @@ export class MockedDrawingService {
return of(drawing);
}
updatePosition(_server: Server, _drawing: Drawing, _x: number, _y: number) {
updatePosition(_server: Server, _project: Project, _drawing: Drawing, _x: number, _y: number) {
return of(this.drawing);
}

View File

@ -84,6 +84,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
public isInterfaceLabelVisible: boolean = false;
public notificationsVisibility: boolean = false;
public layersVisibility: boolean = false;
public gridVisibility: boolean = false;
tools = {
selection: true,
@ -240,6 +241,7 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.notificationsVisibility = localStorage.getItem('notificationsVisibility') === 'true' ? true : false;
this.layersVisibility = localStorage.getItem('layersVisibility') === 'true' ? true : false;
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? true : false;
this.addKeyboardListeners();
}
@ -617,6 +619,20 @@ export class ProjectMapComponent implements OnInit, OnDestroy {
this.mapChild.applyMapSettingsChanges();
}
public toggleGrid(visible: boolean) {
this.gridVisibility = visible;
if (this.gridVisibility) {
localStorage.setItem('gridVisibility', 'true');
} else {
localStorage.removeItem('gridVisibility');
}
this.mapChild.gridVisibility = this.gridVisibility ? 1 : 0;
}
public toggleSnapToGrid(enabled: boolean) {
this.project.snap_to_grid = enabled;
}
private showMessage(msg) {
if (this.notificationsVisibility) {
if (msg.type === 'error') this.toasterService.error(msg.message);

View File

@ -8,17 +8,20 @@ import { Drawing } from '../cartography/models/drawing';
import { getTestServer } from './testing';
import { DrawingService } from './drawing.service';
import { AppTestingModule } from '../testing/app-testing/app-testing.module';
import { Project } from '../models/project';
import { SvgToDrawingConverter } from '../cartography/helpers/svg-to-drawing-converter';
describe('DrawingService', () => {
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
let httpServer: HttpServer;
let server: Server;
let project: Project = new Project();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, AppTestingModule],
providers: [HttpServer, DrawingService]
providers: [HttpServer, SvgToDrawingConverter, DrawingService]
});
httpClient = TestBed.get(HttpClient);
@ -40,7 +43,7 @@ describe('DrawingService', () => {
drawing.project_id = 'myproject';
drawing.drawing_id = 'id';
service.updatePosition(server, drawing, 10, 20).subscribe();
service.updatePosition(server, project, drawing, 10, 20).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/drawings/id');
expect(req.request.method).toEqual('PUT');
@ -55,7 +58,7 @@ describe('DrawingService', () => {
drawing.project_id = 'myproject';
drawing.drawing_id = 'id';
service.updatePosition(server, drawing, 10.1, 20.6).subscribe();
service.updatePosition(server, project, drawing, 10.1, 20.6).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/drawings/id');
expect(req.request.method).toEqual('PUT');

View File

@ -5,10 +5,15 @@ import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import { Server } from '../models/server';
import { HttpServer } from './http-server.service';
import { Project } from '../models/project';
import { SvgToDrawingConverter } from '../cartography/helpers/svg-to-drawing-converter';
@Injectable()
export class DrawingService {
constructor(private httpServer: HttpServer) {}
constructor(
private httpServer: HttpServer,
private svgToDrawingConverter: SvgToDrawingConverter
) {}
add(server: Server, project_id: string, x: number, y: number, svg: string) {
return this.httpServer.post<Drawing>(server, `/projects/${project_id}/drawings`, {
@ -29,10 +34,23 @@ export class DrawingService {
});
}
updatePosition(server: Server, drawing: Drawing, x: number, y: number): Observable<Drawing> {
updatePosition(server: Server, project: Project, drawing: Drawing, x: number, y: number): Observable<Drawing> {
let xPosition: number = Math.round(x);
let yPosition: number = Math.round(y);
if (project.snap_to_grid) {
drawing.element = this.svgToDrawingConverter.convert(drawing.svg);
xPosition = Math.round((xPosition + drawing.element.width/2) / project.drawing_grid_size) * project.drawing_grid_size;
yPosition = Math.round((yPosition + drawing.element.width/2) / project.drawing_grid_size) * project.drawing_grid_size;
xPosition = Math.round(xPosition - drawing.element.width/2);
yPosition = Math.round(yPosition - drawing.element.height/2);
}
return this.httpServer.put<Drawing>(server, `/projects/${drawing.project_id}/drawings/${drawing.drawing_id}`, {
x: Math.round(x),
y: Math.round(y)
x: xPosition,
y: yPosition
});
}

View File

@ -154,11 +154,14 @@ describe('NodeService', () => {
}));
it('should updatePosition of node', inject([NodeService], (service: NodeService) => {
let project = {
project_id: '1'
} as Project;
const node = new Node();
node.project_id = 'myproject';
node.node_id = 'id';
service.updatePosition(server, node, 10, 20).subscribe();
service.updatePosition(server, project, node, 10, 20).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/nodes/id');
expect(req.request.method).toEqual('PUT');
@ -169,11 +172,14 @@ describe('NodeService', () => {
}));
it('should updatePosition of node and round to integer', inject([NodeService], (service: NodeService) => {
let project = {
project_id: '1'
} as Project;
const node = new Node();
node.project_id = 'myproject';
node.node_id = 'id';
service.updatePosition(server, node, 10.1, 20.6).subscribe();
service.updatePosition(server, project, node, 10.1, 20.6).subscribe();
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/projects/myproject/nodes/id');
expect(req.request.method).toEqual('PUT');

View File

@ -53,10 +53,21 @@ export class NodeService {
});
}
updatePosition(server: Server, node: Node, x: number, y: number): Observable<Node> {
updatePosition(server: Server, project: Project, node: Node, x: number, y: number): Observable<Node> {
let xPosition: number = Math.round(x);
let yPosition: number = Math.round(y);
if (project.snap_to_grid) {
xPosition = Math.round((xPosition + node.width/2) / project.grid_size) * project.grid_size;
yPosition = Math.round((yPosition + node.width/2) / project.grid_size) * project.grid_size;
xPosition = Math.round(xPosition - node.width/2);
yPosition = Math.round(yPosition - node.height/2);
}
return this.httpServer.put<Node>(server, `/projects/${node.project_id}/nodes/${node.node_id}`, {
x: Math.round(x),
y: Math.round(y)
x: xPosition,
y: yPosition
});
}