From e263a534dda7f2f7bdf0dd03f190ee4c9588a321 Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Thu, 31 Jan 2013 09:07:21 -0800 Subject: [PATCH] basic d3 graph at /collections --- app/controllers/collections_controller.rb | 4 + app/controllers/links_controller.rb | 2 +- app/helpers/collections_helper.rb | 5 + app/views/collections/index.html.erb | 171 ++++++++++++++++++++++ app/views/layouts/application.html.erb | 4 + 5 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 app/views/collections/index.html.erb diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 3d8f9909ea..7180e85733 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -1,2 +1,6 @@ class CollectionsController < ApplicationController + def index + @links = Link.where(head_kind: 'orvos#collection') | + Link.where(tail_kind: 'orvos#collection') + end end diff --git a/app/controllers/links_controller.rb b/app/controllers/links_controller.rb index b7916d84d2..78529c149a 100644 --- a/app/controllers/links_controller.rb +++ b/app/controllers/links_controller.rb @@ -1,2 +1,2 @@ -class MetadataController < ApplicationController +class LinksController < ApplicationController end diff --git a/app/helpers/collections_helper.rb b/app/helpers/collections_helper.rb index 30179854a2..b2eee48ea6 100644 --- a/app/helpers/collections_helper.rb +++ b/app/helpers/collections_helper.rb @@ -1,2 +1,7 @@ module CollectionsHelper + def d3ify_links(links) + links.collect do |x| + {source: x.tail_uuid, target: x.head_uuid, type: x.name} + end + end end diff --git a/app/views/collections/index.html.erb b/app/views/collections/index.html.erb new file mode 100644 index 0000000000..677face1f8 --- /dev/null +++ b/app/views/collections/index.html.erb @@ -0,0 +1,171 @@ +<% content_for :head do %> +<%= javascript_include_tag '/d3.v3.min.js' %> + + +<% end %> + +<% content_for :js do %> + +jQuery(function($){ + +var links = <%= raw d3ify_links(@links).to_json %>; + +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 w = 960, + h = 600; + +var force = d3.layout.force() + .nodes(d3.values(nodes)) + .links(links) + .size([w, h]) + .linkDistance(250) + .charge(-300) + .on("tick", tick) + .start(); + +var svg = d3.select("body").append("svg:svg") + .attr("width", w) + .attr("height", h); + +// Per-type markers, as they don't inherit styles. +svg.append("svg:defs").selectAll("marker") + .data(["created", "member_of", "can_read", "can_write"]) + .enter().append("svg:marker") + .attr("id", String) + .attr("viewBox", "0 -5 10 10") + .attr("refX", 15) + .attr("refY", -1.5) + .attr("markerWidth", 6) + .attr("markerHeight", 6) + .attr("orient", "auto") + .append("svg:path") + .attr("d", "M0,-5L10,0L0,5"); + +var path = svg.append("svg:g").selectAll("path") + .data(force.links()) + .enter().append("svg:path") + .attr("class", function(d) { return "link " + d.type; }) + .attr("marker-end", function(d) { return "url(#" + d.type + ")"; }); + +var circle = svg.append("svg:g").selectAll("circle") + .data(force.nodes()) + .enter().append("svg:circle") + .attr("r", 6) + .call(force.drag); + +var text = svg.append("svg:g").selectAll("g") + .data(force.nodes()) + .enter().append("svg:g"); + +// A copy of the text with a thick white stroke for legibility. +text.append("svg:text") + .attr("x", 8) + .attr("y", ".31em") + .attr("class", "shadow") + .text(function(d) { return d.name; }); + +text.append("svg:text") + .attr("x", 8) + .attr("y", ".31em") + .text(function(d) { return d.name; }); + +var edgetext = svg.append("svg:g").selectAll("g") + .data(force.links()) + .enter().append("svg:g"); + +edgetext + .append("svg:text") + .attr("x",0) + .attr("y","-0.2em") + .text(function(d) { return d.type; }); + +// Use elliptical arc path segments to doubly-encode directionality. +function tick() { + path.attr("d", function(d) { + var dx = d.target.x - d.source.x, + dy = d.target.y - d.source.y, + // dr = Math.sqrt(dx * dx + dy * dy); + dr = 0; + return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; + }); + + circle.attr("transform", function(d) { + return "translate(" + d.x + "," + d.y + ")"; + }); + + text.attr("transform", function(d) { + return "translate(" + d.x + "," + d.y + ")"; + }); + + edgetext.attr("transform", function(d) { + return "translate(" + + (d.source.x + d.target.x)/2 + "," + + (d.source.y + d.target.y)/2 + + ")rotate(" + + (Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) * 180 / Math.PI) + + ")"; + }); +} + +})(jQuery); +<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d8b4066d5b..2b27522adc 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,6 +5,10 @@ <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> + <%= yield :head %> + <%= javascript_tag do %> + <%= yield :js %> + <% end %> -- 2.30.2