/** * Element for managing subscriptions. */ angular.module('quay').directive('planManager', function () { var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/plan-manager.html', replace: false, transclude: false, restrict: 'C', scope: { 'user': '=user', 'organization': '=organization', 'hasSubscription': '=hasSubscription', 'readyForPlan': '&readyForPlan', 'planChanged': '&planChanged' }, controller: function($scope, $element, PlanService, ApiService) { $scope.isExistingCustomer = false; $scope.parseDate = function(timestamp) { return new Date(timestamp * 1000); }; $scope.isPlanVisible = function(plan, subscribedPlan) { if ($scope.organization && !PlanService.isOrgCompatible(plan)) { return false; } // A plan is visible if it is not deprecated, or if it is both not superseded // by another plan, and also the active plan for the user. if (plan['deprecated']) { var superseded = PlanService.getPlanImmediately(plan['superseded_by']); if (superseded) { return !$scope.isPlanVisible(superseded, subscribedPlan); } return subscribedPlan && plan.stripeId === subscribedPlan.stripeId; } return true; }; $scope.isPlanActive = function(plan, subscribedPlan) { // A plan is active if it is either the plan directly subscribed to by the user // or the plan which supersedes the plan to which the user is subscribed. if (!subscribedPlan) { return false; } if (subscribedPlan['deprecated'] && subscribedPlan['superseded_by']) { return $scope.isPlanActive(plan, PlanService.getPlanImmediately(subscribedPlan['superseded_by'])); } return plan.stripeId === subscribedPlan.stripeId; }; $scope.changeSubscription = function(planId, opt_async) { if ($scope.planChanging) { return; } var callbacks = { 'opening': function() { $scope.planChanging = true; }, 'started': function() { $scope.planChanging = true; }, 'opened': function() { $scope.planChanging = true; }, 'closed': function() { $scope.planChanging = false; }, 'success': subscribedToPlan, 'failure': function(resp) { $scope.planChanging = false; } }; PlanService.changePlan($scope, $scope.organization, planId, callbacks, opt_async); }; $scope.cancelSubscription = function() { $scope.changeSubscription(PlanService.getFreePlan()); }; var subscribedToPlan = function(sub) { $scope.subscription = sub; $scope.isExistingCustomer = !!sub['isExistingCustomer']; PlanService.getPlanIncludingDeprecated(sub.plan, function(subscribedPlan) { $scope.subscribedPlan = subscribedPlan; $scope.planUsagePercent = sub.usedPrivateRepos * 100 / $scope.subscribedPlan.privateRepos; if ($scope.planChanged) { $scope.planChanged({ 'plan': subscribedPlan }); } $scope.planChanging = false; $scope.planLoading = false; $scope.hasSubscription = subscribedPlan.stripeId != PlanService.getFreePlan(); }); }; var update = function() { $scope.planLoading = true; if (!$scope.plans) { return; } PlanService.getSubscription($scope.organization, subscribedToPlan, function() { $scope.isExistingCustomer = false; subscribedToPlan({ 'plan': PlanService.getFreePlan() }); }); }; var loadPlans = function() { if ($scope.plans || $scope.loadingPlans) { return; } if (!$scope.user && !$scope.organization) { return; } $scope.loadingPlans = true; PlanService.verifyLoaded(function(plans) { $scope.plans = plans; update(); if ($scope.readyForPlan) { var planRequested = $scope.readyForPlan(); if (planRequested && planRequested != PlanService.getFreePlan()) { $scope.changeSubscription(planRequested, /* async */true); } } }); }; // Start the initial download. $scope.planLoading = true; loadPlans(); $scope.$watch('organization', loadPlans); $scope.$watch('user', loadPlans); } }; return directiveDefinitionObject; });