Commit 0aebb5d92ebefd9d0659d7341bf929a20df8b0b0
Exists in
master
and in
1 other branch
Merge branch 'registration_errors'
Showing
9 changed files
with
155 additions
and
47 deletions
Show diff stats
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> {{ 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("Register Component", () => { |
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 "./../../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
... | ... | @@ -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 | } | ... | ... |