Commit a944f06af9883d338e0a3432e12ab6db4f62d594

Authored by Victor Costa
1 parent a5c48faf

Display replies of comments

src/app/article/comment/comment.component.spec.ts
@@ -30,12 +30,11 @@ describe("Components", () => { @@ -30,12 +30,11 @@ describe("Components", () => {
30 }); 30 });
31 }); 31 });
32 32
33 - it("render a post comment tag when click in reply", done => { 33 + it("set show reply to true when click reply", done => {
34 helpers.createComponentFromClass(ContainerComponent).then(fixture => { 34 helpers.createComponentFromClass(ContainerComponent).then(fixture => {
35 let component: CommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance; 35 let component: CommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
36 component.reply(); 36 component.reply();
37 - fixture.debugElement.getLocal("$rootScope").$apply();  
38 - expect(fixture.debugElement.queryAll("noosfero-post-comment").length).toEqual(1); 37 + expect(component.showReply).toBeTruthy(1);
39 done(); 38 done();
40 }); 39 });
41 }); 40 });
src/app/article/comment/comment.component.ts
1 -import { Input, Component } from 'ng-forward'; 1 +import { Inject, Input, Component } from 'ng-forward';
  2 +import { PostCommentComponent } from "./post-comment/post-comment.component";
2 3
3 @Component({ 4 @Component({
4 selector: 'noosfero-comment', 5 selector: 'noosfero-comment',
5 templateUrl: 'app/article/comment/comment.html' 6 templateUrl: 'app/article/comment/comment.html'
6 }) 7 })
  8 +@Inject("$scope")
7 export class CommentComponent { 9 export class CommentComponent {
8 10
9 @Input() comment: noosfero.Comment; 11 @Input() comment: noosfero.Comment;
@@ -11,6 +13,12 @@ export class CommentComponent { @@ -11,6 +13,12 @@ export class CommentComponent {
11 13
12 showReply: boolean = false; 14 showReply: boolean = false;
13 15
  16 + constructor(private $scope: ng.IScope) {
  17 + $scope.$on(PostCommentComponent.EVENT_COMMENT_RECEIVED, (event: ng.IAngularEvent, comment: noosfero.Comment) => {
  18 + this.showReply = false;
  19 + });
  20 + }
  21 +
14 reply() { 22 reply() {
15 this.showReply = true; 23 this.showReply = true;
16 } 24 }
src/app/article/comment/comment.html
@@ -19,7 +19,5 @@ @@ -19,7 +19,5 @@
19 <div class="title">{{ctrl.comment.title}}</div> 19 <div class="title">{{ctrl.comment.title}}</div>
20 <div class="body">{{ctrl.comment.body}}</div> 20 <div class="body">{{ctrl.comment.body}}</div>
21 </div> 21 </div>
22 -  
23 - <noosfero-post-comment ng-if="ctrl.showReply" [article]="ctrl.article" [reply-of]="ctrl.comment"></noosfero-post-comment>  
24 - 22 + <noosfero-comments [show-form]="ctrl.showReply" [article]="ctrl.article" [parent]="ctrl.comment"></noosfero-comments>
25 </div> 23 </div>
src/app/article/comment/comments.component.spec.ts
@@ -22,33 +22,39 @@ describe(&quot;Components&quot;, () =&gt; { @@ -22,33 +22,39 @@ describe(&quot;Components&quot;, () =&gt; {
22 new Provider('NotificationService', { useValue: helpers.mocks.notificationService }) 22 new Provider('NotificationService', { useValue: helpers.mocks.notificationService })
23 ].concat(helpers.provideFilters("translateFilter")); 23 ].concat(helpers.provideFilters("translateFilter"));
24 24
25 - @Component({ selector: 'test-container-component', directives: [CommentsComponent], template: htmlTemplate, providers: providers })  
26 - class ContainerComponent {  
27 - article = { id: 1 }; 25 + let properties = { article: { id: 1 }, parent: null };
  26 + function createComponent() {
  27 + return helpers.quickCreateComponent({
  28 + providers: providers,
  29 + directives: [CommentsComponent],
  30 + template: htmlTemplate,
  31 + properties: properties
  32 + });
28 } 33 }
29 34
  35 +
30 it("render comments associated to an article", done => { 36 it("render comments associated to an article", done => {
31 - helpers.createComponentFromClass(ContainerComponent).then(fixture => { 37 + createComponent().then(fixture => {
32 expect(fixture.debugElement.queryAll("noosfero-comment").length).toEqual(2); 38 expect(fixture.debugElement.queryAll("noosfero-comment").length).toEqual(2);
33 done(); 39 done();
34 }); 40 });
35 }); 41 });
36 42
37 it("render a post comment tag", done => { 43 it("render a post comment tag", done => {
38 - helpers.createComponentFromClass(ContainerComponent).then(fixture => { 44 + createComponent().then(fixture => {
39 expect(fixture.debugElement.queryAll("noosfero-post-comment").length).toEqual(1); 45 expect(fixture.debugElement.queryAll("noosfero-post-comment").length).toEqual(1);
40 done(); 46 done();
41 }); 47 });
42 }); 48 });
43 49
44 - it("update comments list when receive an event", done => {  
45 - helpers.createComponentFromClass(ContainerComponent).then(fixture => {  
46 - fixture.debugElement.getLocal("$rootScope").$emit(PostCommentComponent.EVENT_COMMENT_RECEIVED, { id: 1 }); 50 + it("update comments list when receive an reply", done => {
  51 + properties.parent = { id: 2 };
  52 + createComponent().then(fixture => {
  53 + fixture.debugElement.getLocal("$rootScope").$emit(PostCommentComponent.EVENT_COMMENT_RECEIVED, { id: 1, reply_of: properties.parent });
47 fixture.debugElement.getLocal("$rootScope").$apply(); 54 fixture.debugElement.getLocal("$rootScope").$apply();
48 expect(fixture.debugElement.queryAll("noosfero-comment").length).toEqual(3); 55 expect(fixture.debugElement.queryAll("noosfero-comment").length).toEqual(3);
49 done(); 56 done();
50 }); 57 });
51 }); 58 });
52 -  
53 }); 59 });
54 }); 60 });
src/app/article/comment/comments.component.ts
@@ -12,17 +12,26 @@ import { CommentComponent } from &quot;./comment.component&quot;; @@ -12,17 +12,26 @@ import { CommentComponent } from &quot;./comment.component&quot;;
12 export class CommentsComponent { 12 export class CommentsComponent {
13 13
14 comments: noosfero.Comment[] = []; 14 comments: noosfero.Comment[] = [];
  15 + @Input() showForm = true;
15 @Input() article: noosfero.Article; 16 @Input() article: noosfero.Article;
  17 + @Input() parent: noosfero.Comment;
16 18
17 constructor(private commentService: CommentService, private $rootScope: ng.IScope) { 19 constructor(private commentService: CommentService, private $rootScope: ng.IScope) {
18 $rootScope.$on(PostCommentComponent.EVENT_COMMENT_RECEIVED, (event: ng.IAngularEvent, comment: noosfero.Comment) => { 20 $rootScope.$on(PostCommentComponent.EVENT_COMMENT_RECEIVED, (event: ng.IAngularEvent, comment: noosfero.Comment) => {
19 - this.comments.push(comment); 21 + if ((!this.parent && !comment.reply_of) || (comment.reply_of && this.parent && comment.reply_of.id === this.parent.id)) {
  22 + if (!this.comments) this.comments = [];
  23 + this.comments.push(comment);
  24 + }
20 }); 25 });
21 } 26 }
22 27
23 ngOnInit() { 28 ngOnInit() {
24 - this.commentService.getByArticle(this.article).then((result: noosfero.RestResult<noosfero.Comment[]>) => {  
25 - this.comments = result.data;  
26 - }); 29 + if (this.parent) {
  30 + this.comments = this.parent.replies;
  31 + } else {
  32 + this.commentService.getByArticle(this.article).then((result: noosfero.RestResult<noosfero.Comment[]>) => {
  33 + this.comments = result.data;
  34 + });
  35 + }
27 } 36 }
28 } 37 }
src/app/article/comment/comments.html
1 <div class="comments"> 1 <div class="comments">
2 - <noosfero-post-comment [article]="ctrl.article"></noosfero-post-comment> 2 + <noosfero-post-comment ng-if="ctrl.showForm" [article]="ctrl.article" [parent]="ctrl.parent"></noosfero-post-comment>
3 3
4 <div class="comments-list"> 4 <div class="comments-list">
5 <noosfero-comment ng-repeat="comment in ctrl.comments" [comment]="comment" [article]="ctrl.article"></noosfero-comment> 5 <noosfero-comment ng-repeat="comment in ctrl.comments" [comment]="comment" [article]="ctrl.article"></noosfero-comment>
src/app/article/comment/post-comment/post-comment.component.spec.ts
@@ -33,9 +33,9 @@ describe(&quot;Components&quot;, () =&gt; { @@ -33,9 +33,9 @@ describe(&quot;Components&quot;, () =&gt; {
33 helpers.createComponentFromClass(ContainerComponent).then(fixture => { 33 helpers.createComponentFromClass(ContainerComponent).then(fixture => {
34 let component: PostCommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance; 34 let component: PostCommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
35 commentService.createInArticle = jasmine.createSpy("createInArticle").and.returnValue(helpers.mocks.promiseResultTemplate({ data: {} })); 35 commentService.createInArticle = jasmine.createSpy("createInArticle").and.returnValue(helpers.mocks.promiseResultTemplate({ data: {} }));
36 - component["$rootScope"].$emit = jasmine.createSpy("$emit"); 36 + component["$scope"].$emit = jasmine.createSpy("$emit");
37 component.save(); 37 component.save();
38 - expect(component["$rootScope"].$emit).toHaveBeenCalledWith(PostCommentComponent.EVENT_COMMENT_RECEIVED, jasmine.any(Object)); 38 + expect(component["$scope"].$emit).toHaveBeenCalledWith(PostCommentComponent.EVENT_COMMENT_RECEIVED, jasmine.any(Object));
39 done(); 39 done();
40 }); 40 });
41 }); 41 });
@@ -55,9 +55,9 @@ describe(&quot;Components&quot;, () =&gt; { @@ -55,9 +55,9 @@ describe(&quot;Components&quot;, () =&gt; {
55 helpers.createComponentFromClass(ContainerComponent).then(fixture => { 55 helpers.createComponentFromClass(ContainerComponent).then(fixture => {
56 let component: PostCommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance; 56 let component: PostCommentComponent = fixture.debugElement.componentViewChildren[0].componentInstance;
57 component.comment = <any>{ reply_of_id: null }; 57 component.comment = <any>{ reply_of_id: null };
58 - component.replyOf = <any>{ id: 10 }; 58 + component.parent = <any>{ id: 10 };
59 component.save(); 59 component.save();
60 - expect(component.comment.reply_of_id).toEqual(component.replyOf.id); 60 + expect(component.comment.reply_of_id).toEqual(component.parent.id);
61 done(); 61 done();
62 }); 62 });
63 }); 63 });
src/app/article/comment/post-comment/post-comment.component.ts
@@ -6,24 +6,25 @@ import { NotificationService } from &quot;../../../shared/services/notification.servi @@ -6,24 +6,25 @@ import { NotificationService } from &quot;../../../shared/services/notification.servi
6 selector: 'noosfero-post-comment', 6 selector: 'noosfero-post-comment',
7 templateUrl: 'app/article/comment/post-comment/post-comment.html' 7 templateUrl: 'app/article/comment/post-comment/post-comment.html'
8 }) 8 })
9 -@Inject(CommentService, NotificationService, "$rootScope") 9 +@Inject(CommentService, NotificationService, "$scope")
10 export class PostCommentComponent { 10 export class PostCommentComponent {
11 11
12 public static EVENT_COMMENT_RECEIVED = "comment.received"; 12 public static EVENT_COMMENT_RECEIVED = "comment.received";
13 13
14 @Input() article: noosfero.Article; 14 @Input() article: noosfero.Article;
15 - @Input() replyOf: noosfero.Comment; 15 + @Input() parent: noosfero.Comment;
16 16
17 - comment: noosfero.Comment; 17 + comment = <noosfero.Comment>{};
18 18
19 - constructor(private commentService: CommentService, private notificationService: NotificationService, private $rootScope: ng.IScope) { } 19 + constructor(private commentService: CommentService, private notificationService: NotificationService, private $scope: ng.IScope) { }
20 20
21 save() { 21 save() {
22 - if (this.replyOf && this.comment) {  
23 - this.comment.reply_of_id = this.replyOf.id; 22 + if (this.parent && this.comment) {
  23 + this.comment.reply_of_id = this.parent.id;
24 } 24 }
25 this.commentService.createInArticle(this.article, this.comment).then((result: noosfero.RestResult<noosfero.Comment>) => { 25 this.commentService.createInArticle(this.article, this.comment).then((result: noosfero.RestResult<noosfero.Comment>) => {
26 - this.$rootScope.$emit(PostCommentComponent.EVENT_COMMENT_RECEIVED, result.data); 26 + this.$scope.$emit(PostCommentComponent.EVENT_COMMENT_RECEIVED, result.data);
  27 + this.comment.body = "";
27 this.notificationService.success({ title: "Good job!", message: "Comment saved!" }); 28 this.notificationService.success({ title: "Good job!", message: "Comment saved!" });
28 }); 29 });
29 } 30 }
src/lib/ng-noosfero-api/http/comment.service.spec.ts
@@ -22,8 +22,8 @@ describe(&quot;Services&quot;, () =&gt; { @@ -22,8 +22,8 @@ describe(&quot;Services&quot;, () =&gt; {
22 22
23 it("should return comments by article", (done) => { 23 it("should return comments by article", (done) => {
24 let articleId = 1; 24 let articleId = 1;
25 - $httpBackend.expectGET(`/api/v1/articles/${articleId}/comments`).respond(200, { comments: [{ name: "comment1" }] });  
26 - commentService.getByArticle(<noosfero.Article>{id: articleId}).then((result: noosfero.RestResult<noosfero.Comment[]>) => { 25 + $httpBackend.expectGET(`/api/v1/articles/${articleId}/comments?without_reply=true`).respond(200, { comments: [{ name: "comment1" }] });
  26 + commentService.getByArticle(<noosfero.Article>{ id: articleId }).then((result: noosfero.RestResult<noosfero.Comment[]>) => {
27 expect(result.data).toEqual([{ name: "comment1" }]); 27 expect(result.data).toEqual([{ name: "comment1" }]);
28 done(); 28 done();
29 }); 29 });
@@ -32,9 +32,9 @@ describe(&quot;Services&quot;, () =&gt; { @@ -32,9 +32,9 @@ describe(&quot;Services&quot;, () =&gt; {
32 32
33 it("should create a comment in an article", (done) => { 33 it("should create a comment in an article", (done) => {
34 let articleId = 1; 34 let articleId = 1;
35 - let comment: noosfero.Comment = <any>{ id: null};  
36 - $httpBackend.expectPOST(`/api/v1/articles/${articleId}/comments`, comment ).respond(200, {comment: { id: 2 }});  
37 - commentService.createInArticle(<noosfero.Article>{id: articleId}, comment).then((result: noosfero.RestResult<noosfero.Comment>) => { 35 + let comment: noosfero.Comment = <any>{ id: null };
  36 + $httpBackend.expectPOST(`/api/v1/articles/${articleId}/comments`, comment).respond(200, { comment: { id: 2 } });
  37 + commentService.createInArticle(<noosfero.Article>{ id: articleId }, comment).then((result: noosfero.RestResult<noosfero.Comment>) => {
38 expect(result.data).toEqual({ id: 2 }); 38 expect(result.data).toEqual({ id: 2 });
39 done(); 39 done();
40 }); 40 });
src/lib/ng-noosfero-api/http/comment.service.ts
@@ -21,9 +21,10 @@ export class CommentService extends RestangularService&lt;noosfero.Comment&gt; { @@ -21,9 +21,10 @@ export class CommentService extends RestangularService&lt;noosfero.Comment&gt; {
21 }; 21 };
22 } 22 }
23 23
24 - getByArticle(article: noosfero.Article, params?: any): ng.IPromise<noosfero.RestResult<noosfero.Comment[]>> { 24 + getByArticle(article: noosfero.Article, params: any = {}): ng.IPromise<noosfero.RestResult<noosfero.Comment[]>> {
  25 + params['without_reply'] = true;
25 let articleElement = this.articleService.getElement(<number>article.id); 26 let articleElement = this.articleService.getElement(<number>article.id);
26 - return this.list(articleElement); 27 + return this.list(articleElement, params);
27 } 28 }
28 29
29 createInArticle(article: noosfero.Article, comment: noosfero.Comment): ng.IPromise<noosfero.RestResult<noosfero.Comment>> { 30 createInArticle(article: noosfero.Article, comment: noosfero.Comment): ng.IPromise<noosfero.RestResult<noosfero.Comment>> {
src/lib/ng-noosfero-api/interfaces/comment.ts
1 namespace noosfero { 1 namespace noosfero {
2 export interface Comment extends RestModel { 2 export interface Comment extends RestModel {
3 reply_of_id: number; 3 reply_of_id: number;
  4 + reply_of: Comment;
  5 + replies: Comment[];
  6 + body: string;
4 } 7 }
5 } 8 }