Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit c3bcee2

Browse files
author
Nick Litwin
committed
Merge branch 'dev' into organize-gulp
2 parents 4dd106a + 94c2939 commit c3bcee2

32 files changed

+1456
-430
lines changed

app/account/login/login.controller.js

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,96 +3,116 @@
33

44
angular.module('tc.account').controller('LoginController', LoginController);
55

6-
LoginController.$inject = ['$log', '$state', '$stateParams', '$location', '$scope', 'TcAuthService', 'AuthTokenService', 'UserService', 'NotificationService', 'Helpers', 'CONSTANTS'];
6+
LoginController.$inject = ['$log', '$state', '$stateParams', '$location', '$scope', 'TcAuthService', 'UserService', 'NotificationService', 'Helpers', 'CONSTANTS'];
77

8-
function LoginController($log, $state, $stateParams, $location, $scope, TcAuthService, AuthTokenService, UserService, NotificationService, Helpers, CONSTANTS) {
9-
$log = $log.getInstance("LoginController");
8+
function LoginController($log, $state, $stateParams, $location, $scope, TcAuthService, UserService, NotificationService, Helpers, CONSTANTS) {
109
var vm = this;
10+
$log = $log.getInstance("LoginController");
1111
vm.$stateParams = $stateParams;
1212
vm.passwordReset = false;
13-
vm.usernameExists = true;
1413
vm.currentPasswordDefaultPlaceholder = "Password";
14+
vm.loginErrors = {
15+
USERNAME_NONEXISTANT: false,
16+
WRONG_PASSWORD: false,
17+
SOCIAL_LOGIN_ERROR: false
18+
};
19+
20+
vm.login = login;
21+
vm.socialLogin = socialLogin;
22+
1523
// reference for main vm
1624
var mainVm = $scope.$parent.main;
1725

18-
if ($stateParams.notifyReset) {
19-
NotificationService.inform('Your new password has been set. Please log in. If you have any trouble, please contact [email protected].');
20-
}
26+
activate();
2127

22-
function _doLogin(usernameOrEmail, password) {
23-
return TcAuthService.login(usernameOrEmail, password).then(
24-
function(data) {
25-
// success
26-
$log.debug('logged in');
27-
// setup login event for analytics tracking
28-
Helpers.setupLoginEventMetrices(usernameOrEmail);
29-
return Helpers.redirectPostLogin($stateParams.next);
30-
})
31-
.catch(function(resp) {
32-
$log.warn(resp);
33-
switch (resp.status) {
34-
case "ACCOUNT_INACTIVE":
35-
$state.go('registeredSuccessfully');
36-
// user should already be redirected
37-
break;
38-
case "UNKNOWN_ERROR":
39-
default:
40-
vm.wrongPassword = true;
41-
vm.password = '';
42-
}
43-
});
28+
function activate() {
29+
if ($stateParams.notifyReset) {
30+
NotificationService.inform('Your new password has been set. Please log in. If you have any trouble, please contact [email protected].');
31+
}
4432
}
4533

46-
vm.login = function() {
47-
vm.usernameExists = true;
48-
vm.wrongPassword = false;
34+
function login() {
35+
vm.loginErrors.USERNAME_NONEXISTANT = false;
36+
vm.loginErrors.WRONG_PASSWORD = false;
37+
4938
// TODO ideally it should be done by dedicated directive to handle all outside clicks
5039
mainVm.menuVisible = false;
5140

5241
if (Helpers.isEmail(vm.username)) {
42+
// the user is loggin in using email
5343
vm.emailOrUsername = 'email';
44+
5445
// ensure email exists
46+
// uses same validity check as registration
47+
// valid => email isn't already used by someone
5548
UserService.validateUserEmail(vm.username).then(function(data) {
5649
if (data.valid) {
5750
// email doesn't exist
58-
vm.usernameExists = false;
51+
vm.loginErrors.USERNAME_NONEXISTANT = true;
5952
} else {
60-
vm.usernameExists = true;
6153
_doLogin(vm.username, vm.currentPassword);
6254
}
6355
}).catch(function(resp) {
6456
// TODO handle error
6557
// assume email exists, login would in any case if it didn't
66-
vm.usernameExists = true;
58+
vm.loginErrors.USERNAME_NONEXISTANT = false;
6759
_doLogin(vm.username, vm.currentPassword);
6860
});
6961
} else {
62+
// the user is logging in using a username
7063
vm.emailOrUsername = 'username';
64+
7165
// username - make sure it exists
7266
UserService.validateUserHandle(vm.username).then(function(data) {
7367
if (data.valid) {
7468
// username doesn't exist
75-
vm.usernameExists = false;
69+
vm.loginErrors.USERNAME_NONEXISTANT = true;
7670
} else {
77-
vm.usernameExists = true;
7871
_doLogin(vm.username, vm.currentPassword);
7972
}
8073
}).catch(function(resp) {
8174
// TODO handle error
8275
// assume email exists, login would in any case if it didn't
83-
vm.usernameExists = true;
8476
_doLogin(vm.username, vm.currentPassword);
8577
});
8678
}
8779
};
8880

89-
vm.socialLogin = function(backend) {
90-
var params = {}, callbackUrl;
81+
function _doLogin(usernameOrEmail, password) {
82+
return TcAuthService.login(usernameOrEmail, password).then(function(data) {
83+
// success
84+
$log.debug('logged in');
85+
86+
// setup login event for analytics tracking
87+
Helpers.setupLoginEventMetrics(usernameOrEmail);
88+
return Helpers.redirectPostLogin($stateParams.next);
89+
90+
}).catch(function(resp) {
91+
$log.warn(resp);
92+
switch (resp.status) {
93+
case "ACCOUNT_INACTIVE":
94+
$state.go('registeredSuccessfully');
95+
// user should already be redirected
96+
break;
97+
case "UNKNOWN_ERROR":
98+
default:
99+
vm.loginErrors.WRONG_PASSWORD = true;
100+
vm.password = '';
101+
}
102+
});
103+
}
104+
105+
function socialLogin(platform) {
106+
// we need to pass on the 'next' param if we have one
107+
var params = {};
91108
if ($stateParams.next) {
92109
params = {next: $stateParams.next};
93110
}
94-
callbackUrl = $state.href('login', params, {absolute: true});
95-
TcAuthService.socialLogin(backend, callbackUrl)
111+
112+
// redirect back to login
113+
var callbackUrl = $state.href('login', params, {absolute: true});
114+
115+
TcAuthService.socialLogin(platform, callbackUrl)
96116
.then(function() {
97117
$log.debug('logged in');
98118
return Helpers.redirectPostLogin($stateParams.next);
@@ -104,6 +124,7 @@
104124
case "USER_NOT_REGISTERED":
105125
default:
106126
vm.socialLoginError = 401;
127+
vm.loginErrors.SOCIAL_LOGIN_ERROR = true;
107128
break;
108129
}
109130
});

app/account/login/login.jade

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
h1 LOG IN TO TOPCODER
77

88
form(name="vm.loginForm", role="form", ng-submit="vm.loginForm.$valid && vm.login()", novalidate)
9-
.form-errors
10-
p.form-error(ng-hide="vm.usernameExists") We couldn't find a member with that {{vm.emailOrUsername || "username"}}. Please check that you entered it correctly.
9+
.form-errors(ng-messages="vm.loginErrors")
10+
p.form-error(ng-message="USERNAME_NONEXISTANT") We couldn't find a member with that {{vm.emailOrUsername || "username"}}. Please check that you entered it correctly.
1111

12-
p.form-error(ng-show="vm.wrongPassword") That password is incorrect. Please check that you entered the right one.
12+
p.form-error(ng-message="WRONG_PASSWORD") That password is incorrect. Please check that you entered the right one.
1313

14-
p.form-error(ng-show="vm.socialLoginError === 401") User with that profile is not registered.
14+
p.form-error(ng-message="SOCIAL_LOGIN_ERROR") User with that profile is not registered.
1515

16-
div.validation-bar(ng-class="{'error-bar': !vm.usernameExists}")
16+
div.validation-bar(ng-class="{'error-bar': vm.loginErrors.USERNAME_NONEXISTANT}")
1717
input(ng-model="vm.username", name="username", placeholder="Username or Email", type="text", required)
1818

1919
toggle-password

app/directives/account/toggle-password/toggle-password.directive.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
if (relatedTarget.attr('type') === 'checkbox' && relatedTarget.attr('id') === 'currentPasswordCheckbox') {
4141
vm.currentPasswordFocus = true;
4242
vm.currentPasswordPlaceholder = '';
43+
currentPasswordInput.focus();
4344
} else {
4445
// If you are blurring from the password input and clicking anywhere but the checkbox
4546
vm.currentPasswordFocus = false;

app/directives/account/toggle-password/toggle-password.jade

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ input#current-password-input(
22
ng-model="vm.currentPassword",
33
ng-model-options="{allowInvalid: true}",
44

5-
focus-on="focusOnCurrentPasswordInput",
65
ng-focus="vm.onCPFocus($event)",
76
ng-blur="vm.onCPBlur($event)",
87

app/directives/challenge-tile/challenge-tile.directive.jade

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
// Only show if not data science track
3333
p.roles
3434
span(ng-hide="challenge.track === 'DATA_SCIENCE'")
35-
#[span Role: ] #[span {{challenge.userDetails.roles | listRoles}}]
35+
span Role:  
36+
span {{challenge.userDetails.roles | listRoles}}
3637

3738
.completed-challenge(
3839
ng-show="challenge.status === 'COMPLETED' || challenge.status === 'PAST'",
@@ -66,7 +67,8 @@
6667
// Only show if not data science track
6768
p.roles
6869
span(ng-hide="challenge.track === 'DATA_SCIENCE'")
69-
#[span Role: ] #[span {{challenge.userDetails.roles | listRoles}}]
70+
span Role:  
71+
span {{challenge.userDetails.roles | listRoles}}
7072

7173
.challenge.list-view(ng-show="view=='list'", ng-class="challenge.track")
7274
.active-challenge(ng-show="challenge.status === 'ACTIVE'")

app/directives/external-account/external-account.directive.js

Lines changed: 29 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
{ provider: "linkedin", className: "fa-linkedin", displayName: "LinkedIn", disabled: true, order: 5, colorClass: 'el-linkedin', featured: true},
66
{ provider: "stackoverflow", className: "fa-stack-overflow", displayName: "Stack Overflow", disabled: false, order: 3, colorClass: 'el-stackoverflow'},
77
{ provider: "behance", className: "fa-behance", displayName: "Behance", disabled: true, order: 2, colorClass: 'el-behance'},
8-
// { provider: "google-oauth2", className: "fa-google-plus", displayName: "Google+", disabled: true, order: }, colorClass: 'el-dribble',
98
{ provider: "github", className: "fa-github", displayName: "Github", disabled: false, order: 1, colorClass: 'el-github', featured: true},
109
{ provider: "bitbucket", className: "fa-bitbucket", displayName: "Bitbucket", disabled: false, order: 7, colorClass: 'el-bitbucket'},
1110
{ provider: "twitter", className: "fa-twitter", displayName: "Twitter", disabled: true, order: 4, colorClass: 'el-twitter'},
12-
{ provider: "weblinks", className: "fa-globe", displayName: "Web Links", disabled: true, order: 8, colorClass: 'el-weblinks'}
11+
{ provider: "weblink", className: "fa-globe", displayName: "Web Links", disabled: true, order: -1, colorClass: 'el-weblinks'}
1312
// TODO add more
1413
];
1514

@@ -20,28 +19,36 @@
2019
templateUrl: 'directives/external-account/external-account.directive.html',
2120
scope: {
2221
linkedAccounts: '=',
23-
linksData: '=',
2422
readOnly: '='
2523
},
2624
controller: ['$log', '$scope', 'ExternalAccountService', 'toaster',
2725
function($log, $scope, ExternalAccountService, toaster) {
26+
2827
$log = $log.getInstance("ExtAccountDirectiveCtrl")
29-
$scope.accountList = _.clone(_supportedAccounts, true);
28+
29+
var _accountList = _.clone(_supportedAccounts, true);
30+
_.remove(_accountList, function(al) { return al.order < 0});
3031
$scope.$watchCollection('linkedAccounts', function(newValue, oldValue) {
31-
for (var i=0;i<$scope.accountList.length;i++) {
32-
var _idx = _.findIndex(newValue, function(a) {
33-
return $scope.accountList[i].provider === a.providerType;
34-
});
35-
if (_idx == -1) {
36-
$scope.accountList[i].status = 'unlinked';
37-
} else {
38-
// check if data
39-
if ($scope.linksData[$scope.accountList[i].provider]) {
40-
$scope.accountList[i].status = 'linked';
32+
if (newValue) {
33+
angular.forEach(_accountList, function(account) {
34+
var _linkedAccount = _.find(newValue, function(p) {
35+
return p.provider === account.provider
36+
});
37+
var accountStatus = _.get(_linkedAccount, 'data.status', null);
38+
if (!_linkedAccount) {
39+
account.status = 'unlinked';
40+
} else if(accountStatus && accountStatus.toLowerCase() === 'pending') {
41+
account.status = 'pending';
4142
} else {
42-
$scope.accountList[i].status = 'pending';
43+
account.status = 'linked';
4344
}
44-
}
45+
});
46+
$scope.accountList = _accountList;
47+
} else {
48+
// reset the status for all accounts
49+
angular.forEach(_accountList, function(account) {
50+
delete account.status;
51+
});
4552
}
4653
});
4754

@@ -62,7 +69,7 @@
6269
ExternalAccountService.linkExternalAccount(provider.provider, null)
6370
.then(function(resp) {
6471
$log.debug("Social account linked: " + JSON.stringify(resp));
65-
$scope.linkedAccounts.push(resp.profile);
72+
$scope.linkedAccounts.push(resp.linkedAccount);
6673
toaster.pop('success', "Success",
6774
String.supplant(
6875
"Your {provider} account has been linked. Data from your linked account will be visible on your profile shortly.",
@@ -92,11 +99,12 @@
9299
.then(function(resp) {
93100
$log.debug("Social account unlinked: " + JSON.stringify(resp));
94101
var toRemove = _.findIndex($scope.linkedAccounts, function(la) {
95-
return la.providerType === provider.provider;
102+
return la.provider === provider.provider;
96103
});
97-
// remove from both links array and links data array
98-
$scope.linkedAccounts.splice(toRemove, 1);
99-
delete $scope.linksData[provider.provider];
104+
if (toRemove > -1) {
105+
// remove from the linkedAccounts array
106+
$scope.linkedAccounts.splice(toRemove, 1);
107+
}
100108
toaster.pop('success', "Success",
101109
String.supplant(
102110
"Your {provider} account has been unlinked.",
@@ -120,60 +128,6 @@
120128
]
121129
};
122130
})
123-
.directive('externalLinksData', function() {
124-
return {
125-
restrict: 'E',
126-
templateUrl: 'directives/external-account/external-link-data.directive.html',
127-
scope: {
128-
linkedAccountsData: '=',
129-
externalLinks: '='
130-
},
131-
controller: ['$log', '$scope', 'ExternalAccountService',
132-
function($log, $scope, ExternalAccountService) {
133-
$log = $log.getInstance('ExternalLinksDataDirective');
134-
var validProviders = _.pluck(_supportedAccounts, 'provider');
135-
function reCalcData(links, data) {
136-
$scope.linkedAccounts = [];
137-
angular.forEach(links, function(link) {
138-
139-
var provider = link.providerType;
140-
var isValidProviderIdx = _.findIndex(validProviders, function(p) {
141-
return p === provider;
142-
});
143-
// skip if we dont care about this provider
144-
if (isValidProviderIdx == -1)
145-
return;
146-
147-
if (!data[provider]) {
148-
$scope.linkedAccounts.push({
149-
provider: provider,
150-
data: {
151-
handle: link.name,
152-
status: 'PENDING'
153-
}
154-
});
155-
} else {
156-
// add data
157-
$scope.linkedAccounts.push({
158-
provider: provider,
159-
data: data[provider]
160-
});
161-
}
162-
});
163-
}
164-
165-
166-
$scope.$watch('linkedAccountsData', function(newValue, oldValue) {
167-
reCalcData($scope.externalLinks, newValue);
168-
});
169-
170-
$scope.$watchCollection('externalLinks', function(newValue, oldValue) {
171-
reCalcData(newValue, $scope.linkedAccountsData);
172-
});
173-
}
174-
]
175-
}
176-
})
177131
.filter('providerData', function() {
178132
return function(input, field) {
179133
return _.result(_.find(_supportedAccounts, function(s) {

0 commit comments

Comments
 (0)