Merge branch 'master' into nomenclature
Conflicts: test/data/test.db
This commit is contained in:
commit
f4681f2c18
60 changed files with 1716 additions and 496 deletions
260
static/js/app.js
260
static/js/app.js
|
@ -621,7 +621,8 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
}]);
|
||||
|
||||
|
||||
$provide.factory('TriggerService', ['UtilService', '$sanitize', function(UtilService, $sanitize) {
|
||||
$provide.factory('TriggerService', ['UtilService', '$sanitize', 'KeyService',
|
||||
function(UtilService, $sanitize, KeyService) {
|
||||
var triggerService = {};
|
||||
|
||||
var triggerTypes = {
|
||||
|
@ -640,10 +641,29 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
'type': 'option',
|
||||
'name': 'branch_name'
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
'get_redirect_url': function(namespace, repository) {
|
||||
var redirect_uri = KeyService['githubRedirectUri'] + '/trigger/' +
|
||||
namespace + '/' + repository;
|
||||
|
||||
var authorize_url = KeyService['githubTriggerAuthorizeUrl'];
|
||||
var client_id = KeyService['githubTriggerClientId'];
|
||||
|
||||
return authorize_url + 'client_id=' + client_id +
|
||||
'&scope=repo,user:email&redirect_uri=' + redirect_uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
triggerService.getRedirectUrl = function(name, namespace, repository) {
|
||||
var type = triggerTypes[name];
|
||||
if (!type) {
|
||||
return '';
|
||||
}
|
||||
return type['get_redirect_url'](namespace, repository);
|
||||
};
|
||||
|
||||
triggerService.getDescription = function(name, config) {
|
||||
var type = triggerTypes[name];
|
||||
if (!type) {
|
||||
|
@ -1313,29 +1333,37 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
'id': 'repo_push',
|
||||
'title': 'Push to Repository',
|
||||
'icon': 'fa-upload'
|
||||
},
|
||||
{
|
||||
'id': 'build_queued',
|
||||
'title': 'Dockerfile Build Queued',
|
||||
'icon': 'fa-tasks'
|
||||
},
|
||||
{
|
||||
'id': 'build_start',
|
||||
'title': 'Dockerfile Build Started',
|
||||
'icon': 'fa-circle-o-notch'
|
||||
},
|
||||
{
|
||||
'id': 'build_success',
|
||||
'title': 'Dockerfile Build Successfully Completed',
|
||||
'icon': 'fa-check-circle-o'
|
||||
},
|
||||
{
|
||||
'id': 'build_failure',
|
||||
'title': 'Dockerfile Build Failed',
|
||||
'icon': 'fa-times-circle-o'
|
||||
}
|
||||
];
|
||||
|
||||
if (Features.BUILD_SUPPORT) {
|
||||
var buildEvents = [
|
||||
{
|
||||
'id': 'build_queued',
|
||||
'title': 'Dockerfile Build Queued',
|
||||
'icon': 'fa-tasks'
|
||||
},
|
||||
{
|
||||
'id': 'build_start',
|
||||
'title': 'Dockerfile Build Started',
|
||||
'icon': 'fa-circle-o-notch'
|
||||
},
|
||||
{
|
||||
'id': 'build_success',
|
||||
'title': 'Dockerfile Build Successfully Completed',
|
||||
'icon': 'fa-check-circle-o'
|
||||
},
|
||||
{
|
||||
'id': 'build_failure',
|
||||
'title': 'Dockerfile Build Failed',
|
||||
'icon': 'fa-times-circle-o'
|
||||
}];
|
||||
|
||||
for (var i = 0; i < buildEvents.length; ++i) {
|
||||
events.push(buildEvents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var methods = [
|
||||
{
|
||||
'id': 'quay_notification',
|
||||
|
@ -1538,7 +1566,7 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
if (metadata.updated_tags && Object.getOwnPropertyNames(metadata.updated_tags).length) {
|
||||
return 'Repository {repository} has been pushed with the following tags updated: {updated_tags}';
|
||||
} else {
|
||||
return 'Repository {repository} has been pushed';
|
||||
return 'Repository {repository} fhas been pushed';
|
||||
}
|
||||
},
|
||||
'page': function(metadata) {
|
||||
|
@ -1686,21 +1714,31 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
|
||||
$provide.factory('KeyService', ['$location', 'Config', function($location, Config) {
|
||||
var keyService = {}
|
||||
var oauth = window.__oauth;
|
||||
|
||||
keyService['stripePublishableKey'] = Config['STRIPE_PUBLISHABLE_KEY'];
|
||||
|
||||
keyService['githubClientId'] = Config['GITHUB_CLIENT_ID'];
|
||||
keyService['githubLoginClientId'] = Config['GITHUB_LOGIN_CLIENT_ID'];
|
||||
keyService['githubRedirectUri'] = Config.getUrl('/oauth2/github/callback');
|
||||
keyService['githubTriggerClientId'] = oauth['GITHUB_TRIGGER_CONFIG']['CLIENT_ID'];
|
||||
keyService['githubLoginClientId'] = oauth['GITHUB_LOGIN_CONFIG']['CLIENT_ID'];
|
||||
keyService['googleLoginClientId'] = oauth['GOOGLE_LOGIN_CONFIG']['CLIENT_ID'];
|
||||
|
||||
keyService['googleLoginClientId'] = Config['GOOGLE_LOGIN_CLIENT_ID'];
|
||||
keyService['githubRedirectUri'] = Config.getUrl('/oauth2/github/callback');
|
||||
keyService['googleRedirectUri'] = Config.getUrl('/oauth2/google/callback');
|
||||
|
||||
keyService['googleLoginUrl'] = 'https://accounts.google.com/o/oauth2/auth?response_type=code&';
|
||||
keyService['githubLoginUrl'] = 'https://github.com/login/oauth/authorize?';
|
||||
keyService['githubLoginUrl'] = oauth['GITHUB_LOGIN_CONFIG']['AUTHORIZE_ENDPOINT'];
|
||||
keyService['googleLoginUrl'] = oauth['GOOGLE_LOGIN_CONFIG']['AUTHORIZE_ENDPOINT'];
|
||||
|
||||
keyService['githubEndpoint'] = oauth['GITHUB_LOGIN_CONFIG']['GITHUB_ENDPOINT'];
|
||||
|
||||
keyService['githubTriggerAuthorizeUrl'] = oauth['GITHUB_LOGIN_CONFIG']['AUTHORIZE_ENDPOINT'];
|
||||
|
||||
keyService['googleLoginScope'] = 'openid email';
|
||||
keyService['githubLoginScope'] = 'user:email';
|
||||
keyService['googleLoginScope'] = 'openid email';
|
||||
|
||||
keyService.isEnterprise = function(service) {
|
||||
var isGithubEnterprise = keyService['githubLoginUrl'].indexOf('https://github.com/') < 0;
|
||||
return service == 'github' && isGithubEnterprise;
|
||||
};
|
||||
|
||||
keyService.getExternalLoginUrl = function(service, action) {
|
||||
var state_clause = '';
|
||||
|
@ -2548,7 +2586,10 @@ quayApp.directive('focusablePopoverContent', ['$timeout', '$popover', function (
|
|||
$body = $('body');
|
||||
var hide = function() {
|
||||
$body.off('click');
|
||||
|
||||
if (!scope) { return; }
|
||||
scope.$apply(function() {
|
||||
if (!scope) { return; }
|
||||
scope.$hide();
|
||||
});
|
||||
};
|
||||
|
@ -2645,9 +2686,9 @@ quayApp.directive('userSetup', function () {
|
|||
$scope.errorMessage = '';
|
||||
$scope.sent = true;
|
||||
$scope.sendingRecovery = false;
|
||||
}, function(result) {
|
||||
}, function(resp) {
|
||||
$scope.invalidRecovery = true;
|
||||
$scope.errorMessage = result.data;
|
||||
$scope.errorMessage = ApiService.getErrorMessage(resp, 'Cannot send recovery email');
|
||||
$scope.sent = false;
|
||||
$scope.sendingRecovery = false;
|
||||
});
|
||||
|
@ -2681,6 +2722,8 @@ quayApp.directive('externalLoginButton', function () {
|
|||
},
|
||||
controller: function($scope, $timeout, $interval, ApiService, KeyService, CookieService, Features, Config) {
|
||||
$scope.signingIn = false;
|
||||
$scope.isEnterprise = KeyService.isEnterprise;
|
||||
|
||||
$scope.startSignin = function(service) {
|
||||
$scope.signInStarted({'service': service});
|
||||
|
||||
|
@ -3137,6 +3180,22 @@ quayApp.directive('logsView', function () {
|
|||
'delete_robot': 'Delete Robot Account: {robot}',
|
||||
'create_repo': 'Create Repository: {repo}',
|
||||
'push_repo': 'Push to repository: {repo}',
|
||||
'repo_verb': function(metadata) {
|
||||
var prefix = '';
|
||||
if (metadata.verb == 'squash') {
|
||||
prefix = 'Pull of squashed tag {tag}'
|
||||
}
|
||||
|
||||
if (metadata.token) {
|
||||
prefix += ' via token {token}';
|
||||
} else if (metadata.username) {
|
||||
prefix += ' by {username}';
|
||||
} else {
|
||||
prefix += ' by {_ip}';
|
||||
}
|
||||
|
||||
return prefix;
|
||||
},
|
||||
'pull_repo': function(metadata) {
|
||||
if (metadata.token) {
|
||||
return 'Pull repository {repo} via token {token}';
|
||||
|
@ -3267,6 +3326,7 @@ quayApp.directive('logsView', function () {
|
|||
'delete_robot': 'Delete Robot Account',
|
||||
'create_repo': 'Create Repository',
|
||||
'push_repo': 'Push to repository',
|
||||
'repo_verb': 'Pull Repo Verb',
|
||||
'pull_repo': 'Pull repository',
|
||||
'delete_repo': 'Delete repository',
|
||||
'change_repo_permission': 'Change repository permission',
|
||||
|
@ -3358,7 +3418,6 @@ quayApp.directive('logsView', function () {
|
|||
$scope.logsPath = '/api/v1/' + url;
|
||||
|
||||
if (!$scope.chart) {
|
||||
window.console.log('creating chart');
|
||||
$scope.chart = new LogUsageChart(logKinds);
|
||||
$($scope.chart).bind('filteringChanged', function(e) {
|
||||
$scope.$apply(function() { $scope.kindsAllowed = e.allowed; });
|
||||
|
@ -4541,23 +4600,6 @@ quayApp.directive('planManager', function () {
|
|||
$scope.planChanged({ 'plan': subscribedPlan });
|
||||
}
|
||||
|
||||
if (sub.usedPrivateRepos > $scope.subscribedPlan.privateRepos) {
|
||||
$scope.limit = 'over';
|
||||
} else if (sub.usedPrivateRepos == $scope.subscribedPlan.privateRepos) {
|
||||
$scope.limit = 'at';
|
||||
} else if (sub.usedPrivateRepos >= $scope.subscribedPlan.privateRepos * 0.7) {
|
||||
$scope.limit = 'near';
|
||||
} else {
|
||||
$scope.limit = 'none';
|
||||
}
|
||||
|
||||
if (!$scope.chart) {
|
||||
$scope.chart = new UsageChart();
|
||||
$scope.chart.draw('repository-usage-chart');
|
||||
}
|
||||
|
||||
$scope.chart.update(sub.usedPrivateRepos || 0, $scope.subscribedPlan.privateRepos || 0);
|
||||
|
||||
$scope.planChanging = false;
|
||||
$scope.planLoading = false;
|
||||
});
|
||||
|
@ -4800,11 +4842,14 @@ quayApp.directive('stepView', function ($compile) {
|
|||
|
||||
this.next = function() {
|
||||
if (this.currentStepIndex >= 0) {
|
||||
if (!this.getCurrentStep().scope.completeCondition) {
|
||||
var currentStep = this.getCurrentStep();
|
||||
if (!currentStep || !currentStep.scope) { return; }
|
||||
|
||||
if (!currentStep.scope.completeCondition) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.getCurrentStep().element.hide();
|
||||
currentStep.element.hide();
|
||||
|
||||
if (this.unwatch) {
|
||||
this.unwatch();
|
||||
|
@ -5259,25 +5304,42 @@ quayApp.directive('triggerSetupGithub', function () {
|
|||
controller: function($scope, $element, ApiService) {
|
||||
$scope.analyzeCounter = 0;
|
||||
$scope.setupReady = false;
|
||||
|
||||
$scope.refs = null;
|
||||
$scope.branchNames = null;
|
||||
$scope.tagNames = null;
|
||||
|
||||
$scope.state = {
|
||||
'branchFilter': '',
|
||||
'hasBranchFilter': false,
|
||||
'currentRepo': null,
|
||||
'branchTagFilter': '',
|
||||
'hasBranchTagFilter': false,
|
||||
'isInvalidLocation': true,
|
||||
'currentLocation': null
|
||||
};
|
||||
|
||||
$scope.isMatchingBranch = function(branchName, filter) {
|
||||
$scope.isMatching = function(kind, name, filter) {
|
||||
try {
|
||||
var patt = new RegExp(filter);
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var m = branchName.match(patt);
|
||||
return m && m[0].length == branchName.length;
|
||||
var fullname = (kind + '/' + name);
|
||||
var m = fullname.match(patt);
|
||||
return m && m[0].length == fullname.length;
|
||||
}
|
||||
|
||||
$scope.addRef = function(kind, name) {
|
||||
if ($scope.isMatching(kind, name, $scope.state.branchTagFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var newFilter = kind + '/' + name;
|
||||
var existing = $scope.state.branchTagFilter;
|
||||
if (existing) {
|
||||
$scope.state.branchTagFilter = '(' + existing + ')|(' + newFilter + ')';
|
||||
} else {
|
||||
$scope.state.branchTagFilter = newFilter;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.stepsCompleted = function() {
|
||||
|
@ -5297,17 +5359,29 @@ quayApp.directive('triggerSetupGithub', function () {
|
|||
}, ApiService.errorDisplay('Cannot load repositories'));
|
||||
};
|
||||
|
||||
$scope.loadBranches = function(callback) {
|
||||
$scope.loadBranchesAndTags = function(callback) {
|
||||
var params = {
|
||||
'repository': $scope.repository.namespace + '/' + $scope.repository.name,
|
||||
'trigger_uuid': $scope.trigger['id'],
|
||||
'field_name': 'branch_name'
|
||||
'field_name': 'refs'
|
||||
};
|
||||
|
||||
ApiService.listTriggerFieldValues($scope.trigger['config'], params).then(function(resp) {
|
||||
$scope.branchNames = resp['values'];
|
||||
$scope.refs = resp['values'];
|
||||
$scope.branchNames = [];
|
||||
$scope.tagNames = [];
|
||||
|
||||
for (var i = 0; i < $scope.refs.length; ++i) {
|
||||
var ref = $scope.refs[i];
|
||||
if (ref.kind == 'branch') {
|
||||
$scope.branchNames.push(ref.name);
|
||||
} else {
|
||||
$scope.tagNames.push(ref.name);
|
||||
}
|
||||
}
|
||||
|
||||
callback();
|
||||
}, ApiService.errorDisplay('Cannot load branch names'));
|
||||
}, ApiService.errorDisplay('Cannot load branch and tag names'));
|
||||
};
|
||||
|
||||
$scope.loadLocations = function(callback) {
|
||||
|
@ -5357,7 +5431,7 @@ quayApp.directive('triggerSetupGithub', function () {
|
|||
};
|
||||
|
||||
$scope.selectRepo = function(repo, org) {
|
||||
$scope.currentRepo = {
|
||||
$scope.state.currentRepo = {
|
||||
'repo': repo,
|
||||
'avatar_url': org['info']['avatar_url'],
|
||||
'toString': function() {
|
||||
|
@ -5408,19 +5482,19 @@ quayApp.directive('triggerSetupGithub', function () {
|
|||
$scope.repoLookahead = repos;
|
||||
};
|
||||
|
||||
$scope.$watch('currentRepo', function(repo) {
|
||||
if (repo) {
|
||||
$scope.$watch('state.currentRepo', function(repo) {
|
||||
if (repo) {
|
||||
$scope.selectRepoInternal(repo);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('state.branchFilter', function(bf) {
|
||||
$scope.$watch('state.branchTagFilter', function(bf) {
|
||||
if (!$scope.trigger) { return; }
|
||||
|
||||
if ($scope.state.hasBranchFilter) {
|
||||
$scope.trigger['config']['branch_regex'] = bf;
|
||||
if ($scope.state.hasBranchTagFilter) {
|
||||
$scope.trigger['config']['branchtag_regex'] = bf;
|
||||
} else {
|
||||
delete $scope.trigger['config']['branch_regex'];
|
||||
delete $scope.trigger['config']['branchtag_regex'];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -5901,6 +5975,54 @@ quayApp.directive('notificationsBubble', function () {
|
|||
});
|
||||
|
||||
|
||||
quayApp.directive('usageChart', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/usage-chart.html',
|
||||
replace: false,
|
||||
transclude: false,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'current': '=current',
|
||||
'total': '=total',
|
||||
'limit': '=limit',
|
||||
'usageTitle': '@usageTitle'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
$scope.limit = "";
|
||||
|
||||
var chart = null;
|
||||
|
||||
var update = function() {
|
||||
if ($scope.current == null || $scope.total == null) { return; }
|
||||
if (!chart) {
|
||||
chart = new UsageChart();
|
||||
chart.draw('usage-chart-element');
|
||||
}
|
||||
|
||||
var current = $scope.current || 0;
|
||||
var total = $scope.total || 0;
|
||||
if (current > total) {
|
||||
$scope.limit = 'over';
|
||||
} else if (current == total) {
|
||||
$scope.limit = 'at';
|
||||
} else if (current >= total * 0.7) {
|
||||
$scope.limit = 'near';
|
||||
} else {
|
||||
$scope.limit = 'none';
|
||||
}
|
||||
|
||||
chart.update($scope.current, $scope.total);
|
||||
};
|
||||
|
||||
$scope.$watch('current', update);
|
||||
$scope.$watch('total', update);
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
||||
|
||||
|
||||
quayApp.directive('notificationView', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
|
|
Reference in a new issue