You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sa...@apache.org on 2019/02/25 19:04:44 UTC

[atlas] branch master updated: ATLAS-3030: UI : Allow to search the node in the lineage graph

This is an automated email from the ASF dual-hosted git repository.

sarath pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new b9642b6  ATLAS-3030: UI : Allow to search the node in the lineage graph
b9642b6 is described below

commit b9642b62bca574bda897b199c5beb722238f3201
Author: kevalbhatt <kb...@apache.org>
AuthorDate: Mon Feb 25 11:04:21 2019 -0800

    ATLAS-3030: UI : Allow to search the node in the lineage graph
    
    Signed-off-by: Sarath Subramanian <ss...@hortonworks.com>
---
 dashboardv2/public/css/scss/graph.scss             |  30 +++
 .../entity-icon/disabled/falcon_feed_creation.png  | Bin 0 -> 6830 bytes
 .../disabled/falcon_feed_replication.png           | Bin 0 -> 6830 bytes
 .../img/entity-icon/disabled/falcon_process.png    | Bin 0 -> 6830 bytes
 .../img/entity-icon/falcon_feed_creation.png       | Bin 0 -> 9620 bytes
 .../img/entity-icon/falcon_feed_replication.png    | Bin 0 -> 9620 bytes
 .../public/img/entity-icon/falcon_process.png      | Bin 0 -> 9620 bytes
 dashboardv2/public/js/main.js                      |   3 +-
 dashboardv2/public/js/router/Router.js             |   1 +
 .../js/templates/graph/LineageLayoutView_tmpl.html |  25 ++-
 dashboardv2/public/js/utils/CommonViewFunction.js  |  20 +-
 .../public/js/utils/{Overrides.js => Helper.js}    | 202 ++-------------------
 dashboardv2/public/js/utils/Overrides.js           | 182 -------------------
 dashboardv2/public/js/utils/Utils.js               |   9 -
 dashboardv2/public/js/views/common/Statistics.js   |   8 +-
 .../js/views/detail_page/DetailPageLayoutView.js   |   2 +-
 .../public/js/views/graph/LineageLayoutView.js     | 188 +++++++++++++------
 .../public/js/views/search/SearchLayoutView.js     |   4 +-
 18 files changed, 231 insertions(+), 443 deletions(-)

diff --git a/dashboardv2/public/css/scss/graph.scss b/dashboardv2/public/css/scss/graph.scss
index 3646261..4a9fd57 100644
--- a/dashboardv2/public/css/scss/graph.scss
+++ b/dashboardv2/public/css/scss/graph.scss
@@ -38,6 +38,12 @@
         stroke: $color_mountain_mist_approx;
         fill: $white;
         stroke-width: 1.5px;
+
+        &.serach-rect {
+            stroke: $color_keppel_approx;
+            fill: transparent;
+            stroke-width: 2.5px
+        }
     }
 
     .label {
@@ -276,6 +282,7 @@ g.type-TK>rect {
 .lineage-fltr-panel,
 .lineage-search-panel {
     position: absolute;
+    top: 45px;
     border: 1px solid #ccc;
     width: 250px;
     max-height: 99%;
@@ -445,6 +452,11 @@ span#zoom_in {
     position: relative;
     width: 100%;
     height: 64vh;
+    overflow: hidden !important;
+
+    &.auto-height {
+        height: auto !important;
+    }
 }
 
 .active.fullscreen-mode {
@@ -471,4 +483,22 @@ span#zoom_in {
     .lineage-box {
         padding: 10px !important;
     }
+}
+
+@keyframes zoominoutsinglefeatured {
+    0% {
+        transform: scale(1, 1);
+    }
+
+    50% {
+        transform: scale(1.2, 1.2);
+    }
+
+    100% {
+        transform: scale(1, 1);
+    }
+}
+
+.wobble {
+    animation: zoominoutsinglefeatured 1s 5;
 }
\ No newline at end of file
diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png
new file mode 100644
index 0000000..b98be6c
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png differ
diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png
new file mode 100644
index 0000000..b98be6c
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png differ
diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_process.png b/dashboardv2/public/img/entity-icon/disabled/falcon_process.png
new file mode 100644
index 0000000..b98be6c
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/disabled/falcon_process.png differ
diff --git a/dashboardv2/public/img/entity-icon/falcon_feed_creation.png b/dashboardv2/public/img/entity-icon/falcon_feed_creation.png
new file mode 100644
index 0000000..ddb3829
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/falcon_feed_creation.png differ
diff --git a/dashboardv2/public/img/entity-icon/falcon_feed_replication.png b/dashboardv2/public/img/entity-icon/falcon_feed_replication.png
new file mode 100644
index 0000000..ddb3829
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/falcon_feed_replication.png differ
diff --git a/dashboardv2/public/img/entity-icon/falcon_process.png b/dashboardv2/public/img/entity-icon/falcon_process.png
new file mode 100644
index 0000000..ddb3829
Binary files /dev/null and b/dashboardv2/public/img/entity-icon/falcon_process.png differ
diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js
index 493e002..cb98f12 100644
--- a/dashboardv2/public/js/main.js
+++ b/dashboardv2/public/js/main.js
@@ -189,6 +189,7 @@ require.config({
 
 require(['App',
     'router/Router',
+    'utils/Helper',
     'utils/CommonViewFunction',
     'utils/Globals',
     'utils/UrlLinks',
@@ -198,7 +199,7 @@ require(['App',
     'bootstrap',
     'd3',
     'select2'
-], function(App, Router, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList) {
+], function(App, Router, Helper, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList) {
     var that = this;
     this.asyncFetchCounter = 6;
     this.entityDefCollection = new VEntityList();
diff --git a/dashboardv2/public/js/router/Router.js b/dashboardv2/public/js/router/Router.js
index 9f4536e..0b0d1a8 100644
--- a/dashboardv2/public/js/router/Router.js
+++ b/dashboardv2/public/js/router/Router.js
@@ -103,6 +103,7 @@ define([
             this.postRouteExecute();
         },
         preRouteExecute: function() {
+            $(".tooltip").tooltip("hide");
             // console.log("Pre-Route Change Operations can be performed here !!");
         },
         postRouteExecute: function(name, args) {
diff --git a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
index 2c92103..3adc8ad 100644
--- a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
@@ -46,11 +46,32 @@
             </div>
         </div>
     </div>
+    <div class="lineage-search-panel">
+        <div class="header clearfix">
+            <h4>Search</h4>
+            <span data-id="search-togler" style="margin: 7px" class="btn btn-action btn-sm fltr-togler"><i class="fa fa-close"></i></span>
+        </div>
+        <div class="body">
+            <div class="col-sm-12 no-padding">
+                <div class="srchType clearfix">
+                    <label class="srchTitle">Search Lineage Entity: </label>
+                    <div class="">
+                        <div class="col-sm-12 no-padding temFilter">
+                            <select data-id="typeSearch"></select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
     <div class="graph-button-group pull-right">
         <div>
             <button type="button" data-id="fltr-togler" class="btn btn-action btn-gray btn-sm"><i class="fa fa-filter"></i></button>
         </div>
         <div>
+            <button type="button" data-id="search-togler" class="btn btn-action btn-gray btn-sm"><i class="fa fa-search"></i></button>
+        </div>
+        <div>
             <button type="button" data-id="fullScreen-toggler" class="btn btn-action btn-gray btn-sm fullscreen_lineage"><i class="fa fa-expand"></i></button>
         </div>
         <div class="btn-group">
@@ -61,12 +82,14 @@
     <div class="fontLoader">
         <i class="fa fa-refresh fa-spin-custom"></i>
     </div>
+    <canvas width="960" height="500" style="display:none; position: absolute;"></canvas>
     <div class="legends pull-left" style="height: 25px; padding: 2px;">
         <span style="margin-right: 8px; color:#fb4200;"><i class="fa fa-circle-o fa-fw" aria-hidden="true"></i>Current Entity</span>
         <span style="margin-right: 8px; color:#df9b00;"><i class="fa fa-long-arrow-right fa-fw" aria-hidden="true"></i>Lineage</span>
         <span style="margin-right: 8px; color:#fb4200;"><i class="fa fa-long-arrow-right fa-fw" aria-hidden="true"></i>Impact</span>
     </div>
-    <svg width="100%" height="calc(100% - 28px)" viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg>
+    <!-- <svg width="100%" height="calc(100% - 28px)" preserveAspectRatio="xMidYMid meet" viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg> -->
+    <svg width="{{width}}" height="{{height}}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"></svg>
     <div class="lineage-details node-details">
         <span data-id="close" style="margin: 7px;position: absolute;right: 0" class="btn btn-action btn-sm fltr-togler"><i class="fa fa-close"></i></span>
         <h4 class="title"><span data-id="typeName"></span></h4>
diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js
index 19f2319..a20635d 100644
--- a/dashboardv2/public/js/utils/CommonViewFunction.js
+++ b/dashboardv2/public/js/utils/CommonViewFunction.js
@@ -76,9 +76,21 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Glob
             valueObject = options.valueObject,
             extractJSON = options.extractJSON,
             isTable = _.isUndefined(options.isTable) ? true : options.isTable,
-            attributeDefs = options.attributeDefs;
+            attributeDefs = options.attributeDefs,
+            numberFormat = options.numberFormat;
 
         var table = "",
+            getValue = function(val) {
+                if (val && numberFormat) {
+                    if (_.isNumber(val)) {
+                        return numberFormat(val);
+                    } else if (!_.isNaN(parseInt(val))) {
+                        return numberFormat(val);
+                    }
+                } else {
+                    return val;
+                }
+            },
             fetchInputOutputValue = function(id, defEntity) {
                 var that = this;
                 scope.entityModel.getEntityHeader(id, {
@@ -95,7 +107,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Glob
                             id = data.guid;
                         }
                         if (value.length > 0) {
-                            scope.$('td div[data-id="' + id + '"]').html('<a href="#!/detailPage/' + id + '">' + value + '</a>');
+                            scope.$('td div[data-id="' + id + '"]').html('<a href="#!/detailPage/' + id + '">' + getValue(value) + '</a>');
                         } else {
                             scope.$('td div[data-id="' + id + '"]').html('<a href="#!/detailPage/' + id + '">' + _.escape(id) + '</a>');
                         }
@@ -137,7 +149,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Glob
                     if (_.isString(inputOutputField) || _.isBoolean(inputOutputField) || _.isNumber(inputOutputField)) {
                         var tempVarfor$check = inputOutputField.toString();
                         if (tempVarfor$check.indexOf("$") == -1) {
-                            valueOfArray.push('<span class="json-string">' + _.escape(inputOutputField) + '</span>');
+                            valueOfArray.push('<span class="json-string">' + getValue(_.escape(inputOutputField)) + '</span>');
                         }
                     } else if (_.isObject(inputOutputField) && !id) {
                         var attributesList = inputOutputField;
@@ -233,7 +245,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Glob
                 val = _.escape(keyValue);
             }
             if (isTable) {
-                var htmlTag = '<div class="scroll-y">' + val + '</div>';
+                var htmlTag = '<div class="scroll-y">' + getValue(val) + '</div>';
                 if (_.isObject(valueObject[key])) {
                     var matchedLinkString = val.match(/href|value-loader\w*/g),
                         matchedJson = val.match(/json-value|json-string\w*/g),
diff --git a/dashboardv2/public/js/utils/Overrides.js b/dashboardv2/public/js/utils/Helper.js
similarity index 58%
copy from dashboardv2/public/js/utils/Overrides.js
copy to dashboardv2/public/js/utils/Helper.js
index b3b591c..3f211e9 100644
--- a/dashboardv2/public/js/utils/Overrides.js
+++ b/dashboardv2/public/js/utils/Helper.js
@@ -15,40 +15,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-define(['require', 'utils/Utils', 'marionette', 'backgrid', 'asBreadcrumbs', 'jquery-placeholder'], function(require, Utils) {
+define(['require',
+    'utils/Utils',
+    'd3',
+    'marionette'
+], function(require, Utils, d3) {
     'use strict';
-
-    Backbone.$.ajaxSetup({
-        cache: false
-    });
-
-    var oldBackboneSync = Backbone.sync;
-    Backbone.sync = function(method, model, options) {
-        var that = this;
-        if (options.queryParam) {
-            var generateQueryParam = $.param(options.queryParam);
-            if (options.url.indexOf('?') !== -1) {
-                options.url = options.url + "&" + generateQueryParam;
-            } else {
-                options.url = options.url + "?" + generateQueryParam;
-            }
-        }
-        return oldBackboneSync.apply(this, [method, model,
-            _.extend(options, {
-                error: function(response) {
-                    if (!options.skipDefaultError) {
-                        Utils.defaultErrorHandler(that, response);
-                    }
-                    that.trigger("error", that, response);
-                    if (options.cust_error) {
-                        options.cust_error(that, response);
-                    }
-                }
-            })
-        ]);
-    }
     _.mixin({
+        numberFormatWithComa: function(number) {
+            return d3.format(',')(number);
+        },
         isEmptyArray: function(val) {
             if (val && _.isArray(val)) {
                 return _.isEmpty(val);
@@ -230,158 +206,20 @@ define(['require', 'utils/Utils', 'marionette', 'backgrid', 'asBreadcrumbs', 'jq
             this.$('input, textarea').placeholder();
         }
     }
-
-    String.prototype.trunc = String.prototype.trunc ||
-        function(n) {
-            return (this.length > n) ? this.substr(0, n - 1) + '...' : this;
-        };
-    String.prototype.capitalize = function() {
-        return this.charAt(0).toUpperCase() + this.slice(1);
-    }
-
-
-
-    /*
-     * Overriding Cell for adding custom className to Cell i.e <td>
-     */
-    var cellInit = Backgrid.Cell.prototype.initialize;
-    Backgrid.Cell.prototype.initialize = function() {
-        cellInit.apply(this, arguments);
-        var className = this.column.get('className');
-        var rowClassName = this.column.get('rowClassName');
-        if (rowClassName) this.$el.addClass(rowClassName);
-        if (className) this.$el.addClass(className);
-    }
-    /*
-     * Overriding Cell for adding custom width to Cell i.e <td>
-     */
-    Backgrid.HeaderRow = Backgrid.HeaderRow.extend({
-        render: function() {
-            var that = this;
-            Backgrid.HeaderRow.__super__.render.apply(this, arguments);
-            _.each(this.columns.models, function(modelValue) {
-                var elAttr = modelValue.get('elAttr'),
-                    elAttrObj = null;
-                if (elAttr) {
-                    if (_.isFunction(elAttr)) {
-                        elAttrObj = elAttr(modelValue);
-                    } else if (_.isObject(elAttr)) {
-                        if (!_.isArray(elAttr)) {
-                            elAttrObj = [elAttr];
-                        } else {
-                            elAttrObj = elAttr;
-                        }
-                    }
-                    _.each(elAttrObj, function(val) {
-                        that.$el.find('.' + modelValue.get('name')).data(val);
-                    });
-                }
-                if (modelValue.get('width')) that.$el.find('.' + modelValue.get('name')).css('min-width', modelValue.get('width') + 'px');
-                if (modelValue.get('toolTip')) that.$el.find('.' + modelValue.get('name')).attr('title', modelValue.get('toolTip'));
-            });
-            return this;
+    $('body').on('click', 'pre.code-block .expand-collapse-button', function(e) {
+        var $el = $(this).parents('.code-block');
+        if ($el.hasClass('shrink')) {
+            $el.removeClass('shrink');
+        } else {
+            $el.addClass('shrink');
         }
     });
-    /*
-     * HtmlCell renders any html code
-     * @class Backgrid.HtmlCell
-     * @extends Backgrid.Cell
-     */
-    var HtmlCell = Backgrid.HtmlCell = Backgrid.Cell.extend({
-
-        /** @property */
-        className: "html-cell",
 
-        render: function() {
-            this.$el.empty();
-            var rawValue = this.model.get(this.column.get("name"));
-            var formattedValue = this.formatter.fromRaw(rawValue, this.model);
-            this.$el.append(formattedValue);
-            this.delegateEvents();
-            return this;
-        }
+    // For adding tooltip globally
+    $('body').tooltip({
+        selector: '[title]',
+        placement: 'bottom',
+        container: 'body'
     });
 
-
-    /*
-     * Backgrid Header render listener when resize or re-ordered
-     */
-    var BackgridHeaderInitializeMethod = function(options) {
-        this.columns = options.columns;
-        if (!(this.columns instanceof Backbone.Collection)) {
-            this.columns = new Backgrid.Columns(this.columns);
-        }
-        this.createHeaderRow();
-
-        this.listenTo(this.columns, "sort", _.bind(function() {
-            this.createHeaderRow();
-            this.render();
-        }, this));
-    };
-
-    /**
-     * Sets up a new headerRow and attaches it to the view
-     * Tested with backgrid 0.3.5
-     */
-    var BackgridHeaderCreateHeaderRowMethod = function() {
-        this.row = new Backgrid.HeaderRow({
-            columns: this.columns,
-            collection: this.collection
-        });
-    };
-
-    /**
-     * Tested with backgrid 0.3.5
-     */
-    var BackgridHeaderRenderMethod = function() {
-        this.$el.empty();
-        this.$el.append(this.row.render().$el);
-        this.delegateEvents();
-
-        // Trigger event
-        this.trigger("backgrid:header:rendered", this);
-
-        return this;
-    };
-
-    // Backgrid patch
-    Backgrid.Header.prototype.initialize = BackgridHeaderInitializeMethod;
-    Backgrid.Header.prototype.createHeaderRow = BackgridHeaderCreateHeaderRowMethod;
-    Backgrid.Header.prototype.render = BackgridHeaderRenderMethod;
-
-    /* End: Backgrid Header render listener when resize or re-ordered */
-
-    var UriCell = Backgrid.UriCell = Backgrid.Cell.extend({
-        className: "uri-cell",
-        title: null,
-        target: "_blank",
-
-        initialize: function(options) {
-            UriCell.__super__.initialize.apply(this, arguments);
-            this.title = options.title || this.title;
-            this.target = options.target || this.target;
-        },
-
-        render: function() {
-            this.$el.empty();
-            var rawValue = this.model.get(this.column.get("name"));
-            var href = _.isFunction(this.column.get("href")) ? this.column.get('href')(this.model) : this.column.get('href');
-            var klass = this.column.get("klass");
-            var formattedValue = this.formatter.fromRaw(rawValue, this.model);
-            this.$el.append($("<a>", {
-                tabIndex: -1,
-                href: href,
-                title: this.title || formattedValue,
-                'class': klass
-            }).text(formattedValue));
-
-            if (this.column.has("iconKlass")) {
-                var iconKlass = this.column.get("iconKlass");
-                var iconTitle = this.column.get("iconTitle");
-                this.$el.find('a').append('<i class="' + iconKlass + '" title="' + iconTitle + '"></i>');
-            }
-            this.delegateEvents();
-            return this;
-        }
-    });
-});
\ No newline at end of file
+})
\ No newline at end of file
diff --git a/dashboardv2/public/js/utils/Overrides.js b/dashboardv2/public/js/utils/Overrides.js
index b3b591c..61c9595 100644
--- a/dashboardv2/public/js/utils/Overrides.js
+++ b/dashboardv2/public/js/utils/Overrides.js
@@ -48,188 +48,6 @@ define(['require', 'utils/Utils', 'marionette', 'backgrid', 'asBreadcrumbs', 'jq
             })
         ]);
     }
-    _.mixin({
-        isEmptyArray: function(val) {
-            if (val && _.isArray(val)) {
-                return _.isEmpty(val);
-            } else {
-                return false;
-            }
-        },
-        startsWith: function(str, matchStr) {
-            if (str && matchStr && _.isString(str) && _.isString(matchStr)) {
-                return str.lastIndexOf(matchStr, 0) === 0
-            } else {
-                return;
-            }
-        },
-        isUndefinedNull: function(val) {
-            if (_.isUndefined(val) || _.isNull(val)) {
-                return true
-            } else {
-                return false;
-            }
-        },
-        trim: function(val) {
-            if (val && val.trim) {
-                return val.trim();
-            } else {
-                return val;
-            }
-        },
-        isTypePrimitive: function(type) {
-            if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double" || type === "string" || type === "boolean" || type === "date") {
-                return true;
-            }
-            return false;
-        }
-    });
-    var getPopoverEl = function(e) {
-        return $(e.target).parent().data("bs.popover") || $(e.target).data("bs.popover") || $(e.target).parents('.popover').length;
-    }
-    $(document).on('click DOMMouseScroll mousewheel', function(e) {
-        if (e.originalEvent) {
-            // Do action if it is triggered by a human.
-            //e.isImmediatePropagationStopped();
-            var isPopOverEl = getPopoverEl(e)
-            if (!isPopOverEl) {
-                $('.popover').popover('hide');
-            } else if (isPopOverEl.$tip) {
-                $('.popover').not(isPopOverEl.$tip).popover('hide');
-            }
-        }
-    });
-    $('body').on('hidden.bs.popover', function(e) {
-        $(e.target).data("bs.popover").inState = { click: false, hover: false, focus: false }
-    });
-    $('body').on('show.bs.popover', '[data-js="popover"]', function() {
-        $('.popover').not(this).popover('hide');
-    });
-    $('body').on('keypress', 'input.number-input,.number-input .select2-search__field', function(e) {
-        if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
-            return false;
-        }
-    });
-    $('body').on('keypress', 'input.number-input-negative,.number-input-negative .select2-search__field', function(e) {
-        if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) {
-            if (e.which == 45) {
-                if (this.value.length) {
-                    return false;
-                }
-            } else {
-                return false;
-            }
-        }
-    });
-    $('body').on('keypress', 'input.number-input-exponential,.number-input-exponential .select2-search__field', function(e) {
-        if ((e.which != 8 && e.which != 0) && (e.which < 48 || e.which > 57) && (e.which != 69 && e.which != 101 && e.which != 43 && e.which != 45 && e.which != 46 && e.which != 190)) {
-            return false;
-        }
-    });
-    $("body").on('click', '.dropdown-menu.dropdown-changetitle li a', function() {
-        $(this).parents('li').find(".btn:first-child").html($(this).text() + ' <span class="caret"></span>');
-    });
-    $("body").on('click', '.btn', function() {
-        $(this).blur();
-    });
-
-    $.fn.select2.amd.define("ServiceTypeFilterDropdownAdapter", [
-            "select2/utils",
-            "select2/dropdown",
-            "select2/dropdown/attachBody",
-            "select2/dropdown/attachContainer",
-            "select2/dropdown/search",
-            "select2/dropdown/minimumResultsForSearch",
-            "select2/dropdown/closeOnSelect",
-        ],
-        function(Utils, Dropdown, AttachBody, AttachContainer, Search, MinimumResultsForSearch, CloseOnSelect) {
-
-            // Decorate Dropdown with Search functionalities
-            var dropdownWithSearch = Utils.Decorate(Utils.Decorate(Dropdown, CloseOnSelect), Search);
-
-            dropdownWithSearch.prototype.render = function() {
-                // Copy and modify default search render method
-                var $rendered = Dropdown.prototype.render.call(this);
-
-                // Add ability for a placeholder in the search box
-                var placeholder = this.options.get("placeholderForSearch") || "";
-                var $search = $(
-                    '<span class="select2-search select2-search--dropdown"><div class="row">' +
-                    '<div class="col-md-10"><input class="select2-search__field" placeholder="' + placeholder + '" type="search"' +
-                    ' tabindex="-1" autocomplete="off" autocorrect="off" autocapitalize="off"' +
-                    ' spellcheck="false" role="textbox" /></div>' +
-                    '<div class="col-md-2"><button type="button" style="margin-left: -20px" class="btn btn-action btn-sm filter " title="Entity Attribute Filter"><i class="fa fa-filter"></i></button></div>' +
-                    '</div></span>'
-                );
-                if (!this.options.options.getFilterBox) {
-                    throw "In order to render the filter options adapter needed getFilterBox function"
-                }
-                var $Filter = $('<ul class="type-filter-ul"></ul>');
-                this.$Filter = $Filter;
-                this.$Filter.append(this.options.options.getFilterBox());
-                this.$Filter.hide();
-
-                this.$searchContainer = $search;
-                if ($Filter.find('input[type="checkbox"]:checked').length) {
-                    $search.find('button.filter').addClass('active');
-                } else {
-                    $search.find('button.filter').removeClass('active');
-                }
-                this.$search = $search.find('input');
-
-                $rendered.prepend($search);
-                $rendered.append($Filter);
-                return $rendered;
-            };
-            var oldDropdownWithSearchBindRef = dropdownWithSearch.prototype.bind;
-            dropdownWithSearch.prototype.bind = function(container, $container) {
-                var self = this;
-                oldDropdownWithSearchBindRef.call(this, container, $container);
-                var self = this;
-                this.$Filter.on('click', 'li', function() {
-                    var itemCallback = self.options.options.onFilterItemSelect;
-                    itemCallback && itemCallback(this);
-                })
-
-                this.$searchContainer.find('button.filter').click(function() {
-                    container.$dropdown.find('.select2-search').hide(150);
-                    container.$dropdown.find('.select2-results').hide(150);
-                    self.$Filter.html(self.options.options.getFilterBox());
-                    self.$Filter.show();
-                });
-                this.$Filter.on('click', 'button.filterDone', function() {
-                    container.$dropdown.find('.select2-search').show(150);
-                    container.$dropdown.find('.select2-results').show(150);
-                    self.$Filter.hide();
-                    var filterSubmitCallback = self.options.options.onFilterSubmit;
-                    filterSubmitCallback && filterSubmitCallback({
-                        filterVal: _.map(self.$Filter.find('input[type="checkbox"]:checked'), function(item) {
-                            return $(item).data('value')
-                        })
-                    });
-                });
-                container.$element.on('hideFilter', function() {
-                    container.$dropdown.find('.select2-search').show();
-                    container.$dropdown.find('.select2-results').show();
-                    self.$Filter.hide();
-                });
-
-            }
-            // Decorate the dropdown+search with necessary containers
-            var adapter = Utils.Decorate(dropdownWithSearch, AttachContainer);
-            adapter = Utils.Decorate(adapter, AttachBody);
-
-            return adapter;
-        });
-
-    // For placeholder support 
-    if (!('placeholder' in HTMLInputElement.prototype)) {
-        var originalRender = Backbone.Marionette.LayoutView.prototype.render;
-        Backbone.Marionette.LayoutView.prototype.render = function() {
-            originalRender.apply(this, arguments);
-            this.$('input, textarea').placeholder();
-        }
-    }
 
     String.prototype.trunc = String.prototype.trunc ||
         function(n) {
diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js
index 327bbcc..0cec81d 100644
--- a/dashboardv2/public/js/utils/Utils.js
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -763,14 +763,5 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums',
             this.attr(attributeName, firstString);
         }
     }
-
-    $('body').on('click', 'pre.code-block .expand-collapse-button', function(e) {
-        var $el = $(this).parents('.code-block');
-        if ($el.hasClass('shrink')) {
-            $el.removeClass('shrink');
-        } else {
-            $el.addClass('shrink');
-        }
-    });
     return Utils;
 });
\ No newline at end of file
diff --git a/dashboardv2/public/js/views/common/Statistics.js b/dashboardv2/public/js/views/common/Statistics.js
index 11c5463..8a44ce6 100644
--- a/dashboardv2/public/js/views/common/Statistics.js
+++ b/dashboardv2/public/js/views/common/Statistics.js
@@ -70,8 +70,8 @@ define(['require',
                     success: function(data) {
                         var data = _.first(data.toJSON()),
                             no_records = '<tr class="empty text-center"><td colspan="2"><span>No records found!</span></td></tr>',
-                            activeEntityTable = _.isEmpty(data.entity.entityActive) ? no_records : CommonViewFunction.propertyTable({ scope: that, valueObject: data.entity.entityActive }),
-                            deleteEntityTable = _.isEmpty(data.entity.entityDeleted) ? no_records : CommonViewFunction.propertyTable({ scope: that, valueObject: data.entity.entityDeleted });
+                            activeEntityTable = _.isEmpty(data.entity.entityActive) ? no_records : CommonViewFunction.propertyTable({ scope: that, valueObject: data.entity.entityActive, numberFormat: _.numberFormatWithComa }),
+                            deleteEntityTable = _.isEmpty(data.entity.entityDeleted) ? no_records : CommonViewFunction.propertyTable({ scope: that, valueObject: data.entity.entityDeleted, numberFormat: _.numberFormatWithComa });
                         var totalActive = 0,
                             totalDeleted = 0;
                         if (data.entity && data.general.entityCount) {
@@ -84,8 +84,8 @@ define(['require',
                         }
                         that.ui.entityActive.html(activeEntityTable);
                         that.ui.entityDelete.html(deleteEntityTable);
-                        that.ui.entityActiveHeader.html("&nbsp;(" + (totalActive - totalDeleted) + ")");
-                        that.ui.entityDeletedHeader.html("&nbsp;(" + totalDeleted + ")");
+                        that.ui.entityActiveHeader.html("&nbsp;(" + _.numberFormatWithComa((totalActive - totalDeleted)) + ")");
+                        that.ui.entityDeletedHeader.html("&nbsp;(" + _.numberFormatWithComa(totalDeleted) + ")");
                     }
                 });
             }
diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
index f48ab99..53c484b 100644
--- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
+++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
@@ -390,7 +390,7 @@ define(['require',
                     val.entityGuid === that.id ? tag['self'].push(val) : tag['propagated'].push(val);
                 });
                 _.each(tag.self, function(val) {
-                    tagData += '<span class="btn btn-action btn-sm btn-icon btn-blue" title=' + val.typeName + ' data-id="tagClick"><span>' + val.typeName + '</span><i class="fa fa-close" data-id="deleteTag" data-type="tag" title="Remove Tag"></i></span>';
+                    tagData += '<span class="btn btn-action btn-sm btn-icon btn-blue" data-id="tagClick"><span title=' + val.typeName + ' >' + val.typeName + '</span><i class="fa fa-close" data-id="deleteTag" data-type="tag" title="Remove Tag"></i></span>';
                 });
                 _.each(tag.propagated, function(val) {
                     var crossButton = '<i class="fa fa-close" data-id="deleteTag" data-entityguid="' + val.entityGuid + '" data-type="tag" title="Remove Tag"></i>';
diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js b/dashboardv2/public/js/views/graph/LineageLayoutView.js
index 5ba2f2f..5a7262b 100644
--- a/dashboardv2/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv2/public/js/views/graph/LineageLayoutView.js
@@ -51,11 +51,20 @@ define(['require',
                 selectDepth: 'select[data-id="selectDepth"]',
                 fltrTogler: '[data-id="fltr-togler"]',
                 lineageFilterPanel: '.lineage-fltr-panel',
-                LineageFullscreenToggler: '[data-id="fullScreen-toggler"]',
+                lineageFullscreenToggler: '[data-id="fullScreen-toggler"]',
+                searchTogler: '[data-id="search-togler"]',
+                lineageSearchPanel: '.lineage-search-panel',
+                lineageTypeSearch: '[data-id="typeSearch"]',
                 lineageDetailClose: '[data-id="close"]',
+                searchNode: '[data-id="searchNode"]',
                 nodeEntityList: '[data-id="entityList"]'
             },
-
+            templateHelpers: function() {
+                return {
+                    width: "100%",
+                    height: "100%"
+                };
+            },
             /** ui events hash */
             events: function() {
                 var events = {};
@@ -63,7 +72,8 @@ define(['require',
                 events["click " + this.ui.checkDeletedEntity] = 'onCheckUnwantedEntity';
                 events['change ' + this.ui.selectDepth] = 'onSelectDepthChange';
                 events["click " + this.ui.fltrTogler] = 'onClickFiltrTogler';
-                events["click " + this.ui.LineageFullscreenToggler] = 'onClickLineageFullscreenToggler';
+                events["click " + this.ui.lineageFullscreenToggler] = 'onClickLineageFullscreenToggler';
+                events["click " + this.ui.searchTogler] = 'onClickSearchTogler';
                 events["click " + this.ui.lineageDetailClose] = function() {
                     this.toggleLineageInfomationSlider({ close: true });
                 };
@@ -87,6 +97,9 @@ define(['require',
                     isDeletedEntityHideCheck: false,
                     depthCount: ''
                 };
+                this.searchNodeObj = {
+                    selectedNode: ''
+                }
             },
 
             initializeGraph: function() {
@@ -156,7 +169,20 @@ define(['require',
             },
             onClickFiltrTogler: function() {
                 var lineageFilterPanel = this.ui.lineageFilterPanel;
+                var lineageSearchPanel = this.ui.lineageSearchPanel;
                 $(lineageFilterPanel).toggleClass("show-filter-panel");
+                if (lineageSearchPanel.hasClass('show-search-panel')) {
+                    $(this.ui.lineageSearchPanel).toggleClass("show-search-panel")
+                }
+            },
+            onClickSearchTogler: function() {
+                var lineageSearchPanel = this.ui.lineageSearchPanel;
+                var lineageFilterPanel = this.ui.lineageFilterPanel;
+                $(lineageSearchPanel).toggleClass("show-search-panel");
+                if (lineageFilterPanel.hasClass('show-filter-panel')) {
+                    $(this.ui.lineageFilterPanel).toggleClass("show-filter-panel");
+
+                }
             },
             onSelectDepthChange: function(e, options) {
                 this.initializeGraph();
@@ -344,6 +370,10 @@ define(['require',
                 if (this.asyncFetchCounter == 0) {
                     this.createGraph();
                 }
+                if (this.lineageData) {
+                    this.renderLineageTypeSearch();
+                    this.lineageTypeSearch()
+                }
             },
             checkForLineageOrImpactFlag: function(relations, guid) {
                 var that = this,
@@ -372,31 +402,28 @@ define(['require',
                     this.$('.lineage-edge-details').removeClass('open');
                 }
             },
-            setGraphZoomPositionCal: function(argument) {
-                var initialScale = 1.6,
-                    svgEl = this.$('svg'),
-                    scaleEl = this.$('svg').find('>g'),
-                    translateValue = [(this.$('svg').width() - this.g.graph().width * initialScale) / 2, (this.$('svg').height() - this.g.graph().height * initialScale) / 2]
-                if (_.keys(this.g._nodes).length > 15) {
-                    initialScale = 0;
-                    this.$('svg').addClass('noScale');
-                }
-                if (svgEl.parents('.panel.panel-fullscreen').length) {
-                    translateValue = [20, 20];
-                    if (svgEl.hasClass('noScale')) {
-                        if (!scaleEl.hasClass('scaleLinage')) {
-                            scaleEl.addClass('scaleLinage');
-                            initialScale = 1.6;
-                        } else {
-                            scaleEl.removeClass('scaleLinage');
-                            initialScale = 0;
-                        }
-                    }
-                } else {
-                    scaleEl.removeClass('scaleLinage');
-                }
-                this.zoom.translate(translateValue)
-                    .scale(initialScale);
+            centerNode: function(nodeID) {
+                var zoom = function() {
+                        svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
+                    },
+                    matrix = this.$('svg').find("g.nodes").find('>g#' + nodeID).attr('transform').replace(/[^0-9\-.,]/g, '').split(','),
+                    x = matrix[0],
+                    y = matrix[1],
+                    viewerWidth = this.$('svg').width(),
+                    viewerHeight = this.$('svg').height(),
+                    gBBox = d3.select('g').node().getBBox(),
+                    zoomListener = d3.behavior.zoom().scaleExtent([0.01, 50]).on("zoom", zoom),
+                    scale = 1.2,
+                    xa = -((x * scale) - (viewerWidth / 2)),
+                    ya = -((y * scale) - (viewerHeight / 2));
+
+                this.zoom.translate([xa, ya]);
+                d3.select('g').transition()
+                    .duration(350)
+                    .attr("transform", "translate(" + xa + "," + ya + ")scale(" + scale + ")");
+                zoomListener.scale(scale);
+                zoomListener.translate([xa, ya]);
+                this.zoom.scale(scale);
             },
             zoomed: function(that) {
                 this.$('svg').find('>g').attr("transform",
@@ -404,6 +431,18 @@ define(['require',
                     "scale(" + this.zoom.scale() + ")"
                 );
             },
+            interpolateZoom: function(translate, scale, that, zoom) {
+                return d3.transition().duration(350).tween("zoom", function() {
+                    var iTranslate = d3.interpolate(zoom.translate(), translate),
+                        iScale = d3.interpolate(zoom.scale(), scale);
+                    return function(t) {
+                        zoom
+                            .scale(iScale(t))
+                            .translate(iTranslate(t));
+                        that.zoomed();
+                    };
+                });
+            },
             createGraph: function() {
                 var that = this,
                     width = this.$('svg').width(),
@@ -442,7 +481,7 @@ define(['require',
                     var shapeSvg = parent.append('circle')
                         .attr('fill', 'url(#img_' + node.id + ')')
                         .attr('r', '24px')
-                        .attr('data-stroke',node.id)
+                        .attr('data-stroke', node.id)
                         .attr("class", "nodeImage " + (currentNode ? "currentNode" : (node.isProcess ? "process" : "node")));
 
                     parent.insert("defs")
@@ -481,31 +520,16 @@ define(['require',
                     .attr("enable-background", "new 0 0 " + width + " " + height),
                     svgGroup = svg.append("g");
                 var zoom = this.zoom = d3.behavior.zoom()
-                    .scaleExtent([0.5, 6])
+                    .center([width / 2, height / 2])
+                    .scaleExtent([0.01, 50])
                     .on("zoom", that.zoomed.bind(this));
 
-
-                function interpolateZoom(translate, scale) {
-                    var self = this;
-                    return d3.transition().duration(350).tween("zoom", function() {
-                        var iTranslate = d3.interpolate(zoom.translate(), translate),
-                            iScale = d3.interpolate(zoom.scale(), scale);
-                        return function(t) {
-                            zoom
-                                .scale(iScale(t))
-                                .translate(iTranslate(t));
-                            that.zoomed();
-                        };
-                    });
-                }
-
                 function zoomClick() {
                     var clicked = d3.event.target,
                         direction = 1,
-                        factor = 0.2,
+                        factor = 0.5,
                         target_zoom = 1,
-                        center = [that.g.graph().width / 2, that.g.graph().height / 2],
-                        extent = zoom.scaleExtent(),
+                        center = [width / 2, height / 2],
                         translate = zoom.translate(),
                         translate0 = [],
                         l = [],
@@ -515,10 +539,6 @@ define(['require',
                     direction = (this.id === 'zoom_in') ? 1 : -1;
                     target_zoom = zoom.scale() * (1 + factor * direction);
 
-                    if (target_zoom < extent[0] || target_zoom > extent[1]) {
-                        return false;
-                    }
-
                     translate0 = [(center[0] - view.x) / view.k, (center[1] - view.y) / view.k];
                     view.k = target_zoom;
                     l = [translate0[0] * view.k + view.x, translate0[1] * view.k + view.y];
@@ -526,7 +546,7 @@ define(['require',
                     view.x += center[0] - l[0];
                     view.y += center[1] - l[1];
 
-                    interpolateZoom([view.x, view.y], view.k);
+                    that.interpolateZoom([view.x, view.y], view.k, that, zoom);
                 }
                 d3.selectAll(this.$('.lineageZoomButton')).on('click', zoomClick);
                 var tooltip = d3Tip()
@@ -555,7 +575,7 @@ define(['require',
                 }
                 render(svgGroup, this.g);
                 svg.on("dblclick.zoom", null)
-                    .on("wheel.zoom", null);
+                // .on("wheel.zoom", null);
                 //change text postion 
                 svgGroup.selectAll("g.nodes g.label")
                     .attr("transform", "translate(2,-35)");
@@ -605,8 +625,8 @@ define(['require',
                     }).on('click', function(d) {
                         if (d3.event.defaultPrevented) return; // ignore drag
                         that.toggleLineageInfomationSlider({ open: true, obj: d });
-                        svgGroup.selectAll('[data-stroke]').attr('stroke','none');
-                        svgGroup.selectAll('[data-stroke]').attr('stroke',function(c) {
+                        svgGroup.selectAll('[data-stroke]').attr('stroke', 'none');
+                        svgGroup.selectAll('[data-stroke]').attr('stroke', function(c) {
                             if (c == d) {
                                 return "#316132";
                             } else {
@@ -639,7 +659,7 @@ define(['require',
                 });
 
                 // Center the graph
-                this.setGraphZoomPositionCal();
+                this.centerNode(that.guid);
                 zoom.event(svg);
                 //svg.attr('height', this.g.graph().height * initialScale + 40);
                 if (platform.name === "IE") {
@@ -660,6 +680,60 @@ define(['require',
                     });
                 }
             },
+            renderLineageTypeSearch: function() {
+                var that = this;
+                var lineageData = $.extend(true, {}, this.lineageData);
+                var data = [];
+
+                var typeStr = '<option></option>';
+                if (!_.isEmpty(lineageData)) {
+                    _.each(lineageData.guidEntityMap, function(obj, index) {
+                        typeStr += '<option value="' + obj.guid + '">' + obj.attributes.name + '</option>';
+                    });
+                }
+                that.ui.lineageTypeSearch.html(typeStr);
+            },
+            lineageTypeSearch: function() {
+                var that = this;
+                that.ui.lineageTypeSearch.select2({
+                    closeOnSelect: true,
+                    placeholder: 'Select Node'
+                }).on('change.select2', function(e) {
+                    e.stopPropagation();
+                    e.stopImmediatePropagation();
+                    d3.selectAll(".serach-rect").remove();
+                    var selectedNode = $('[data-id="typeSearch"]').val();
+                    that.searchNodeObj.selectedNode = $('[data-id="typeSearch"]').val();
+                    that.centerNode(selectedNode);
+
+                    that.svg.selectAll('.nodes g.label').attr('stroke', function(c, d) {
+                        if (c == selectedNode) {
+                            return "#316132";
+                        } else {
+                            return 'none';
+                        }
+                    });
+                    // Using jquery for selector because d3 select is not working for few process entities.
+                    d3.select($(".node#" + selectedNode)[0]).insert("rect", "circle")
+                        .attr("class", "serach-rect")
+                        .attr("x", -50)
+                        .attr("y", -27.5)
+                        .attr("width", 100)
+                        .attr("height", 55);
+                    d3.selectAll(".nodes circle").classed("wobble", function(d, i, nodes) {
+                        if (d == selectedNode) {
+                            return true;
+                        } else {
+                            return false;
+                        }
+                    });
+
+                });
+                if (that.searchNodeObj.selectedNode) {
+                    that.ui.lineageTypeSearch.val(that.searchNodeObj.selectedNode);
+                    that.ui.lineageTypeSearch.trigger("change.select2");
+                }
+            },
             toggleLineageInfomationSlider: function(options) {
                 if (options.open && !this.$('.lineage-details').hasClass("open")) {
                     this.$('.lineage-details').addClass('open');
diff --git a/dashboardv2/public/js/views/search/SearchLayoutView.js b/dashboardv2/public/js/views/search/SearchLayoutView.js
index 78d683d..2a0d995 100644
--- a/dashboardv2/public/js/views/search/SearchLayoutView.js
+++ b/dashboardv2/public/js/views/search/SearchLayoutView.js
@@ -465,11 +465,11 @@ define(['require',
                     var name = Utils.getName(model.toJSON(), 'name');
                     if (model.get('category') == 'ENTITY' && (serviceTypeToBefiltered && serviceTypeToBefiltered.length ? _.contains(serviceTypeToBefiltered, model.get('serviceType')) : true)) {
                         var entityCount = (that.entityCountObj.entity.entityActive[name] + (that.entityCountObj.entity.entityDeleted[name] ? that.entityCountObj.entity.entityDeleted[name] : 0));
-                        typeStr += '<option value="' + (name) + '" data-name="' + (name) + '">' + (name) + ' ' + (entityCount ? "(" + entityCount + ")" : '') + '</option>';
+                        typeStr += '<option value="' + (name) + '" data-name="' + (name) + '">' + (name) + ' ' + (entityCount ? "(" + _.numberFormatWithComa(entityCount) + ")" : '') + '</option>';
                     }
                     if (isTypeOnly == undefined && model.get('category') == 'CLASSIFICATION') {
                         var tagEntityCount = that.entityCountObj.tag.tagEntities[name];
-                        tagStr += '<option value="' + (name) + '" data-name="' + (name) + '">' + (name) + ' ' + (tagEntityCount ? "(" + tagEntityCount + ")" : '') + '</option>';
+                        tagStr += '<option value="' + (name) + '" data-name="' + (name) + '">' + (name) + ' ' + (tagEntityCount ? "(" + _.numberFormatWithComa(tagEntityCount) + ")" : '') + '</option>';
                     }
                 });
                 if (_.isUndefined(isTypeOnly)) {