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

[WIP] User refactor #752

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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