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 | } | ... | ... |