12033: Fix tests.
[arvados.git] / apps / workbench / public / graph-example.html
1 <!-- Copyright (C) The Arvados Authors. All rights reserved.
2
3 SPDX-License-Identifier: AGPL-3.0 -->
4
5 <!DOCTYPE html>
6 <!-- from http://bl.ocks.org/1153292 -->
7 <html>
8   <head>
9     <meta http-equiv="Content-type" content="text/html; charset=utf-8">
10     <title>Object graph example</title>
11     <script src="d3.v3.min.js"></script>
12     <style type="text/css">
13
14 path.link {
15   fill: none;
16   stroke: #666;
17   stroke-width: 1.5px;
18 }
19
20 marker#can_read {
21   fill: green;
22 }
23
24 path.link.can_read {
25   stroke: green;
26   stroke-dasharray: 0,4 1;
27 }
28
29 path.link.can_write {
30   stroke: green;
31 }
32
33 path.link.member_of {
34   stroke: blue;
35   stroke-dasharray: 0,4 1;
36 }
37
38 path.link.created {
39   stroke: red;
40 }
41
42 circle {
43   fill: #ccc;
44   stroke: #333;
45   stroke-width: 1.5px;
46 }
47
48 edgetext {
49   font: 12px sans-serif;
50   pointer-events: none;
51     text-align: center;
52 }
53
54 text {
55   font: 12px sans-serif;
56   pointer-events: none;
57 }
58
59 text.shadow {
60   stroke: #fff;
61   stroke-width: 3px;
62   stroke-opacity: .8;
63 }
64
65     </style>
66   </head>
67   <body>
68     <script type="text/javascript">
69
70 var links = [
71   {source: "user: customer", target: "project: customer_project", type: "can_read"},
72   {source: "user: import robot", target: "project: customer_project", type: "can_read"},
73   {source: "user: pipeline robot", target: "project: customer_project", type: "can_read"},
74   {source: "user: uploader", target: "collection: w3anr2hk2wgfpuo", type: "created"},
75   {source: "user: uploader", target: "project: customer_project", type: "created"},
76   {source: "collection: w3anr2hk2wgfpuo", target: "project: customer_project", type: "member_of"}
77 ];
78
79 var nodes = {};
80
81 // Compute the distinct nodes from the links.
82 links.forEach(function(link) {
83   link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
84   link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
85 });
86
87 var w = 960,
88     h = 500;
89
90 var force = d3.layout.force()
91     .nodes(d3.values(nodes))
92     .links(links)
93     .size([w, h])
94     .linkDistance(250)
95     .charge(-300)
96     .on("tick", tick)
97     .start();
98
99 var svg = d3.select("body").append("svg:svg")
100     .attr("width", w)
101     .attr("height", h);
102
103 // Per-type markers, as they don't inherit styles.
104 svg.append("svg:defs").selectAll("marker")
105     .data(["created", "member_of", "can_read", "can_write"])
106   .enter().append("svg:marker")
107     .attr("id", String)
108     .attr("viewBox", "0 -5 10 10")
109     .attr("refX", 15)
110     .attr("refY", -1.5)
111     .attr("markerWidth", 6)
112     .attr("markerHeight", 6)
113     .attr("orient", "auto")
114   .append("svg:path")
115     .attr("d", "M0,-5L10,0L0,5");
116
117 var path = svg.append("svg:g").selectAll("path")
118     .data(force.links())
119   .enter().append("svg:path")
120     .attr("class", function(d) { return "link " + d.type; })
121     .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
122
123 var circle = svg.append("svg:g").selectAll("circle")
124     .data(force.nodes())
125   .enter().append("svg:circle")
126     .attr("r", 6)
127     .call(force.drag);
128
129 var text = svg.append("svg:g").selectAll("g")
130     .data(force.nodes())
131   .enter().append("svg:g");
132
133 // A copy of the text with a thick white stroke for legibility.
134 text.append("svg:text")
135     .attr("x", 8)
136     .attr("y", ".31em")
137     .attr("class", "shadow")
138     .text(function(d) { return d.name; });
139
140 text.append("svg:text")
141     .attr("x", 8)
142     .attr("y", ".31em")
143     .text(function(d) { return d.name; });
144
145 var edgetext = svg.append("svg:g").selectAll("g")
146     .data(force.links())
147     .enter().append("svg:g");
148
149 edgetext
150     .append("svg:text")
151     .attr("x",0)
152     .attr("y","-0.2em")
153     .text(function(d) { return d.type; });
154
155 // Use elliptical arc path segments to doubly-encode directionality.
156 function tick() {
157   path.attr("d", function(d) {
158     var dx = d.target.x - d.source.x,
159         dy = d.target.y - d.source.y,
160         // dr = Math.sqrt(dx * dx + dy * dy);
161         dr = 0;
162     return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
163   });
164
165   circle.attr("transform", function(d) {
166     return "translate(" + d.x + "," + d.y + ")";
167   });
168
169   text.attr("transform", function(d) {
170     return "translate(" + d.x + "," + d.y + ")";
171   });
172
173   edgetext.attr("transform", function(d) {
174       return "translate(" +
175           (d.source.x + d.target.x)/2 + "," +
176           (d.source.y + d.target.y)/2 +
177           ")rotate(" +
178           (Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) * 180 / Math.PI) +
179           ")";
180   });
181 }
182
183     </script>
184   </body>
185 </html>