Commit 12a28da7f0beea6a5e66993ef52a12a72e1a448d
Committed by
Joenio Costa
1 parent
50f90482
Exists in
master
and in
22 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 | ... | ... |