diff --git a/static/css/quay.css b/static/css/quay.css index 1f7dab88a..172af7f87 100644 --- a/static/css/quay.css +++ b/static/css/quay.css @@ -1490,6 +1490,26 @@ p.editable:hover i { padding: 6px; } +.org-admin .plans-table thead td { + color: #aaa; + font-weight: bold; +} + +.org-admin .plans-table td { + padding: 10px; + font-size: 16px; + vertical-align: middle; +} + +.org-admin .plans-table td.controls { + text-align: right; +} + +.org-admin .plans-table .plan-price { + font-size: 16px; + margin-bottom: 0px; +} + /* Overrides for typeahead to work with bootstrap 3. */ .twitter-typeahead .tt-query, diff --git a/static/js/controllers.js b/static/js/controllers.js index cec50c675..7942b9616 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -1180,8 +1180,63 @@ function OrgViewCtrl($rootScope, $scope, Restangular, $routeParams) { loadOrganization(); } -function OrgAdminCtrl($scope, Restangular, $routeParams) { +function OrgAdminCtrl($rootScope, $scope, Restangular, $routeParams, UserService, PlanService) { + // Load the list of plans. + PlanService.getPlans(function(plans) { + $scope.plans = plans.business; + }); + var orgname = $routeParams.orgname; + + var loadOrganization = function() { + var getOrganization = Restangular.one(getRestUrl('organization', orgname)); + getOrganization.get().then(function(resp) { + if (resp && resp.is_admin) { + $scope.organization = resp; + $rootScope.title = orgname + ' (Admin)'; + } + + $scope.loading = false; + }, function() { + $scope.loading = false; + }); + }; + + var subscribedToPlan = function(sub) { + $scope.subscription = sub; + PlanService.getPlan(sub.plan, function(subscribedPlan) { + $scope.subscribedPlan = subscribedPlan; + $scope.planUsagePercent = sub.usedPrivateRepos * 100 / $scope.subscribedPlan.privateRepos; + + if (sub.usedPrivateRepos > $scope.subscribedPlan.privateRepos) { + $scope.overLimit = true; + } else if (sub.usedPrivateRepos >= $scope.subscribedPlan.privateRepos * 0.7) { + $scope.nearLimit = true; + } else { + $scope.overLimit = false; + $scope.nearLimit = false; + } + + $scope.planLoading = false; + }); + }; + + var loadSubscription = function() { + $scope.planLoading = true; + UserService.getCurrentSubscription(subscribedToPlan, function() { + // Organization has no subscription. + $scope.planLoading = false; + }); + }; + + $scope.getActiveSubClass = function() { + if ($scope.overLimit) { return 'danger'; } + if ($scope.nearLimit) { return 'warning'; } + return 'success'; + }; + + loadSubscription(); + loadOrganization(); } function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { diff --git a/static/partials/org-admin.html b/static/partials/org-admin.html new file mode 100644 index 000000000..008583e79 --- /dev/null +++ b/static/partials/org-admin.html @@ -0,0 +1,108 @@ +
+ +
+ +
+ No matching organization found +
+ +
+
+ +
+ + + + +
+
+ +
+
+ You are using more private repositories than your plan allows, please + upgrade your subscription + to avoid disruptions in your organization's service. +
+ +
+ You are nearing the number of allowed private repositories. It might be time to think about + upgrading your subscription + to avoid future disruptions in your organization's service. +
+ + + +
+
+
+
+ Current Usage +
+
+
+ {{ subscription.usedPrivateRepos }} of {{ subscribedPlan.privateRepos }} private repositories used +
+
+
+
+
+
+
+
+
+
+ + +
+
+ You are using more private repositories than your plan allows, please + upgrade your subscription to avoid disruptions in your organization's service. +
+ +
+ You are nearing the number of allowed private repositories. It might be time to think about + upgrading your subscription to avoid future disruptions in your organization's service. +
+ + + + + + + + + + + + + + + +
PlanPrivate RepositoriesPrice
{{ plan.title }}{{ plan.privateRepos }}
${{ plan.price / 100 }}
+
+
+ +
+
+ + + +
+
+
+
+ + +
+ members +
+
+
+
+