Commit 0aebb5d92ebefd9d0659d7341bf929a20df8b0b0

Authored by Victor Costa
2 parents 3ad422aa 022de891

Merge branch 'registration_errors'

src/app/account/register-component.html
... ... @@ -3,6 +3,14 @@
3 3 <h1>{{"account.register.welcomeMessageTitle" | translate }}</h1>
4 4 <div class="environment-signup-intro" ng-bind-html="ctrl.environment.signup_intro"></div>
5 5 </div>
  6 +
  7 + <div class="error-messages" ng-if="ctrl.errorMessages">
  8 + <p>{{ "account.register.errorMessagesTitle" | translate }}</p>
  9 + <ul>
  10 + <li ng-repeat="error in ctrl.errorMessages">{{ error.fieldName | translate }} {{ error.message | translate }}</li>
  11 + </ul>
  12 + </div>
  13 +
6 14 <form name="signupForm">
7 15 <div class="row">
8 16 <div class="col-md-12 register-field">
... ... @@ -17,10 +25,12 @@
17 25 <span class="input-group-addon" style="font-weight: bold;"><i class="fa fa-globe"></i>&nbsp;{{ ctrl.environment.host }}</span>
18 26 <input type="text" id="username" name="username" class="form-control" placeholder="{{'account.register.usernameLabel' | translate }}" ng-model="ctrl.account.login" required>
19 27 </div>
20   - <div class="help-block" ng-show="signupForm.username.$touched" ng-messages="signupForm.username.$error">
21   - <ul class="list-unstyled">
22   - <li ng-messages-include="languages/messages.html"></li>
23   - </ul>
  28 + <div class="help-block" ng-messages="signupForm.username.$error">
  29 + <div ng-if="signupForm.username.$touched && !signupForm.username.$empty">
  30 + <ul class="list-unstyled">
  31 + <li ng-messages-include="app/shared/messages/form-errors.html"></li>
  32 + </ul>
  33 + </div>
24 34 </div>
25 35 </div>
26 36  
... ... @@ -29,22 +39,26 @@
29 39 <span class="input-group-addon"><i class="fa fa-envelope"></i></span>
30 40 <input type="email" class="form-control" id="email" name="email" placeholder="{{'account.register.emailLabel' | translate }}" ng-model="ctrl.account.email" required>
31 41 </div>
32   - <div class="help-block" ng-show="signupForm.email.$touched" ng-messages="signupForm.email.$error">
33   - <ul class="list-unstyled">
34   - <li ng-messages-include="languages/messages.html"></li>
35   - </ul>
  42 + <div class="help-block" ng-messages="signupForm.email.$error">
  43 + <div ng-if="signupForm.email.$touched && !signupForm.email.$empty">
  44 + <ul class="list-unstyled">
  45 + <li ng-messages-include="app/shared/messages/form-errors.html"></li>
  46 + </ul>
  47 + </div>
36 48 </div>
37 49 </div>
38 50  
39 51 <div class="form-group col-md-6 register-field" ng-class="ctrl.isInvalid(signupForm.password)">
40 52 <div class="input-group">
41 53 <span class="input-group-addon"><i class="fa fa-lock"></i></span>
42   - <input type="password" class="form-control" id="password" name="password" placeholder="{{'account.register.passwordLabel' | translate }}" ng-model="ctrl.account.password" required>
  54 + <input type="password" class="form-control" id="password" name="password" placeholder="{{'account.register.passwordLabel' | translate }}" ng-model="ctrl.account.password" required minlength="4">
43 55 </div>
44   - <div class="help-block" ng-show="signupForm.password.$touched" ng-messages="signupForm.password.$error">
45   - <ul class="list-unstyled">
46   - <li ng-messages-include="languages/messages.html"></li>
47   - </ul>
  56 + <div class="help-block" ng-messages="signupForm.password.$error">
  57 + <div ng-if="signupForm.password.$touched && !signupForm.password.$empty">
  58 + <ul class="list-unstyled">
  59 + <li ng-messages-include="app/shared/messages/form-errors.html"></li>
  60 + </ul>
  61 + </div>
48 62 </div>
49 63 </div>
50 64  
... ... @@ -55,7 +69,7 @@
55 69 </div>
56 70 <div class="help-block" ng-show="signupForm.passwordConfirm.$touched" ng-messages="signupForm.passwordConfirm.$error">
57 71 <ul class="list-unstyled">
58   - <li ng-messages-include="languages/messages.html"></li>
  72 + <li ng-messages-include="app/shared/messages/form-errors.html"></li>
59 73 <li ng-message="passwordMatch" translate="messages.invalid.passwordMatch"></li>
60 74 </ul>
61 75 </div>
... ... @@ -72,6 +86,5 @@
72 86 </div>
73 87 </form>
74 88  
75   - <p class="already-registered-message">{{"account.register.haveAccountMessage" | translate}}</p>
76   -
  89 + <a class="already-registered-message" ng-href="#" ng-click="ctrl.openLogin()">{{"account.register.haveAccountMessage" | translate}}</a>
77 90 </div>
... ...
src/app/account/register-terms.html
1 1 <div class="modal-header">
2   - <h3 class="modal-title">Register terms</h3>
  2 + <h3 class="modal-title">{{ "account.register.termsOfUseTitle" | translate }} - {{ ctrl.environment.name }}</h3>
3 3 </div>
4 4 <div class="modal-body modal-body-overflow" ng-bind-html="ctrl.environment.terms_of_use"></div>
5 5 <div class="modal-footer">
... ...
src/app/account/register.component.spec.ts
1 1 import { ComponentTestHelper, createClass } from "../../spec/component-test-helper";
2 2 import * as helpers from "../../spec/helpers";
3 3 import { RegisterComponent } from "./register.component";
4   -// import {RegisterService} from "../../lib/ng-noosfero-api/http/register.service"
5   -
6 4  
7 5 describe("Register Component", () => {
8 6 const htmlTemplate: string = '<noosfero-register></noosfero-register>';
9 7  
10 8 let helper: ComponentTestHelper<RegisterComponent>;
11 9 let registerService = helpers.mocks.registerService;
12   - let stateService = jasmine.createSpyObj("$state", ["transitionTo"]);
  10 + let stateService: angular.ui.IStateService;
13 11 let notificationService = helpers.mocks.notificationService;
14 12 notificationService.success = jasmine.createSpy('success');
15 13 notificationService.error = jasmine.createSpy('error');
16   -
17   -
18   - let account: any = {
19   - id: 1,
20   - login: 'test',
21   - email: 'test@email.com',
22   - password: 'xxx',
23   - passwordConfirmation: 'xxx'
24   - };
  14 + let user_data: any;
  15 + let response: any;
  16 + let deferred: any;
  17 + let $rootScope: ng.IRootScopeService;
  18 + let $q: ng.IQService;
25 19  
26 20 beforeEach(() => {
  21 + stateService = jasmine.createSpyObj("$state", ["transitionTo"]);
  22 +
27 23 angular.mock.module('templates');
28 24 angular.mock.module('ngSanitize');
29 25 angular.mock.module('ngMessages');
... ... @@ -45,8 +41,53 @@ describe(&quot;Register Component&quot;, () =&gt; {
45 41 helper = new ComponentTestHelper<RegisterComponent>(cls, done);
46 42 });
47 43  
  44 + beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => {
  45 + $rootScope = _$rootScope_;
  46 + $q = _$q_;
  47 + }));
  48 +
48 49 it('register page was rendered', () => {
49 50 expect(helper.debugElement.query('div.register-page').length).toEqual(1);
50 51 });
51 52  
  53 + it("registers a new user", done => {
  54 + user_data = { username: "username", password: "password", password_confirmation: "password", email: "user@company.com" };
  55 + response = {};
  56 +
  57 + helper.component.account = user_data;
  58 +
  59 + deferred = $q.defer();
  60 + deferred.resolve({ data: response });
  61 + registerService.createAccount = jasmine.createSpy("createAccount").and.returnValue(deferred.promise);
  62 +
  63 + helper.component.signup();
  64 + helper.detectChanges();
  65 +
  66 + expect(registerService.createAccount).toHaveBeenCalledWith(user_data);
  67 + expect(stateService.transitionTo).toHaveBeenCalledWith("main.environment");
  68 + expect(notificationService.success).toHaveBeenCalled();
  69 +
  70 + done();
  71 + });
  72 +
  73 + it("gives error when registration fails", done => {
  74 + user_data = { password: "pas" };
  75 + response = { data: { message: '{ "password": ["is too short"] }' } };
  76 +
  77 + helper.component.account = user_data;
  78 +
  79 + deferred = $q.defer();
  80 + deferred.reject(response);
  81 + registerService.createAccount = jasmine.createSpy("createAccount").and.returnValue(deferred.promise);
  82 +
  83 + helper.component.signup();
  84 + helper.detectChanges();
  85 +
  86 + expect(registerService.createAccount).toHaveBeenCalledWith(user_data);
  87 +
  88 + expect(stateService.transitionTo).not.toHaveBeenCalledWith("main.environment");
  89 + expect(notificationService.error).toHaveBeenCalled();
  90 +
  91 + done();
  92 + });
52 93 });
... ...
src/app/account/register.component.ts
... ... @@ -3,6 +3,7 @@ import { RegisterService } from &quot;./../../lib/ng-noosfero-api/http/register.servi
3 3 import { NotificationService } from "./../shared/services/notification.service";
4 4 import { EnvironmentService } from "../../lib/ng-noosfero-api/http/environment.service";
5 5 import { RegisterController } from "./register.controller";
  6 +import { AuthController } from "./../login";
6 7 import { IModalComponent } from "../shared/components/interfaces";
7 8  
8 9 @Component({
... ... @@ -20,6 +21,8 @@ export class RegisterComponent {
20 21  
21 22 modalInstance: ng.ui.bootstrap.IModalServiceInstance;
22 23  
  24 + errorMessages: any[];
  25 +
23 26 constructor(
24 27 private $state: ng.ui.IStateService,
25 28 private $uibModal: ng.ui.bootstrap.IModalService,
... ... @@ -33,19 +36,27 @@ export class RegisterComponent {
33 36 }
34 37  
35 38 signup() {
36   - if (this.account.password === this.account.passwordConfirmation) {
37   - this.registerService.createAccount(this.account).then((response) => {
38   -
39   - if (response.status === 201) {
40   - this.$state.transitionTo('main.environment');
41   - this.notificationService.success({ title: "account.register.success.title", message: "account.register.success.message" });
42   - } else {
43   - throw new Error('Invalid attributes');
  39 + let error = '';
  40 + let errors: any;
  41 + let field = '';
  42 + this.errorMessages = [];
  43 + this.registerService.createAccount(this.account).then((response) => {
  44 + this.$state.transitionTo('main.environment');
  45 + this.notificationService.success({ title: "account.register.success.title", message: "account.register.success.message" });
  46 + }).catch((response) => {
  47 + if (response.data.error) {
  48 + errors = response.data['error'].split(', ');
  49 + for (error in errors) {
  50 + this.errorMessages.push({ message: errors[error] });
  51 + }
  52 + } else if (response.data.message) {
  53 + errors = JSON.parse(response.data.message);
  54 + for (field in errors) {
  55 + this.errorMessages.push({ fieldName: field, message: errors[field][0] });
44 56 }
45   - });
46   - } else {
47   - this.notificationService.error({ message: "account.register.passwordConfirmation.failed" });
48   - }
  57 + }
  58 + this.notificationService.error({ title: "account.register.save.failed" });
  59 + });
49 60 }
50 61  
51 62 isInvalid(field: any): any {
... ... @@ -63,4 +74,14 @@ export class RegisterComponent {
63 74 scope: this.$scope
64 75 });
65 76 }
  77 +
  78 + openLogin() {
  79 + this.modalInstance = this.$uibModal.open({
  80 + templateUrl: 'app/login/login.html',
  81 + controller: AuthController,
  82 + controllerAs: 'vm',
  83 + bindToController: true
  84 + });
  85 + }
  86 +
66 87 }
... ...
src/app/account/scss/register.scss
... ... @@ -29,6 +29,7 @@
29 29 .register-page .already-registered-message {
30 30 margin-top: 60px;
31 31 text-align: center;
  32 + display: block;
32 33 }
33 34  
34 35 .register-page input {
... ...
src/app/shared/messages/form-errors.html 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +<li ng-message="required" translate="messages.invalid.required"></li>
  2 +<li ng-message="minlength" translate="messages.invalid.minlength"></li>
  3 +<li ng-message="maxlength" translate="messages.invalid.maxlength"></li>
  4 +<li ng-message="email" translate="messages.invalid.email"></li>
... ...
src/languages/en.json
... ... @@ -120,6 +120,7 @@
120 120 "account.register.signupMessage": "Register",
121 121 "account.register.haveAccountMessage": "Already have an account?",
122 122 "account.register.termsOfUseMessage": "terms of use",
  123 + "account.register.termsOfUseTitle": "Terms of use",
123 124 "account.register.success.title": "Good job!",
124 125 "account.register.success.message": "Account created!",
125 126 "account.register.passwordConfirmation.failed": "Wrong password confirmation",
... ... @@ -148,5 +149,20 @@
148 149 "tasks.add_friend.message": "wants to be friend of",
149 150 "tasks.add_member.message": "wants to join",
150 151 "tasks.create_community.message": "wants to create a new community:",
151   - "tasks.suggest_article.message": "suggested a new article:"
  152 + "tasks.suggest_article.message": "suggested a new article:",
  153 + "account.register.save.failed": "This account could not be created",
  154 + "account.register.mandatoryField": "This field is mandatory",
  155 + "account.register.invalidEmail": "This field must be a valid email address.",
  156 + "account.register.shortPassword": "The password must have at least 4 characters)",
  157 + "account.register.errorMessagesTitle": "There were problems with the following fields:",
  158 + "email is missing": "email can't be blank",
  159 + "login is missing": "username can't be blank",
  160 + "password is missing": "password can't be blank",
  161 + "login": "username",
  162 + "has already been taken": "has already been taken",
  163 + "email": "email",
  164 + "identifier": "identifier",
  165 + "is not available.": "is not available",
  166 + "user": "user",
  167 + "is invalid": "is invalid"
152 168 }
... ...
src/languages/messages.html
... ... @@ -1,4 +0,0 @@
1   -<li ng-message="required" translate="messages.invalid.required"></li>
2   -<li ng-message="minlength" translate="messages.invalid.minlength"></li>
3   -<li ng-message="maxlength" translate="messages.invalid.maxlength"></li>
4   -<li ng-message="email" translate="messages.invalid.email"></li>
src/languages/pt.json
... ... @@ -121,6 +121,7 @@
121 121 "account.register.passwordConfirmationLabel": "Confirmar senha",
122 122 "account.register.accountCreatingMessage": "Ao criar uma conta, você está concordando com os ",
123 123 "account.register.termsOfUseMessage": "termos de uso",
  124 + "account.register.termsOfUseTitle": "Termos de uso",
124 125 "account.register.signupMessage": "Criar Conta",
125 126 "account.register.haveAccountMessage": "Já possui uma conta?",
126 127 "account.register.success.title": "Bom trabalho!",
... ... @@ -151,5 +152,20 @@
151 152 "tasks.add_friend.message": "quer ser amigo de",
152 153 "tasks.add_member.message": "quer entrar em",
153 154 "tasks.create_community.message": "quer criar uma nova comunidade:",
154   - "tasks.suggest_article.message": "sugeriu um novo artigo:"
  155 + "tasks.suggest_article.message": "sugeriu um novo artigo:",
  156 + "account.register.save.failed": "A conta não pode ser criada",
  157 + "account.register.mandatoryField": "Este campo é obrigatório",
  158 + "account.register.invalidEmail": "Este campo deve ser um endereço de e-mail válido.",
  159 + "account.register.shortPassword": "A senha deve ter no mínimo 4 caracteres",
  160 + "account.register.errorMessagesTitle": "Houve erros com os seguintes campos:",
  161 + "email is missing": "email não pode ficar em branco",
  162 + "login is missing": "nome de usuário não pode ficar em branco",
  163 + "password is missing": "senha não pode ficar em branco",
  164 + "login": "nome de usuário",
  165 + "has already been taken": "já está sendo usado",
  166 + "email": "email",
  167 + "identifier": "identificador",
  168 + "is not available.": "não está disponível",
  169 + "user": "usuário",
  170 + "is invalid": "é inválido"
155 171 }
... ...