Repository: incubator-atlas Updated Branches: refs/heads/master 0e81ceb4a -> c4eebe0ed
ATLAS-406 Resizing lineage window â should be an anchor on a corner â like ppt for graphic (sanjayp via shwethags) Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/c4eebe0e Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/c4eebe0e Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/c4eebe0e Branch: refs/heads/master Commit: c4eebe0ed4a8489d92a9f75edef4819dc3fcde32 Parents: 0e81ceb Author: Shwetha GS <[email protected]> Authored: Wed Jan 13 20:07:34 2016 +0530 Committer: Shwetha GS <[email protected]> Committed: Wed Jan 13 20:07:34 2016 +0530 ---------------------------------------------------------------------- dashboard/bower.json | 47 +- dashboard/gruntfile.js | 4 +- dashboard/public/css/common.css | 25 +- dashboard/public/css/lineage.css | 6 +- dashboard/public/index.html | 2 + .../public/modules/lineage/lineageController.js | 656 ------------------- .../modules/lineage/lineage_ioController.js | 59 +- .../modules/lineage/views/lineage_io.html | 2 + release-log.txt | 1 + 9 files changed, 104 insertions(+), 698 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/bower.json ---------------------------------------------------------------------- diff --git a/dashboard/bower.json b/dashboard/bower.json index 2ffdc90..18ce5da 100644 --- a/dashboard/bower.json +++ b/dashboard/bower.json @@ -1,25 +1,26 @@ { - "name": "atlas-metadata", - "description": "Apache Atlas", - "version": "1.0.0-SNAPSHOT", - "devDependencies": { - "angular": "~1.2.15", - "angular-resource": "~1.2.15", - "angular-cookies": "~1.2.15", - "angular-route": "~1.2.15", - "angular-sanitize": "~1.2.15", - "bootstrap": "~3.1.1", - "angular-bootstrap": "~0.12.0", - "angular-ui-router": "~0.2.13", - "d3": "~3.5.3", - "d3-tip": "~0.6.6", - "lodash": "~3.0.0", - "angular-ui-utils": "~0.1.1", - "font-awesome": "~4.2.0", - "closure-compiler": "https://dl.google.com/closure-compiler/compiler-20140814.zip", - "ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip" - }, - "resolutions": { - "d3": "~3.5.3" - } + "name": "atlas-metadata", + "description": "Apache Atlas", + "version": "1.0.0-SNAPSHOT", + "devDependencies": { + "angular": "~1.2.15", + "angular-resource": "~1.2.15", + "angular-cookies": "~1.2.15", + "angular-route": "~1.2.15", + "angular-sanitize": "~1.2.15", + "bootstrap": "~3.1.1", + "angular-bootstrap": "~0.12.0", + "angular-ui-router": "~0.2.13", + "d3": "~3.5.3", + "d3-tip": "~0.6.6", + "lodash": "~3.0.0", + "angular-ui-utils": "~0.1.1", + "font-awesome": "~4.2.0", + "closure-compiler": "https://dl.google.com/closure-compiler/compiler-20140814.zip", + "ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip", + "jquery-ui": "1.10.4" + }, + "resolutions": { + "d3": "~3.5.3" + } } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/gruntfile.js ---------------------------------------------------------------------- diff --git a/dashboard/gruntfile.js b/dashboard/gruntfile.js index 52ae412..ef91408 100644 --- a/dashboard/gruntfile.js +++ b/dashboard/gruntfile.js @@ -154,9 +154,7 @@ module.exports = function(grunt) { 'hosts': [{ 'hostnames': ['*'], 'routes': { - '/': distPath, - //'/api': 'http://162.249.6.39:21000/api' - '/api': 'http://ec2-52-25-142-7.us-west-2.compute.amazonaws.com:21000/api' + '/': distPath } }] } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/css/common.css ---------------------------------------------------------------------- diff --git a/dashboard/public/css/common.css b/dashboard/public/css/common.css index e8d9345..853c664 100644 --- a/dashboard/public/css/common.css +++ b/dashboard/public/css/common.css @@ -114,14 +114,14 @@ header ul.menuBar li a{ header ul.menuBar li a>i { margin-right: 3px; font-size: 12px; -} +} header ul.menuBar li a:hover{ color: #fff; background: transparent; -} +} header ul.menuBar li a:focus{ background: transparent; -} +} header ul.menuBar li.active a{ color: #333333; background-color: #ffffff; @@ -319,11 +319,11 @@ Tags on Home Page design -o-text-overflow: ellipsis; white-space: nowrap; text-transform: capitalize; - float: left; - + float: left; + background: lightblue !important; color: black !important; - margin: 4px !important; + margin: 4px !important; padding-left: 7px !important; padding-right: 7px !important; } @@ -335,7 +335,7 @@ Tags on Home Page design text-overflow: ellipsis; -o-text-overflow: ellipsis; white-space: nowrap; - text-transform: capitalize; + text-transform: capitalize; } .searchResultCount { max-width: 500px; @@ -343,7 +343,7 @@ Tags on Home Page design overflow: hidden; text-overflow: ellipsis; -o-text-overflow: ellipsis; - text-transform: capitalize; + text-transform: capitalize; } .maxwidth125px { @@ -361,11 +361,18 @@ Tags on Home Page design .tagAlign{ text-align: center; -} +} .h160 { height: 160px !important; } .tag-attr{ font-weight:bold; +} +.zoom-buttons{ + width:63px !important; +} +.graph{ + overflow: hidden!important; + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/css/lineage.css ---------------------------------------------------------------------- diff --git a/dashboard/public/css/lineage.css b/dashboard/public/css/lineage.css index 180bebf..36f2423 100644 --- a/dashboard/public/css/lineage.css +++ b/dashboard/public/css/lineage.css @@ -69,7 +69,7 @@ div.lineage { .lineage-viz { margin: 0 auto; - overflow: auto; + overflow: hidden; /*border: 1px solid #ddd; border-top: none;*/ @@ -78,6 +78,10 @@ div.lineage { margin: 5px; border-radius: 2px } + +.title-font{ + font-size:12px!important; +} /*.images {*/ /*background-image: url("../img/process.png");*/ /*}â*/ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/index.html ---------------------------------------------------------------------- diff --git a/dashboard/public/index.html b/dashboard/public/index.html index 2d0993f..cfd4e6d 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -36,6 +36,7 @@ <link rel="stylesheet" href="/css/lineage.css"> <link rel="stylesheet" href="/css/tags.css"> <link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.css"> + <link rel="stylesheet" href="/lib/jquery-ui/themes/ui-lightness/jquery-ui.css"> </head> @@ -68,6 +69,7 @@ <script src="/lib/lodash/lodash.js"></script> <script src="/lib/d3/d3.js"></script> <script src="/lib/d3-tip/index.js"></script> +<script src="/lib/jquery-ui/ui/jquery-ui.js"></script> <script src="/js/app.min.js"></script> </body> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/modules/lineage/lineageController.js ---------------------------------------------------------------------- diff --git a/dashboard/public/modules/lineage/lineageController.js b/dashboard/public/modules/lineage/lineageController.js deleted file mode 100644 index 2d88147..0000000 --- a/dashboard/public/modules/lineage/lineageController.js +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * 'License'); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -angular.module('dgc.lineage').controller('LineageController', ['$element', '$scope', '$state', '$stateParams', 'lodash', 'LineageResource', 'd3', 'DetailsResource', '$q', - function($element, $scope, $state, $stateParams, _, LineageResource, d3, DetailsResource, $q) { - var guidsList = []; - - function getLineageData(tableData, callRender) { - LineageResource.get({ - tableName: tableData.tableName, - type: tableData.type - }, function lineageSuccess(response) { - if (!_.isEmpty(response.results.values.vertices)) { - var allGuids = loadProcess(response.results.values.edges, response.results.values.vertices); - allGuids.then(function(res) { - guidsList = res; - $scope.lineageData = transformData(response.results); - if (callRender) { - render(); - } - }) - .on("dblclick", function(d) { - $state.go("details", { - id: d.guid - }); - }); - }else{ - $scope.requested = false; - } - }); - } - - function loadProcess(edges, vertices) { - - var urlCalls = []; - var deferred = $q.defer(); - for (var guid in edges) { - if (!vertices.hasOwnProperty(guid)) { - urlCalls.push(DetailsResource.get({ - id: guid - }).$promise); - } - - } - $q.all(urlCalls) - .then(function(results) { - deferred.resolve(results); - }); - return deferred.promise; - } - - $scope.type = $element.parent().attr('data-table-type'); - $scope.requested = false; - $scope.height = $element[0].offsetHeight; - $scope.width = $element[0].offsetWidth; - - function render() { - renderGraph($scope.lineageData, { - eleObj : $element, - element: $element[0], - height: $scope.height, - width: $scope.width - }); - $scope.rendered = true; - } - - $scope.onReset = function(){ - renderGraph($scope.lineageData, { - eleObj : $element, - element: $element[0], - height: $scope.height, - width: $scope.width - }); - }; - - $scope.$on('render-lineage', function(event, lineageData) { - if (lineageData.type === $scope.type) { - if (!$scope.lineageData) { - if (!$scope.requested) { - getLineageData(lineageData, true); - $scope.requested = true; - } - } else { - render(); - } - } - }); - - function transformData(metaData) { - var edges = metaData.values.edges, - vertices = metaData.values.vertices, - nodes = {}; - - function getNode(guid) { - var name, type, tip; - if (vertices.hasOwnProperty(guid)) { - name = vertices[guid].values.name; - type = vertices[guid].values.vertexId.values.typeName; - } else { - var loadProcess = getLoadProcessTypes(guid); - if (typeof loadProcess !== "undefined") { - name = loadProcess.name; - type = loadProcess.typeName; - tip = loadProcess.tip; - } else { - name = 'Load Process'; - type = 'Load Process'; - } - } - var vertex = { - guid: guid, - name: name, - type: type, - tip: tip - }; - if (!nodes.hasOwnProperty(guid)) { - nodes[guid] = vertex; - } - return nodes[guid]; - } - - function getLoadProcessTypes(guid) { - var procesRes = []; - angular.forEach(guidsList, function(value) { - if (value.id.id === guid) { - procesRes.name = value.values.name; - procesRes.typeName = value.typeName; - procesRes.tip = value.values.queryText; - } - }); - return procesRes; - } - - function attachParent(edge, node) { - edge.forEach(function eachPoint(childGuid) { - var childNode = getNode(childGuid); - node.children = node.children || []; - node.children.push(childNode); - childNode.parent = node.guid; - }); - } - - /* Loop through all edges and attach them to correct parent */ - for (var guid in edges) { - var edge = edges[guid], - node = getNode(guid); - - /* Attach parent to each endpoint of edge */ - attachParent(edge, node); - } - - /* Return the first node w/o parent, this is root node*/ - return _.find(nodes, function(node) { - return !node.hasOwnProperty('parent'); - }); - } - - function renderGraph(data, container) { - // ************** Generate the tree diagram ***************** - var element = d3.select(container.element), - widthg = Math.max(container.width, 960), - heightg = Math.max(container.height, 500), - - totalNodes = 0, - maxLabelLength = 0, - selectedNode = null, - draggingNode = null, - dragListener = null, - dragStarted = true, - domNode = null, - multiParents = null, - nodes = null, - tooltip = null, - node = null, - i = 0, - duration = 750, - root, - depthwidth = 10; - - - var viewerWidth = widthg - 15, - viewerHeight = heightg; - - var tree = d3.layout.tree().nodeSize([100, 200]); - /*.size([viewerHeight, viewerWidth]);*/ - - container.eleObj.find(".graph").html(''); - container.eleObj.find("svg").remove(); - - // define a d3 diagonal projection for use by the node paths later on. - var diagonal = d3.svg.diagonal() - .projection(function(d) { - return [d.y, d.x]; - }); - - // A recursive helper function for performing some setup by walking through all nodes - - function visit(parent, visitFn, childrenFn) { - if (!parent) return; - - visitFn(parent); - - var children = childrenFn(parent); - if (children) { - var count = children.length; - for (var i = 0; i < count; i++) { - visit(children[i], visitFn, childrenFn); - } - } - } - - // Call visit function to establish maxLabelLength - visit(data, function(d) { - totalNodes++; - maxLabelLength = Math.max(d.name.length, maxLabelLength); - - }, function(d) { - return d.children && d.children.length > 0 ? d.children : null; - }); - - - // sort the tree according to the node names - - function sortTree() { - tree.sort(function(a, b) { - return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; - }); - } - // Sort the tree initially incase the JSON isn't in a sorted order. - sortTree(); - - // Define the zoom function for the zoomable tree - - function zoom() { - svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); - } - - - // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents - var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); - /* Initialize tooltip */ - tooltip = d3.tip() - .attr('class', 'd3-tip') - .html(function(d) { - return '<pre class="alert alert-success">' + d.name + '</pre>'; - }); - - // define the baseSvg, attaching a class for styling and the zoomListener - var baseSvg = element.append('svg') - .attr("width", viewerWidth) - .attr("height", viewerHeight) - .attr("class", "overlay") - .call(zoomListener) - .call(tooltip); - - - // Define the drag listeners for drag/drop behaviour of nodes. - dragListener = d3.behavior.drag() - .on("dragstart", function(d) { - if (d ===root) { - return; - } - dragStarted = true; - nodes = tree.nodes(d); - d3.event.sourceEvent.stopPropagation(); - // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); - }) - .on("dragend", function(d) { - if (d ===root) { - return; - } - domNode = this; - if (selectedNode) { - // now remove the element from the parent, and insert it into the new elements children - var index = draggingNode.parent.children.indexOf(draggingNode); - if (index > -1) { - draggingNode.parent.children.splice(index, 1); - } - if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') { - if (typeof selectedNode.children !== 'undefined') { - selectedNode.children.push(draggingNode); - } else { - selectedNode._children.push(draggingNode); - } - } else { - selectedNode.children = []; - selectedNode.children.push(draggingNode); - } - // Make sure that the node being added to is expanded so user can see added node is correctly moved - expand(selectedNode); - sortTree(); - endDrag(); - } else { - endDrag(); - } - }); - - function endDrag() { - selectedNode = null; - d3.selectAll('.ghostCircle').attr('class', 'ghostCircle'); - d3.select(domNode).attr('class', 'node'); - // now restore the mouseover event or we won't be able to drag a 2nd time - d3.select(domNode).select('.ghostCircle').attr('pointer-events', ''); - updateTempConnector(); - if (draggingNode !== null) { - update(root); - centerNode(draggingNode); - draggingNode = null; - } - } - - - function expand(d) { - if (d._children) { - d.children = d._children; - d.children.forEach(expand); - d._children = null; - } - } - - // Function to update the temporary connector indicating dragging affiliation - var updateTempConnector = function() { - var data = []; - if (draggingNode !== null && selectedNode !== null) { - // have to flip the source coordinates since we did this for the existing connectors on the original tree - data = [{ - source: { - x: selectedNode.y0, - y: selectedNode.x0 - }, - target: { - x: draggingNode.y0, - y: draggingNode.x0 - } - }]; - } - var link = svgGroup.selectAll(".templink").data(data); - - link.enter().append("path") - .attr("class", "templink") - .attr("d", d3.svg.diagonal()) - .attr('pointer-events', 'none'); - - link.attr("d", d3.svg.diagonal()); - - link.exit().remove(); - }; - - // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. - - function centerNode(source) { - var scale = (depthwidth === 10) ? zoomListener.scale() : 0.4; - var x = -source.y0; - var y = -source.x0; - x = x * scale + 150; - y = y * scale + viewerHeight / 2; - d3.select('g').transition() - .duration(duration) - .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); - zoomListener.scale(scale); - zoomListener.translate([x, y]); - } - - // Toggle children function - - function toggleChildren(d) { - if (d.children) { - d._children = d.children; - d.children = null; - } else if (d._children) { - d.children = d._children; - d._children = null; - } - return d; - } - - // Toggle children on click. - - function click(d) { - if (d3.event.defaultPrevented) return; // click suppressed - d = toggleChildren(d); - update(d); - //centerNode(d); - } - - //arrow - baseSvg.append("svg:defs") - .append("svg:marker") - .attr("id", "arrow") - .attr("viewBox", "0 0 10 10") - .attr("refX", 22) - .attr("refY", 5) - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", 6) - .attr("markerHeight", 9) - .attr("orient", "auto") - .append("svg:path") - .attr("d", "M 0 0 L 10 5 L 0 10 z"); - - //marker for input type graph - baseSvg.append("svg:defs") - .append("svg:marker") - .attr("id", "input-arrow") - .attr("viewBox", "0 0 10 10") - .attr("refX", -15) - .attr("refY", 5) - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", 6) - .attr("markerHeight", 9) - .attr("orient", "auto") - .append("svg:path") - .attr("d", "M -2 5 L 8 0 L 8 10 z"); - - function update(source) { - // Compute the new height, function counts total children of root node and sets tree height accordingly. - // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed - // This makes the layout more consistent. - var levelWidth = [1]; - var childCount = function(level, n) { - - if (n.children && n.children.length > 0) { - if (levelWidth.length <= level + 1) levelWidth.push(0); - - levelWidth[level + 1] += n.children.length; - n.children.forEach(function(d) { - childCount(level + 1, d); - }); - } - }; - childCount(0, root); - tree = tree.nodeSize([50, 100]); - - // Compute the new tree layout. - var nodes = tree.nodes(root).reverse(), - links = tree.links(nodes); - - // Set widths between levels based on maxLabelLength. - nodes.forEach(function(d) { - if(levelWidth.length > 1 && depthwidth === 10){ - for(var o=0; o < levelWidth.length; o++){ - if(levelWidth[o] > 4 ) { depthwidth = 70; break;} - } - } - var maxLebal = maxLabelLength; - if(depthwidth === 10) { maxLebal = 20;} - d.y = (d.depth * (maxLebal * depthwidth)); - }); - - // Update the nodes⦠- node = svgGroup.selectAll("g.node") - .data(nodes, function(d) { - return d.id || (d.id = ++i); - }); - - // Enter any new nodes at the parent's previous position. - var nodeEnter = node.enter().append("g") - .call(dragListener) - .attr("class", "node") - .attr("transform", function() { - return "translate(" + source.y0 + "," + source.x0 + ")"; - }) - .on('click', click); - - nodeEnter.append("image") - .attr("class","nodeImage") - .attr("xlink:href", function(d) { - return d.type === 'Table' ? '../img/tableicon.png' : '../img/process.png'; - }) - .on('mouseover', function(d) { - if (d.type === 'LoadProcess' || 'Table') { - tooltip.show(d); - } - }) - .on('mouseout', function(d) { - if (d.type === 'LoadProcess' || 'Table') { - tooltip.hide(d); - } - }) - .attr("x", "-18px") - .attr("y", "-18px") - .attr("width", "34px") - .attr("height", "34px"); - - nodeEnter.append("text") - .attr("x", function(d) { - return d.children || d._children ? -10 : 10; - }) - .attr("dx", function (d) { return d.children ? 50 : -50; }) - .attr("dy", -24) - .attr('class', 'place-label') - .attr("text-anchor", function(d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function(d) { - var nameDis = (d.name.length > 15) ? d.name.substring(0,15) + "..." : d.name; - $(this).attr('title', d.name); - return nameDis; - }) - .style("fill-opacity", 0); - - // Update the text to reflect whether node has children or not. - node.select('text') - .attr("x", function(d) { - return d.children || d._children ? -10 : 10; - }) - .attr("text-anchor", function(d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function(d) { - var nameDis = (d.name.length > 15) ? d.name.substring(0,15) + "..." : d.name; - $(this).attr('title', d.name); - return nameDis; - }); - - // Change the circle fill depending on whether it has children and is collapsed - // Change the circle fill depending on whether it has children and is collapsed - node.select("image.nodeImage") - .attr("r", 4.5) - .attr("xlink:href", function(d) { - if(d._children){ - return d.type === 'Table' ? '../img/tableicon1.png' : '../img/process1.png'; - } - return d.type === 'Table' ? '../img/tableicon.png' : '../img/process.png'; - }); - - - // Transition nodes to their new position. - var nodeUpdate = node.transition() - .duration(duration) - .attr("transform", function(d) { - return "translate(" + d.y + "," + d.x + ")"; - }); - - // Fade the text in - nodeUpdate.select("text") - .style("fill-opacity", 1); - - // Transition exiting nodes to the parent's new position. - var nodeExit = node.exit().transition() - .duration(duration) - .attr("transform", function() { - return "translate(" + source.y + "," + source.x + ")"; - }) - .remove(); - - nodeExit.select("circle") - .attr("r", 0); - - nodeExit.select("text") - .style("fill-opacity", 0); - - // Update the links⦠- var link = svgGroup.selectAll("path.link") - .data(links, function(d) { - return d.target.id; - }); - - // Enter any new links at the parent's previous position. - link.enter().insert("path", "g") - .attr("class", "link") - .style('stroke', 'green') - .attr("d", function() { - var o = { - x: source.x0, - y: source.y0 - }; - return diagonal({ - source: o, - target: o - }); - }); - - // Transition links to their new position. - link.transition() - .duration(duration) - .attr("d", diagonal); - - // Transition exiting nodes to the parent's new position. - link.exit().transition() - .duration(duration) - .attr("d", function() { - var o = { - x: source.x, - y: source.y - }; - return diagonal({ - source: o, - target: o - }); - }) - .remove(); - - // Stash the old positions for transition. - nodes.forEach(function(d) { - d.x0 = d.x; - d.y0 = d.y; - }); - - if ($scope.type === 'inputs') { - link.attr("marker-start", "url(#input-arrow)"); //if input - } else { - link.attr("marker-end", "url(#arrow)"); //if input - } - } - - // Append a group which holds all nodes and which the zoom Listener can act upon. - var svgGroup = baseSvg.append("g") - .attr("transform", "translate(120 ," + heightg/2 + ")"); - - // Define the root - root = data; - root.x0 = viewerHeight / 2; - root.y0 = 0; - - // Layout the tree initially and center on the root node. - update(root); - centerNode(root); - - var couplingParent1 = tree.nodes(root).filter(function(d) { - return d.name === 'cluster'; - })[0]; - var couplingChild1 = tree.nodes(root).filter(function(d) { - return d.name === 'JSONConverter'; - })[0]; - - multiParents = [{ - parent: couplingParent1, - child: couplingChild1 - }]; - - multiParents.forEach(function() { - svgGroup.append("path", "g"); - }); - - - } - - } -]); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/modules/lineage/lineage_ioController.js ---------------------------------------------------------------------- diff --git a/dashboard/public/modules/lineage/lineage_ioController.js b/dashboard/public/modules/lineage/lineage_ioController.js index 41f69c2..3f4e990 100644 --- a/dashboard/public/modules/lineage/lineage_ioController.js +++ b/dashboard/public/modules/lineage/lineage_ioController.js @@ -131,6 +131,8 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ } $scope.onReset = function() { + $scope.height = $scope.initialHeight; + angular.element('.lineage-viz').height($scope.height); renderGraph($scope.lineageData, { eleObj: $element, element: $element[0], @@ -237,9 +239,8 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ function renderGraph(data, container) { // ************** Generate the tree diagram ***************** var element = d3.select(container.element), - widthg = Math.max(container.width, 1100), - heightg = Math.max((window.innerHeight - 400), 500), - + widthg = container.width || 1100, + heightg = container.height || Math.max((window.innerHeight - 400), 300), totalNodes = 0, maxLabelLength = 0, selectedNode = null, @@ -258,7 +259,8 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ var viewerWidth = widthg - 15, - viewerHeight = heightg; + viewerHeight = heightg, + center = [viewerWidth / 2, viewerHeight / 2]; var tree = d3.layout.tree().size([viewerHeight, viewerWidth]); /*.size([viewerHeight, viewerWidth]); nodeSize([100, 200]);*/ @@ -308,9 +310,9 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ // Sort the tree initially incase the JSON isn't in a sorted order. sortTree(); - // Define the zoom function for the zoomable tree + // Define the zoom function for the zoomable tree function zoom() { - svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); + d3.select('g').attr("transform", "translate(" + zoomListener.translate() + ")scale(" + zoomListener.scale() + ")"); } // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents @@ -334,6 +336,7 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ .attr("height", viewerHeight) .attr("class", "overlay") .call(zoomListener) + .call(zoomListener.event) .on("dblclick.zoom", function() { return null; }) @@ -708,6 +711,45 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ var svgGroup = baseSvg.append("g") .attr("transform", "translate(0,0)"); + // Simplest possible buttons + var intervalID; + + d3.selectAll('.zoom-buttons').on('mousedown', function(){ + d3.event.preventDefault(); + $scope.factor = (this.id === 'zoom_in') ? 1.1 : 1/1.1; + intervalID = setInterval(zoom_by, 40, $scope.factor); + }).on('mouseup', function(){ + d3.event.preventDefault(); + clearInterval(intervalID); + intervalID = undefined; + }); + + function zoom_by(factor){ + var scale = zoomListener.scale(), + extent = zoomListener.scaleExtent(), + translate = zoomListener.translate(), + x = translate[0], y = translate[1], + target_scale = scale * factor; + + // If we're already at an extent, done + if (target_scale === extent[0] || target_scale === extent[1]) { return false; } + // If the factor is too much, scale it down to reach the extent exactly + var clamped_target_scale = Math.max(extent[0], Math.min(extent[1], target_scale)); + if (clamped_target_scale !== target_scale){ + target_scale = clamped_target_scale; + factor = target_scale / scale; + } + + // Center each vector, stretch, then put back + x = (x - center[0]) * factor + center[0]; + y = (y - center[1]) * factor + center[1]; + + // Enact the zoom immediately + zoomListener.scale(target_scale) + .translate([x,y]); + zoom(); + } + // Define the root root = data; root.x0 = viewerWidth / 2; @@ -716,6 +758,11 @@ angular.module('dgc.lineage').controller('Lineage_ioController', ['$element', '$ // Layout the tree initially and center on the root node. update(root); centerNode(root); + if(!$scope.initialHeight){ + $scope.initialHeight = angular.element('.lineage-viz').height(); + } + angular.element('.lineage-viz').resizable({minWidth:1150, maxWidth:1150, maxHeight: angular.element('.lineage-viz').height(), minHeight:50 + }); $scope.requested = false; var couplingParent1 = tree.nodes(root).filter(function(d) { return d.name === 'cluster'; http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/dashboard/public/modules/lineage/views/lineage_io.html ---------------------------------------------------------------------- diff --git a/dashboard/public/modules/lineage/views/lineage_io.html b/dashboard/public/modules/lineage/views/lineage_io.html index 58f8f19..49a5d2a 100644 --- a/dashboard/public/modules/lineage/views/lineage_io.html +++ b/dashboard/public/modules/lineage/views/lineage_io.html @@ -20,6 +20,8 @@ <button type="button" class="btn btn-primary pull-right" ng-click="onReset()"> Reset </button> + <button type="button" class="btn btn-primary zoom-buttons pull-right" id="zoom_out"><i class="fa fa-minus"></i></button> + <button type="button" class="btn btn-primary zoom-buttons pull-right" id="zoom_in"><i class="fa fa-plus"></i> </button> <div class="graph"> <h4 data-ng-if="!requested && !lineageData" class="alignLineage">No lineage data found</h4> <i data-ng-if="requested" class="fa fa-spinner fa-spin fa-5x"></i> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/c4eebe0e/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index 7126845..f433865 100644 --- a/release-log.txt +++ b/release-log.txt @@ -6,6 +6,7 @@ INCOMPATIBLE CHANGES: ATLAS-379 Create sqoop and falcon metadata addons (venkatnrangan,bvellanki,sowmyaramesh via shwethags) ALL CHANGES: +ATLAS-406 Resizing lineage window â should be an anchor on a corner â like ppt for graphic (sanjayp via shwethags) ATLAS-432 QuickStart lineage is broken (yhemanth via shwethags) ATLAS-421 typo in Architecture.twiki (dbist13 via shwethags) ATLAS-387 Running quick_start without a valid atlas endpoint in configuration or argument prints a spurious success message (yhemanth via shwethags)
