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