Skip to content
This repository has been archived by the owner on Aug 30, 2021. It is now read-only.

Commit

Permalink
refactor providers.
Browse files Browse the repository at this point in the history
support multiple e-mails

client-side validation

update signup form

start or emails list.  need to implement add and edit modal, and ability to switch primary.

showErrors enhancements.

formatting.
  • Loading branch information
rhutchison committed Aug 4, 2015
1 parent d0613ce commit b676d4e
Show file tree
Hide file tree
Showing 20 changed files with 397 additions and 173 deletions.
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"angular-bootstrap": "~0.13",
"angular-ui-utils": "bower",
"angular-ui-router": "~0.2",
"angular-file-upload": "1.1.5"
"angular-file-upload": "~1.1.5",
"angular-messages": "1.3.17"
},
"resolutions": {
"angular": "~1.3"
Expand Down
1 change: 1 addition & 0 deletions config/assets/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'public/lib/angular/angular.js',
'public/lib/angular-resource/angular-resource.js',
'public/lib/angular-animate/angular-animate.js',
'public/lib/angular-messages/angular-messages.js',
'public/lib/angular-ui-router/release/angular-ui-router.js',
'public/lib/angular-ui-utils/ui-utils.js',
'public/lib/angular-bootstrap/ui-bootstrap-tpls.js',
Expand Down
1 change: 1 addition & 0 deletions config/assets/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'public/lib/angular/angular.min.js',
'public/lib/angular-resource/angular-resource.min.js',
'public/lib/angular-animate/angular-animate.min.js',
'public/lib/angular-messages/angular-messages.min.js',
'public/lib/angular-ui-router/release/angular-ui-router.min.js',
'public/lib/angular-ui-utils/ui-utils.min.js',
'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js',
Expand Down
2 changes: 1 addition & 1 deletion modules/core/client/app/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
var ApplicationConfiguration = (function () {
// Init module configuration options
var applicationModuleName = 'mean';
var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'angularFileUpload'];
var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ngMessages', 'ui.router', 'ui.bootstrap', 'ui.utils', 'angularFileUpload'];

// Add a new vertical module
var registerModule = function (moduleName, dependencies) {
Expand Down
15 changes: 9 additions & 6 deletions modules/core/client/css/core.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@
.x-ng-cloak {
display: none !important;
}
.ng-invalid.ng-dirty {
border-color: #FA787E;
}
.ng-valid.ng-dirty {
border-color: #78FA89;
}
.header-profile-image {
opacity: 0.8;
height: 28px;
Expand All @@ -33,3 +27,12 @@ a:hover .header-profile-image {
padding-top: 11px !important;
padding-bottom: 11px !important;
}
.error-text {
display: none;
}
.has-error .help-block.error-text {
display: block;
}
.has-error .help-inline.error-text {
display: inline;
}
84 changes: 84 additions & 0 deletions modules/core/client/directives/show-errors.client.directives.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use strict';

/**
* Edits by Ryan Hutchison
* Credit: https://github.com/paulyoder/angular-bootstrap-show-errors */

angular.module('core')
.directive('showErrors', ['$timeout', '$interpolate', function ($timeout, $interpolate) {
var linkFn = function (scope, el, attrs, formCtrl) {
var inputEl, inputName, inputNgEl, options, showSuccess, toggleClasses,
initCheck = false,
showValidationMessages = false,
blurred = false;

options = scope.$eval(attrs.showErrors) || {};
showSuccess = options.showSuccess || false;
inputEl = el[0].querySelector('.form-control[name]') || el[0].querySelector('[name]');
inputNgEl = angular.element(inputEl);
inputName = $interpolate(inputNgEl.attr('name') || '')(scope);

if (!inputName) {
throw 'show-errors element has no child input elements with a \'name\' attribute class';
}

inputNgEl.bind('blur', function () {
blurred = true;

return toggleClasses(formCtrl[inputName].$invalid);
});

var reset = function () {
return $timeout(function () {
el.removeClass('has-error');
el.removeClass('has-success');
showValidationMessages = false;
blurred = false;
}, 0, false);
};

scope.$watch(function () {
return formCtrl[inputName] && formCtrl[inputName].$invalid;
}, function (invalid) {
if (!blurred) {
return;
}
return toggleClasses(invalid);
});

scope.$on('show-errors-check-validity', function (event, name) {
if (angular.isUndefined(name) || formCtrl['$name'] === name) {
initCheck = true;
showValidationMessages = true;

return toggleClasses(formCtrl[inputName].$invalid);
}
});

scope.$on('show-errors-reset', function (event, name) {
if (angular.isUndefined(name) || formCtrl['$name'] === name) {
return reset();
}
});

toggleClasses = function (invalid) {
el.toggleClass('has-error', showValidationMessages && invalid);
if (showSuccess) {
return el.toggleClass('has-success', showValidationMessages && !invalid);
}
};
};

return {
restrict: 'A',
require: '^form',
compile: function (elem, attrs) {
if (attrs.showErrors.indexOf('skipFormGroupCheck') === -1) {
if (!(elem.hasClass('form-group') || elem.hasClass('input-group'))) {
throw 'show-errors element does not have the \'form-group\' or \'input-group\' class';
}
}
return linkFn;
}
};
}]);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
angular.module('users').controller('AuthenticationController', ['$scope', '$state', '$http', '$location', '$window', 'Authentication',
function ($scope, $state, $http, $location, $window, Authentication) {
$scope.authentication = Authentication;
$scope.credentials = {
emails: [{
isPrimary: true
}]
};

// Get an eventual error defined in the URL query string:
$scope.error = $location.search().err;
Expand All @@ -12,7 +17,12 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$stat
$location.path('/');
}

$scope.signup = function () {
$scope.signup = function (isValid) {
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'userForm');
return false;
}

$http.post('/api/auth/signup', $scope.credentials).success(function (response) {
// If successful we assign the response to the global user model
$scope.authentication.user = response;
Expand All @@ -24,7 +34,12 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$stat
});
};

$scope.signin = function () {
$scope.signin = function (isValid) {
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'userForm');
return false;
}

$http.post('/api/auth/signin', $scope.credentials).success(function (response) {
// If successful we assign the response to the global user model
$scope.authentication.user = response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ angular.module('users').controller('SocialAccountsController', ['$scope', '$http
function ($scope, $http, Authentication) {
$scope.user = Authentication.user;

// Check if there are additional accounts
$scope.hasConnectedAdditionalSocialAccounts = function (provider) {
for (var i in $scope.user.additionalProvidersData) {
return true;
// Check if there are social accounts
$scope.hasConnectedSocialAccounts = function() {
if ($scope.user.providers) {
for(var prop in $scope.user.providers) {
if ($scope.user.providers.hasOwnProperty(prop)) {
return true;
}
}
}

return false;
};

// Check if provider is already in use with current user
$scope.isConnectedSocialAccount = function (provider) {
return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]);
$scope.isConnectedSocialAccount = function(provider) {
return $scope.user.providers && $scope.user.providers[provider];
};

// Remove a user social account
Expand Down
20 changes: 12 additions & 8 deletions modules/users/client/views/authentication/signin.client.view.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<div data-ng-controller="AuthenticationController">
<h3 class="col-md-12 text-center">Or with your account</h3>
<div class="col-xs-offset-2 col-xs-8 col-md-offset-5 col-md-2">
<form data-ng-submit="signin()" class="signin form-horizontal" autocomplete="off">
<div class="col-xs-offset-2 col-xs-8 col-md-offset-4 col-md-4">
<form name="userForm" data-ng-submit="signin(userForm.$valid)" class="signin" novalidate autocomplete="off">
<fieldset>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control"
data-ng-model="credentials.username" placeholder="Username">
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="Username" required>
<div ng-messages="userForm.username.$error" role="alert">
<p class="help-block error-text" ng-message="required">Username is required.</p>
</div>
</div>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control"
data-ng-model="credentials.password" placeholder="Password">
<input type="password" id="password" name="password" class="form-control" data-ng-model="credentials.password" placeholder="Password" required>
<div ng-messages="userForm.password.$error" role="alert">
<p class="help-block error-text" ng-message="required">Password is required.</p>
</div>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-primary">Sign in</button>
Expand Down
45 changes: 28 additions & 17 deletions modules/users/client/views/authentication/signup.client.view.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
<div data-ng-controller="AuthenticationController">
<h3 class="col-md-12 text-center">Or sign up using your email</h3>
<div class="col-xs-offset-2 col-xs-8 col-md-offset-5 col-md-2">
<form name="userForm" data-ng-submit="signup()" class="signin form-horizontal" novalidate autocomplete="off">
<div class="col-xs-offset-2 col-xs-8 col-md-offset-4 col-md-4">
<form name="userForm" data-ng-submit="signup(userForm.$valid)" class="signin" novalidate autocomplete="off">
<fieldset>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="firstName">First Name</label>
<input type="text" required id="firstName" name="firstName" class="form-control"
data-ng-model="credentials.firstName" placeholder="First Name">
<input type="text" id="firstName" name="firstName" class="form-control" data-ng-model="credentials.firstName" placeholder="First Name" required>
<div ng-messages="userForm.firstName.$error" role="alert">
<p class="help-block error-text" ng-message="required">First name is required.</p>
</div>
</div>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="lastName">Last Name</label>
<input type="text" id="lastName" name="lastName" class="form-control"
data-ng-model="credentials.lastName" placeholder="Last Name">
<input type="text" id="lastName" name="lastName" class="form-control" data-ng-model="credentials.lastName" placeholder="Last Name" required>
<div ng-messages="userForm.lastName.$error" role="alert">
<p class="help-block error-text" ng-message="required">Last name is required.</p>
</div>
</div>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="email">Email</label>
<input type="email" id="email" name="email" class="form-control" data-ng-model="credentials.email"
placeholder="Email">
<input type="email" id="email" name="email" class="form-control" data-ng-model="credentials.emails[0].address" placeholder="Email" required>
<div ng-messages="userForm.email.$error" role="alert">
<p class="help-block error-text" ng-message="required">Email address is required.</p>
</div>
</div>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control"
data-ng-model="credentials.username" placeholder="Username">
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="Username" required>
<div ng-messages="userForm.username.$error" role="alert">
<p class="help-block error-text" ng-message="required">Username is required.</p>
</div>
</div>
<div class="form-group">
<div class="form-group" data-show-errors>
<label for="password">Password</label>
<input type="password" id="password" name="password" class="form-control"
data-ng-model="credentials.password" placeholder="Password">
<input type="password" id="password" name="password" class="form-control" data-ng-model="credentials.password" placeholder="Password" required ng-minlength="6">
<div ng-messages="userForm.password.$error" role="alert">
<p class="help-block error-text" ng-message="required">Password is required.</p>
<p class="help-block error-text" ng-message="minlength">Password is too short.</p>
</div>
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-large btn-primary">Sign up</button>
Expand Down
59 changes: 36 additions & 23 deletions modules/users/client/views/settings/edit-profile.client.view.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
<section class="row" data-ng-controller="EditProfileController">
<div class="col-xs-offset-1 col-xs-10 col-md-offset-4 col-md-4">
<form name="userForm" data-ng-submit="updateUserProfile(userForm.$valid)" class="signin form-horizontal" autocomplete="off">
<fieldset>
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" id="firstName" name="firstName" class="form-control" data-ng-model="user.firstName" placeholder="First Name">
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" id="lastName" name="lastName" class="form-control" data-ng-model="user.lastName" placeholder="Last Name">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" class="form-control" data-ng-model="user.email" placeholder="Email">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control" data-ng-model="user.username" placeholder="Username">
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-lg btn-primary">Save Profile</button>
<div class="col-xs-10 col-md-8">
<section>
<h4>Account</h4>
<form name="userForm" data-ng-submit="updateUserProfile(userForm.$valid)" class="signin" autocomplete="off">
<fieldset>
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" id="firstName" name="firstName" class="form-control" data-ng-model="user.firstName" placeholder="First Name">
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" id="lastName" name="lastName" class="form-control" data-ng-model="user.lastName" placeholder="Last Name">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-control" data-ng-model="user.username" placeholder="Username">
</div>
</fieldset>
<div class="text-right form-group">
<button type="submit" class="btn btn-primary">Save Profile</button>
</div>
<div data-ng-show="success" class="text-center text-success">
<strong>Profile Saved Successfully</strong>
</div>
<div data-ng-show="error" class="text-center text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>
</form>
</section>
<section>
<h4>Emails</h4>
<ul class="list-unstyled">
<li ng-repeat="email in user.emails" class="row">
<div class="col-md-8">
<div>{{email.address}}</div>
<span class="label label-primary" ng-if="email.isPrimary">Primary</span>
</div>
<div class="col-md-4">
<a class="btn btn-link">Edit</a>
</div>
</li>
</ul>
</section>
</div>
</section>
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<section class="row" data-ng-controller="SocialAccountsController">
<h3 class="col-md-12 text-center" data-ng-show="hasConnectedAdditionalSocialAccounts()">Connected social accounts:</h3>
<h3 class="col-md-12 text-center" data-ng-show="hasConnectedSocialAccounts()">Connected social accounts:</h3>
<div class="col-md-12 text-center">
<div data-ng-repeat="(providerName, providerData) in user.additionalProvidersData" class="social-account-container">
<div data-ng-repeat="(providerName, providerData) in user.providers" class="social-account-container">
<img ng-src="/modules/users/img/buttons/{{providerName}}.png">
<a class="btn btn-danger btn-remove-account" data-ng-click="removeUserSocialAccount(providerName)">
<i class="glyphicon glyphicon-trash"></i>
</a>
</div>
</div>
<h3 class="col-md-12 text-center" data-ng-show="hasConnectedAdditionalSocialAccounts()">Unconnected social accounts:</h3>
<h3 class="col-md-12 text-center" data-ng-show="hasConnectedSocialAccounts()">Unconnected social accounts:</h3>
<div class="col-md-12 text-center">
<div class="social-account-container" data-ng-hide="isConnectedSocialAccount('facebook')">
<img ng-src="/modules/users/img/buttons/facebook.png">
Expand Down
Loading

0 comments on commit b676d4e

Please sign in to comment.