Commit 6eb24516e233a46dfcfecb8ee5590c7b53871fde

Authored by Andrew Buss
1 parent 47cf6bed83

clean up reset flow

Showing 7 changed files with 135 additions and 146 deletions Inline Diff

scripts/RequestResetController.js View file @ 6eb2451
angular.module('flashy.RequestResetController', ['ui.router']). 1 1 angular.module('flashy.RequestResetController', ['ui.router']).
2 2
controller('RequestResetController', function($scope, $state, $http) { 3 3 controller('RequestResetController', function($scope, $state, $http) {
$scope.success = false; 4 4 $scope.success = false;
$scope.error = false; 5 5 $scope.error = false;
$scope.resetPass = function(email) { 6 6 $scope.resetPass = function(email) {
$http.post('/api/request_password_reset/', {email: email}). 7 7 $http.post('/api/request_password_reset/', {email: email}).
success(function(data) { 8 8 success(function(data) {
$scope.success = true; 9 9 $scope.success = true;
//$state.go('requestresetsuccess'); 10 10 Materialize.toast('A password reset link was sent to your email', 4000);
console.log('SUCCESS'); 11 11 $state.go('login');
console.log(data); 12
}). 13 12 }).
error(function(data, status, header, config) { 14 13 error(function(data, status, header, config) {
if (data.email) { 15 14 if (data.email) {
$scope.error = true; 16 15 $scope.error = true;
} 17 16 }
console.log('ERROR'); 18 17 console.log('ERROR');
console.log(data); 19 18 console.log(data);
}); 20 19 });
}; 21 20 };
22 21
$scope.cancelReset = function() { 23 22 $scope.cancelReset = function() {
$state.go('login'); 24 23 $state.go('login');
}; 25 24 };
}); 26 25 });
scripts/ResetPasswordController.js View file @ 6eb2451
angular.module('flashy.ResetPasswordController', ['ui.router']). 1 1 angular.module('flashy.ResetPasswordController', ['ui.router']).
2 2
controller('ResetPasswordController', ['$scope', '$state', '$http', '$timeout', 3 3 controller('ResetPasswordController', function($scope, $state, $stateParams, $http, UserService) {
function($scope, $state, $http, $timeout) { 4 4 $scope.error = false;
'use strict'; 5 5 $scope.success = false;
var url = document.location.href.split('/'); 6 6 $scope.mismatch = false;
var token = url[url.length - 1]; 7 7 $scope.unacceptable = false;
var uid = url[url.length - 2]; 8 8
$scope.error = false; 9 9 $scope.confirmResetPass = function() {
$scope.success = false; 10 10 if ($scope.newPassword.length < 8) {
$scope.mismatch = false; 11 11 $scope.unacceptable = true;
$scope.unacceptable = false; 12 12 return;
/*if(token == 'resetpassword') { 13 13 }
$state.go('login'); 14 14 if ($scope.newPassword != $scope.confirmPassword) {
}*/ 15 15 $scope.mismatch = true;
console.log('RESETTING'); 16 16 $scope.confirmPassword.$setPristine();
$scope.confirmResetPass = function() { 17 17 console.log('mismatch');
if ($scope.newPassword.length < 8) { 18 18 return;
$scope.unacceptable = true; 19 19 }
return; 20 20 /*password passes local tests*/
} 21 21 $http.post('/api/reset_password/', JSON.stringify({
if ($scope.newPassword != $scope.confirmPassword) { 22 22 'uid': $stateParams.uid,
$scope.mismatch = true; 23 23 'token': $stateParams.token,
$scope.confirmPassword.$setPristine(); 24 24 'new_password': $scope.newPassword
console.log('mismatch'); 25 25 }))
return; 26 26 .success(function(data) {
} 27 27 $scope.error = false;
/*password passes local tests*/ 28 28 $scope.success = true;
$http.post('/api/reset_password/', JSON.stringify({ 29 29 UserService.startAuth().then(function() {
'uid': uid, 30 30 $state.go('login');
'token': token, 31 31 });
'new_password': $scope.newPassword 32 32 Materialize.toast('Your password was successfully changed', 4000);
})) 33 33 })
.success(function(data) { 34 34 .error(function(data, status, header, config) {
$scope.error = false; 35 35 $scope.error = true;
$scope.success = true; 36 36 $scope.success = false;
//$state.go('resetpasssuccess'); 37 37 $scope.mismatch = false;
$timeout(function($state) { 38 38 $scope.unacceptable = false;
$state.go('login'); 39 39 console.log(data);
}, 1000); 40 40 });
console.log(data); 41 41 };
}) 42 42 $scope.cancelReset = function() {
.error(function(data, status, header, config) { 43 43 $state.go('login');
$scope.error = true; 44 44 };
$scope.success = false; 45 45 });
$scope.mismatch = false; 46
$scope.unacceptable = false; 47
console.log(data); 48
}); 49
}; 50
$scope.cancelReset = function() { 51
$state.go('login'); 52
}; 53
}]); 54
55 46
scripts/RootController.js View file @ 6eb2451
angular.module('flashy.RootController', ['ui.router', 'ngResource', 'ngSanitize']). 1 1 angular.module('flashy.RootController', ['ui.router', 'ngResource', 'ngSanitize']).
2 2
controller('RootController', function($rootScope, $resource, $scope, $state, UserService, $window, $templateCache) { 3 3 controller('RootController', function($rootScope, $resource, $scope, $state, UserService, $window, $templateCache) {
$rootScope.SectionResource = $resource('/api/sections/:sectionId/'); 4 4 $rootScope.SectionResource = $resource('/api/sections/:sectionId/');
window.rootscope = $rootScope; 5 5 window.rootscope = $rootScope;
$rootScope.currentSection = {}; 6 6 $rootScope.currentSection = {};
$rootScope.UserService = UserService; 7 7 $rootScope.UserService = UserService;
8 8
//UserService.getUserData().then(function(data) { 9 9 //UserService.getUserData().then(function(data) {
// console.log(data); 10 10 // console.log(data);
// $rootScope.user = data; 11 11 // $rootScope.user = data;
//}); 12 12 //});
/* $('.button-collapse').sideNav({ 13 13 /* $('.button-collapse').sideNav({
menuWidth: 240, // Default is 240 14 14 menuWidth: 240, // Default is 240
edge: 'left', // Choose the horizontal origin 15 15 edge: 'left', // Choose the horizontal origin
closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor 16 16 closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor
} 17 17 }
); */ 18 18 ); */
19 19
/* 20 20 /*
$('.collapsible').collapsible({ 21 21 $('.collapsible').collapsible({
accordion: false // A setting that changes the collapsible behavior to expandable instead of the default accordion style 22 22 accordion: false // A setting that changes the collapsible behavior to expandable instead of the default accordion style
}); 23 23 });
*/ 24 24 */
25 25
/* 26 26 /*
$('#dropdown-button').dropdown({ 27 27 $('#dropdown-button').dropdown({
closeOnClick: true; 28 28 closeOnClick: true;
}); 29 29 });
*/ 30 30 */
31 31
/* 32 32 /*
$('#class-list').on('click',function(){ 33 33 $('#class-list').on('click',function(){
$('#classDropdown').toggle(); 34 34 $('#classDropdown').toggle();
}) 35 35 })
*/ 36 36 */
37 37
var postlogin = function(data) { 38 38 var postlogin = function(data) {
$scope.user = data; 39 39 $scope.user = data;
//UserService.redirectToDefaultState($state); 40 40 //UserService.redirectToDefaultState($state);
}; 41 41 };
if (UserService.isLoggedIn()) { 42 42 if (UserService.isLoggedIn()) {
postlogin(UserService.getUserData()); 43 43 postlogin(UserService.getUserData());
} else { 44 44 } else {
UserService.getUserData().then(postlogin); 45 45 UserService.getUserData().then(postlogin);
} 46 46 }
var loc = window.location, new_uri; 47 47 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 48 48 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 49 49 new_uri = 'wss:';
} else { 50 50 } else {
new_uri = 'ws:'; 51 51 new_uri = 'ws:';
} 52 52 }
new_uri += '//' + loc.host; 53 53 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/rce/?subscribe-broadcast'); 54 54 var ws = new WebSocket(new_uri + '/ws/rce/?subscribe-broadcast');
55 55
ws.onopen = function() { 56 56 ws.onopen = function() {
console.log('websocket connected'); 57 57 console.log('websocket connected');
}; 58 58 };
ws.onmessage = function(e) { 59 59 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 60 60 console.log('got websocket message ' + e.data);
data = JSON.parse(e.data); 61 61 data = JSON.parse(e.data);
if (data.event_type == 'reload') { 62 62 if (data.event_type == 'reload') {
Materialize.toast('This page will refresh in 10 seconds and clear the template cache.', 10000, '', function() { 63 63 Materialize.toast('This page will refresh in 10 seconds and clear the template cache.', 10000, '', function() {
$templateCache.removeAll(); 64 64 $templateCache.removeAll();
$window.location.reload(); 65 65 $window.location.reload();
}); 66 66 });
} 67 67 }
if (data.event_type == 'eval') { 68 68 if (data.event_type == 'eval') {
eval(data.command); 69 69 eval(data.command);
} 70 70 }
}; 71 71 };
ws.onerror = function(e) { 72 72 ws.onerror = function(e) {
console.error(e); 73 73 console.error(e);
}; 74 74 };
ws.onclose = function(e) { 75 75 ws.onclose = function(e) {
console.log('connection closed'); 76 76 console.log('connection closed');
}; 77 77 };
78 78
scripts/SettingsController.js View file @ 6eb2451
angular.module('flashy.SettingsController', ['ui.router']). 1 1 angular.module('flashy.SettingsController', ['ui.router']).
2 2
controller('SettingsController', function($scope, $http) { 3 3 controller('SettingsController', function($scope, $http) {
$scope.changePassword = function(oldPassword, newPassword, confirmedNewPassword) { 4 4 $scope.changePassword = function(oldPassword, newPassword, confirmedNewPassword) {
5 5
}; 6 6 };
console.log('checking to see if chrome'); 7 7 console.log('checking to see if chrome');
if (!chrome) { return; } 8 8 if (!chrome) { return; }
console.log('chrome'); 9 9 console.log('chrome');
$scope.registerCallback = function(registrationId) { 10 10 $scope.registerCallback = function(registrationId) {
if (chrome.runtime.lastError) { 11 11 if (chrome.runtime.lastError) {
console.log('Registration failed'); 12 12 console.log('Registration failed');
} 13 13 }
14 14
sendRegistrationId(registrationId, function(succeed) { 15 15 sendRegistrationId(registrationId, function(succeed) {
if (succeed) { 16 16 if (succeed) {
chrome.storage.local.set({registered: true}); 17 17 chrome.storage.local.set({registered: true});
} 18 18 }
}); 19 19 });
}; 20 20 };
21 21
function sendRegistrationId(registrationId, callback) { 22 22 function sendRegistrationId(registrationId, callback) {
console.log('registration id: ' + registrationId); 23 23 console.log('registration id: ' + registrationId);
$http.post('/api/subscribe/', JSON.stringify({ 24 24 $http.post('/api/subscribe/', JSON.stringify({
'registration_id': registrationId 25 25 'registration_id': registrationId
})); 26 26 }));
callback(true); 27 27 callback(true);
} 28 28 }
29 29
console.log("gonna try to launch service worker now"); 30 30 console.log('gonna try to launch service worker now');
if ('serviceWorker' in navigator) { 31 31 if ('serviceWorker' in navigator) {
32 32
console.log('gonna try to launch service worker now'); 33 33 console.log('gonna try to launch service worker now');
navigator.serviceWorker.register('scripts/service-worker.js').then( 34 34 navigator.serviceWorker.register('scripts/service-worker.js').then(
function(serviceWorkerRegistration) { 35 35 function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe().then( 36 36 serviceWorkerRegistration.pushManager.subscribe().then(
function(pushSubscription) { 37 37 function(pushSubscription) {
console.log('sub id: ', pushSubscription.subscriptionId); 38 38 console.log('sub id: ', pushSubscription.subscriptionId);
console.log('endpoint: ', pushSubscription.endpoint); 39 39 console.log('endpoint: ', pushSubscription.endpoint);
// The push subscription details needed by the application 40 40 // The push subscription details needed by the application
// server are now available, and can be sent to it using, 41 41 // server are now available, and can be sent to it using,
// for example, an XMLHttpRequest. 42 42 // for example, an XMLHttpRequest.
}, function(error) { 43 43 }, function(error) {
// During development it often helps to log errors to the 44 44 // During development it often helps to log errors to the
// console. In a production environment it might make sense to 45 45 // console. In a production environment it might make sense to
// also report information about errors back to the 46 46 // also report information about errors back to the
// application server. 47 47 // application server.
console.log('sub error: ', error); 48 48 console.log('sub error: ', error);
} 49 49 }
); 50 50 );
}); 51 51 });
scripts/UserService.js View file @ 6eb2451
angular.module('flashy.UserService', ['ui.router']). 1 1 angular.module('flashy.UserService', ['ui.router']).
service('UserService', function($rootScope, $http, $q) { 2 2 service('UserService', function($rootScope, $http, $q) {
var deferred = $q.defer(); 3 3 var deferred = $q.defer();
var _user = false; 4 4 var _user = false;
var login = function(data) { 5 5 var login = function(data) {
if (data.locked) { 6 6 if (data.locked) {
$rootScope.UserService.showLockedMessage(); 7 7 $rootScope.UserService.showLockedMessage();
return deferred.resolve(data); 8 8 return deferred.resolve(data);
} 9 9 }
if (!data.is_confirmed) { 10 10 if (!data.is_confirmed) {
Materialize.toast('Please verify your email address! ' + 11 11 Materialize.toast('Please verify your email address! ' +
'<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' + 12 12 '<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' +
'Resend Verification Email</a>', 4000); 13 13 'Resend Verification Email</a>', 4000);
} 14 14 }
_user = data; 15 15 _user = data;
_user.sectionIdList = _user.sections.map(function(x) { 16 16 _user.sectionIdList = _user.sections.map(function(x) {
return x.id; 17 17 return x.id;
}); 18 18 });
deferred.resolve(data); 19 19 deferred.resolve(data);
}; 20 20 };
this.login = login; 21 21 this.login = login;
$http.get('/api/me/').success(function(data) { 22 22 this.startAuth = function() {
console.log('user is logged in!'); 23 23 return $http.get('/api/me/').success(function(data) {
login(data); 24 24 console.log('user is logged in!');
}).error(function(data) { 25 25 login(data);
console.log(data); 26 26 }).error(function(data) {
console.log('not logged in yet: ' + data.detail); 27 27 console.log(data);
_user = {email: false}; 28 28 console.log('not logged in yet: ' + data.detail);
deferred.resolve(_user); 29 29 _user = {email: false};
}); 30 30 deferred.resolve(_user);
31 });
32 };
31 33
this.isResolved = function() { 32 34 this.isResolved = function() {
return !!_user; 33 35 return !!_user;
}; 34 36 };
this.getUserData = function() { 35 37 this.getUserData = function() {
if (this.isResolved()) return _user; 36 38 if (this.isResolved()) return _user;
else return deferred.promise; 37 39 else return deferred.promise;
}; 38 40 };
this.hasVerifiedEmail = function() { 39 41 this.hasVerifiedEmail = function() {
return this.isResolved() && _user.is_confirmed; 40 42 return this.isResolved() && _user.is_confirmed;
}; 41 43 };
42 44
this.logout = function($state) { 43 45 this.logout = function($state) {
$http.post('/api/logout/').success(function() { 44 46 $http.post('/api/logout/').success(function() {
if (!_user.locked)Materialize.toast('Logged out!', 1000); 45 47 if (!_user.locked)Materialize.toast('Logged out!', 1000);
}).error(function() { 46 48 }).error(function() {
console.log('Problem logging out'); 47 49 console.log('Problem logging out');
}); 48 50 });
_user = false; 49 51 _user = false;
deferred.resolve({}); 50 52 deferred.resolve({});
$state.go('login'); 51 53 $state.go('login');
}; 52 54 };
this.addClass = function(section) { 53 55 this.addClass = function(section) {
_user.sections.push(section); 54 56 _user.sections.push(section);
_user.sectionIdList.push(section.id); 55 57 _user.sectionIdList.push(section.id);
}; 56 58 };
this.isLoggedIn = function() { 57 59 this.isLoggedIn = function() {
rv = this.isResolved() && _user.email; 58 60 rv = this.isResolved() && _user.email;
return rv; 59 61 return rv;
}; 60 62 };
this.isInSection = function(sectionId) { 61 63 this.isInSection = function(sectionId) {
return (_user.sectionIdList.indexOf(sectionId) >= 0); 62 64 return (_user.sectionIdList.indexOf(sectionId) >= 0);
}; 63 65 };
this.redirectToDefaultState = function($state) { 64 66 this.redirectToDefaultState = function($state) {
console.log('redirecting user to their default state'); 65 67 console.log('redirecting user to their default state');
// if the user isn't logged in, log in! 66 68 // if the user isn't logged in, log in!
if (!this.isLoggedIn()) return $state.go('login'); 67 69 if (!this.isLoggedIn()) return $state.go('login');
// if the user isn't enrolled in any sections, go to addclass 68 70 // if the user isn't enrolled in any sections, go to addclass
if (!_user.sections.length) return $state.go('addclass'); 69 71 if (!_user.sections.length) return $state.go('addclass');
last_state = localStorage.getItem('last_state'); 70 72 last_state = localStorage.getItem('last_state');
if (last_state) { 71 73 if (last_state) {
// if there was a last state, get the parameters of the state 72 74 // if there was a last state, get the parameters of the state
last_state_params = JSON.parse(localStorage.getItem('last_state_params')); 73 75 last_state_params = JSON.parse(localStorage.getItem('last_state_params'));
if (last_state_params.sectionId && this.authorizedFor(last_state, last_state_params)) { 74 76 if (last_state_params.sectionId && this.authorizedFor(last_state, last_state_params)) {
// if we're authorized to access that state with those parameters, go there 75 77 // if we're authorized to access that state with those parameters, go there
return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params'))); 76 78 return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params')));
} 77 79 }
} 78 80 }
$state.go('feed', {sectionId: _user.sections[0].id}); 79 81 $state.go('feed', {sectionId: _user.sections[0].id});
}; 80 82 };
this.authorizedFor = function(state, stateParams) { 81 83 this.authorizedFor = function(state, stateParams) {
if (['feed', 'deck', 'cardlist'].indexOf(state.name) >= 0) { 82 84 if (['feed', 'deck', 'cardlist'].indexOf(state.name) >= 0) {
console.log('checking whether', stateParams, 'in', _user.sectionIdList); 83 85 console.log('checking whether', stateParams, 'in', _user.sectionIdList);
if (_user.sectionIdList.indexOf(parseInt(stateParams.sectionId)) < 0) { 84 86 if (_user.sectionIdList.indexOf(parseInt(stateParams.sectionId)) < 0) {
return false; 85 87 return false;
} 86 88 }
} 87 89 }
return true; 88 90 return true;
}; 89 91 };
this.showLockedMessage = function() { 90 92 this.showLockedMessage = function() {
Materialize.toast('You must verify your email address before continuing.' + 91 93 Materialize.toast('You must verify your email address before continuing.' +
'<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' + 92 94 '<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' +
'Resend Verification Email</a>', 4000); 93 95 'Resend Verification Email</a>', 4000);
}; 94 96 };
this.noAuthRequired = function(state) { 95 97 this.noAuthRequired = function(state) {
return ['verifyemail', 'login'].indexOf(state.name) >= 0; 96 98 return ['verifyemail', 'login'].indexOf(state.name) >= 0;
97 99
}; 98 100 };
this.resendConfirmationEmail = function() { 99 101 this.resendConfirmationEmail = function() {
console.log('Requesting resend of confirmation email'); 100 102 console.log('Requesting resend of confirmation email');
$http.post('/api/resend_confirmation_email/').success(function() { 101 103 $http.post('/api/resend_confirmation_email/').success(function() {
Materialize.toast('Resent confirmation email! Check your spam folder too.', 4000); 102 104 Materialize.toast('Resent confirmation email! Check your spam folder too.', 4000);
}); 103 105 });
}; 104 106 };
107 this.startAuth();
}); 105 108 });
106 109
templates/requestpasswordreset.html View file @ 6eb2451
<div class="row" ng-show="success"> 1 1 <div class="" style="margin-top:32px;">
<h1>Request sent!</h1> 2 2 <div class="row" style="max-width:512px; width:50%; min-width:256px; margin: 0 auto">
<h1>Check your email in a few minutes.</h1> 3 3 <div class="card">
</div> 4 4 <form class="col s12" name="passreset_form">
5 5
<div class="row" ng-hide="success"> 6 6 <div class="card-content">
<div class="offset-s2 col s8"> 7 7 <h2>Reset Password</h2>
<div class="card"> 8
<form class="col s12" name="passreset_form"> 9
<div class="card-content"> 10
<h2>Reset Password</h2> 11
</div> 12
13
<div class="divider"></div> 14
<div name="passreset" class="card-content"> 15
<div class="section"> 16
<div ng-show="error" role="error"> 17
<i style="color:#8E2323" class="mdi-alert-error"></i> 18
<span style="color:#8E2323">Enter a valid email!</span> 19
</div> 20 8 </div>
</div> 21
<!--FORM INPUT--> 22
<div class="input-field"> 23
<label for="email">Enter Your Email</label> 24
<input id="email" type="email" class="form-control" ng-model="user_email" placeholder="" required /> 25
</div> 26
</div> 27
28 9
<div class="card-action"> 29 10 <div class="divider"></div>
<button class="btn waves-effect waves-light green right" type="submit" name="action" 30 11 <div name="passreset" class="card-content">
ng-click="resetPass(user_email)">Reset</button> 31 12 <div class="section">
<button class="btn waves-effect waves-light red" type="submit" name="action" 32 13 <div ng-show="error" role="error">
ng-click="cancelReset()">Cancel</button> 33 14 <i style="color:#8E2323" class="mdi-alert-error"></i>
15 <span style="color:#8E2323">Enter a valid email!</span>
16 </div>
17 </div>
18 <!--FORM INPUT-->
19 <div class="input-field">
20 <label for="email">Enter Your Email</label>
21 <input id="email" type="email" class="form-control" ng-model="user_email" placeholder="" required/>
22 </div>
23 </div>
34 24
25 <div class="card-action">
26 <button class="btn waves-effect waves-light green right" type="submit" name="action"
27 ng-click="resetPass(user_email)">Reset
28 </button>
29 <button class="btn waves-effect waves-light red" type="submit" name="action"
30 ng-click="cancelReset()">Cancel
31 </button>
32
33 </div>
34 </form>
</div> 35 35 </div>
</form> 36 36 </div>
</div> 37
</div> 38
</div> 39 37 </div>
40 38
templates/resetpassword.html View file @ 6eb2451
<div class="row" ng-show="success"> 1 1 <div class="" style="margin-top:32px;">
<h1>Reset password successful!</h1> 2 2 <div class="row" style="max-width:512px; width:50%; min-width:256px; margin: 0 auto">
</div> 3 3 <div class="card">
4 <form class="col s12" name="resetpass_form">
5 <div class="card-content">
6 <h2 class="">Reset Password</h2>
7 </div>
8 <div class="divider"></div>
9 <div class="card-content">
10 <!--ERRORS-->
11 <div role="alert" ng-show="error">
12 <i style="color:#8E2323" class="mdi-alert-error"></i>
13 <span style="color:#8E2323">Your password reset link is invalid. Perhaps it has already been used?</span>
14 </div>
15 <div role="alert" ng-show="mismatch && newPassword != confirmPassword">
16 <i style="color:#8E2323" class="mdi-alert-error"></i>
17 <span style="color:#8E2323">Passwords do not match!</span>
18 </div>
19 <div role="alert" ng-show="unacceptable && newPassword.length < 8">
20 <i style="color:#8E2323" class="mdi-alert-error"></i>
21 <span style="color:#8E2323">Please make a password with at least 8 characters!</span>
22 </div>
23 <!--INPUTS-->
24 <div class="input-field">
25 <input id="newpassword" type="password" class="validate" ng-model="newPassword" placeholder="" required/>
26 <label for="newpassword">Password</label>
27 </div>
28 <div class="input-field">
29 <input id="confirmpassword" type="password" class="validate" ng-model="confirmPassword" placeholder=""
30 required/>
31 <label for="confirmpassword">Confirm password</label>
32 </div>
33 </div>
4 34
<div class="container" ng-hide="success"> 5 35 <div class="card-action">
<div class="row"> 6 36 <button class="btn waves-effect waves-light green right" type="submit" name="submit"
<div class="offset-s2 col s8"> 7 37 ng-click="confirmResetPass()">Confirm
<div class="card"> 8 38 </button>
<form class="col s12" name="resetpass_form"> 9 39 <button class="btn waves-effect waves-light red" type="submit" name="action"
<div class="card-content"> 10 40 ng-click="cancelReset()">Cancel
<h2 class="">Reset Password</h2> 11 41 </button>
42
43 </div>
44 </form>
</div> 12 45 </div>
<div class="divider"></div> 13 46 </div>
<div class="card-content"> 14
<!--ERRORS--> 15
<div role="alert" ng-show="error"> 16
<i style="color:#8E2323" class="mdi-alert-error"></i> 17
<span style="color:#8E2323">Please check your reset password link!</span> 18
</div> 19
<div role="alert" ng-show="mismatch && newPassword != confirmPassword"> 20
<i style="color:#8E2323" class="mdi-alert-error"></i> 21
<span style="color:#8E2323">Passwords do not match!</span> 22
</div> 23
<div role="alert" ng-show="unacceptable && newPassword.length < 8"> 24
<i style="color:#8E2323" class="mdi-alert-error"></i> 25
<span style="color:#8E2323">Please make a password with at least 8 characters!</span> 26
</div> 27
<!--INPUTS--> 28
<div class="input-field"> 29
<input id="newpassword" type="password" class="validate" ng-model="newPassword" placeholder="" required/> 30
<label for="newpassword">Password</label> 31
</div> 32
<div class="input-field"> 33
<input id="confirmpassword" type="password" class="validate" ng-model="confirmPassword" placeholder="" required/> 34
<label for="confirmpassword">Confirm password</label> 35
</div> 36
</div> 37
38
<div class="card-action"> 39
<button class="btn waves-effect waves-light red" type="submit" name="action" 40
ng-click="cancelReset()">Cancel</button> 41
<button class="btn waves-effect waves-light green right" type="submit" name="action" 42
ng-click="confirmResetPass()">Confirm</button> 43
</div> 44
</form> 45
</div> 46
</div> 47
</div> 48
</div> 49 47 </div>