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 | 22 | title |
23 | 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 | 31 | def comment_actions(comment) |
26 | 32 | url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) |
27 | 33 | links = links_for_comment_actions(comment) | ... | ... |
app/views/content_viewer/view_page.rhtml
... | ... | @@ -84,6 +84,8 @@ |
84 | 84 | |
85 | 85 | <%= display_source_info(@page) %> |
86 | 86 | |
87 | +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %> | |
88 | + | |
87 | 89 | <div class="comments" id="comments_list"> |
88 | 90 | |
89 | 91 | <% if @page.accept_comments? || @comments_count > 0 %> | ... | ... |
lib/noosfero/plugin.rb
... | ... | @@ -349,6 +349,12 @@ class Noosfero::Plugin |
349 | 349 | [] |
350 | 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 | 358 | # -> Adds fields to the signup form |
353 | 359 | # returns = lambda block that creates html code |
354 | 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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 | 496 | end |
497 | 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 | 524 | end | ... | ... |