diff --git a/static/directives/signin-form.html b/static/directives/signin-form.html index ef0b5f795..cf982f08b 100644 --- a/static/directives/signin-form.html +++ b/static/directives/signin-form.html @@ -4,19 +4,17 @@ placeholder="Username" ng-model="user.username" autofocus> - - + + OR - - + + Sign In with GitHub - +
Invalid username or password.
diff --git a/static/js/app.js b/static/js/app.js index 85893934e..cd4a9ad70 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -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) { diff --git a/static/js/controllers.js b/static/js/controllers.js index 8c362d1c7..ba0b31855 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -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; }; diff --git a/static/partials/new-organization.html b/static/partials/new-organization.html index 955c0d2d0..2180834c4 100644 --- a/static/partials/new-organization.html +++ b/static/partials/new-organization.html @@ -43,7 +43,8 @@

Sign In

-
+
diff --git a/static/partials/plans.html b/static/partials/plans.html index 178169b79..2172d15bf 100644 --- a/static/partials/plans.html +++ b/static/partials/plans.html @@ -83,7 +83,7 @@