Commit 9b3a27c9804db1b9a5d72e43ca85b6579815de3f

Authored by Leandro Santos
1 parent da32e022

refactoring recent documents block

src/app/layout/blocks/recent-documents/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 "./recent-documents.component"; 2 +export * from "./recent-documents-block.component";
src/app/layout/blocks/recent-documents/recent-documents-block.component.spec.ts 0 → 100644
@@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
  1 +import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Provider, Input, provide, Component} from 'ng-forward';
  3 +import {provideFilters} from '../../../../spec/helpers';
  4 +import {RecentDocumentsBlockComponent} from './recent-documents-block.component';
  5 +
  6 +const htmlTemplate: string = '<noosfero-recent-documents-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-recent-documents-block>';
  7 +
  8 +const tcb = new TestComponentBuilder();
  9 +
  10 +describe("Components", () => {
  11 + describe("Recent Documents Block Component", () => {
  12 +
  13 + let settingsObj = {};
  14 + let mockedArticleService = {
  15 + getByProfile: (profile: noosfero.Profile, filters: any): any => {
  16 + return Promise.resolve({ data: [{ name: "article1" }], headers: (name: string) => { return name; } });
  17 + }
  18 + };
  19 + let profile = { name: 'profile-name' };
  20 + beforeEach(angular.mock.module("templates"));
  21 +
  22 + let state = jasmine.createSpyObj("state", ["go"]);
  23 +
  24 +
  25 + function getProviders() {
  26 + return [
  27 + new Provider('$state', { useValue: state }),
  28 + new Provider('ArticleService', {
  29 + useValue: mockedArticleService
  30 + }),
  31 + ].concat(provideFilters("truncateFilter", "stripTagsFilter"));
  32 + }
  33 + let componentClass: any = null;
  34 +
  35 + function getComponent() {
  36 + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [RecentDocumentsBlockComponent], providers: getProviders() })
  37 + class BlockContainerComponent {
  38 + block = { type: 'Block', settings: settingsObj };
  39 + owner = profile;
  40 + constructor() {
  41 + }
  42 + }
  43 + return BlockContainerComponent;
  44 + }
  45 +
  46 +
  47 + it("get recent documents from the article service", done => {
  48 + tcb.createAsync(getComponent()).then(fixture => {
  49 + let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
  50 + expect(recentDocumentsBlock.documents).toEqual([{ name: "article1" }]);
  51 + done();
  52 + });
  53 + });
  54 +
  55 + it("go to article page when open a document", done => {
  56 + tcb.createAsync(getComponent()).then(fixture => {
  57 + let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
  58 + recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } });
  59 + expect(state.go).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "identifier" });
  60 + done();
  61 + });
  62 + });
  63 +
  64 + it("it uses default limit 5 if not defined on block", done => {
  65 + settingsObj = null;
  66 + mockedArticleService = jasmine.createSpyObj("mockedArticleService", ["getByProfile"]);
  67 + (<any>mockedArticleService).mocked = true;
  68 + let thenMocked = jasmine.createSpy("then");
  69 + mockedArticleService.getByProfile = jasmine.createSpy("getByProfile").and.returnValue({then: thenMocked});
  70 + let getByProfileFunct = mockedArticleService.getByProfile;
  71 + tcb.createAsync(getComponent()).then(fixture => {
  72 + let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
  73 + recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } });
  74 + expect(getByProfileFunct).toHaveBeenCalledWith(profile, { content_type: 'TinyMceArticle', per_page: 5 });
  75 + done();
  76 + });
  77 + });
  78 +
  79 + });
  80 +});
src/app/layout/blocks/recent-documents/recent-documents-block.component.ts 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +import {Component, Inject, Input} from "ng-forward";
  2 +import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service";
  3 +
  4 +@Component({
  5 + selector: "noosfero-recent-documents-block",
  6 + templateUrl: 'app/layout/blocks/recent-documents/recent-documents-block.html'
  7 +})
  8 +@Inject(ArticleService, "$state")
  9 +export class RecentDocumentsBlockComponent {
  10 +
  11 + @Input() block: any;
  12 + @Input() owner: any;
  13 +
  14 + profile: any;
  15 + documents: any;
  16 +
  17 + documentsLoaded: boolean = false;
  18 +
  19 + constructor(private articleService: ArticleService, private $state: any) {
  20 + }
  21 +
  22 + ngOnInit() {
  23 + this.profile = this.owner;
  24 + this.documents = [];
  25 +
  26 + let limit = ((this.block && this.block.settings) ? this.block.settings.limit : null) || 5;
  27 + // FIXME get all text articles
  28 + // FIXME make the getByProfile a generic method where we tell the type passing a class TinyMceArticle
  29 + // and the promise should be of type TinyMceArticle[], per example
  30 + this.articleService.getByProfile(this.profile, { content_type: 'TinyMceArticle', per_page: limit })
  31 + .then((result: noosfero.RestResult<noosfero.Article[]>) => {
  32 + this.documents = <noosfero.Article[]>result.data;
  33 + this.documentsLoaded = true;
  34 + });
  35 + }
  36 +
  37 + openDocument(article: any) {
  38 + this.$state.go("main.profile.page", { page: article.path, profile: article.profile.identifier });
  39 + }
  40 +
  41 +}
src/app/layout/blocks/recent-documents/recent-documents-block.html 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +<div deckgrid source="ctrl.documents" class="deckgrid">
  2 + <div class="a-card panel media" ng-click="mother.ctrl.openDocument(card);">
  3 + <div class="author media-left" ng-show="card.author.image">
  4 + <img ng-src="{{card.author.image.url}}" class="img-circle">
  5 + </div>
  6 + <div class="header media-body">
  7 + <h5 class="title media-heading" ng-bind="card.title"></h5>
  8 +
  9 + <div class="subheader">
  10 + <span class="time">
  11 + <i class="fa fa-clock-o"></i> <span am-time-ago="card.created_at | dateFormat"></span>
  12 + </span>
  13 + </div>
  14 + </div>
  15 + <img ng-show="card.image" ng-src="{{card.image.url}}" class="img-responsive article-image">
  16 + <div class="post-lead" ng-bind-html="card.body | stripTags | truncate: 100: '...': true"></div>
  17 + </div>
  18 +</div>
src/app/layout/blocks/recent-documents/recent-documents-block.scss 0 → 100644
@@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
  1 +.block.recentdocumentsblock {
  2 + .deckgrid[deckgrid]::before {
  3 + font-size: 0; /* See https://github.com/akoenig/angular-deckgrid/issues/14#issuecomment-35728861 */
  4 + visibility: hidden;
  5 + }
  6 + .author {
  7 + img {
  8 + width: 30px;
  9 + height: 30px;
  10 + }
  11 + }
  12 + .header {
  13 + .subheader {
  14 + color: #C1C1C1;
  15 + font-size: 10px;
  16 + }
  17 + }
  18 + .post-lead {
  19 + color: #8E8E8E;
  20 + font-size: 14px;
  21 + }
  22 + .article-image {
  23 + margin: 10px 0;
  24 + }
  25 +}
  26 +
  27 +.col-md-2-5 {
  28 + .deckgrid[deckgrid]::before {
  29 + content: '1 .deck-column';
  30 + }
  31 +}
  32 +
  33 +.col-md-7 {
  34 + .block.recentdocumentsblock {
  35 + background-color: transparent;
  36 + border: 0;
  37 +
  38 + .deckgrid[deckgrid]::before {
  39 + content: '3 .deck-column';
  40 + }
  41 +
  42 + .panel-heading {
  43 + display: none;
  44 + }
  45 + .panel-body {
  46 + padding: 0;
  47 + }
  48 +
  49 + .deckgrid {
  50 + .column {
  51 + float: left;
  52 + }
  53 +
  54 + .deck-column {
  55 + @extend .col-md-4;
  56 + padding: 0;
  57 +
  58 + .a-card {
  59 + padding: 10px;
  60 + margin: 3px;
  61 + }
  62 + }
  63 + }
  64 + }
  65 +}
src/app/layout/blocks/recent-documents/recent-documents.component.spec.ts
@@ -1,80 +0,0 @@ @@ -1,80 +0,0 @@
1 -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';  
2 -import {Provider, Input, provide, Component} from 'ng-forward';  
3 -import {provideFilters} from '../../../../spec/helpers';  
4 -import {RecentDocumentsBlockComponent} from './recent-documents.component';  
5 -  
6 -const htmlTemplate: string = '<noosfero-recent-documents-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-recent-documents-block>';  
7 -  
8 -const tcb = new TestComponentBuilder();  
9 -  
10 -describe("Components", () => {  
11 - describe("Recent Documents Block Component", () => {  
12 -  
13 - let settingsObj = {};  
14 - let mockedArticleService = {  
15 - getByProfile: (profile: noosfero.Profile, filters: any): any => {  
16 - return Promise.resolve({ data: [{ name: "article1" }], headers: (name: string) => { return name; } });  
17 - }  
18 - };  
19 - let profile = { name: 'profile-name' };  
20 - beforeEach(angular.mock.module("templates"));  
21 -  
22 - let state = jasmine.createSpyObj("state", ["go"]);  
23 -  
24 -  
25 - function getProviders() {  
26 - return [  
27 - new Provider('$state', { useValue: state }),  
28 - new Provider('ArticleService', {  
29 - useValue: mockedArticleService  
30 - }),  
31 - ].concat(provideFilters("truncateFilter", "stripTagsFilter"));  
32 - }  
33 - let componentClass: any = null;  
34 -  
35 - function getComponent() {  
36 - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [RecentDocumentsBlockComponent], providers: getProviders() })  
37 - class BlockContainerComponent {  
38 - block = { type: 'Block', settings: settingsObj };  
39 - owner = profile;  
40 - constructor() {  
41 - }  
42 - }  
43 - return BlockContainerComponent;  
44 - }  
45 -  
46 -  
47 - it("get recent documents from the article service", done => {  
48 - tcb.createAsync(getComponent()).then(fixture => {  
49 - let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;  
50 - expect(recentDocumentsBlock.documents).toEqual([{ name: "article1" }]);  
51 - done();  
52 - });  
53 - });  
54 -  
55 - it("go to article page when open a document", done => {  
56 - tcb.createAsync(getComponent()).then(fixture => {  
57 - let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;  
58 - recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } });  
59 - expect(state.go).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "identifier" });  
60 - done();  
61 - });  
62 - });  
63 -  
64 - it("it uses default limit 5 if not defined on block", done => {  
65 - settingsObj = null;  
66 - mockedArticleService = jasmine.createSpyObj("mockedArticleService", ["getByProfile"]);  
67 - (<any>mockedArticleService).mocked = true;  
68 - let thenMocked = jasmine.createSpy("then");  
69 - mockedArticleService.getByProfile = jasmine.createSpy("getByProfile").and.returnValue({then: thenMocked});  
70 - let getByProfileFunct = mockedArticleService.getByProfile;  
71 - tcb.createAsync(getComponent()).then(fixture => {  
72 - let recentDocumentsBlock: RecentDocumentsBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance;  
73 - recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } });  
74 - expect(getByProfileFunct).toHaveBeenCalledWith(profile, { content_type: 'TinyMceArticle', per_page: 5 });  
75 - done();  
76 - });  
77 - });  
78 -  
79 - });  
80 -});  
81 \ No newline at end of file 0 \ No newline at end of file
src/app/layout/blocks/recent-documents/recent-documents.component.ts
@@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
1 -import {Component, Inject, Input} from "ng-forward";  
2 -import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service";  
3 -  
4 -@Component({  
5 - selector: "noosfero-recent-documents-block",  
6 - templateUrl: 'app/layout/blocks/recent-documents/recent-documents.html'  
7 -})  
8 -@Inject(ArticleService, "$state")  
9 -export class RecentDocumentsBlockComponent {  
10 -  
11 - @Input() block: any;  
12 - @Input() owner: any;  
13 -  
14 - profile: any;  
15 - documents: any;  
16 -  
17 - documentsLoaded: boolean = false;  
18 -  
19 - constructor(private articleService: ArticleService, private $state: any) {  
20 - }  
21 -  
22 - ngOnInit() {  
23 - this.profile = this.owner;  
24 - this.documents = [];  
25 -  
26 - let limit = ((this.block && this.block.settings) ? this.block.settings.limit : null) || 5;  
27 - // FIXME get all text articles  
28 - // FIXME make the getByProfile a generic method where we tell the type passing a class TinyMceArticle  
29 - // and the promise should be of type TinyMceArticle[], per example  
30 - this.articleService.getByProfile(this.profile, { content_type: 'TinyMceArticle', per_page: limit })  
31 - .then((result: noosfero.RestResult<noosfero.Article[]>) => {  
32 - this.documents = <noosfero.Article[]>result.data;  
33 - this.documentsLoaded = true;  
34 - });  
35 - }  
36 -  
37 - openDocument(article: any) {  
38 - this.$state.go("main.profile.page", { page: article.path, profile: article.profile.identifier });  
39 - }  
40 -  
41 -}  
src/app/layout/blocks/recent-documents/recent-documents.html
@@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
1 -<div deckgrid source="ctrl.documents" class="deckgrid">  
2 - <div class="a-card panel media" ng-click="mother.ctrl.openDocument(card);">  
3 - <div class="author media-left" ng-show="card.author.image">  
4 - <img ng-src="{{card.author.image.url}}" class="img-circle">  
5 - </div>  
6 - <div class="header media-body">  
7 - <h5 class="title media-heading" ng-bind="card.title"></h5>  
8 -  
9 - <div class="subheader">  
10 - <span class="time">  
11 - <i class="fa fa-clock-o"></i> <span am-time-ago="card.created_at | dateFormat"></span>  
12 - </span>  
13 - </div>  
14 - </div>  
15 - <img ng-show="card.image" ng-src="{{card.image.url}}" class="img-responsive article-image">  
16 - <div class="post-lead" ng-bind-html="card.body | stripTags | truncate: 100: '...': true"></div>  
17 - </div>  
18 -</div>  
src/app/layout/blocks/recent-documents/recent-documents.scss
@@ -1,65 +0,0 @@ @@ -1,65 +0,0 @@
1 -.block.recentdocumentsblock {  
2 - .deckgrid[deckgrid]::before {  
3 - font-size: 0; /* See https://github.com/akoenig/angular-deckgrid/issues/14#issuecomment-35728861 */  
4 - visibility: hidden;  
5 - }  
6 - .author {  
7 - img {  
8 - width: 30px;  
9 - height: 30px;  
10 - }  
11 - }  
12 - .header {  
13 - .subheader {  
14 - color: #C1C1C1;  
15 - font-size: 10px;  
16 - }  
17 - }  
18 - .post-lead {  
19 - color: #8E8E8E;  
20 - font-size: 14px;  
21 - }  
22 - .article-image {  
23 - margin: 10px 0;  
24 - }  
25 -}  
26 -  
27 -.col-md-2-5 {  
28 - .deckgrid[deckgrid]::before {  
29 - content: '1 .deck-column';  
30 - }  
31 -}  
32 -  
33 -.col-md-7 {  
34 - .block.recentdocumentsblock {  
35 - background-color: transparent;  
36 - border: 0;  
37 -  
38 - .deckgrid[deckgrid]::before {  
39 - content: '3 .deck-column';  
40 - }  
41 -  
42 - .panel-heading {  
43 - display: none;  
44 - }  
45 - .panel-body {  
46 - padding: 0;  
47 - }  
48 -  
49 - .deckgrid {  
50 - .column {  
51 - float: left;  
52 - }  
53 -  
54 - .deck-column {  
55 - @extend .col-md-4;  
56 - padding: 0;  
57 -  
58 - .a-card {  
59 - padding: 10px;  
60 - margin: 3px;  
61 - }  
62 - }  
63 - }  
64 - }  
65 -}  
src/app/main/main.component.ts
@@ -11,7 +11,7 @@ import {EnvironmentComponent} from &quot;../environment/environment.component&quot;; @@ -11,7 +11,7 @@ import {EnvironmentComponent} from &quot;../environment/environment.component&quot;;
11 import {EnvironmentHomeComponent} from "../environment/environment-home.component"; 11 import {EnvironmentHomeComponent} from "../environment/environment-home.component";
12 import {PeopleBlockComponent} from "../layout/blocks/people/people-block.component"; 12 import {PeopleBlockComponent} from "../layout/blocks/people/people-block.component";
13 import {LinkListBlockComponent} from "./../layout/blocks/link-list/link-list-block.component"; 13 import {LinkListBlockComponent} from "./../layout/blocks/link-list/link-list-block.component";
14 -import {RecentDocumentsBlockComponent} from "../layout/blocks/recent-documents/recent-documents.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"; 15 import {ProfileImageBlockComponent} from "../layout/blocks/profile-image/profile-image-block.component";
16 import {RawHTMLBlockComponent} from "../layout/blocks/raw-html/raw-html-block.component"; 16 import {RawHTMLBlockComponent} from "../layout/blocks/raw-html/raw-html-block.component";
17 17