This is an automated email from the ASF dual-hosted git repository. kbhatt pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
commit 445c38325b1d0a99dbcf48db107243916fa3985c Author: kevalbhatt <[email protected]> AuthorDate: Tue Apr 28 22:30:24 2020 +0530 ATLAS-3761:- UI: Show progress bar for migration page (cherry picked from commit b4246817251429ec986e9f4a37adca7cf334a2a4) --- dashboardv2/public/css/scss/migration-style.scss | 6 +- dashboardv2/public/css/scss/stats.scss | 62 ++++++++-- dashboardv2/public/js/migration.js | 4 - .../js/templates/migration/MigrationView_tmpl.html | 2 +- .../public/js/templates/site/Statistics_tmpl.html | 12 +- dashboardv2/public/js/utils/Helper.js | 137 +++++++++++---------- .../utils/MigrationEnums.js} | 26 ++-- dashboardv2/public/js/views/site/Statistics.js | 94 ++++++++++++-- dashboardv2/public/migration-status.html.tpl | 8 +- 9 files changed, 239 insertions(+), 112 deletions(-) diff --git a/dashboardv2/public/css/scss/migration-style.scss b/dashboardv2/public/css/scss/migration-style.scss index a54bcef..60c9758 100644 --- a/dashboardv2/public/css/scss/migration-style.scss +++ b/dashboardv2/public/css/scss/migration-style.scss @@ -25,4 +25,8 @@ @import "loader.scss"; @import "theme.scss"; @import "stats.scss"; -@import "override.scss"; \ No newline at end of file +@import "override.scss"; + +.initialLoading { + left: 0px !important; +} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/stats.scss b/dashboardv2/public/css/scss/stats.scss index 2114117..7bf7581 100644 --- a/dashboardv2/public/css/scss/stats.scss +++ b/dashboardv2/public/css/scss/stats.scss @@ -61,6 +61,7 @@ .panel { &.panel-default { padding: 5px; + margin: 5px; } .panel-body { @@ -80,6 +81,12 @@ .table { &.stat-table { + width: 100%; + + td { + display: table-cell; + } + &.notification-table { &.table-striped>tbody>tr:nth-of-type(odd) { background-color: $color_white_lilac_approx; @@ -113,17 +120,54 @@ } } -.refresh-container { - background: white; +.statistics-header { + height: 50px; + width: 100%; + display: flex; + justify-content: center; + align-items: center; position: fixed; - z-index: 9999; - right: 23px; - top: 7px; - border-radius: 23px; + z-index: 999; + top: 0px; + padding: 0px 15px; + background: #fff; + border-bottom: 1px #e8e9ee solid; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .05); + + &>div { + margin: 0px 5px; + } - .btn { - margin: 0px; + pre { + width: 100%; + padding: 5px 10px; + margin: 0px 10px; + color: $gray; + + .color { + color: $color_jungle_green_approx; + font-weight: bold; + } + } + + .progress { + width: 100%; + margin-top: 7px; + margin-bottom: 0px; + + .progress-bar-success { + background-color: $color_jungle_green_approx; + } + } + + .refresh-container { + background: white; border-radius: 23px; - padding: 10px 10px; + + .btn { + margin: 0px; + border-radius: 23px; + padding: 10px 10px; + } } } \ No newline at end of file diff --git a/dashboardv2/public/js/migration.js b/dashboardv2/public/js/migration.js index e49a69f..fca59ce 100644 --- a/dashboardv2/public/js/migration.js +++ b/dashboardv2/public/js/migration.js @@ -77,9 +77,6 @@ require.config({ 'pnotify': { 'exports': ['pnotify'] }, - 'jstree': { - 'deps': ['jquery'] - }, 'd3': { 'exports': ['d3'] } @@ -106,7 +103,6 @@ require.config({ 'moment': 'libs/moment/js/moment.min', 'moment-timezone': 'libs/moment-timezone/moment-timezone-with-data.min', 'jquery-ui': 'external_lib/jquery-ui/jquery-ui.min', - 'jstree': 'libs/jstree/jstree.min', 'd3': 'libs/d3/d3.min' }, diff --git a/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html b/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html index 41a665f..67572fa 100644 --- a/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html +++ b/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html @@ -14,4 +14,4 @@ * See the License for the specific language governing permissions and * limitations under the License. --> -<div id="r_statisticsView" style="padding-top:30px;"></div> \ No newline at end of file +<div id="r_statisticsView" style="padding-top:60px;"></div> \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/Statistics_tmpl.html b/dashboardv2/public/js/templates/site/Statistics_tmpl.html index ce4b9ee..646e37f 100644 --- a/dashboardv2/public/js/templates/site/Statistics_tmpl.html +++ b/dashboardv2/public/js/templates/site/Statistics_tmpl.html @@ -14,8 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. --> -<div class="refresh-container statisticsRefresh hide" data-id="statisticsRefresh"> - <button type="button" class="btn fa fa-refresh pull-right btn-sm btn-action" title="Refresh Data"></button> +<div class="statistics-header col-md-12 hide"> + <div class="progress hide"> + <div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" aria-valuemin="0" aria-valuemax="100" data-id="migrationProgressBar"> + <span data-id="migrationProgressBarValue"></span> + </div> + </div> + <pre class="successStatus hide">Migration is <span class="color">successful</span>. To exit form migration mode, please remove <span class="color">atlas.migration.data.filename</span> property and restart Atlas.</pre> + <div class="refresh-container statisticsRefresh" data-id="statisticsRefresh"> + <button type="button" class="btn fa fa-refresh pull-right btn-sm btn-action" title="Refresh Data"></button> + </div> </div> <div class="panel-group server-stats-container statsContainer hide col-md-12" id="accordion"> <div class="panel panel-default custom-panel expand_collapse_panel-icon" data-id="entity"> diff --git a/dashboardv2/public/js/utils/Helper.js b/dashboardv2/public/js/utils/Helper.js index 88323c8..931c45d 100644 --- a/dashboardv2/public/js/utils/Helper.js +++ b/dashboardv2/public/js/utils/Helper.js @@ -127,83 +127,84 @@ define(['require', $("body").on('click', '.btn', function() { $(this).blur(); }); - $.fn.select2.amd.define("TagHideDeleteButtonAdapter", [ - "select2/utils", - "select2/selection/multiple", - "select2/selection/placeholder", - "select2/selection/eventRelay", - "select2/selection/search", - ], - function(Utils, MultipleSelection, Placeholder, EventRelay, SelectionSearch) { + if ($.fn.select2) { + $.fn.select2.amd.define("TagHideDeleteButtonAdapter", [ + "select2/utils", + "select2/selection/multiple", + "select2/selection/placeholder", + "select2/selection/eventRelay", + "select2/selection/search", + ], + function(Utils, MultipleSelection, Placeholder, EventRelay, SelectionSearch) { - // Decorates MultipleSelection with Placeholder + // Decorates MultipleSelection with Placeholder + + var adapter = Utils.Decorate(MultipleSelection, Placeholder); + adapter = Utils.Decorate(adapter, SelectionSearch); + adapter = Utils.Decorate(adapter, EventRelay); + + adapter.prototype.render = function() { + // Use selection-box from SingleSelection adapter + // This implementation overrides the default implementation + var $search = $( + '<li class="select2-search select2-search--inline">' + + '<input class="select2-search__field" type="search" tabindex="-1"' + + ' autocomplete="off" autocorrect="off" autocapitalize="none"' + + ' spellcheck="false" role="textbox" aria-autocomplete="list" />' + + '</li>' + ); - var adapter = Utils.Decorate(MultipleSelection, Placeholder); - adapter = Utils.Decorate(adapter, SelectionSearch); - adapter = Utils.Decorate(adapter, EventRelay); + this.$searchContainer = $search; + this.$search = $search.find('input'); + var $selection = MultipleSelection.prototype.render.call(this); + this._transferTabIndex(); + return $selection; + }; - adapter.prototype.render = function() { - // Use selection-box from SingleSelection adapter - // This implementation overrides the default implementation - var $search = $( - '<li class="select2-search select2-search--inline">' + - '<input class="select2-search__field" type="search" tabindex="-1"' + - ' autocomplete="off" autocorrect="off" autocapitalize="none"' + - ' spellcheck="false" role="textbox" aria-autocomplete="list" />' + - '</li>' - ); + adapter.prototype.update = function(data) { + // copy and modify SingleSelection adapter + var that = this; + this.clear(); + if (data.length === 0) { + this.$selection.find('.select2-selection__rendered') + .append(this.$searchContainer); + this.$search.attr('placeholder', this.options.get("placeholder")); + return; + } + this.$search.attr('placeholder', ''); + var $rendered = this.$selection.find('.select2-selection__rendered'), + $selectionContainer = []; + if (data.length > 0) { + _.each(data, function(obj) { + var $container = $('<li class="select2-selection__choice"></li>'), + formatted = that.display(obj, $rendered), + $remove = $('<span class="select2-selection__choice__remove" role="presentation">×</span>'), + allowRemoveAttr = $(obj.element).data("allowremove"), + allowRemove = obj.allowRemove === undefined ? allowRemoveAttr : obj.allowRemove; + if (allowRemove === undefined || allowRemove !== false) { + $container.append($remove); + } + $container.data("data", obj); + $container.append(formatted); + $selectionContainer.push($container); + }); + Utils.appendMany($rendered, $selectionContainer); + } - this.$searchContainer = $search; - this.$search = $search.find('input'); - var $selection = MultipleSelection.prototype.render.call(this); - this._transferTabIndex(); - return $selection; - }; - adapter.prototype.update = function(data) { - // copy and modify SingleSelection adapter - var that = this; - this.clear(); - if (data.length === 0) { + var searchHadFocus = this.$search[0] == document.activeElement; + this.$search.attr('placeholder', ''); this.$selection.find('.select2-selection__rendered') .append(this.$searchContainer); - this.$search.attr('placeholder', this.options.get("placeholder")); - return; - } - this.$search.attr('placeholder', ''); - var $rendered = this.$selection.find('.select2-selection__rendered'), - $selectionContainer = []; - if (data.length > 0) { - _.each(data, function(obj) { - var $container = $('<li class="select2-selection__choice"></li>'), - formatted = that.display(obj, $rendered), - $remove = $('<span class="select2-selection__choice__remove" role="presentation">×</span>'), - allowRemoveAttr = $(obj.element).data("allowremove"), - allowRemove = obj.allowRemove === undefined ? allowRemoveAttr : obj.allowRemove; - if (allowRemove === undefined || allowRemove !== false) { - $container.append($remove); - } - $container.data("data", obj); - $container.append(formatted); - $selectionContainer.push($container); - }); - Utils.appendMany($rendered, $selectionContainer); - } - + this.resizeSearch(); + if (searchHadFocus) { + this.$search.focus(); + } + }; + return adapter; + }); - var searchHadFocus = this.$search[0] == document.activeElement; - this.$search.attr('placeholder', ''); - this.$selection.find('.select2-selection__rendered') - .append(this.$searchContainer); - this.resizeSearch(); - if (searchHadFocus) { - this.$search.focus(); - } - }; - return adapter; - }); - if ($.fn.select2) { $.fn.select2.amd.define("ServiceTypeFilterDropdownAdapter", [ "select2/utils", "select2/dropdown", diff --git a/dashboardv2/public/css/scss/migration-style.scss b/dashboardv2/public/js/utils/MigrationEnums.js similarity index 76% copy from dashboardv2/public/css/scss/migration-style.scss copy to dashboardv2/public/js/utils/MigrationEnums.js index a54bcef..c89b9da 100644 --- a/dashboardv2/public/css/scss/migration-style.scss +++ b/dashboardv2/public/js/utils/MigrationEnums.js @@ -1,4 +1,4 @@ -/* +/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -16,13 +16,17 @@ * limitations under the License. */ -@import "__mixin.scss"; -@import "__variable.scss"; -@import "common.scss"; -@import "table.scss"; -@import "form.scss"; -@import "panel.scss"; -@import "loader.scss"; -@import "theme.scss"; -@import "stats.scss"; -@import "override.scss"; \ No newline at end of file +define(['require'], function(require) { + 'use strict'; + + var Enums = {}; + + Enums.migrationStatus = { + STARTED: "STARTED", + IN_PROGRESS: "IN_PROGRESS", + FAIL: "FAIL", + DONE: "DONE" + } + + return Enums; +}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/Statistics.js b/dashboardv2/public/js/views/site/Statistics.js index 73786d8..868bd62 100644 --- a/dashboardv2/public/js/views/site/Statistics.js +++ b/dashboardv2/public/js/views/site/Statistics.js @@ -28,10 +28,11 @@ define(['require', 'collection/VTagList', 'utils/CommonViewFunction', 'utils/Enums', + 'utils/MigrationEnums', 'moment', 'utils/Utils', 'moment-timezone' -], function(require, Backbone, StatTmpl, StatsNotiTable, TopicOffsetTable, EntityTable, Modal, VCommon, UrlLinks, VTagList, CommonViewFunction, Enums, moment, Utils) { +], function(require, Backbone, StatTmpl, StatsNotiTable, TopicOffsetTable, EntityTable, Modal, VCommon, UrlLinks, VTagList, CommonViewFunction, Enums, MigrationEnums, moment, Utils) { 'use strict'; var StatisticsView = Backbone.Marionette.LayoutView.extend( @@ -57,15 +58,17 @@ define(['require', memoryCard: "[data-id='memory-card']", memoryPoolUsage: "[data-id='memory-pool-usage-card']", statisticsRefresh: "[data-id='statisticsRefresh']", - notificationDetails: "[data-id='notificationDetails']" + notificationDetails: "[data-id='notificationDetails']", + migrationProgressBar: "[data-id='migrationProgressBar']", + migrationProgressBarValue: "[data-id='migrationProgressBarValue']" }, /** ui events hash */ events: function() { var events = {}; events["click " + this.ui.statisticsRefresh] = function(e) { - this.$('.statsContainer,.statsNotificationContainer,.statisticsRefresh').addClass('hide'); - this.$('.statsLoader,.statsNotificationLoader').addClass('show'); + this.showLoader(); this.fetchMetricData(); + this.fetchStatusData(); }; return events; }, @@ -77,7 +80,11 @@ define(['require', _.extend(this, options); var that = this; this.DATA_MAX_LENGTH = 25; - if (this.isMigrationView !== true) { + this.loaderCount = 0; + if (this.isMigrationView) { + this.migrationImportStatus = new VTagList(); + this.migrationImportStatus.url = UrlLinks.migrationStatusApiUrl(); + } else { var modal = new Modal({ title: 'Statistics', content: this, @@ -110,8 +117,54 @@ define(['require', }) } }, + fetchStatusData: function() { + var that = this; + ++this.loaderCount; + that.migrationImportStatus.fetch({ + success: function(data) { + var data = _.first(data.toJSON()), + migrationStatus = data.MigrationStatus || null, + operationStatus = migrationStatus.operationStatus, + showProgress = true, + totalProgress = 0, + progressMessage = ""; + if (migrationStatus) { + if (MigrationEnums.migrationStatus[operationStatus] === "DONE") { + showProgress = false; + } else if (MigrationEnums.migrationStatus[operationStatus] === "IN_PROGRESS" || MigrationEnums.migrationStatus[operationStatus] === "STARTED") { + var currentIndex = migrationStatus.currentIndex || 0, + totalCount = migrationStatus.totalCount || 0; + totalProgress = Math.ceil((migrationStatus.currentIndex / migrationStatus.totalCount) * 100) + progressMessage = totalProgress + "%"; + that.ui.migrationProgressBar.removeClass("progress-bar-danger"); + that.ui.migrationProgressBar.addClass("progress-bar-success"); + } else if (MigrationEnums.migrationStatus[operationStatus] === "FAIL") { + totalProgress = "100"; + progressMessage = "Failed"; + that.ui.migrationProgressBar.addClass("progress-bar-danger"); + that.ui.migrationProgressBar.removeClass("progress-bar-success"); + } + if (showProgress) { + that.$el.find(".statistics-header>.progress").removeClass("hide"); + that.$el.find(".statistics-header>.successStatus").addClass("hide"); + that.ui.migrationProgressBar.css({ width: totalProgress + '%' }); + that.ui.migrationProgressBarValue.text(progressMessage); + } else { + that.$el.find(".statistics-header>.progress").addClass("hide"); + that.$el.find(".statistics-header>.successStatus").removeClass("hide"); + } + } + + }, + complete: function() { + --that.loaderCount; + that.hideLoader(); + } + }); + }, fetchMetricData: function(options) { var that = this; + ++this.loaderCount; this.metricCollection.fetch({ success: function(data) { var data = _.first(data.toJSON()); @@ -119,11 +172,6 @@ define(['require', that.renderEntities({ data: data }); that.renderSystemDeatils({ data: data }); that.renderClassifications({ data: data }); - that.$('.statsContainer,.statsNotificationContainer').removeClass('hide'); - if (that.isMigrationView) { - that.$('.statisticsRefresh').removeClass('hide'); - } - that.$('.statsLoader,.statsNotificationLoader').removeClass('show'); if (options && options.update) { if (that.modal) { that.modal.$el.find('.header-button .fa-refresh').prop('disabled', false).removeClass('fa-spin'); @@ -132,11 +180,37 @@ define(['require', content: "Metric data is refreshed" }) } + }, + complete: function() { + --that.loaderCount; + that.hideLoader() } }); }, + hideLoader: function() { + if (this.loaderCount === 0) { + var className = ".statsContainer"; + if (this.isMigrationView) { + className += ",.statistics-header"; + } + this.$(className).removeClass('hide'); + this.$('.statsLoader').removeClass('show'); + } + }, + showLoader: function() { + var className = ".statsContainer"; + if (this.isMigrationView) { + className += ",.statistics-header"; + } + this.$(className).addClass('hide'); + this.$('.statsLoader').addClass('show'); + }, onRender: function() { this.bindEvents(); + if (this.isMigrationView) { + this.showLoader(); + this.fetchStatusData(); + } this.fetchMetricData(); }, closePanel: function(options) { diff --git a/dashboardv2/public/migration-status.html.tpl b/dashboardv2/public/migration-status.html.tpl index 74d94d7..1e7c991 100644 --- a/dashboardv2/public/migration-status.html.tpl +++ b/dashboardv2/public/migration-status.html.tpl @@ -45,12 +45,8 @@ </head> <body> - <div class="container-fluid"> - <div class="col-sm-12"> - <div class="page-wrapper"> - <div class="initialLoading"></div> - </div> - </div> + <div class="page-wrapper"> + <div class="initialLoading"></div> </div> <!-- build:js scripts/main.js --> <script data-main="js/migration.js?bust=<%- bust %>" src="js/libs/requirejs/require.js?bust=<%- bust %>"></script>
