diff --git a/static/css/quay.css b/static/css/quay.css index ed0c3b390..47791564c 100644 --- a/static/css/quay.css +++ b/static/css/quay.css @@ -130,6 +130,16 @@ text-decoration: none !important; } +.new-repo .required-plan { + margin: 10px; + margin-top: 20px; + margin-left: 50px; +} + +.new-repo .required-plan .alert { + color: #444 !important; +} + .new-repo .new-header { font-size: 22px; } diff --git a/static/js/app.js b/static/js/app.js index 69b3399aa..9d3e615be 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -54,7 +54,7 @@ quayApp = angular.module('quay', ['restangular', 'angularMoment', 'angulartics', return keyService; }]); - $provide.factory('PlanService', [function() { + $provide.factory('PlanService', ['Restangular', 'KeyService', function(Restangular, KeyService) { var plans = [ { title: 'Open Source', @@ -96,11 +96,54 @@ quayApp = angular.module('quay', ['restangular', 'angularMoment', 'angulartics', planService.planList = function() { return plans; - } + }; planService.getPlan = function(planId) { return planDict[planId]; - } + }; + + planService.getMinimumPlan = function(privateCount) { + for (var i = 0; i < plans.length; i++) { + var plan = plans[i]; + if (plan.privateRepos >= privateCount) { + return plan; + } + } + + return null; + }; + + planService.showSubscribeDialog = function($scope, planId, started, success, failed) { + var submitToken = function(token) { + $scope.$apply(function() { + started(); + }); + + mixpanel.track('plan_subscribe'); + + var subscriptionDetails = { + token: token.id, + plan: planId, + }; + + var createSubscriptionRequest = Restangular.one('user/plan'); + $scope.$apply(function() { + createSubscriptionRequest.customPUT(subscriptionDetails).then(success, failed); + }); + }; + + var planDetails = planService.getPlan(planId) + StripeCheckout.open({ + key: KeyService.stripePublishableKey, + address: false, // TODO change to true + amount: planDetails.price, + currency: 'usd', + name: 'Quay ' + planDetails.title + ' Subscription', + description: 'Up to ' + planDetails.privateRepos + ' private repositories', + panelLabel: 'Subscribe', + token: submitToken + }); + }; return planService; }]); diff --git a/static/js/controllers.js b/static/js/controllers.js index 334311918..df1ea6e22 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -701,6 +701,8 @@ function UserAdminCtrl($scope, $timeout, Restangular, PlanService, UserService, if (sub.usedPrivateRepos > $scope.subscribedPlan.privateRepos) { $scope.errorMessage = 'You are using more private repositories than your plan allows, please upgrate your subscription to avoid disruptions in your service.'; + } else { + $scope.errorMessage = null; } $scope.planLoading = false; @@ -709,7 +711,7 @@ function UserAdminCtrl($scope, $timeout, Restangular, PlanService, UserService, mixpanel.people.set({ 'plan': sub.plan }); - } + }; $scope.planLoading = true; var getSubscription = Restangular.one('user/plan'); @@ -720,36 +722,16 @@ function UserAdminCtrl($scope, $timeout, Restangular, PlanService, UserService, $scope.planChanging = false; $scope.subscribe = function(planId) { - var submitToken = function(token) { - $scope.$apply(function() { - mixpanel.track('plan_subscribe'); - - $scope.planChanging = true; - $scope.errorMessage = undefined; - - var subscriptionDetails = { - token: token.id, - plan: planId, - }; - - var createSubscriptionRequest = Restangular.one('user/plan'); - createSubscriptionRequest.customPUT(subscriptionDetails).then(subscribedToPlan, function() { - // Failure - $scope.errorMessage = 'Unable to subscribe.'; - }); - }); - }; - - var planDetails = PlanService.getPlan(planId) - StripeCheckout.open({ - key: KeyService.stripePublishableKey, - address: false, // TODO change to true - amount: planDetails.price, - currency: 'usd', - name: 'Quay ' + planDetails.title + ' Subscription', - description: 'Up to ' + planDetails.privateRepos + ' private repositories', - panelLabel: 'Subscribe', - token: submitToken + PlanService.showSubscribeDialog($scope, planId, function() { + // Subscribing. + $scope.planChanging = true; + }, function(plan) { + // Subscribed. + subscribedToPlan(plan); + }, function() { + // Failure. + $scope.errorMessage = 'Unable to subscribe.'; + $scope.planChanging = false; }); }; @@ -920,7 +902,7 @@ function V1Ctrl($scope, $location, UserService) { }; } -function NewRepoCtrl($scope, $location, $http, UserService, Restangular) { +function NewRepoCtrl($scope, $location, $http, UserService, Restangular, PlanService) { $scope.repo = { 'is_public': 1, 'description': '', @@ -999,6 +981,16 @@ function NewRepoCtrl($scope, $location, $http, UserService, Restangular) { }); }; + var subscribedToPlan = function(sub) { + $scope.planChanging = false; + $scope.subscription = sub; + $scope.subscribedPlan = PlanService.getPlan(sub.plan); + $scope.planRequired = null; + if ($scope.subscription.usedPrivateRepos >= $scope.subscribedPlan.privateRepos) { + $scope.planRequired = PlanService.getMinimumPlan($scope.subscription.usedPrivateRepos); + } + }; + $scope.$watch( function () { return UserService.currentUser(); }, function (currentUser) { $scope.user = currentUser; @@ -1061,4 +1053,28 @@ function NewRepoCtrl($scope, $location, $http, UserService, Restangular) { $scope.creating = false; }); }; + + $scope.upgradePlan = function() { + PlanService.showSubscribeDialog($scope, $scope.planRequired.stripeId, function() { + // Subscribing. + $scope.planChanging = true; + }, function(plan) { + // Subscribed. + subscribedToPlan(plan); + }, function() { + // Failure. + $('#couldnotsubscribeModal').modal(); + $scope.planChanging = false; + }); + }; + + $scope.plans = PlanService.planList(); + + // Load the user's subscription information in case they want to create a private + // repository. + var getSubscription = Restangular.one('user/plan'); + getSubscription.get().then(subscribedToPlan, function() { + // User has no subscription + $scope.planRequired = PlanService.getMinimumPlan(1); + }); } \ No newline at end of file diff --git a/static/partials/new-repo.html b/static/partials/new-repo.html index cde232546..dd02d2faa 100644 --- a/static/partials/new-repo.html +++ b/static/partials/new-repo.html @@ -62,6 +62,15 @@ You choose who can see, pull and push from/to this repository. + + +