diff --git a/plugins/comment_group/controllers/profile/comment_group_plugin_profile_controller.rb b/plugins/comment_group/controllers/profile/comment_group_plugin_profile_controller.rb new file mode 100644 index 0000000..0bcb1f8 --- /dev/null +++ b/plugins/comment_group/controllers/profile/comment_group_plugin_profile_controller.rb @@ -0,0 +1,16 @@ +class CommentGroupPluginProfileController < ProfileController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + + def view_comments + article_id = params[:article_id] + group_id = params[:group_id] + + article = profile.articles.find(article_id) + comments = article.group_comments.without_spam.in_group(group_id) + render :update do |page| + page.replace_html "comments_list_group_#{group_id}", :partial => 'comment/comment.rhtml', :collection => comments.as_thread + page.replace_html "comment-count-#{group_id}", comments.count + end + end + +end diff --git a/plugins/comment_group/controllers/public/comment_group_plugin_public_controller.rb b/plugins/comment_group/controllers/public/comment_group_plugin_public_controller.rb new file mode 100644 index 0000000..61d9a86 --- /dev/null +++ b/plugins/comment_group/controllers/public/comment_group_plugin_public_controller.rb @@ -0,0 +1,8 @@ +class CommentGroupPluginPublicController < PublicController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + + def comment_group + render :json => { :group_id => Comment.find(params[:id]).group_id } + end + +end diff --git a/plugins/comment_group/db/migrate/20121220201629_add_group_id_to_comment.rb b/plugins/comment_group/db/migrate/20121220201629_add_group_id_to_comment.rb new file mode 100644 index 0000000..80afbea --- /dev/null +++ b/plugins/comment_group/db/migrate/20121220201629_add_group_id_to_comment.rb @@ -0,0 +1,9 @@ +class AddGroupIdToComment < ActiveRecord::Migration + def self.up + add_column :comments, :group_id, :integer + end + + def self.down + remove_column :comments, :group_id + end +end diff --git a/plugins/comment_group/lib/comment_group_plugin.rb b/plugins/comment_group/lib/comment_group_plugin.rb new file mode 100644 index 0000000..813baae --- /dev/null +++ b/plugins/comment_group/lib/comment_group_plugin.rb @@ -0,0 +1,50 @@ +require_dependency 'comment_group_plugin/ext/article' +require_dependency 'comment_group_plugin/ext/comment' + +#FIXME See a better way to generalize this parameter. +ActionView::Base.sanitized_allowed_attributes += ['data-macro', 'data-macro-group_id'] + +class CommentGroupPlugin < Noosfero::Plugin + + def self.plugin_name + "Comment Group" + end + + def self.plugin_description + _("A plugin that display comment groups.") + end + + def load_comments(article) + article.comments.without_spam.without_group.as_thread + end + + #FIXME make this test + def macro_display_comments(params, inner_html, source) + group_id = params[:group_id].to_i + article = source + count = article.group_comments.without_spam.in_group(group_id).count + + lambda {render :partial => 'plugins/comment_group_macro/views/comment_group.rhtml', :locals => {:group_id => group_id, :article_id => article.id, :inner_html => inner_html, :count => count, :profile_identifier => article.profile.identifier }} + end + + def macro_methods + 'macro_display_comments' + end + + def config_macro_display_comments + { :params => [], :skip_dialog => true, :generator => 'makeCommentable();', :js_files => 'comment_group.js', :icon_path => '/designs/icons/tango/Tango/16x16/emblems/emblem-system.png', :css_files => 'comment_group.css' } + end + + def comment_form_extra_contents(args) + comment = args[:comment] + group_id = comment.group_id || args[:group_id] + lambda { + hidden_field_tag('comment[group_id]', group_id) if group_id + } + end + + def js_files + 'comment_group_macro.js' + end + +end diff --git a/plugins/comment_group/lib/comment_group_plugin/ext/article.rb b/plugins/comment_group/lib/comment_group_plugin/ext/article.rb new file mode 100644 index 0000000..db1e2c7 --- /dev/null +++ b/plugins/comment_group/lib/comment_group_plugin/ext/article.rb @@ -0,0 +1,21 @@ +require_dependency 'article' + +class Article + + #FIXME make this test + has_many :group_comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc', :conditions => [ 'group_id IS NOT NULL'] + + #FIXME make this test + validate :not_empty_group_comments_removed + + #FIXME make this test + def not_empty_group_comments_removed + if body + groups_with_comments = group_comments.collect {|comment| comment.group_id}.uniq + groups = Hpricot(body.to_s).search('.macro').collect{|element| element['data-macro-group_id'].to_i} + errors.add_to_base(N_('Not empty group comment cannot be removed')) unless (groups_with_comments-groups).empty? + end + end + +end + diff --git a/plugins/comment_group/lib/comment_group_plugin/ext/comment.rb b/plugins/comment_group/lib/comment_group_plugin/ext/comment.rb new file mode 100644 index 0000000..89bce1c --- /dev/null +++ b/plugins/comment_group/lib/comment_group_plugin/ext/comment.rb @@ -0,0 +1,12 @@ +require_dependency 'comment' + +class Comment + + named_scope :without_group, :conditions => {:group_id => nil } + + named_scope :in_group, lambda { |group_id| { + :conditions => ['group_id = ?', group_id] + } + } + +end diff --git a/plugins/comment_group/public/comment_group.css b/plugins/comment_group/public/comment_group.css new file mode 100644 index 0000000..6a69d84 --- /dev/null +++ b/plugins/comment_group/public/comment_group.css @@ -0,0 +1,6 @@ +div.article_comments { + background-color:#dddddd; + border-style: solid; + border-color:#bbbbbb; + border-width:2px; +} diff --git a/plugins/comment_group/public/comment_group.js b/plugins/comment_group/public/comment_group.js new file mode 100644 index 0000000..96a3f31 --- /dev/null +++ b/plugins/comment_group/public/comment_group.js @@ -0,0 +1,47 @@ +function getNextGroupId() { + max = -1; + groups = jQuery('#article_body_ifr').contents().find('.article_comments'); + groups.each(function(key, value) { + value = jQuery(value).attr('data-macro-group_id'); + if(value>max) max = parseInt(value); + }); + return max+1; +} + +function makeCommentable() { + tinyMCE.activeEditor.focus(); + start = jQuery(tinyMCE.activeEditor.selection.getStart()).closest('p'); + end = jQuery(tinyMCE.activeEditor.selection.getEnd()).closest('p'); + + //text = start.parent().children(); + text = jQuery('#article_body_ifr').contents().find('*'); + selection = text.slice(text.index(start), text.index(end)+1); + + hasTag = false; + selection.each(function(key, value) { + commentTag = jQuery(value).closest('.article_comments'); + if(commentTag.length) { + commentTag.children().unwrap('
"); + } + } +} + diff --git a/plugins/comment_group/public/comment_group_macro.js b/plugins/comment_group/public/comment_group_macro.js new file mode 100644 index 0000000..a85966d --- /dev/null +++ b/plugins/comment_group/public/comment_group_macro.js @@ -0,0 +1,39 @@ +var comment_group_anchor; +jQuery(document).ready(function($) { + var anchor = window.location.hash; + if(anchor.length==0) return; + + var val = anchor.split('-'); //anchor format = #comment-\d+ + if(val.length!=2 || val[0]!='#comment') return; + if($('div[data-macro=display_comments]').length==0) return; //display_comments div must exists + var comment_id = val[1]; + if(!/^\d+$/.test(comment_id)) return; //test for integer + + comment_group_anchor = anchor; + var url = '/plugin/comment_group_macro/public/comment_group/'+comment_id; + $.getJSON(url, function(data) { + if(data.group_id!=null) { + var button = $('div.comment_group_'+ data.group_id + ' a'); + button.click(); + $.scrollTo(button); + } + }); +}); + +function toggleGroup(group) { + var div = jQuery('div.comments_list_toggle_group_'+group); + var visible = div.is(':visible'); + if(!visible) + jQuery('div.comment-group-loading-'+group).addClass('comment-button-loading'); + + div.toggle('fast'); + return visible; +} + +function loadCompleted(group) { + jQuery('div.comment-group-loading-'+group).removeClass('comment-button-loading') + if(comment_group_anchor) { + jQuery.scrollTo(jQuery(comment_group_anchor)); + comment_group_anchor = null; + } +} diff --git a/plugins/comment_group/public/images/comments.gif b/plugins/comment_group/public/images/comments.gif new file mode 100644 index 0000000..e3982a9 Binary files /dev/null and b/plugins/comment_group/public/images/comments.gif differ diff --git a/plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb b/plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb new file mode 100644 index 0000000..eeae722 --- /dev/null +++ b/plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb @@ -0,0 +1,38 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' +require File.dirname(__FILE__) + '/../../controllers/profile/comment_group_plugin_profile_controller' + +# Re-raise errors caught by the controller. +class CommentGroupPluginProfileController; def rescue_action(e) raise e end; end + +class CommentGroupPluginProfileControllerTest < ActionController::TestCase + + def setup + @controller = CommentGroupPluginProfileController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @profile = create_user('testuser').person + @article = profile.articles.build(:name => 'test') + @article.save! + end + attr_reader :article + attr_reader :profile + + should 'be able to show group comments' do + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 + assert_template 'comment/_comment.rhtml' + assert_match /comments_list_group_0/, @response.body + assert_match /\"comment-count-0\", \"1\"/, @response.body + end + + should 'do not show global comments' do + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :group_id => nil) + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 + assert_template 'comment/_comment.rhtml' + assert_match /comments_list_group_0/, @response.body + assert_match /\"comment-count-0\", \"1\"/, @response.body + end + +end diff --git a/plugins/comment_group/test/functional/comment_group_plugin_public_controller_test.rb b/plugins/comment_group/test/functional/comment_group_plugin_public_controller_test.rb new file mode 100644 index 0000000..3cb011c --- /dev/null +++ b/plugins/comment_group/test/functional/comment_group_plugin_public_controller_test.rb @@ -0,0 +1,33 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' +require File.dirname(__FILE__) + '/../../controllers/public/comment_group_plugin_public_controller' + +# Re-raise errors caught by the controller. +class CommentGroupPluginPublicController; def rescue_action(e) raise e end; end + +class CommentGroupPluginPublicControllerTest < ActionController::TestCase + + def setup + @controller = CommentGroupPluginPublicController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @profile = create_user('testuser').person + @article = profile.articles.build(:name => 'test') + @article.save! + end + attr_reader :article + attr_reader :profile + + should 'be able to return group_id for a comment' do + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) + xhr :get, :comment_group, :id => comment.id + assert_match /\{\"group_id\":0\}/, @response.body + end + + should 'return group_id=null for a global comment' do + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala' ) + xhr :get, :comment_group, :id => comment.id + assert_match /\{\"group_id\":null\}/, @response.body + end + +end diff --git a/plugins/comment_group/test/unit/comment_group_plugin_test.rb b/plugins/comment_group/test/unit/comment_group_plugin_test.rb new file mode 100644 index 0000000..4eb2c74 --- /dev/null +++ b/plugins/comment_group/test/unit/comment_group_plugin_test.rb @@ -0,0 +1,81 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' + +class CommentGroupPluginTest < ActiveSupport::TestCase + + include Noosfero::Plugin::HotSpot + + def setup + @environment = Environment.default + end + + attr_reader :environment + + should 'register comment_group_macro in environment' do + Environment.macros = {} + Environment.macros[environment.id] = {} + macros = Environment.macros[environment.id] + context = mock() + context.stubs(:environment).returns(environment) + plugin = CommentGroupPlugin.new(context) + assert_equal ['macro_display_comments'], macros.keys + end + + should 'load_comments returns all the comments wihout group of an article passed as parameter' do + article = fast_create(Article) + c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) + c2 = fast_create(Comment, :source_id => article.id) + c3 = fast_create(Comment, :source_id => article.id) + + plugin = CommentGroupPlugin.new + assert_equal [], [c2, c3] - plugin.load_comments(article) + assert_equal [], plugin.load_comments(article) - [c2, c3] + end + + should 'load_comments not returns spam comments' do + article = fast_create(Article) + c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) + c2 = fast_create(Comment, :source_id => article.id) + c3 = fast_create(Comment, :source_id => article.id, :spam => true) + + plugin = CommentGroupPlugin.new + assert_equal [], [c2] - plugin.load_comments(article) + assert_equal [], plugin.load_comments(article) - [c2] + end + + should 'load_comments returns only root comments of article' do + article = fast_create(Article) + c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) + c2 = fast_create(Comment, :source_id => article.id) + c3 = fast_create(Comment, :source_id => article.id, :reply_of_id => c2.id) + + plugin = CommentGroupPlugin.new + assert_equal [], [c2] - plugin.load_comments(article) + assert_equal [], plugin.load_comments(article) - [c2] + end + + should 'params of macro display comments configuration be an empty array' do + plugin = CommentGroupPlugin.new + assert_equal [], plugin.config_macro_display_comments[:params] + end + + should 'skip_dialog of macro display comments configuration be true' do + plugin = CommentGroupPlugin.new + assert plugin.config_macro_display_comments[:skip_dialog] + end + + should 'generator of macro display comments configuration be the makeCommentable function' do + plugin = CommentGroupPlugin.new + assert_equal 'makeCommentable();', plugin.config_macro_display_comments[:generator] + end + + should 'js_files of macro display comments configuration return comment_group.js' do + plugin = CommentGroupPlugin.new + assert_equal 'comment_group.js', plugin.config_macro_display_comments[:js_files] + end + + should 'css_files of macro display comments configuration return comment_group.css' do + plugin = CommentGroupPlugin.new + assert_equal 'comment_group.css', plugin.config_macro_display_comments[:css_files] + end + +end diff --git a/plugins/comment_group/views/_comment_group.rhtml b/plugins/comment_group/views/_comment_group.rhtml new file mode 100644 index 0000000..1c25537 --- /dev/null +++ b/plugins/comment_group/views/_comment_group.rhtml @@ -0,0 +1,30 @@ +
"); - } - } -} - diff --git a/plugins/comment_group_macro/public/comment_group_macro.js b/plugins/comment_group_macro/public/comment_group_macro.js deleted file mode 100644 index a85966d..0000000 --- a/plugins/comment_group_macro/public/comment_group_macro.js +++ /dev/null @@ -1,39 +0,0 @@ -var comment_group_anchor; -jQuery(document).ready(function($) { - var anchor = window.location.hash; - if(anchor.length==0) return; - - var val = anchor.split('-'); //anchor format = #comment-\d+ - if(val.length!=2 || val[0]!='#comment') return; - if($('div[data-macro=display_comments]').length==0) return; //display_comments div must exists - var comment_id = val[1]; - if(!/^\d+$/.test(comment_id)) return; //test for integer - - comment_group_anchor = anchor; - var url = '/plugin/comment_group_macro/public/comment_group/'+comment_id; - $.getJSON(url, function(data) { - if(data.group_id!=null) { - var button = $('div.comment_group_'+ data.group_id + ' a'); - button.click(); - $.scrollTo(button); - } - }); -}); - -function toggleGroup(group) { - var div = jQuery('div.comments_list_toggle_group_'+group); - var visible = div.is(':visible'); - if(!visible) - jQuery('div.comment-group-loading-'+group).addClass('comment-button-loading'); - - div.toggle('fast'); - return visible; -} - -function loadCompleted(group) { - jQuery('div.comment-group-loading-'+group).removeClass('comment-button-loading') - if(comment_group_anchor) { - jQuery.scrollTo(jQuery(comment_group_anchor)); - comment_group_anchor = null; - } -} diff --git a/plugins/comment_group_macro/public/images/comments.gif b/plugins/comment_group_macro/public/images/comments.gif deleted file mode 100644 index e3982a9..0000000 Binary files a/plugins/comment_group_macro/public/images/comments.gif and /dev/null differ diff --git a/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_profile_controller_test.rb b/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_profile_controller_test.rb deleted file mode 100644 index 8933044..0000000 --- a/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_profile_controller_test.rb +++ /dev/null @@ -1,38 +0,0 @@ -require File.dirname(__FILE__) + '/../../../../test/test_helper' -require File.dirname(__FILE__) + '/../../controllers/profile/comment_group_macro_plugin_profile_controller' - -# Re-raise errors caught by the controller. -class CommentGroupMacroPluginProfileController; def rescue_action(e) raise e end; end - -class CommentGroupMacroPluginProfileControllerTest < ActionController::TestCase - - def setup - @controller = CommentGroupMacroPluginProfileController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - - @profile = create_user('testuser').person - @article = profile.articles.build(:name => 'test') - @article.save! - end - attr_reader :article - attr_reader :profile - - should 'be able to show group comments' do - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) - xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 - assert_template 'comment/_comment.rhtml' - assert_match /comments_list_group_0/, @response.body - assert_match /\"comment-count-0\", \"1\"/, @response.body - end - - should 'do not show global comments' do - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :group_id => nil) - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) - xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 - assert_template 'comment/_comment.rhtml' - assert_match /comments_list_group_0/, @response.body - assert_match /\"comment-count-0\", \"1\"/, @response.body - end - -end diff --git a/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_public_controller_test.rb b/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_public_controller_test.rb deleted file mode 100644 index 24d89b6..0000000 --- a/plugins/comment_group_macro/test/functional/comment_group_macro_plugin_public_controller_test.rb +++ /dev/null @@ -1,33 +0,0 @@ -require File.dirname(__FILE__) + '/../../../../test/test_helper' -require File.dirname(__FILE__) + '/../../controllers/public/comment_group_macro_plugin_public_controller' - -# Re-raise errors caught by the controller. -class CommentGroupMacroPluginPublicController; def rescue_action(e) raise e end; end - -class CommentGroupMacroPluginPublicControllerTest < ActionController::TestCase - - def setup - @controller = CommentGroupMacroPluginPublicController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - - @profile = create_user('testuser').person - @article = profile.articles.build(:name => 'test') - @article.save! - end - attr_reader :article - attr_reader :profile - - should 'be able to return group_id for a comment' do - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :group_id => 0) - xhr :get, :comment_group, :id => comment.id - assert_match /\{\"group_id\":0\}/, @response.body - end - - should 'return group_id=null for a global comment' do - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala' ) - xhr :get, :comment_group, :id => comment.id - assert_match /\{\"group_id\":null\}/, @response.body - end - -end diff --git a/plugins/comment_group_macro/test/unit/comment_group_macro_plugin_test.rb b/plugins/comment_group_macro/test/unit/comment_group_macro_plugin_test.rb deleted file mode 100644 index 373f42b..0000000 --- a/plugins/comment_group_macro/test/unit/comment_group_macro_plugin_test.rb +++ /dev/null @@ -1,81 +0,0 @@ -require File.dirname(__FILE__) + '/../../../../test/test_helper' - -class CommentGroupMacroPluginTest < ActiveSupport::TestCase - - include Noosfero::Plugin::HotSpot - - def setup - @environment = Environment.default - end - - attr_reader :environment - - should 'register comment_group_macro in environment' do - Environment.macros = {} - Environment.macros[environment.id] = {} - macros = Environment.macros[environment.id] - context = mock() - context.stubs(:environment).returns(environment) - plugin = CommentGroupMacroPlugin.new(context) - assert_equal ['macro_display_comments'], macros.keys - end - - should 'load_comments returns all the comments wihout group of an article passed as parameter' do - article = fast_create(Article) - c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) - c2 = fast_create(Comment, :source_id => article.id) - c3 = fast_create(Comment, :source_id => article.id) - - plugin = CommentGroupMacroPlugin.new - assert_equal [], [c2, c3] - plugin.load_comments(article) - assert_equal [], plugin.load_comments(article) - [c2, c3] - end - - should 'load_comments not returns spam comments' do - article = fast_create(Article) - c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) - c2 = fast_create(Comment, :source_id => article.id) - c3 = fast_create(Comment, :source_id => article.id, :spam => true) - - plugin = CommentGroupMacroPlugin.new - assert_equal [], [c2] - plugin.load_comments(article) - assert_equal [], plugin.load_comments(article) - [c2] - end - - should 'load_comments returns only root comments of article' do - article = fast_create(Article) - c1 = fast_create(Comment, :source_id => article.id, :group_id => 1) - c2 = fast_create(Comment, :source_id => article.id) - c3 = fast_create(Comment, :source_id => article.id, :reply_of_id => c2.id) - - plugin = CommentGroupMacroPlugin.new - assert_equal [], [c2] - plugin.load_comments(article) - assert_equal [], plugin.load_comments(article) - [c2] - end - - should 'params of macro display comments configuration be an empty array' do - plugin = CommentGroupMacroPlugin.new - assert_equal [], plugin.config_macro_display_comments[:params] - end - - should 'skip_dialog of macro display comments configuration be true' do - plugin = CommentGroupMacroPlugin.new - assert plugin.config_macro_display_comments[:skip_dialog] - end - - should 'generator of macro display comments configuration be the makeCommentable function' do - plugin = CommentGroupMacroPlugin.new - assert_equal 'makeCommentable();', plugin.config_macro_display_comments[:generator] - end - - should 'js_files of macro display comments configuration return comment_group.js' do - plugin = CommentGroupMacroPlugin.new - assert_equal 'comment_group.js', plugin.config_macro_display_comments[:js_files] - end - - should 'css_files of macro display comments configuration return comment_group.css' do - plugin = CommentGroupMacroPlugin.new - assert_equal 'comment_group.css', plugin.config_macro_display_comments[:css_files] - end - -end diff --git a/plugins/comment_group_macro/views/_comment_group.rhtml b/plugins/comment_group_macro/views/_comment_group.rhtml deleted file mode 100644 index 56877c3..0000000 --- a/plugins/comment_group_macro/views/_comment_group.rhtml +++ /dev/null @@ -1,30 +0,0 @@ -