mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-21 13:57:48 +00:00
Drawings, ref. #10
This commit is contained in:
parent
5690db42cd
commit
2eb7246f87
@ -7,6 +7,7 @@ import { Link } from "../shared/models/link.model";
|
|||||||
import { GraphLayout } from "../shared/widgets/graph.widget";
|
import { GraphLayout } from "../shared/widgets/graph.widget";
|
||||||
import { Context } from "../../map/models/context";
|
import { Context } from "../../map/models/context";
|
||||||
import { Size } from "../shared/models/size.model";
|
import { Size } from "../shared/models/size.model";
|
||||||
|
import { Drawing } from "../shared/models/drawing.model";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -17,6 +18,7 @@ import { Size } from "../shared/models/size.model";
|
|||||||
export class MapComponent implements OnInit, OnChanges, OnDestroy {
|
export class MapComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() nodes: Node[] = [];
|
@Input() nodes: Node[] = [];
|
||||||
@Input() links: Link[] = [];
|
@Input() links: Link[] = [];
|
||||||
|
@Input() drawings: Drawing[] = [];
|
||||||
@Input() width = 1500;
|
@Input() width = 1500;
|
||||||
@Input() height = 600;
|
@Input() height = 600;
|
||||||
@Input() phylloRadius = 7;
|
@Input() phylloRadius = 7;
|
||||||
@ -43,6 +45,7 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
(changes['height'] && !changes['height'].isFirstChange()) ||
|
(changes['height'] && !changes['height'].isFirstChange()) ||
|
||||||
(changes['phylloRadius'] && !changes['phylloRadius'].isFirstChange()) ||
|
(changes['phylloRadius'] && !changes['phylloRadius'].isFirstChange()) ||
|
||||||
(changes['pointRadius'] && !changes['pointRadius'].isFirstChange()) ||
|
(changes['pointRadius'] && !changes['pointRadius'].isFirstChange()) ||
|
||||||
|
(changes['drawings'] && !changes['drawings'].isFirstChange()) ||
|
||||||
(changes['nodes'] && !changes['nodes'].isFirstChange()) ||
|
(changes['nodes'] && !changes['nodes'].isFirstChange()) ||
|
||||||
(changes['links'] && !changes['links'].isFirstChange())
|
(changes['links'] && !changes['links'].isFirstChange())
|
||||||
) {
|
) {
|
||||||
@ -115,6 +118,7 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
this.graphLayout.setNodes(this.nodes);
|
this.graphLayout.setNodes(this.nodes);
|
||||||
this.graphLayout.setLinks(this.links);
|
this.graphLayout.setLinks(this.links);
|
||||||
|
this.graphLayout.setDrawings(this.drawings);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw();
|
||||||
}
|
}
|
||||||
|
9
src/app/cartography/shared/models/drawing.model.ts
Normal file
9
src/app/cartography/shared/models/drawing.model.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export class Drawing {
|
||||||
|
drawing_id: string;
|
||||||
|
project_id: string;
|
||||||
|
rotation: number;
|
||||||
|
svg: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
z: number;
|
||||||
|
}
|
60
src/app/cartography/shared/widgets/drawings.widget.ts
Normal file
60
src/app/cartography/shared/widgets/drawings.widget.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import {Widget} from "./widget";
|
||||||
|
import {Drawing} from "../models/drawing.model";
|
||||||
|
import {SVGSelection} from "../../../map/models/types";
|
||||||
|
|
||||||
|
|
||||||
|
export class DrawingsWidget implements Widget {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
public draw(view: SVGSelection, drawings: Drawing[]) {
|
||||||
|
const drawing = view.selectAll<SVGGElement, Drawing>('g.drawing')
|
||||||
|
.data(drawings);
|
||||||
|
|
||||||
|
const drawing_enter = drawing.enter()
|
||||||
|
.append<SVGGElement>('g')
|
||||||
|
.attr('class', 'drawing');
|
||||||
|
|
||||||
|
const parser = new DOMParser();
|
||||||
|
|
||||||
|
const drawing_image = drawing_enter.append<SVGImageElement>('image')
|
||||||
|
.attr('xlink:href', (d: Drawing) => {
|
||||||
|
let svg = d.svg;
|
||||||
|
if (svg.indexOf("xmlns") < 0) {
|
||||||
|
svg = svg.replace('svg', 'svg xmlns="http://www.w3.org/2000/svg"');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'data:image/svg+xml;base64,' + btoa(svg);
|
||||||
|
})
|
||||||
|
.attr('width', (d: Drawing) => {
|
||||||
|
const svg_dom = parser.parseFromString(d.svg, 'text/xml');
|
||||||
|
const roots = svg_dom.getElementsByTagName('svg');
|
||||||
|
if (roots.length > 0) {
|
||||||
|
if (roots[0].hasAttribute('width')) {
|
||||||
|
return roots[0].getAttribute('width');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.attr('height', (d: Drawing) => {
|
||||||
|
const svg_dom = parser.parseFromString(d.svg, 'text/xml');
|
||||||
|
const roots = svg_dom.getElementsByTagName('svg');
|
||||||
|
if (roots.length > 0) {
|
||||||
|
if (roots[0].hasAttribute('height')) {
|
||||||
|
return roots[0].getAttribute('height');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const drawing_merge = drawing.merge(drawing_enter)
|
||||||
|
.attr('transform', (d: Drawing) => {
|
||||||
|
return `translate(${d.x},${d.y})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
drawing.exit().remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
private appendSVG(svg: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -7,14 +7,18 @@ import { SVGSelection } from "../../../map/models/types";
|
|||||||
import { LinksWidget } from "./links.widget";
|
import { LinksWidget } from "./links.widget";
|
||||||
import { D3ZoomEvent, zoom } from "d3-zoom";
|
import { D3ZoomEvent, zoom } from "d3-zoom";
|
||||||
import { event } from "d3-selection";
|
import { event } from "d3-selection";
|
||||||
|
import {Drawing} from "../models/drawing.model";
|
||||||
|
import {DrawingsWidget} from "./drawings.widget";
|
||||||
|
|
||||||
export class GraphLayout implements Widget {
|
export class GraphLayout implements Widget {
|
||||||
|
|
||||||
private nodes: Node[] = [];
|
private nodes: Node[] = [];
|
||||||
private links: Link[] = [];
|
private links: Link[] = [];
|
||||||
|
private drawings: Drawing[] = [];
|
||||||
|
|
||||||
private nodesWidget = new NodesWidget();
|
private nodesWidget = new NodesWidget();
|
||||||
private linksWidget = new LinksWidget();
|
private linksWidget = new LinksWidget();
|
||||||
|
private drawingsWidget = new DrawingsWidget();
|
||||||
|
|
||||||
private centerZeroZeroPoint = true;
|
private centerZeroZeroPoint = true;
|
||||||
|
|
||||||
@ -26,42 +30,46 @@ export class GraphLayout implements Widget {
|
|||||||
this.links = links;
|
this.links = links;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setDrawings(drawings: Drawing[]) {
|
||||||
|
this.drawings = drawings;
|
||||||
|
}
|
||||||
|
|
||||||
draw(view: SVGSelection, context: Context) {
|
draw(view: SVGSelection, context: Context) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
const drawing = view
|
const canvas = view
|
||||||
.selectAll<SVGGElement, Context>('g.drawing')
|
.selectAll<SVGGElement, Context>('g.canvas')
|
||||||
.data([context]);
|
.data([context]);
|
||||||
|
|
||||||
const drawingEnter = drawing.enter()
|
const canvasEnter = canvas.enter()
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.attr('class', 'drawing');
|
.attr('class', 'canvas');
|
||||||
|
|
||||||
if (this.centerZeroZeroPoint) {
|
if (this.centerZeroZeroPoint) {
|
||||||
drawing.attr(
|
canvas.attr(
|
||||||
'transform',
|
'transform',
|
||||||
(ctx: Context) => `translate(${ctx.getSize().width / 2}, ${ctx.getSize().height / 2})`);
|
(ctx: Context) => `translate(${ctx.getSize().width / 2}, ${ctx.getSize().height / 2})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const links = drawingEnter.append<SVGGElement>('g')
|
// const links = canvasEnter.append<SVGGElement>('g')
|
||||||
.attr('class', 'links');
|
// .attr('class', 'links');
|
||||||
|
//
|
||||||
|
// const nodes = canvasEnter.append<SVGGElement>('g')
|
||||||
|
// .attr('class', 'nodes');
|
||||||
|
|
||||||
const nodes = drawingEnter.append<SVGGElement>('g')
|
this.linksWidget.draw(canvas, this.links);
|
||||||
.attr('class', 'nodes');
|
this.nodesWidget.draw(canvas, this.nodes);
|
||||||
|
this.drawingsWidget.draw(canvas, this.drawings)
|
||||||
this.linksWidget.draw(drawing, this.links);
|
|
||||||
this.nodesWidget.draw(drawing, this.nodes);
|
|
||||||
|
|
||||||
const onZoom = function(this: SVGSVGElement) {
|
const onZoom = function(this: SVGSVGElement) {
|
||||||
const e: D3ZoomEvent<SVGSVGElement, any> = event;
|
const e: D3ZoomEvent<SVGSVGElement, any> = event;
|
||||||
if (self.centerZeroZeroPoint) {
|
if (self.centerZeroZeroPoint) {
|
||||||
drawing.attr(
|
canvas.attr(
|
||||||
'transform',
|
'transform',
|
||||||
`translate(${context.getSize().width / 2 + e.transform.x}, ` +
|
`translate(${context.getSize().width / 2 + e.transform.x}, ` +
|
||||||
`${context.getSize().height / 2 + e.transform.y}) scale(${e.transform.k})`);
|
`${context.getSize().height / 2 + e.transform.y}) scale(${e.transform.k})`);
|
||||||
} else {
|
} else {
|
||||||
drawing.attr('transform', e.transform.toString());
|
canvas.attr('transform', e.transform.toString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
<svg preserveAspectRatio="none"></svg>
|
<svg xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="none"></svg>
|
||||||
|
Before Width: | Height: | Size: 39 B After Width: | Height: | Size: 83 B |
@ -1,5 +1,5 @@
|
|||||||
<div *ngIf="project" class="project-map">
|
<div *ngIf="project" class="project-map">
|
||||||
<app-map [nodes]="nodes" [links]="links"></app-map>
|
<app-map [nodes]="nodes" [links]="links" [drawings]="drawings"></app-map>
|
||||||
|
|
||||||
<div class="project-toolbar">
|
<div class="project-toolbar">
|
||||||
<mat-toolbar color="primary" class="project-toolbar">
|
<mat-toolbar color="primary" class="project-toolbar">
|
||||||
|
@ -25,6 +25,7 @@ import { Snapshot } from "../shared/models/snapshot";
|
|||||||
import { ProgressDialogService } from "../shared/progress-dialog/progress-dialog.service";
|
import { ProgressDialogService } from "../shared/progress-dialog/progress-dialog.service";
|
||||||
import { ProgressDialogComponent } from "../shared/progress-dialog/progress-dialog.component";
|
import { ProgressDialogComponent } from "../shared/progress-dialog/progress-dialog.component";
|
||||||
import { ToastyService } from "ng2-toasty";
|
import { ToastyService } from "ng2-toasty";
|
||||||
|
import {Drawing} from "../cartography/shared/models/drawing.model";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -36,6 +37,7 @@ import { ToastyService } from "ng2-toasty";
|
|||||||
export class ProjectMapComponent implements OnInit {
|
export class ProjectMapComponent implements OnInit {
|
||||||
public nodes: Node[] = [];
|
public nodes: Node[] = [];
|
||||||
public links: Link[] = [];
|
public links: Link[] = [];
|
||||||
|
public drawings: Drawing[] = [];
|
||||||
|
|
||||||
project: Project;
|
project: Project;
|
||||||
server: Server;
|
server: Server;
|
||||||
@ -86,6 +88,10 @@ export class ProjectMapComponent implements OnInit {
|
|||||||
this.symbolService
|
this.symbolService
|
||||||
.load(this.server)
|
.load(this.server)
|
||||||
.flatMap(() => {
|
.flatMap(() => {
|
||||||
|
return this.projectService.drawings(this.server, project.project_id);
|
||||||
|
})
|
||||||
|
.flatMap((drawings: Drawing[]) => {
|
||||||
|
this.drawings = drawings;
|
||||||
return this.projectService.links(this.server, project.project_id);
|
return this.projectService.links(this.server, project.project_id);
|
||||||
})
|
})
|
||||||
.flatMap((links: Link[]) => {
|
.flatMap((links: Link[]) => {
|
||||||
|
@ -7,6 +7,7 @@ import 'rxjs/add/operator/map';
|
|||||||
import { Link } from "../../cartography/shared/models/link.model";
|
import { Link } from "../../cartography/shared/models/link.model";
|
||||||
import { Server } from "../models/server";
|
import { Server } from "../models/server";
|
||||||
import { HttpServer } from "./http-server.service";
|
import { HttpServer } from "./http-server.service";
|
||||||
|
import {Drawing} from "../../cartography/shared/models/drawing.model";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProjectService {
|
export class ProjectService {
|
||||||
@ -43,6 +44,12 @@ export class ProjectService {
|
|||||||
.map(response => response.json() as Link[]);
|
.map(response => response.json() as Link[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawings(server: Server, project_id: string): Observable<Drawing[]> {
|
||||||
|
return this.httpServer
|
||||||
|
.get(server, `/projects/${project_id}/drawings`)
|
||||||
|
.map(response => response.json() as Drawing[]);
|
||||||
|
}
|
||||||
|
|
||||||
delete(server: Server, project_id: string): Observable<any> {
|
delete(server: Server, project_id: string): Observable<any> {
|
||||||
return this.httpServer
|
return this.httpServer
|
||||||
.delete(server, `/projects/${project_id}`);
|
.delete(server, `/projects/${project_id}`);
|
||||||
|
Loading…
Reference in New Issue
Block a user