http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/utils/TableLayout.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/TableLayout.js 
b/dashboardv2/public/js/utils/TableLayout.js
new file mode 100644
index 0000000..e513241
--- /dev/null
+++ b/dashboardv2/public/js/utils/TableLayout.js
@@ -0,0 +1,400 @@
+/**
+ * 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.
+ */
+
+ /**
+ * @file This is the common View file for displaying Table/Grid to be used 
overall in the application.
+ */
+define(['require',
+    'backbone',
+    'hbs!tmpl/common/TableLayout_tmpl',
+    'backgrid-filter',
+    'backgrid-paginator',
+    'backgrid-sizeable',
+    'backgrid-orderable'
+], function(require, Backbone, FSTablelayoutTmpl) {
+    'use strict';
+
+    var FSTableLayout = Backbone.Marionette.LayoutView.extend(
+        /** @lends FSTableLayout */
+        {
+            _viewName: 'FSTableLayout',
+
+            template: FSTablelayoutTmpl,
+
+            /** Layout sub regions */
+            regions: {
+                'rTableList': 'div[data-id="r_tableList"]',
+                'rTableSpinner': 'div[data-id="r_tableSpinner"]',
+                'rPagination': 'div[data-id="r_pagination"]',
+                'rFooterRecords': 'div[data-id="r_footerRecords"]'
+            },
+
+            // /** ui selector cache */
+            ui: {
+                selectPageSize: 'select[data-id="pageSize"]'
+            },
+
+            gridOpts: {
+                className: 'table table-bordered table-hover table-condensed 
backgrid',
+                emptyText: 'No Records found!'
+            },
+
+            /**
+             * Backgrid.Filter default options
+             */
+            filterOpts: {
+                placeholder: 'plcHldr.searchByResourcePath',
+                wait: 150
+            },
+
+            /**
+             * Paginator default options
+             */
+            paginatorOpts: {
+                // If you anticipate a large number of pages, you can adjust
+                // the number of page handles to show. The sliding window
+                // will automatically show the next set of page handles when
+                // you click next at the end of a window.
+                windowSize: 5, // Default is 10
+
+                // Used to multiple windowSize to yield a number of pages to 
slide,
+                // in the case the number is 5
+                slideScale: 0.5, // Default is 0.5
+
+                // Whether sorting should go back to the first page
+                goBackFirstOnSort: false // Default is true
+            },
+
+            /**
+               page handlers for pagination
+            */
+            controlOpts: {
+                rewind: {
+                    label: "《",
+                    title: "First"
+                },
+                back: {
+                    label: "〈",
+                    title: "Previous"
+                },
+                forward: {
+                    label: "〉",
+                    title: "Next"
+                },
+                fastForward: {
+                    label: "》",
+                    title: "Last"
+                }
+            },
+            columnOpts: {
+                initialColumnsVisible: 4,
+                // State settings
+                saveState: false,
+                loadStateOnInit: true
+            },
+
+            includePagination: true,
+
+            includeFilter: false,
+
+            includeHeaderSearch: false,
+
+            includePageSize: false,
+
+            includeFooterRecords: true,
+
+            includeColumnManager: false,
+
+            includeSizeAbleColumns: false,
+
+            includeOrderAbleColumns: false,
+
+
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events['change ' + this.ui.selectPageSize] = 
'onPageSizeChange';
+                return events;
+            },
+
+            /**
+             * intialize a new HDFSTableLayout Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'collection', 'columns', 
'includePagination',
+                    'includeHeaderSearch', 'includeFilter', 'includePageSize',
+                    'includeFooterRecords', 'includeColumnManager', 
'includeSizeAbleColumns', 'includeOrderAbleColumns'));
+
+                _.extend(this.gridOpts, options.gridOpts, { collection: 
this.collection, columns: this.columns });
+                _.extend(this.filterOpts, options.filterOpts);
+                _.extend(this.paginatorOpts, options.paginatorOpts);
+                _.extend(this.controlOpts, options.controlOpts);
+                _.extend(this.columnOpts, options.columnOpts);
+
+                this.bindEvents();
+            },
+
+            /** all events binding here */
+            bindEvents: function() {
+                this.listenTo(this.collection, 'request', function() {
+                    
this.$('div[data-id="r_tableSpinner"]').addClass('loading');
+                }, this);
+                this.listenTo(this.collection, 'sync error', function() {
+                    
this.$('div[data-id="r_tableSpinner"]').removeClass('loading');
+                }, this);
+
+                this.listenTo(this.collection, 'reset', function(collection, 
response) {
+                    if (this.includePagination) {
+                        this.renderPagination();
+                    }
+                    if (this.includeFooterRecords) {
+                        this.renderFooterRecords(this.collection.state);
+                    }
+                }, this);
+
+                /*This "sort" trigger event is fired when clicked on
+                'sortable' header cell (backgrid).
+                Collection.trigger event was fired because backgrid has
+                removeCellDirection function (backgrid.js - line no: 2088)
+                which is invoked when "sort" event is triggered
+                on collection (backgrid.js - line no: 2081).
+                removeCellDirection function - removes "ascending" and 
"descending"
+                which in turn removes chevrons from every 'sortable' 
header-cells*/
+                this.listenTo(this.collection, "backgrid:sort", function() {
+                    this.collection.trigger("sort");
+                });
+
+                /*this.listenTo(this.collection, 'remove', function(model, 
collection, response){
+                    if (model.isNew() || !this.includePagination) {
+                        return;
+                    }
+                    if (this.collection.state && 
this.collection.state.totalRecords>0) {
+                        this.collection.state.totalRecords-=1;
+                    }
+                    if (this.collection.length===0 && this.collection.state && 
this.collection.state.totalRecords>0) {
+
+                        if 
(this.collection.state.totalRecords>this.collection.state.currentPage*this.collection.state.pageSize)
 {
+                            this.collection.fetch({reset:true});
+                        } else {
+                            if (this.collection.state.currentPage>0) {
+                                this.collection.state.currentPage-=1;
+                                this.collection.fetch({reset:true});
+                            }
+                        }
+
+                    } else if (this.collection.length===0 && 
this.collection.state && this.collection.state.totalRecords===0) {
+                        this.collection.state.currentPage=0;
+                        this.collection.fetch({reset:true});
+                    }
+                }, this);*/
+
+                // It will show tool tip when td has ellipsis  Property
+                this.listenTo(this.collection, "backgrid:refresh", function() {
+                    /*this.$('.table td').bind('mouseenter', function() {
+                        var $this = $(this);
+                        if (this.offsetWidth < this.scrollWidth && 
!$this.attr('title')) {
+                            $this.attr('title', $this.text());
+                        }
+                    });*/
+                }, this);
+
+            },
+
+            /** on render callback */
+            onRender: function() {
+                this.renderTable();
+                if (this.includePagination) {
+                    this.renderPagination();
+                }
+                if (this.includeFilter) {
+                    this.renderFilter();
+                }
+                if (!this.includePageSize) {
+                    this.ui.selectPageSize.remove();
+                }
+                if (this.includeFooterRecords) {
+                    this.renderFooterRecords(this.collection.state);
+                }
+                if (this.includeColumnManager) {
+                    this.renderColumnManager();
+                }
+                if (this.includeSizeAbleColumns) {
+                    this.renderSizeAbleColumns();
+                }
+                if (this.includeOrderAbleColumns) {
+                    this.renderOrderAbleColumns();
+                }
+                
this.$('[data-id="pageSize"]').val(this.collection.state.pageSize);
+
+
+            },
+            /**
+             * show table
+             */
+            renderTable: function() {
+                var that = this;
+                this.rTableList.show(new Backgrid.Grid(this.gridOpts));
+            },
+
+            /**
+             * show pagination buttons(first, last, next, prev and numbers)
+             */
+            renderPagination: function() {
+                var options = _.extend({
+                    collection: this.collection,
+                    controls: this.controlOpts
+                }, this.paginatorOpts);
+
+                // TODO - Debug this part
+                if (this.rPagination) {
+                    this.rPagination.show(new 
Backgrid.Extension.Paginator(options));
+                } else if (this.regions.rPagination) {
+                    this.$('div[data-id="r_pagination"]').show(new 
Backgrid.Extension.Paginator(options));
+                }
+            },
+
+            /**
+             * show/hide pagination buttons of the grid
+             */
+            showHidePager: function() {
+
+                if (!this.includePagination) {
+                    return;
+                }
+
+                if (this.collection.state && 
this.collection.state.totalRecords > this.collection.state.pageSize) {
+                    this.$('div[data-id="r_pagination"]').show();
+                } else {
+                    this.$('div[data-id="r_pagination"]').hide();
+                }
+            },
+
+            /**
+             * show/hide filter of the grid
+             */
+            renderFilter: function() {
+                this.rFilter.show(new Backgrid.Extension.ServerSideFilter({
+                    collection: this.collection,
+                    name: ['name'],
+                    placeholder: 'plcHldr.searchByResourcePath',
+                    wait: 150
+                }));
+
+                setTimeout(function() {
+                    that.$('table').colResizable({ liveDrag: true });
+                }, 0);
+            },
+
+            /**
+             * show/hide footer details of the list/collection shown in the 
grid
+             */
+            renderFooterRecords: function(collectionState) {
+                var collState = collectionState;
+                var totalRecords = collState.totalRecords || 0;
+                var pageStartIndex = totalRecords ? (collState.currentPage * 
collState.pageSize) : 0;
+                var pageEndIndex = pageStartIndex + this.collection.length;
+
+                this.$('[data-id="r_footerRecords"]').html('Showing ' + 
(totalRecords ? pageStartIndex + 1 : 0) + ' to ' + pageEndIndex + ' of ' + 
totalRecords + ' entries');
+                return this;
+            },
+            /**
+             * ColumnManager for the table
+             */
+            renderColumnManager: function() {
+                var $el = this.$("[data-id='control']");
+                var colManager = new 
Backgrid.Extension.ColumnManager(this.columns, this.columnOpts);
+                // Add control
+                var colVisibilityControl = new 
Backgrid.Extension.ColumnManagerVisibilityControl({
+                    columnManager: colManager
+                });
+
+                $el.append(colVisibilityControl.render().el);
+            },
+
+            renderSizeAbleColumns: function() {
+                // Add sizeable columns
+                var sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({
+                    collection: this.collection,
+                    columns: this.columns,
+                    grid: this.getGridObj()
+                });
+                this.$('thead').before(sizeAbleCol.render().el);
+
+                // Add resize handlers
+                var sizeHandler = new 
Backgrid.Extension.SizeAbleColumnsHandlers({
+                    sizeAbleColumns: sizeAbleCol,
+                    grid: this.getGridObj(),
+                    saveModelWidth: true
+                });
+                this.$('thead').before(sizeHandler.render().el);
+
+                // Listen to resize events
+                this.columns.on('resize', function(columnModel, newWidth, 
oldWidth) {
+                    console.log('Resize event on column; name, model, new and 
old width: ', columnModel.get("name"), columnModel, newWidth, oldWidth);
+                });
+            },
+
+            renderOrderAbleColumns: function() {
+                // Add orderable columns
+                var sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({
+                    collection: this.collection,
+                    grid: this.getGridObj(),
+                    columns: this.columns
+                });
+                var orderHandler = new Backgrid.Extension.OrderableColumns({
+                    grid: this.getGridObj(),
+                    sizeAbleColumns: sizeAbleCol
+                });
+                this.$('thead').before(orderHandler.render().el);
+            },
+
+            /** on close */
+            onClose: function() {},
+
+            /**
+             * get the Backgrid object
+             * @return {null}
+             */
+            getGridObj: function() {
+                if (this.rTableList.currentView) {
+                    return this.rTableList.currentView;
+                }
+                return null;
+            },
+
+            /**
+             * handle change event on page size select box
+             * @param  {Object} e event
+             */
+            onPageSizeChange: function(e) {
+                var pagesize = $(e.currentTarget).val();
+                this.collection.state.pageSize = parseInt(pagesize, 10);
+
+                this.collection.state.currentPage = 
this.collection.state.firstPage;
+
+                this.collection.fetch({
+                    sort: false,
+                    reset: true,
+                    cache: false
+                });
+            }
+        });
+
+    return FSTableLayout;
+});

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/utils/Utils.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/Utils.js 
b/dashboardv2/public/js/utils/Utils.js
new file mode 100644
index 0000000..7b2db79
--- /dev/null
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -0,0 +1,187 @@
+/**
+ * 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.
+ */
+
+ define(['require', 'utils/Globals'], function(require, Globals) {
+    'use strict';
+
+    var Utils = {};
+    require(['noty'], function() {
+        $.extend($.noty.defaults, {
+            timeout: 5000,
+            layout: "topRight",
+            theme: "relax",
+            closeWith: ['click', 'button'],
+            animation: {
+                open: 'animated flipInX',
+                close: 'animated flipOutX',
+                easing: 'swing',
+                speed: 500
+            }
+        });
+    });
+    Utils.generateUUID = function() {
+        var d = new Date().getTime();
+        if (window.performance && typeof window.performance.now === 
"function") {
+            d += performance.now(); //use high-precision timer if available
+        }
+        var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, 
function(c) {
+            var r = (d + Math.random() * 16) % 16 | 0;
+            d = Math.floor(d / 16);
+            return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
+        });
+        return uuid;
+    };
+
+    Utils.notifyInfo = function(options) {
+        noty({
+            type: "information",
+            text: "<i class='fa fa-exclamation-circle'></i> " + 
(options.content || "Info message.")
+        });
+    };
+    Utils.notifyWarn = function(options) {
+        noty({
+            type: "warning",
+            text: "<i class='fa fa-times-circle'></i> " + (options.content || 
"Info message.")
+        });
+    };
+
+    Utils.notifyError = function(options) {
+        noty({
+            type: "error",
+            text: "<i class='fa fa-times-circle'></i> " + (options.content || 
"Error occurred.")
+        });
+    };
+
+    Utils.notifySuccess = function(options) {
+        noty({
+            type: "success",
+            text: "<i class='fa fa-check-circle-o'></i> " + (options.content 
|| "Error occurred.")
+        });
+    };
+    Utils.defaultErrorHandler = function(model, error) {
+        /*
+                require(['views/common/ErrorView', 'App'], function(vError, 
App) {
+                    if (error.status == 404) {
+                        App.rContent.show(new vError({
+                            status: error.status
+                        }));
+                    } else if (error.status == 401) {
+                        App.rContent.show(new vError({
+                            status: error.status
+                        }));
+                    } else if (error.status == 419) {
+                        window.location = 'login.jsp'
+                    } else if (error.status == "0") {
+                        var diffTime = (new Date().getTime() - 
prevNetworkErrorTime);
+                        if (diffTime > 3000) {
+                            prevNetworkErrorTime = new Date().getTime();
+                            Utils.notifyError({
+                                content: "Network Connection Failure : " +
+                                    "It seems you are not connected to the 
internet. Please check your internet connection and try again"
+                            })
+
+                        }
+                    }
+                });
+            */
+    };
+
+    Utils.localStorage = {
+        checkLocalStorage: function(key, value) {
+            if (typeof(Storage) !== "undefined") {
+                return this.getLocalStorage(key, value);
+            } else {
+                console.log('Sorry! No Web Storage support');
+                Utils.cookie.checkCookie(key, value);
+            }
+        },
+        setLocalStorage: function(key, value) {
+            localStorage.setItem(key, value);
+            return { found: false, 'value': value };
+        },
+        getLocalStorage: function(key, value) {
+            var keyValue = localStorage.getItem(key)
+            if (!keyValue || keyValue == "undefined") {
+                return this.setLocalStorage(key, value);
+            } else {
+                return { found: true, 'value': keyValue };
+            }
+        }
+    }
+    Utils.cookie = {
+        setCookie: function(cname, cvalue) {
+            //var d = new Date();
+            //d.setTime(d.getTime() + (exdays*24*60*60*1000));
+            //var expires = "expires=" + d.toGMTString();
+            document.cookie = cname + "=" + cvalue + "; "
+            return { found: false, 'value': cvalue };
+        },
+        getCookie: function(findString) {
+            var search = findString + "=";
+            var ca = document.cookie.split(';');
+            for (var i = 0; i < ca.length; i++) {
+                var c = ca[i];
+                while (c.charAt(0) == ' ') c = c.substring(1);
+                if (c.indexOf(name) == 0) {
+                    return c.substring(name.length, c.length);
+                }
+            }
+            return "";
+        },
+        checkCookie: function(key, value) {
+            var findString = getCookie(key);
+            if (findString != "" || keyValue != "undefined") {
+                return { found: true, 'value': ((findString == "undefined") ? 
(undefined) : (findString)) };
+            } else {
+                return setCookie(key, value);
+            }
+        }
+    }
+    Utils.getQueryParams = function(qs) {
+        qs = qs.split('+').join(' ');
+        var params = {},
+            tokens,
+            re = /[?&]?([^=]+)=([^&]*)/g;
+        while (tokens = re.exec(qs)) {
+            params[decodeURIComponent(tokens[1])] = 
decodeURIComponent(tokens[2]);
+        }
+        return params;
+    }
+
+    Utils.setUrl = function(options) {
+        if (options) {
+            if (options.mergeBrowserUrl) {
+                var hashUrl = window.location.hash.split("?");
+                if (hashUrl.length > 1) {
+                    var param = Utils.getQueryParams(hashUrl[1]);
+                    options.urlParams = _.extend(param, options.urlParams)
+                }
+            }
+            if (options.urlParams) {
+                var urlParams = "?"
+                _.each(options.urlParams, function(value, key, obj) {
+                    urlParams += key + "=" + value + "&";
+                });
+                urlParams = urlParams.slice(0, -1);
+                options.url += urlParams;
+            }
+            Backbone.history.navigate(options.url, { trigger: options.trigger 
!= undefined ? options.trigger : true });
+        }
+    }
+    return Utils;
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/views/asset/AssetPageLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/asset/AssetPageLayoutView.js 
b/dashboardv2/public/js/views/asset/AssetPageLayoutView.js
new file mode 100644
index 0000000..c86fef4
--- /dev/null
+++ b/dashboardv2/public/js/views/asset/AssetPageLayoutView.js
@@ -0,0 +1,416 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/asset/AssetPageLayoutView_tmpl',
+    'modules/Modal',
+    'models/VEntity',
+    'utils/Utils',
+    'utils/Globals',
+], function(require, Backbone, AssetPageLayoutViewTmpl, Modal, VEntity, Utils, 
Globals) {
+    'use strict';
+
+    var AssetPageLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends AssetPageLayoutView */
+        {
+            _viewName: 'AssetPageLayoutView',
+
+            template: AssetPageLayoutViewTmpl,
+
+            /** Layout sub regions */
+            regions: {
+                RTagLayoutView: "#r_tagLayoutView",
+                RSearchLayoutView: "#r_searchLayoutView",
+                REntityTableLayoutView: "#r_entityTableLayoutView",
+            },
+
+            /** ui selector cache */
+            ui: {
+                tagClick: '[data-id="tagClick"]',
+                addTag: '[data-id="addTag"]',
+            },
+
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                events["click " + this.ui.tagClick] = function(e) {
+                    if (e.target.nodeName.toLocaleLowerCase() == "i") {
+                        this.onClickTagCross(e);
+                    } else {
+                        Utils.setUrl({
+                            url: '#!/dashboard/assetPage',
+                            urlParams: {
+                                query: e.currentTarget.text
+                            },
+                            mergeBrowserUrl: true,
+                            trigger: false
+                        });
+                        this.vent.trigger("tag:click", { 'query': 
e.currentTarget.text });
+                    }
+                };
+                events["click " + this.ui.addTag] = function(e) {
+                    this.addModalView(e);
+                };
+                events["click " + this.ui.tagCrossIcon] = function(e) {};
+                return events;
+            },
+            /**
+             * intialize a new AssetPageLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'globalVent', 'collection', 
'vent'));
+                this.entityModel = new VEntity();
+                this.searchCollection = this.collection;
+                this.fetchList = 0
+                this.commonTableOptions = {
+                    collection: this.searchCollection,
+                    includeFilter: false,
+                    includePagination: true,
+                    includePageSize: false,
+                    includeFooterRecords: true,
+                    includeSizeAbleColumns: false,
+                    gridOpts: {
+                        emptyText: 'No Record found!',
+                        className: 'table table-bordered table-hover 
table-condensed backgrid table-quickMenu'
+                    },
+                    filterOpts: {},
+                    paginatorOpts: {}
+                };
+
+            },
+            bindEvents: function() {
+                this.listenTo(this.vent, "search:click", function(value) {
+                    this.fetchCollection(value);
+                    this.REntityTableLayoutView.reset();
+                }, this);
+                this.listenTo(this.searchCollection, "reset", function(value) {
+                    this.renderTableLayoutView();
+                }, this);
+                this.listenTo(this.searchCollection, "error", function(value) {
+                    this.$('.fontLoader').hide();
+                    this.$('.entityTable').show();
+                    Utils.notifyError({
+                        content: "Invalid expression"
+                    });
+                }, this);
+            },
+            onRender: function() {
+                this.renderTagLayoutView();
+                this.renderSearchLayoutView();
+                this.renderTableLayoutView();
+                this.bindEvents();
+            },
+            fetchCollection: function(value) {
+                this.$('.fontLoader').show();
+                this.$('.entityTable').hide();
+                if (value) {
+                    if (value.type) {
+                        this.searchCollection.url = 
"/api/atlas/discovery/search/" + value.type;
+                    }
+                    $.extend(this.searchCollection.queryParams, { 'query': 
value.query });
+                }
+                this.searchCollection.fetch({ reset: true });
+            },
+            renderTagLayoutView: function() {
+                var that = this;
+                require(['views/tag/TagLayoutView'], function(TagLayoutView) {
+                    that.RTagLayoutView.show(new TagLayoutView({
+                        globalVent: that.globalVent,
+                        vent: that.vent
+                    }));
+                });
+            },
+            renderSearchLayoutView: function() {
+                var that = this;
+                require(['views/search/SearchLayoutView'], 
function(SearchLayoutView) {
+                    that.RSearchLayoutView.show(new SearchLayoutView({
+                        globalVent: that.globalVent,
+                        vent: that.vent
+                    }));
+                    var hashUrl = window.location.hash.split("?");
+                    if (hashUrl.length > 1) {
+                        var param = Utils.getQueryParams(hashUrl[1]);
+                        if (param) {
+                            var type = param.searchType;
+                            var query = param.query;
+                            that.vent.trigger("tag:click", { 'query': query, 
'searchType': type });
+                        }
+                    }
+                });
+            },
+            renderTableLayoutView: function() {
+                var that = this,
+                    count = 4;
+                require(['utils/TableLayout'], function(TableLayout) {
+                    var columnCollection = Backgrid.Columns.extend({
+                        sortKey: "position",
+                        comparator: function(item) {
+                            return item.get(this.sortKey) || 999;
+                        },
+                        setPositions: function() {
+                            _.each(this.models, function(model, index) {
+                                if (model.get('name') == "name") {
+                                    model.set("position", 1, { silent: true });
+                                } else if (model.get('name') == "description") 
{
+                                    model.set("position", 2, { silent: true });
+                                } else if (model.get('name') == "owner") {
+                                    model.set("position", 3, { silent: true });
+                                } else if (model.get('name') == "createTime") {
+                                    model.set("position", 4, { silent: true });
+                                } else {
+                                    model.set("position", ++count, { silent: 
true });
+                                }
+                            });
+                            return this;
+                        }
+                    });
+                    var columns = new 
columnCollection(that.getEntityTableColumns());
+                    columns.setPositions().sort();
+                    that.REntityTableLayoutView.show(new 
TableLayout(_.extend({}, that.commonTableOptions, {
+                        globalVent: that.globalVent,
+                        columns: columns,
+                        includeOrderAbleColumns: true
+                    })));
+                    if (that.fetchList <= 0) {
+                        that.$('.fontLoader').hide();
+                        that.$('.entityTable').show();
+                    }
+                });
+
+            },
+            getEntityTableColumns: function() {
+                var that = this,
+                    col = {};
+                var responseData = this.searchCollection.responseData;
+                if (this.searchCollection.responseData) {
+                    if (responseData.dataType) {
+                        if (responseData.dataType.attributeDefinitions.length 
== 2 && responseData.dataType.attributeDefinitions[1].name == "instanceInfo") {
+                            return this.getFixedColumn();
+                        } else {
+                            var modelJSON = this.searchCollection.toJSON()[0];
+                            _.keys(modelJSON).map(function(key) {
+                                if (key.indexOf("$") == -1 && typeof 
modelJSON[key] != "object") {
+                                    if (typeof modelJSON[key] == "string" || 
typeof modelJSON[key] == "number") {
+                                        if (typeof modelJSON[key] == "number" 
&& key != "createTime") {
+                                            return;
+                                        }
+                                        col[key] = {
+                                            cell: (key == "name") ? ("Html") : 
("String"),
+                                            editable: false,
+                                            sortable: false,
+                                            orderable: true,
+                                            formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                                fromRaw: function(rawValue, 
model) {
+                                                    if 
(model.get('createTime') == rawValue) {
+                                                        return new 
Date(rawValue);
+                                                    }
+                                                    if (model.get('name') == 
rawValue) {
+                                                        if (model.get('$id$')) 
{
+                                                            return '<a 
href="#!/dashboard/detailPage/' + model.get('$id$').id + '">' + rawValue + 
'</a>';
+                                                        } else {
+                                                            return '<a>' + 
rawValue + '</a>';
+                                                        }
+                                                    } else {
+                                                        return rawValue;
+                                                    }
+                                                }
+                                            })
+                                        };
+                                    }
+                                }
+                            });
+                            col['tag'] = {
+                                label: "Tags",
+                                cell: "Html",
+                                editable: false,
+                                sortable: false,
+                                orderable: true,
+                                formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                    fromRaw: function(rawValue, model) {
+                                        var traits = model.get('$traits$');
+                                        var atags = "";
+                                        
_.keys(model.get('$traits$')).map(function(key) {
+                                            atags += '<a data-id="tagClick">' 
+ traits[key].$typeName$ + '<i class="fa fa-times" data-id="delete" 
data-name="' + traits[key].$typeName$ + '" data-guid="' + model.get('$id$').id 
+ '" ></i></a>';
+                                        });
+                                        return '<div class="tagList">' + atags 
+ '</div>';
+                                    }
+                                })
+                            };
+                            col['addTag'] = {
+                                label: "Tools",
+                                cell: "Html",
+                                editable: false,
+                                sortable: false,
+                                orderable: true,
+                                formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                                    fromRaw: function(rawValue, model) {
+                                        if (model.get('$id$')) {
+                                            return '<a 
href="javascript:void(0)" data-id="addTag" class="addTagGuid" data-guid="' + 
model.get('$id$').id + '" ><i class="fa fa-tag"></i></a>';
+                                        } else {
+                                            return '<a 
href="javascript:void(0)" data-id="addTag"><i class="fa fa-tag"></i></a>';
+
+                                        }
+                                    }
+                                })
+                            };
+                            return 
this.searchCollection.constructor.getTableCols(col, this.searchCollection);
+                        }
+                    } else {
+                        return this.getFixedColumn();
+                    }
+                }
+            },
+            getFixedColumn: function() {
+                var that = this;
+                return this.searchCollection.constructor.getTableCols({
+                    instanceInfo: {
+                        label: "Type Name",
+                        cell: "html",
+                        editable: false,
+                        sortable: false,
+                        formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                var modelObject = model.toJSON();
+                                if (modelObject.$typeName$ && 
modelObject.instanceInfo) {
+                                    return '<a href="#!/dashboard/detailPage/' 
+ modelObject.instanceInfo.guid + '">' + modelObject.instanceInfo.typeName + 
'</a>';
+                                } else if (!modelObject.$typeName$) {
+                                    return '<a href="#!/dashboard/detailPage/' 
+ modelObject.guid + '">' + modelObject.typeName + '</a>';
+                                }
+                            }
+                        })
+                    },
+                    name: {
+                        label: "Name",
+                        cell: "html",
+                        editable: false,
+                        sortable: false,
+                        formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                var modelObject = model.toJSON();
+                                if (modelObject.$typeName$ && 
modelObject.instanceInfo) {
+                                    var guid = 
model.toJSON().instanceInfo.guid;
+                                    ++that.fetchList
+                                    model.getEntity(guid, {
+                                        beforeSend: function() {},
+                                        success: function(data) {
+                                            --that.fetchList
+                                            if (that.fetchList <= 0) {
+                                                that.$('.fontLoader').hide();
+                                                that.$('.entityTable').show();
+
+                                            }
+                                            if (data.definition && 
data.definition.values && data.definition.values.name) {
+                                                return that.$('td a[data-id="' 
+ guid + '"]').html(data.definition.values.name);
+                                            } else {
+                                                return that.$('td a[data-id="' 
+ guid + '"]').html(data.definition.id.id);
+                                            }
+                                        },
+                                        error: function(error, data, status) {
+                                            that.$('.fontLoader').hide();
+                                            that.$('.entityTable').show();
+                                        },
+                                        complete: function() {}
+                                    });
+                                    return '<a href="#!/dashboard/detailPage/' 
+ guid + '" data-id="' + guid + '"></a>';
+                                } else if (!modelObject.$typeName$) {
+                                    var guid = model.toJSON().guid;
+                                    ++that.fetchList
+                                    model.getEntity(guid, {
+                                        beforeSend: function() {},
+                                        success: function(data) {
+                                            --that.fetchList
+                                            if (that.fetchList <= 0) {
+                                                that.$('.fontLoader').hide();
+                                                that.$('.entityTable').show();
+                                            }
+                                            if (data.definition && 
data.definition.values && data.definition.values.name) {
+                                                return that.$('td a[data-id="' 
+ guid + '"]').html(data.definition.values.name);
+                                            } else {
+                                                return that.$('td a[data-id="' 
+ guid + '"]').html(data.definition.id.id);
+                                            }
+                                        },
+                                        error: function(error, data, status) {
+                                            that.$('.fontLoader').hide();
+                                            that.$('.entityTable').show();
+                                        },
+                                        complete: function() {}
+                                    });
+                                    return '<a href="#!/dashboard/detailPage/' 
+ guid + '" data-id="' + guid + '"></a>';
+                                }
+                            }
+                        })
+                    }
+                }, this.searchCollection);
+            },
+            addModalView: function(e) {
+                var that = this;
+                require(['views/tag/addTagModalView'], 
function(addTagModalView) {
+                    var view = new addTagModalView({
+                        vent: that.vent,
+                        guid: that.$(e.currentTarget).data("guid"),
+                        modalCollection: that.searchCollection
+                    });
+                    // view.saveTagData = function() {
+                    //override saveTagData function 
+                    // }
+                });
+            },
+            onClickTagCross: function(e) {
+                var tagName = $(e.target).data("name");
+                var that = this;
+                require([
+                    'modules/Modal'
+                ], function(Modal) {
+                    var modal = new Modal({
+                        title: 'Are you sure you want to delete ?',
+                        okText: 'Delete',
+                        htmlContent: "<b>Tag: " + tagName + "</b>",
+                        cancelText: "Cancel",
+                        allowCancel: true,
+                        okCloses: true,
+                        showFooter: true,
+                    }).open();
+                    modal.on('ok', function() {
+                        that.deleteTagData(e);
+                    });
+                    modal.on('closeModal', function() {
+                        modal.trigger('cancel');
+                    });
+                });
+            },
+            deleteTagData: function(e) {
+                var that = this,
+                    tagName = $(e.target).data("name");
+                var guid = $(e.target).data("guid");
+                require(['models/VTag'], function(VTag) {
+                    var tagModel = new VTag();
+                    tagModel.deleteTag(guid, tagName, {
+                        beforeSend: function() {},
+                        success: function(data) {
+                            that.searchCollection.fetch({ reset: true });
+                        },
+                        error: function(error, data, status) {},
+                        complete: function() {}
+                    });
+                });
+            }
+        });
+    return AssetPageLayoutView;
+});

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/views/common/BackgridHeader.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/common/BackgridHeader.js 
b/dashboardv2/public/js/views/common/BackgridHeader.js
new file mode 100644
index 0000000..b8c5ddb
--- /dev/null
+++ b/dashboardv2/public/js/views/common/BackgridHeader.js
@@ -0,0 +1,267 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'underscore',
+    'utils/Utils',
+    'utils/Globals',
+    'backgrid-filter',
+    'backgrid-paginator',
+    'select2',
+], function(require, Backbone, _, Utils) {
+    'use strict';
+
+    var HeaderSearchCell = Backbone.View.extend({
+
+        tagName: 'td',
+
+        className: 'backgrid-filter',
+
+        template: _.template('<input type="search" <% if (placeholder) { %> 
placeholder="<%- placeholder %>" <% } %> name="<%- name %>" <% if (style) { %> 
style="<%- style %>" <% } %> />'),
+        //<a class='clear' href='#'>&times;</a>'),
+
+        placeholder: '',
+
+        events: {
+            'keyup input': 'evKeyUp',
+            'submit': 'search'
+        },
+
+        initialize: function(options) {
+            _.extend(this, _.pick(options, 'column'));
+            this.name = this.column.get('name');
+            if (this.column.get('reName') !== undefined)
+                this.name = this.column.get('reName');
+
+            var collection = this.collection,
+                self = this;
+            if (Backbone.PageableCollection && collection instanceof 
Backbone.PageableCollection) {
+                collection.queryParams[this.name] = function() {
+                    return self.searchBox().val() || null;
+                };
+            }
+        },
+
+        render: function() {
+            this.$el.empty().append(this.template({
+                name: this.column.get('name'),
+                placeholder: this.column.get('placeholder') || 'Search',
+                style: this.column.get('headerSearchStyle')
+            }));
+            this.$el.addClass('renderable');
+            this.delegateEvents();
+            return this;
+
+        },
+
+        evKeyUp: function(e) {
+            var $clearButton = this.clearButton();
+            var searchTerms = this.searchBox().val();
+
+            if (!e.shiftKey) {
+                this.search();
+            }
+
+            if (searchTerms) {
+                $clearButton.show();
+            } else {
+                $clearButton.hide();
+            }
+        },
+
+        searchBox: function() {
+            return this.$el.find('input[type=search]');
+        },
+
+        clearButton: function() {
+            return this.$el.find('.clear');
+        },
+
+        search: function() {
+            var data = {};
+            // go back to the first page on search
+            var collection = this.collection;
+            if (Backbone.PageableCollection &&
+                collection instanceof Backbone.PageableCollection &&
+                collection.mode === 'server') {
+                collection.state.currentPage = collection.state.firstPage;
+            }
+            var query = this.searchBox().val();
+            if (query) data[this.name] = query;
+            if (collection.extraSearchParams) {
+                _.extend(data, collection.extraSearchParams);
+            }
+            if (collection.mode === 'server') {
+                collection.fetch({
+                    data: data,
+                    reset: true,
+                    success: function() {},
+                    error: function(msResponse) {
+                        Utils.notifyError('Error', 'Invalid input data!');
+                    }
+                });
+            } else if (collection.mode === 'client') {
+
+            }
+        },
+
+        clear: function(e) {
+            if (e) e.preventDefault();
+            this.searchBox().val(null);
+            this.collection.fetch({
+                reset: true
+            });
+        }
+    });
+
+    var HeaderFilterCell = Backbone.View.extend({
+
+        tagName: 'td',
+
+        className: 'backgrid-filter',
+
+        template: _.template('<select >  <option>ALL</option>' +
+            '<% _.each(list, function(data) {' +
+            'if(_.isObject(data)){ %>' +
+            '<option value="<%= data.value %>"><%= data.label %></option>' +
+            '<% }else{ %>' +
+            '<option value="<%= data %>"><%= data %></option>' +
+            '<% } %>' +
+            '<% }); %></select>'),
+
+        placeholder: '',
+        events: {
+            'click': function() {},
+        },
+        initialize: function(options) {
+            _.extend(this, _.pick(options, 'column'));
+            this.name = this.column.get('name');
+            this.headerFilterOptions = this.column.get('headerFilterOptions');
+        },
+        render: function() {
+            var that = this;
+            this.$el.empty().append(this.template({
+                name: this.column.get('name'),
+                list: this.headerFilterOptions.filterList,
+            }));
+
+            this.$el.find('select').select2({
+                allowClear: true,
+                closeOnSelect: false,
+                width: this.headerFilterOptions.filterWidth || '100%',
+                height: this.headerFilterOptions.filterHeight || '20px',
+            });
+
+            this.$el.addClass('renderable');
+
+            this.$el.find('select').on('click', function(e) {
+                that.search(e.currentTarget.value);
+            });
+            return this;
+        },
+        search: function(selectedOptionValue) {
+            var data = {},
+                query;
+            // go back to the first page on search
+            var collection = this.collection;
+            if (Backbone.PageableCollection &&
+                collection instanceof Backbone.PageableCollection &&
+                collection.mode === 'server') {
+                collection.state.currentPage = collection.state.firstPage;
+            }
+            if (selectedOptionValue !== 'ALL') {
+                query = selectedOptionValue;
+            }
+            if (query) {
+                data[this.name] = query;
+            }
+            if (collection.extraSearchParams) {
+                _.extend(data, collection.extraSearchParams);
+            }
+            collection.fetch({
+                data: data,
+                reset: true
+            });
+        },
+        /*clear: function (e) {
+            if (e) e.preventDefault();
+            this.searchBox().val(null);
+            this.collection.fetch({reset: true});
+        }*/
+    });
+    var HeaderRow = Backgrid.Row.extend({
+        requiredOptions: ['columns', 'collection'],
+
+        initialize: function() {
+            Backgrid.Row.prototype.initialize.apply(this, arguments);
+        },
+        makeCell: function(column, options) {
+            var headerCell;
+            switch (true) {
+                case (column.has('canHeaderSearch') && 
column.get('canHeaderSearch') === true):
+                    headerCell = new HeaderSearchCell({
+                        column: column,
+                        collection: this.collection,
+                    });
+                    break;
+                case (column.has('canHeaderFilter') && 
column.get('canHeaderFilter') === true):
+                    headerCell = new HeaderFilterCell({
+                        column: column,
+                        collection: this.collection,
+                    });
+                    break;
+                default:
+                    headerCell = new Backbone.View({
+                        tagName: 'td'
+                    });
+            }
+            return headerCell;
+        }
+    });
+    var Header = Backgrid.Header.extend({
+
+        initialize: function(options) {
+            var args = Array.prototype.slice.apply(arguments);
+            Backgrid.Header.prototype.initialize.apply(this, args);
+
+            this.searchRow = new HeaderRow({
+                columns: this.columns,
+                collection: this.collection
+            });
+        },
+        /**
+          Renders this table head with a single row of header cells.
+          */
+        render: function() {
+            var args = Array.prototype.slice.apply(arguments);
+            Backgrid.Header.prototype.render.apply(this, args);
+
+            this.$el.append(this.searchRow.render().$el);
+            return this;
+        },
+        remove: function() {
+            var args = Array.prototype.slice.apply(arguments);
+            Backgrid.Header.prototype.remove.apply(this, args);
+
+            this.searchRow.remove.apply(this.searchRow, arguments);
+            return Backbone.View.prototype.remove.apply(this, arguments);
+        }
+    });
+    return Header;
+});

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js 
b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
new file mode 100644
index 0000000..87adec0
--- /dev/null
+++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
@@ -0,0 +1,195 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/detail_page/DetailPageLayoutView_tmpl'
+], function(require, Backbone, DetailPageLayoutViewTmpl) {
+    'use strict';
+
+    var DetailPageLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends DetailPageLayoutView */
+        {
+            _viewName: 'DetailPageLayoutView',
+
+            template: DetailPageLayoutViewTmpl,
+
+            /** Layout sub regions */
+            regions: {
+                REntityDetailTableLayoutView: "#r_entityDetailTableLayoutView",
+                RSchemaTableLayoutView: "#r_schemaTableLayoutView",
+                RTagTableLayoutView: "#r_tagTableLayoutView",
+                RLineageLayoutView: "#r_lineageLayoutView",
+            },
+            /** ui selector cache */
+            ui: {},
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                return events;
+            },
+            /**
+             * intialize a new DetailPageLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'globalVent', 'collection', 
'vent'));
+                this.bindEvents();
+                this.commonTableOptions = {
+                    collection: this.collection,
+                    includeFilter: false,
+                    includePagination: false,
+                    includePageSize: false,
+                    includeFooterRecords: true,
+                    gridOpts: {
+                        className: "table table-striped table-condensed 
backgrid table-quickMenu",
+                        emptyText: 'No records found!'
+                    },
+                    filterOpts: {},
+                    paginatorOpts: {}
+                };
+            },
+            bindEvents: function() {
+                this.listenTo(this.collection, 'reset', function() {
+                    var collectionJSON = this.collection.toJSON();
+                    if (collectionJSON[0].id && collectionJSON[0].id.id) {
+                        var tagGuid = collectionJSON[0].id.id;
+                    }
+                    if (collectionJSON && collectionJSON.length) {
+                        if (collectionJSON[0].values) {
+                            this.name = collectionJSON[0].values.name;
+                            this.description = 
collectionJSON[0].values.description;
+                            if (this.name) {
+                                this.$('.breadcrumbName').text(this.name);
+                                this.$('.name').show();
+                                this.$('.name').html('<strong>Name: 
</strong><span>' + this.name + '</span>');
+                            } else {
+                                this.$('.name').hide();
+                            }
+                            if (this.description) {
+                                this.$('.description').show();
+                                
this.$('.description').html('<strong>Description: </strong><span>' + 
this.description + '</span>');
+                            } else {
+                                this.$('.description').hide();
+                            }
+                        }
+                    }
+                    this.renderEntityDetailTableLayoutView();
+                    this.renderTagTableLayoutView(tagGuid);
+                    this.renderLineageLayoutView(tagGuid);
+                    this.renderSchemaLayoutView();
+                }, this);
+            },
+            onRender: function() {},
+            renderEntityDetailTableLayoutView: function() {
+                var that = this;
+                require(['views/entity/EntityDetailTableLayoutView'], 
function(EntityDetailTableLayoutView) {
+                    that.REntityDetailTableLayoutView.show(new 
EntityDetailTableLayoutView({
+                        globalVent: that.globalVent,
+                        collection: that.collection
+                    }));
+                });
+            },
+            renderTagTableLayoutView: function(tagGuid) {
+                var that = this;
+                require(['views/tag/TagDetailTableLayoutView'], 
function(TagDetailTableLayoutView) {
+                    that.RTagTableLayoutView.show(new 
TagDetailTableLayoutView({
+                        globalVent: that.globalVent,
+                        collection: that.collection,
+                        guid: tagGuid
+                    }));
+                });
+            },
+            renderLineageLayoutView: function(tagGuid) {
+                var that = this;
+                require(['views/graph/LineageLayoutView'], 
function(LineageLayoutView) {
+                    that.RLineageLayoutView.show(new LineageLayoutView({
+                        globalVent: that.globalVent,
+                        assetName: that.name,
+                        guid: tagGuid
+                    }));
+                });
+            },
+            renderSchemaLayoutView: function() {
+                var that = this;
+                require(['views/schema/SchemaLayoutView'], 
function(SchemaLayoutView) {
+                    that.RSchemaTableLayoutView.show(new SchemaLayoutView({
+                        globalVent: that.globalVent,
+                        name: that.name,
+                        vent: that.vent
+                    }));
+                });
+            },
+            getTagTableColumns: function() {
+                var that = this;
+                return this.collection.constructor.getTableCols({
+                    tag: {
+                        label: "Tag",
+                        cell: "html",
+                        editable: false,
+                        sortable: false,
+                        formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                var modelObject = model.toJSON();
+                                if (modelObject.$typeName$ && 
modelObject.instanceInfo) {
+                                    return '<a href="#!/dashboard/detailPage/' 
+ modelObject.instanceInfo.guid + '">' + modelObject.instanceInfo.typeName + 
'</a>';
+                                } else if (!modelObject.$typeName$) {
+                                    return '<a href="#!/dashboard/detailPage/' 
+ modelObject.guid + '">' + modelObject.typeName + '</a>';
+                                }
+                            }
+                        })
+                    },
+                    attributes: {
+                        label: "Attributes",
+                        cell: "html",
+                        editable: false,
+                        sortable: false,
+                        formatter: _.extend({}, 
Backgrid.CellFormatter.prototype, {
+                            fromRaw: function(rawValue, model) {
+                                var modelObject = model.toJSON();
+                                if (modelObject.$typeName$ && 
modelObject.instanceInfo) {
+                                    var guid = 
model.toJSON().instanceInfo.guid;
+                                    model.getEntity(guid, {
+                                        beforeSend: function() {},
+                                        success: function(data) {
+                                            return that.$('td a[data-id="' + 
guid + '"]').html(data.definition.values.name);
+                                        },
+                                        error: function(error, data, status) 
{},
+                                        complete: function() {}
+                                    });
+                                    return '<a href="#!/dashboard/detailPage/' 
+ guid + '" data-id="' + guid + '"></a>';
+                                } else if (!modelObject.$typeName$) {
+                                    var guid = model.toJSON().guid;
+                                    model.getEntity(guid, {
+                                        beforeSend: function() {},
+                                        success: function(data) {
+                                            return that.$('td a[data-id="' + 
guid + '"]').html(data.definition.values.name);
+                                        },
+                                        error: function(error, data, status) 
{},
+                                        complete: function() {}
+                                    });
+                                    return '<a href="#!/dashboard/detailPage/' 
+ guid + '" data-id="' + guid + '"></a>';
+                                }
+                            }
+                        })
+                    }
+                }, this.collection);
+            }
+        });
+    return DetailPageLayoutView;
+});

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js 
b/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js
new file mode 100644
index 0000000..609840e
--- /dev/null
+++ b/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js
@@ -0,0 +1,119 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/entity/EntityDetailTableLayoutView_tmpl',
+], function(require, Backbone, EntityDetailTableLayoutView_tmpl) {
+    'use strict';
+
+    var EntityDetailTableLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends EntityDetailTableLayoutView */
+        {
+            _viewName: 'EntityDetailTableLayoutView',
+
+            template: EntityDetailTableLayoutView_tmpl,
+
+            /** Layout sub regions */
+            regions: {},
+
+            /** ui selector cache */
+            ui: {
+                detailValue: "[data-id='detailValue']",
+            },
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                return events;
+            },
+            /**
+             * intialize a new EntityDetailTableLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'globalVent', 'collection'));
+                this.collectionObject = this.collection.toJSON();
+                this.entityModel = new this.collection.model();
+            },
+            bindEvents: function() {},
+            onRender: function() {
+                this.entityTableGenerate();
+            },
+            entityTableGenerate: function() {
+                var that = this,
+                    table = "",
+                    valueObject = this.collectionObject[0].values;
+                _.keys(valueObject).map(function(key) {
+                    /*  if (key == 'columns')
+                          return;*/
+                    var keyValue = valueObject[key];
+                    if (_.isArray(keyValue)) {
+                        var subLink = "";
+                        for (var i = 0; i < keyValue.length; i++) {
+                            var inputOutputField = keyValue[i];
+                            if (_.isObject(inputOutputField.id)) {
+                                id = inputOutputField.id.id;
+                            } else {
+                                id = inputOutputField.id;
+                            }
+                            that.fetchInputOutputValue(id);
+                            //var coma = (i = 0) ? ('') : (',');
+                            subLink += '<div data-id="' + id + '"></div>';
+                        }
+                        table += '<tr><td>' + key + '</td><td>' + subLink + 
'</td></tr>';
+                    } else if (_.isObject(keyValue)) {
+                        var id = "";
+                        if (_.isObject(keyValue.id)) {
+                            id = keyValue.id.id;
+                        } else {
+                            id = keyValue.id;
+                        }
+                        that.fetchInputOutputValue(id);
+                        table += '<tr><td>' + key + '</td><td><div data-id="' 
+ id + '"></div></td></tr>';
+                    } else {
+                        if (key == "createTime" || key == "lastAccessTime" || 
key == "retention") {
+                            table += '<tr><td>' + key + '</td><td>' + new 
Date(valueObject[key]) + '</td></tr>';
+                        } else {
+                            table += '<tr><td>' + key + '</td><td>' + 
valueObject[key] + '</td></tr>';
+                        }
+
+                    }
+                });
+                that.ui.detailValue.append(table);
+            },
+            fetchInputOutputValue: function(id) {
+                var that = this;
+                this.entityModel.getEntity(id, {
+                    beforeSend: function() {},
+                    success: function(data) {
+                        var value = "";
+                        if (data.definition.values.name) {
+                            value = data.definition.values.name;
+                        } else {
+                            value = data.GUID;
+                        }
+
+                        that.$('td div[data-id="' + data.GUID + '"]').html('<a 
href="#!/dashboard/detailPage/' + data.GUID + '">' + value + '</a>');
+                    },
+                    error: function(error, data, status) {},
+                    complete: function() {}
+                });
+            }
+        });
+    return EntityDetailTableLayoutView;
+});

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/a5f8c5aa/dashboardv2/public/js/views/graph/LineageLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js 
b/dashboardv2/public/js/views/graph/LineageLayoutView.js
new file mode 100644
index 0000000..973d091
--- /dev/null
+++ b/dashboardv2/public/js/views/graph/LineageLayoutView.js
@@ -0,0 +1,285 @@
+/**
+ * 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.
+ */
+
+define(['require',
+    'backbone',
+    'hbs!tmpl/graph/LineageLayoutView_tmpl',
+    'collection/VLineageList',
+    'models/VEntity',
+    'dagreD3',
+    'd3-tip'
+], function(require, Backbone, LineageLayoutViewtmpl, VLineageList, VEntity, 
dagreD3, d3Tip) {
+    'use strict';
+
+    var LineageLayoutView = Backbone.Marionette.LayoutView.extend(
+        /** @lends LineageLayoutView */
+        {
+            _viewName: 'LineageLayoutView',
+
+            template: LineageLayoutViewtmpl,
+
+            /** Layout sub regions */
+            regions: {},
+
+            /** ui selector cache */
+            ui: {
+                graph: ".graph"
+            },
+
+            /** ui events hash */
+            events: function() {
+                var events = {};
+                return events;
+            },
+
+            /**
+             * intialize a new LineageLayoutView Layout
+             * @constructs
+             */
+            initialize: function(options) {
+                _.extend(this, _.pick(options, 'globalVent', 'assetName', 
'guid'));
+                this.inputCollection = new VLineageList();
+                this.outputCollection = new VLineageList();
+                this.entityModel = new VEntity();
+                this.inputCollection.url = "/api/atlas/lineage/hive/table/" + 
this.assetName + "/inputs/graph";
+                this.outputCollection.url = "/api/atlas/lineage/hive/table/" + 
this.assetName + "/outputs/graph";
+                this.bindEvents();
+                this.fetchGraphData();
+                this.data = {};
+                this.fetchList = 0
+            },
+            bindEvents: function() {
+                this.listenTo(this.inputCollection, 'reset', function() {
+                    $('.lineageLayout').show();
+                    this.generateData(this.inputCollection, 'input');
+                    this.outputCollection.fetch({ reset: true });
+                }, this);
+                this.listenTo(this.outputCollection, 'reset', function() {
+                    $('.lineageLayout').show();
+                    this.generateData(this.outputCollection, 'output');
+                    this.outputState = true;
+                }, this);
+                this.listenTo(this.outputCollection, 'error', function() {
+                    this.$('.fontLoader').hide();
+                    $('.lineageLayout').hide();
+
+                }, this);
+                this.listenTo(this.inputCollection, 'error', function() {
+                    this.$('.fontLoader').hide();
+                    this.$('.lineageLayout').hide();
+                }, this);
+            },
+            onRender: function() {
+                this.$('.fontLoader').show();
+                this.g = new dagreD3.graphlib.Graph()
+                    .setGraph({})
+                    .setDefaultEdgeLabel(function() {
+                        return {};
+                    });
+            },
+            fetchGraphData: function() {
+                this.inputCollection.fetch({ reset: true });
+            },
+            generateData: function(collection, type) {
+                var that = this;
+
+                function addValueInObject(data) {
+                    var obj = {};
+                    if (data && data.definition && data.definition.values) {
+                        var values = data.definition.values;
+                        obj['label'] = values.name
+                        obj['id'] = data.GUID;
+                        if (values.queryText) {
+                            obj['queryText'] = values.queryText;
+                        }
+                    } else {
+                        obj['label'] = vertices[val].values.name;
+                    }
+                    obj['class'] = "type-TOP";
+                    that.g.setNode(data.GUID, obj);
+                    --that.fetchList;
+                    if (that.fetchList <= 0) {
+                        if (that.edgesAndvertices) {
+                            that.createGraph(that.edgesAndvertices, 
that.startingPoint);
+                        } else if (this.outputState && !that.edgesAndvertices) 
{
+                            that.$('svg').height('100');
+                            that.$('svg').html('<text x="' + 
(that.$('svg').width() - 150) / 2 + '" y="' + that.$('svg').height() / 2 + '" 
fill="black">No lineage data found</text>');
+                            that.$('.fontLoader').hide();
+                        }
+                    }
+                }
+
+                function fetchLoadProcess(id) {
+                    ++that.fetchList
+                    that.entityModel.getEntity(id, {
+                        beforeSend: function() {},
+                        success: function(data) {
+                            addValueInObject(data);
+                        },
+                        error: function(error, data, status) {},
+                        complete: function() {}
+                    });
+                }
+
+                function makeNode(c) {
+
+                    var edges = c.edges,
+                        vertices = c.vertices,
+                        allKeys = [];
+                    _.each(c.edges, function(val, key, obj) {
+                        allKeys.push(key)
+                        _.each(val, function(val1, key1, obj1) {
+                            allKeys.push(val1)
+                        });
+                    });
+                    var uniquNode = _.uniq(allKeys);
+                    _.each(uniquNode, function(val, key) {
+                        var obj = {}
+                        if (vertices[val] && vertices[val].values) {
+                            obj['label'] = vertices[val].values.name;
+                            obj['id'] = val;
+                            obj['class'] = "type-TOP";
+                            obj['typeName'] = 
vertices[val].values.vertexId.values.typeName;
+                            that.g.setNode(val, obj);
+                        } else {
+                            fetchLoadProcess(val);
+                        }
+
+                    });
+                }
+                _.each(collection.models, function(values) {
+                    var valuObj = values.get('values');
+                    that.startingPoint = [];
+                    if (!_.isEmpty(valuObj.edges)) {
+                        if (type == "input") {
+                            that.edgesAndvertices = {
+                                edges: {},
+                                vertices: valuObj.vertices
+                            }
+                            _.each(valuObj.edges, function(val, key, obj) {
+                                _.each(val, function(val1, key1, obj1) {
+                                    var chiledParent = {};
+                                    if (!obj[val1]) {
+                                        that.startingPoint.push(val1)
+                                    }
+                                    that.edgesAndvertices.edges[val1] = [key];
+                                });
+                            });
+                        } else {
+                            that.edgesAndvertices = valuObj;
+                            that.startingPoint = [that.guid];
+                        }
+                        makeNode(that.edgesAndvertices);
+                    } else {
+                        if (type == 'output') {
+                            that.outputState = true;
+                        }
+                    }
+                });
+                if (this.fetchList <= 0) {
+                    if (this.edgesAndvertices) {
+                        this.createGraph(that.edgesAndvertices, 
this.startingPoint);
+                    } else if (this.outputState && !this.edgesAndvertices) {
+                        this.$('.fontLoader').hide();
+                        that.$('svg').height('100');
+                        that.$('svg').html('<text x="' + 
(that.$('svg').width() - 150) / 2 + '" y="' + that.$('svg').height() / 2 + '" 
fill="black">No lineage data found</text>');
+                    }
+                }
+            },
+            createGraph: function(edgesAndvertices, startingPoint) {
+                var that = this;
+
+                this.g.nodes().forEach(function(v) {
+                    var node = that.g.node(v);
+                    // Round the corners of the nodes
+                    node.rx = node.ry = 5;
+                });
+
+                // Set up edges, no special attributes.
+                // For input
+                var lastVal = "";
+                _.each(startingPoint, function(val, key, obj) {
+                    that.g.setEdge(val, edgesAndvertices.edges[val][0]);
+                    lastVal = edgesAndvertices.edges[val][0];
+                });
+                createRemaningEdge(edgesAndvertices.edges, lastVal);
+
+                function createRemaningEdge(obj, starting) {
+                    if (obj[starting] && obj[starting].length) {
+                        that.g.setEdge(starting, obj[starting]);
+                        createRemaningEdge(obj, obj[starting]);
+                    }
+                }
+
+                if (this.outputState) {
+                    // Create the renderer
+                    var render = new dagreD3.render();
+                    // Set up an SVG group so that we can translate the final 
graph.
+                    var svg = d3.select(this.$("svg")[0]),
+                        svgGroup = svg.append("g");
+                    var zoom = d3.behavior.zoom().on("zoom", function() {
+                        svgGroup.attr("transform", "translate(" + 
d3.event.translate + ")" +
+                            "scale(" + d3.event.scale + ")");
+                    });
+                    var tooltip = d3Tip()
+                        .attr('class', 'd3-tip')
+                        .html(function(d) {
+                            var value = that.g.node(d)
+                            var htmlStr = "<h5>Name: <span 
style='color:#359f89'>" + value.label + "</span></h5> ";
+                            if (value.queryText) {
+                                htmlStr += "<h5>Query: <span 
style='color:#359f89'>" + value.queryText + "</span></h5> "
+                            }
+                            return htmlStr;
+                        });
+                    svg.call(zoom)
+                        .call(tooltip);
+
+
+                    this.$('.fontLoader').hide();
+                    // Run the renderer. This is what draws the final graph.
+                    this.g.graph().rankDir = 'LR';
+                    //render(d3.select(this.$("svg g")[0]), this.g);
+                    render(svgGroup, this.g);
+                    svg.on("dblclick.zoom", function() {
+                        return null;
+                    })
+                    svgGroup.selectAll("g.nodes g.node")
+                        .on('mouseover', function(d) {
+                            tooltip.show(d);
+                        })
+                        .on('dblclick', function(d) {
+                            tooltip.hide(d);
+                            
Backbone.history.navigate("#!/dashboard/detailPage/" + d, { trigger: true });
+                        })
+                        .on('mouseout', function(d) {
+                            tooltip.hide(d);
+                        });
+                    // Center the graph
+                    var initialScale = 1.5;
+                    zoom.translate([(this.$('svg').width() - 
this.g.graph().width * initialScale) / 2, (this.$('svg').height() - 
this.g.graph().height * initialScale) / 2])
+                        .scale(initialScale)
+                        .event(svg);
+                    //svg.attr('height', this.g.graph().height * initialScale 
+ 40);
+
+                }
+
+            }
+        });
+    return LineageLayoutView;
+
+});

Reply via email to