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> <span class="value">' + _.escape(value.term) + '</span>'; + queryArray.push(tagKeyValue); + } if (value.query) { queryArray.push('<span class="key">Query:</span> <span class="value">' + _.trim(_.escape(value.query)) + '</span> '); } @@ -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 }); }
