mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-21 13:57:48 +00:00
Different layers, Ref: #11
This commit is contained in:
parent
bdbbc0a3f4
commit
f03abfe761
10
src/app/cartography/shared/models/layer.ts
Normal file
10
src/app/cartography/shared/models/layer.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {Drawing} from "./drawing";
|
||||
import {Link} from "./link";
|
||||
import {Node} from "./node";
|
||||
|
||||
export class Layer {
|
||||
index: number;
|
||||
nodes: Node[];
|
||||
drawings: Drawing[];
|
||||
links: Link[];
|
||||
}
|
@ -2,6 +2,7 @@ import {Label} from "./label";
|
||||
import {Port} from "../../../shared/models/port";
|
||||
import {Selectable} from "../managers/selection-manager";
|
||||
|
||||
|
||||
export class Node implements Selectable {
|
||||
command_line: string;
|
||||
compute_id: string;
|
||||
|
@ -1,14 +1,20 @@
|
||||
import {Widget} from "./widget";
|
||||
import {Drawing} from "../models/drawing";
|
||||
import {SVGSelection} from "../models/types";
|
||||
import {Layer} from "../models/layer";
|
||||
|
||||
|
||||
export class DrawingsWidget implements Widget {
|
||||
constructor() {}
|
||||
|
||||
public draw(view: SVGSelection, drawings: Drawing[]) {
|
||||
const drawing = view.selectAll<SVGGElement, Drawing>('g.drawing')
|
||||
.data(drawings);
|
||||
public draw(view: SVGSelection, drawings?: Drawing[]) {
|
||||
const drawing = view
|
||||
.selectAll<SVGGElement, Drawing>('g.drawing')
|
||||
.data((l: Layer) => {
|
||||
return l.drawings;
|
||||
}, (d: Drawing) => {
|
||||
return d.drawing_id;
|
||||
});
|
||||
|
||||
const drawing_enter = drawing.enter()
|
||||
.append<SVGGElement>('g')
|
||||
@ -53,8 +59,4 @@ export class DrawingsWidget implements Widget {
|
||||
|
||||
drawing.exit().remove();
|
||||
}
|
||||
|
||||
private appendSVG(svg: string) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ import { DrawingsWidget } from "./drawings.widget";
|
||||
import { DrawingLineWidget } from "./drawing-line.widget";
|
||||
import {SelectionTool} from "../tools/selection-tool";
|
||||
import {MovingTool} from "../tools/moving-tool";
|
||||
import {LayersWidget} from "./layers.widget";
|
||||
import {Layer} from "../models/layer";
|
||||
|
||||
|
||||
export class GraphLayout implements Widget {
|
||||
private nodes: Node[] = [];
|
||||
@ -22,6 +25,7 @@ export class GraphLayout implements Widget {
|
||||
private drawingLineTool: DrawingLineWidget;
|
||||
private selectionTool: SelectionTool;
|
||||
private movingTool: MovingTool;
|
||||
private layersWidget: LayersWidget;
|
||||
|
||||
private centerZeroZeroPoint = true;
|
||||
|
||||
@ -32,6 +36,7 @@ export class GraphLayout implements Widget {
|
||||
this.drawingLineTool = new DrawingLineWidget();
|
||||
this.selectionTool = new SelectionTool();
|
||||
this.movingTool = new MovingTool();
|
||||
this.layersWidget = new LayersWidget();
|
||||
}
|
||||
|
||||
public setNodes(nodes: Node[]) {
|
||||
@ -54,6 +59,10 @@ export class GraphLayout implements Widget {
|
||||
return this.linksWidget;
|
||||
}
|
||||
|
||||
public getDrawingsWidget() {
|
||||
return this.drawingsWidget;
|
||||
}
|
||||
|
||||
public getDrawingLineTool() {
|
||||
return this.drawingLineTool;
|
||||
}
|
||||
@ -89,9 +98,56 @@ export class GraphLayout implements Widget {
|
||||
(ctx: Context) => `translate(${ctx.getSize().width / 2}, ${ctx.getSize().height / 2})`);
|
||||
}
|
||||
|
||||
this.linksWidget.draw(canvas, this.links);
|
||||
this.nodesWidget.draw(canvas, this.nodes);
|
||||
this.drawingsWidget.draw(canvas, this.drawings);
|
||||
|
||||
const layers = {};
|
||||
|
||||
this.nodes.forEach((n: Node) => {
|
||||
const key = n.z.toString();
|
||||
if (!(key in layers)) {
|
||||
layers[key] = new Layer();
|
||||
layers[key].nodes = [];
|
||||
layers[key].drawings = [];
|
||||
layers[key].links = [];
|
||||
}
|
||||
layers[key].nodes.push(n);
|
||||
});
|
||||
|
||||
|
||||
this.drawings.forEach((d: Drawing) => {
|
||||
const key = d.z.toString();
|
||||
if (!(key in layers)) {
|
||||
layers[key] = new Layer();
|
||||
layers[key].nodes = [];
|
||||
layers[key].drawings = [];
|
||||
layers[key].links = [];
|
||||
}
|
||||
layers[key].drawings.push(d);
|
||||
});
|
||||
|
||||
this.links.forEach((l: Link) => {
|
||||
if (!l.source || !l.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
const key = Math.min(l.source.z, l.target.z).toString();
|
||||
|
||||
if (!(key in layers)) {
|
||||
layers[key] = new Layer();
|
||||
layers[key].nodes = [];
|
||||
layers[key].drawings = [];
|
||||
layers[key].links = [];
|
||||
}
|
||||
layers[key].links.push(l);
|
||||
});
|
||||
|
||||
const layers_list: Layer[] = Object.keys(layers).sort((a: string, b: string) => {
|
||||
return Number(a) - Number(b);
|
||||
}).map((key: string) => {
|
||||
return layers[key];
|
||||
});
|
||||
|
||||
this.layersWidget.graphLayout = this;
|
||||
this.layersWidget.draw(canvas, layers_list);
|
||||
|
||||
this.drawingLineTool.draw(view, context);
|
||||
this.selectionTool.draw(view, context);
|
||||
|
38
src/app/cartography/shared/widgets/layers.widget.ts
Normal file
38
src/app/cartography/shared/widgets/layers.widget.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { Widget } from "./widget";
|
||||
import { SVGSelection } from "../models/types";
|
||||
import { GraphLayout } from "./graph.widget";
|
||||
import { Layer } from "../models/layer";
|
||||
|
||||
|
||||
export class LayersWidget implements Widget {
|
||||
public graphLayout: GraphLayout;
|
||||
|
||||
public draw(view: SVGSelection, layers: Layer[]) {
|
||||
|
||||
const layers_selection = view
|
||||
.selectAll<SVGGElement, Layer>('g.layer')
|
||||
.data(layers);
|
||||
|
||||
layers_selection
|
||||
.enter()
|
||||
.append<SVGGElement>('g')
|
||||
.attr('class', 'layer')
|
||||
.attr('data-index', (layer: Layer) => layer.index);
|
||||
|
||||
layers_selection
|
||||
.exit()
|
||||
.remove();
|
||||
|
||||
this.graphLayout
|
||||
.getNodesWidget()
|
||||
.draw(layers_selection);
|
||||
|
||||
this.graphLayout
|
||||
.getDrawingsWidget()
|
||||
.draw(layers_selection);
|
||||
|
||||
this.graphLayout
|
||||
.getLinksWidget()
|
||||
.draw(layers_selection);
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
import {BaseType, select, Selection} from "d3-selection";
|
||||
import { select } from "d3-selection";
|
||||
|
||||
import { Widget } from "./widget";
|
||||
import { SVGSelection } from "../models/types";
|
||||
import { Link } from "../models/link";
|
||||
import { LinkStatus } from "../models/link-status";
|
||||
import { MultiLinkCalculatorHelper } from "../../map/helpers/multi-link-calculator-helper";
|
||||
import {SerialLinkWidget} from "./serial-link.widget";
|
||||
import {EthernetLinkWidget} from "./ethernet-link.widget";
|
||||
import { SerialLinkWidget } from "./serial-link.widget";
|
||||
import { EthernetLinkWidget } from "./ethernet-link.widget";
|
||||
import { Layer } from "../models/layer";
|
||||
|
||||
|
||||
export class LinksWidget implements Widget {
|
||||
@ -96,29 +97,30 @@ export class LinksWidget implements Widget {
|
||||
});
|
||||
}
|
||||
|
||||
public draw(view: SVGSelection, links: Link[]) {
|
||||
const self = this;
|
||||
|
||||
this.multiLinkCalculatorHelper.assignDataToLinks(links);
|
||||
|
||||
const linksLayer = view.selectAll("g.links").data([{}]);
|
||||
linksLayer
|
||||
.enter()
|
||||
.append<SVGGElement>('g')
|
||||
.attr("class", "links");
|
||||
|
||||
const link = linksLayer
|
||||
public draw(view: SVGSelection, links?: Link[]) {
|
||||
const link = view
|
||||
.selectAll<SVGGElement, Link>("g.link")
|
||||
.data(links.filter((l: Link) => {
|
||||
return l.target && l.source;
|
||||
}));
|
||||
.data((layer: Layer) => {
|
||||
console.log(layer.links);
|
||||
if (layer.links) {
|
||||
const layer_links = layer.links.filter((l: Link) => {
|
||||
return l.target && l.source;
|
||||
});
|
||||
this.multiLinkCalculatorHelper.assignDataToLinks(layer_links);
|
||||
return layer_links;
|
||||
}
|
||||
return [];
|
||||
}, (l: Link) => {
|
||||
return l.link_id;
|
||||
});
|
||||
|
||||
|
||||
const link_enter = link.enter()
|
||||
.append<SVGGElement>('g')
|
||||
.attr('class', 'link')
|
||||
.attr('link_id', (l: Link) => l.link_id)
|
||||
.attr('map-source', (l: Link) => l.source.node_id)
|
||||
.attr('map-target', (l: Link) => l.target.node_id)
|
||||
.attr('map-target', (l: Link) => l.target.node_id);
|
||||
|
||||
const merge = link.merge(link_enter);
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Widget } from "./widget";
|
||||
import { Node } from "../models/node";
|
||||
import { SVGSelection } from "../models/types";
|
||||
import {event, select} from "d3-selection";
|
||||
import {event, select, Selection} from "d3-selection";
|
||||
import {D3DragEvent, drag} from "d3-drag";
|
||||
import {Symbol} from "../models/symbol";
|
||||
import {Layer} from "../models/layer";
|
||||
|
||||
|
||||
export class NodesWidget implements Widget {
|
||||
@ -78,16 +79,23 @@ export class NodesWidget implements Widget {
|
||||
|
||||
}
|
||||
|
||||
public draw(view: SVGSelection, nodes: Node[]) {
|
||||
public draw(view: SVGSelection, nodes?: Node[]) {
|
||||
const self = this;
|
||||
|
||||
const node = view
|
||||
.selectAll<SVGGElement, any>('g.node')
|
||||
.data(nodes, (n: Node) => {
|
||||
return n.node_id;
|
||||
});
|
||||
let nodes_selection: Selection<SVGGElement, Node, any, any> = view
|
||||
.selectAll<SVGGElement, Node>('g.node');
|
||||
|
||||
const node_enter = node
|
||||
if (nodes) {
|
||||
nodes_selection = nodes_selection.data(nodes);
|
||||
} else {
|
||||
nodes_selection = nodes_selection.data((l: Layer) => {
|
||||
return l.nodes;
|
||||
}, (n: Node) => {
|
||||
return n.node_id;
|
||||
});
|
||||
}
|
||||
|
||||
const node_enter = nodes_selection
|
||||
.enter()
|
||||
.append<SVGGElement>('g')
|
||||
.attr('class', 'node');
|
||||
@ -134,7 +142,7 @@ export class NodesWidget implements Widget {
|
||||
.attr('y', '0');
|
||||
}
|
||||
|
||||
const node_merge = node
|
||||
const node_merge = nodes_selection
|
||||
.merge(node_enter)
|
||||
.classed('selected', (n: Node) => n.is_selected)
|
||||
.on("contextmenu", function (n: Node, i: number) {
|
||||
@ -175,7 +183,7 @@ export class NodesWidget implements Widget {
|
||||
|
||||
node_merge.call(dragging());
|
||||
|
||||
node
|
||||
nodes_selection
|
||||
.exit()
|
||||
.remove();
|
||||
}
|
||||
|
@ -6,6 +6,11 @@ import { Server } from '../models/server';
|
||||
import { HttpServer } from './http-server.service';
|
||||
|
||||
|
||||
class MyType {
|
||||
id: number;
|
||||
}
|
||||
|
||||
|
||||
describe('HttpServer', () => {
|
||||
let httpClient: HttpClient;
|
||||
let httpTestingController: HttpTestingController;
|
||||
@ -44,6 +49,37 @@ describe('HttpServer', () => {
|
||||
expect(req.request.responseType).toEqual("json");
|
||||
});
|
||||
|
||||
it('should make GET query for get method and return instance of type', () => {
|
||||
const testData: MyType = {id: 3};
|
||||
|
||||
service.get<MyType>(server, '/test').subscribe(data => {
|
||||
expect(data instanceof MyType).toBeFalsy();
|
||||
expect(data).toEqual(testData);
|
||||
});
|
||||
|
||||
const req = httpTestingController.expectOne('http://127.0.0.1:3080/v2/test');
|
||||
expect(req.request.method).toEqual("GET");
|
||||
expect(req.request.responseType).toEqual("json");
|
||||
|
||||
req.flush({id: 3});
|
||||
});
|
||||
|
||||
it('HttpClient should make GET query for get method and return instance of type', () => {
|
||||
const testData: MyType = {id: 3};
|
||||
|
||||
httpClient.get<MyType>('http://localhost/test').subscribe(data => {
|
||||
// when this condition is true, it would be great
|
||||
expect(data instanceof MyType).toBeFalsy();
|
||||
expect(data).toEqual(testData);
|
||||
});
|
||||
|
||||
const req = httpTestingController.expectOne('http://localhost/test');
|
||||
expect(req.request.method).toEqual("GET");
|
||||
expect(req.request.responseType).toEqual("json");
|
||||
|
||||
req.flush(testData);
|
||||
});
|
||||
|
||||
it('should make GET query for getText method', () => {
|
||||
service.getText(server, '/test').subscribe();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user