Make images loaded lazily on the repo tags page, as they will not be needed in the read-only (common) case.

This commit is contained in:
Joseph Schorr 2015-05-07 15:51:49 -04:00
parent 8eb9c376cd
commit 23fafa6b4a
7 changed files with 107 additions and 38 deletions

View file

@ -2,3 +2,11 @@
font-family: Consolas, "Lucida Console", Monaco, monospace; font-family: Consolas, "Lucida Console", Monaco, monospace;
font-size: 12px; font-size: 12px;
} }
.tag-operations-dialog .loader-container {
height: 10px;
text-align: center;
margin-bottom: 20px;
margin-top: 10px;
position: relative;
}

View file

@ -1,5 +1,5 @@
<div class="repo-panel-tags-element"> <div class="repo-panel-tags-element">
<div class="tab-header-controls" ng-show="images"> <div class="tab-header-controls">
<div class="btn-group btn-group-sm" ng-show="repository.can_write"> <div class="btn-group btn-group-sm" ng-show="repository.can_write">
<button class="btn" ng-class="!showingHistory ? 'btn-primary active' : 'btn-default'" ng-click="showHistory(false)"> <button class="btn" ng-class="!showingHistory ? 'btn-primary active' : 'btn-default'" ng-click="showHistory(false)">
<i class="fa fa-tags"></i>Current Tags <i class="fa fa-tags"></i>Current Tags
@ -17,8 +17,7 @@
is-enabled="showingHistory" ng-show="showingHistory"></div> is-enabled="showingHistory" ng-show="showingHistory"></div>
<!-- Normal View --> <!-- Normal View -->
<div class="resource-view" resource="imagesResource" error-message="'Could not load images'" <div ng-show="!showingHistory">
ng-show="!showingHistory">
<div class="co-check-bar"> <div class="co-check-bar">
<span class="cor-checkable-menu" controller="checkedTags"> <span class="cor-checkable-menu" controller="checkedTags">
<div class="cor-checkable-menu-item" item-filter="allTagFilter"> <div class="cor-checkable-menu-item" item-filter="allTagFilter">
@ -156,7 +155,8 @@
</div> </div>
</div> </div>
<div class="tag-operations-dialog" repository="repository" images="images" <div class="tag-operations-dialog" repository="repository"
get-images="getImages({'callback': callback})"
action-handler="tagActionHandler"></div> action-handler="tagActionHandler"></div>
<div class="fetch-tag-dialog" repository="repository" action-handler="fetchTagActionHandler"></div> <div class="fetch-tag-dialog" repository="repository" action-handler="fetchTagActionHandler"></div>

View file

@ -1,4 +1,24 @@
<div class="tag-operations-dialog-element"> <div class="tag-operations-dialog-element">
<!-- Loading Images Dialog -->
<div class="modal fade" id="loadingImagesModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Loading Repository Images</h4>
</div>
<div class="modal-body">
<div class="loader-container">
<div class="cor-loader"></div>
</div>
<div style="text-align: center;">
Please wait while we load the repository's full image list
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Add Tag Dialog --> <!-- Add Tag Dialog -->
<div class="modal fade" id="createOrMoveTagModal"> <div class="modal fade" id="createOrMoveTagModal">
<div class="modal-dialog"> <div class="modal-dialog">
@ -30,7 +50,7 @@
<div class="tag-specific-images-view" <div class="tag-specific-images-view"
tag="tagToCreate" tag="tagToCreate"
repository="repo" repository="repo"
images="images" images="imagesInternal"
image-cutoff="toTagImage" image-cutoff="toTagImage"
style="margin: 10px; margin-top: 20px; margin-bottom: -10px;" style="margin: 10px; margin-top: 20px; margin-bottom: -10px;"
ng-show="isAnotherImageTag(toTagImage, tagToCreate)"> ng-show="isAnotherImageTag(toTagImage, tagToCreate)">
@ -80,7 +100,7 @@
<span class="label label-default tag">{{ deleteTagInfo.tag }}</span>? <span class="label label-default tag">{{ deleteTagInfo.tag }}</span>?
<div class="tag-specific-images-view" tag="deleteTagInfo.tag" repository="repository" <div class="tag-specific-images-view" tag="deleteTagInfo.tag" repository="repository"
images="images" style="margin-top: 20px"> images="imagesInternal" style="margin-top: 20px">
The following images and any other images not referenced by a tag will be deleted: The following images and any other images not referenced by a tag will be deleted:
</div> </div>
</div> </div>

View file

@ -13,6 +13,8 @@ angular.module('quay').directive('repoPanelTags', function () {
'selectedTags': '=selectedTags', 'selectedTags': '=selectedTags',
'imagesResource': '=imagesResource', 'imagesResource': '=imagesResource',
'images': '=images', 'images': '=images',
'getImages': '&getImages'
}, },
controller: function($scope, $element, $filter, $location, ApiService, UIService) { controller: function($scope, $element, $filter, $location, ApiService, UIService) {
var orderBy = $filter('orderBy'); var orderBy = $filter('orderBy');

View file

@ -14,10 +14,17 @@ angular.module('quay').directive('tagOperationsDialog', function () {
'images': '=images', 'images': '=images',
'actionHandler': '=actionHandler', 'actionHandler': '=actionHandler',
'getImages': '&getImages',
'tagChanged': '&tagChanged' 'tagChanged': '&tagChanged'
}, },
controller: function($scope, $element, $timeout, ApiService) { controller: function($scope, $element, $timeout, ApiService) {
$scope.addingTag = false; $scope.addingTag = false;
$scope.imagesInternal = [];
$scope.$watch('images', function(images) {
if (!images) { return; }
$scope.imagesInternal = images;
});
var markChanged = function(added, removed) { var markChanged = function(added, removed) {
// Reload the repository and the images. // Reload the repository and the images.
@ -142,39 +149,70 @@ angular.module('quay').directive('tagOperationsDialog', function () {
}, errorHandler); }, errorHandler);
}; };
var lazyLoadImages = function(callback) {
if ($scope.imagesInternal.length) {
callback();
return;
}
var isLoading = true;
$timeout(function() {
if (isLoading) {
$('#loadingImagesModal').modal({});
}
}, 500);
var cb = function(images) {
isLoading = false;
$('#loadingImagesModal').modal('hide');
$scope.imagesInternal = images;
callback();
};
$scope.getImages({'callback': cb});
};
$scope.actionHandler = { $scope.actionHandler = {
'askDeleteTag': function(tag) { 'askDeleteTag': function(tag) {
$scope.deleteTagInfo = { lazyLoadImages(function() {
'tag': tag $scope.deleteTagInfo = {
}; 'tag': tag
};
});
}, },
'askDeleteMultipleTags': function(tags) { 'askDeleteMultipleTags': function(tags) {
$scope.deleteMultipleTagsInfo = { lazyLoadImages(function() {
'tags': tags $scope.deleteMultipleTagsInfo = {
}; 'tags': tags
};
});
}, },
'askAddTag': function(image) { 'askAddTag': function(image) {
$scope.tagToCreate = ''; lazyLoadImages(function() {
$scope.toTagImage = image; $scope.tagToCreate = '';
$scope.addingTag = false; $scope.toTagImage = image;
$scope.addTagForm.$setPristine(); $scope.addingTag = false;
$element.find('#createOrMoveTagModal').modal('show'); $scope.addTagForm.$setPristine();
$element.find('#createOrMoveTagModal').modal('show');
});
}, },
'askRevertTag': function(tag, image_id) { 'askRevertTag': function(tag, image_id) {
if (tag.image_id == image_id) { lazyLoadImages(function() {
bootbox.alert('This is the current image for the tag'); if (tag.image_id == image_id) {
return; bootbox.alert('This is the current image for the tag');
} return;
}
$scope.revertTagInfo = { $scope.revertTagInfo = {
'tag': tag, 'tag': tag,
'image_id': image_id 'image_id': image_id
}; };
$element.find('#revertTagModal').modal('show'); $element.find('#revertTagModal').modal('show');
});
} }
}; };
} }

View file

@ -64,6 +64,9 @@
}; };
var loadRepository = function() { var loadRepository = function() {
// Mark the images to be reloaded.
$scope.viewScope.images = null;
var params = { var params = {
'repository': $scope.namespace + '/' + $scope.name 'repository': $scope.namespace + '/' + $scope.name
}; };
@ -77,11 +80,6 @@
$timeout(function() { $timeout(function() {
$scope.setTags($routeParams.tag); $scope.setTags($routeParams.tag);
// Load the images.
if ($scope.imagesRequired) {
loadImages();
}
// Track builds. // Track builds.
if (!$scope.repository.is_building) { if (!$scope.repository.is_building) {
$scope.viewScope.builds = []; $scope.viewScope.builds = [];
@ -93,13 +91,14 @@
}); });
}; };
var loadImages = function() { var loadImages = function(opt_callback) {
var params = { var params = {
'repository': $scope.namespace + '/' + $scope.name 'repository': $scope.namespace + '/' + $scope.name
}; };
$scope.viewScope.imagesResource = ApiService.listRepositoryImagesAsResource(params).get(function(resp) { $scope.viewScope.imagesResource = ApiService.listRepositoryImagesAsResource(params).get(function(resp) {
$scope.viewScope.images = resp.images; $scope.viewScope.images = resp.images;
opt_callback && opt_callback(resp.images);
}); });
}; };
@ -166,16 +165,18 @@
$scope.requireImages = function() { $scope.requireImages = function() {
// Lazily load the repo's images if this is the first call to a tab // Lazily load the repo's images if this is the first call to a tab
// that needs the images. // that needs the images.
if (!$scope.imagesRequired) { if ($scope.viewScope.images == null) {
loadImages(); loadImages();
} }
$scope.imagesRequired = true;
}; };
$scope.handleChangesState = function(value) { $scope.handleChangesState = function(value) {
$scope.viewScope.changesVisible = value; $scope.viewScope.changesVisible = value;
}; };
$scope.getImages = function(callback) {
loadImages(callback);
};
} }
function OldRepoViewCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiService, $routeParams, $rootScope, $location, $timeout, Config, UtilService) { function OldRepoViewCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiService, $routeParams, $rootScope, $location, $timeout, Config, UtilService) {

View file

@ -21,8 +21,7 @@
<i class="fa fa-info-circle"></i> <i class="fa fa-info-circle"></i>
</span> </span>
<span class="cor-tab" tab-title="Tags" tab-target="#tags" <span class="cor-tab" tab-title="Tags" tab-target="#tags">
tab-init="requireImages()">
<i class="fa fa-tags"></i> <i class="fa fa-tags"></i>
</span> </span>
@ -66,7 +65,8 @@
repository="viewScope.repository" repository="viewScope.repository"
images="viewScope.images" images="viewScope.images"
images-resource="viewScope.imagesResource" images-resource="viewScope.imagesResource"
selected-tags="viewScope.selectedTags"></div> selected-tags="viewScope.selectedTags"
get-images="getImages(callback)"></div>
</div> </div>
<!-- Builds --> <!-- Builds -->