You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ol...@apache.org on 2013/04/22 15:28:39 UTC
svn commit: r1470498 - in /archiva/trunk/archiva-modules/archiva-web:
archiva-web-common/src/main/resources/org/apache/archiva/i18n/
archiva-webapp/src/main/webapp/css/
archiva-webapp/src/main/webapp/js/archiva/
archiva-webapp/src/main/webapp/js/templa...
Author: olamy
Date: Mon Apr 22 13:28:38 2013
New Revision: 1470498
URL: http://svn.apache.org/r1470498
Log:
[MRM-1752] Graph visualization for dependencies
Submitted by Antoine ROUAZE
Modified:
archiva/trunk/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js
archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-web-common/src/main/resources/org/apache/archiva/i18n/default.properties Mon Apr 22 13:28:38 2013
@@ -371,6 +371,7 @@ artifact.detail.tab.header.metadatas=Met
artifact.detail.tab.header.mailing.list=Mailing Lists
artifact.detail.tab.header.info=Info
artifact.detail.tab.header.dependency.tree=Dependency Tree
+artifact.detail.tab.header.dependency.graph=Dependency Graph
artifact.detail.tab.header.used.by=Used By
artifact.detail.tab.header.file.content=Artifacts Content
artifact.detail.tab.header.file.download=Artifacts
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/archiva.css Mon Apr 22 13:28:38 2013
@@ -187,4 +187,39 @@ ol.linenums {
color: #333333;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 14px;
+}
+
+path.link {
+ fill: none;
+ stroke: #666;
+ stroke-width: 1.5px;
+}
+
+marker#licensing {
+ fill: green;
+}
+
+path.link.licensing {
+ stroke: green;
+}
+
+path.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 {
+ stroke: #fff;
+ stroke-width: 3px;
+ stroke-opacity: .8;
}
\ No newline at end of file
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/archiva.js Mon Apr 22 13:28:38 2013
@@ -82,6 +82,7 @@ $.ajax({
"sammy": "sammy.0.7.4",
"select2": "select2.min-3.2",
"jqueryFileTree": "jqueryFileTree-1.0.1",
+ "d3": "d3.min.3.1.5",
"redback": "redback/redback",
"redback.roles": "redback/roles",
"redback.user": "redback/user",
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/main.js Mon Apr 22 13:28:38 2013
@@ -550,6 +550,24 @@ function(jquery,ui,sammy,tmpl,i18n,jquer
checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependency-tree-content-a");
});
+ this.get('#artifact-dependency-graph/:groupId/:artifactId/:version', function(context) {
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependency-graph-content-a");
+ });
+
+ this.get('#artifact-dependency-graph~:repository/::groupId/:artifactId/:version', function(context) {
+
+ var repositoryId = this.params.repositoryId;
+ var groupId= this.params.groupId;
+ var artifactId= this.params.artifactId;
+ var version= this.params.version;
+ checkArtifactDetailContent(groupId,artifactId,version,repositoryId,"artifact-details-dependency-graph-content-a");
+ })
+
this.get('#artifact-mailing-list/:groupId/:artifactId/:version',function(context){
var repositoryId = this.params.repositoryId;
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/archiva/search.js Mon Apr 22 13:28:38 2013
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-define("archiva.search",["jquery","i18n","jquery.tmpl","select2","knockout","knockout.simpleGrid","jqueryFileTree","prettify"]
+define("archiva.search",["jquery","i18n","jquery.tmpl","select2","knockout","knockout.simpleGrid","jqueryFileTree","prettify", "d3"]
, function(jquery,i18n,jqueryTmpl,select2,ko,koSimpleGrid) {
//-----------------------------------------
@@ -466,6 +466,17 @@ define("archiva.search",["jquery","i18n"
return;
}
+ if ($(e.target).attr("data-target")=="#artifact-details-dependency-graph-content") {
+ var location ="#artifact-dependency-graph";
+ if (self.repositoryId) {
+ location+="~"+self.repositoryId;
+ }
+ location+="/"+self.groupId+"/"+self.artifactId+"/"+self.version;
+ displayGraph(treeDependencyUrl);
+ window.sammyArchivaApplication.setLocation(location);
+ return;
+ }
+
if ($(e.target).attr("data-target")=="#artifact-details-used-by-content") {
var location ="#artifact-used-by";
if (self.repositoryId){
@@ -530,7 +541,201 @@ define("archiva.search",["jquery","i18n"
});
}
+ displayGraphData=function(data) {
+
+ var w = 960,
+ h = 500,
+ r =6,
+ node,
+ link,
+ root;
+
+ var onmousedown = false;
+
+ var svg = d3.select("#artifact-details-dependency-graph-content")
+ .append("svg:svg")
+ .attr("width", w)
+ .attr("height", h)
+ .attr("pointer-events", "all")
+ .append('svg:g')
+ .call(d3.behavior.zoom().on("zoom", redraw))
+ .append('svg:g');
+
+ svg.append('svg:rect')
+ .attr('width', w)
+ .attr('height', h)
+ .attr('fill', 'rgba(255, 255, 255, 0)')
+
+ var force = d3.layout.force()
+ .on("tick", tick)
+ .linkDistance(100)
+ .charge(-300)
+ .size([w, h]);
+
+ var nodes = flatten(data[0]);
+ var links = d3.layout.tree().links(nodes);
+
+ force.nodes(nodes)
+ .links(links)
+ .start();
+
+ svg.append("svg:defs").selectAll("marker")
+ .data(["suit"])
+ .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 suit";
+ })
+ .attr("marker-end", function (d) {
+ return "url(#suit)";
+ });
+
+ var circle = svg.append("svg:g").selectAll("circle")
+ .data(force.nodes())
+ .enter().append("svg:circle")
+ .attr("r", r)
+ .on("click", click)
+ .on("mouseenter",onmouseover)
+ .on("mouseleave", function (d, i) {
+ setTimeout(function() {
+ $("#plot_overlay").remove();
+ }, 201)})
+ .call(force.drag);
+
+ force.drag()
+ .on("dragstart", function() {
+ $("#plot_overlay").remove();
+ onmousedown = true;
+ })
+ .on("dragend", function() {
+ $("#plot_overlay").remove();
+ onmousedown = false;
+ });
+
+ var text = svg.append("svg:g")
+ .selectAll("g")
+ .data(force.nodes())
+ .enter().append("svg:g");
+
+ text.append("svg:text")
+ .attr("x", 8)
+ .attr("y", ".31em")
+ .attr("class", "shadow")
+ .text(function (d) {
+ return d.artifact.artifactId;
+ });
+
+ text.append("svg:text")
+ .attr("x", 8)
+ .attr("y", ".31em")
+ .text(function (d) {
+ return d.artifact.artifactId;
+ });
+
+ function tick() {
+ path.attr("d", function (d) {
+ var dx = d.target.x - d.source.x,
+ dy = d.target.y - d.source.y,
+ 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 + ")";
+ });
+ }
+
+ function redraw() {
+ trans=d3.event.translate;
+ scale=d3.event.scale;
+ svg.attr("transform",
+ "translate(" + trans + ")"
+ + " scale(" + scale + ")");
+ }
+
+ function click(d) {
+ var location ="#artifact";
+ var selectedRepo=getSelectedBrowsingRepository();
+ if (selectedRepo){
+ location+="~"+selectedRepo;
+ }
+ location+="/"+d.artifact.groupId+"/"+d.artifact.artifactId+"/"+d.artifact.version;
+
+ window.sammyArchivaApplication.setLocation(location);
+ }
+
+ function onmouseover(d) {
+ if (!onmousedown) {
+ var x;
+ var y;
+ if (d3.event.pageX != undefined && d3.event.pageY != undefined) {
+ x = d3.event.pageX;
+ y = d3.event.pageY;
+ } else {
+ x = d3.event.clientX + document.body.scrollLeft +
+ document.documentElement.scrollLeft;
+ y = d3.event.clientY + document.body.scrollTop +
+ document.documentElement.scrollTop;
+ }
+ x += r;
+ y += r;
+ setTimeout(function() {
+ var bubble_code = "<div id='plot_overlay' class='popover fade in left' style='position:absolute; top:"
+ + y + "px; left:" + x + "px; z-index: 1; display: block;'>" +
+ "<h3 class='popover-title'>Details</h3>" +
+ "<div class='popover-content'><ul><li>ArtifactId: " +d.artifact.artifactId + "</li>"
+ + "<li>GroupId: " +d.artifact.groupId + "</li>"
+ + "<li>Version: " +d.artifact.version + "</li></ul></div>" +
+ "</div>";
+ $("body").append(bubble_code);
+ }, 200);
+ }
+ }
+
+ function flatten(root) {
+ var nodes = [], i = 0;
+
+ function recurse(node) {
+ if (node.childs) {
+ node.childs.forEach(recurse);
+ node.children = node.childs;
+ }
+ if (!node.id) node.id = ++i;
+
+ nodes.push(node);
+ }
+
+ recurse(root);
+ return nodes;
+ }
+ }
+
+ displayGraph=function(treeDependencyUrl) {
+ $.ajax(treeDependencyUrl, {
+ type: "GET",
+ dataType: 'json',
+ success: function(data) {
+ displayGraphData(data);
+ }
+ });
+ }
displayGroup=function(groupId){
var selectedRepo=getSelectedBrowsingRepository();
@@ -2101,4 +2306,4 @@ define("archiva.search",["jquery","i18n"
-});
\ No newline at end of file
+});
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html
URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html?rev=1470498&r1=1470497&r2=1470498&view=diff
==============================================================================
--- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html (original)
+++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/js/templates/archiva/search.html Mon Apr 22 13:28:38 2013
@@ -518,6 +518,10 @@
data-target="#artifact-details-dependency-tree-content" href="#artifact-details-dependency-tree-content">${$.i18n.prop('artifact.detail.tab.header.dependency.tree')}</a>
</li>
<li>
+ <a data-toggle="tab" id="artifact-details-dependency-graph-content-a"
+ data-target="#artifact-details-dependency-graph-content" href="#artifact-details-dependency-graph-content">${$.i18n.prop('artifact.detail.tab.header.dependency.graph')}</a>
+ </li>
+ <li>
<a data-toggle="tab" id="artifact-details-download-content-a" data-target="#artifact-details-download-content"
href="#artifact-details-download-content">${$.i18n.prop('artifact.detail.tab.header.file.download')}</a>
</li>
@@ -693,6 +697,8 @@
<div id="artifact-details-dependency-tree-content" class="tab-pane"></div>
+<div id="artifact-details-dependency-graph-content" class="tab-pane"></div>
+
<div id="artifact-details-files-content" class="tab-pane"></div>
<div id="artifact-details-download-content" class="tab-pane"></div>
@@ -968,4 +974,4 @@
<pre class="prettyprint linenums" id="artifact-content-text"></pre>
</div>
-</script>
\ No newline at end of file
+</script>