Commit 64000ab5a564b9ee11a757d634c2ec1698838746

Authored by Michel Felipe
2 parents fb1e923a b4a0a739

Merge branch 'register_page' into 'master'

See merge request !47
bower.json
... ... @@ -39,7 +39,8 @@
39 39 "angular-click-outside": "^2.7.1",
40 40 "ng-ckeditor": "^0.2.1",
41 41 "angular-tag-cloud": "^0.3.0",
42   - "angular-ui-switch": "^0.1.1"
  42 + "angular-ui-switch": "^0.1.1",
  43 + "angular-password": "^1.0.1"
43 44 },
44 45 "devDependencies": {
45 46 "angular-mocks": "~1.5.0"
... ...
src/app/account/index.ts 0 → 100644
... ... @@ -0,0 +1 @@
  1 +export * from "./register.component";
... ...
src/app/account/register-component.html 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +<div class="register-page">
  2 + <div class="welcome-message">
  3 + <h1>{{"account.register.welcomeMessageTitle" | translate }}</h1>
  4 + <div class="environment-signup-intro" ng-bind-html="ctrl.environment.signup_intro"></div>
  5 + </div>
  6 + <form name="signupForm">
  7 + <div class="row">
  8 + <div class="col-md-12 register-field">
  9 + <div class="input-group">
  10 + <span class="input-group-addon"><i class="fa fa-male"></i><i class="fa fa-female"></i></span>
  11 + <input type="text" class="form-control" id="name" name="fullName" placeholder="{{'account.register.fullNameLabel' | translate }}" ng-model="ctrl.account.name">
  12 + </div>
  13 + </div>
  14 +
  15 + <div class="form-group col-md-12 register-field" ng-class="ctrl.isInvalid(signupForm.username)">
  16 + <div class="input-group">
  17 + <span class="input-group-addon" style="font-weight: bold;"><i class="fa fa-globe"></i>&nbsp;{{ 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>
  19 + </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>
  24 + </div>
  25 + </div>
  26 +
  27 + <div class="form-group col-md-12 register-field" ng-class="ctrl.isInvalid(signupForm.email)">
  28 + <div class="input-group">
  29 + <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>
  31 + </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>
  36 + </div>
  37 + </div>
  38 +
  39 + <div class="form-group col-md-6 register-field" ng-class="ctrl.isInvalid(signupForm.password)">
  40 + <div class="input-group">
  41 + <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>
  43 + </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>
  48 + </div>
  49 + </div>
  50 +
  51 + <div class="form-group col-md-6 register-field" ng-class="ctrl.isInvalid(signupForm.passwordConfirm)">
  52 + <div class="input-group">
  53 + <span class="input-group-addon"><i class="fa fa-unlock-alt"></i></span>
  54 + <input type="password" class="form-control" id="passwordConfirm" name="passwordConfirm" match-password="password" placeholder="{{'account.register.passwordConfirmationLabel' | translate}}" ng-model="ctrl.account.passwordConfirmation" required>
  55 + </div>
  56 + <div class="help-block" ng-show="signupForm.passwordConfirm.$touched" ng-messages="signupForm.passwordConfirm.$error">
  57 + <ul class="list-unstyled">
  58 + <li ng-messages-include="languages/messages.html"></li>
  59 + <li ng-message="passwordMatch" translate="messages.invalid.passwordMatch"></li>
  60 + </ul>
  61 + </div>
  62 + </div>
  63 +
  64 + <div class="col-md-12">
  65 + <p class="terms-info">{{"account.register.accountCreatingMessage" | translate}} <a (click)="ctrl.openTerms()" href="#">{{"account.register.termsOfUseMessage" | translate}}</a>.</p>
  66 + </div>
  67 +
  68 + <div class="col-md-12">
  69 + <button type="submit" class="btn btn-default" ng-disabled="signupForm.$invalid" ng-click="ctrl.signup()">{{"account.register.signupMessage" | translate}}</button>
  70 + </div>
  71 +
  72 + </div>
  73 + </form>
  74 +
  75 + <p class="already-registered-message">{{"account.register.haveAccountMessage" | translate}}</p>
  76 +
  77 +</div>
... ...
src/app/account/register-terms.html 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +<div class="modal-header">
  2 + <h3 class="modal-title">Register terms</h3>
  3 +</div>
  4 +<div class="modal-body modal-body-overflow" ng-bind-html="ctrl.environment.terms_of_use"></div>
  5 +<div class="modal-footer">
  6 + <button class="btn btn-primary" type="button" (click)="vm.closeTerms()">OK</button>
  7 +</div>
... ...
src/app/account/register.component.spec.ts 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +import { ComponentTestHelper, createClass } from "../../spec/component-test-helper";
  2 +import * as helpers from "../../spec/helpers";
  3 +import { RegisterComponent } from "./register.component";
  4 +// import {RegisterService} from "../../lib/ng-noosfero-api/http/register.service"
  5 +
  6 +
  7 +describe("Register Component", () => {
  8 + const htmlTemplate: string = '<noosfero-register></noosfero-register>';
  9 +
  10 + let helper: ComponentTestHelper<RegisterComponent>;
  11 + let registerService = helpers.mocks.registerService;
  12 + let stateService = jasmine.createSpyObj("$state", ["transitionTo"]);
  13 + let notificationService = helpers.mocks.notificationService;
  14 + notificationService.success = jasmine.createSpy('success');
  15 + 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 + };
  25 +
  26 + beforeEach(() => {
  27 + angular.mock.module('templates');
  28 + angular.mock.module('ngSanitize');
  29 + angular.mock.module('ngMessages');
  30 + angular.mock.module('ngPassword');
  31 + });
  32 +
  33 + beforeEach((done) => {
  34 + let cls = createClass({
  35 + template: htmlTemplate,
  36 + directives: [RegisterComponent],
  37 + providers: [
  38 + helpers.createProviderToValue('$state', stateService),
  39 + helpers.createProviderToValue('$uibModal', helpers.mocks.$modal),
  40 + helpers.createProviderToValue('RegisterService', registerService),
  41 + helpers.createProviderToValue('NotificationService', notificationService),
  42 + helpers.createProviderToValue('EnvironmentService', helpers.mocks.environmentService)
  43 + ]
  44 + });
  45 + helper = new ComponentTestHelper<RegisterComponent>(cls, done);
  46 + });
  47 +
  48 + it('register page was rendered', () => {
  49 + expect(helper.debugElement.query('div.register-page').length).toEqual(1);
  50 + });
  51 +
  52 +});
... ...
src/app/account/register.component.ts 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +import { Inject, Input, Component, Output, EventEmitter, provide } from 'ng-forward';
  2 +import { RegisterService } from "./../../lib/ng-noosfero-api/http/register.service";
  3 +import { NotificationService } from "./../shared/services/notification.service";
  4 +import { EnvironmentService } from "../../lib/ng-noosfero-api/http/environment.service";
  5 +import { RegisterController } from "./register.controller";
  6 +import { IModalComponent } from "../shared/components/interfaces";
  7 +
  8 +@Component({
  9 + selector: 'noosfero-register',
  10 + templateUrl: 'app/account/register-component.html',
  11 + providers: [
  12 + provide('registerService', { useClass: RegisterService })
  13 + ]
  14 +})
  15 +
  16 +@Inject('$state', '$uibModal', '$scope', RegisterService, NotificationService, EnvironmentService)
  17 +export class RegisterComponent {
  18 + @Input() account: any;
  19 + environment: noosfero.Environment;
  20 +
  21 + modalInstance: ng.ui.bootstrap.IModalServiceInstance;
  22 +
  23 + constructor(
  24 + private $state: ng.ui.IStateService,
  25 + private $uibModal: ng.ui.bootstrap.IModalService,
  26 + private $scope: ng.IScope,
  27 + public registerService: RegisterService,
  28 + private notificationService: NotificationService,
  29 + private environmentService: EnvironmentService
  30 + ) {
  31 + this.account = {};
  32 + this.environment = environmentService.getCurrentEnvironment();
  33 + }
  34 +
  35 + 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');
  44 + }
  45 + });
  46 + } else {
  47 + this.notificationService.error({ message: "account.register.passwordConfirmation.failed" });
  48 + }
  49 + }
  50 +
  51 + isInvalid(field: any): any {
  52 + return { 'has-error': field['$touched'] && field['$invalid'] };
  53 + }
  54 +
  55 + openTerms() {
  56 +
  57 + this.modalInstance = this.$uibModal.open({
  58 + templateUrl: 'app/account/register-terms.html',
  59 + size: 'lg',
  60 + controller: RegisterController,
  61 + controllerAs: 'vm',
  62 + bindToController: true,
  63 + scope: this.$scope
  64 + });
  65 + }
  66 +}
... ...
src/app/account/register.controller.ts 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +import { Input } from "ng-forward";
  2 +import { IModalComponent } from "../shared/components/interfaces";
  3 +
  4 +export class RegisterController {
  5 +
  6 + static $inject = ["$log", "$stateParams", "$scope"];
  7 + ctrl: IModalComponent;
  8 +
  9 + constructor(
  10 + private $log: ng.ILogService,
  11 + private $stateParams: any
  12 + ) { }
  13 +
  14 + closeTerms() {
  15 + this.ctrl.modalInstance.dismiss('ok');
  16 + }
  17 +}
... ...
src/app/account/register.html 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<div class="row">
  2 + <div class="col-md-3"></div>
  3 +
  4 + <!-- component at center of page -->
  5 + <div class="col-md-6">
  6 + <noosfero-register></noosfero-register>
  7 + </div>
  8 +
  9 + <div class="col-md-3"></div>
  10 +</div>
... ...
src/app/account/scss/register.scss 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +.modal .modal-body-overflow {
  2 + max-height: 420px;
  3 + overflow-y: auto;
  4 +}
  5 +
  6 +.register-page button {
  7 + width: 100%;
  8 + text-transform: uppercase;
  9 + font-weight: 600;
  10 +}
  11 +
  12 +.register-page .light-text {
  13 + color: #BBB;
  14 + margin-top: 0px;
  15 + margin-bottom: 0px;
  16 + font-weight: 600;
  17 +}
  18 +
  19 +.register-page .terms-info {
  20 + margin-top: 30px;
  21 + margin-bottom: 30px;
  22 + font-weight: bold;
  23 +}
  24 +
  25 +.register-page .welcome-message {
  26 + text-align: center;
  27 +}
  28 +
  29 +.register-page .already-registered-message {
  30 + margin-top: 60px;
  31 + text-align: center;
  32 +}
  33 +
  34 +.register-page input {
  35 + height: 40px;
  36 +}
  37 +
  38 +.register-page .register-field {
  39 + margin-bottom: 25px;
  40 +}
  41 +
  42 +.register-page input:focus {
  43 + border: 2px solid #bbb;
  44 +}
... ...
src/app/layout/blocks/block.component.ts
... ... @@ -18,7 +18,7 @@ export class BlockComponent {
18 18 @Input() block: noosfero.Block;
19 19 @Input() owner: noosfero.Profile | noosfero.Environment;
20 20  
21   - private modalInstance: any = null;
  21 + private modalInstance: ng.ui.bootstrap.IModalServiceInstance;
22 22 originalBlock: noosfero.Block;
23 23  
24 24 currentUser: noosfero.User;
... ... @@ -26,7 +26,8 @@ export class BlockComponent {
26 26 editionMode = false;
27 27 designMode = false;
28 28  
29   - constructor(private $uibModal: any,
  29 + constructor(
  30 + private $uibModal: ng.ui.bootstrap.IModalService,
30 31 private $scope: ng.IScope,
31 32 private $state: ng.ui.IStateService,
32 33 private $rootScope: ng.IRootScopeService,
... ...
src/app/layout/navbar/navbar.html
... ... @@ -20,6 +20,12 @@
20 20 <a ng-href="#" ng-click="ctrl.openLogin()">{{"navbar.login" | translate}}</a>
21 21 </li>
22 22  
  23 + <li ng-show="!ctrl.currentUser">
  24 + <a ui-sref="main.register">
  25 + Sign Up
  26 + </a>
  27 + </li>
  28 +
23 29 <li class="dropdown profile-menu" ng-show="ctrl.currentUser" uib-dropdown>
24 30 <a href="#" class="dropdown-toggle" aria-expanded="false" uib-dropdown-toggle>
25 31 <noosfero-profile-image [profile]="ctrl.currentUser.person" class="profile-image"></noosfero-profile-image>
... ...
src/app/layout/navbar/navbar.ts
1   -import {Component, Inject, EventEmitter, Input} from "ng-forward";
2   -import {LanguageSelectorComponent} from "../language-selector/language-selector.component";
3   -import {SessionService, AuthService, AuthController, AuthEvents} from "./../../login";
4   -import {EnvironmentService} from "./../../../lib/ng-noosfero-api/http/environment.service";
5   -import {SidebarNotificationService} from "../sidebar/sidebar.notification.service";
6   -import {BodyStateClassesService} from '../services/body-state-classes.service';
7   -import {DesignModeTogglerComponent} from './../../admin/layout-edit/designModeToggler.component';
8   -import {BootstrapSwitcherComponent, BootstrapSwitcherItem} from './../../shared/components/bootstrap-switcher/bootstrap-switcher.component';
  1 +import { Component, Inject, EventEmitter, Input } from "ng-forward";
  2 +import { LanguageSelectorComponent } from "../language-selector/language-selector.component";
  3 +import { SessionService, AuthService, AuthController, AuthEvents } from "./../../login";
  4 +import { EnvironmentService } from "./../../../lib/ng-noosfero-api/http/environment.service";
  5 +import { SidebarNotificationService } from "../sidebar/sidebar.notification.service";
  6 +import { BodyStateClassesService } from '../services/body-state-classes.service';
  7 +import { DesignModeTogglerComponent } from './../../admin/layout-edit/designModeToggler.component';
  8 +import { BootstrapSwitcherComponent, BootstrapSwitcherItem } from './../../shared/components/bootstrap-switcher/bootstrap-switcher.component';
9 9  
10 10 @Component({
11 11 selector: "acme-navbar",
... ... @@ -17,14 +17,14 @@ import {BootstrapSwitcherComponent, BootstrapSwitcherItem} from &#39;./../../shared/
17 17 export class Navbar {
18 18  
19 19 private currentUser: noosfero.User;
20   - private modalInstance: any = null;
  20 + private modalInstance: ng.ui.bootstrap.IModalServiceInstance;
21 21 public showHamburger: boolean = false;
22 22 public currentEnvironment: noosfero.Environment = <any>{ name: '' };
23 23 /**
24 24 *
25 25 */
26 26 constructor(
27   - private $uibModal: any,
  27 + private $uibModal: ng.ui.bootstrap.IModalService,
28 28 public authService: AuthService,
29 29 private session: SessionService,
30 30 private $state: ng.ui.IStateService,
... ...
src/app/layout/scss/_forms.scss
... ... @@ -2,6 +2,10 @@ label {
2 2 cursor: pointer;
3 3 }
4 4  
  5 +.has-error .help-block {
  6 + font-weight: bold;
  7 +}
  8 +
5 9 .checkbox-nice {
6 10 position: relative;
7 11 padding-left: 15px;
... ...
src/app/login/login.html
... ... @@ -21,4 +21,7 @@
21 21 </div>
22 22 <button type="submit" class="btn btn-default btn-block" ng-click="vm.login()">{{"auth.form.login_button" | translate}}</button>
23 23 </form>
  24 + <div class="text-center">
  25 + <a ui-sref="main.register" ng-click="$close()">{{"auth.createAccount" | translate}}</a>
  26 + </div>
24 27 </div>
... ...
src/app/login/session.service.ts
... ... @@ -23,4 +23,4 @@ export class SessionService {
23 23 return this.$localStorage.currentUser;
24 24 };
25 25  
26   -}
27 26 \ No newline at end of file
  27 +}
... ...
src/app/main/main.component.ts
... ... @@ -21,6 +21,7 @@ import { PersonTagsPluginInterestsBlockComponent } from &quot;../layout/blocks/person
21 21 import { TagsBlockComponent } from "../layout/blocks/tags/tags-block.component";
22 22 import { CustomContentComponent } from "../profile/custom-content/custom-content.component";
23 23 import { RecentActivitiesPluginActivitiesBlockComponent } from "../layout/blocks/recent-activities-plugin-activities/recent-activities-plugin-activities-block.component";
  24 +import { RegisterComponent } from "../account/register.component";
24 25  
25 26 import { MembersBlockComponent } from "../layout/blocks/members/members-block.component";
26 27 import { CommunitiesBlockComponent } from "../layout/blocks/communities/communities-block.component";
... ... @@ -34,6 +35,7 @@ import { AuthService } from &quot;../login/auth.service&quot;;
34 35 import { SessionService } from "../login/session.service";
35 36 import { EnvironmentService } from "./../../lib/ng-noosfero-api/http/environment.service";
36 37 import { NotificationService } from "../shared/services/notification.service";
  38 +import { RegisterService } from "./../../lib/ng-noosfero-api/http/register.service";
37 39  
38 40 import { BodyStateClassesService } from "./../layout/services/body-state-classes.service";
39 41  
... ... @@ -113,16 +115,16 @@ export class EnvironmentContent {
113 115 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
114 116 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
115 117 LoginBlockComponent, CustomContentComponent, PermissionDirective, SearchFormComponent, SearchComponent,
116   - PersonTagsPluginInterestsBlockComponent, TagsBlockComponent, RecentActivitiesPluginActivitiesBlockComponent, BlockComponent
  118 + PersonTagsPluginInterestsBlockComponent, TagsBlockComponent, RecentActivitiesPluginActivitiesBlockComponent, BlockComponent, RegisterComponent
117 119 ].concat(plugins.mainComponents).concat(plugins.hotspots),
118   - providers: [AuthService, SessionService, NotificationService, BodyStateClassesService,
  120 + providers: [AuthService, SessionService, NotificationService, BodyStateClassesService, RegisterService,
119 121 "ngAnimate", "ngCookies", "ngStorage", "ngTouch",
120 122 "ngSanitize", "ngMessages", "ngAria", "restangular",
121 123 "ui.router", "ui.bootstrap", "toastr", "ngCkeditor",
122 124 "angular-bind-html-compile", "angularMoment", "angular.filter", "akoenig.deckgrid",
123 125 "angular-timeline", "duScroll", "oitozero.ngSweetAlert",
124 126 "pascalprecht.translate", "tmh.dynamicLocale", "angularLoad",
125   - "angular-click-outside", "ngTagCloud", "noosfero.init", "uiSwitch"]
  127 + "angular-click-outside", "ngTagCloud", "noosfero.init", "uiSwitch", "ngPassword"]
126 128 })
127 129 @StateConfig([
128 130 {
... ... @@ -143,7 +145,6 @@ export class EnvironmentContent {
143 145 url: '/',
144 146 component: EnvironmentComponent,
145 147 name: 'main.environment',
146   - abstract: true,
147 148 views: {
148 149 "content": {
149 150 templateUrl: "app/environment/environment.html",
... ... @@ -153,6 +154,18 @@ export class EnvironmentContent {
153 154 }
154 155 },
155 156 {
  157 + url: '/account/signup',
  158 + component: RegisterComponent,
  159 + name: 'main.register',
  160 + views: {
  161 + "content": {
  162 + templateUrl: "app/account/register.html",
  163 + controller: RegisterComponent,
  164 + controllerAs: "vm"
  165 + }
  166 + }
  167 + },
  168 + {
156 169 url: "^/:profile",
157 170 abstract: true,
158 171 component: ProfileComponent,
... ...
src/app/profile/custom-content/custom-content.component.ts
1   -import {Component, Input, Inject} from 'ng-forward';
2   -import {ProfileService} from '../../../lib/ng-noosfero-api/http/profile.service';
3   -import {NotificationService} from '../../shared/services/notification.service';
4   -import {PermissionDirective} from '../../shared/components/permission/permission.directive';
5   -import {DesignModeService} from '../../admin/layout-edit/designMode.service';
  1 +import { Component, Input, Inject } from 'ng-forward';
  2 +import { ProfileService } from '../../../lib/ng-noosfero-api/http/profile.service';
  3 +import { NotificationService } from '../../shared/services/notification.service';
  4 +import { PermissionDirective } from '../../shared/components/permission/permission.directive';
  5 +import { DesignModeService } from '../../admin/layout-edit/designMode.service';
6 6  
7 7 @Component({
8 8 selector: 'custom-content',
... ... @@ -21,9 +21,10 @@ export class CustomContentComponent {
21 21  
22 22 content: string;
23 23 originalContent: string;
24   - private modalInstance: any = null;
  24 + private modalInstance: ng.ui.bootstrap.IModalServiceInstance;
25 25  
26   - constructor(private $uibModal: any,
  26 + constructor(
  27 + private $uibModal: ng.ui.bootstrap.IModalService,
27 28 private $scope: ng.IScope,
28 29 private profileService: ProfileService,
29 30 private notificationService: NotificationService,
... ...
src/app/shared/components/interfaces.ts
1   -
2   -
3 1 export interface IComponentWithPermissions {
4 2 permissions: () => string[];
5   -}
6 3 \ No newline at end of file
  4 +}
  5 +
  6 +export interface IModalComponent {
  7 + $uibModal: ng.ui.bootstrap.IModalService;
  8 + modalInstance: ng.ui.bootstrap.IModalServiceInstance;
  9 +}
... ...
src/languages/en.json
... ... @@ -28,6 +28,7 @@
28 28 "auth.form.password": "Password",
29 29 "auth.form.keepLoggedIn": "Keep me logged in",
30 30 "auth.form.login_button": "Login",
  31 + "auth.createAccount": "Create account",
31 32 "navbar.content_viewer_actions.new_item": "New Item",
32 33 "navbar.profile_actions.new_item": "New Item",
33 34 "navbar.content_viewer_actions.new_post": "New Post",
... ... @@ -100,5 +101,23 @@
100 101 "block.edition.language.label": "Show for:",
101 102 "activities.event.description": "Event on",
102 103 "time.at": "at",
103   - "date.on": "On"
  104 + "date.on": "On",
  105 + "account.register.welcomeMessageTitle": "Nice to have you there!",
  106 + "account.register.fullNameLabel": "Full name",
  107 + "account.register.usernameLabel": "Username",
  108 + "account.register.emailLabel": "Email",
  109 + "account.register.passwordLabel": "Password",
  110 + "account.register.passwordConfirmationLabel": "Password confirmation",
  111 + "account.register.accountCreatingMessage": "By creating an account, you are agreeing with the ",
  112 + "account.register.signupMessage": "Register",
  113 + "account.register.haveAccountMessage": "Already have an account?",
  114 + "account.register.termsOfUseMessage": "terms of use",
  115 + "account.register.success.title": "Good job!",
  116 + "account.register.success.message": "Account created!",
  117 + "account.register.passwordConfirmation.failed": "Wrong password confirmation",
  118 + "messages.invalid.required": "This field is required",
  119 + "messages.invalid.maxlength": "This field is too long",
  120 + "messages.invalid.minlength": "This field is too short",
  121 + "messages.invalid.email": "This needs to be a valid email",
  122 + "messages.invalid.passwordMatch": "Your passwords did not match"
104 123 }
... ...
src/languages/messages.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/pt.json
... ... @@ -28,6 +28,7 @@
28 28 "auth.form.password": "Senha",
29 29 "auth.form.keepLoggedIn": "Continuar logado",
30 30 "auth.form.login_button": "Login",
  31 + "auth.createAccount": "Criar conta",
31 32 "navbar.content_viewer_actions.new_item": "Novo Item",
32 33 "navbar.profile_actions.new_item": "Novo Item",
33 34 "navbar.content_viewer_actions.new_post": "Novo Artigo",
... ... @@ -100,5 +101,26 @@
100 101 "block.edition.language.label": "Exibir para:",
101 102 "activities.event.description": "Evento em",
102 103 "time.at": "às",
103   - "date.on": "Em"
  104 + "date.on": "Em",
  105 + "account.register.welcomeMessageTitle": "Ótimo ter você aqui!",
  106 + "account.register.seeMoreMessage": "Saiba mais ",
  107 + "account.register.informationsMessage": "informações",
  108 + "account.register.fullNameLabel": "Nome completo",
  109 + "account.register.lastNameLabel": "Sobrenome",
  110 + "account.register.usernameLabel": "Nome de usuário",
  111 + "account.register.emailLabel": "Email",
  112 + "account.register.passwordLabel": "Senha",
  113 + "account.register.passwordConfirmationLabel": "Confirmar senha",
  114 + "account.register.accountCreatingMessage": "Ao criar uma conta, você está concordando com os ",
  115 + "account.register.termsOfUseMessage": "termos de uso",
  116 + "account.register.signupMessage": "Criar Conta",
  117 + "account.register.haveAccountMessage": "Já possui uma conta?",
  118 + "account.register.success.title": "Bom trabalho!",
  119 + "account.register.success.message": "Conta criada com sucesso!",
  120 + "account.register.passwordConfirmation.failed": "A confirmação de senha não corresponde à senha",
  121 + "messages.invalid.required": "Campo obrigatório",
  122 + "messages.invalid.maxlength": "O valor é muito longo",
  123 + "messages.invalid.minlength": "O valor é muito curto",
  124 + "messages.invalid.email": "Informe um email válido",
  125 + "messages.invalid.passwordMatch": "As senhas não coincidem"
104 126 }
... ...
src/lib/ng-noosfero-api/http/article.service.spec.ts
... ... @@ -17,7 +17,6 @@ describe(&quot;Services&quot;, () =&gt; {
17 17 articleService = _ArticleService_;
18 18 }));
19 19  
20   -
21 20 describe("Succesfull requests", () => {
22 21  
23 22 it("should remove article", (done) => {
... ... @@ -92,6 +91,5 @@ describe(&quot;Services&quot;, () =&gt; {
92 91 });
93 92 });
94 93  
95   -
96 94 });
97 95 });
... ...
src/lib/ng-noosfero-api/http/register.service.spec.ts 0 → 100644
... ... @@ -0,0 +1,39 @@
  1 +import { RegisterService } from "./register.service";
  2 +
  3 +describe("Services", () => {
  4 +
  5 + describe("Register Service", () => {
  6 +
  7 + let $httpBackend: ng.IHttpBackendService;
  8 + let registerService: RegisterService;
  9 + let $rootScope: ng.IRootScopeService;
  10 + let user: any = {
  11 + id: 1,
  12 + login: 'test',
  13 + email: 'test@email.com'
  14 + };
  15 +
  16 + beforeEach(angular.mock.module("main", ($translateProvider: angular.translate.ITranslateProvider) => {
  17 + $translateProvider.translations('en', {});
  18 + }));
  19 +
  20 + beforeEach(inject((_$httpBackend_: ng.IHttpBackendService, _RegisterService_: RegisterService, _$rootScope_: ng.IRootScopeService) => {
  21 + $httpBackend = _$httpBackend_;
  22 + registerService = _RegisterService_;
  23 + $rootScope = _$rootScope_;
  24 + }));
  25 +
  26 + describe("Succesfull requests", () => {
  27 +
  28 + it("should creaet a new account", (done) => {
  29 +
  30 + $httpBackend.expectPOST(`/api/v1/register?email=${user.email}&id=${user.id}&login=${user.login}`).respond(201, [{ login: "test" }]);
  31 + registerService.createAccount(user).then((response: restangular.IResponse) => {
  32 + expect(response.data[0].login).toEqual("test");
  33 + done();
  34 + });
  35 + $httpBackend.flush();
  36 + });
  37 + });
  38 + });
  39 +});
... ...
src/lib/ng-noosfero-api/http/register.service.ts 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +import { Injectable, Inject } from "ng-forward";
  2 +import { RestangularService } from "./restangular_service";
  3 +
  4 +@Injectable()
  5 +@Inject("Restangular")
  6 +export class RegisterService {
  7 + constructor(private Restangular: restangular.IService) {
  8 + this.Restangular = Restangular;
  9 + }
  10 +
  11 + createAccount(user: noosfero.User): ng.IPromise<noosfero.RestResult<noosfero.User>> {
  12 + return this.Restangular.all("").customPOST(user, "register", user);
  13 + }
  14 +}
... ...
src/lib/ng-noosfero-api/http/restangular_service.ts
... ... @@ -80,14 +80,16 @@ export abstract class RestangularService&lt;T extends noosfero.RestModel&gt; {
80 80 }
81 81 return {
82 82 data: (response.data[dataKey] || response.data),
83   - headers: response.headers
  83 + headers: response.headers,
  84 + status: response.status
84 85 };
85 86 };
86 87  
87 88 protected buildResult(response: restangular.IResponse): noosfero.RestResult<T> {
88 89 return {
89 90 data: response.data,
90   - headers: response.headers
  91 + headers: response.headers,
  92 + status: response.status
91 93 };
92 94 };
93 95 /**
... ...
src/lib/ng-noosfero-api/interfaces/environment.ts
... ... @@ -5,7 +5,7 @@ namespace noosfero {
5 5 * @name noofero.Environment
6 6 * @description
7 7 * A representation of a Noosfero Environment.
8   - */
  8 + */
9 9 export interface Environment extends RestModel {
10 10 /**
11 11 * @ngdoc property
... ... @@ -23,6 +23,21 @@ namespace noosfero {
23 23 * @returns {string} The Environment layout (e.g. default, rightbar)
24 24 */
25 25 layout_template: string;
  26 +
  27 + /**
  28 + * @ngdoc property
  29 + * @name signup_intro
  30 + * @propertyOf noofero.Environment
  31 + * @returns {string} The Environment signup introduction HTML (e.g. Welcome to Noosfero...!!)
  32 + */
  33 + signup_intro: string;
  34 +
  35 + /**
  36 + * @ngdoc property
  37 + * @name host
  38 + * @propertyOf noofero.Environment
  39 + * @returns {string} The Environment default domain address with 'http://' prefix (e.g. http://localhost)
  40 + */
  41 + host: string;
26 42 }
27 43 }
28   -
... ...
src/lib/ng-noosfero-api/interfaces/rest_result.ts
... ... @@ -3,5 +3,6 @@ namespace noosfero {
3 3 export interface RestResult<T> {
4 4 data: T;
5 5 headers: Function;
  6 + status: Number;
6 7 }
7   -}
8 8 \ No newline at end of file
  9 +}
... ...
src/spec/mocks.ts
... ... @@ -40,6 +40,11 @@ export var mocks: any = {
40 40 return this.modalInstance;
41 41 }
42 42 },
  43 + registerService: {
  44 + createAccount: (user: noosfero.User) => {
  45 + return Promise.resolve({ status: 201 });
  46 + }
  47 + },
43 48 authService: {
44 49 loginSuccess: {
45 50 event: Function,
... ... @@ -145,6 +150,15 @@ export var mocks: any = {
145 150 return mocks.promiseResultTemplate({
146 151 people: {}
147 152 });
  153 + },
  154 + getCurrentEnvironment: (): any => {
  155 + return {
  156 + id: 1,
  157 + settings: {},
  158 + layout_template: '',
  159 + signup_intro: 'Welcome to Noosfero',
  160 + host: 'http://localhost'
  161 + };
148 162 }
149 163 },
150 164 profileService: {
... ... @@ -240,6 +254,7 @@ export var mocks: any = {
240 254 },
241 255 notificationService: {
242 256 success: () => { },
243   - confirmation: () => { }
  257 + confirmation: () => { },
  258 + error: () => { }
244 259 }
245 260 };
... ...
typings.json
... ... @@ -8,6 +8,7 @@
8 8 "angular-mocks": "github:DefinitelyTyped/DefinitelyTyped/angularjs/angular-mocks.d.ts",
9 9 "angular-translate": "github:DefinitelyTyped/DefinitelyTyped/angular-translate/angular-translate.d.ts#19850bf86c876e0c2544842114878ece4664941a",
10 10 "angular-ui-router": "github:DefinitelyTyped/DefinitelyTyped/angular-ui-router/angular-ui-router.d.ts#655f8c1bf3c71b0e1ba415b36309604f79326ac8",
  11 + "angular-ui-bootstrap": "github:DefinitelyTyped/DefinitelyTyped/angular-ui-bootstrap/angular-ui-bootstrap.d.ts",
11 12 "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#4de74cb527395c13ba20b438c3a7a419ad931f1c",
12 13 "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#dd638012d63e069f2c99d06ef4dcc9616a943ee4",
13 14 "jquery": "github:DefinitelyTyped/DefinitelyTyped/jquery/jquery.d.ts#470954c4f427e0805a2d633636a7c6aa7170def8",
... ...