From ff4644261fad4e68817ee482100c2a819c0a0a5e Mon Sep 17 00:00:00 2001 From: BubaVV Date: Tue, 16 Oct 2018 16:34:18 +0300 Subject: [PATCH] Periodically check item status if it in transition state Several Angular based dashboards, such as images and snapshots, not regenerated after some item on this page changes its status from transition state. For example, an image may be shown forever in the "Creating" state with running progress bar. To improve UI this patch re-upload items list until some item in transition state. If status of item changed, then 'trackBy' field changed and Angular will re-render row with this particular item with ng-repeat-start directive and won't re-render all entire page. Change-Id: I2308baebb65b11180d66bd69d834386022c2ad84 Closes-bug: #1797592 --- .../table/hz-resource-table.controller.js | 21 ++++++++++++++++--- .../hz-resource-table.controller.spec.js | 12 +++++++++-- openstack_dashboard/api/rest/config.py | 4 +++- .../static/app/core/images/images.service.js | 2 +- .../app/core/images/images.service.spec.js | 4 ++-- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/horizon/static/framework/widgets/table/hz-resource-table.controller.js b/horizon/static/framework/widgets/table/hz-resource-table.controller.js index 89adaa46d6..d45cd9aa8e 100644 --- a/horizon/static/framework/widgets/table/hz-resource-table.controller.js +++ b/horizon/static/framework/widgets/table/hz-resource-table.controller.js @@ -27,7 +27,8 @@ 'horizon.framework.widgets.magic-search.events', 'horizon.framework.widgets.magic-search.service', 'horizon.framework.util.actions.action-result.service', - 'horizon.framework.conf.resource-type-registry.service' + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.app.core.openstack-service-api.settings' ]; function controller( @@ -37,10 +38,13 @@ magicSearchEvents, searchService, actionResultService, - registry + registry, + settings ) { var ctrl = this; + var lastSearchQuery = {}; + var timerRunning = false; // 'Public' Controller members ctrl.actionResultHandler = actionResultHandler; @@ -50,6 +54,11 @@ ctrl.items = []; ctrl.itemsSrc = []; ctrl.itemInTransitionFunction = itemInTransitionFunction; + ctrl.ajaxPollInterval = 2500; + settings.getSetting('AJAX_POLL_INTERVAL').then( + function (response) { + ctrl.ajaxPollInterval = response; + }); // Watch for changes to search bar $scope.$on(magicSearchEvents.SERVER_SEARCH_UPDATED, handleServerSearch); @@ -171,6 +180,7 @@ function onLoad(response) { ctrl.itemsSrc = response.data.items; + timerRunning = false; } function actionResultHandler(returnValue) { @@ -236,7 +246,12 @@ } function itemInTransitionFunction(item) { - return ctrl.resourceType.itemInTransitionFunction(item); + var itemInTransition = ctrl.resourceType.itemInTransitionFunction(item); + if (ctrl.ajaxPollInterval && itemInTransition && !timerRunning) { + timerRunning = true; + setTimeout(listResources, ctrl.ajaxPollInterval); + } + return itemInTransition; } } diff --git a/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js b/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js index 399045c550..3671cf15a3 100644 --- a/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js +++ b/horizon/static/framework/widgets/table/hz-resource-table.controller.spec.js @@ -18,7 +18,8 @@ 'use strict'; describe('hz-generic-table controller', function() { - var ctrl, listFunctionDeferred, actionResultDeferred, needsFilterFirstFunctionDeferred, $scope; + var ctrl, listFunctionDeferred, actionResultDeferred, + needsFilterFirstFunctionDeferred, $scope, settingCall; beforeEach(module('horizon.framework.util')); beforeEach(module('horizon.framework.conf')); @@ -65,9 +66,16 @@ spyOn(resourceType, 'list').and.returnValue(listFunctionDeferred.promise); spyOn(registry, 'getResourceType').and.returnValue(resourceType); + var settings = { + getSetting: function() { + settingCall = $q.defer(); + return settingCall.promise; + } + }; ctrl = $controller('horizon.framework.widgets.table.ResourceTableController', { $scope: $scope, - 'horizon.framework.conf.resource-type-registry.service': registry}, + 'horizon.framework.conf.resource-type-registry.service': registry, + 'horizon.app.core.openstack-service-api.settings': settings}, {resourceTypeName: 'OS::Test::Example'}); $scope.ctrl = ctrl; $scope.$apply(); diff --git a/openstack_dashboard/api/rest/config.py b/openstack_dashboard/api/rest/config.py index a216cd3496..9bca3fd39b 100644 --- a/openstack_dashboard/api/rest/config.py +++ b/openstack_dashboard/api/rest/config.py @@ -43,7 +43,9 @@ class Settings(generic.View): 'HORIZON_IMAGES_UPLOAD_MODE': api.glance.get_image_upload_mode(), 'HORIZON_ACTIVE_IMAGE_VERSION': str(api.glance.VERSIONS.active), 'IMAGES_ALLOW_LOCATION': getattr(settings, 'IMAGES_ALLOW_LOCATION', - False) + False), + 'AJAX_POLL_INTERVAL': settings.HORIZON_CONFIG.get( + 'ajax_poll_interval', 2500) } @rest_utils.ajax() diff --git a/openstack_dashboard/static/app/core/images/images.service.js b/openstack_dashboard/static/app/core/images/images.service.js index a039a8519c..cd113c0c66 100644 --- a/openstack_dashboard/static/app/core/images/images.service.js +++ b/openstack_dashboard/static/app/core/images/images.service.js @@ -132,7 +132,7 @@ return {data: {items: response.data.items.map(modifyImage)}}; function modifyImage(image) { - image.trackBy = image.id + image.updated_at; + image.trackBy = image.id + image.updated_at + image.status; image.apiVersion = version; image.visibility = $filter('imageVisibility')(image, projectId); image.name = image.name || image.id; diff --git a/openstack_dashboard/static/app/core/images/images.service.spec.js b/openstack_dashboard/static/app/core/images/images.service.spec.js index ebab4f0ff0..d94fae09cc 100644 --- a/openstack_dashboard/static/app/core/images/images.service.spec.js +++ b/openstack_dashboard/static/app/core/images/images.service.spec.js @@ -95,11 +95,11 @@ spyOn(glance, 'getVersion').and.returnValue(deferredVersion.promise); spyOn(session, 'get').and.returnValue(deferredSession.promise); var result = service.getImagesPromise({}); - deferred.resolve({data: {items: [{id: 1, updated_at: 'jul1'}]}}); + deferred.resolve({data: {items: [{id: 1, updated_at: 'jul1', status: 'active'}]}}); deferredVersion.resolve({data: {version: '2'}}); deferredSession.resolve({project_id: '12'}); $timeout.flush(); - expect(result.$$state.value.data.items[0].trackBy).toBe('1jul1'); + expect(result.$$state.value.data.items[0].trackBy).toBe('1jul1active'); })); });