Skip to content

Instantly share code, notes, and snippets.

@empiimp
Forked from mbostock/.block
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save empiimp/8852277 to your computer and use it in GitHub Desktop.

Select an option

Save empiimp/8852277 to your computer and use it in GitHub Desktop.
Model of Territory Forecast data flow from sql server base tables to Excel file

Click to drag nodes. Dashed links are resolved suits; green links are licensing.

Internal connections between tables/views/excel files...

Implemented in D3.js.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
#licensing {
fill: green;
}
.link.licensing {
stroke: green;
}
.link.resolved {
stroke-dasharray: 0,2 1;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/
// Arrow goes from Source to Target
var links = [
{source: "Report..vwForecastCallAnalytics", target: "ForecastCallAnalytics", type: "licensing"},
{source: "Report..tblForecastCallAnalytics", target: "Report..vwForecastCallAnalytics", type: "licensing"},
{source: "Report..cntl_ACL_UserkeyToField", target: "Report..vwForecastCallAnalytics", type: "suit"},
{source: "Report..cntl_ACL_UserkeyToTerritory", target: "Report..vwForecastCallAnalytics", type: "suit"},
{source: "Salesforce..spPopulate_tblForecastCallHistory", target: "Report..tblForecastCallAnalytics", type: "resolved"},
{source: "Report..tblOrderOpportunity", target: "Salesforce..spPopulate_tblForecastCallHistory", type: "suit"},
{source: "with:history2", target: "Salesforce..spPopulate_tblForecastCallHistory", type: "suit"},
{source: "Salesforce..tblForecastCallHistory", target: "with:history2", type: "suit"},
{source: "Salesforce..ForecastCall", target: "with:history2", type: "suit"},
{source: "Salesforce..vwFiscalWeeks", target: "with:history2", type: "suit"},
{source: "Salesforce..User", target: "with:history2", type: "suit"},
{source: "Salesforce..vwFiscalQuarters", target: "with:history2", type: "suit"},
{source: "#history2", target: "Salesforce..tblForecastCallHistory", type: "resolved"},
{source: "with:sn", target: "#history2", type: "resolved"},
{source: "#history1", target: "with:sn", type: "suit"},
{source: "with:history", target: "#history1", type: "suit"},
{source: "SalesforceReplica..ForecastCall__History", target: "with:history", type: "resolved"},
{source: "SalesforceReplica..TerritoryForecast__History", target: "with:history", type: "resolved"},
{source: "Salesforce..ForecastCall", target: "with:history", type: "resolved"},
{source: "SalesforceReplica..TerritoryForecast__History", target: "with:history", type: "resolved"}
];
var nodes = {};
// Compute the distinct nodes from the links.
links.forEach(function(link) {
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});
var width = 960,
height = 500;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(60)
.charge(-300)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
.data(["suit", "licensing", "resolved"])
.enter().append("marker")
.attr("id", function(d) { return d; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
var path = svg.append("g").selectAll("path")
.data(force.links())
.enter().append("path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
var circle = svg.append("g").selectAll("circle")
.data(force.nodes())
.enter().append("circle")
.attr("r", 6)
.call(force.drag);
var text = svg.append("g").selectAll("text")
.data(force.nodes())
.enter().append("text")
.attr("x", 8)
.attr("y", ".31em")
.text(function(d) { return d.name; });
// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
path.attr("d", linkArc);
circle.attr("transform", transform);
text.attr("transform", transform);
}
function linkArc(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment