Merge master into bitbucket
This commit is contained in:
commit
b96e35b28c
44 changed files with 695 additions and 110 deletions
26
static/js/directives/filters/abbreviated.js
Normal file
26
static/js/directives/filters/abbreviated.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Filter which displays numbers with suffixes.
|
||||
*
|
||||
* Based on: https://gist.github.com/pedrorocha-net/9aa21d5f34d9cc15d18f
|
||||
*/
|
||||
angular.module('quay').filter('abbreviated', function() {
|
||||
return function(number) {
|
||||
if (number >= 10000000) {
|
||||
return (number / 1000000).toFixed(0) + 'M'
|
||||
}
|
||||
|
||||
if (number >= 1000000) {
|
||||
return (number / 1000000).toFixed(1) + 'M'
|
||||
}
|
||||
|
||||
if (number >= 10000) {
|
||||
return (number / 1000).toFixed(0) + 'K'
|
||||
}
|
||||
|
||||
if (number >= 1000) {
|
||||
return (number / 1000).toFixed(1) + 'K'
|
||||
}
|
||||
|
||||
return number
|
||||
}
|
||||
});
|
25
static/js/directives/ng-transcope.js
Normal file
25
static/js/directives/ng-transcope.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Directive to transclude a template under an ng-repeat. From: http://stackoverflow.com/a/24512435
|
||||
*/
|
||||
angular.module('quay').directive('ngTranscope', function() {
|
||||
return {
|
||||
link: function( $scope, $element, $attrs, controller, $transclude ) {
|
||||
if ( !$transclude ) {
|
||||
throw minErr( 'ngTranscope' )( 'orphan',
|
||||
'Illegal use of ngTransclude directive in the template! ' +
|
||||
'No parent directive that requires a transclusion found. ' +
|
||||
'Element: {0}',
|
||||
startingTag( $element ));
|
||||
}
|
||||
var innerScope = $scope.$new();
|
||||
|
||||
$transclude( innerScope, function( clone ) {
|
||||
$element.empty();
|
||||
$element.append( clone );
|
||||
$element.on( '$destroy', function() {
|
||||
innerScope.$destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -57,14 +57,16 @@ angular.module('quay').directive('repoPanelBuilds', function () {
|
|||
$scope.fullBuilds = orderBy(unordered, $scope.options.predicate, $scope.options.reverse);
|
||||
};
|
||||
|
||||
var loadBuilds = function() {
|
||||
var loadBuilds = function(opt_forcerefresh) {
|
||||
if (!$scope.builds || !$scope.repository || !$scope.options.filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: We only refresh if the filter has changed.
|
||||
var filter = $scope.options.filter;
|
||||
if ($scope.buildsResource && filter == $scope.currentFilter) { return; }
|
||||
if ($scope.buildsResource && filter == $scope.currentFilter && !opt_forcerefresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
var since = null;
|
||||
var limit = 10;
|
||||
|
@ -104,17 +106,30 @@ angular.module('quay').directive('repoPanelBuilds', function () {
|
|||
}
|
||||
|
||||
// Replace any build records with updated records from the server.
|
||||
var requireReload = false;
|
||||
$scope.builds.map(function(build) {
|
||||
var found = false;
|
||||
for (var i = 0; i < $scope.allBuilds.length; ++i) {
|
||||
var current = $scope.allBuilds[i];
|
||||
if (current.id == build.id && current.phase != build.phase) {
|
||||
$scope.allBuilds[i] = build;
|
||||
break
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the build was not found, then a new build has started. Reload
|
||||
// the builds list.
|
||||
if (!found) {
|
||||
requireReload = true;
|
||||
}
|
||||
});
|
||||
|
||||
updateBuilds();
|
||||
if (requireReload) {
|
||||
loadBuilds(/* force refresh */true);
|
||||
} else {
|
||||
updateBuilds();
|
||||
}
|
||||
};
|
||||
|
||||
var loadBuildTriggers = function() {
|
||||
|
|
|
@ -96,20 +96,24 @@ angular.module('quay').directive('repoPanelChanges', function () {
|
|||
'isEnabled': '=isEnabled'
|
||||
},
|
||||
controller: function($scope, $element, $timeout, ApiService, UtilService, ImageMetadataService) {
|
||||
$scope.tagNames = [];
|
||||
|
||||
var update = function() {
|
||||
if (!$scope.repository || !$scope.selectedTags) { return; }
|
||||
if (!$scope.repository || !$scope.isEnabled) { return; }
|
||||
|
||||
$scope.tagNames = Object.keys($scope.repository.tags);
|
||||
$scope.currentImage = null;
|
||||
$scope.currentTag = null;
|
||||
|
||||
if (!$scope.tracker) {
|
||||
if ($scope.tracker) {
|
||||
refreshTree();
|
||||
} else {
|
||||
updateImages();
|
||||
}
|
||||
};
|
||||
|
||||
var updateImages = function() {
|
||||
if (!$scope.repository || !$scope.images) { return; }
|
||||
if (!$scope.repository || !$scope.images || !$scope.isEnabled) { return; }
|
||||
|
||||
$scope.tracker = new RepositoryImageTracker($scope.repository, $scope.images);
|
||||
|
||||
|
@ -120,16 +124,17 @@ angular.module('quay').directive('repoPanelChanges', function () {
|
|||
|
||||
$scope.$watch('selectedTags', update)
|
||||
$scope.$watch('repository', update);
|
||||
$scope.$watch('isEnabled', update);
|
||||
|
||||
$scope.$watch('images', updateImages);
|
||||
|
||||
$scope.$watch('isEnabled', function(isEnabled) {
|
||||
if (isEnabled) {
|
||||
refreshTree();
|
||||
}
|
||||
});
|
||||
$scope.updateState = function() {
|
||||
update();
|
||||
};
|
||||
|
||||
var refreshTree = function() {
|
||||
if (!$scope.repository || !$scope.images) { return; }
|
||||
if (!$scope.repository || !$scope.images || !$scope.isEnabled) { return; }
|
||||
if ($scope.selectedTags.length < 1) { return; }
|
||||
|
||||
$('#image-history-container').empty();
|
||||
|
||||
|
@ -149,6 +154,7 @@ angular.module('quay').directive('repoPanelChanges', function () {
|
|||
// Give enough time for the UI to be drawn before we resize the tree.
|
||||
$timeout(function() {
|
||||
$scope.tree.notifyResized();
|
||||
$scope.setTag($scope.selectedTags[0]);
|
||||
}, 100);
|
||||
|
||||
// Listen for changes to the selected tag and image in the tree.
|
||||
|
|
35
static/js/directives/ui/multiselect-dropdown.js
Normal file
35
static/js/directives/ui/multiselect-dropdown.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* An element which displays a dropdown for selecting multiple elements.
|
||||
*/
|
||||
angular.module('quay').directive('multiselectDropdown', function ($compile) {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/multiselect-dropdown.html',
|
||||
transclude: true,
|
||||
replace: false,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'items': '=items',
|
||||
'selectedItems': '=selectedItems',
|
||||
'itemName': '@itemName',
|
||||
'itemChecked': '&itemChecked'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
$scope.isChecked = function(checked, item) {
|
||||
return checked.indexOf(item) >= 0;
|
||||
};
|
||||
|
||||
$scope.toggleItem = function(item) {
|
||||
var isChecked = $scope.isChecked($scope.selectedItems, item);
|
||||
if (!isChecked) {
|
||||
$scope.selectedItems.push(item);
|
||||
} else {
|
||||
var index = $scope.selectedItems.indexOf(item);
|
||||
$scope.selectedItems.splice(index, 1);
|
||||
}
|
||||
$scope.itemChecked({'item': item, 'checked': !isChecked});
|
||||
};
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
|
@ -128,6 +128,15 @@ angular.module('quay').directive('robotsManager', function () {
|
|||
}, ApiService.errorDisplay('Cannot delete robot account'));
|
||||
};
|
||||
|
||||
|
||||
$scope.askDeleteRobot = function(info) {
|
||||
bootbox.confirm('Are you sure you want to delete robot ' + info.name + '?', function(resp) {
|
||||
if (resp) {
|
||||
$scope.deleteRobot(info);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var update = function() {
|
||||
if (!$scope.user && !$scope.organization) { return; }
|
||||
if ($scope.loading || !$scope.isEnabled) { return; }
|
||||
|
|
Reference in a new issue