atlas-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From suma...@apache.org
Subject incubator-atlas git commit: ATLAS-138 - Combine Input/Output graph ( Anilsg via Suma Shivaprasad)
Date Tue, 06 Oct 2015 06:15:01 GMT
Repository: incubator-atlas
Updated Branches:
  refs/heads/master 231512447 -> cf2c8bc0c


ATLAS-138 - Combine Input/Output graph ( Anilsg via Suma Shivaprasad)


Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/cf2c8bc0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/cf2c8bc0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/cf2c8bc0

Branch: refs/heads/master
Commit: cf2c8bc0c2821b9672761c6cf551783613f003ab
Parents: 2315124
Author: Suma Shivaprasad <sumasai.shivaprasad@gmail.com>
Authored: Tue Oct 6 11:41:35 2015 +0530
Committer: Suma Shivaprasad <sumasai.shivaprasad@gmail.com>
Committed: Tue Oct 6 11:42:15 2015 +0530

----------------------------------------------------------------------
 dashboard/gruntfile.js                          |   2 +-
 .../public/modules/details/detailsModule.js     |   2 +-
 .../public/modules/details/views/details.html   |   1 +
 .../public/modules/lineage_io/Find Results      |  30 +
 .../modules/lineage_io/lineage_ioController.js  | 750 +++++++++++++++++++
 .../modules/lineage_io/lineage_ioModule.js      |  21 +
 .../modules/lineage_io/lineage_ioResource.js    |  23 +
 .../modules/lineage_io/views/lineage_io.html    |  30 +
 release-log.txt                                 |   1 +
 9 files changed, 858 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/gruntfile.js
----------------------------------------------------------------------
diff --git a/dashboard/gruntfile.js b/dashboard/gruntfile.js
index 76ca84a..07a5bf8 100644
--- a/dashboard/gruntfile.js
+++ b/dashboard/gruntfile.js
@@ -151,7 +151,7 @@ module.exports = function(grunt) {
                         'hostnames': ['*'],
                         'routes': {
                             '/': distPath,
-                            '/api': 'http://162.249.6.50:21000/api'
+                            '/api': 'http://162.212.133.190:21000/api'
                         }
                     }]
                 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/details/detailsModule.js
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/details/detailsModule.js b/dashboard/public/modules/details/detailsModule.js
index 987750a..8bc5b53 100644
--- a/dashboard/public/modules/details/detailsModule.js
+++ b/dashboard/public/modules/details/detailsModule.js
@@ -18,4 +18,4 @@
 
 'use strict';
 
-angular.module('dgc.details', ['dgc.lineage']);
+angular.module('dgc.details', ['dgc.lineage', 'dgc.lineage_io']);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/details/views/details.html
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/details/views/details.html b/dashboard/public/modules/details/views/details.html
index c0419cb..bdf1c57 100644
--- a/dashboard/public/modules/details/views/details.html
+++ b/dashboard/public/modules/details/views/details.html
@@ -44,6 +44,7 @@
             <tab data-heading="Schema" data-ng-if="isTable"><ng-include src="'/modules/details/views/schema.html'"/></tab>
             <tab data-heading="Output" data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('outputs')"><ng-include data-table-type="outputs" src="'/modules/lineage/views/lineage.html'"/></tab>
             <tab data-heading="Input"  data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('inputs')"><ng-include data-table-type="inputs" src="'/modules/lineage/views/lineage.html'"/></tab>
+            <tab data-heading="Lineage"  data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('io')"><ng-include data-table-type="io" src="'/modules/lineage_io/views/lineage_io.html'"/></tab>
         </tabset>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/lineage_io/Find
Results
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/lineage_io/Find Results b/dashboard/public/modules/lineage_io/Find
Results
new file mode 100644
index 0000000..ba9fb32
--- /dev/null
+++ b/dashboard/public/modules/lineage_io/Find Results	
@@ -0,0 +1,30 @@
+Searching 16184 files for "LineageController"
+
+/Users/anilgayakwad/MPR/Anil/incubator-atlas/dashboard/public/modules/lineage/lineageController.js:
+   18  'use strict';
+   19  
+   20: angular.module('dgc.lineage').controller('LineageController', ['$element', '$scope',
'$state', '$stateParams', 'lodash', 'LineageResource', 'd3', 'DetailsResource', '$q',
+   21      function($element, $scope, $state, $stateParams, _, LineageResource, d3, DetailsResource,
$q) {
+   22          var guidsList = [];
+
+/Users/anilgayakwad/MPR/Anil/incubator-atlas/dashboard/public/modules/lineage/views/lineage.html:
+   17    -->
+   18  
+   19: <div class="lineage-viz" data-ng-controller="LineageController">
+   20      <button type="button" class="btn btn-primary pull-right" ng-click="onReset()">
+   21          Reset
+
+2 matches across 2 files
+
+
+Searching 16184 files for "lineage.html"
+
+/Users/anilgayakwad/MPR/Anil/incubator-atlas/dashboard/public/modules/details/views/details.html:
+   43              </tab>
+   44              <tab data-heading="Schema" data-ng-if="isTable"><ng-include src="'/modules/details/views/schema.html'"/></tab>
+   45:             <tab data-heading="Output" data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('outputs')"><ng-include data-table-type="outputs" src="'/modules/lineage/views/lineage.html'"/></tab>
+   46:             <tab data-heading="Input"  data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('inputs')"><ng-include data-table-type="inputs" src="'/modules/lineage/views/lineage.html'"/></tab>
+   47  
+   48              <tab data-heading="Lineage"  data-ng-if="isTable" data-disable="!tableName"
data-select="onActivate('io')"><ng-include data-table-type="io" src="'/modules/lineage_io/views/lineage_io.html'"/></tab>
+
+2 matches in 1 file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/lineage_io/lineage_ioController.js
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/lineage_io/lineage_ioController.js b/dashboard/public/modules/lineage_io/lineage_ioController.js
new file mode 100644
index 0000000..11cefd7
--- /dev/null
+++ b/dashboard/public/modules/lineage_io/lineage_ioController.js
@@ -0,0 +1,750 @@
+/*
+ * 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_io').controller('Lineage_ioController', ['$element', '$scope',
'$state', '$stateParams', 'lodash', 'Lineage_ioResource', 'd3', 'DetailsResource', '$q',
+    function($element, $scope, $state, $stateParams, _, LineageResource, d3, DetailsResource,
$q) {
+        var guidsList = [];
+
+        function inVertObj(edgs) {
+            var newEdgsObj = {};
+
+            $.each(edgs, function(key, value) {
+                for (var k = 0; k < value.length; k++) {
+                    newEdgsObj[value[k]] = newEdgsObj[value[k]] || [];
+                    newEdgsObj[value[k]] = [key];
+                }
+            });
+            return newEdgsObj;
+        }
+
+        function getCombinedLineageData(tableData, callRender) {
+            LineageResource.get({
+                tableName: tableData.tableName,
+                type: 'outputs'
+            }, function lineageSuccess(response1) {
+
+                LineageResource.get({
+                    tableName: tableData.tableName,
+                    type: 'inputs'
+                }, function lineageSuccess(response) {
+                    response.results.values.edges = inVertObj(response.results.values.edges);
+
+                    angular.forEach(response.results.values.edges, function(value, key) {
+                        angular.forEach(response1.results.values.edges, function(value1,
key1) {
+                            if (key === key1) {
+                                var array1 = value;
+                                angular.forEach(value1, function(value2) {
+                                    array1.push(value2);
+                                });
+                                response.results.values.edges[key] = array1;
+                                response1.results.values.edges[key] = array1;
+                            }
+                        });
+                    });
+
+                    angular.extend(response.results.values.edges, response1.results.values.edges);
+                    angular.extend(response.results.values.vertices, response1.results.values.vertices);
+
+                    if (!_.isEmpty(response.results.values.vertices)) {
+                        loadProcess(response.results.values.edges, response.results.values.vertices)
+                            .then(function(res) {
+                                guidsList = res;
+
+                                $scope.lineageData = transformData(response.results);
+
+                                if (callRender) {
+                                    render();
+                                }
+                            });
+                    }
+                    $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) {
+                        if ($scope.type === 'io') {
+                            console.log($scope.type);
+                            getCombinedLineageData(lineageData, true);
+                        } else {
+                            getCombinedLineageData(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);
+            }
+
+            var starTingObj = {
+                name: 'root',
+                guid: 'root',
+                children: []
+            };
+
+            angular.forEach(nodes, function(value) {
+                if (!value.hasOwnProperty('parent')) {
+                    starTingObj.children.push(value);
+                }
+            });
+
+            return starTingObj;
+        }
+
+        function renderGraph(data, container) {
+            // ************** Generate the tree diagram  *****************
+            var element = d3.select(container.element),
+                widthg = Math.max(container.width, 1100),
+                //heightg = Math.max(container.height, 500),
+                heightg = Math.max((window.innerHeight - 380), 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().size([viewerHeight, viewerWidth]);
+            /*.size([viewerHeight, viewerWidth]);   nodeSize([100, 200]);*/
+
+            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)
+                .on("dblclick.zoom", function() {
+                    return null;
+                })
+                .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();
+
+                nodes = _.uniq(nodes, 'guid');
+
+                _.each(nodes, function(o, i) {
+                    var itemsOfTheSameDepth = _.where(nodes, {
+                        depth: o.depth
+                    });
+                    var indexOfCurrent = _.indexOf(itemsOfTheSameDepth, o);
+                    var interval = viewerHeight / itemsOfTheSameDepth.length;
+                    nodes[i].x = interval / 2 + (interval * indexOfCurrent);
+                });
+
+                var links = tree.links(nodes);
+
+                _.each(links, function(o, i) {
+                    //links[i].target = _.find(nodes, {guid: o.target.id});
+                    links[i].target = _.find(nodes, {
+                        guid: o.target.guid
+                    });
+                });
+
+                // 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', function(d) {
+                        if (d.guid === "root") {
+                            return "hide";
+                        } else {
+                            return "";
+                        }
+                    })
+                    .classed('node', true)
+                    .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('dblclick', function(d) {
+                        $state.go("details", {
+                            id: d.guid
+                        });
+                    })
+                    .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);
+                // .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', function(d) {
+                        if (d.source.guid === "root") {
+                            return "hide";
+                        } else {
+                            return "";
+                        }
+                    })
+                    .classed('link', true)
+                    .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(0,0)");
+
+            // Define the root
+            root = data;
+            root.x0 = viewerWidth / 2;
+            root.y0 = viewerHeight / 2;
+
+            // 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");
+            });
+        }
+
+    }
+]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/lineage_io/lineage_ioModule.js
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/lineage_io/lineage_ioModule.js b/dashboard/public/modules/lineage_io/lineage_ioModule.js
new file mode 100644
index 0000000..a4b8ef6
--- /dev/null
+++ b/dashboard/public/modules/lineage_io/lineage_ioModule.js
@@ -0,0 +1,21 @@
+/*
+ * 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_io', []);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/lineage_io/lineage_ioResource.js
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/lineage_io/lineage_ioResource.js b/dashboard/public/modules/lineage_io/lineage_ioResource.js
new file mode 100644
index 0000000..ba8f4b7
--- /dev/null
+++ b/dashboard/public/modules/lineage_io/lineage_ioResource.js
@@ -0,0 +1,23 @@
+/*
+ * 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_io').factory('Lineage_ioResource', ['$resource', function($resource)
{
+    return $resource('/api/atlas/lineage/hive/table/:tableName/:type/graph', {});
+}]);

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/dashboard/public/modules/lineage_io/views/lineage_io.html
----------------------------------------------------------------------
diff --git a/dashboard/public/modules/lineage_io/views/lineage_io.html b/dashboard/public/modules/lineage_io/views/lineage_io.html
new file mode 100644
index 0000000..e7ac084
--- /dev/null
+++ b/dashboard/public/modules/lineage_io/views/lineage_io.html
@@ -0,0 +1,30 @@
+<!--
+  ~ 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.
+  -->
+
+<div class="lineage-viz" data-ng-controller="Lineage_ioController">
+    <button type="button" class="btn btn-primary pull-right" ng-click="onReset()">
+        Reset
+    </button>
+    <div class="graph">
+      <h4 data-ng-if="!requested && !lineageData">No lineage data found</h4>
+      <i data-ng-if="requested" class="fa fa-spinner fa-spin fa-5x"></i>
+      <svg >
+          <g/>
+      </svg>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/cf2c8bc0/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index 503afd5..4fa8339 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-54 Rename configs in hive hook (shwethags)
 ATLAS-3 Mixed Index creation fails with Date types (suma.shivaprasad via shwethags)
 
 ALL CHANGES:
+ATLAS-138 Combine Input/Output graph ( Anilsg via Suma Shivaprasad )
 ATLAS-128 DSL - Add support for comparisions on list type (suma.shivaprasad via shwethags)
 ATLAS-168 Atlas UI - Max column in hive 4 (darshankumar89 via shwethags)
 ATLAS-155 Images do not show up on the dashboard (darshankumar89 via shwethags)



Mime
View raw message