Merge pull request #350 from coreos-inc/superseceded
Allow a stripe plan to be superseded
This commit is contained in:
commit
74bffa3e25
4 changed files with 44 additions and 3 deletions
|
@ -16,6 +16,7 @@ PLANS = [
|
||||||
'bus_features': False,
|
'bus_features': False,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Basic',
|
'title': 'Basic',
|
||||||
|
@ -26,6 +27,7 @@ PLANS = [
|
||||||
'bus_features': False,
|
'bus_features': False,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Yacht',
|
'title': 'Yacht',
|
||||||
|
@ -36,6 +38,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 180,
|
'free_trial_days': 180,
|
||||||
|
'superseded_by': 'bus-small-30',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Personal',
|
'title': 'Personal',
|
||||||
|
@ -46,6 +49,7 @@ PLANS = [
|
||||||
'bus_features': False,
|
'bus_features': False,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': 'personal-30',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Skiff',
|
'title': 'Skiff',
|
||||||
|
@ -56,6 +60,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': 'bus-micro-30',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Yacht',
|
'title': 'Yacht',
|
||||||
|
@ -66,6 +71,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': 'bus-small-30',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Freighter',
|
'title': 'Freighter',
|
||||||
|
@ -76,6 +82,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': 'bus-medium-30',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Tanker',
|
'title': 'Tanker',
|
||||||
|
@ -86,6 +93,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
'free_trial_days': 14,
|
'free_trial_days': 14,
|
||||||
|
'superseded_by': 'bus-large-30',
|
||||||
},
|
},
|
||||||
|
|
||||||
# Active plans
|
# Active plans
|
||||||
|
@ -98,6 +106,7 @@ PLANS = [
|
||||||
'bus_features': False,
|
'bus_features': False,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Personal',
|
'title': 'Personal',
|
||||||
|
@ -108,6 +117,7 @@ PLANS = [
|
||||||
'bus_features': False,
|
'bus_features': False,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Skiff',
|
'title': 'Skiff',
|
||||||
|
@ -118,6 +128,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Yacht',
|
'title': 'Yacht',
|
||||||
|
@ -128,6 +139,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Freighter',
|
'title': 'Freighter',
|
||||||
|
@ -138,6 +150,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Tanker',
|
'title': 'Tanker',
|
||||||
|
@ -148,6 +161,7 @@ PLANS = [
|
||||||
'bus_features': True,
|
'bus_features': True,
|
||||||
'deprecated': False,
|
'deprecated': False,
|
||||||
'free_trial_days': 30,
|
'free_trial_days': 30,
|
||||||
|
'superseded_by': None,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tr ng-repeat="plan in plans" ng-show="isPlanVisible(plan, subscribedPlan)"
|
<tr ng-repeat="plan in plans" ng-show="isPlanVisible(plan, subscribedPlan)"
|
||||||
ng-class="{'active':(subscribedPlan.stripeId === plan.stripeId), 'deprecated-plan':plan.deprecated}">
|
ng-class="{'active':isPlanActive(plan, subscribedPlan), 'deprecated-plan':plan.deprecated}">
|
||||||
<td>
|
<td>
|
||||||
{{ plan.title }}
|
{{ plan.title }}
|
||||||
<div class="deprecated-plan-label" ng-show="plan.deprecated">
|
<div class="deprecated-plan-label" ng-show="plan.deprecated">
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div ng-switch-default>
|
<div ng-switch-default>
|
||||||
<button class="btn" ng-show="subscribedPlan.stripeId !== plan.stripeId"
|
<button class="btn" ng-show="!isPlanActive(plan, subscribedPlan)"
|
||||||
ng-class="subscribedPlan.price == 0 ? 'btn-primary' : 'btn-default'"
|
ng-class="subscribedPlan.price == 0 ? 'btn-primary' : 'btn-default'"
|
||||||
ng-click="changeSubscription(plan.stripeId)">
|
ng-click="changeSubscription(plan.stripeId)">
|
||||||
<span class="cor-loader-inline" ng-show="planChanging"></span>
|
<span class="cor-loader-inline" ng-show="planChanging"></span>
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
<span ng-show="!planChanging && subscribedPlan.price == 0 && !isExistingCustomer">Start Free Trial</span>
|
<span ng-show="!planChanging && subscribedPlan.price == 0 && !isExistingCustomer">Start Free Trial</span>
|
||||||
<span ng-show="!planChanging && subscribedPlan.price == 0 && isExistingCustomer">Subscribe</span>
|
<span ng-show="!planChanging && subscribedPlan.price == 0 && isExistingCustomer">Subscribe</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-danger" ng-show="subscription.plan === plan.stripeId && plan.price > 0"
|
<button class="btn btn-danger" ng-show="isPlanActive(plan, subscribedPlan) && plan.price > 0"
|
||||||
ng-click="cancelSubscription()">
|
ng-click="cancelSubscription()">
|
||||||
<span class="cor-loader-inline" ng-show="planChanging"></span>
|
<span class="cor-loader-inline" ng-show="planChanging"></span>
|
||||||
<span ng-show="!planChanging">Cancel</span>
|
<span ng-show="!planChanging">Cancel</span>
|
||||||
|
|
|
@ -25,7 +25,13 @@ angular.module('quay').directive('planManager', function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.isPlanVisible = function(plan, subscribedPlan) {
|
$scope.isPlanVisible = function(plan, subscribedPlan) {
|
||||||
|
// 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']) {
|
if (plan['deprecated']) {
|
||||||
|
superseded = plan['superseded_by']
|
||||||
|
if (superseded) {
|
||||||
|
return !$scope.isPlanVisible(superseded, subscribedPlan);
|
||||||
|
}
|
||||||
return plan == subscribedPlan;
|
return plan == subscribedPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +42,20 @@ angular.module('quay').directive('planManager', function () {
|
||||||
return true;
|
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) {
|
$scope.changeSubscription = function(planId, opt_async) {
|
||||||
if ($scope.planChanging) { return; }
|
if ($scope.planChanging) { return; }
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,13 @@ function(KeyService, UserService, CookieService, ApiService, Features, Config) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
planService.getPlanImmediately = function(planId) {
|
||||||
|
// Get the plan by name, without bothering to check if the plans are loaded.
|
||||||
|
// This method will return undefined if planId is undefined or null, or if
|
||||||
|
// the planDict has not yet been loaded.
|
||||||
|
return planDict[planId];
|
||||||
|
};
|
||||||
|
|
||||||
planService.getMinimumPlan = function(privateCount, isBusiness, callback) {
|
planService.getMinimumPlan = function(privateCount, isBusiness, callback) {
|
||||||
planService.getPlans(function(plans) {
|
planService.getPlans(function(plans) {
|
||||||
for (var i = 0; i < plans.length; i++) {
|
for (var i = 0; i < plans.length; i++) {
|
||||||
|
|
Reference in a new issue