Commit 451be0ef9e2d26647c0b5c8af6a3b2cf0771ae52

Authored by Carlos Purificação
Committed by Michel Felipe
1 parent 29d769ad

Display content block initial version

src/app/layout/blocks/display-content/display-content-block.component.spec.ts 0 → 100644
... ... @@ -0,0 +1,75 @@
  1 +import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Provider, provide} from 'ng-forward';
  3 +import {ComponentTestHelper, createClass} from './../../../../spec/component-test-helper';
  4 +import {providers} from 'ng-forward/cjs/testing/providers';
  5 +import {DisplayContentBlockComponent} from './display-content-block.component';
  6 +import * as helpers from './../../../../spec/helpers';
  7 +
  8 +const htmlTemplate: string = '<noosfero-display-content-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-display-content-block>';
  9 +
  10 +describe("Components", () => {
  11 +
  12 + describe("Display Content Block Component", () => {
  13 + let state = jasmine.createSpyObj("state", ["go"]);
  14 + let providers = [
  15 + provide('ArticleService', {
  16 + useValue: helpers.mocks.articleService
  17 + }),
  18 + provide('$state', { useValue: state })
  19 + ].concat(helpers.provideFilters("translateFilter"));
  20 +
  21 + let sections: noosfero.Section[] = [
  22 + { value: 'abstract', checked: 'abstract'},
  23 + { value: 'title', checked: 'title' }
  24 + ];
  25 + let settings: noosfero.Settings = {
  26 + limit: 6,
  27 + sections: sections
  28 + };
  29 +
  30 + let helper: ComponentTestHelper<DisplayContentBlockComponent>;
  31 +
  32 + beforeEach(angular.mock.module("templates"));
  33 +
  34 + /**
  35 + * The beforeEach procedure will initialize the helper and parse
  36 + * the component according to the given providers. Unfortunetly, in
  37 + * this mode, the providers and properties given to the construtor
  38 + * can't be overriden.
  39 + */
  40 + beforeEach((done) => {
  41 + // Create the component bed for the test. Optionally, this could be done
  42 + // in each test if one needs customization of these parameters per test
  43 + let cls = createClass({
  44 + template: htmlTemplate,
  45 + directives: [DisplayContentBlockComponent],
  46 + providers: providers,
  47 + properties: {
  48 + block: {
  49 + settings: settings
  50 + }
  51 + }
  52 + });
  53 + helper = new ComponentTestHelper<DisplayContentBlockComponent>(cls, done);
  54 + });
  55 +
  56 + it("verify settings is injected", () => {
  57 + expect(helper.component.block).not.toBeNull;
  58 + expect(helper.component.block.settings).not.toBeNull;
  59 + expect(helper.component.block.settings.limit).toEqual(6);
  60 + expect(helper.component.block.settings.sections.length).toEqual(3);
  61 + });
  62 +
  63 + it("verify abstract is displayed", () => {
  64 + expect(helper.all("div[ng-bind-html|='article.abstract']")[0]).not.toBeNull;
  65 + });
  66 +
  67 + it("verify title is displayed", () => {
  68 + expect(helper.all("div > h5")[0]).not.toBeNull;
  69 + });
  70 +
  71 + it("verify body is not displayed", () => {
  72 + expect(helper.all("div[ng-bind-html|='article.body']")[0]).toBeNull;
  73 + });
  74 + });
  75 +});
... ...
src/app/layout/blocks/display-content/display-content-block.component.ts 0 → 100644
... ... @@ -0,0 +1,55 @@
  1 +import {Input, Inject, Component} from "ng-forward";
  2 +import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service";
  3 +
  4 +@Component({
  5 + selector: "noosfero-display-content-block",
  6 + templateUrl: 'app/layout/blocks/display-content/display-content-block.html',
  7 +})
  8 +@Inject(ArticleService, "$state")
  9 +export class DisplayContentBlockComponent {
  10 +
  11 + @Input() block: noosfero.Block;
  12 + @Input() owner: noosfero.Profile;
  13 +
  14 + profile: noosfero.Profile;
  15 + articles: noosfero.Article[];
  16 + sections: noosfero.Section[];
  17 +
  18 + documentsLoaded: boolean = false;
  19 +
  20 + /**
  21 + * This configuration doesn't exists on Noosfero. Statically typing here.
  22 + */
  23 + private addDefaultSections() {
  24 + let author: noosfero.Section = <noosfero.Section>{ value: 'author', checked: 'author' };
  25 + this.sections.push(author);
  26 + }
  27 +
  28 + constructor(private articleService: ArticleService, private $state: ng.ui.IStateService) {
  29 + }
  30 +
  31 + ngOnInit() {
  32 + this.profile = this.owner;
  33 + let limit = ((this.block && this.block.settings) ? this.block.settings.limit : null) || 5;
  34 + this.articleService.getByProfile(this.profile, { content_type: 'TinyMceArticle', per_page: limit })
  35 + .then((result: noosfero.RestResult<noosfero.Article[]>) => {
  36 + this.articles = <noosfero.Article[]>result.data;
  37 + this.sections = this.block.settings.sections;
  38 + // Add sections not defined by Noosfero API
  39 + this.addDefaultSections();
  40 + this.documentsLoaded = true;
  41 + });
  42 + }
  43 +
  44 + /**
  45 + * Returns whether a settings section should be displayed.
  46 + *
  47 + */
  48 + private display(section_name: string): boolean {
  49 + let section: noosfero.Section = this.sections.find( function(section: noosfero.Section) {
  50 + return section.value === section_name;
  51 + });
  52 + return section !== undefined && section.checked !== undefined;
  53 + }
  54 +}
  55 +
... ...
src/app/layout/blocks/display-content/display-content-block.html 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +<div class="{{ctrl.type}}-block">
  2 + <div ng-repeat="article in ctrl.articles" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: article.path})"" class="article">
  3 + <!-- Article Title -->
  4 + <div class="page-header" ng-if="ctrl.display('title')">
  5 + <h5 class="title media-heading" ng-bind="article.title"></h3>
  6 + </div>
  7 +
  8 + <div class="sub-header clearfix">
  9 + <!-- Article Abstract and Read More Link -->
  10 + <div class="post-lead" ng-if="ctrl.display('abstract')">
  11 + <div ng-bind-html="article.abstract"></div>
  12 + <a href="#" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: article.path})">
  13 + <i class="fa fa-pencil-square-o fa-fw fa-lg"></i> {{"article.actions.read_more" | translate}}
  14 + </a>
  15 + </div>
  16 + <div class="page-info pull-right small text-muted" ng-if="ctrl.display('publish_date')">
  17 + <!-- Article Published Date -->
  18 + <span class="time">
  19 + <i class="fa fa-clock-o"></i> <span am-time-ago="article.created_at | dateFormat"></span>
  20 + </span>
  21 + <!-- Article Author -->
  22 + <span class="author" ng-if="ctrl.display('author')">
  23 + <i class="fa fa-user"></i>
  24 + <a ui-sref="main.profile.home({profile: article.author.identifier})" ng-if="article.author">
  25 + <span class="author-name" ng-bind="article.author.name"></span>
  26 + </a>
  27 + </span>
  28 + </div>
  29 + </div>
  30 +
  31 + <div class="post-lead">
  32 + <!-- Article Image -->
  33 + <img ng-show="ctrl.display('image')" ng-src="{{article.image.url}}" class="img-responsive article-image">
  34 + <!-- Article Body -->
  35 + <div ng-bind-html="article.body" ng-show="ctrl.display('body')"></div>
  36 + </div>
  37 +
  38 + <!-- Article Tags -->
  39 + <div ng-if="ctrl.display('tags')" class="post-lead">
  40 + <div class="label" ng-repeat="tag in article.tag_list">
  41 + <span class="badge" ng-bind="tag"></span>
  42 + </div>
  43 + </div>
  44 +
  45 + </div>
  46 +</div>
... ...
src/app/layout/blocks/display-content/display-content-block.scss 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +.members-block {
  2 + .member {
  3 + img, i.profile-image {
  4 + width: 60px;
  5 + }
  6 + img {
  7 + display: inline-block;
  8 + vertical-align: top;
  9 + }
  10 + i.profile-image {
  11 + text-align: center;
  12 + background-color: #889DB1;
  13 + color: #F1F1F1;
  14 + font-size: 4.5em;
  15 + }
  16 + }
  17 +}
... ...
src/app/layout/blocks/display-content/index.ts 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +/* Module Index Entry - generated using the script npm run generate-index */
  2 +export * from "./display-content-block.component";
... ...
src/app/main/main.component.ts
... ... @@ -9,18 +9,16 @@ import {BoxesComponent} from &quot;../layout/boxes/boxes.component&quot;;
9 9 import {BlockComponent} from "../layout/blocks/block.component";
10 10 import {EnvironmentComponent} from "../environment/environment.component";
11 11 import {EnvironmentHomeComponent} from "../environment/environment-home.component";
12   -import {PeopleBlockComponent} from "../layout/blocks/people/people-block.component";
13   -import {LinkListBlockComponent} from "./../layout/blocks/link-list/link-list-block.component";
14   -import {RecentDocumentsBlockComponent} from "../layout/blocks/recent-documents/recent-documents-block.component";
15   -import {ProfileImageBlockComponent} from "../layout/blocks/profile-image/profile-image-block.component";
16   -import {RawHTMLBlockComponent} from "../layout/blocks/raw-html/raw-html-block.component";
  12 +import {PeopleBlockComponent} from "../layout/blocks/people-block/people-block.component";
  13 +import {DisplayContentBlockComponent} from "../layout/blocks/display-content/display-content-block.component";
  14 +import {LinkListBlockComponent} from "./../layout/blocks/link-list/link-list.component";
  15 +import {RecentDocumentsBlockComponent} from "../layout/blocks/recent-documents/recent-documents.component";
  16 +import {ProfileImageBlockComponent} from "../layout/blocks/profile-image-block/profile-image-block.component";
  17 +import {RawHTMLBlockComponent} from "../layout/blocks/raw-html/raw-html.component";
17 18 import {StatisticsBlockComponent} from "../layout/blocks/statistics/statistics-block.component";
18 19  
19   -import {MembersBlockComponent} from "./../layout/blocks/members/members-block.component";
20   -import {CommunitiesBlockComponent} from "./../layout/blocks/communities/communities-block.component";
21   -
22   -import {LoginBlockComponent} from "../layout/blocks/login-block/login-block.component";
23   -
  20 +import {MembersBlockComponent} from "./../layout/blocks/members-block/members-block.component";
  21 +import {CommunitiesBlockComponent} from "./../layout/blocks/communities-block/communities-block.component";
24 22 import {NoosferoTemplate} from "../shared/pipes/noosfero-template.filter";
25 23 import {DateFormat} from "../shared/pipes/date-format.filter";
26 24  
... ... @@ -83,7 +81,7 @@ export class EnvironmentContent {
83 81 * NoosferoTemplate, DateFormat, RawHTMLBlock
84 82 * @description
85 83 * The Main controller for the Noosfero Angular Theme application.
86   - *
  84 + *
87 85 * The main route '/' is defined as the URL for this controller, which routes
88 86 * requests to the {@link main.MainContentComponent} controller and also, the '/profile' route,
89 87 * which routes requests to the {@link profile.Profile} controller. See {@link profile.Profile}
... ... @@ -94,7 +92,7 @@ export class EnvironmentContent {
94 92 template: '<div ng-view></div>',
95 93 directives: [
96 94 ArticleBlogComponent, ArticleViewComponent, BoxesComponent, BlockComponent,
97   - EnvironmentComponent, PeopleBlockComponent,
  95 + EnvironmentComponent, PeopleBlockComponent, DisplayContentBlockComponent,
98 96 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent,
99 97 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
100 98 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
... ...
src/languages/en.json
... ... @@ -37,6 +37,7 @@
37 37 "comment.post.success.message": "Comment saved!",
38 38 "comment.reply": "reply",
39 39 "article.actions.edit": "Edit",
  40 + "article.actions.read_more": "Read More",
40 41 "article.basic_editor.title": "Title",
41 42 "article.basic_editor.body": "Body",
42 43 "article.basic_editor.save": "Save",
... ...
src/languages/pt.json
... ... @@ -37,6 +37,7 @@
37 37 "comment.post.success.message": "Comentário salvo com sucesso!",
38 38 "comment.reply": "responder",
39 39 "article.actions.edit": "Editar",
  40 + "article.actions.read_more": "Ler mais",
40 41 "article.basic_editor.title": "Título",
41 42 "article.basic_editor.body": "Corpo",
42 43 "article.basic_editor.save": "Salvar",
... ...
src/lib/ng-noosfero-api/interfaces/article.ts
1 1  
2 2 namespace noosfero {
3 3 export interface Article extends RestModel {
  4 + abstract: string;
4 5 path: string;
5 6 profile: Profile;
6 7 type: string;
... ...
src/lib/ng-noosfero-api/interfaces/block.ts
1 1 namespace noosfero {
2 2 export interface Block extends RestModel {
3 3 id: number;
4   - settings: any;
  4 + settings: Settings;
  5 + limit: number;
5 6 api_content: any;
6 7 }
7 8 }
... ...
src/lib/ng-noosfero-api/interfaces/section.ts 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +namespace noosfero {
  2 + /**
  3 + * @ngdoc interface
  4 + * @name noosfero.Section
  5 + * @description
  6 + * Represents a block settings section. A Section has a value property,
  7 + * which represents the Section name, and an optinally checked property which
  8 + * has the same value as the value property indicating that this property is
  9 + * selected in the block configuration.
  10 + */
  11 + export interface Section {
  12 +
  13 + value: string;
  14 + checked: string;
  15 + }
  16 +}
0 17 \ No newline at end of file
... ...
src/lib/ng-noosfero-api/interfaces/settings.ts 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +namespace noosfero {
  2 + /**
  3 + * Represents a noosfero block settings.
  4 + */
  5 + export interface Settings {
  6 + sections: noosfero.Section[];
  7 + limit: number;
  8 + }
  9 +}
0 10 \ No newline at end of file
... ...