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,6 +3,14 @@ | ||
3 | <h1>{{"account.register.welcomeMessageTitle" | translate }}</h1> | 3 | <h1>{{"account.register.welcomeMessageTitle" | translate }}</h1> |
4 | <div class="environment-signup-intro" ng-bind-html="ctrl.environment.signup_intro"></div> | 4 | <div class="environment-signup-intro" ng-bind-html="ctrl.environment.signup_intro"></div> |
5 | </div> | 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 | <form name="signupForm"> | 14 | <form name="signupForm"> |
7 | <div class="row"> | 15 | <div class="row"> |
8 | <div class="col-md-12 register-field"> | 16 | <div class="col-md-12 register-field"> |
@@ -17,10 +25,12 @@ | @@ -17,10 +25,12 @@ | ||
17 | <span class="input-group-addon" style="font-weight: bold;"><i class="fa fa-globe"></i> {{ ctrl.environment.host }}</span> | 25 | <span class="input-group-addon" style="font-weight: bold;"><i class="fa fa-globe"></i> {{ ctrl.environment.host }}</span> |
18 | <input type="text" id="username" name="username" class="form-control" placeholder="{{'account.register.usernameLabel' | translate }}" ng-model="ctrl.account.login" required> | 26 | <input type="text" id="username" name="username" class="form-control" placeholder="{{'account.register.usernameLabel' | translate }}" ng-model="ctrl.account.login" required> |
19 | </div> | 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 | </div> | 34 | </div> |
25 | </div> | 35 | </div> |
26 | 36 | ||
@@ -29,22 +39,26 @@ | @@ -29,22 +39,26 @@ | ||
29 | <span class="input-group-addon"><i class="fa fa-envelope"></i></span> | 39 | <span class="input-group-addon"><i class="fa fa-envelope"></i></span> |
30 | <input type="email" class="form-control" id="email" name="email" placeholder="{{'account.register.emailLabel' | translate }}" ng-model="ctrl.account.email" required> | 40 | <input type="email" class="form-control" id="email" name="email" placeholder="{{'account.register.emailLabel' | translate }}" ng-model="ctrl.account.email" required> |
31 | </div> | 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 | </div> | 48 | </div> |
37 | </div> | 49 | </div> |
38 | 50 | ||
39 | <div class="form-group col-md-6 register-field" ng-class="ctrl.isInvalid(signupForm.password)"> | 51 | <div class="form-group col-md-6 register-field" ng-class="ctrl.isInvalid(signupForm.password)"> |
40 | <div class="input-group"> | 52 | <div class="input-group"> |
41 | <span class="input-group-addon"><i class="fa fa-lock"></i></span> | 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 | </div> | 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 | </div> | 62 | </div> |
49 | </div> | 63 | </div> |
50 | 64 | ||
@@ -55,7 +69,7 @@ | @@ -55,7 +69,7 @@ | ||
55 | </div> | 69 | </div> |
56 | <div class="help-block" ng-show="signupForm.passwordConfirm.$touched" ng-messages="signupForm.passwordConfirm.$error"> | 70 | <div class="help-block" ng-show="signupForm.passwordConfirm.$touched" ng-messages="signupForm.passwordConfirm.$error"> |
57 | <ul class="list-unstyled"> | 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 | <li ng-message="passwordMatch" translate="messages.invalid.passwordMatch"></li> | 73 | <li ng-message="passwordMatch" translate="messages.invalid.passwordMatch"></li> |
60 | </ul> | 74 | </ul> |
61 | </div> | 75 | </div> |
@@ -72,6 +86,5 @@ | @@ -72,6 +86,5 @@ | ||
72 | </div> | 86 | </div> |
73 | </form> | 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 | </div> | 90 | </div> |
src/app/account/register-terms.html
1 | <div class="modal-header"> | 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 | </div> | 3 | </div> |
4 | <div class="modal-body modal-body-overflow" ng-bind-html="ctrl.environment.terms_of_use"></div> | 4 | <div class="modal-body modal-body-overflow" ng-bind-html="ctrl.environment.terms_of_use"></div> |
5 | <div class="modal-footer"> | 5 | <div class="modal-footer"> |
src/app/account/register.component.spec.ts
1 | import { ComponentTestHelper, createClass } from "../../spec/component-test-helper"; | 1 | import { ComponentTestHelper, createClass } from "../../spec/component-test-helper"; |
2 | import * as helpers from "../../spec/helpers"; | 2 | import * as helpers from "../../spec/helpers"; |
3 | import { RegisterComponent } from "./register.component"; | 3 | import { RegisterComponent } from "./register.component"; |
4 | -// import {RegisterService} from "../../lib/ng-noosfero-api/http/register.service" | ||
5 | - | ||
6 | 4 | ||
7 | describe("Register Component", () => { | 5 | describe("Register Component", () => { |
8 | const htmlTemplate: string = '<noosfero-register></noosfero-register>'; | 6 | const htmlTemplate: string = '<noosfero-register></noosfero-register>'; |
9 | 7 | ||
10 | let helper: ComponentTestHelper<RegisterComponent>; | 8 | let helper: ComponentTestHelper<RegisterComponent>; |
11 | let registerService = helpers.mocks.registerService; | 9 | let registerService = helpers.mocks.registerService; |
12 | - let stateService = jasmine.createSpyObj("$state", ["transitionTo"]); | 10 | + let stateService: angular.ui.IStateService; |
13 | let notificationService = helpers.mocks.notificationService; | 11 | let notificationService = helpers.mocks.notificationService; |
14 | notificationService.success = jasmine.createSpy('success'); | 12 | notificationService.success = jasmine.createSpy('success'); |
15 | notificationService.error = jasmine.createSpy('error'); | 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 | beforeEach(() => { | 20 | beforeEach(() => { |
21 | + stateService = jasmine.createSpyObj("$state", ["transitionTo"]); | ||
22 | + | ||
27 | angular.mock.module('templates'); | 23 | angular.mock.module('templates'); |
28 | angular.mock.module('ngSanitize'); | 24 | angular.mock.module('ngSanitize'); |
29 | angular.mock.module('ngMessages'); | 25 | angular.mock.module('ngMessages'); |
@@ -45,8 +41,53 @@ describe("Register Component", () => { | @@ -45,8 +41,53 @@ describe("Register Component", () => { | ||
45 | helper = new ComponentTestHelper<RegisterComponent>(cls, done); | 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 | it('register page was rendered', () => { | 49 | it('register page was rendered', () => { |
49 | expect(helper.debugElement.query('div.register-page').length).toEqual(1); | 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,6 +3,7 @@ import { RegisterService } from "./../../lib/ng-noosfero-api/http/register.servi | ||
3 | import { NotificationService } from "./../shared/services/notification.service"; | 3 | import { NotificationService } from "./../shared/services/notification.service"; |
4 | import { EnvironmentService } from "../../lib/ng-noosfero-api/http/environment.service"; | 4 | import { EnvironmentService } from "../../lib/ng-noosfero-api/http/environment.service"; |
5 | import { RegisterController } from "./register.controller"; | 5 | import { RegisterController } from "./register.controller"; |
6 | +import { AuthController } from "./../login"; | ||
6 | import { IModalComponent } from "../shared/components/interfaces"; | 7 | import { IModalComponent } from "../shared/components/interfaces"; |
7 | 8 | ||
8 | @Component({ | 9 | @Component({ |
@@ -20,6 +21,8 @@ export class RegisterComponent { | @@ -20,6 +21,8 @@ export class RegisterComponent { | ||
20 | 21 | ||
21 | modalInstance: ng.ui.bootstrap.IModalServiceInstance; | 22 | modalInstance: ng.ui.bootstrap.IModalServiceInstance; |
22 | 23 | ||
24 | + errorMessages: any[]; | ||
25 | + | ||
23 | constructor( | 26 | constructor( |
24 | private $state: ng.ui.IStateService, | 27 | private $state: ng.ui.IStateService, |
25 | private $uibModal: ng.ui.bootstrap.IModalService, | 28 | private $uibModal: ng.ui.bootstrap.IModalService, |
@@ -33,19 +36,27 @@ export class RegisterComponent { | @@ -33,19 +36,27 @@ export class RegisterComponent { | ||
33 | } | 36 | } |
34 | 37 | ||
35 | signup() { | 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 | isInvalid(field: any): any { | 62 | isInvalid(field: any): any { |
@@ -63,4 +74,14 @@ export class RegisterComponent { | @@ -63,4 +74,14 @@ export class RegisterComponent { | ||
63 | scope: this.$scope | 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,6 +29,7 @@ | ||
29 | .register-page .already-registered-message { | 29 | .register-page .already-registered-message { |
30 | margin-top: 60px; | 30 | margin-top: 60px; |
31 | text-align: center; | 31 | text-align: center; |
32 | + display: block; | ||
32 | } | 33 | } |
33 | 34 | ||
34 | .register-page input { | 35 | .register-page input { |
@@ -0,0 +1,4 @@ | @@ -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,6 +120,7 @@ | ||
120 | "account.register.signupMessage": "Register", | 120 | "account.register.signupMessage": "Register", |
121 | "account.register.haveAccountMessage": "Already have an account?", | 121 | "account.register.haveAccountMessage": "Already have an account?", |
122 | "account.register.termsOfUseMessage": "terms of use", | 122 | "account.register.termsOfUseMessage": "terms of use", |
123 | + "account.register.termsOfUseTitle": "Terms of use", | ||
123 | "account.register.success.title": "Good job!", | 124 | "account.register.success.title": "Good job!", |
124 | "account.register.success.message": "Account created!", | 125 | "account.register.success.message": "Account created!", |
125 | "account.register.passwordConfirmation.failed": "Wrong password confirmation", | 126 | "account.register.passwordConfirmation.failed": "Wrong password confirmation", |
@@ -148,5 +149,20 @@ | @@ -148,5 +149,20 @@ | ||
148 | "tasks.add_friend.message": "wants to be friend of", | 149 | "tasks.add_friend.message": "wants to be friend of", |
149 | "tasks.add_member.message": "wants to join", | 150 | "tasks.add_member.message": "wants to join", |
150 | "tasks.create_community.message": "wants to create a new community:", | 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,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,6 +121,7 @@ | ||
121 | "account.register.passwordConfirmationLabel": "Confirmar senha", | 121 | "account.register.passwordConfirmationLabel": "Confirmar senha", |
122 | "account.register.accountCreatingMessage": "Ao criar uma conta, você está concordando com os ", | 122 | "account.register.accountCreatingMessage": "Ao criar uma conta, você está concordando com os ", |
123 | "account.register.termsOfUseMessage": "termos de uso", | 123 | "account.register.termsOfUseMessage": "termos de uso", |
124 | + "account.register.termsOfUseTitle": "Termos de uso", | ||
124 | "account.register.signupMessage": "Criar Conta", | 125 | "account.register.signupMessage": "Criar Conta", |
125 | "account.register.haveAccountMessage": "Já possui uma conta?", | 126 | "account.register.haveAccountMessage": "Já possui uma conta?", |
126 | "account.register.success.title": "Bom trabalho!", | 127 | "account.register.success.title": "Bom trabalho!", |
@@ -151,5 +152,20 @@ | @@ -151,5 +152,20 @@ | ||
151 | "tasks.add_friend.message": "quer ser amigo de", | 152 | "tasks.add_friend.message": "quer ser amigo de", |
152 | "tasks.add_member.message": "quer entrar em", | 153 | "tasks.add_member.message": "quer entrar em", |
153 | "tasks.create_community.message": "quer criar uma nova comunidade:", | 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 | } |