浏览代码

still needs css styling but dendograms!

Chris Mague 6 年之前
父节点
当前提交
48e384b3d1
共有 4 个文件被更改,包括 78 次插入15 次删除
  1. 15 14
      lib/neoinfra/graph.rb
  2. 2 1
      web/controllers/graph.rb
  3. 10 0
      web/controllers/views.rb
  4. 51 0
      web/views/graphview.erb

+ 15 - 14
lib/neoinfra/graph.rb

@@ -5,6 +5,8 @@ require 'vpc'
 require 'accounts'
 require 'fog-aws'
 require 'neo4j'
+require 'csv'
+require 'sinatra'
 
 # NeoInfra Account information
 module NeoInfra
@@ -15,24 +17,23 @@ module NeoInfra
       neo4j_url = "http://#{@cfg.neo4j[:host]}:#{@cfg.neo4j[:port]}"
       Neo4j::Session.open(:server_db, neo4j_url)
     end
+
     def graph_vpcs
-      nodes = []
-      rels = []
-      i = 0
-      @cfg = NeoInfra::Config.new
-      @cfg.accounts.each do |account|
-        nodes << {title: account[:name], label: 'account'}
-        i +=1
-        Vpc.where(default: "false").each do |vpc|
-          if vpc.owned.name == account[:name]
-            source = i
-            nodes << {title: vpc.name, label: 'vpc'}
-            i +=1
-            rels << {source: source, target: i}
+      csv_string = CSV.generate(force_quotes: false ) do |csv|
+        csv << ['id,value']
+        csv << ['aws,']
+        @cfg = NeoInfra::Config.new
+        @cfg.accounts.each do |account|
+          csv << ["aws.#{account[:name]},"]
+          Vpc.where(default: "false").each do |vpc|
+            if vpc.owned.name == account[:name]
+              csv << ["aws.#{account[:name]}.#{vpc.name},1"]
+            end
           end
         end
       end
-      return {nodes: nodes, links: rels}
+      return csv_string.gsub('"', '')
     end
+
   end
 end

+ 2 - 1
web/controllers/graph.rb

@@ -16,7 +16,8 @@ class Graph < Sinatra::Base
   set :views, File.join(File.dirname(__FILE__), '..', '/views')
 
   get '/vpcs' do
+    headers('Content-Type' => "text/csv")
     g = NeoInfra::Graph.new
-    g.graph_vpcs.to_json
+    g.graph_vpcs
   end
 end

+ 10 - 0
web/controllers/views.rb

@@ -69,4 +69,14 @@ class Views < Sinatra::Base
       end
     end
   end
+
+  get '/graph' do
+    respond_to do |wants|
+      wants.html do
+        erb :graphview,
+            layout: :base_layout,
+            locals: { graphview: "foo" }
+      end
+    end
+  end
 end

+ 51 - 0
web/views/graphview.erb

@@ -0,0 +1,51 @@
+<center><svg width="900" height="600"></svg></center>
+<script src="http://d3js.org/d3.v4.min.js"></script>
+<script>
+
+var svg = d3.select("svg"),
+    width = +svg.attr("width"),
+    height = +svg.attr("height"),
+    g = svg.append("g").attr("transform", "translate(40,0)");
+
+var tree = d3.cluster()
+    .size([height, width - 160]);
+
+var stratify = d3.stratify()
+    .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });
+
+d3.csv("/graph/vpcs", function(error, data) {
+  if (error) throw error;
+
+  var root = stratify(data)
+      .sort(function(a, b) { return (a.height - b.height) || a.id.localeCompare(b.id); });
+
+  tree(root);
+
+  var link = g.selectAll(".link")
+      .data(root.descendants().slice(1))
+    .enter().append("path")
+      .attr("class", "link")
+      .attr("d", function(d) {
+        return "M" + d.y + "," + d.x
+            + "C" + (d.parent.y + 100) + "," + d.x
+            + " " + (d.parent.y + 100) + "," + d.parent.x
+            + " " + d.parent.y + "," + d.parent.x;
+      });
+
+  var node = g.selectAll(".node")
+      .data(root.descendants())
+    .enter().append("g")
+      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
+      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
+
+  node.append("circle")
+      .attr("r", 2.5);
+
+  node.append("text")
+      .attr("dy", 3)
+      .attr("x", function(d) { return d.children ? -8 : 8; })
+      .style("text-anchor", function(d) { return d.children ? "end" : "start"; })
+      .text(function(d) { return d.id.substring(d.id.lastIndexOf(".") + 1); });
+});
+
+</script>