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:
parent
91f4464cb6
commit
abe6db334d
5 changed files with 109 additions and 24 deletions
|
@ -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">
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Reference in a new issue