ATLAS-2600: Glossary UI update for add/update/remove of classifications to terms

Signed-off-by: Madhan Neethiraj <[email protected]>


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

Branch: refs/heads/master
Commit: 6d51ddec5b413ec46e45a7fe7e154a4e4db4fb09
Parents: 2237a89
Author: kevalbhatt <[email protected]>
Authored: Thu Apr 26 21:23:57 2018 +0530
Committer: Madhan Neethiraj <[email protected]>
Committed: Thu Apr 26 11:09:03 2018 -0700

----------------------------------------------------------------------
 dashboardv2/public/css/scss/override.scss       |  18 +-
 dashboardv2/public/js/router/Router.js          |  10 +-
 .../detail_page/DetailPageLayoutView_tmpl.html  |   2 +-
 .../CreateEditGlossaryLayoutView_tmpl.html      |   2 +-
 .../glossary/GlossaryDetailLayoutView_tmpl.html |  32 ++-
 .../glossary/GlossaryLayoutView_tmpl.html       |   2 +-
 .../templates/search/SearchLayoutView_tmpl.html |  12 +-
 .../search/SearchResultLayoutView_tmpl.html     |  11 +-
 .../public/js/utils/CommonViewFunction.js       | 185 ++++++------
 dashboardv2/public/js/utils/Overrides.js        |   2 +-
 dashboardv2/public/js/utils/Utils.js            |  40 ++-
 .../views/detail_page/DetailPageLayoutView.js   | 151 ++++------
 .../js/views/glossary/AssignTermLayoutView.js   |   2 +-
 .../glossary/CreateEditGlossaryLayoutView.js    |   1 -
 .../views/glossary/GlossaryDetailLayoutView.js  | 147 ++++++++--
 .../js/views/glossary/GlossaryLayoutView.js     | 281 ++++++++++++++-----
 .../js/views/graph/RelationshipLayoutView.js    |  12 +-
 .../js/views/profile/ProfileLayoutView.js       |   5 +-
 .../public/js/views/schema/SchemaLayoutView.js  |  31 +-
 .../public/js/views/search/SearchLayoutView.js  | 116 ++++++--
 .../js/views/search/SearchResultLayoutView.js   |  56 ++--
 .../public/js/views/tag/TagDetailLayoutView.js  |   3 +-
 .../js/views/tag/TagDetailTableLayoutView.js    |  40 +--
 .../public/js/views/tag/TagLayoutView.js        |   2 +-
 24 files changed, 760 insertions(+), 403 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/css/scss/override.scss
----------------------------------------------------------------------
diff --git a/dashboardv2/public/css/scss/override.scss 
b/dashboardv2/public/css/scss/override.scss
index 1815c14..c9b12bd 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -372,6 +372,21 @@ div.columnmanager-dropdown-container {
 }
 
 .stack-modal[aria-role="alertdialog"] {
+    &.width-600 {
+        width: 600px !important;
+        left: calc(50% - 250px) !important;
+        margin-left: 0 !important;
+    }
+    &.width-500 {
+        width: 500px !important;
+        left: calc(50% - 216px) !important;
+        margin-left: 0 !important;
+    }
+    &.width-400 {
+        width: 400px !important;
+        left: calc(50% - 183px);
+        margin-left: 0 !important;
+    }
     .alert.ui-pnotify-container {
         color: $color_ironside_gray_approx;
         background-color: $white;
@@ -430,6 +445,7 @@ div.columnmanager-dropdown-container {
 .fa-color {
     color: $color_keppel_approx
 }
-.w30{
+
+.w30 {
     width: 30% !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/router/Router.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/router/Router.js 
b/dashboardv2/public/js/router/Router.js
index d4cdf26..9899a96 100644
--- a/dashboardv2/public/js/router/Router.js
+++ b/dashboardv2/public/js/router/Router.js
@@ -47,7 +47,11 @@ define([
             this.bindCommonEvents();
             this.listenTo(this, 'route', this.postRouteExecute, this);
             this.searchVent = new Backbone.Wreqr.EventAggregator();
-            this.glossaryCollection = new VGlossaryList([], {});
+            this.glossaryCollection = new VGlossaryList([], {
+                comparator: function(item) {
+                    return item.get("displayName");
+                }
+            });
             this.preFetchedCollectionLists = {
                 'entityDefCollection': this.entityDefCollection,
                 'typeHeaders': this.typeHeaders,
@@ -221,7 +225,7 @@ define([
                     if (Utils.getUrlState.isTagTab()) {
                         
App.rSideNav.currentView.RTagLayoutView.currentView.manualRender();
                     } else if (Utils.getUrlState.isGlossaryTab()) {
-                        
App.rSideNav.currentView.RGlossaryLayoutView.currentView.manualRender(_.extend({},
 paramObj));
+                        
App.rSideNav.currentView.RGlossaryLayoutView.currentView.manualRender(_.extend({
 isTrigger: true }, paramObj));
                     }
                 }
 
@@ -263,7 +267,7 @@ define([
                 }
                 App.rSideNav.currentView.selectTab();
                 if (paramObj) {
-                    isinitialView = (paramObj.type || (paramObj.dslChecked == 
"true" ? "" : paramObj.tag) || (paramObj.query ? paramObj.query.trim() : 
"")).length === 0;
+                    isinitialView = (paramObj.type || (paramObj.dslChecked == 
"true" ? "" : (paramObj.tag || paramObj.term)) || (paramObj.query ? 
paramObj.query.trim() : "")).length === 0;
                 }
                 App.rNContent.show(new SearchDetailLayoutView(
                     _.extend({

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html
index a23797f..a968c62 100644
--- a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html
@@ -30,7 +30,7 @@
                 </button>
             </div>
         </div>
-        <div class="form-group">
+        <div class="form-group termBox">
             <span class="control-label-sm-pr pull-left">Term:</span>
             <div class="pull-left" data-id="termList">
                 <button class="btn btn-action btn-sm" title="Add Term" 
data-id="addTerm">

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html
 
b/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html
index f783706..4e4470a 100644
--- 
a/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html
+++ 
b/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html
@@ -18,7 +18,7 @@
     <div class="form-group">
         <label class="control-label col-sm-2 {{#if create}}required{{/if}}" 
for="name">Name</label>
         <div class="col-sm-10">
-            <input class="form-control" name="displayName" 
value="{{displayName}}" data-id="displayName" placeholder="Display 
Name(required)" autofocus/>
+            <input class="form-control" name="displayName" 
value="{{displayName}}" data-id="displayName" placeholder="Name(required)" 
autofocus/>
         </div>
     </div>
     <div class="form-group">

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
index 25967ea..ff798e1 100644
--- 
a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
+++ 
b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html
@@ -35,6 +35,14 @@
         </div>
         {{#if isTermView}}
         <div class="form-group clearfix">
+            <span class="control-label-sm-pr pull-left">Classifications:</span>
+            <div class="pull-left" data-id="tagList">
+                <button class="btn btn-action btn-sm" title="Add 
Classification" data-id="addTag">
+                    <i class="fa fa-plus"> </i>
+                </button>
+            </div>
+        </div>
+        <div class="form-group clearfix">
             <span class="control-label-sm-pr pull-left">Categories:</span>
             <div class="pull-left" data-id="categoryList">
                 <button class="btn btn-action btn-sm" title="Add Category" 
data-id="addCategory">
@@ -51,17 +59,35 @@
                 </button>
             </div>
         </div>
+        {{/if}} {{#if isTermView}}
+        <div class="row">
+            <div class="col-sm-12 default-tab">
+                <ul class="nav nav-tabs" data-id="tab-list">
+                    <li role="entities" class="tab active"><a 
href="#tab-entities" aria-controls="tab-entities" role="tab" 
data-toggle="tab">Entities</a></li>
+                    <li role="classification"><a href="#tab-tagTable" 
aria-controls="tab-tagTable" role="tab" 
data-toggle="tab">Classifications</a></li>
+                </ul>
+            </div>
+        </div>
         {{/if}}
     </div>
 </div>
 <div class="container-fluid gray-bg">
-    <div class="row">
-        <div class="col-sm-custom">
+    {{#if isTermView}}
+    <div class="tab-content">
+        <div id="tab-entities" role="entities" class="tab-pane active animated 
fadeIn">
             <div id="r_searchResultLayoutView">
-                <div class="fontLoader" style="display: block;min-height: 
50px;position:relative;margin-top: 25px;">
+                <div class="fontLoader-relative">
+                    <i class="fa fa-refresh fa-spin-custom"></i>
+                </div>
+            </div>
+        </div>
+        <div id="tab-tagTable" role="classification" class="tab-pane animated 
fadeIn">
+            <div id="r_tagTableLayoutView">
+                <div class="fontLoader-relative">
                     <i class="fa fa-refresh fa-spin-custom"></i>
                 </div>
             </div>
         </div>
     </div>
+    {{/if}}
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html
index f29f4e7..7546b04 100644
--- a/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
 -->
-<div class="col-sm-12 add-seperator">
+<div class="col-sm-12 {{#unless isAssignView}}add-seperator{{/unless}}">
     <div class="row">
         {{#unless isAssignView}}
         <div class="col-sm-8 no-padding" style="margin-top: 5px;">

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html
index b30023e..2a46662 100644
--- a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html
@@ -36,10 +36,10 @@
             <div class="srchType clearfix">
                 <span class="srchTitle">Search By Type</span>
                 <div class="">
-                    <div class="col-sm-10 no-padding temFilter">
+                    <div class="col-sm-10 no-padding typeFilter">
                         <select data-id="typeLOV"></select>
                     </div>
-                    <div class="col-sm-2 no-padding temFilterBtn">
+                    <div class="col-sm-2 no-padding typeFilterBtn">
                         <button type="button" class="btn btn-action btn-md 
pull-right typeLOV active" title="Entity Attribute Filter" 
data-id="typeAttrFilter"><i class="fa fa-filter"></i></button>
                     </div>
                 </div>
@@ -55,6 +55,14 @@
                     </div>
                 </div>
             </div>
+            <div class="srchType termBox clearfix">
+                <span class="srchTitle">Search By Term</span>
+                <div class="">
+                    <div class="col-sm-12 no-padding">
+                        <select data-id="termLOV"></select>
+                    </div>
+                </div>
+            </div>
             <div class="srchType">
                 <span class="srchTitle searchText">Search By Text</span>
                 <input type="text" class="form-control" data-id="searchInput" 
placeholder="Search by text" style="margin: 5px 0px;">

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html 
b/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html
index 411aaab..31cae24 100644
--- a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
 -->
-<div class="">
+<div class="position-relative">
     <div class="tableOverlay"></div>
     <!-- Not for table Loader its only for initial loading -->
     <div class="fontLoader" style="z-index:999">
@@ -32,21 +32,18 @@
                     <div class="inline" data-id="colManager"></div>
                     <div class="inline" data-id="containerCheckBox" 
style="display: none;">
                         <label class="checkbox-inline btn" 
for="historicalentities">
-                            <input type="checkbox" 
data-id="checkDeletedEntity" data-value="includeDE" 
-                            id="historicalentities"/>
+                            <input type="checkbox" 
data-id="checkDeletedEntity" data-value="includeDE" id="historicalentities" />
                             <b>Show historical entities</b></label>
                     </div>
-                    {{#ifCond fromView '!==' "glossary"}}
                     <div class="inline" data-id="containerCheckBox" 
style="display: none;">
                         <label class="checkbox-inline btn" 
for="subclassifications">
-                            <input type="checkbox" 
data-id="checkSubClassification" data-value="excludeSC" 
id="subclassifications"/>
+                            <input type="checkbox" 
data-id="checkSubClassification" data-value="excludeSC" id="subclassifications" 
/>
                             <b>Exclude sub-classifications</b></label>
                     </div>
-                    {{/ifCond}}
                     {{#ifCond fromView '!==' "classification"}}
                     <div class="inline" data-id="containerCheckBox" 
style="display: none;">
                         <label class="checkbox-inline btn" for="subtypes">
-                            <input type="checkbox" data-id="checkSubType" 
data-value="excludeST" id="subtypes"/>
+                            <input type="checkbox" data-id="checkSubType" 
data-value="excludeST" id="subtypes" />
                             <b>Exclude sub-types</b></label>
                     </div>
                     {{/ifCond}}

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/utils/CommonViewFunction.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js 
b/dashboardv2/public/js/utils/CommonViewFunction.js
index b7e2c72..a2ff93d 100644
--- a/dashboardv2/public/js/utils/CommonViewFunction.js
+++ b/dashboardv2/public/js/utils/CommonViewFunction.js
@@ -20,52 +20,54 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
     'use strict';
 
     var CommonViewFunction = {};
-    CommonViewFunction.deleteTagModel = function(options) {
-        var modal = new Modal({
-            title: options.titleMessage,
-            okText: options.buttonText,
-            htmlContent: options.msg,
-            cancelText: "Cancel",
-            allowCancel: true,
-            okCloses: true,
-            showFooter: true,
-        }).open();
-        return modal;
-    };
     CommonViewFunction.deleteTag = function(options) {
         require(['models/VTag'], function(VTag) {
-            var tagModel = new VTag();
             if (options && options.guid && options.tagName) {
-                if (options.showLoader) {
-                    options.showLoader();
-                }
-                tagModel.deleteAssociation(options.guid, options.tagName, {
-                    skipDefaultError: true,
-                    success: function(data) {
-                        Utils.notifySuccess({
-                            content: "Classification " + options.tagName + 
Messages.removeSuccessMessage
-                        });
-                        if (options.callback) {
-                            options.callback();
-                        }
-                        if (options.collection) {
-                            options.collection.fetch({ reset: true });
-                        }
+                var tagModel = new VTag(),
+                    notifyObj = {
+                        modal: true,
+                        text: options.msg,
+                        title: options.titleMessage,
+                        okText: options.okText,
+                        ok: function(argument) {
+                            if (options.showLoader) {
+                                options.showLoader();
+                            }
+                            tagModel.deleteAssociation(options.guid, 
options.tagName, {
+                                skipDefaultError: true,
+                                success: function(data) {
+                                    Utils.notifySuccess({
+                                        content: "Classification " + 
options.tagName + Messages.removeSuccessMessage
+                                    });
+                                    if (options.callback) {
+                                        options.callback();
+                                    }
+                                    if (options.collection) {
+                                        options.collection.fetch({ reset: true 
});
+                                    }
 
-                    },
-                    cust_error: function(model, response) {
-                        var message = options.tagName + 
Messages.deleteErrorMessage;
-                        if (response && response.responseJSON) {
-                            message = response.responseJSON.errorMessage;
-                        }
-                        if (options.hideLoader) {
-                            options.hideLoader();
+                                },
+                                cust_error: function(model, response) {
+                                    var message = options.tagName + 
Messages.deleteErrorMessage;
+                                    if (response && response.responseJSON) {
+                                        message = 
response.responseJSON.errorMessage;
+                                    }
+                                    if (options.hideLoader) {
+                                        options.hideLoader();
+                                    }
+                                    Utils.notifyError({
+                                        content: message
+                                    });
+                                }
+                            });
+                        },
+                        cancel: function(argument) {
+                            if (options.hideLoader) {
+                                options.hideLoader();
+                            }
                         }
-                        Utils.notifyError({
-                            content: message
-                        });
-                    }
-                });
+                    };
+                Utils.notifyConfirm(notifyObj);
             }
         });
     };
@@ -331,6 +333,10 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
             }
             queryArray.push(tagKeyValue);
         }
+        if (value.term) {
+            var tagKeyValue = '<span class="key">Term:</span>&nbsp<span 
class="value">' + _.escape(value.term) + '</span>';
+            queryArray.push(tagKeyValue);
+        }
         if (value.query) {
             queryArray.push('<span class="key">Query:</span>&nbsp<span 
class="value">' + _.trim(_.escape(value.query)) + '</span>&nbsp');
         }
@@ -600,9 +606,24 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
                 "okText": model ? "Update" : "Create",
                 "allowCancel": true
             }).open();
+            modal.$el.find('button.ok').attr("disabled", "true");
+            if (model) {
+                view.$('input,textarea').on('keyup', function(e) {
+                    modal.$el.find('button.ok').attr("disabled", false);
+                });
+            } else {
+                view.ui.displayName.on('keyup', function(e) {
+                    modal.$el.find('button.ok').attr("disabled", false);
+                });
+            }
+            view.ui.displayName.on('keyup', function(e) {
+                if ((e.keyCode == 8 || e.keyCode == 32 || e.keyCode == 46) && 
e.currentTarget.value.trim() == "") {
+                    modal.$el.find('button.ok').attr("disabled", true);
+                }
+            });
             modal.on('ok', function() {
                 if (isGlossaryView) {
-                    modal.$el.find('button.ok').attr("disabled", "true");
+                    modal.$el.find('button.ok').attr("disabled", true);
                 }
                 
CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, 
"modal": modal }, options));
             });
@@ -637,19 +658,29 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
             messageType = "Category ";
         }
         var ajaxOptions = {
+            silent: true,
             success: function(rModel, response) {
                 Utils.notifySuccess({
                     content: messageType + ref.ui.displayName.val() + 
Messages[model ? "editSuccessMessage" : "addSuccessMessage"]
                 });
                 if (options.callback) {
-                    options.callback(response);
+                    var obj = rModel;
+                    if (isGlossaryView) {
+                        obj = _.omit((rModel && rModel.toJSON ? 
rModel.toJSON() : rModel), 'terms', 'categories');
+                    }
+                    options.callback(obj);
                 }
                 modal.trigger('closeModal');
+            },
+            cust_error: function() {
+                if (isGlossaryView) {
+                    modal.$el.find('button.ok').attr("disabled", false);
+                }
             }
         }
         if (model) {
             if (isGlossaryView) {
-                model.set(data).save(null, ajaxOptions)
+                model.clone().set(data, { silent: true }).save(null, 
ajaxOptions)
             } else {
                 newModel[isTermView ? "createEditTerm" : 
"createEditCategory"](_.extend(ajaxOptions, {
                     guid: model.guid,
@@ -694,12 +725,11 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
                 ajaxOptions = {
                     success: function(rModel, response) {
                         Utils.notifySuccess({
-                            content: ((isCategoryView ? "Term" : "Category") + 
" association is removed successfully")
+                            content: ((isCategoryView || isEntityView ? "Term" 
: "Category") + " association is removed successfully")
                         });
                         if (options.callback) {
                             options.callback();
                         }
-                        modal.trigger('closeModal');
                     },
                     cust_error: function() {
                         if (options.hideLoader) {
@@ -707,44 +737,37 @@ define(['require', 'utils/Utils', 'modules/Modal', 
'utils/Messages', 'utils/Enum
                         }
                     }
                 },
-                modal = new Modal({
+                notifyObj = {
+                    modal: true,
+                    text: options.msg,
                     title: options.titleMessage,
                     okText: options.buttonText,
-                    htmlContent: options.msg,
-                    cancelText: "Cancel",
-                    allowCancel: true,
-                    okCloses: true,
-                    showFooter: true,
-                }).open();
-            modal.on('ok', function() {
-                if (options.showLoader) {
-                    options.showLoader();
-                }
-                if (isEntityView && model) {
-                    var data = [model];
-                    newModel.removeTermFromEntity(termGuid, 
_.extend(ajaxOptions, {
-                        data: JSON.stringify(data)
-                    }))
-                } else {
-                    var data = _.extend({}, model);
-                    if (isTermView) {
-                        data.categories = _.reject(data.categories, 
function(term) { return term.categoryGuid == selectedGuid });
-                    } else {
-                        data.terms = _.reject(data.terms, function(term) { 
return term.termGuid == selectedGuid });
-                    }
+                    ok: function(argument) {
+                        if (options.showLoader) {
+                            options.showLoader();
+                        }
+                        if (isEntityView && model) {
+                            var data = [model];
+                            newModel.removeTermFromEntity(termGuid, 
_.extend(ajaxOptions, {
+                                data: JSON.stringify(data)
+                            }))
+                        } else {
+                            var data = _.extend({}, model);
+                            if (isTermView) {
+                                data.categories = _.reject(data.categories, 
function(term) { return term.categoryGuid == selectedGuid });
+                            } else {
+                                data.terms = _.reject(data.terms, 
function(term) { return term.termGuid == selectedGuid });
+                            }
 
-                    newModel[isTermView ? "createEditTerm" : 
"createEditCategory"](_.extend(ajaxOptions, {
-                        guid: model.guid,
-                        data: JSON.stringify(_.extend({}, model, data)),
-                    }));
-                }
-            });
-            modal.on('closeModal', function() {
-                modal.trigger('cancel');
-                if (options.onModalClose) {
-                    options.onModalClose()
-                }
-            });
+                            newModel[isTermView ? "createEditTerm" : 
"createEditCategory"](_.extend(ajaxOptions, {
+                                guid: model.guid,
+                                data: JSON.stringify(_.extend({}, model, 
data)),
+                            }));
+                        }
+                    },
+                    cancel: function(argument) {}
+                };
+            Utils.notifyConfirm(notifyObj);
         }
     }
     CommonViewFunction.addRestCsrfCustomHeader = function(xhr, settings) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/utils/Overrides.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/Overrides.js 
b/dashboardv2/public/js/utils/Overrides.js
index a7bf395..81141f4 100644
--- a/dashboardv2/public/js/utils/Overrides.js
+++ b/dashboardv2/public/js/utils/Overrides.js
@@ -66,7 +66,7 @@ define(['require', 'utils/Utils', 'marionette', 'backgrid', 
'asBreadcrumbs', 'jq
     var getPopoverEl = function(e) {
         return $(e.target).parent().data("bs.popover") || 
$(e.target).data("bs.popover") || $(e.target).parents('.popover').length;
     }
-    $('body').on('click DOMMouseScroll mousewheel', function(e) {
+    $(document).on('click DOMMouseScroll mousewheel', function(e) {
         if (e.originalEvent) {
             // Do action if it is triggered by a human.
             //e.isImmediatePropagationStopped();

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/utils/Utils.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/Utils.js 
b/dashboardv2/public/js/utils/Utils.js
index ff6b5ff..0b16bb2 100644
--- a/dashboardv2/public/js/utils/Utils.js
+++ b/dashboardv2/public/js/utils/Utils.js
@@ -124,7 +124,7 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
         var modal = {};
         if (options && options.modal) {
             var myStack = { "dir1": "down", "dir2": "right", "push": "top", 
'modal': true };
-            modal['addclass'] = 'stack-modal';
+            modal['addclass'] = 'stack-modal ' + (options.modalClass ? 
modalClass : 'width-500');
             modal['stack'] = myStack;
         }
         notify(_.extend({
@@ -133,7 +133,7 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
             confirm: {
                 confirm: true,
                 buttons: [{
-                        text: 'cancel',
+                        text: options.cancelText || 'Cancel',
                         addClass: 'btn-action btn-md',
                         click: function(notice) {
                             options.cancel(notice);
@@ -141,7 +141,7 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
                         }
                     },
                     {
-                        text: 'Ok',
+                        text: options.okText || 'Ok',
                         addClass: 'btn-atlas btn-md',
                         click: function(notice) {
                             options.ok(notice);
@@ -439,19 +439,19 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
         return returnObj;
     }
     Utils.showTitleLoader = function(loaderEl, titleBoxEl) {
-        loaderEl.css({
+        loaderEl.css ? loaderEl.css({
             'display': 'block',
             'position': 'relative',
             'height': '85px',
             'marginTop': '85px',
             'marginLeft': '50%',
             'left': '0%'
-        });
-        titleBoxEl.hide();
+        }) : null;
+        titleBoxEl.hide ? titleBoxEl.hide() : null;
     }
     Utils.hideTitleLoader = function(loaderEl, titleBoxEl) {
-        loaderEl.hide();
-        titleBoxEl.fadeIn();
+        loaderEl.hide ? loaderEl.hide() : null;
+        titleBoxEl.fadeIn ? titleBoxEl.fadeIn() : null;
     }
     Utils.findAndMergeRefEntity = function(attributeObject, referredEntities) {
         var mergeObject = function(obj) {
@@ -477,6 +477,28 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
             });
         }
     }
+    Utils.getNestedSuperTypes = function(options) {
+        var data = options.data,
+            collection = options.collection,
+            superTypes = [];
+
+        var getData = function(data, collection) {
+            superTypes = superTypes.concat(data.superTypes);
+
+            if (data.superTypes && data.superTypes.length) {
+                _.each(data.superTypes, function(superTypeName) {
+                    if (collection.fullCollection) {
+                        var collectionData = 
collection.fullCollection.findWhere({ name: superTypeName }).toJSON();
+                    } else {
+                        var collectionData = collection.findWhere({ name: 
superTypeName }).toJSON();
+                    }
+                    return getData(collectionData, collection);
+                });
+            }
+        }
+        getData(data, collection);
+        return _.uniq(superTypes);
+    }
     Utils.getNestedSuperTypeObj = function(options) {
         var flag = 0,
             data = options.data,
@@ -513,7 +535,7 @@ define(['require', 'utils/Globals', 'pnotify', 
'utils/Messages', 'utils/Enums',
             }
         }
         getData(data, collection);
-        return attributeDefs
+        return attributeDefs;
     }
 
     Utils.getProfileTabType = function(profileData, skipData) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/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
index d0b7009..07878e1 100644
--- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
+++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js
@@ -90,7 +90,7 @@ define(['require',
                         Utils.setUrl({
                             url: '#!/glossary/' + 
$(e.currentTarget).find('i').data('guid'),
                             mergeBrowserUrl: false,
-                            urlParams: { gType: "term" },
+                            urlParams: { gType: "term", viewType: "term", 
fromView: "entity" },
                             trigger: true
                         });
                     }
@@ -118,7 +118,6 @@ define(['require',
              */
             initialize: function(options) {
                 _.extend(this, _.pick(options, 'value', 'collection', 'id', 
'entityDefCollection', 'typeHeaders', 'enumDefCollection', 
'classificationDefCollection', 'glossaryCollection'));
-                this.bindEvents();
                 $('body').addClass("detail-page");
             },
             bindEvents: function() {
@@ -126,6 +125,10 @@ define(['require',
                 this.listenTo(this.collection, 'reset', function() {
                     this.entityObject = this.collection.first().toJSON();
                     var collectionJSON = this.entityObject.entity;
+
+                    if (collectionJSON && 
collectionJSON.typeName.startsWith("__AtlasGlossary")) {
+                        this.$(".termBox").hide();
+                    }
                     // MergerRefEntity.
                     Utils.findAndMergeRefEntity(collectionJSON.attributes, 
this.entityObject.referredEntities);
 
@@ -200,6 +203,7 @@ define(['require',
                         fetchCollection: this.fetchCollection.bind(that),
                         enumDefCollection: this.enumDefCollection,
                         classificationDefCollection: 
this.classificationDefCollection,
+                        glossaryCollection: this.glossaryCollection,
                         attributeDefs: (function() {
                             return that.getEntityDef(collectionJSON);
                         })()
@@ -208,6 +212,8 @@ define(['require',
                     this.renderRelationshipLayoutView(obj);
                     this.renderAuditTableLayoutView(obj);
                     this.renderTagTableLayoutView(obj);
+
+                    // To render profile tab check for attribute "profileData" 
or typeName = "hive_db","hbase_namespace"
                     if (collectionJSON && 
(!_.isUndefined(collectionJSON.attributes['profileData']) || 
collectionJSON.typeName === "hive_db" || collectionJSON.typeName === 
"hbase_namespace")) {
                         if (collectionJSON.typeName === "hive_db" || 
collectionJSON.typeName === "hbase_namespace") {
                             this.$('.profileTab a').text("Tables")
@@ -221,48 +227,53 @@ define(['require',
                         }));
                     }
 
-                    // To render Schema check attribute 
"schemaElementsAttribute"
-                    var schemaOptions = this.activeEntityDef.get('options');
-                    if (schemaOptions && 
schemaOptions.hasOwnProperty('schemaElementsAttribute') && 
schemaOptions.schemaElementsAttribute !== "") {
-                        this.$('.schemaTable').show();
-                        this.renderSchemaLayoutView(_.extend({}, obj, {
-                            attribute: 
collectionJSON.attributes[schemaOptions.schemaElementsAttribute]
-                        }));
-                    } else if (this.value && this.value.tabActive == "schema") 
{
-                        Utils.setUrl({
-                            url: Utils.getUrlState.getQueryUrl().queyParams[0],
-                            urlParams: { tabActive: 'properties' },
-                            mergeBrowserUrl: false,
-                            trigger: true,
-                            updateTabState: true
-                        });
-                    }
-                    if (this.activeEntityDef && 
_.contains(this.activeEntityDef.get('superTypes'), "DataSet")) {
-                        this.$('.lineageGraph').show();
-                        this.renderLineageLayoutView({
-                            guid: this.id,
-                            entityDefCollection: this.entityDefCollection,
-                            fetchCollection: this.fetchCollection.bind(this),
-                            actionCallBack: function() {
-                                that.$('#expand_collapse_panel').click();
-                            }
-                        });
-                        this.$(".resizeGraph").resizable({
-                            handles: ' s',
-                            minHeight: 375,
-                            stop: function(event, ui) {
-                                ui.element.height(($(this).height()));
-                            },
-                        });
-                    } else if (this.value && this.value.tabActive == 
"lineage") {
-                        Utils.setUrl({
-                            url: Utils.getUrlState.getQueryUrl().queyParams[0],
-                            urlParams: { tabActive: 'properties' },
-                            mergeBrowserUrl: false,
-                            trigger: true,
-                            updateTabState: true
-                        });
+                    if (this.activeEntityDef) {
+                        // To render Schema check attribute 
"schemaElementsAttribute"
+                        var schemaOptions = 
this.activeEntityDef.get('options');
+                        if (schemaOptions && 
schemaOptions.hasOwnProperty('schemaElementsAttribute') && 
schemaOptions.schemaElementsAttribute !== "") {
+                            this.$('.schemaTable').show();
+                            this.renderSchemaLayoutView(_.extend({}, obj, {
+                                attribute: 
collectionJSON.attributes[schemaOptions.schemaElementsAttribute]
+                            }));
+                        } else if (this.value && this.value.tabActive == 
"schema") {
+                            Utils.setUrl({
+                                url: 
Utils.getUrlState.getQueryUrl().queyParams[0],
+                                urlParams: { tabActive: 'properties' },
+                                mergeBrowserUrl: false,
+                                trigger: true,
+                                updateTabState: true
+                            });
+                        }
+
+                        if (_.contains(Utils.getNestedSuperTypes({ data: 
this.activeEntityDef.toJSON(), collection: this.entityDefCollection }), 
"DataSet")) {
+                            this.$('.lineageGraph').show();
+                            this.renderLineageLayoutView({
+                                guid: this.id,
+                                entityDefCollection: this.entityDefCollection,
+                                fetchCollection: 
this.fetchCollection.bind(this),
+                                actionCallBack: function() {
+                                    that.$('#expand_collapse_panel').click();
+                                }
+                            });
+                            this.$(".resizeGraph").resizable({
+                                handles: ' s',
+                                minHeight: 375,
+                                stop: function(event, ui) {
+                                    ui.element.height(($(this).height()));
+                                },
+                            });
+                        } else if (this.value && this.value.tabActive == 
"lineage") {
+                            Utils.setUrl({
+                                url: 
Utils.getUrlState.getQueryUrl().queyParams[0],
+                                urlParams: { tabActive: 'properties' },
+                                mergeBrowserUrl: false,
+                                trigger: true,
+                                updateTabState: true
+                            });
+                        }
                     }
+
+
                 }, this);
                 this.listenTo(this.collection, 'error', function(model, 
response) {
                     this.$('.fontLoader-relative').removeClass('show');
@@ -275,31 +286,9 @@ define(['require',
             },
             onRender: function() {
                 var that = this;
+                this.bindEvents();
                 Utils.showTitleLoader(this.$('.page-title .fontLoader'), 
this.$('.entityDetail'));
                 this.$('.fontLoader-relative').addClass('show'); // to show 
tab loader
-                // this.ui.fullscreenPanel.on('fullscreen_done', function(e, 
panel) {
-                //     var svgEl = panel.find('.panel-body svg'),
-                //         scaleEl = svgEl.find('>g'),
-                //         zoom = that.RLineageLayoutView.currentView.zoom,
-                //         svg = that.RLineageLayoutView.currentView.svg,
-                //         viewThis = that.RLineageLayoutView.currentView,
-                //         setGraphZoomPositionCal = 
that.RLineageLayoutView.currentView.setGraphZoomPositionCal,
-                //         zoomed = 
that.RLineageLayoutView.currentView.zoomed;;
-
-                //     if (zoom) {
-                //         setGraphZoomPositionCal.call(viewThis);
-                //         zoomed.call(viewThis);
-                //         if ($(e.currentTarget).find('i').hasClass('fa 
fa-compress')) {
-                //             svg.call(zoom)
-                //                 .on("dblclick.zoom", null);
-
-                //         } else {
-                //             svg.call(zoom)
-                //                 .on("wheel.zoom", null)
-                //                 .on("dblclick.zoom", null);
-                //         }
-                //     }
-                // })
             },
             onShow: function() {
                 if (this.value && this.value.tabActive) {
@@ -330,32 +319,16 @@ define(['require',
                 }
             },
             onClickTagCross: function(e) {
-                var tagName = $(e.currentTarget).parent().text(),
-                    that = this;
-                var modal = CommonViewFunction.deleteTagModel({
+                var that = this,
+                    tagName = $(e.currentTarget).parent().text();
+                CommonViewFunction.deleteTag(_.extend({}, {
                     msg: "<div class='ellipsis'>Remove: " + "<b>" + 
_.escape(tagName) + "</b> assignment from" + " " + "<b>" + this.name + 
"?</b></div>",
                     titleMessage: Messages.removeTag,
-                    buttonText: "Remove"
-                });
-                if (modal) {
-                    modal.on('ok', function() {
-                        that.deleteTagData({
-                            'tagName': tagName,
-                            'guid': that.id,
-                            'el': $(e.currentTarget)
-                        });
-                    });
-                    modal.on('closeModal', function() {
-                        modal.trigger('cancel');
-                    });
-                }
-            },
-            deleteTagData: function(options) {
-                var that = this,
-                    tagName = options.el.text();
-                Utils.showTitleLoader(this.$('.page-title .fontLoader'), 
this.$('.entityDetail'));
-                CommonViewFunction.deleteTag(_.extend({}, options, {
+                    okText: "Remove",
+                    showLoader: that.showLoader.bind(that),
                     hideLoader: that.hideLoader.bind(that),
+                    tagName: tagName,
+                    guid: that.id,
                     callback: function() {
                         that.fetchCollection();
                     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js 
b/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js
index fd7631d..5dcdfc7 100644
--- a/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js
@@ -102,7 +102,7 @@ define(['require',
                     ajaxOptions = {
                         success: function(rModel, response) {
                             Utils.notifySuccess({
-                                content: (that.isCategoryView ? "Term" : 
"Category") + " is associated successfully "
+                                content: (that.isCategoryView || 
that.isEntityView ? "Term" : "Category") + " is associated successfully "
                             });
                             that.modal.trigger('closeModal');
                             if (that.callback) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js
----------------------------------------------------------------------
diff --git 
a/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js 
b/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js
index e06b05b..ec29339 100644
--- a/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js
@@ -41,7 +41,6 @@ define(['require',
 
             /** ui selector cache */
             ui: {
-                "qualifiedName": "[data-id='qualifiedName']",
                 "displayName": "[data-id='displayName']",
                 "shortDescription": "[data-id='shortDescription']",
                 "longDescription": "[data-id='longDescription']",

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js 
b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
index 2ba3c45..f807455 100644
--- a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js
@@ -36,6 +36,7 @@ define(['require',
             /** Layout sub regions */
             regions: {
                 RSearchResultLayoutView: "#r_searchResultLayoutView",
+                RTagTableLayoutView: "#r_tagTableLayoutView"
             },
             templateHelpers: function() {
                 return {
@@ -51,14 +52,21 @@ define(['require',
                 title: "[data-id='title']",
                 shortDescription: "[data-id='shortDescription']",
                 longDescription: "[data-id='longDescription']",
+
                 categoryList: "[data-id='categoryList']",
                 removeCategory: "[data-id='removeCategory']",
                 categoryClick: "[data-id='categoryClick']",
                 addCategory: "[data-id='addCategory']",
+
                 termList: "[data-id='termList']",
                 removeTerm: "[data-id='removeTerm']",
                 termClick: "[data-id='termClick']",
-                addTerm: "[data-id='addTerm']"
+                addTerm: "[data-id='addTerm']",
+
+                tagList: "[data-id='tagList']",
+                removeTag: '[data-id="removeTag"]',
+                tagClick: '[data-id="tagClick"]',
+                addTag: '[data-id="addTag"]',
             },
             /** ui events hash */
             events: function() {
@@ -73,7 +81,7 @@ define(['require',
                         Utils.setUrl({
                             url: '#!/glossary/' + guid,
                             mergeBrowserUrl: false,
-                            urlParams: { gType: "category" },
+                            urlParams: { gType: "category", viewType: 
"category", fromView: "glossary" },
                             trigger: true,
                             updateTabState: true
                         });
@@ -89,12 +97,23 @@ define(['require',
                         Utils.setUrl({
                             url: '#!/glossary/' + guid,
                             mergeBrowserUrl: false,
-                            urlParams: { gType: "term" },
+                            urlParams: { gType: "term", viewType: "term", 
fromView: "glossary" },
                             trigger: true,
                             updateTabState: true
                         });
                     }
                 };
+                events["click " + this.ui.tagClick] = function(e) {
+                    if (e.target.nodeName.toLocaleLowerCase() == "i") {
+                        this.onClickTagCross(e);
+                    } else {
+                        Utils.setUrl({
+                            url: '#!/tag/tagAttribute/' + 
e.currentTarget.textContent,
+                            mergeBrowserUrl: false,
+                            trigger: true
+                        });
+                    }
+                };
                 events["click " + this.ui.editButton] = function(e) {
                     var that = this,
                         model = 
this.glossaryCollection.fullCollection.get(this.guid);
@@ -103,11 +122,11 @@ define(['require',
                             "model": model,
                             "isGlossaryView": this.isGlossaryView,
                             "collection": this.glossaryCollection,
-                            "callback": function(newModel) {
-                                that.data = newModel;
-                                model.set(newModel);
+                            "callback": function(data) {
+                                model.set(_.extend({}, model.toJSON(), data), 
{ silent: true });
+                                that.data = data;
                                 that.renderDetails(that.data);
-                                
//that.glossaryCollection.trigger("update:details");
+                                
that.glossaryCollection.trigger("update:details", { isGlossaryUpdate: true });
                             }
                         });
                     } else {
@@ -116,15 +135,33 @@ define(['require',
                             "isCategoryView": this.isCategoryView,
                             "model": this.data,
                             "collection": this.glossaryCollection,
-                            "callback": function() {
-                                that.getData();
-                                
that.glossaryCollection.trigger("update:details");
+                            "callback": function(data) {
+                                if (data.displayName != that.data.displayName) 
{
+                                    var glossary = 
that.glossaryCollection.fullCollection.get(data.anchor.glossaryGuid);
+                                    if (that.isTermView) {
+                                        _.find(glossary.get('terms'), 
function(obj) {
+                                            if (obj.termGuid == data.guid) {
+                                                obj.displayText = 
data.displayName
+                                            }
+                                        });
+                                    } else if (!data.parentCategory) {
+                                        _.find(glossary.get('categories'), 
function(obj) {
+                                            if (obj.categoryGuid == data.guid) 
{
+                                                obj.displayText = 
data.displayName
+                                            }
+                                        });
+                                    }
+                                    
that.glossaryCollection.trigger("update:details", { data: that.data });
+                                }
+                                that.data = data;
+                                that.renderDetails(that.data);
                             }
                         });
                     }
                 };
                 events["click " + this.ui.addTerm] = 'onClickAddTermBtn';
                 events["click " + this.ui.addCategory] = 
'onClickAddCategoryBtn';
+                events["click " + this.ui.addTag] = 'onClickAddTagBtn';
                 return events;
             },
             /**
@@ -144,6 +181,7 @@ define(['require',
                 }
             },
             onRender: function() {
+                this.$('.fontLoader-relative').show();
                 this.getData();
                 this.bindEvents();
             },
@@ -165,8 +203,20 @@ define(['require',
                         "guid": this.guid,
                         "ajaxOptions": {
                             success: function(data) {
+                                if (that.isDestroyed) {
+                                    return;
+                                }
                                 if (that.isTermView) {
-                                    that.renderSearchResultLayoutView();
+                                    var obj = {
+                                        "guid": that.guid,
+                                        "entityDefCollection": 
that.entityDefCollection,
+                                        "typeHeaders": that.typeHeaders,
+                                        "tagCollection": that.collection,
+                                        "enumDefCollection": 
that.enumDefCollection,
+                                        "classificationDefCollection": 
that.classificationDefCollection
+                                    }
+                                    that.renderSearchResultLayoutView(obj);
+                                    that.renderTagTableLayoutView(obj);
                                 }
                                 that.data = data;
                                 that.glossary.selectedItem.model = data;
@@ -185,7 +235,7 @@ define(['require',
                 this.ui.longDescription.text(data.longDescription);
                 this.generateCategories(data.categories);
                 this.generateTerm(data.terms);
-
+                this.generateTag(data.classifications);
             },
             generateCategories: function(data) {
                 var that = this,
@@ -208,6 +258,15 @@ define(['require',
                 this.ui.termList.prepend(terms);
 
             },
+            generateTag: function(tagObject) {
+                var that = this,
+                    tagData = "";
+                _.each(tagObject, 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="removeTag" data-type="tag" 
title="Remove Tag"></i></span>';
+                });
+                this.ui.tagList.find("span.btn").remove();
+                this.ui.tagList.prepend(tagData);
+            },
             onClickAddTermBtn: function(e) {
                 var that = this;
                 require(['views/glossary/AssignTermLayoutView'], 
function(AssignTermLayoutView) {
@@ -240,6 +299,45 @@ define(['require',
                     });
                 });
             },
+            onClickAddTagBtn: function(e) {
+                var that = this;
+                require(['views/tag/AddTagModalView'], 
function(AddTagModalView) {
+                    var tagList = [];
+                    _.map(that.data.classifications, function(obj) {
+                        if (obj.entityGuid === that.guid) {
+                            tagList.push(obj.typeName);
+                        }
+                    });
+                    var view = new AddTagModalView({
+                        guid: that.guid,
+                        tagList: tagList,
+                        callback: function() {
+                            that.getData();
+                        },
+                        showLoader: that.showLoader.bind(that),
+                        hideLoader: that.hideLoader.bind(that),
+                        collection: that.classificationDefCollection,
+                        enumDefCollection: that.enumDefCollection
+                    });
+                });
+            },
+            onClickTagCross: function(e) {
+                var that = this,
+                    tagName = $(e.currentTarget).text(),
+                    termName = this.data.displayName;
+                CommonViewFunction.deleteTag(_.extend({}, {
+                    msg: "<div class='ellipsis'>Remove: " + "<b>" + 
_.escape(tagName) + "</b> assignment from" + " " + "<b>" + termName + 
"?</b></div>",
+                    titleMessage: Messages.removeTag,
+                    okText: "Remove",
+                    showLoader: that.showLoader.bind(that),
+                    hideLoader: that.hideLoader.bind(that),
+                    tagName: tagName,
+                    guid: that.guid,
+                    callback: function() {
+                        that.getData();
+                    }
+                }));
+            },
             onClickRemoveAssociationBtn: function(e) {
                 var $el = $(e.currentTarget),
                     guid = $el.data('guid'),
@@ -267,7 +365,17 @@ define(['require',
             hideLoader: function() {
                 Utils.hideTitleLoader(this.$('.page-title .fontLoader'), 
this.ui.details);
             },
-            renderSearchResultLayoutView: function() {
+            renderTagTableLayoutView: function(options) {
+                var that = this;
+                require(['views/tag/TagDetailTableLayoutView'], 
function(TagDetailTableLayoutView) {
+                    that.RTagTableLayoutView.show(new 
TagDetailTableLayoutView(_.extend({}, options, {
+                        "entityName": that.ui.title.text(),
+                        "fetchCollection": that.getData.bind(that),
+                        "entity": that.data
+                    })));
+                });
+            },
+            renderSearchResultLayoutView: function(options) {
                 var that = this;
                 require(['views/search/SearchResultLayoutView'], 
function(SearchResultLayoutView) {
                     var value = {
@@ -275,17 +383,10 @@ define(['require',
                         'searchType': 'basic'
                     };
                     if (that.RSearchResultLayoutView) {
-                        that.RSearchResultLayoutView.show(new 
SearchResultLayoutView({
-                            "value": _.extend({}, that.value, { "searchType": 
"basic" }),
-                            "termName": that.data.qualifiedName,
-                            "guid": that.guid,
-                            "entityDefCollection": that.entityDefCollection,
-                            "typeHeaders": that.typeHeaders,
-                            "tagCollection": that.collection,
-                            "enumDefCollection": that.enumDefCollection,
-                            "classificationDefCollection": 
that.classificationDefCollection,
+                        that.RSearchResultLayoutView.show(new 
SearchResultLayoutView(_.extend({}, options, {
+                            "value": { "searchType": "basic", "term": 
that.data.qualifiedName },
                             "fromView": "glossary"
-                        }));
+                        })));
                     }
                 });
             },

http://git-wip-us.apache.org/repos/asf/atlas/blob/6d51ddec/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js 
b/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js
index 57c58c7..3e13a89 100644
--- a/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js
+++ b/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js
@@ -92,26 +92,42 @@ define(['require',
                 this.isAssignView = this.isAssignTermView || 
this.isAssignCategoryView || this.isAssignEntityView;
                 this.bindEvents();
                 this.query = {
-                    term: {
-                        url: null
-                    },
-                    category: {
-                        url: null
-                    }
+                    term: {},
+                    category: {}
                 };
+                if (Utils.getUrlState.isGlossaryTab() && this.value && 
this.value.viewType) {
+                    this.viewType = this.value.viewType;
+                }
+                this.query[this.viewType] = _.extend({}, this.value, { "guid": 
this.guid });
             },
             bindEvents: function() {
                 var that = this;
-                this.listenTo(this.glossaryCollection.fullCollection, "reset 
add remove change", function() {
+                this.listenTo(this.glossaryCollection.fullCollection, "reset 
add change", function(skip) {
                     this.generateTree();
+                    this.setValues();
                 }, this);
-                this.listenTo(this.glossaryCollection, "update:details", 
function() {
-                    this.getGlossary();
+                this.listenTo(this.glossaryCollection, "update:details", 
function(options) {
+                    var isGlossaryUpdate = options.isGlossaryUpdate;
+                    if (isGlossaryUpdate) {
+                        if (this.ui.termTree.jstree(true).refresh) {
+                            this.ui.termTree.jstree(true).refresh();
+                        }
+                        if (this.ui.categoryTree.jstree(true).refresh) {
+                            this.ui.categoryTree.jstree(true).refresh();
+                        }
+                    } else {
+                        var $tree = this.ui[this.viewType == "term" ? 
"termTree" : "categoryTree"];
+                        if ($tree.jstree(true).refresh) {
+                            $tree.jstree(true).refresh();
+                        }
+                    }
                 }, this);
-                $('body').on('click', '.termPopoverOptions li, 
.categoryPopoverOptions li', function(e) {
-                    that.$('.termPopover,.categoryPopover').popover('hide');
-                    that[$(this).find('a').data('fn')](e)
-                });
+                if (!this.isAssignView) {
+                    $('body').on('click', '.termPopoverOptions li, 
.categoryPopoverOptions li', function(e) {
+                        
that.$('.termPopover,.categoryPopover').popover('hide');
+                        that[$(this).find('a').data('fn')](e)
+                    });
+                }
             },
             onRender: function() {
                 if (this.isAssignCategoryView) {
@@ -124,7 +140,19 @@ define(['require',
                     this.getGlossary();
                 }
             },
+            setValues: function() {
+                if (this.viewType == "category") {
+                    if (!this.ui.glossaryView.prop("checked")) {
+                        this.ui.glossaryView.prop("checked", 
true).trigger("change");
+                    }
+                } else {
+                    if (this.ui.glossaryView.prop("checked")) {
+                        this.ui.glossaryView.prop("checked", 
false).trigger("change");
+                    }
+                }
+            },
             glossaryViewToggle: function(e) {
+                var that = this;
                 if (e.currentTarget.checked) {
                     this.$('.category-view').show();
                     this.$('.term-view').hide();
@@ -134,18 +162,45 @@ define(['require',
                     this.$('.category-view').hide();
                     this.viewType = "term";
                 }
+                var setDefaultSelector = function() {
+                    var model = null;
+                    if (that.value.gId) {
+                        model = 
that.glossaryCollection.fullCollection.get(that.value.gId);
+                    } else {
+                        model = that.glossaryCollection.fullCollection.first();
+                    }
+                    model = model.toJSON ? model.toJSON() : model;
+                    that.glossary.selectedItem = {
+                        type: "Glossary",
+                        guid: model.guid,
+                        id: model.guid,
+                        model: model,
+                        gType: "glossary"
+                    }
+                }
                 if (Utils.getUrlState.isGlossaryTab()) {
-                    // var name = this.query[this.viewType].url;
-                    // var guid = this.glossary.selectedItem.guid;
-                    // Utils.setUrl({
-                    //     url: '#!/glossary/' + guid,
-                    //     urlParams: {
-                    //         viewType: this.viewType,
-                    //     },
-                    //     mergeBrowserUrl: false,
-                    //     trigger: true,
-                    //     updateTabState: true
-                    // });
+                    var obj = this.query[this.viewType],
+                        $tree = this.ui[(this.viewType == "term" ? "termTree" 
: "categoryTree")]
+                    if (obj.guid) {
+                        var node = $tree.jstree(true).get_node(obj.guid);
+                        if (node) {
+                            $tree.jstree('activate_node', obj.guid);
+                            this.glossary.selectedItem = node.original;
+                        } else {
+                            setDefaultSelector();
+                        }
+                    } else {
+                        setDefaultSelector();
+                        $tree.jstree('activate_node', 
that.glossary.selectedItem.guid);
+                    }
+                    this.query[this.viewType] = _.extend(obj, 
_.pick(this.glossary.selectedItem, 'model', 'guid', 'gType'), { "viewType": 
this.viewType, "isNodeNotFoundAtLoad": 
this.query[this.viewType].isNodeNotFoundAtLoad });
+                    Utils.setUrl({
+                        url: '#!/glossary/' + this.glossary.selectedItem.guid,
+                        urlParams: _.extend({}, _.omit(obj, 'guid', 'model', 
'type', 'isNodeNotFoundAtLoad')),
+                        mergeBrowserUrl: false,
+                        trigger: false,
+                        updateTabState: true
+                    });
                 }
             },
             getGlossary: function() {
@@ -162,6 +217,7 @@ define(['require',
                         "glossaryName": options.node.glossaryName,
                         "model": obj,
                         "type": "GlossaryCategory",
+                        "gType": "category",
                         "children": true
                     }
                 });
@@ -188,19 +244,26 @@ define(['require',
             generateData: function(opt) {
                 var that = this,
                     type = opt.type;
+                if (opt.type == this.viewType) {
+                    this.query[opt.type].isNodeNotFoundAtLoad = true;
+                }
                 var getSelectedState = function(options) {
                     var objGuid = options.objGuid,
                         node = options.node,
                         index = options.index;
                     if (!that.guid) {
+                        that.query[that.viewType].isNodeNotFoundAtLoad = false;
                         var selectedItem = {
                             "type": "Glossary",
-                            "model": that.glossaryCollection.first().toJSON()
+                            "gType": "glossary",
+                            "model": 
that.glossaryCollection.fullCollection.first().toJSON()
                         };
                         selectedItem.text = selectedItem.model.displayName;
                         selectedItem.guid = selectedItem.model.guid;
                         if (index == 0 && selectedItem.guid == objGuid) {
                             that.glossary.selectedItem = selectedItem;
+                            that.query[that.viewType].model = 
selectedItem.model;
+                            that.query[that.viewType].type = 
selectedItem.gType;
                             return {
                                 'opened': true,
                                 'selected': true
@@ -208,7 +271,10 @@ define(['require',
                         }
                     } else {
                         if (that.guid == objGuid) {
+                            that.query[that.viewType].isNodeNotFoundAtLoad = 
false;
                             that.glossary.selectedItem = node
+                            that.query[that.viewType].model = node.model;
+                            that.query[that.viewType].type = node.gType;
                             return {
                                 'opened': true,
                                 'selected': true
@@ -225,6 +291,7 @@ define(['require',
                             "id": obj.guid,
                             "model": obj,
                             "type": obj.typeName ? obj.typeName : "Glossary",
+                            "gType": "glossary",
                             "children": []
                         }
                     parent.state = getSelectedState({
@@ -238,11 +305,12 @@ define(['require',
                             if (category.parentCategoryGuid) {
                                 return;
                             }
-                            var type = category.typeName || "GlossaryCategory",
+                            var typeName = category.typeName || 
"GlossaryCategory",
                                 guid = category.categoryGuid,
                                 categoryObj = {
                                     "text": category.displayText,
-                                    "type": type,
+                                    "type": typeName,
+                                    "gType": "category",
                                     "guid": guid,
                                     "id": guid,
                                     "parent": obj,
@@ -262,11 +330,12 @@ define(['require',
                     }
                     if (type == "term" && obj.terms) {
                         _.each(obj.terms, function(term) {
-                            var type = term.typeName || "GlossaryTerm",
+                            var typeName = term.typeName || "GlossaryTerm",
                                 guid = term.termGuid,
                                 termObj = {
                                     "text": term.displayText,
-                                    "type": type,
+                                    "type": typeName,
+                                    "gType": "term",
                                     "guid": guid,
                                     "id": guid,
                                     "parent": obj,
@@ -287,8 +356,32 @@ define(['require',
                 });
             },
             manualRender: function(options) {
-                _.extend(this, options);
-                this.triggerUrl();
+                _.extend(this, _.omit(options, 'isTrigger'));
+                if (this.value && this.value.viewType) {
+                    this.viewType = this.value.viewType;
+                }
+                this.setValues();
+                if (this.guid && this.value && ((this.value.fromView && 
this.value.fromView) || (this.value.updateView))) {
+                    var $tree = this.ui[this.viewType == "term" ? "termTree" : 
"categoryTree"],
+                        node = $tree.jstree(true).get_node(this.guid);
+                    if (node) {
+                        $tree.jstree('activate_node', this.guid);
+                        delete this.value.fromView;
+                        delete this.value.updateView;
+                        this.glossary.selectedItem = node.original;
+                        Utils.setUrl({
+                            url: '#!/glossary/' + this.guid,
+                            urlParams: this.value,
+                            mergeBrowserUrl: false,
+                            trigger: false,
+                            updateTabState: true
+                        });
+                        this.glossaryCollection.trigger("update:details", { 
isGlossaryUpdate: this.value.gType == "glossary" });
+                    }
+                }
+                if (options.isTrigger) {
+                    this.triggerUrl();
+                }
             },
             generateTree: function() {
                 var $termTree = this.ui.termTree,
@@ -298,10 +391,14 @@ define(['require',
                         return {
                             "plugins": ["search", "themes", "core", 
"wholerow", "sort", "conditionalselect"],
                             "conditionalselect": function(node) {
+                                var obj = node && node.original && 
node.original.type;
+                                if (!obj) {
+                                    return;
+                                }
                                 if (that.isAssignView) {
-                                    return node.original.type != "Glossary" ? 
true : false;
+                                    return obj != "Glossary" ? true : false;
                                 } else {
-                                    return node.original.type != "NoAction" ? 
true : false;
+                                    return obj != "NoAction" ? true : false;
                                 }
                             },
                             "core": {
@@ -319,12 +416,10 @@ define(['require',
                             }
                         }
                     },
-                    treeLoaded = function() {
-                        if (that.selectFirstNodeManually) {
-                            that.selectFirstNodeManually = false;
+                    treeLoaded = function(options) {
+                        if (that.query[options.type].isNodeNotFoundAtLoad == 
true) {
                             var id = that.glossary.selectedItem.guid;
-                            $treeEl.jstree('select_node', '#' + id + 
'_anchor');
-                            $treeEl.jstree('open_node', '#' + id + '_anchor');
+                            options.$el.jstree('activate_node', id);
                         }
                     },
                     createAction = function(options) {
@@ -355,10 +450,25 @@ define(['require',
                             })
                             .on("select_node.jstree", function(e, data) {
                                 that.glossary.selectedItem = 
data.node.original;
-                                //$("." + popoverClassName).popover('hide');
-                                that.triggerUrl();
+                                var popoverClassName = (type == "term" ? 
'.termPopover' : '.categoryPopover'),
+                                    currentClickedPopoverEl = "";
+                                if (data.event) {
+                                    if 
($(data.event.currentTarget).parent().hasClass('jstree-leaf')) {
+                                        currentClickedPopoverEl = 
$(data.event.currentTarget).parent().find(popoverClassName);
+                                    } else {
+                                        currentClickedPopoverEl = 
$(data.event.currentTarget).parent().find(">div " + popoverClassName);
+                                    }
+                                    
$(popoverClassName).not(currentClickedPopoverEl).popover('hide');
+                                }
+                                if (that.query[type].isNodeNotFoundAtLoad == 
true) {
+                                    that.query[type].isNodeNotFoundAtLoad = 
false;
+                                } else if (type == that.viewType) {
+                                    that.triggerUrl();
+                                }
                             }).bind('loaded.jstree', function(e, data) {
-                                treeLoaded();
+                                if (that.query[type].isNodeNotFoundAtLoad == 
true) {
+                                    treeLoaded({ "$el": $el, "type": type });
+                                }
                             });
                     },
                     initializeTermTree = function() {
@@ -374,6 +484,7 @@ define(['require',
                     },
                     initializeCategoryTree = function() {
                         if ($categoryTree.data('jstree')) {
+                            $('.categoryPopover').popover('destroy');
                             $categoryTree.jstree(true).refresh();
                         } else {
                             initializeTree({
@@ -409,7 +520,7 @@ define(['require',
                             var node = that.glossary.selectedItem,
                                 liString = "";
                             if (node.type == "Glossary") {
-                                liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' 
data-fn='createSubNode'>Create Sub-Term</a></li>" +
+                                liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' 
data-fn='createSubNode'>Create Term</a></li>" +
                                     "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-trash-o'></i><a href='javascript:void(0)' 
data-fn='deleteNode'>Delete Glossary</a></li>"
                             } else {
                                 liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-trash-o'></i><a href='javascript:void(0)' 
data-fn='deleteNode'>Delete Term</a></li>"
@@ -429,7 +540,7 @@ define(['require',
                             var node = that.glossary.selectedItem,
                                 liString = "";
                             if (node.type == "Glossary") {
-                                liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' 
data-fn='createSubNode'>Create Sub-Category</a></li>" +
+                                liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' 
data-fn='createSubNode'>Create Category</a></li>" +
                                     "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-trash-o'></i><a href='javascript:void(0)' 
data-fn='deleteNode'>Delete Glossary</a></li>"
                             } else {
                                 liString = "<li data-type=" + node.type + " 
class='listTerm'><i class='fa fa-plus'></i> <a href='javascript:void(0)' 
data-fn='createSubNode'>Create Sub-Category</a></li>" +
@@ -466,59 +577,101 @@ define(['require',
             deleteNode: function(opt) {
                 var that = this,
                     messageType = "",
+                    type = this.glossary.selectedItem.type,
+                    guid = this.glossary.selectedItem.guid,
+                    gId = this.glossary.selectedItem.glossaryId,
                     options = {
                         success: function(rModel, response) {
+                            if (!gId) {
+                                gId = guid;
+                            }
+                            var glossary = 
that.glossaryCollection.fullCollection.get(gId);
+                            if (that.value) {
+                                if (that.value.gType == "term") {
+                                    glossary.set('terms', 
_.reject(glossary.get('terms'), function(obj) {
+                                        return obj.termGuid == guid;
+                                    }), { silent: true });
+                                } else if (that.value.gType == "category") {
+                                    glossary.set('categories', 
_.reject(glossary.get('categories'), function(obj) {
+                                        return obj.categoryGuid == guid;
+                                    }), { silent: true });
+                                } else {
+                                    glossary = 
that.glossaryCollection.fullCollection.first();
+                                    if (glossary) {
+                                        gId = glossary.get('guid');
+                                    } else {
+                                        gId = null
+                                    }
+                                }
+                            }
                             Utils.notifySuccess({
                                 content: messageType + 
Messages.deleteSuccessMessage
                             });
-                            that.getGlossary();
+                            var url = gId ? '#!/glossary/' + gId : 
'#!/glossary/';
+                            Utils.setUrl({
+                                url: '#!/glossary/' + gId,
+                                mergeBrowserUrl: false,
+                                trigger: true,
+                                urlParams: gId ? _.extend({}, that.value, {
+                                    gType: 'glossary',
+                                    updateView: true,
+                                    gId: null
+                                }) : null,
+                                updateTabState: true
+                            });
                         }
                     },
-                    type = this.glossary.selectedItem.type,
-                    guid = this.glossary.selectedItem.guid
+                    notifyObj = {
+                        modal: true,
+                        ok: function(argument) {
+                            if (type == "Glossary") {
+                                
that.glossaryCollection.fullCollection.get(guid).destroy(options, { silent: 
true, reset: false });
+                            } else if (type == "GlossaryCategory") {
+                                new 
that.glossaryCollection.model().deleteCategory(guid, options);
+                            } else if (type == "GlossaryTerm") {
+                                new 
that.glossaryCollection.model().deleteTerm(guid, options);
+                            }
+                        },
+                        cancel: function(argument) {}
+                    };
                 if (type == "Glossary") {
                     messageType = "Glossary";
-                    
this.glossaryCollection.fullCollection.get(guid).destroy(options);
                 } else if (type == "GlossaryCategory") {
                     messageType = "Category"
-                    new this.glossaryCollection.model().deleteCategory(guid, 
options);
                 } else if (type == "GlossaryTerm") {
                     messageType = "Term";
-                    new this.glossaryCollection.model().deleteTerm(guid, 
options);
                 }
+                notifyObj['text'] = "Are you sure you want to delete the " + 
messageType;;
+                Utils.notifyConfirm(notifyObj);
             },
-            triggerUrl: function() {
+            triggerUrl: function(options) {
                 if (this.isAssignView) {
                     return;
                 }
                 var selectedItem = this.glossary.selectedItem;
-                if (this.glossaryCollection.length && _.isEmpty(selectedItem)) 
{
+                if (this.glossaryCollection.length && (_.isEmpty(selectedItem) 
|| this.query[this.viewType].isNodeNotFoundAtLoad)) {
                     selectedItem = { "model": 
this.glossaryCollection.first().toJSON() };
                     selectedItem.guid = selectedItem.model.guid;
-                    selectedItem.type = "glossary";
+                    selectedItem.type = "Glossary";
                     this.glossary.selectedItem = selectedItem;
-                    this.selectFirstNodeManually = true;
+                    this.query[this.viewType].model = selectedItem.model;
+                    this.query[this.viewType].gType = "glossary"
+                    delete this.query[this.viewType].gId;
                 }
                 if (_.isEmpty(selectedItem)) {
                     return;
                 }
-                var type = selectedItem.type;
                 if (Utils.getUrlState.isGlossaryTab() || 
Utils.getUrlState.isDetailPage()) {
-                    var urlParams = { gType: "glossary" },
-                        guid = selectedItem.guid;
-                    if (type === "GlossaryTerm") {
-                        urlParams.gType = "term";
-                    } else if (type === "GlossaryCategory") {
-                        urlParams.gType = "category";
-                    }
+                    var obj = {};
                     if (selectedItem.glossaryId) {
-                        urlParams["gId"] = selectedItem.glossaryId;
+                        obj["gId"] = selectedItem.glossaryId;
                     }
+                    this.query[this.viewType] = _.extend(obj, this.value, 
_.pick(this.glossary.selectedItem, 'model', 'type', 'gType', 'guid'), { 
"viewType": this.viewType, "isNodeNotFoundAtLoad": 
this.query[this.viewType].isNodeNotFoundAtLoad });
                     Utils.setUrl({
-                        url: '#!/glossary/' + guid,
+                        url: '#!/glossary/' + obj.guid,
                         mergeBrowserUrl: false,
                         trigger: true,
-                        urlParams: urlParams,
+                        urlParams: _.omit(obj, 'model', 'guid', 'type', 
'isNodeNotFoundAtLoad'),
                         updateTabState: true
                     });
                 }

Reply via email to