Commit 12a28da7f0beea6a5e66993ef52a12a72e1a448d
Committed by
Joenio Costa
1 parent
50f90482
Exists in
master
and in
28 other branches
Added plugin for mark comment as read
Signed-off-by: Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> (ActionItem2670)
Showing
14 changed files
with
334 additions
and
0 deletions
Show diff stats
app/helpers/comment_helper.rb
@@ -22,6 +22,12 @@ module CommentHelper | @@ -22,6 +22,12 @@ module CommentHelper | ||
22 | title | 22 | title |
23 | end | 23 | end |
24 | 24 | ||
25 | + def comment_extra_contents(comment) | ||
26 | + @plugins.dispatch(:comment_extra_contents, comment).collect do |extra_content| | ||
27 | + extra_content.kind_of?(Proc) ? self.instance_eval(&extra_content) : extra_content | ||
28 | + end.join('\n') | ||
29 | + end | ||
30 | + | ||
25 | def comment_actions(comment) | 31 | def comment_actions(comment) |
26 | url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) | 32 | url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) |
27 | links = links_for_comment_actions(comment) | 33 | links = links_for_comment_actions(comment) |
app/views/content_viewer/view_page.rhtml
@@ -84,6 +84,8 @@ | @@ -84,6 +84,8 @@ | ||
84 | 84 | ||
85 | <%= display_source_info(@page) %> | 85 | <%= display_source_info(@page) %> |
86 | 86 | ||
87 | +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %> | ||
88 | + | ||
87 | <div class="comments" id="comments_list"> | 89 | <div class="comments" id="comments_list"> |
88 | 90 | ||
89 | <% if @page.accept_comments? || @comments_count > 0 %> | 91 | <% if @page.accept_comments? || @comments_count > 0 %> |
lib/noosfero/plugin.rb
@@ -349,6 +349,12 @@ class Noosfero::Plugin | @@ -349,6 +349,12 @@ class Noosfero::Plugin | ||
349 | [] | 349 | [] |
350 | end | 350 | end |
351 | 351 | ||
352 | + # -> Adds adicional content to article | ||
353 | + # returns = lambda block that creates html code | ||
354 | + def article_extra_contents(article) | ||
355 | + nil | ||
356 | + end | ||
357 | + | ||
352 | # -> Adds fields to the signup form | 358 | # -> Adds fields to the signup form |
353 | # returns = lambda block that creates html code | 359 | # returns = lambda block that creates html code |
354 | def signup_extra_contents | 360 | def signup_extra_contents |
plugins/mark_comment_as_read/controllers/mark_comment_as_read_plugin_profile_controller.rb
0 → 100644
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +class MarkCommentAsReadPluginProfileController < ProfileController | ||
2 | + | ||
3 | + append_view_path File.join(File.dirname(__FILE__) + '/../views') | ||
4 | + | ||
5 | + def mark_as_read | ||
6 | + comment = Comment.find(params[:id]) | ||
7 | + comment.mark_as_read(user) | ||
8 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | ||
9 | + end | ||
10 | + | ||
11 | + def mark_as_not_read | ||
12 | + comment = Comment.find(params[:id]) | ||
13 | + comment.mark_as_not_read(user) | ||
14 | + render :text => {'ok' => true}.to_json, :content_type => 'application/json' | ||
15 | + end | ||
16 | + | ||
17 | +end |
plugins/mark_comment_as_read/db/migrate/20130509184338_create_mark_comment_as_read_plugin.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class CreateMarkCommentAsReadPlugin < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :mark_comment_as_read_plugin do |t| | ||
4 | + t.integer :comment_id | ||
5 | + t.integer :person_id | ||
6 | + end | ||
7 | + add_index :mark_comment_as_read_plugin, [:comment_id, :person_id], :unique => true | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + drop_table :mark_comment_as_read_plugin | ||
12 | + end | ||
13 | +end |
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin.rb
0 → 100644
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +require_dependency 'mark_comment_as_read_plugin/ext/comment' | ||
2 | + | ||
3 | +class MarkCommentAsReadPlugin < Noosfero::Plugin | ||
4 | + | ||
5 | + def self.plugin_name | ||
6 | + "MarkCommentAsReadPlugin" | ||
7 | + end | ||
8 | + | ||
9 | + def self.plugin_description | ||
10 | + _("Provide a button to mark a comment as read.") | ||
11 | + end | ||
12 | + | ||
13 | + def js_files | ||
14 | + 'mark_comment_as_read.js' | ||
15 | + end | ||
16 | + | ||
17 | + def stylesheet? | ||
18 | + true | ||
19 | + end | ||
20 | + | ||
21 | + def comment_actions(comment) | ||
22 | + lambda do | ||
23 | + [{:link => link_to_function(_('Mark as not read'), 'toggle_comment_read(this, %s, false);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_not_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-not-read-#{comment.id}")}, | ||
24 | + {:link => link_to_function(_('Mark as read'), 'toggle_comment_read(this, %s, true);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-read-#{comment.id}")}] if user | ||
25 | + end | ||
26 | + end | ||
27 | + | ||
28 | + def check_comment_actions(comment) | ||
29 | + lambda do | ||
30 | + if user | ||
31 | + comment.marked_as_read?(user) ? "#comment-action-mark-as-not-read-#{comment.id}" : "#comment-action-mark-as-read-#{comment.id}" | ||
32 | + end | ||
33 | + end | ||
34 | + end | ||
35 | + | ||
36 | + def article_extra_contents(article) | ||
37 | + lambda do | ||
38 | + if user | ||
39 | + ids = article.comments.marked_as_read(user).collect { |comment| comment.id} | ||
40 | + "<script type=\"text/javascript\">mark_comments_as_read(#{ids.to_json});</script>" if !ids.empty? | ||
41 | + end | ||
42 | + end | ||
43 | + end | ||
44 | + | ||
45 | +end |
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/ext/comment.rb
0 → 100644
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +require_dependency 'comment' | ||
2 | + | ||
3 | +class Comment | ||
4 | + | ||
5 | + has_many :read_comments, :class_name => 'MarkCommentAsReadPlugin::ReadComments' | ||
6 | + has_many :people, :through => :read_comments | ||
7 | + | ||
8 | + def mark_as_read(person) | ||
9 | + people << person | ||
10 | + end | ||
11 | + | ||
12 | + def mark_as_not_read(person) | ||
13 | + people.delete(person) | ||
14 | + end | ||
15 | + | ||
16 | + def marked_as_read?(person) | ||
17 | + person && people.find(:first, :conditions => {:id => person.id}) | ||
18 | + end | ||
19 | + | ||
20 | + def self.marked_as_read(person) | ||
21 | + find(:all, :joins => [:read_comments], :conditions => {:author_id => person.id}) | ||
22 | + end | ||
23 | + | ||
24 | +end |
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/read_comments.rb
0 → 100644
plugins/mark_comment_as_read/public/mark_comment_as_read.js
0 → 100644
@@ -0,0 +1,28 @@ | @@ -0,0 +1,28 @@ | ||
1 | +function mark_comments_as_read(comments) { | ||
2 | + jQuery(document).ready(function($) { | ||
3 | + for(var i=0; i<comments.length; i++) { | ||
4 | + $comment = jQuery('#comment-'+comments[i]); | ||
5 | + $comment.find('.comment-content').first().addClass('comment-mark-read'); | ||
6 | + } | ||
7 | + }); | ||
8 | +} | ||
9 | + | ||
10 | +function toggle_comment_read(button, url, mark) { | ||
11 | + var $ = jQuery; | ||
12 | + var $button = $(button); | ||
13 | + $button.addClass('comment-button-loading'); | ||
14 | + $.post(url, function(data) { | ||
15 | + if (data.ok) { | ||
16 | + var $comment = $button.closest('.article-comment'); | ||
17 | + var $content = $comment.find('.comment-content').first(); | ||
18 | + if(mark) | ||
19 | + $content.addClass('comment-mark-read'); | ||
20 | + else | ||
21 | + $content.removeClass('comment-mark-read'); | ||
22 | + $button.hide(); | ||
23 | + $button.removeClass('comment-button-loading'); | ||
24 | + return; | ||
25 | + } | ||
26 | + }); | ||
27 | +} | ||
28 | + |
plugins/mark_comment_as_read/test/functional/mark_comment_as_read_plugin_profile_controller_test.rb
0 → 100644
@@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/mark_comment_as_read_plugin_profile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class MarkCommentAsReadPluginProfileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class MarkCommentAsReadPluginProfileControllerTest < ActionController::TestCase | ||
8 | + def setup | ||
9 | + @controller = MarkCommentAsReadPluginProfileController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + @profile = create_user('profile').person | ||
13 | + @article = TinyMceArticle.create!(:profile => @profile, :name => 'An article') | ||
14 | + @comment = Comment.new(:source => @article, :author => @profile, :body => 'test') | ||
15 | + @comment.save! | ||
16 | + login_as(@profile.identifier) | ||
17 | + environment = Environment.default | ||
18 | + environment.enable_plugin(MarkCommentAsReadPlugin) | ||
19 | + self.stubs(:user).returns(@profile) | ||
20 | + end | ||
21 | + | ||
22 | + attr_reader :profile, :comment | ||
23 | + | ||
24 | + should 'mark comment as read' do | ||
25 | + xhr :post, :mark_as_read, :profile => profile.identifier, :id => comment.id | ||
26 | + assert_match /\{\"ok\":true\}/, @response.body | ||
27 | + end | ||
28 | + | ||
29 | + should 'mark comment as not read' do | ||
30 | + xhr :post, :mark_as_not_read, :profile => profile.identifier, :id => comment.id | ||
31 | + assert_match /\{\"ok\":true\}/, @response.body | ||
32 | + end | ||
33 | +end |
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_plugin/comment_test.rb
0 → 100644
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class MarkCommentAsReadPlugin::CommentTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @person = create_user('user').person | ||
7 | + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article') | ||
8 | + @comment = Comment.create!(:title => 'title', :body => 'body', :author_id => @person.id, :source => @article) | ||
9 | + end | ||
10 | + | ||
11 | + should 'mark comment as read' do | ||
12 | + assert !@comment.marked_as_read?(@person) | ||
13 | + @comment.mark_as_read(@person) | ||
14 | + assert @comment.marked_as_read?(@person) | ||
15 | + end | ||
16 | + | ||
17 | + should 'do not mark a comment as read again' do | ||
18 | + @comment.mark_as_read(@person) | ||
19 | + assert_raise ActiveRecord::StatementInvalid do | ||
20 | + @comment.mark_as_read(@person) | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | + should 'mark comment as not read' do | ||
25 | + @comment.mark_as_read(@person) | ||
26 | + assert @comment.marked_as_read?(@person) | ||
27 | + @comment.mark_as_not_read(@person) | ||
28 | + assert !@comment.marked_as_read?(@person) | ||
29 | + end | ||
30 | + | ||
31 | + should 'return comments marked as read for a user' do | ||
32 | + person2 = create_user('user2').person | ||
33 | + @comment.mark_as_read(@person) | ||
34 | + assert_equal [], @article.comments.marked_as_read(@person) - [@comment] | ||
35 | + assert_equal [], @article.comments.marked_as_read(person2) | ||
36 | + end | ||
37 | + | ||
38 | +end |
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_test.rb
0 → 100644
@@ -0,0 +1,87 @@ | @@ -0,0 +1,87 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class MarkCommentAsReadPluginTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + include ActionView::Helpers::TagHelper | ||
6 | + include NoosferoTestHelper | ||
7 | + | ||
8 | + def setup | ||
9 | + @plugin = MarkCommentAsReadPlugin.new | ||
10 | + @person = create_user('user').person | ||
11 | + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article') | ||
12 | + @comment = Comment.create!(:source => @article, :author => @person, :body => 'test') | ||
13 | + self.stubs(:user).returns(@person) | ||
14 | + self.stubs(:profile).returns(@person) | ||
15 | + end | ||
16 | + | ||
17 | + attr_reader :plugin, :comment | ||
18 | + | ||
19 | + should 'show link when person is logged in' do | ||
20 | + action = @plugin.comment_actions(@comment) | ||
21 | + link = self.instance_eval(&action) | ||
22 | + assert link | ||
23 | + end | ||
24 | + | ||
25 | + should 'do not show link when person is not logged in' do | ||
26 | + self.stubs(:user).returns(nil) | ||
27 | + action = @plugin.comment_actions(@comment) | ||
28 | + link = self.instance_eval(&action) | ||
29 | + assert !link | ||
30 | + end | ||
31 | + | ||
32 | + should 'return actions when comment is not read' do | ||
33 | + action = @plugin.comment_actions(@comment) | ||
34 | + links = self.instance_eval(&action) | ||
35 | + assert_equal 2, links.size | ||
36 | + end | ||
37 | + | ||
38 | + should 'return actions when comment is read' do | ||
39 | + @comment.mark_as_read(@person) | ||
40 | + action = @plugin.comment_actions(@comment) | ||
41 | + links = self.instance_eval(&action) | ||
42 | + assert_equal 2, links.size | ||
43 | + end | ||
44 | + | ||
45 | + should 'do not return any id when user is not logged in' do | ||
46 | + self.stubs(:user).returns(nil) | ||
47 | + action = @plugin.check_comment_actions(@comment) | ||
48 | + id = self.instance_eval(&action) | ||
49 | + assert !id | ||
50 | + end | ||
51 | + | ||
52 | + should 'return id of mark as not read link when comment is read' do | ||
53 | + @comment.mark_as_read(@person) | ||
54 | + action = @plugin.check_comment_actions(@comment) | ||
55 | + id = self.instance_eval(&action) | ||
56 | + assert_equal "#comment-action-mark-as-not-read-#{@comment.id}", id | ||
57 | + end | ||
58 | + | ||
59 | + should 'return id of mark as read link when comment is not read' do | ||
60 | + action = @plugin.check_comment_actions(@comment) | ||
61 | + id = self.instance_eval(&action) | ||
62 | + assert_equal "#comment-action-mark-as-read-#{@comment.id}", id | ||
63 | + end | ||
64 | + | ||
65 | + should 'return javascript to mark comment as read' do | ||
66 | + @comment.mark_as_read(@person) | ||
67 | + content = @plugin.article_extra_contents(@article) | ||
68 | + assert self.instance_eval(&content) | ||
69 | + end | ||
70 | + | ||
71 | + should 'do not return extra content if comment is not marked as read' do | ||
72 | + content = @plugin.article_extra_contents(@article) | ||
73 | + assert !self.instance_eval(&content) | ||
74 | + end | ||
75 | + | ||
76 | + should 'do not return extra content if user is not logged in' do | ||
77 | + @comment.mark_as_read(@person) | ||
78 | + self.stubs(:user).returns(nil) | ||
79 | + content = @plugin.article_extra_contents(@article) | ||
80 | + assert !self.instance_eval(&content) | ||
81 | + end | ||
82 | + | ||
83 | + def link_to_function(content, url, options = {}) | ||
84 | + link_to(content, url, options) | ||
85 | + end | ||
86 | + | ||
87 | +end |
test/unit/plugin_test.rb
@@ -496,4 +496,29 @@ class PluginTest < ActiveSupport::TestCase | @@ -496,4 +496,29 @@ class PluginTest < ActiveSupport::TestCase | ||
496 | end | 496 | end |
497 | end | 497 | end |
498 | 498 | ||
499 | + should 'comment_actions be nil if the comment is nil' do | ||
500 | + class SomePlugin < Noosfero::Plugin; end | ||
501 | + plugin = SomePlugin.new | ||
502 | + assert_nil plugin.comment_actions(nil) | ||
503 | + end | ||
504 | + | ||
505 | + should 'comment_actions be nil by default' do | ||
506 | + class SomePlugin < Noosfero::Plugin; end | ||
507 | + plugin = SomePlugin.new | ||
508 | + assert_nil plugin.comment_actions(Comment.new) | ||
509 | + end | ||
510 | + | ||
511 | + should 'check_comment_actions be an empty array if the comment is nil' do | ||
512 | + class SomePlugin < Noosfero::Plugin; end | ||
513 | + plugin = SomePlugin.new | ||
514 | + assert_equal [], plugin.check_comment_actions(nil) | ||
515 | + end | ||
516 | + | ||
517 | + | ||
518 | + should 'check_comment_actions be an empty array by default' do | ||
519 | + class SomePlugin < Noosfero::Plugin; end | ||
520 | + plugin = SomePlugin.new | ||
521 | + assert_equal [], plugin.check_comment_actions(Comment.new) | ||
522 | + end | ||
523 | + | ||
499 | end | 524 | end |