Commit 167edf002e12ba607a4a935a7a6d0a4a5eeb1fba

Authored by Victor Costa
1 parent 3963f52f

Add components to edit block settings

src/app/layout/blocks/block-edition/block-edition.component.ts 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +import { Input, Component } from 'ng-forward';
  2 +
  3 +@Component({
  4 + selector: 'noosfero-block-edition',
  5 + templateUrl: 'app/layout/blocks/block-edition/block-edition.html'
  6 +})
  7 +export class BlockEditionComponent {
  8 +
  9 + displayOptions: any;
  10 + displayUserOptions: any;
  11 + languageOptions: any;
  12 +
  13 + constructor() {
  14 + this.displayOptions = ["always", "home_page_only", "except_home_page", "never"];
  15 + this.displayUserOptions = ["all", "logged", "not_logged"];
  16 + this.languageOptions = ["all", "en", "pt"]; // FIXME get language list
  17 + }
  18 +}
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.ts 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  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 +
  6 +@Component({
  7 + selector: 'noosfero-block',
  8 + templateUrl: 'app/layout/blocks/block.html',
  9 + directives: [BlockEditionComponent]
  10 +})
  11 +@Inject("$uibModal", "$scope", BlockService, NotificationService)
  12 +export class BlockComponent {
  13 +
  14 + @Input() block: any;
  15 + @Input() owner: any;
  16 +
  17 + private modalInstance: any = null;
  18 + originalBlock: noosfero.Block;
  19 +
  20 + constructor(private $uibModal: any, private $scope: ng.IScope, private blockService: BlockService, private notificationService: NotificationService) { }
  21 +
  22 + openEdit() {
  23 + if (!this.originalBlock) this.originalBlock = JSON.parse(JSON.stringify(this.block)); // deep copy of block data
  24 + this.modalInstance = this.$uibModal.open({
  25 + templateUrl: 'app/layout/blocks/block-edition/block-edition.html',
  26 + size: 'lg',
  27 + controller: BlockEditionComponent,
  28 + controllerAs: 'modal',
  29 + bindToController: true,
  30 + scope: this.$scope
  31 + });
  32 + }
  33 +
  34 + save() {
  35 + this.blockService.update(this.attributesToUpdate(this.block)).then(() => {
  36 + this.closeEdit();
  37 + this.notificationService.success({ title: "block.edition.success.title", message: "block.edition.success.message" });
  38 + });
  39 + }
  40 +
  41 + preview() {
  42 + this.closeEdit();
  43 + }
  44 +
  45 + cancel() {
  46 + this.block = this.originalBlock;
  47 + this.closeEdit();
  48 + }
  49 +
  50 + protected attributesToUpdate(block: noosfero.Block) {
  51 + return <any>{
  52 + id: this.block.id,
  53 + display: this.block.settings.display,
  54 + title: this.block.title,
  55 + display_user: this.block.settings.display_user,
  56 + language: this.block.settings.language
  57 + };
  58 + }
  59 +
  60 + private closeEdit() {
  61 + if (this.modalInstance) {
  62 + this.modalInstance.close();
  63 + this.modalInstance = null;
  64 + }
  65 + }
  66 +
  67 +}
src/app/layout/blocks/block.html 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div 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 + &.invisible-block {
  3 + .block {
  4 + opacity: 0.4;
  5 + }
5 } 6 }
6 - .panel-heading {  
7 - background-color: transparent;  
8 - border: 0; 7 + .block {
  8 + .panel-title {
  9 + font-size: 15px;
  10 + font-weight: bold;
  11 + }
  12 + .panel-heading {
  13 + background-color: transparent;
  14 + border: 0;
  15 + }
  16 + }
  17 + .actions {
  18 + position: absolute;
  19 + z-index: 100;
  20 + right: 16px;
  21 + top: 1px;
9 } 22 }
10 } 23 }
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-content [block]="block" [owner]="ctrl.owner"></noosfero-block-content>  
8 - </div>  
9 - </div> 2 + <noosfero-block ng-repeat="block in box.blocks | displayBlocks:ctrl.isHomepage:ctrl.currentUser | orderBy: 'position'" [block]="block" [owner]="ctrl.owner"></noosfero-block>
10 </div> 3 </div>
src/app/main/main.component.ts
@@ -7,6 +7,7 @@ import {ArticleViewComponent} from &quot;./../article/article-default-view.component&quot; @@ -7,6 +7,7 @@ import {ArticleViewComponent} from &quot;./../article/article-default-view.component&quot;
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 {BlockContentComponent} from "../layout/blocks/block-content.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";
12 import {PeopleBlockComponent} from "../layout/blocks/people/people-block.component"; 13 import {PeopleBlockComponent} from "../layout/blocks/people/people-block.component";
@@ -100,7 +101,7 @@ export class EnvironmentContent { @@ -100,7 +101,7 @@ export class EnvironmentContent {
100 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, ProfileComponent, 101 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, ProfileComponent,
101 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent, 102 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
102 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent, 103 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
103 - LoginBlockComponent, CustomContentComponent, PermissionDirective 104 + LoginBlockComponent, CustomContentComponent, PermissionDirective, BlockComponent
104 ].concat(plugins.mainComponents).concat(plugins.hotspots), 105 ].concat(plugins.mainComponents).concat(plugins.hotspots),
105 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService, 106 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService,
106 "ngAnimate", "ngCookies", "ngStorage", "ngTouch", 107 "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",
@@ -74,5 +75,20 @@ @@ -74,5 +75,20 @@
74 "profile.content.success.message": "Profile saved!", 75 "profile.content.success.message": "Profile saved!",
75 "custom_content.title": "Edit content", 76 "custom_content.title": "Edit content",
76 "profile.custom_header.label": "Header", 77 "profile.custom_header.label": "Header",
77 - "profile.custom_footer.label": "Footer" 78 + "profile.custom_footer.label": "Footer",
  79 + "block.edit": "Edit",
  80 + "block.edition.title": "Edit Block",
  81 + "block.edition.success.title": "Good job!",
  82 + "block.edition.success.message": "Block saved!",
  83 + "block.edition.display.label": "Display this block:",
  84 + "block.edition.title.label": "Custom title for this block:",
  85 + "block.edition.display.always": "In all pages",
  86 + "block.edition.display.home_page_only": "Only in the homepage",
  87 + "block.edition.display.except_home_page": "In all pages, except in the homepage",
  88 + "block.edition.display.never": "Don't display",
  89 + "block.edition.display_user.label": "Display to users:",
  90 + "block.edition.display_user.all": "All users",
  91 + "block.edition.display_user.logged": "Logged",
  92 + "block.edition.display_user.not_logged": "Not logged",
  93 + "block.edition.language.label": "Show for:"
78 } 94 }
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",
@@ -74,5 +75,20 @@ @@ -74,5 +75,20 @@
74 "profile.content.success.message": "Perfil salvo!", 75 "profile.content.success.message": "Perfil salvo!",
75 "custom_content.title": "Editar conteúdo", 76 "custom_content.title": "Editar conteúdo",
76 "profile.custom_header.label": "Cabeçalho", 77 "profile.custom_header.label": "Cabeçalho",
77 - "profile.custom_footer.label": "Rodapé" 78 + "profile.custom_footer.label": "Rodapé",
  79 + "block.edit": "Editar",
  80 + "block.edition.title": "Editar Bloco",
  81 + "block.edition.success.title": "Bom trabalho!",
  82 + "block.edition.success.message": "Bloco salvo com sucesso!",
  83 + "block.edition.display.label": "Exibir este bloco:",
  84 + "block.edition.title.label": "Título personalizado do bloco:",
  85 + "block.edition.display.always": "Em todas as páginas",
  86 + "block.edition.display.home_page_only": "Apenas na página inicial",
  87 + "block.edition.display.except_home_page": "Em todas as páginas, exceto na inicial",
  88 + "block.edition.display.never": "Não exibir",
  89 + "block.edition.display_user.label": "Exibir para usuários:",
  90 + "block.edition.display_user.all": "Todos os usuários",
  91 + "block.edition.display_user.logged": "Logados",
  92 + "block.edition.display_user.not_logged": "Não logados",
  93 + "block.edition.language.label": "Exibir para:"
78 } 94 }
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 }