Commit 5161636a08ea267906fc341042d3a33afbe22f75

Authored by Carlos Purificação
2 parents 7921e436 f68015db

Merge branch 'login-block' into 'master'

Login block

Added the Noosfero basic login-block.

See merge request !12
src/app/layout/blocks/login-block/index.ts 0 → 100644
src/app/layout/blocks/login-block/login-block.component.spec.ts 0 → 100644
... ... @@ -0,0 +1,110 @@
  1 +import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Injectable, Provider, provide} from "ng-forward";
  3 +import {ComponentTestHelper, createClass} from './../../../../spec/component-test-helper';
  4 +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  5 +import {providers} from 'ng-forward/cjs/testing/providers';
  6 +import {LoginBlockComponent} from './login-block.component';
  7 +import * as helpers from "./../../../../spec/helpers";
  8 +import {SessionService, AuthService, AuthController, AuthEvents} from "./../../../login";
  9 +
  10 +const htmlTemplate: string = '<noosfero-login-block></noosfero-login-block>';
  11 +
  12 +describe("Components", () => {
  13 +
  14 + describe("Login Block Component", () => {
  15 + let helper: ComponentTestHelper<LoginBlockComponent>;
  16 + let person: any = null;
  17 +
  18 + /**
  19 + * Mock objects
  20 + */
  21 + let authService: any = helpers.mocks.authService;
  22 + let user = <noosfero.User>{ person: person };
  23 + let sessionService: any = <any>helpers.mocks.sessionWithCurrentUser(user);
  24 + let state = jasmine.createSpyObj("$state", ["go"]);
  25 + let scope = helpers.mocks.scopeWithEvents;
  26 +
  27 + let providers = [
  28 + new Provider('SessionService', { useValue: sessionService }),
  29 + new Provider('$state', { useValue: state }),
  30 + new Provider('AuthService', { useValue: authService }),
  31 + new Provider('$scope', { useValue: scope })
  32 + ];
  33 +
  34 + beforeEach( angular.mock.module("templates") );
  35 +
  36 + beforeEach( (done: Function) => {
  37 + let cls = createClass({
  38 + template: htmlTemplate,
  39 + directives: [LoginBlockComponent],
  40 + providers: providers,
  41 + properties: {}
  42 + });
  43 + helper = new ComponentTestHelper<LoginBlockComponent>(cls, done);
  44 + });
  45 +
  46 + it("expect person to be null with no logged in user", () => {
  47 + expect(helper.component.currentUser).toBeNull;
  48 + });
  49 +
  50 + it("expect person to be defined when user login", () => {
  51 + // Executes the login method on the component
  52 + doComponentLogin();
  53 + expect(helper.component.currentUser.person).toBe(person);
  54 + });
  55 +
  56 + it("expect person to be null when user logout", () => {
  57 + // First do a login
  58 + doComponentLogin();
  59 + // The logout the user
  60 + doComponentLogout();
  61 + // Check if the current user was cleared
  62 + expect(helper.component.currentUser).toBeNull;
  63 + });
  64 +
  65 + /**
  66 + * Execute the logout method on the target component
  67 + */
  68 + function doComponentLogout() {
  69 + // Create a mock for the AuthService logout method
  70 + spyOn(authService, "logout");
  71 + helper.component.logout();
  72 + expect(authService.logout).toHaveBeenCalled();
  73 + // After the component logout method execution, fire the
  74 + // AuthService event
  75 + simulateLogoutEvent();
  76 + }
  77 +
  78 + /**
  79 + * Execute the login method on the target component
  80 + */
  81 + function doComponentLogin() {
  82 + // Create a mock for the AuthService login method
  83 + spyOn(authService, "login");
  84 + helper.component.login();
  85 + expect(authService.login).toHaveBeenCalled();
  86 + // After the component login method execution, fire the
  87 + // AuthService event
  88 + simulateLoginEvent();
  89 + }
  90 +
  91 + /**
  92 + * Simulate the AuthService loginSuccess event
  93 + */
  94 + function simulateLoginEvent() {
  95 + let successEvent: string = AuthEvents[AuthEvents.loginSuccess];
  96 +
  97 + (<any>helper.component.authService)[successEvent].next(user);
  98 + }
  99 +
  100 + /**
  101 + * Simulate the AuthService logoutSuccess event
  102 + */
  103 + function simulateLogoutEvent() {
  104 + let successEvent: string = AuthEvents[AuthEvents.logoutSuccess];
  105 +
  106 + (<any>helper.component.authService)[successEvent].next(user);
  107 + }
  108 + });
  109 +
  110 +});
0 111 \ No newline at end of file
... ...
src/app/layout/blocks/login-block/login-block.component.ts 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +import {Input, Inject, Component} from "ng-forward";
  2 +import {SessionService, AuthService, AuthEvents} from "./../../../login";
  3 +
  4 +/**
  5 + * @ngdoc controller
  6 + * @name layout.blocks.LoginBlockComponent
  7 + * @description
  8 + * The Noosfero block responible for presenting a login form and user status
  9 + */
  10 +@Component({
  11 + selector: "noosfero-login-block",
  12 + templateUrl: 'app/layout/blocks/login-block/login-block.html',
  13 +})
  14 +@Inject("SessionService", "$state", 'AuthService', "$scope")
  15 +export class LoginBlockComponent {
  16 +
  17 + /**
  18 + * @ngdoc property
  19 + * @name currentUser
  20 + * @propertyOf layout.blocks.LoginBlockComponent
  21 + * @description
  22 + * The current loged in user
  23 + */
  24 + currentUser: noosfero.User;
  25 +
  26 + /**
  27 + * @ngdoc property
  28 + * @name credentials
  29 + * @propertyOf layout.blocks.LoginBlockComponent
  30 + * @description
  31 + * The credentials of the currentUser
  32 + */
  33 + credentials: noosfero.Credentials;
  34 +
  35 + constructor(
  36 + private session: SessionService,
  37 + private $state: ng.ui.IStateService,
  38 + public authService: AuthService,
  39 + private $scope: ng.IScope) {
  40 + this.currentUser = this.session.currentUser();
  41 +
  42 + this.authService.subscribe(AuthEvents[AuthEvents.loginSuccess], () => {
  43 + this.currentUser = this.session.currentUser();
  44 + });
  45 +
  46 + this.authService.subscribe(AuthEvents[AuthEvents.logoutSuccess], () => {
  47 + this.currentUser = this.session.currentUser();
  48 + });
  49 +
  50 + }
  51 +
  52 + /**
  53 + * @ngdoc method
  54 + * @name login
  55 + * @methodOf layout.blocks.LoginBlockComponent
  56 + * @description
  57 + * Logs in the user using its credentials
  58 + */
  59 + login() {
  60 + this.authService.login(this.credentials);
  61 + }
  62 +
  63 + /**
  64 + * @ngdoc method
  65 + * @name logout
  66 + * @methodOf layout.blocks.LoginBlockComponent
  67 + * @description
  68 + * Logout the user
  69 + */
  70 + logout() {
  71 + this.authService.logout();
  72 + };
  73 +}
... ...
src/app/layout/blocks/login-block/login-block.html 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +<div class="logged-user-info" ng-show="ctrl.currentUser">
  2 + <h4>Logged in as {{ctrl.currentUser.person.identifier}}</h4>
  3 + <ul>
  4 + <li>User since
  5 + <span class="time">
  6 + <span am-time-ago="ctrl.currentUser.person.created_at | dateFormat"></span>
  7 + </span>
  8 + </li>
  9 + <li><a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})">Profile Homepage</a></li>
  10 + </ul>
  11 + <div class="user-actions">
  12 + <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a>
  13 + </div>
  14 +</div>
  15 +<div class="logged-user-info" ng-show="!ctrl.currentUser">
  16 + <form>
  17 + <div class="form-group">
  18 + <label for="exampleInputEmail1">{{"auth.form.login" | translate}}</label>
  19 + <input type="text" class="form-control" id="exampleInputEmail1" placeholder="Login / Email" ng-model="ctrl.credentials.username">
  20 + </div>
  21 + <div class="form-group">
  22 + <label for="exampleInputPassword1">{{"auth.form.password" | translate}}</label>
  23 + <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" ng-model="ctrl.credentials.password">
  24 + </div>
  25 + <button type="submit" class="btn btn-default" ng-click="ctrl.login()">{{"auth.form.login_button" | translate}}</button>
  26 + </form>
  27 +</div>
0 28 \ No newline at end of file
... ...
src/app/login/session.service.ts
... ... @@ -11,13 +11,11 @@ export class SessionService {
11 11  
12 12 create(data: UserResponse): noosfero.User {
13 13 this.$localStorage.currentUser = data.user;
14   - this.$log.debug('User session created.', this.$localStorage.currentUser);
15 14 return this.$localStorage.currentUser;
16 15 };
17 16  
18 17 destroy() {
19 18 delete this.$localStorage.currentUser;
20   - this.$log.debug('User session destroyed.');
21 19 };
22 20  
23 21 currentUser(): noosfero.User {
... ...
src/app/main/main.component.ts
... ... @@ -19,6 +19,7 @@ import {StatisticsBlockComponent} from &quot;../layout/blocks/statistics/statistics-b
19 19 import {MembersBlockComponent} from "./../layout/blocks/members/members-block.component";
20 20 import {CommunitiesBlockComponent} from "./../layout/blocks/communities/communities-block.component";
21 21  
  22 +import {LoginBlockComponent} from "../layout/blocks/login-block/login-block.component";
22 23  
23 24 import {NoosferoTemplate} from "../shared/pipes/noosfero-template.filter";
24 25 import {DateFormat} from "../shared/pipes/date-format.filter";
... ... @@ -96,7 +97,8 @@ export class EnvironmentContent {
96 97 EnvironmentComponent, PeopleBlockComponent,
97 98 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent,
98 99 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
99   - MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent
  100 + MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
  101 + LoginBlockComponent
100 102 ].concat(plugins.mainComponents).concat(plugins.hotspots),
101 103  
102 104 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService]
... ...
src/lib/ng-noosfero-api/interfaces/person.ts
... ... @@ -6,6 +6,5 @@ namespace noosfero {
6 6 * A representation of a Person in Noosfero.
7 7 */
8 8 export interface Person extends Profile {
9   -
10 9 }
11 10 }
12 11 \ No newline at end of file
... ...
src/lib/ng-noosfero-api/interfaces/profile.ts
... ... @@ -22,6 +22,14 @@ namespace noosfero {
22 22 * @returns {string} The unque identifier for the Profile
23 23 */
24 24 identifier: string;
  25 +
  26 + /**
  27 + * @ngdoc property
  28 + * @name created_at
  29 + * @propertyOf noofero.Profile
  30 + * @returns {string} The timestamp this object was created
  31 + */
  32 + created_at: string;
25 33  
26 34 /**
27 35 * @ngdoc property
... ...
src/spec/component-test-helper.ts
... ... @@ -2,6 +2,7 @@ import { Component } from &quot;ng-forward&quot;;
2 2 import { TestComponentBuilder, ngClass } from 'ng-forward/cjs/testing/test-component-builder';
3 3 import { INgForwardJQuery } from "ng-forward/cjs/util/jqlite-extensions";
4 4 import { ComponentFixture } from 'ng-forward/cjs/testing/test-component-builder';
  5 +import * as helpers from './helpers';
5 6  
6 7 /**
7 8 * @ngdoc object
... ... @@ -149,6 +150,7 @@ export function createClass({
149 150 providers = <any[]>[],
150 151 properties = <any>{}
151 152 }): any {
  153 + providers = providers.concat(helpers.provideFilters("translateFilter"));
152 154 @Component({ selector: 'component-test-helper-container', template, directives, providers })
153 155 class Test {
154 156 constructor() {
... ...
src/spec/mocks.ts
... ... @@ -68,6 +68,7 @@ export var mocks: any = {
68 68 mocks.authService['logoutSuccess'].event(param);
69 69 }
70 70 },
  71 + login: () => { },
71 72 logout: () => { },
72 73 subscribe: (eventName: string, fn: Function) => {
73 74 mocks.authService[eventName].subscribe(fn);
... ...