Skip to content

Instantly share code, notes, and snippets.

@TheLurps
Created September 17, 2024 17:30
Show Gist options
  • Select an option

  • Save TheLurps/4c58cb902286f6d35ac31476f9b96d8e to your computer and use it in GitHub Desktop.

Select an option

Save TheLurps/4c58cb902286f6d35ac31476f9b96d8e to your computer and use it in GitHub Desktop.
Service map generated using D3.js and dummy data
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dummy service map</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.node circle {
fill: blue;
stroke: black;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
pointer-events: none;
}
.link {
fill: none;
stroke: grey;
stroke-opacity: 0.6;
stroke-width: 1.5px;
}
.marker {
fill: grey;
stroke: none;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
const data = [
{
"id": "1",
"name": "RZ1VCMRDS101",
"services": [
{
"id": "1",
"name": "RDP",
"listeners": [
{
"id": "1",
"name": "TCP",
"ip": "192.168.1.1",
"port": "3389"
}
],
"depends_on": ["4", "5"]
}
]
},
{
"id": "2",
"name": "RZ1VCMWEB101",
"services": [
{
"id": "2",
"name": "HTTP",
"listeners": [
{
"id": "2",
"name": "TCP",
"ip": "192.168.1.2",
"port": "80"
}
],
"depends_on": ["5"]
},
{
"id": "3",
"name": "HTTPS",
"listeners": [
{
"id": "3",
"name": "TCP",
"ip": "192.168.1.2",
"port": "443"
}
],
"depends_on": ["5"]
}
]
},
{
"id": "3",
"name": "RZ1VCMRDS001",
"services": [
{
"id": "4",
"name": "RDP",
"listeners": [
{
"id": "4",
"name": "TCP",
"ip": "192.168.1.3",
"port": "3389"
}
],
"depends_on": []
},
]
},
{
"id": "4",
"name": "RZ1VCMSQL001",
"services": [
{
"id": "5",
"name": "MSSQL",
"listeners": [
{
"id": "5",
"name": "TCP",
"ip": "192.168.1.4",
"port": "1433"
}
],
"depends_on": []
},
]
}
];
console.log(data);
const nodes = [];
const links = [];
data.forEach(group => {
group.services.forEach(service => {
nodes.push({ id: service.id, name: group.name + " - " + service.name });
service.depends_on.forEach(dep => {
links.push({ source: service.id, target: dep });
});
});
});
const width = 800;
const height = 600;
const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").selectAll("marker")
.data(["end"])
.enter().append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.attr("class", "marker")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(100))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2));
const link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(links)
.enter().append("line")
.attr("class", "link")
.attr("marker-end", "url(#arrow)");
const node = svg.append("g")
.attr("class", "nodes")
.selectAll("g")
.data(nodes)
.enter().append("g")
.attr("class", "node");
node.append("circle")
.attr("r", 10);
node.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.text(d => d.name);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("transform", d => `translate(${d.x},${d.y})`);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment