Make the pricing page ask for signup and, if completed, redirect to the proper page to subscribe to a plan. Also fixes a redirect issue with Github signin on the new org page

This commit is contained in:
Joseph Schorr 2013-12-11 17:50:48 -05:00
parent 91f4464cb6
commit abe6db334d
5 changed files with 109 additions and 24 deletions

View file

@ -4,19 +4,17 @@
placeholder="Username" ng-model="user.username" autofocus>
<input type="password" class="form-control input-lg" name="password"
placeholder="Password" ng-model="user.password">
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign In</button>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign In</button>
<span class="social-alternate">
<i class="fa fa-circle"></i>
<span class="inner-text">OR</span>
</span>
<a id="github-signin-link"
href="https://github.com/login/oauth/authorize?client_id={{ githubClientId }}&scope=user:email{{ mixpanelDistinctIdClause }}"
class="btn btn-primary btn-lg btn-block">
<a id="github-signin-link" class="btn btn-primary btn-lg btn-block" href="javascript:void(0)" ng-click="showGithub()">
<i class="fa fa-github fa-lg"></i> Sign In with GitHub
</a>
</form>
</form>
<div class="alert alert-danger" ng-show="invalidCredentials">Invalid username or password.</div>
<div class="alert alert-danger" ng-show="needsEmailVerification">

View file

@ -174,7 +174,8 @@ quayApp = angular.module('quay', ['ngRoute', 'restangular', 'angularMoment', 'an
return keyService;
}]);
$provide.factory('PlanService', ['Restangular', 'KeyService', 'UserService', function(Restangular, KeyService, UserService) {
$provide.factory('PlanService', ['Restangular', 'KeyService', 'UserService', '$cookieStore',
function(Restangular, KeyService, UserService, $cookieStore) {
var plans = null;
var planDict = {};
var planService = {};
@ -192,6 +193,29 @@ quayApp = angular.module('quay', ['ngRoute', 'restangular', 'angularMoment', 'an
}
}
};
planService.notePlan = function(planId) {
$cookieStore.put('quay.notedplan', planId);
};
planService.handleNotedPlan = function() {
var planId = planService.getAndResetNotedPlan();
if (!planId) { return; }
planService.isBusinessPlan(planId, function(bus) {
if (bus) {
document.location = '/organizations/new/?plan=' + planId;
} else {
document.location = '/user?plan=' + planId;
}
});
};
planService.getAndResetNotedPlan = function() {
var planId = $cookieStore.get('quay.notedplan');
$cookieStore.put('quay.notedplan', '');
return planId;
};
planService.handleCardError = function(resp) {
if (!planService.isCardError(resp)) { return; }
@ -249,6 +273,20 @@ quayApp = angular.module('quay', ['ngRoute', 'restangular', 'angularMoment', 'an
});
};
planService.isBusinessPlan = function(planId, callback) {
planService.verifyLoaded(function() {
planSource = plans.business;
for (var i = 0; i < planSource.length; i++) {
var plan = planSource[i];
if (plan.stripeId == planId) {
callback(true);
return;
}
}
callback(false);
});
};
planService.getPlans = function(callback) {
planService.verifyLoaded(callback);
};
@ -602,31 +640,57 @@ quayApp.directive('signinForm', function () {
transclude: true,
restrict: 'C',
scope: {
'redirectUrl': '=redirectUrl'
'redirectUrl': '=redirectUrl',
'signInStarted': '&signInStarted',
'signedIn': '&signedIn'
},
controller: function($scope, $location, $timeout, Restangular, KeyService, UserService) {
$scope.githubClientId = KeyService.githubClientId;
$scope.showGithub = function() {
$scope.markStarted();
var appendMixpanelId = function() {
var mixpanelDistinctIdClause = '';
if (mixpanel.get_distinct_id !== undefined) {
$scope.mixpanelDistinctIdClause = "&state=" + mixpanel.get_distinct_id();
} else {
// Mixpanel not yet loaded, try again later
$timeout(appendMixpanelId, 200);
$scope.mixpanelDistinctIdClause = "&state=" + encodeURIComponent(mixpanel.get_distinct_id());
}
// Needed to ensure that UI work done by the started callback is finished before the location
// changes.
$timeout(function() {
var url = 'https://github.com/login/oauth/authorize?client_id=' + encodeURIComponent(KeyService.githubClientId) +
'&scope=user:email' + mixpanelDistinctIdClause;
document.location = url;
}, 250);
};
appendMixpanelId();
$scope.markStarted = function() {
if ($scope.signInStarted != null) {
$scope.signInStarted();
}
};
$scope.signin = function() {
$scope.markStarted();
var signinPost = Restangular.one('signin');
signinPost.customPOST($scope.user).then(function() {
$scope.needsEmailVerification = false;
$scope.invalidCredentials = false;
// Redirect to the specified page or the landing page
if ($scope.signedIn != null) {
$scope.signedIn();
}
UserService.load();
$location.path($scope.redirectUrl ? $scope.redirectUrl : '/');
// Redirect to the specified page or the landing page
// Note: The timeout of 500ms is needed to ensure dialogs containing sign in
// forms get removed before the location changes.
$timeout(function() {
if ($scope.redirectUrl == $location.path()) {
return;
}
$location.path($scope.redirectUrl ? $scope.redirectUrl : '/');
}, 500);
}, function(result) {
$scope.needsEmailVerification = result.data.needsEmailVerification;
$scope.invalidCredentials = result.data.invalidCredentials;
@ -1850,8 +1914,9 @@ quayApp.directive('ngBlur', function() {
};
});
quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', '$http', '$cookieStore', '$timeout',
function($location, $rootScope, Restangular, UserService, $http, $cookieStore, $timeout) {
quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanService', '$http', '$cookieStore', '$timeout',
function($location, $rootScope, Restangular, UserService, PlanService, $http, $cookieStore, $timeout) {
// Handle session expiration.
Restangular.setErrorInterceptor(function(response) {
if (response.status == 401) {
$('#sessionexpiredModal').modal({});
@ -1861,6 +1926,9 @@ quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', '$http', '
return true;
});
// Check if we need to redirect based on a previously chosen plan.
PlanService.handleNotedPlan();
var changeTab = function(activeTab) {
$timeout(function() {
$('a[data-toggle="tab"]').each(function(index) {

View file

@ -38,10 +38,17 @@ function PlansCtrl($scope, $location, UserService, PlanService) {
$scope.user = currentUser;
}, true);
$scope.signedIn = function() {
$('#signinModal').modal('hide');
PlanService.handleNotedPlan();
};
$scope.buyNow = function(plan) {
if ($scope.user && !$scope.user.anonymous) {
document.location = '/user?plan=' + plan;
} else {
PlanService.notePlan(plan);
$('#signinModal').modal({});
}
};
@ -50,6 +57,7 @@ function PlansCtrl($scope, $location, UserService, PlanService) {
if ($scope.user && !$scope.user.anonymous) {
document.location = '/organizations/new/?plan=' + plan;
} else {
PlanService.notePlan(plan);
$('#signinModal').modal({});
}
};
@ -106,7 +114,7 @@ function RepoListCtrl($scope, Restangular, UserService) {
});
}
function LandingCtrl($scope, $timeout, $location, Restangular, UserService, KeyService) {
function LandingCtrl($scope, $timeout, $location, Restangular, UserService, KeyService, PlanService) {
$scope.namespace = null;
$scope.$watch('namespace', function(namespace) {
@ -1270,7 +1278,7 @@ function OrgsCtrl($scope, UserService) {
function NewOrgCtrl($scope, $routeParams, $timeout, $location, UserService, PlanService, Restangular) {
$scope.loading = true;
$scope.$watch( function () { return UserService.currentUser(); }, function (currentUser) {
$scope.$watch(function () { return UserService.currentUser(); }, function (currentUser) {
$scope.user = currentUser;
$scope.loading = false;
}, true);
@ -1288,6 +1296,16 @@ function NewOrgCtrl($scope, $routeParams, $timeout, $location, UserService, Plan
}
});
$scope.signedIn = function() {
PlanService.handleNotedPlan();
};
$scope.signinStarted = function() {
PlanService.getMinimumPlan(1, true, function(plan) {
PlanService.notePlan(plan.stripeId);
});
};
$scope.setPlan = function(plan) {
$scope.currentPlan = plan;
};

View file

@ -43,7 +43,8 @@
<h4 class="panel-title">Sign In</h4>
</div>
<div class="panel-body">
<div class="signin-form" redirect-url="'/organizations/new'"></div>
<div class="signin-form" redirect-url="'/organizations/new'" sign-in-started="signinStarted()"
signed-in="signedIn()"></div>
</div>
</div>
</div>

View file

@ -83,7 +83,7 @@
<h4 class="modal-title">Please Sign In</h4>
</div>
<div class="modal-body">
Please sign into Quay in order to continue
<div class="signin-form" signed-in="signedIn()" redirect-url="'/plans/'"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>