From a848cc0c1cbc3e384635b4f5401570222b0b0839 Mon Sep 17 00:00:00 2001 From: mokaddem Date: Wed, 29 Apr 2020 16:03:01 +0200 Subject: [PATCH] chg: [galaxy:fork_tree] Added version node - WiP --- app/Model/Galaxy.php | 25 ++++- app/View/Galaxies/fork_tree.ctp | 165 ++++++++++++++++++++++++------- app/View/GalaxyClusters/view.ctp | 1 + 3 files changed, 155 insertions(+), 36 deletions(-) diff --git a/app/Model/Galaxy.php b/app/Model/Galaxy.php index 3dc6d7a23..b6961c031 100644 --- a/app/Model/Galaxy.php +++ b/app/Model/Galaxy.php @@ -523,7 +523,30 @@ class Galaxy extends AppModel foreach ($clusters as $i => $cluster) { if (!empty($cluster['GalaxyCluster']['extended_from'])) { $parent = $cluster['GalaxyCluster']['extended_from']; - $lookup[$parent['GalaxyCluster']['id']]['children'][] = &$clusters[$i]; + $clusterVersion = $cluster['GalaxyCluster']['extends_version']; + $parentVersion = $lookup[$parent['GalaxyCluster']['id']]['GalaxyCluster']['version']; + if ($clusterVersion == $parentVersion) { + $lookup[$parent['GalaxyCluster']['id']]['children'][] = &$clusters[$i]; + } else { + // version differs, insert version node between child and parent + $lastVersionNode = array( + 'isVersion' => true, + 'isLast' => true, + 'version' => $parentVersion, + 'parentUuid' => $parent['GalaxyCluster']['uuid'], + 'children' => array() + ); + $versionNode = array( + 'isVersion' => true, + 'isLast' => false, + 'version' => $clusterVersion, + 'parentUuid' => $parent['GalaxyCluster']['uuid'], + 'children' => array(&$clusters[$i]) + ); + // $lookup[$parent['GalaxyCluster']['id']]['children'][] = &$clusters[$i]; + $lookup[$parent['GalaxyCluster']['id']]['children'][] = $versionNode; + $lookup[$parent['GalaxyCluster']['id']]['children'][] = $lastVersionNode; + } } else { $tree[] = &$clusters[$i]; } diff --git a/app/View/Galaxies/fork_tree.ctp b/app/View/Galaxies/fork_tree.ctp index 187e63e29..4b13fb2b5 100644 --- a/app/View/Galaxies/fork_tree.ctp +++ b/app/View/Galaxies/fork_tree.ctp @@ -64,7 +64,7 @@ function buildTree() { nodes.forEach(function(d) { d.y = d.depth * ratioFactor; }); var node = svg.selectAll("g.node") - .data(nodes, function(d) { return d.isRoot ? 'root' : d.GalaxyCluster.id; }); + .data(nodes, function(d) { return getId(d) }); var nodeEnter = node.enter().append("g") .attr("class", "node") @@ -73,37 +73,10 @@ function buildTree() { .on("dblclick", nodeDbclick); var gEnter = nodeEnter.append('g'); - gEnter.append("circle") - .attr("r", function(d) { return d.isRoot ? 5 : 15 }) - .style("fill", function(d) { return d.isRoot ? "lightsteelblue" : "#fff"; }) - .style("stroke", "steelblue") - .style("stroke-width", "2px") - gEnter.append("image") - .attr("xlink:href", function(d) { - if (d.isRoot) { - return transparentImg; - } else { - return d.GalaxyCluster.default ? '/img/orgs/MISP.png' : '/img/orgs/' + d.GalaxyCluster.orgc_id + '.png'; - } - }) - .attr("x", "-12px") - .attr("y", "-12px") - .attr("width", "24px") - .attr("height", "24px") - .on("error", function() { // avoid broken link image - d3.select(this).attr("xlink:href", transparentImg); - }); - - nodeEnter.append("text") - .attr("dy", function(d) { return d.children ? "2.5em" : ".35em"; }) - .attr("x", function(d) { return d.children ? "0em" : "1.5em"; }) - .attr("text-anchor", function(d) { return d.children ? (d.isRoot ? "start" : "middle") : "start"; }) - .text(function(d) { return d.isRoot ? d.Galaxy.name + ' galaxy' : d.GalaxyCluster.value; }) - .style("fill-opacity", 1) - .style("font-weight", function(d) { return d.isRoot ? 'bold' : ''}); + drawEntities(gEnter); var link = svg.selectAll("path.link") - .data(links, function(d) { return d.target.GalaxyCluster.id; }); + .data(links, function(d) { return getId(d.target); }); link.enter().insert("path", "g") .attr("class", "link") @@ -118,6 +91,124 @@ function buildTree() { // .y(function(d) { return d.x; })); } +function drawEntities(gEnter) { + gEnter.filter(function(d) { return d.isRoot }).call(drawGalaxy); + gEnter.filter(function(d) { return d.isVersion === true }).call(drawVersion); + gEnter.filter(function(d) { return !d.isRoot && d.isVersion !== true }).call(drawCluster); +} + +function drawCluster(gEnter) { + gEnter.append("circle") + .attr("r", 15) + .style("fill", "#fff") + .style("stroke", "steelblue") + .style("stroke-width", "2px") + gEnter.append("image") + .attr("xlink:href", function(d) { + return d.GalaxyCluster.default ? '/img/orgs/MISP.png' : '/img/orgs/' + d.GalaxyCluster.orgc_id + '.png'; + }) + .attr("x", "-12px") + .attr("y", "-12px") + .attr("width", "24px") + .attr("height", "24px") + .on("error", function() { // avoid broken link image + d3.select(this).attr("xlink:href", transparentImg); + }); + + drawLabel(gEnter, { + text: function(d) { return getTextFromNode(d, 'cluster'); }, + x: function(d) { return d.children ? "0em" : "1.5em"; }, + dy: function(d) { return d.children ? "2.5em" : ".35em"; }, + textAnchor: function(d) { return d.children ? "middle" : "start"; }, + fontWeight: '' + }); +} + +function drawGalaxy(gEnter) { + gEnter.append("circle") + .attr("r", 5) + .style("fill", "lightsteelblue") + .style("stroke", "steelblue") + .style("stroke-width", "2px"); + + drawLabel(gEnter, { + text: function(d) { return getTextFromNode(d, 'galaxy') }, + x: function(d) { return d.children ? "0em" : "1.5em"; }, + dy: function(d) { return d.children ? "2em" : ".35em"; }, + textAnchor: "start", + fontWeight: 'bold' + }); +} +function drawVersion(gEnter) { + gEnter.append("rect") + .attr("y", -12) + .attr("width", function(d) { return getTextWidth(getTextFromNode(d, 'version')) + 5 + 'px'; }) + .attr("height", 24) + .style("fill", function(d) { return d.isLast ? "cornflowerblue" : "darkgrey" }) + .style("stroke", function(d) { return d.isLast ? "steelblue" : "gray" }) + .style("stroke-width", "2px") + .append("title") + .text(""); + drawLabel(gEnter, { + text: function(d) { return getTextFromNode(d, 'version') }, + x: "7px", + dy: "4px", + textAnchor: "start", + fontWeight: "bold" + }); +} + +function drawLabel(gEnter, options) { + var defaultOptions = { + text: '', + x: '', + dx: '', + y: '', + dy: '', + textAnchor: 'start', + fontWeight: '' + } + options = $.extend(defaultOptions, options); + gEnter.append("text") + .attr("dy", options.dy) + .attr("dx", options.dx) + .attr("x", options.x) + .attr("y", options.y) + .attr("text-anchor", options.textAnchor) + .attr("font-weight", options.fontWeight) + .style("fill-opacity", 1) + .text(options.text); +} + +function getTextFromNode(d, nodeType) { + if (nodeType == 'cluster') { + return d.GalaxyCluster.value; + } else if (nodeType == 'galaxy') { + return d.Galaxy.name + ' galaxy'; + } else if (nodeType == 'version') { + return d.version; + } else { + return ''; + } +} + +function getTextWidth(text) { + return text.length * parseFloat(getComputedStyle(document.documentElement).fontSize); +} + +function getId(d) { + var id = ""; + if (d.isRoot) { + id = 'root' + } else if (d.isVersion) { + id = 'version-' + d.parentUuid + '-' + d.version; + } else { + id = d.GalaxyCluster.id; + } + return id; +} + + function nodeDbclick(d) { var url, clickedId if (d.isRoot) { @@ -133,11 +224,15 @@ function nodeDbclick(d) { function nodeHover(d) { var $d3Element = $(this); - $d3Element.tooltip({ - html: true, - container: 'body', - title: generate_tooltip(d) - }).tooltip('show') + var hasTooltip = $d3Element.data('tooltip') !== undefined + window.ddd = $d3Element; + if (!d.isRoot && d.isVersion !== true && !hasTooltip) { + $d3Element.tooltip({ + html: true, + container: 'body', + title: generate_tooltip(d) + }).tooltip('show') + } } function generate_tooltip(d) { diff --git a/app/View/GalaxyClusters/view.ctp b/app/View/GalaxyClusters/view.ctp index 784759161..6231c2533 100755 --- a/app/View/GalaxyClusters/view.ctp +++ b/app/View/GalaxyClusters/view.ctp @@ -35,6 +35,7 @@ $table_data[] = array('key' => __('Name'), 'value' => $cluster['GalaxyCluster']['value']); $table_data[] = array('key' => __('Parent Galaxy'), 'value' => $cluster['Galaxy']['name'] ? $cluster['Galaxy']['name'] : $cluster['Galaxy']['type']); $table_data[] = array('key' => __('Description'), 'value' => $cluster['GalaxyCluster']['description']); + $table_data[] = array('key' => __('Version'), 'value' => $cluster['GalaxyCluster']['version']); $table_data[] = array('key' => __('UUID'), 'value' => $cluster['GalaxyCluster']['uuid']); $table_data[] = array('key' => __('Collection UUID'), 'value' => $cluster['GalaxyCluster']['collection_uuid']); $table_data[] = array('key' => __('Source'), 'value' => $cluster['GalaxyCluster']['source']);