Skip to content

Commit

Permalink
add missing template
Browse files Browse the repository at this point in the history
  • Loading branch information
karimra committed Nov 17, 2020
1 parent 5b6ef98 commit 9a3ceee
Showing 1 changed file with 315 additions and 0 deletions.
315 changes: 315 additions & 0 deletions templates/graph/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>ContainerLab Topology '{{ .Name }}'</title>
<style>
html, body{
width: 100%;
height: 100%;
}
#graph {
width: 80%;
height: 100%;
}
#content {
width: 80%;
height: 50%;
}
</style>
</head>

<body>
<div id="content" style="margin:0 auto;">
<h1>ContainerLab Topology '{{ .Name }}'</h1>
<div>
<button id='saveButton' class="button">Export as PNG</button>
</div>

<div id="graph"></div>

<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
<script src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
<script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
<script>

var width,height
var chartWidth, chartHeight
var margin
var svg = d3.select("#graph").append("svg")
var chartLayer = svg.append("g").classed("chartLayer", true)

var r = 20;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = `{{ .Data }}`
data = JSON.parse(data)
console.log(data)

main()

function main() {
setSize(data)
draw()
tabulate(data.nodes, ["name", "image", "kind", "group", "state", "ipv4_address", "ipv6_address"]);
// Set-up the export button
d3.select('#saveButton').on('click', function(){
var svgString = getSVGString(svg.node());
svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback

function save( dataBlob, filesize ){
saveAs( dataBlob, '{{ .Name }}.png' ); // FileSaver.js function
}
});
}

function setSize() {
width = document.querySelector("#graph").clientWidth
height = document.querySelector("#graph").clientHeight

margin = {top:0, left:0, bottom:0, right:0 }


chartWidth = width - (margin.left+margin.right)
chartHeight = height - (margin.top+margin.bottom)

svg.attr("width", width).attr("height", height)
console.log(width, height)

chartLayer
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("transform", "translate("+[margin.left, margin.top]+")")
}

function draw() {
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.name }))
.force("collide",d3.forceCollide(2*r))
.force("charge", d3.forceManyBody().strength(-500))
.force("x", d3.forceX(chartWidth/2))
.force("y", d3.forceY(chartHeight/2))

var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(data.links)
.enter()
.append("line")
.attr("stroke", "black")

var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(data.nodes)
.enter().append("circle")
.attr("r", r)
.style("fill", function (d) { return color(d.group); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));

var labels = svg.selectAll("text")
.data(data.nodes)
.enter()
.append("text")
.text(function(d) { return d.name; })
.style("font", "20px Georgia")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));


var ticked = function() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });

node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });

labels
.attr("x", function(d) { return d.x-r; })
.attr("y", function(d) { return d.y+2*r; });


}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;

}

function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = Math.ceil((d.fx)/10)*10;
d.fy = Math.ceil((d.fy)/10)*10;
}
simulation
.nodes(data.nodes)
.on("tick", ticked);

simulation.force("link")
.links(data.links);
}

// The table generation function
function tabulate(data, columns) {
var table = d3.select("#content").append("table")
.attr("class", "table table-sm table-dark")
.attr("width", chartWidth * 0.7)
.style("border-collapse", "collapse")// <= Add this line in
.style("border", "2px black solid"), // <= Add this line in

thead = table.append("thead"),
tbody = table.append("tbody");

// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) {
return column.replace("_", " ");
});

// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(data)
.enter()
.append("tr");

// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.attr("style", "font-family: Courier") // sets the font style
.html(function(d) { return d.value; });

return table;
}

// Below are the functions that handle actual exporting:
// getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
function getSVGString( svgNode ) {
svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
var cssStyleText = getCSSStyles( svgNode );
appendCSS( cssStyleText, svgNode );

var serializer = new XMLSerializer();
var svgString = serializer.serializeToString(svgNode);
svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix

return svgString;

function getCSSStyles( parentElement ) {
var selectorTextArr = [];

// Add Parent element Id and Classes to the list
selectorTextArr.push( '#'+parentElement.id );
for (var c = 0; c < parentElement.classList.length; c++)
if ( !contains('.'+parentElement.classList[c], selectorTextArr) )
selectorTextArr.push( '.'+parentElement.classList[c] );

// Add Children element Ids and Classes to the list
var nodes = parentElement.getElementsByTagName("*");
for (var i = 0; i < nodes.length; i++) {
var id = nodes[i].id;
if ( !contains('#'+id, selectorTextArr) )
selectorTextArr.push( '#'+id );

var classes = nodes[i].classList;
for (var c = 0; c < classes.length; c++)
if ( !contains('.'+classes[c], selectorTextArr) )
selectorTextArr.push( '.'+classes[c] );
}

// Extract CSS Rules
var extractedCSSText = "";
for (var i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];

try {
if(!s.cssRules) continue;
} catch( e ) {
if(e.name !== 'SecurityError') throw e; // for Firefox
continue;
}

var cssRules = s.cssRules;
for (var r = 0; r < cssRules.length; r++) {
if ( contains( cssRules[r].selectorText, selectorTextArr ) )
extractedCSSText += cssRules[r].cssText;
}
}


return extractedCSSText;

function contains(str,arr) {
return arr.indexOf( str ) === -1 ? false : true;
}

}

function appendCSS( cssText, element ) {
var styleElement = document.createElement("style");
styleElement.setAttribute("type","text/css");
styleElement.innerHTML = cssText;
var refNode = element.hasChildNodes() ? element.children[0] : null;
element.insertBefore( styleElement, refNode );
}
}

function svgString2Image( svgString, width, height, format, callback ) {
var format = format ? format : 'png';

var imgsrc = 'data:image/svg+xml;base64,'+ btoa( unescape( encodeURIComponent( svgString ) ) ); // Convert SVG string to data URL

var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");

canvas.width = width;
canvas.height = height;

var image = new Image();
image.onload = function() {
context.clearRect ( 0, 0, width, height );
context.drawImage(image, 0, 0, width, height);

canvas.toBlob( function(blob) {
var filesize = Math.round( blob.length/1024 ) + ' KB';
if ( callback ) callback( blob, filesize );
});


};

image.src = imgsrc;
}

</script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</div>
</body>
</html>

0 comments on commit 9a3ceee

Please sign in to comment.