Commit b7f58749b06254a479706327ad4a6c9a91c9ed8f

Authored by Ábner Oliveira
2 parents da20ce18 0c28a983

Merge branch 'master' of softwarepublico.gov.br:noosfero-themes/angular-theme

src/app/layout/blocks/block-content.component.spec.ts 0 → 100644
@@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
  1 +import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Input, provide, Component} from 'ng-forward';
  3 +
  4 +import {BlockContentComponent} from './block-content.component';
  5 +
  6 +const tcb = new TestComponentBuilder();
  7 +
  8 +const htmlTemplate: string = '<noosfero-block-content [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-block-content>';
  9 +
  10 +describe("Components", () => {
  11 + describe("Block Component", () => {
  12 +
  13 + // the karma preprocessor html2js transform the templates html into js files which put
  14 + // the templates to the templateCache into the module templates
  15 + // we need to load the module templates here as the template for the
  16 + // component Block will be load on our tests
  17 + beforeEach(angular.mock.module("templates"));
  18 +
  19 + it("receives the block and the owner as inputs", done => {
  20 +
  21 + // Creating a container component (BlockContainerComponent) to include
  22 + // the component under test (Block)
  23 + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockContentComponent] })
  24 + class BlockContainerComponent {
  25 + block = { type: 'Block' };
  26 + owner = { name: 'profile-name' };
  27 + constructor() {
  28 + }
  29 + }
  30 +
  31 + // uses the TestComponentBuilder instance to initialize the component
  32 + tcb
  33 + .createAsync(BlockContainerComponent).then(fixture => {
  34 + // and here we can inspect and run the test assertions
  35 + let myComponent: BlockContentComponent = fixture.componentInstance;
  36 +
  37 + // assure the block object inside the Block matches
  38 + // the provided through the parent component
  39 + expect(myComponent.block.type).toEqual("Block");
  40 + expect(myComponent.owner.name).toEqual("profile-name");
  41 + done();
  42 + });
  43 + });
  44 +
  45 +
  46 + it("renders a component which matches to the block type", done => {
  47 + // CustomBlock component created to check if it will be used
  48 + // when a block with type 'CustomBlock' is provided to the noosfero-block (Block)
  49 + // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider
  50 + @Component({ selector: 'noosfero-custom-block', template: "<h1>My Custom Block</h1>" })
  51 + class CustomBlock {
  52 + @Input() block: any;
  53 + @Input() owner: any;
  54 + }
  55 +
  56 + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockContentComponent, CustomBlock] })
  57 + class CustomBlockType {
  58 + block = { type: 'CustomBlock' };
  59 + owner = { name: 'profile-name' };
  60 + constructor() {
  61 + }
  62 + }
  63 + tcb
  64 + .createAsync(CustomBlockType).then(fixture => {
  65 + let myComponent: CustomBlockType = fixture.componentInstance;
  66 + expect(myComponent.block.type).toEqual("CustomBlock");
  67 + expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("My Custom Block");
  68 + done();
  69 + });
  70 + });
  71 +
  72 +
  73 + it("renders the default block when hasn't defined a block type", done => {
  74 + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockContentComponent] })
  75 + class CustomBlockType {
  76 + block: any = { type: null };
  77 + owner: any = { name: 'profile-name' };
  78 + constructor() {
  79 + }
  80 + }
  81 + tcb
  82 + .createAsync(CustomBlockType).then(fixture => {
  83 + let myComponent: CustomBlockType = fixture.componentInstance;
  84 + expect(myComponent.block.type).toBeNull();
  85 + expect(!!fixture.debugElement.nativeElement.querySelector("noosfero-default-block")).toBeTruthy();
  86 + done();
  87 + });
  88 + });
  89 +
  90 + });
  91 +});
src/app/layout/blocks/block-content.component.ts 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +import { Input, Inject, Component } from 'ng-forward';
  2 +
  3 +@Component({
  4 + selector: 'noosfero-block-content',
  5 + template: '<div></div>'
  6 +})
  7 +@Inject("$element", "$scope", "$injector", "$compile")
  8 +export class BlockContentComponent {
  9 +
  10 + @Input() block: any;
  11 + @Input() owner: any;
  12 +
  13 + ngOnInit() {
  14 + let blockName = (this.block && this.block.type) ? this.block.type.replace(/::/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : "default-block";
  15 + this.$element.replaceWith(this.$compile('<noosfero-' + blockName + ' [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-' + blockName + '>')(this.$scope));
  16 + }
  17 +
  18 + constructor(private $element: any, private $scope: ng.IScope, private $injector: ng.auto.IInjectorService, private $compile: ng.ICompileService) {
  19 + }
  20 +}
src/app/layout/blocks/block-edition/block-edition.component.spec.ts 0 → 100644
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
  1 +import {Component} from 'ng-forward';
  2 +import {BlockEditionComponent} from './block-edition.component';
  3 +import * as helpers from "../../../../spec/helpers";
  4 +import {ComponentTestHelper, createClass} from '../../../../spec/component-test-helper';
  5 +
  6 +const htmlTemplate: string = '<noosfero-block-edition></noosfero-block-edition>';
  7 +
  8 +describe("Boxes Component", () => {
  9 +
  10 + let helper: ComponentTestHelper<BlockEditionComponent>;
  11 + let translatorService = {
  12 + availableLanguages: { 'en': 'English', 'pt': 'Portuguese' }
  13 + };
  14 +
  15 + beforeEach(() => {
  16 + angular.mock.module("templates");
  17 + });
  18 +
  19 + beforeEach((done) => {
  20 + let cls = createClass({
  21 + template: htmlTemplate,
  22 + directives: [BlockEditionComponent],
  23 + providers: [
  24 + helpers.createProviderToValue('TranslatorService', translatorService)
  25 + ]
  26 + });
  27 + helper = new ComponentTestHelper<BlockEditionComponent>(cls, done);
  28 + });
  29 +
  30 + it("get available languages from translator service", () => {
  31 + expect(helper.component.languageOptions).toEqual(['all', 'en', 'pt']);
  32 + });
  33 +
  34 +});
src/app/layout/blocks/block-edition/block-edition.component.ts 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +import { Input, Inject, Component } from 'ng-forward';
  2 +import { TranslatorService } from "../../../shared/services/translator.service";
  3 +
  4 +@Component({
  5 + selector: 'noosfero-block-edition',
  6 + templateUrl: 'app/layout/blocks/block-edition/block-edition.html'
  7 +})
  8 +@Inject(TranslatorService)
  9 +export class BlockEditionComponent {
  10 +
  11 + static $inject = ["TranslatorService"]; // @Inject doesn't works with uibModal.open
  12 +
  13 + displayOptions: any;
  14 + displayUserOptions: any;
  15 + languageOptions: any;
  16 +
  17 + constructor(private translatorService: TranslatorService) {
  18 + this.displayOptions = ["always", "home_page_only", "except_home_page", "never"];
  19 + this.displayUserOptions = ["all", "logged", "not_logged"];
  20 + this.languageOptions = ["all"].concat(Object.keys(translatorService.availableLanguages));
  21 + }
  22 +}
src/app/layout/blocks/block-edition/block-edition.html 0 → 100644
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
  1 +<div class="edit-block">
  2 + <h3>{{"block.edition.title" | translate}}</h3>
  3 +
  4 + <form class="options">
  5 + <div class="title block-option">
  6 + <label for="titleInput">{{"block.edition.title.label" | translate}}</label>
  7 + <input type="text" id="titleInput" ng-model="ctrl.block.title" class="block-input">
  8 + </div>
  9 + <div class="display block-option">
  10 + <label for="displayInput">{{"block.edition.display.label" | translate}}</label>
  11 + <select id="displayInput" ng-model="ctrl.block.settings.display" class="block-input">
  12 + <option ng-repeat="option in modal.displayOptions" value="{{option}}">{{"block.edition.display." + option | translate}}</option>
  13 + </select>
  14 + </div>
  15 + <div class="displayUser block-option">
  16 + <label for="displayUserInput">{{"block.edition.display_user.label" | translate}}</label>
  17 + <select id="displayUserInput" ng-model="ctrl.block.settings.display_user" class="block-input">
  18 + <option ng-repeat="option in modal.displayUserOptions" value="{{option}}">{{"block.edition.display_user." + option | translate}}</option>
  19 + </select>
  20 + </div>
  21 + <div class="language block-option">
  22 + <label for="languageInput">{{"block.edition.language.label" | translate}}</label>
  23 + <select id="languageInput" ng-model="ctrl.block.settings.language" class="block-input">
  24 + <option ng-repeat="option in modal.languageOptions" value="{{option}}">{{"language." + option | translate}}</option>
  25 + </select>
  26 + </div>
  27 + </form>
  28 +
  29 + <div class="actions">
  30 + <button type="submit" class="btn btn-default" ng-click="ctrl.save()">Save</button>
  31 + <button type="submit" class="btn btn-warning" ng-click="ctrl.preview()">Preview</button>
  32 + <button type="submit" class="btn btn-danger" ng-click="ctrl.cancel()">Cancel</button>
  33 + </div>
  34 +</div>
src/app/layout/blocks/block-edition/block-edition.scss 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +.edit-block {
  2 + margin: 20px;
  3 +
  4 + .options {
  5 + margin-bottom: 20px;
  6 +
  7 + .block-option {
  8 + @extend .form-group;
  9 + .block-input {
  10 + @extend .form-control;
  11 + }
  12 + }
  13 + }
  14 +}
src/app/layout/blocks/block.component.spec.ts
1 -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';  
2 -import {Input, provide, Component} from 'ng-forward';  
3 - 1 +import {Component} from 'ng-forward';
4 import {BlockComponent} from './block.component'; 2 import {BlockComponent} from './block.component';
  3 +import * as helpers from "../../../spec/helpers";
  4 +import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper';
5 5
6 -const tcb = new TestComponentBuilder();  
7 -  
8 -const htmlTemplate: string = '<noosfero-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-block>';  
9 -  
10 -describe("Components", () => {  
11 - describe("Block Component", () => {  
12 -  
13 - // the karma preprocessor html2js transform the templates html into js files which put  
14 - // the templates to the templateCache into the module templates  
15 - // we need to load the module templates here as the template for the  
16 - // component Block will be load on our tests  
17 - beforeEach(angular.mock.module("templates"));  
18 -  
19 - it("receives the block and the owner as inputs", done => {  
20 -  
21 - // Creating a container component (BlockContainerComponent) to include  
22 - // the component under test (Block)  
23 - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockComponent] })  
24 - class BlockContainerComponent {  
25 - block = { type: 'Block' };  
26 - owner = { name: 'profile-name' };  
27 - constructor() {  
28 - }  
29 - }  
30 -  
31 - // uses the TestComponentBuilder instance to initialize the component  
32 - tcb  
33 - .createAsync(BlockContainerComponent).then(fixture => {  
34 - // and here we can inspect and run the test assertions  
35 - let myComponent: BlockComponent = fixture.componentInstance;  
36 -  
37 - // assure the block object inside the Block matches  
38 - // the provided through the parent component  
39 - expect(myComponent.block.type).toEqual("Block");  
40 - expect(myComponent.owner.name).toEqual("profile-name");  
41 - done();  
42 - });  
43 - }); 6 +const htmlTemplate: string = '<noosfero-block [block]="ctrl.block" [owner]="ctrl.profile"></noosfero-block>';
44 7
  8 +describe("Boxes Component", () => {
45 9
46 - it("renders a component which matches to the block type", done => {  
47 - // CustomBlock component created to check if it will be used  
48 - // when a block with type 'CustomBlock' is provided to the noosfero-block (Block)  
49 - // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider  
50 - @Component({ selector: 'noosfero-custom-block', template: "<h1>My Custom Block</h1>" })  
51 - class CustomBlock {  
52 - @Input() block: any;  
53 - @Input() owner: any;  
54 - }  
55 -  
56 - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockComponent, CustomBlock] })  
57 - class CustomBlockType {  
58 - block = { type: 'CustomBlock' };  
59 - owner = { name: 'profile-name' };  
60 - constructor() {  
61 - }  
62 - }  
63 - tcb  
64 - .createAsync(CustomBlockType).then(fixture => {  
65 - let myComponent: CustomBlockType = fixture.componentInstance;  
66 - expect(myComponent.block.type).toEqual("CustomBlock");  
67 - expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("My Custom Block");  
68 - done();  
69 - }); 10 + let helper: ComponentTestHelper<BlockComponent>;
  11 + beforeEach(() => {
  12 + angular.mock.module("templates");
  13 + });
  14 +
  15 + let properties = {
  16 + block: { id: 1 },
  17 + owner: {
  18 + id: 1,
  19 + identifier: 'profile-name',
  20 + type: 'Person'
  21 + }
  22 + };
  23 + beforeEach((done) => {
  24 + let cls = createClass({
  25 + template: htmlTemplate,
  26 + directives: [BlockComponent],
  27 + properties: properties,
  28 + providers: [
  29 + helpers.createProviderToValue('SessionService', helpers.mocks.sessionWithCurrentUser({})),
  30 + helpers.createProviderToValue('AuthService', helpers.mocks.authService),
  31 + helpers.createProviderToValue('$state', state),
  32 + helpers.createProviderToValue('TranslatorService', translatorService),
  33 + helpers.createProviderToValue('$uibModal', helpers.mocks.$modal),
  34 + helpers.createProviderToValue('BlockService', blockService),
  35 + helpers.createProviderToValue('NotificationService', helpers.mocks.notificationService)
  36 + ]
70 }); 37 });
  38 + helper = new ComponentTestHelper<BlockComponent>(cls, done);
  39 + });
71 40
  41 + let translatorService = jasmine.createSpyObj("translatorService", ["currentLanguage"]);
  42 + let blockService = jasmine.createSpyObj("blockService", ["update"]);
  43 + let state = jasmine.createSpyObj("state", ["current"]);
  44 + state.current = { name: "" };
72 45
73 - it("renders the default block when hasn't defined a block type", done => {  
74 - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [BlockComponent] })  
75 - class CustomBlockType {  
76 - block: any = { type: null };  
77 - owner: any = { name: 'profile-name' };  
78 - constructor() {  
79 - }  
80 - }  
81 - tcb  
82 - .createAsync(CustomBlockType).then(fixture => {  
83 - let myComponent: CustomBlockType = fixture.componentInstance;  
84 - expect(myComponent.block.type).toBeNull();  
85 - expect(!!fixture.debugElement.nativeElement.querySelector("noosfero-default-block")).toBeTruthy();  
86 - done();  
87 - });  
88 - }); 46 + it("set isHomepage as false by default", () => {
  47 + expect(helper.component.isHomepage).toBeFalsy();
  48 + });
  49 +
  50 + it("set isHomepage as true when in profile home page", () => {
  51 + state.current = { name: "main.profile.home" };
  52 + helper.component.ngOnInit();
  53 + expect(helper.component.isHomepage).toBeTruthy();
  54 + });
  55 +
  56 + it("set isHomepage as true when in profile info page", () => {
  57 + state.current = { name: "main.profile.info" };
  58 + helper.component.ngOnInit();
  59 + expect(helper.component.isHomepage).toBeTruthy();
  60 + });
  61 +
  62 + it("set isHomepage as true when in profile page", () => {
  63 + state.current = { name: "main.profile.page" };
  64 + state.params = { page: "/page" };
  65 + (<noosfero.Profile>helper.component.owner).homepage = '/page';
  66 + helper.component.ngOnInit();
  67 + expect(helper.component.isHomepage).toBeTruthy();
  68 + });
  69 +
  70 + it("set isHomepage as true when in environment home page", () => {
  71 + state.current = { name: "main.environment.home" };
  72 + helper.component.owner = <noosfero.Environment>{};
  73 + helper.component.ngOnInit();
  74 + expect(helper.component.isHomepage).toBeTruthy();
  75 + });
  76 +
  77 + it("return true in canDisplay when no display option is setted", () => {
  78 + helper.component.block = <any>{};
  79 + expect(helper.component.canDisplay()).toEqual(true);
  80 + });
  81 +
  82 + it("return false in canDisplay for an invisible block", () => {
  83 + helper.component.block = <any>{ settings: { display: "never" } };
  84 + expect(helper.component.canDisplay()).toEqual(false);
  85 + });
  86 +
  87 + it("return false in canDisplay with except_home_page in homepage", () => {
  88 + helper.component.block = <any>{ settings: { display_user: "except_home_page" } };
  89 + expect(helper.component.canDisplay()).toEqual(false);
  90 + });
  91 +
  92 + it("return false in canDisplay with home_page_only outside homepage", () => {
  93 + helper.component.block = <any>{ settings: { display_user: "home_page_only" } };
  94 + expect(helper.component.canDisplay()).toEqual(false);
  95 + });
  96 +
  97 + it("return true in canDisplay when display_user is all for logged user", () => {
  98 + helper.component.block = <any>{ settings: { display_user: "all" } };
  99 + expect(helper.component.canDisplay()).toEqual(true);
  100 + });
  101 +
  102 + it("return true in canDisplay when display_user is all for not logged user", () => {
  103 + helper.component.currentUser = null;
  104 + helper.component.block = <any>{ settings: { display_user: "all" } };
  105 + expect(helper.component.canDisplay()).toEqual(true);
  106 + });
89 107
  108 + it("return false in canDisplay when display_user is logged for not logged user", () => {
  109 + helper.component.currentUser = null;
  110 + helper.component.block = <any>{ settings: { display_user: "logged" } };
  111 + expect(helper.component.canDisplay()).toEqual(false);
90 }); 112 });
91 -});  
92 \ No newline at end of file 113 \ No newline at end of file
  114 +
  115 + it("return false in canDisplay when display_user is not_logged for logged user", () => {
  116 + helper.component.block = <any>{ settings: { display_user: "not_logged" } };
  117 + expect(helper.component.canDisplay()).toEqual(false);
  118 + });
  119 +
  120 + it("return false in canDisplay when current language is not equal to language in block settings", () => {
  121 + helper.component['translatorService'].currentLanguage = jasmine.createSpy("currentLanguage").and.returnValue("pt");
  122 + helper.component.block = <any>{ settings: { language: "en" } };
  123 + expect(helper.component.canDisplay()).toEqual(false);
  124 + });
  125 +
  126 + it("return false in canDisplay when hide is true", () => {
  127 + helper.component.block = <any>{ id: 1, hide: true };
  128 + expect(helper.component.canDisplay()).toEqual(false);
  129 + });
  130 +
  131 + it("return true in canDisplay when hide is not true", () => {
  132 + helper.component.block = <any>{ id: 1, hide: false };
  133 + expect(helper.component.canDisplay()).toEqual(true);
  134 + });
  135 +
  136 +});
src/app/layout/blocks/block.component.ts
1 -import { Input, Inject, Component } from 'ng-forward'; 1 +import { Input, Component, Inject } from 'ng-forward';
  2 +import { BlockEditionComponent } from './block-edition/block-edition.component';
  3 +import { BlockService } from '../../../lib/ng-noosfero-api/http/block.service';
  4 +import { NotificationService } from '../../shared/services/notification.service';
  5 +import { AuthService, SessionService, AuthEvents } from "../../login";
  6 +import { TranslatorService } from "../../shared/services/translator.service";
2 7
3 @Component({ 8 @Component({
4 selector: 'noosfero-block', 9 selector: 'noosfero-block',
5 - template: '<div></div>' 10 + templateUrl: 'app/layout/blocks/block.html',
  11 + directives: [BlockEditionComponent]
6 }) 12 })
7 -@Inject("$element", "$scope", "$injector", "$compile") 13 +@Inject("$uibModal", "$scope", "$state", "$rootScope", BlockService, NotificationService, AuthService, SessionService, TranslatorService)
8 export class BlockComponent { 14 export class BlockComponent {
9 15
10 - @Input() block: any;  
11 - @Input() owner: any; 16 + @Input() block: noosfero.Block;
  17 + @Input() owner: noosfero.Profile | noosfero.Environment;
  18 +
  19 + private modalInstance: any = null;
  20 + originalBlock: noosfero.Block;
  21 +
  22 + currentUser: noosfero.User;
  23 + isHomepage = true;
  24 + editionMode = false;
  25 +
  26 + constructor(private $uibModal: any,
  27 + private $scope: ng.IScope,
  28 + private $state: ng.ui.IStateService,
  29 + private $rootScope: ng.IRootScopeService,
  30 + private blockService: BlockService,
  31 + private notificationService: NotificationService,
  32 + private authService: AuthService,
  33 + private session: SessionService,
  34 + private translatorService: TranslatorService) {
  35 +
  36 + this.currentUser = this.session.currentUser();
  37 + this.authService.subscribe(AuthEvents[AuthEvents.loginSuccess], () => {
  38 + this.currentUser = this.session.currentUser();
  39 + this.verifyHomepage();
  40 + });
  41 + this.authService.subscribe(AuthEvents[AuthEvents.logoutSuccess], () => {
  42 + this.currentUser = this.session.currentUser();
  43 + this.verifyHomepage();
  44 + });
  45 + this.$rootScope.$on("$stateChangeSuccess", (event: ng.IAngularEvent, toState: ng.ui.IState) => {
  46 + this.verifyHomepage();
  47 + });
  48 + }
12 49
13 ngOnInit() { 50 ngOnInit() {
14 - let blockName = (this.block && this.block.type) ? this.block.type.replace(/::/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : "default-block";  
15 - this.$element.replaceWith(this.$compile('<noosfero-' + blockName + ' [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-' + blockName + '>')(this.$scope)); 51 + this.verifyHomepage();
  52 + }
  53 +
  54 + openEdit() {
  55 + this.editionMode = true;
  56 + if (!this.originalBlock) this.originalBlock = JSON.parse(JSON.stringify(this.block)); // deep copy of block data
  57 + this.modalInstance = this.$uibModal.open({
  58 + templateUrl: 'app/layout/blocks/block-edition/block-edition.html',
  59 + size: 'lg',
  60 + controller: BlockEditionComponent,
  61 + controllerAs: 'modal',
  62 + bindToController: true,
  63 + scope: this.$scope
  64 + });
  65 + }
  66 +
  67 + save() {
  68 + this.editionMode = false;
  69 + this.blockService.update(this.attributesToUpdate()).then(() => {
  70 + this.closeEdit();
  71 + this.notificationService.success({ title: "block.edition.success.title", message: "block.edition.success.message" });
  72 + });
  73 + }
  74 +
  75 + preview() {
  76 + this.closeEdit();
  77 + }
  78 +
  79 + cancel() {
  80 + this.editionMode = false;
  81 + this.block = this.originalBlock;
  82 + this.closeEdit();
16 } 83 }
17 84
18 - constructor(private $element: any, private $scope: ng.IScope, private $injector: ng.auto.IInjectorService, private $compile: ng.ICompileService) { 85 + canDisplay() {
  86 + return this.visible() && this.displayToUser() &&
  87 + this.displayOnLanguage(this.translatorService.currentLanguage()) &&
  88 + !this.block.hide;
19 } 89 }
  90 +
  91 + protected visible() {
  92 + let display = this.block.settings ? (<any>this.block.settings)['display'] : null;
  93 + return !display || ((this.isHomepage ? display !== "except_home_page" : display !== "home_page_only") && display !== "never");
  94 + }
  95 +
  96 + protected displayToUser() {
  97 + let displayUser = this.block.settings ? (<any>this.block.settings)['display_user'] : null;
  98 + return !displayUser || displayUser === "all" ||
  99 + (this.currentUser ? displayUser === "logged" : displayUser === "not_logged");
  100 + }
  101 +
  102 + protected displayOnLanguage(language: string) {
  103 + let displayLanguage = this.block.settings ? (<any>this.block.settings)['language'] : null;
  104 + return !displayLanguage || displayLanguage === "all" ||
  105 + language === displayLanguage;
  106 + }
  107 +
  108 + protected attributesToUpdate() {
  109 + return <any>{
  110 + id: this.block.id,
  111 + display: (<any>this.block.settings).display,
  112 + title: this.block.title,
  113 + display_user: (<any>this.block.settings).display_user,
  114 + language: (<any>this.block.settings).language
  115 + };
  116 + }
  117 +
  118 + protected verifyHomepage() {
  119 + if (this.owner && ["Profile", "Community", "Person"].indexOf((<any>this.owner)['type']) >= 0) {
  120 + let profile = <noosfero.Profile>this.owner;
  121 + this.isHomepage = this.$state.current.name === "main.profile.home";
  122 + if (profile.homepage) {
  123 + this.isHomepage = this.isHomepage ||
  124 + (this.$state.current.name === "main.profile.page" && profile.homepage === this.$state.params['page']);
  125 + } else {
  126 + this.isHomepage = this.isHomepage || this.$state.current.name === "main.profile.info";
  127 + }
  128 + } else {
  129 + this.isHomepage = this.$state.current.name === "main.environment.home";
  130 + }
  131 + }
  132 +
  133 + private closeEdit() {
  134 + if (this.modalInstance) {
  135 + this.modalInstance.close();
  136 + this.modalInstance = null;
  137 + }
  138 + }
  139 +
20 } 140 }
src/app/layout/blocks/block.html 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div ng-show="ctrl.canDisplay() || ctrl.editionMode" ng-class="{'invisible-block': !ctrl.canDisplay()}" class="noosfero-block" ng-mouseover="displayActions = true" ng-mouseleave="displayActions = false">
  2 + <div ng-show="displayActions" class="actions" permission="ctrl.block.permissions" permission-action="allow_edit">
  3 + <button type="submit" class="btn btn-xs btn-default" ng-click="ctrl.openEdit()"><i class="fa fa-edit fa-fw"></i></button>
  4 + </div>
  5 + <div class="panel panel-default block {{ctrl.block.type | lowercase}}" >
  6 + <div class="panel-heading" ng-show="ctrl.block.title">
  7 + <h3 class="panel-title">{{ctrl.block.title}}</h3>
  8 + </div>
  9 + <div class="panel-body {{ctrl.block.type | lowercase}}" >
  10 + <noosfero-block-content [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-block-content>
  11 + </div>
  12 + </div>
  13 +</div>
src/app/layout/blocks/block.scss
1 -.block {  
2 - .panel-title {  
3 - font-size: 15px;  
4 - font-weight: bold; 1 +.noosfero-block {
  2 + position: relative;
  3 + &.invisible-block {
  4 + .block {
  5 + opacity: 0.4;
  6 + }
5 } 7 }
6 - .panel-heading {  
7 - background-color: transparent;  
8 - border: 0; 8 + .block {
  9 + .panel-title {
  10 + font-size: 15px;
  11 + font-weight: bold;
  12 + }
  13 + .panel-heading {
  14 + background-color: transparent;
  15 + border: 0;
  16 + }
  17 + }
  18 + .actions {
  19 + position: absolute;
  20 + z-index: 100;
  21 + right: 1px;
  22 + top: 1px;
9 } 23 }
10 } 24 }
src/app/layout/blocks/index.ts
1 /* Module Index Entry - generated using the script npm run generate-index */ 1 /* Module Index Entry - generated using the script npm run generate-index */
2 -export * from "./block.component"; 2 +export * from "./block-content.component";
src/app/layout/blocks/main/main-block.component.ts
1 import {Component, Input} from 'ng-forward'; 1 import {Component, Input} from 'ng-forward';
2 -import {BlockComponent} from '../block.component';  
3 2
4 @Component({ 3 @Component({
5 selector: 'noosfero-main-block', 4 selector: 'noosfero-main-block',
src/app/layout/boxes/box.html
1 <div ng-class="{'col-md-2-5': box.position!=1, 'col-md-7': box.position==1}"> 1 <div ng-class="{'col-md-2-5': box.position!=1, 'col-md-7': box.position==1}">
2 - <div ng-repeat="block in box.blocks | displayBlocks:ctrl.isHomepage:ctrl.currentUser | orderBy: 'position'" class="panel panel-default block {{block.type | lowercase}}" >  
3 - <div class="panel-heading" ng-show="block.title">  
4 - <h3 class="panel-title">{{block.title}}</h3>  
5 - </div>  
6 - <div class="panel-body {{block.type | lowercase}}" >  
7 - <noosfero-block [block]="block" [owner]="ctrl.owner"></noosfero-block>  
8 - </div>  
9 - </div> 2 + <noosfero-block ng-repeat="block in box.blocks | orderBy: 'position'" [block]="block" [owner]="ctrl.owner"></noosfero-block>
10 </div> 3 </div>
src/app/layout/boxes/boxes.component.spec.ts
@@ -53,35 +53,4 @@ describe(&quot;Boxes Component&quot;, () =&gt; { @@ -53,35 +53,4 @@ describe(&quot;Boxes Component&quot;, () =&gt; {
53 expect(helper.component.boxesOrder(properties['boxes'][0])).toEqual(1); 53 expect(helper.component.boxesOrder(properties['boxes'][0])).toEqual(1);
54 expect(helper.component.boxesOrder(properties['boxes'][1])).toEqual(0); 54 expect(helper.component.boxesOrder(properties['boxes'][1])).toEqual(0);
55 }); 55 });
56 -  
57 - it("set isHomepage as false by default", () => {  
58 - expect(helper.component.isHomepage).toBeFalsy();  
59 - });  
60 -  
61 - it("set isHomepage as true when in profile home page", () => {  
62 - state.current = { name: "main.profile.home" };  
63 - helper.component.ngOnInit();  
64 - expect(helper.component.isHomepage).toBeTruthy();  
65 - });  
66 -  
67 - it("set isHomepage as true when in profile info page", () => {  
68 - state.current = { name: "main.profile.info" };  
69 - helper.component.ngOnInit();  
70 - expect(helper.component.isHomepage).toBeTruthy();  
71 - });  
72 -  
73 - it("set isHomepage as true when in profile page", () => {  
74 - state.current = { name: "main.profile.page" };  
75 - state.params = { page: "/page" };  
76 - (<noosfero.Profile>helper.component.owner).homepage = '/page';  
77 - helper.component.ngOnInit();  
78 - expect(helper.component.isHomepage).toBeTruthy();  
79 - });  
80 -  
81 - it("set isHomepage as true when in environment home page", () => {  
82 - state.current = { name: "main.environment.home" };  
83 - helper.component.owner = <noosfero.Environment>{};  
84 - helper.component.ngOnInit();  
85 - expect(helper.component.isHomepage).toBeTruthy();  
86 - });  
87 }); 56 });
src/app/layout/boxes/boxes.component.ts
1 -import {Input, Inject, Component} from 'ng-forward';  
2 -import {SessionService, AuthService, AuthEvents} from "../../login";  
3 -import {DisplayBlocks} from "./display-blocks.filter"; 1 +import {Input, Component} from 'ng-forward';
4 2
5 @Component({ 3 @Component({
6 selector: "noosfero-boxes", 4 selector: "noosfero-boxes",
7 - templateUrl: "app/layout/boxes/boxes.html",  
8 - directives: [DisplayBlocks] 5 + templateUrl: "app/layout/boxes/boxes.html"
9 }) 6 })
10 -@Inject("SessionService", 'AuthService', "$state", "$rootScope")  
11 export class BoxesComponent { 7 export class BoxesComponent {
12 8
13 @Input() boxes: noosfero.Box[]; 9 @Input() boxes: noosfero.Box[];
14 @Input() owner: noosfero.Profile | noosfero.Environment; 10 @Input() owner: noosfero.Profile | noosfero.Environment;
15 11
16 - currentUser: noosfero.User;  
17 - isHomepage = true;  
18 -  
19 - constructor(private session: SessionService,  
20 - private authService: AuthService,  
21 - private $state: ng.ui.IStateService,  
22 - private $rootScope: ng.IRootScopeService) {  
23 -  
24 - this.currentUser = this.session.currentUser();  
25 - this.authService.subscribe(AuthEvents[AuthEvents.loginSuccess], () => {  
26 - this.currentUser = this.session.currentUser();  
27 - this.verifyHomepage();  
28 - });  
29 - this.authService.subscribe(AuthEvents[AuthEvents.logoutSuccess], () => {  
30 - this.currentUser = this.session.currentUser();  
31 - this.verifyHomepage();  
32 - });  
33 - this.$rootScope.$on("$stateChangeSuccess", (event: ng.IAngularEvent, toState: ng.ui.IState) => {  
34 - this.verifyHomepage();  
35 - });  
36 - }  
37 -  
38 - ngOnInit() {  
39 - this.verifyHomepage();  
40 - }  
41 -  
42 boxesOrder(box: noosfero.Box) { 12 boxesOrder(box: noosfero.Box) {
43 if (box.position === 2) return 0; 13 if (box.position === 2) return 0;
44 return box.position; 14 return box.position;
45 } 15 }
46 -  
47 - private verifyHomepage() {  
48 - if (this.owner && ["Profile", "Community", "Person"].indexOf((<any>this.owner)['type']) >= 0) {  
49 - let profile = <noosfero.Profile>this.owner;  
50 - this.isHomepage = this.$state.current.name === "main.profile.home";  
51 - if (profile.homepage) {  
52 - this.isHomepage = this.isHomepage ||  
53 - (this.$state.current.name === "main.profile.page" && profile.homepage === this.$state.params['page']);  
54 - } else {  
55 - this.isHomepage = this.isHomepage || this.$state.current.name === "main.profile.info";  
56 - }  
57 - } else {  
58 - this.isHomepage = this.$state.current.name === "main.environment.home";  
59 - }  
60 - }  
61 } 16 }
src/app/layout/boxes/display-blocks.filter.spec.ts
@@ -1,100 +0,0 @@ @@ -1,100 +0,0 @@
1 -import {quickCreateComponent} from "../../../spec/helpers";  
2 -import {DisplayBlocks} from './display-blocks.filter';  
3 -  
4 -describe("Filters", () => {  
5 - describe("Display Blocks Filter", () => {  
6 -  
7 - let translatorService = jasmine.createSpyObj("translatorService", ["currentLanguage"]);  
8 -  
9 - it("not fail when blocks is null", done => {  
10 - let filter = new DisplayBlocks(translatorService);  
11 - expect(filter.transform(null, true, <noosfero.User>{})).toEqual([]);  
12 - done();  
13 - });  
14 -  
15 - it("return blocks when no setting is passed", done => {  
16 - let blocks = [{}];  
17 - let filter = new DisplayBlocks(translatorService);  
18 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual(blocks);  
19 - done();  
20 - });  
21 -  
22 - it("return blocks when no display is passed", done => {  
23 - let blocks = [{ setting: {} }];  
24 - let filter = new DisplayBlocks(translatorService);  
25 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual(blocks);  
26 - done();  
27 - });  
28 -  
29 - it("filter invisible blocks", done => {  
30 - let blocks = [{ settings: { display: "never" } }];  
31 - let filter = new DisplayBlocks(translatorService);  
32 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual([]);  
33 - done();  
34 - });  
35 -  
36 - it("filter blocks with except_home_page in homepage", done => {  
37 - let blocks = [{ settings: { display: "except_home_page" } }];  
38 - let filter = new DisplayBlocks(translatorService);  
39 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual([]);  
40 - done();  
41 - });  
42 -  
43 - it("filter blocks with home_page_only outside homepage", done => {  
44 - let blocks = [{ settings: { display: "home_page_only" } }];  
45 - let filter = new DisplayBlocks(translatorService);  
46 - expect(filter.transform(<any>blocks, false, <noosfero.User>{})).toEqual([]);  
47 - done();  
48 - });  
49 -  
50 - it("show all blocks when display_user is all for logged user", done => {  
51 - let blocks = [{ settings: { display_user: "all" } }];  
52 - let filter = new DisplayBlocks(translatorService);  
53 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual(blocks);  
54 - done();  
55 - });  
56 -  
57 - it("show all blocks when display_user is all for not logged user", done => {  
58 - let blocks = [{ settings: { display_user: "all" } }];  
59 - let filter = new DisplayBlocks(translatorService);  
60 - expect(filter.transform(<any>blocks, true, null)).toEqual(blocks);  
61 - done();  
62 - });  
63 -  
64 - it("filter blocks when display_user is logged for not logged user", done => {  
65 - let blocks = [{ settings: { display_user: "logged" } }];  
66 - let filter = new DisplayBlocks(translatorService);  
67 - expect(filter.transform(<any>blocks, true, null)).toEqual([]);  
68 - done();  
69 - });  
70 -  
71 - it("filter blocks when display_user is not_logged for logged user", done => {  
72 - let blocks = [{ settings: { display_user: "not_logged" } }];  
73 - let filter = new DisplayBlocks(translatorService);  
74 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual([]);  
75 - done();  
76 - });  
77 -  
78 - it("filter blocks with different language", done => {  
79 - let blocks = [{ settings: { language: "en" } }];  
80 - translatorService.currentLanguage = jasmine.createSpy("currentLanguage").and.returnValue("pt");  
81 - let filter = new DisplayBlocks(translatorService);  
82 - expect(filter.transform(<any>blocks, true, <noosfero.User>{})).toEqual([]);  
83 - done();  
84 - });  
85 -  
86 - it("filter blocks when hide is true", done => {  
87 - let blocks = [{ hide: true }];  
88 - let filter = new DisplayBlocks(translatorService);  
89 - expect(filter.transform(<any>blocks, true, null)).toEqual([]);  
90 - done();  
91 - });  
92 -  
93 - it("not filter blocks when hide is not true", done => {  
94 - let blocks = [{ id: 1, hide: false }, { id: 2 }];  
95 - let filter = new DisplayBlocks(translatorService);  
96 - expect(filter.transform(<any>blocks, true, null)).toEqual(blocks);  
97 - done();  
98 - });  
99 - });  
100 -});  
src/app/layout/boxes/display-blocks.filter.ts
@@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
1 -import {Pipe, Inject} from "ng-forward";  
2 -import {TranslatorService} from "../../shared/services/translator.service";  
3 -  
4 -@Pipe("displayBlocks")  
5 -@Inject(TranslatorService)  
6 -export class DisplayBlocks {  
7 -  
8 - constructor(private translatorService: TranslatorService) { }  
9 -  
10 - transform(blocks: noosfero.Block[], isHomepage: boolean, currentUser: noosfero.User) {  
11 - let selected: noosfero.Block[] = [];  
12 - blocks = blocks || [];  
13 - for (let block of blocks) {  
14 - if (this.visible(block, isHomepage) && this.displayToUser(block, currentUser) &&  
15 - this.displayOnLanguage(block, this.translatorService.currentLanguage())  
16 - && !block.hide) {  
17 - selected.push(block);  
18 - }  
19 - }  
20 - return selected;  
21 - }  
22 -  
23 - private visible(block: noosfero.Block, isHomepage: boolean) {  
24 - let display = block.settings ? (<any>block.settings)['display'] : null;  
25 - return !display || ((isHomepage ? display !== "except_home_page" : display !== "home_page_only") && display !== "never");  
26 - }  
27 -  
28 - private displayToUser(block: noosfero.Block, currentUser: noosfero.User) {  
29 - let displayUser = block.settings ? (<any>block.settings)['display_user'] : null;  
30 - return !displayUser || displayUser === "all" ||  
31 - (currentUser ? displayUser === "logged" : displayUser === "not_logged");  
32 - }  
33 -  
34 - private displayOnLanguage(block: noosfero.Block, language: string) {  
35 - let displayLanguage = block.settings ? (<any>block.settings)['language'] : null;  
36 - return !displayLanguage || displayLanguage === "all" ||  
37 - language === displayLanguage;  
38 - }  
39 -}  
src/app/main/main.component.ts
@@ -6,6 +6,7 @@ import {ArticleViewComponent} from &quot;./../article/article-default-view.component&quot; @@ -6,6 +6,7 @@ import {ArticleViewComponent} from &quot;./../article/article-default-view.component&quot;
6 6
7 import {ProfileComponent} from "../profile/profile.component"; 7 import {ProfileComponent} from "../profile/profile.component";
8 import {BoxesComponent} from "../layout/boxes/boxes.component"; 8 import {BoxesComponent} from "../layout/boxes/boxes.component";
  9 +import {BlockContentComponent} from "../layout/blocks/block-content.component";
9 import {BlockComponent} from "../layout/blocks/block.component"; 10 import {BlockComponent} from "../layout/blocks/block.component";
10 import {EnvironmentComponent} from "../environment/environment.component"; 11 import {EnvironmentComponent} from "../environment/environment.component";
11 import {EnvironmentHomeComponent} from "../environment/environment-home.component"; 12 import {EnvironmentHomeComponent} from "../environment/environment-home.component";
@@ -97,12 +98,13 @@ export class EnvironmentContent { @@ -97,12 +98,13 @@ export class EnvironmentContent {
97 selector: 'main', 98 selector: 'main',
98 template: '<ui-view></ui-view>', 99 template: '<ui-view></ui-view>',
99 directives: [ 100 directives: [
100 - ArticleBlogComponent, ArticleViewComponent, BoxesComponent, BlockComponent, 101 + ArticleBlogComponent, ArticleViewComponent, BoxesComponent, BlockContentComponent,
101 EnvironmentComponent, PeopleBlockComponent, DisplayContentBlockComponent, 102 EnvironmentComponent, PeopleBlockComponent, DisplayContentBlockComponent,
102 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, ProfileComponent, 103 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, ProfileComponent,
103 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent, 104 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
104 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent, 105 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
105 - LoginBlockComponent, CustomContentComponent, PermissionDirective, SearchFormComponent, SearchComponent 106 + LoginBlockComponent, CustomContentComponent, PermissionDirective, SearchFormComponent, SearchComponent,
  107 + BlockComponent
106 ].concat(plugins.mainComponents).concat(plugins.hotspots), 108 ].concat(plugins.mainComponents).concat(plugins.hotspots),
107 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService, 109 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService,
108 "ngAnimate", "ngCookies", "ngStorage", "ngTouch", 110 "ngAnimate", "ngCookies", "ngStorage", "ngTouch",
src/languages/en.json
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 "navbar.logout": "Log Out", 6 "navbar.logout": "Log Out",
7 "navbar.login": "Login", 7 "navbar.login": "Login",
8 "navbar.toggle_menu": "Toggle navigation", 8 "navbar.toggle_menu": "Toggle navigation",
  9 + "language.all": "All languages",
9 "language.en": "English", 10 "language.en": "English",
10 "language.pt": "Portuguese", 11 "language.pt": "Portuguese",
11 "language.selector": "Language", 12 "language.selector": "Language",
@@ -80,5 +81,20 @@ @@ -80,5 +81,20 @@
80 "designMode.toggle.OFF": "OFF", 81 "designMode.toggle.OFF": "OFF",
81 "search.results.summary": "{results, plural, one{result} other{# results}}", 82 "search.results.summary": "{results, plural, one{result} other{# results}}",
82 "search.results.query.label": "Search for:", 83 "search.results.query.label": "Search for:",
83 - "search.results.query.placeholder": "Search" 84 + "search.results.query.placeholder": "Search",
  85 + "block.edit": "Edit",
  86 + "block.edition.title": "Edit Block",
  87 + "block.edition.success.title": "Good job!",
  88 + "block.edition.success.message": "Block saved!",
  89 + "block.edition.display.label": "Display this block:",
  90 + "block.edition.title.label": "Custom title for this block:",
  91 + "block.edition.display.always": "In all pages",
  92 + "block.edition.display.home_page_only": "Only in the homepage",
  93 + "block.edition.display.except_home_page": "In all pages, except in the homepage",
  94 + "block.edition.display.never": "Don't display",
  95 + "block.edition.display_user.label": "Display to users:",
  96 + "block.edition.display_user.all": "All users",
  97 + "block.edition.display_user.logged": "Logged",
  98 + "block.edition.display_user.not_logged": "Not logged",
  99 + "block.edition.language.label": "Show for:"
84 } 100 }
src/languages/pt.json
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 "navbar.logout": "Sair", 6 "navbar.logout": "Sair",
7 "navbar.login": "Login", 7 "navbar.login": "Login",
8 "navbar.toggle_menu": "Abrir Menu", 8 "navbar.toggle_menu": "Abrir Menu",
  9 + "language.all": "Todos os idiomas",
9 "language.en": "Inglês", 10 "language.en": "Inglês",
10 "language.pt": "Português", 11 "language.pt": "Português",
11 "language.selector": "Idioma", 12 "language.selector": "Idioma",
@@ -80,5 +81,20 @@ @@ -80,5 +81,20 @@
80 "designMode.toggle.OFF": "Desligado", 81 "designMode.toggle.OFF": "Desligado",
81 "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}", 82 "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}",
82 "search.results.query.label": "Buscar:", 83 "search.results.query.label": "Buscar:",
83 - "search.results.query.placeholder": "Informe aqui sua busca" 84 + "search.results.query.placeholder": "Informe aqui sua busca",
  85 + "block.edit": "Editar",
  86 + "block.edition.title": "Editar Bloco",
  87 + "block.edition.success.title": "Bom trabalho!",
  88 + "block.edition.success.message": "Bloco salvo com sucesso!",
  89 + "block.edition.display.label": "Exibir este bloco:",
  90 + "block.edition.title.label": "Título personalizado do bloco:",
  91 + "block.edition.display.always": "Em todas as páginas",
  92 + "block.edition.display.home_page_only": "Apenas na página inicial",
  93 + "block.edition.display.except_home_page": "Em todas as páginas, exceto na inicial",
  94 + "block.edition.display.never": "Não exibir",
  95 + "block.edition.display_user.label": "Exibir para usuários:",
  96 + "block.edition.display_user.all": "Todos os usuários",
  97 + "block.edition.display_user.logged": "Logados",
  98 + "block.edition.display_user.not_logged": "Não logados",
  99 + "block.edition.language.label": "Exibir para:"
84 } 100 }
src/lib/ng-noosfero-api/http/block.service.spec.ts
@@ -29,6 +29,16 @@ describe(&quot;Services&quot;, () =&gt; { @@ -29,6 +29,16 @@ describe(&quot;Services&quot;, () =&gt; {
29 }); 29 });
30 $httpBackend.flush(); 30 $httpBackend.flush();
31 }); 31 });
  32 +
  33 + it("update block settings", (done) => {
  34 + let blockId = 1;
  35 + $httpBackend.expectPOST(`/api/v1/blocks/${blockId}`).respond(200, { block: { id: blockId } });
  36 + blockService.update(<any>{ id: blockId, display: 'never' }).then((result: noosfero.RestResult<noosfero.Block>) => {
  37 + expect(result.data).toEqual({ id: blockId });
  38 + done();
  39 + });
  40 + $httpBackend.flush();
  41 + });
32 }); 42 });
33 43
34 44
src/lib/ng-noosfero-api/http/block.service.ts
@@ -47,4 +47,12 @@ export class BlockService extends RestangularService&lt;noosfero.Block&gt; { @@ -47,4 +47,12 @@ export class BlockService extends RestangularService&lt;noosfero.Block&gt; {
47 return deferred.promise; 47 return deferred.promise;
48 } 48 }
49 49
  50 + update(block: noosfero.Block) {
  51 + let element = this.getElement(block.id);
  52 + let headers = {
  53 + 'Content-Type': 'application/json'
  54 + };
  55 + return this.post(null, element, { block: block }, headers);
  56 + }
  57 +
50 } 58 }
src/lib/ng-noosfero-api/http/restangular_service.ts
@@ -289,7 +289,7 @@ export abstract class RestangularService&lt;T extends noosfero.RestModel&gt; { @@ -289,7 +289,7 @@ export abstract class RestangularService&lt;T extends noosfero.RestModel&gt; {
289 let restRequest: ng.IPromise<any>; 289 let restRequest: ng.IPromise<any>;
290 290
291 if (rootElement) { 291 if (rootElement) {
292 - restRequest = rootElement.customPOST(data, path, headers); 292 + restRequest = rootElement.customPOST(data, path, null, headers);
293 } else { 293 } else {
294 restRequest = this.baseResource.customPOST(data, path, headers); 294 restRequest = this.baseResource.customPOST(data, path, headers);
295 } 295 }
src/lib/ng-noosfero-api/interfaces/block.ts
@@ -5,5 +5,6 @@ namespace noosfero { @@ -5,5 +5,6 @@ namespace noosfero {
5 limit: number; 5 limit: number;
6 api_content: any; 6 api_content: any;
7 hide: boolean; 7 hide: boolean;
  8 + title: string;
8 } 9 }
9 } 10 }