Commit 26af7f72fe3335f5441cccc46a7e74966664ddb4

Authored by Victor Costa
2 parents 23145cad 65df7c9a

Merge branch 'AI3205-comment-paragraph' into stable

Conflicts:
	plugins/comment_paragraph/lib/ext/article.rb
	plugins/comment_paragraph/public/comment_paragraph_macro.js
	plugins/comment_paragraph/public/style.css
	plugins/comment_paragraph/views/comment_paragraph_plugin_profile/_comment_paragraph.html.erb
Showing 29 changed files with 312 additions and 531 deletions   Show diff stats
plugins/comment_paragraph/controllers/comment_paragraph_plugin_admin_controller.rb
@@ -3,27 +3,10 @@ class CommentParagraphPluginAdminController < PluginAdminController @@ -3,27 +3,10 @@ class CommentParagraphPluginAdminController < PluginAdminController
3 3
4 def index 4 def index
5 @settings = Noosfero::Plugin::Settings.new(environment, CommentParagraphPlugin, params[:settings]) 5 @settings = Noosfero::Plugin::Settings.new(environment, CommentParagraphPlugin, params[:settings])
6 - @article_types = []  
7 - available_article_types.each do |type|  
8 - @article_types.push({  
9 - :class_name => type.name,  
10 - :short_description => type.short_description,  
11 - :description => type.description  
12 - })  
13 - end  
14 -  
15 if request.post? 6 if request.post?
16 - @settings.settings[:auto_marking_article_types].reject! { |type| type.blank? }  
17 @settings.save! 7 @settings.save!
18 - redirect_to :controller => 'plugins', :action => 'index' 8 + session[:notice] = _('Settings successfuly saved')
19 end 9 end
20 end 10 end
21 11
22 - protected  
23 -  
24 - def available_article_types  
25 - articles = [TinyMceArticle] + @plugins.dispatch(:content_types)  
26 - articles  
27 - end  
28 -  
29 end 12 end
plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb
@@ -3,11 +3,12 @@ class CommentParagraphPluginProfileController < ProfileController @@ -3,11 +3,12 @@ class CommentParagraphPluginProfileController < ProfileController
3 3
4 def view_comments 4 def view_comments
5 @article_id = params[:article_id] 5 @article_id = params[:article_id]
6 - @paragraph_id = params[:paragraph_id] 6 + @paragraph_uuid = params[:paragraph_uuid]
7 article = profile.articles.find(@article_id) 7 article = profile.articles.find(@article_id)
8 - @comments = article.comments.without_spam.in_paragraph(@paragraph_id) 8 + @comments = article.comments.without_spam.in_paragraph(@paragraph_uuid)
9 @comments_count = @comments.count 9 @comments_count = @comments.count
10 @comments = @comments.without_reply 10 @comments = @comments.without_reply
  11 + render :partial => 'comment/comment.html.erb', :collection => @comments
11 end 12 end
12 13
13 end 14 end
plugins/comment_paragraph/controllers/public/comment_paragraph_plugin_public_controller.rb
@@ -3,7 +3,7 @@ class CommentParagraphPluginPublicController < PublicController @@ -3,7 +3,7 @@ class CommentParagraphPluginPublicController < PublicController
3 3
4 def comment_paragraph 4 def comment_paragraph
5 @comment = Comment.find(params[:id]) 5 @comment = Comment.find(params[:id])
6 - render :json => { :paragraph_id => @comment.paragraph_id } 6 + render :json => { :paragraph_uuid => @comment.paragraph_uuid }
7 end 7 end
8 8
9 end 9 end
plugins/comment_paragraph/db/migrate/20140715201649_add_paragraph_id_to_comment.rb
@@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
1 -class AddParagraphIdToComment < ActiveRecord::Migration  
2 - def self.up  
3 - add_column :comments, :paragraph_id, :integer unless column_exists?(:comments, :paragraph_id)  
4 - end  
5 -  
6 - def self.down  
7 - remove_column :comments, :paragraph_id  
8 - end  
9 -end  
plugins/comment_paragraph/db/migrate/20141223184902_add_paragraph_uuid_to_comments.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class AddParagraphUuidToComments < ActiveRecord::Migration
  2 + def change
  3 + add_column :comments, :paragraph_uuid
  4 + add_index :comments, :paragraph_uuid
  5 + end
  6 +end
plugins/comment_paragraph/lib/comment_paragraph_plugin.rb
@@ -14,11 +14,11 @@ class CommentParagraphPlugin &lt; Noosfero::Plugin @@ -14,11 +14,11 @@ class CommentParagraphPlugin &lt; Noosfero::Plugin
14 14
15 def comment_form_extra_contents(args) 15 def comment_form_extra_contents(args)
16 comment = args[:comment] 16 comment = args[:comment]
17 - paragraph_id = comment.paragraph_id || args[:paragraph_id] 17 + paragraph_uuid = comment.paragraph_uuid || args[:paragraph_uuid]
18 proc { 18 proc {
19 arr = [] 19 arr = []
20 arr << hidden_field_tag('comment[id]', comment.id) 20 arr << hidden_field_tag('comment[id]', comment.id)
21 - arr << hidden_field_tag('comment[paragraph_id]', paragraph_id) if paragraph_id 21 + arr << hidden_field_tag('comment[paragraph_uuid]', paragraph_uuid) if paragraph_uuid
22 arr << hidden_field_tag('comment[comment_paragraph_selected_area]', comment.comment_paragraph_selected_area) unless comment.comment_paragraph_selected_area.blank? 22 arr << hidden_field_tag('comment[comment_paragraph_selected_area]', comment.comment_paragraph_selected_area) unless comment.comment_paragraph_selected_area.blank?
23 arr << hidden_field_tag('comment[comment_paragraph_selected_content]', comment.comment_paragraph_selected_content) unless comment.comment_paragraph_selected_content.blank? 23 arr << hidden_field_tag('comment[comment_paragraph_selected_content]', comment.comment_paragraph_selected_content) unless comment.comment_paragraph_selected_content.blank?
24 arr 24 arr
@@ -40,54 +40,8 @@ class CommentParagraphPlugin &lt; Noosfero::Plugin @@ -40,54 +40,8 @@ class CommentParagraphPlugin &lt; Noosfero::Plugin
40 true 40 true
41 end 41 end
42 42
43 - def cms_controller_filters  
44 - block = proc do  
45 - if params['commit'] == 'Save'  
46 -  
47 - settings = Noosfero::Plugin::Settings.new(environment, CommentParagraphPlugin, params[:settings])  
48 -  
49 - extend CommentParagraphPlugin::CommentParagraphHelper  
50 - if !@article.id.blank? && self.auto_marking_enabled?(settings, @article.class.name)  
51 -  
52 - parsed_paragraphs = []  
53 - paragraph_id = 0  
54 -  
55 - doc = Hpricot(@article.body)  
56 - paragraphs = doc.search("/*").each do |paragraph|  
57 -  
58 - if paragraph.to_html =~ /^<div(.*)paragraph_comment(.*)$/ || paragraph.to_html =~ /^<p>\W<\/p>$/  
59 - parsed_paragraphs << paragraph.to_html  
60 - else  
61 - if paragraph.to_html =~ /^(<div|<table|<p|<ul).*/  
62 - parsed_paragraphs << CommentParagraphPlugin.parse_paragraph(paragraph.to_html, paragraph_id)  
63 - else  
64 - parsed_paragraphs << paragraph.to_html  
65 - end  
66 - end  
67 -  
68 - paragraph_id += 1  
69 -  
70 - end  
71 -  
72 - @article.body = parsed_paragraphs.join()  
73 - @article.save  
74 -  
75 - end  
76 - end  
77 - end  
78 -  
79 - { :type => 'after_filter',  
80 - :method_name => 'new',  
81 - :block => block }  
82 - end  
83 -  
84 - private  
85 -  
86 - def self.parse_paragraph( paragraph_content, paragraph_id )  
87 - "<div class='macro article_comments paragraph_comment' " +  
88 - "data-macro='comment_paragraph_plugin/allow_comment' " +  
89 - "data-macro-paragraph_id='#{paragraph_id}'>#{paragraph_content}</div>\r\n" +  
90 - "<p>&nbsp;</p>" 43 + def self.activation_mode_default_setting
  44 + 'auto'
91 end 45 end
92 46
93 end 47 end
plugins/comment_paragraph/lib/comment_paragraph_plugin/comment_paragraph_helper.rb
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -module CommentParagraphPlugin::CommentParagraphHelper  
2 -  
3 - def auto_marking_enabled?(plugin_settings, article_type)  
4 - auto_marking_setting = plugin_settings.get_setting('auto_marking_article_types')  
5 - auto_marking_setting && auto_marking_setting.include?(article_type) ? true : false  
6 - end  
7 -  
8 -end  
plugins/comment_paragraph/lib/comment_paragraph_plugin/macros/allow_comment.rb
1 -#FIXME See a better way to generalize this parameter.  
2 -ActionView::Base.sanitized_allowed_attributes += ['data-macro', 'data-macro-paragraph_id'] 1 +ActionView::Base.sanitized_allowed_attributes += ['data-macro', 'data-macro-paragraph_uuid']
3 2
4 class CommentParagraphPlugin::AllowComment < Noosfero::Plugin::Macro 3 class CommentParagraphPlugin::AllowComment < Noosfero::Plugin::Macro
  4 +
5 def self.configuration 5 def self.configuration
6 - { :params => [],  
7 - :skip_dialog => true,  
8 - :generator => 'makeAllCommentable();',  
9 - :js_files => 'comment_paragraph.js',  
10 - :icon_path => '/plugins/comment_paragraph/images/balloons-comment.png',  
11 - :css_files => 'comment_paragraph.css' } 6 + { :params => [] }
12 end 7 end
13 8
14 def parse(params, inner_html, source) 9 def parse(params, inner_html, source)
15 - paragraph_id = params[:paragraph_id].to_i 10 + paragraph_uuid = params[:paragraph_uuid]
16 article = source 11 article = source
17 - count = article.paragraph_comments.without_spam.in_paragraph(paragraph_id).count 12 + count = article.paragraph_comments.without_spam.in_paragraph(paragraph_uuid).count
18 13
19 proc { 14 proc {
20 render :partial => 'comment_paragraph_plugin_profile/comment_paragraph', 15 render :partial => 'comment_paragraph_plugin_profile/comment_paragraph',
21 - :locals => {:paragraph_id => paragraph_id, :article_id => article.id, :inner_html => inner_html, :count => count, :profile_identifier => article.profile.identifier } 16 + :locals => {:paragraph_uuid => paragraph_uuid, :article_id => article.id, :inner_html => inner_html, :count => count, :profile_identifier => article.profile.identifier }
22 } 17 }
23 end 18 end
24 end 19 end
plugins/comment_paragraph/lib/ext/article.rb
@@ -2,16 +2,54 @@ require_dependency &#39;article&#39; @@ -2,16 +2,54 @@ require_dependency &#39;article&#39;
2 2
3 class Article 3 class Article
4 4
5 - has_many :paragraph_comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc', :conditions => [ 'paragraph_id IS NOT NULL'] 5 + has_many :paragraph_comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc', :conditions => [ 'paragraph_uuid IS NOT NULL']
6 6
7 - #validate :body_change_with_comments 7 + before_save :comment_paragraph_plugin_parse_html
8 8
9 - def body_change_with_comments  
10 - if body && body_changed? && !self.comments.empty?  
11 - paragraphs_with_comments = self.comments.where("paragraph_id IS NOT NULL")  
12 - errors[:base] << (N_('You are unable to change the body of the article when paragraphs are commented')) unless (paragraphs_with_comments).empty? 9 + settings_items :comment_paragraph_plugin_activate, :type => :boolean, :default => false
  10 +
  11 + def comment_paragraph_plugin_enabled?
  12 + environment.plugin_enabled?(CommentParagraphPlugin) && self.kind_of?(TextArticle)
  13 + end
  14 +
  15 + protected
  16 +
  17 + def comment_paragraph_plugin_activate?
  18 + comment_paragraph_plugin_enabled? && comment_paragraph_plugin_settings.activation_mode == 'auto'
  19 + end
  20 +
  21 + def comment_paragraph_plugin_parse_html
  22 + comment_paragraph_plugin_activate = comment_paragraph_plugin_activate?
  23 + return unless comment_paragraph_plugin_activate
  24 +
  25 + if body && body_changed?
  26 + parsed_paragraphs = []
  27 + updated = body_change[1]
  28 + doc = Hpricot(updated)
  29 + doc.search("/*").each do |paragraph|
  30 + if paragraph.to_html =~ /^<div(.*)paragraph_comment(.*)$/ || paragraph.to_html =~ /^<p>\W<\/p>$/
  31 + parsed_paragraphs << paragraph.to_html
  32 + else
  33 + if paragraph.to_html =~ /^(<div|<table|<p|<ul).*/
  34 + parsed_paragraphs << comment_paragraph_plugin_parse_paragraph(paragraph.to_html, SecureRandom.uuid)
  35 + else
  36 + parsed_paragraphs << paragraph.to_html
  37 + end
  38 + end
  39 + end
  40 + self.body = parsed_paragraphs.join()
13 end 41 end
14 end 42 end
15 -  
16 -end  
17 43
  44 + def comment_paragraph_plugin_settings
  45 + @comment_paragraph_plugin_settings ||= Noosfero::Plugin::Settings.new(environment, CommentParagraphPlugin)
  46 + end
  47 +
  48 + def comment_paragraph_plugin_parse_paragraph(paragraph_content, paragraph_uuid)
  49 + "<div class='macro article_comments paragraph_comment' " +
  50 + "data-macro='comment_paragraph_plugin/allow_comment' " +
  51 + "data-macro-paragraph_uuid='#{paragraph_uuid}'>#{paragraph_content}</div>\r\n" +
  52 + "<p>&nbsp;</p>"
  53 + end
  54 +
  55 +end
plugins/comment_paragraph/lib/ext/comment.rb
@@ -2,17 +2,17 @@ require_dependency &#39;comment&#39; @@ -2,17 +2,17 @@ require_dependency &#39;comment&#39;
2 2
3 class Comment 3 class Comment
4 4
5 - scope :without_paragraph, :conditions => {:paragraph_id => nil } 5 + scope :without_paragraph, :conditions => {:paragraph_uuid => nil }
6 6
7 settings_items :comment_paragraph_selected_area, :type => :string 7 settings_items :comment_paragraph_selected_area, :type => :string
8 settings_items :comment_paragraph_selected_content, :type => :string 8 settings_items :comment_paragraph_selected_content, :type => :string
9 9
10 - scope :in_paragraph, proc { |paragraph_id| {  
11 - :conditions => ['paragraph_id = ?', paragraph_id] 10 + scope :in_paragraph, proc { |paragraph_uuid| {
  11 + :conditions => ['paragraph_uuid = ?', paragraph_uuid]
12 } 12 }
13 } 13 }
14 14
15 - attr_accessible :paragraph_id, :comment_paragraph_selected_area, :id, :comment_paragraph_selected_content 15 + attr_accessible :paragraph_uuid, :comment_paragraph_selected_area, :id, :comment_paragraph_selected_content
16 16
17 before_validation do |comment| 17 before_validation do |comment|
18 comment.comment_paragraph_selected_area = nil if comment.comment_paragraph_selected_area.blank? 18 comment.comment_paragraph_selected_area = nil if comment.comment_paragraph_selected_area.blank?
plugins/comment_paragraph/public/comment_paragraph.css
@@ -1,6 +0,0 @@ @@ -1,6 +0,0 @@
1 -div.article_comments {  
2 - background-color:#dddddd;  
3 - border-style: solid;  
4 - border-color:#bbbbbb;  
5 - border-width:2px;  
6 -}  
7 \ No newline at end of file 0 \ No newline at end of file
plugins/comment_paragraph/public/comment_paragraph.js
@@ -1,57 +0,0 @@ @@ -1,57 +0,0 @@
1 -String.prototype.startsWith = function(needle){  
2 - return(this.indexOf(needle) == 0);  
3 -};  
4 -  
5 -function makeAllCommentable() {  
6 - var paragraphsTxt="";  
7 - var selectedTextCount=0;  
8 - var notSelectedTextCount=0;  
9 - var text;  
10 -  
11 - //Search for text that is not selected in the middle of selected text, in this case unselect everything  
12 - jQuery('#article_body_ifr').contents().find('body').children().each(function( index ) {  
13 - //Check if there are other texts not selected  
14 - var element=jQuery(this).prop('outerHTML');  
15 - if(element.startsWith('<div')){  
16 - selectedTextCount++;  
17 - }else{  
18 - if(! element.startsWith('<p><br></p>') && ! element.startsWith('<p>&nbsp;</p>') ){  
19 - notSelectedTextCount++;  
20 - }  
21 - }  
22 - });  
23 -  
24 - if(selectedTextCount > 0 && notSelectedTextCount>0){  
25 - jQuery('#article_body_ifr').contents().find('body').children('.paragraph_comment').contents().unwrap();  
26 - //Workaround necessary to post the body of the article  
27 - tinymce.activeEditor.execCommand('mceInsertContent', false, " ");  
28 - return;  
29 - }  
30 -  
31 - //Add p tag, when opening the editor. For some season it appear at the end without p tag  
32 - foundCommentableParagraph = false;  
33 - jQuery('#article_body_ifr').contents().find('body').children('div.article_comments').each(function( index ) {  
34 - if(jQuery(this).html()!="" && jQuery(this).html()!=" " && jQuery(this).html()!="<br>"){  
35 - paragraphsTxt+="<p>" + jQuery(this).html() + "</p>";  
36 - }  
37 - foundCommentableParagraph = true;  
38 - });  
39 -  
40 - //undo the paragraph comment tags  
41 - if(foundCommentableParagraph === true){  
42 - tinyMCE.activeEditor.setContent(paragraphsTxt);  
43 - return;  
44 - }  
45 -  
46 - //Wraps the paragraph using the chosen class  
47 - jQuery('#article_body_ifr').contents().find('body').children('p,table,img').each(function( index ) {  
48 - text=jQuery(this).prop('outerHTML');  
49 - if(text!="" && text!=" " && text!="<br>"){  
50 - paragraphsTxt+='<div class="macro article_comments paragraph_comment" data-macro="comment_paragraph_plugin/allow_comment" data-macro-paragraph_id="' + index + '">' + text + '</div><br>'  
51 - }  
52 - });  
53 - tinyMCE.activeEditor.setContent(paragraphsTxt);  
54 -  
55 - //Workaround necessary to post the body of the article  
56 - tinymce.activeEditor.execCommand('mceInsertContent', false, " ");  
57 -}  
plugins/comment_paragraph/public/comment_paragraph_admin.js
@@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
1 -function check_fields(check, table_id, start) {  
2 - var checkboxes = jQuery("#" + table_id + " tbody tr td input[type='checkbox']");  
3 - for (var i = start; i < checkboxes.length; i++) {  
4 - checkboxes[i].checked = check;  
5 - }  
6 -}  
7 -  
8 -function verify_checked() {  
9 - var checkboxes = jQuery("#auto_marking_article_types_conf tbody tr td input[type='checkbox']");  
10 - var allchecked = true  
11 - for (var j = 1; j < checkboxes.length; j++) {  
12 - if(!checkboxes[j].checked) {  
13 - allchecked = false  
14 - break  
15 - }  
16 - }  
17 -  
18 - var checkbox = checkboxes.first();  
19 - checkboxes.first().attr('checked', allchecked);  
20 -}  
21 -  
22 -function check_all() {  
23 - jQuery("input[type='checkbox']").first().click(function () {  
24 - check_fields(this.checked, "auto_marking_article_types_conf", 0)  
25 - });  
26 - verify_checked();  
27 -}  
28 -  
29 -jQuery(document).ready(function() {  
30 - check_all();  
31 - jQuery("input[type='checkbox']").click(function () {  
32 - var checkbox = jQuery(this).attr("id").split("_");  
33 - verify_checked();  
34 -  
35 - if(this.checked == false) {  
36 - jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", false)  
37 - }  
38 - });  
39 -});  
plugins/comment_paragraph/public/comment_paragraph_macro.js
1 -var comment_paragraph_anchor;  
2 -var lastSelectedArea = [];  
3 -var original_paragraphs = [];  
4 -var originalArticleHeight = 0  
5 -  
6 -function setPlusIfZeroComments($){  
7 - $('.comment-count').each(function(){  
8 - var commentCount = $(this).text().trim();  
9 - if(commentCount=='0')  
10 - $(this).text("+");  
11 - });  
12 -}  
13 -  
14 jQuery(document).ready(function($) { 1 jQuery(document).ready(function($) {
15 //Quit if does not detect a comment for that plugin 2 //Quit if does not detect a comment for that plugin
16 if($('.comment_paragraph').size() < 1) 3 if($('.comment_paragraph').size() < 1)
17 return; 4 return;
18 5
19 - originalArticleHeight = $('.article-body').height();  
20 -  
21 - all_paragraphs = $('.comment_paragraph');  
22 - all_paragraphs.each( function(paragraph) {  
23 - var paragraph_id = $( all_paragraphs.get(paragraph) ).attr('data-paragraph');  
24 - var paragraph_content = all_paragraphs.get(paragraph).innerHTML;  
25 - original_paragraphs.push( { id: paragraph_id, content: paragraph_content } );  
26 - });  
27 -  
28 $(document).keyup(function(e) { 6 $(document).keyup(function(e) {
29 // on press ESC key... 7 // on press ESC key...
30 if (e.which == 27) { 8 if (e.which == 27) {
31 - // closing side comment box  
32 hideCommentBox(); 9 hideCommentBox();
33 } 10 }
34 }); 11 });
35 12
36 - setPlusIfZeroComments($);  
37 $('.display-comment-form').unbind(); 13 $('.display-comment-form').unbind();
38 $('.display-comment-form').click(function(){ 14 $('.display-comment-form').click(function(){
39 var $button = $(this); 15 var $button = $(this);
@@ -49,15 +25,18 @@ jQuery(document).ready(function($) { @@ -49,15 +25,18 @@ jQuery(document).ready(function($) {
49 $('.selected_content').val(""); 25 $('.selected_content').val("");
50 }); 26 });
51 27
52 - $('#cancel-comment').die();  
53 - $(document.body).on("click", '#cancel-comment', function(){  
54 - hideCommentBox();  
55 - return false; 28 + //hide comments when click outside
  29 + $('body').click(function(event){
  30 + if ($(event.target).closest('.comment-paragraph-plugin, #comment-bubble').length === 0) {
  31 + hideCommentBox();
  32 + $('#comment-bubble').removeClass('visible');
  33 + hideAllSelectedAreasExcept();
  34 + }
56 }); 35 });
57 36
58 function hideCommentBox() { 37 function hideCommentBox() {
59 $("div.side-comment").hide(); 38 $("div.side-comment").hide();
60 - $('.article-body').removeClass('comment-paragraph-slide-left'); 39 + $('.comment-paragraph-plugin').removeClass('comment-paragraph-slide-left');
61 $('.comments').removeClass('selected'); 40 $('.comments').removeClass('selected');
62 } 41 }
63 42
@@ -76,60 +55,47 @@ jQuery(document).ready(function($) { @@ -76,60 +55,47 @@ jQuery(document).ready(function($) {
76 <div align="center" class="triangle-right" >Comentar</div>\ 55 <div align="center" class="triangle-right" >Comentar</div>\
77 </a>'); 56 </a>');
78 57
79 - $('.side-comments-counter').click(function(){  
80 - var paragraphId = $(this).data('paragraph');  
81 - hideAllCommentsExcept(paragraphId); 58 + $('.comment-paragraph-plugin .side-comments-counter').click(function(){
  59 + var container = $(this).closest('.comment-paragraph-plugin');
  60 + var paragraphId = container.data('paragraph');
82 hideAllSelectedAreasExcept(paragraphId); 61 hideAllSelectedAreasExcept(paragraphId);
83 hideCommentBox(); 62 hideCommentBox();
84 - $(this).closest('.comments').addClass('selected');  
85 - $('.article-body').addClass('comment-paragraph-slide-left');  
86 - $('#side_comment_' + paragraphId).show();  
87 $('#comment-bubble').removeClass('visible'); 63 $('#comment-bubble').removeClass('visible');
  64 + container.addClass('comment-paragraph-slide-left selected');
  65 + container.find('.side-comment').show();
88 //Loads the comments 66 //Loads the comments
89 - var url = $('#link_to_ajax_comments_' + paragraphId).data('url');  
90 - $.ajax({  
91 - dataType: "script",  
92 - url: url  
93 - }).done(function() {  
94 - var button = $('#page-comment-form-' + paragraphId + ' a').get(0);  
95 - button.click(); 67 + var url = container.find('.side-comment').data('comment_paragraph_url');
  68 + $.ajax(url).done(function(data) {
  69 + container.find('.article-comments-list').html(data);
  70 + if(container.find('.article-comment').length==0 || container.find('.selected_area').length) {
  71 + container.find('.post_comment_box a.display-comment-form').click();
  72 + } else {
  73 + container.find('.post_comment_box').removeClass('opened');
  74 + container.find('.post_comment_box').addClass('closed');
  75 + container.find('.display-comment-form').show();
  76 + }
96 }); 77 });
  78 +
  79 + //set a one time handler to prevent multiple selections
  80 + var fn = function() {
  81 + hideAllSelectedAreasExcept();
  82 + $('.comment-paragraph-plugin').off('mousedown', '.comment_paragraph', fn);
  83 + }
  84 + $('.comment-paragraph-plugin').on('mousedown', '.comment_paragraph', fn);
97 }); 85 });
98 86
99 87
100 $('#comment-bubble').click(function(event){ 88 $('#comment-bubble').click(function(event){
101 - $(this).hide();  
102 - if($('.comment-paragraph-slide-left').size()==0){  
103 - $('.article-body').addClass('comment-paragraph-slide-left');  
104 - }  
105 - var url = $("#comment-bubble").data('url');  
106 - var paragraphId = $("#comment-bubble").data("paragraphId");  
107 - hideAllCommentsExcept(paragraphId);  
108 - $('#side_comment_' + paragraphId).show();  
109 - $.ajax({  
110 - dataType: "script",  
111 - url: url  
112 - }).done(function() {  
113 - var button = $('#page-comment-form-' + paragraphId + ' a').get(0);  
114 - button.click();  
115 - }); 89 + var paragraph = $("#comment-bubble").data("paragraph");
  90 + $('#comment-paragraph-plugin_' + paragraph).find('.side-comments-counter').click();
116 }); 91 });
117 92
118 - function hideAllCommentsExcept(clickedParagraph){  
119 - $(".side-comment").each(function(){  
120 - paragraph = $(this).data('paragraph');  
121 - if(paragraph != clickedParagraph){  
122 - $(this).hide();  
123 - //$(this).find().hide();  
124 - }  
125 - });  
126 - }  
127 -  
128 function hideAllSelectedAreasExcept(clickedParagraph){ 93 function hideAllSelectedAreasExcept(clickedParagraph){
129 $(".comment_paragraph").each(function(){ 94 $(".comment_paragraph").each(function(){
130 - paragraph = $(this).data('paragraph'); 95 + paragraph = $(this).closest('.comment-paragraph-plugin').data('paragraph');
131 if(paragraph != clickedParagraph){ 96 if(paragraph != clickedParagraph){
132 $(this).find(".commented-area").contents().unwrap(); 97 $(this).find(".commented-area").contents().unwrap();
  98 + $(this).html($(this).html()); //XXX: workaround to prevent creation of text nodes
133 } 99 }
134 }); 100 });
135 } 101 }
@@ -154,23 +120,20 @@ jQuery(document).ready(function($) { @@ -154,23 +120,20 @@ jQuery(document).ready(function($) {
154 //highlight area from the paragraph 120 //highlight area from the paragraph
155 $('.comment_paragraph').mouseup(function(event) { 121 $('.comment_paragraph').mouseup(function(event) {
156 122
157 - if($('.comment-paragraph-slide-left').size() > 0){  
158 - hideCommentBox();  
159 - } 123 + hideCommentBox();
160 124
161 //Don't do anything if there is no selected text 125 //Don't do anything if there is no selected text
162 if (getSelectionText().length == 0) { 126 if (getSelectionText().length == 0) {
163 return; 127 return;
164 } 128 }
165 129
166 - var paragraphId = $(this).data('paragraph'); 130 + var container = $(this).closest('.comment-paragraph-plugin');
  131 + var paragraphId = container.data('paragraph');
167 132
168 setCommentBubblePosition( event.pageX, event.pageY ); 133 setCommentBubblePosition( event.pageX, event.pageY );
169 134
170 //Prepare to open the div 135 //Prepare to open the div
171 - var url = $('#link_to_ajax_comments_' + paragraphId).data('url');  
172 - $("#comment-bubble").data("url", url);  
173 - $("#comment-bubble").data("paragraphId", paragraphId); 136 + $("#comment-bubble").data("paragraph", paragraphId);
174 $("#comment-bubble").addClass('visible'); 137 $("#comment-bubble").addClass('visible');
175 138
176 var rootElement = $(this).get(0); 139 var rootElement = $(this).get(0);
@@ -182,9 +145,9 @@ jQuery(document).ready(function($) { @@ -182,9 +145,9 @@ jQuery(document).ready(function($) {
182 } catch(e) { 145 } catch(e) {
183 return; 146 return;
184 } 147 }
185 - form = $('#page-comment-form-' + paragraphId).find('form'); 148 + form = container.find('.post_comment_box').find('form');
186 149
187 - //Register the area the has been selected at input.selected_area 150 + //Register the area that has been selected at input.selected_area
188 if (form.find('input.selected_area').length === 0){ 151 if (form.find('input.selected_area').length === 0){
189 $('<input>').attr({ 152 $('<input>').attr({
190 class: 'selected_area', 153 class: 'selected_area',
@@ -197,7 +160,6 @@ jQuery(document).ready(function($) { @@ -197,7 +160,6 @@ jQuery(document).ready(function($) {
197 } 160 }
198 //Register the content being selected at input.comment_paragraph_selected_content 161 //Register the content being selected at input.comment_paragraph_selected_content
199 var selected_content = getSelectionText(); 162 var selected_content = getSelectionText();
200 - if(selected_content.length > 0)  
201 if (form.find('input.selected_content').length === 0){ 163 if (form.find('input.selected_content').length === 0){
202 $('<input>').attr({ 164 $('<input>').attr({
203 class: 'selected_content', 165 class: 'selected_content',
@@ -209,6 +171,7 @@ jQuery(document).ready(function($) { @@ -209,6 +171,7 @@ jQuery(document).ready(function($) {
209 form.find('input.selected_content').val(selected_content) 171 form.find('input.selected_content').val(selected_content)
210 } 172 }
211 rootElement.focus(); 173 rootElement.focus();
  174 + cssApplier.toggleSelection();
212 }); 175 });
213 176
214 function processAnchor(){ 177 function processAnchor(){
@@ -216,16 +179,14 @@ jQuery(document).ready(function($) { @@ -216,16 +179,14 @@ jQuery(document).ready(function($) {
216 if(anchor.length==0) return; 179 if(anchor.length==0) return;
217 var val = anchor.split('-'); //anchor format = #comment-\d+ 180 var val = anchor.split('-'); //anchor format = #comment-\d+
218 if(val.length!=2 || val[0]!='#comment') return; 181 if(val.length!=2 || val[0]!='#comment') return;
219 - if($('div[data-macro=comment_paragraph_plugin\\/allow_comment]').length==0) return; //comment_paragraph_plugin/allow_comment div must exists 182 + if($('.comment-paragraph-plugin').length==0) return;
220 var comment_id = val[1]; 183 var comment_id = val[1];
221 if(!/^\d+$/.test(comment_id)) return; //test for integer 184 if(!/^\d+$/.test(comment_id)) return; //test for integer
222 - comment_paragraph_anchor = anchor; 185 +
223 var url = '/plugin/comment_paragraph/public/comment_paragraph/'+comment_id; 186 var url = '/plugin/comment_paragraph/public/comment_paragraph/'+comment_id;
224 - $.ajax({  
225 - dataType: "script",  
226 - url: url  
227 - }).done(function() {  
228 - var button = $('#page-comment-form-' + comment_id + ' a').get(0) 187 + $.ajax(url).done(function(data) {
  188 + var button = $('#comment-paragraph-plugin_' + data.paragraph_uuid + ' .side-comments-counter').click();
  189 + $('body').animate({scrollTop: parseInt(button.offset().top)}, 500);
229 button.click(); 190 button.click();
230 }); 191 });
231 } 192 }
@@ -234,8 +195,8 @@ jQuery(document).ready(function($) { @@ -234,8 +195,8 @@ jQuery(document).ready(function($) {
234 195
235 $(document).on('mouseenter', 'li.article-comment', function() { 196 $(document).on('mouseenter', 'li.article-comment', function() {
236 var selected_area = $(this).find('input.paragraph_comment_area').val(); 197 var selected_area = $(this).find('input.paragraph_comment_area').val();
237 - var paragraph_id = $(this).find('input.paragraph_id').val();  
238 - var rootElement = $('#comment_paragraph_' + paragraph_id).get(0); 198 + var container = $(this).closest('.comment-paragraph-plugin');
  199 + var rootElement = container.find('.comment_paragraph')[0];
239 200
240 if(selected_area != ""){ 201 if(selected_area != ""){
241 rangy.deserializeSelection(selected_area, rootElement); 202 rangy.deserializeSelection(selected_area, rootElement);
@@ -244,30 +205,6 @@ jQuery(document).ready(function($) { @@ -244,30 +205,6 @@ jQuery(document).ready(function($) {
244 }); 205 });
245 206
246 $(document).on('mouseleave', 'li.article-comment', function() { 207 $(document).on('mouseleave', 'li.article-comment', function() {
247 - var paragraph_id = $(this).find('input.paragraph_id').val();  
248 - var rootElement = $('#comment_paragraph_'+ paragraph_id).get(0);  
249 -  
250 - original_paragraphs.each( function(paragraph) {  
251 - if (paragraph.id == paragraph_id) {  
252 - rootElement.innerHTML = paragraph.content;  
253 - }  
254 - }); 208 + hideAllSelectedAreasExcept();
255 }); 209 });
256 -  
257 - function toggleParagraph(paragraph) {  
258 - var div = $('div.comments_list_toggle_paragraph_'+paragraph);  
259 - var visible = div.is(':visible');  
260 - if(!visible)  
261 - $('div.comment-paragraph-loading-' + paragraph).addClass('comment-button-loading');  
262 - div.toggle('fast');  
263 - return visible;  
264 - }  
265 -  
266 - function loadCompleted(paragraph) {  
267 - $('div.comment-paragraph-loading-'+paragraph).removeClass('comment-button-loading')  
268 - if(comment_paragraph_anchor) {  
269 - $.scrollTo($(comment_paragraph_anchor));  
270 - comment_paragraph_anchor = null;  
271 - }  
272 - }  
273 }); 210 });
plugins/comment_paragraph/public/images/balloons-comment.png

671 Bytes

plugins/comment_paragraph/public/style.css
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 width: 90px; 9 width: 90px;
10 text-decoration: none; 10 text-decoration: none;
11 visibility: hidden; 11 visibility: hidden;
  12 + cursor: pointer;
12 } 13 }
13 14
14 div.article-comments-list-more{ 15 div.article-comments-list-more{
@@ -53,15 +54,15 @@ div.article-comments-list-more{ @@ -53,15 +54,15 @@ div.article-comments-list-more{
53 padding:15px; 54 padding:15px;
54 margin:1em 0 3em; 55 margin:1em 0 3em;
55 color:#fff; 56 color:#fff;
56 - background:#075698; /* default background for browsers without gradient support */ 57 + background:#717171; /* default background for browsers without gradient support */
57 /* css3 */ 58 /* css3 */
58 - background:-webkit-gradient(linear, 0 0, 0 100%, from(#ababab), to(#424242));  
59 - background:-moz-linear-gradient(#ABABAB, #424242);  
60 - background:-o-linear-gradient(#ABABAB, #424242);  
61 - background: linear-gradient(#ABABAB, #424242);  
62 - -webkit-border-radius:10px;  
63 - -moz-border-radius:10px;  
64 - border-radius:10px; 59 + background:-webkit-gradient(linear, 0 0, 0 100%, from(#717171), to(#1F1F1F));
  60 + background:-moz-linear-gradient(#717171, #1F1F1F);
  61 + background:-o-linear-gradient(#717171, #1F1F1F);
  62 + background: linear-gradient(#717171, #1F1F1F);
  63 + -webkit-border-radius:8px;
  64 + -moz-border-radius:8px;
  65 + border-radius:8px;
65 font-weight: bold; 66 font-weight: bold;
66 } 67 }
67 68
@@ -72,7 +73,7 @@ div.article-comments-list-more{ @@ -72,7 +73,7 @@ div.article-comments-list-more{
72 left: 50px; 73 left: 50px;
73 border-width: 20px 0 0 20px; 74 border-width: 20px 0 0 20px;
74 border-style: solid; 75 border-style: solid;
75 - border-color: #424242 transparent; 76 + border-color: #1F1F1F transparent;
76 display: block; 77 display: block;
77 width: 0; 78 width: 0;
78 } 79 }
@@ -99,21 +100,17 @@ div.article-comments-list-more{ @@ -99,21 +100,17 @@ div.article-comments-list-more{
99 } 100 }
100 101
101 .side-comment .comment-created-at{display: none;} 102 .side-comment .comment-created-at{display: none;}
102 -.side-comment #comment_title{display: none;}  
103 -.side-comment .comment_title{display: none;} 103 +.side-comment #comment_title, .side-comment .comment_title{display: none;}
104 .side-comment label[for="comment_title"] {display: none;} 104 .side-comment label[for="comment_title"] {display: none;}
105 105
106 -div[class^='comments_list_toggle_paragraph_'] {  
107 - border-style: solid;  
108 - border-width: 1px;  
109 - border-color: #e7e7e7;  
110 - padding: 5px;  
111 - background-color: whitesmoke;  
112 - width: 280px;  
113 -}  
114 -  
115 -div[class^='comment-paragraph-loading-'] {  
116 - z-index: 99; 106 +.side-comment {
  107 + border-style: solid;
  108 + border-width: 1px;
  109 + border-color: #e7e7e7;
  110 + padding: 5px;
  111 + background-color: whitesmoke;
  112 + width: 280px;
  113 + display: none;
117 } 114 }
118 115
119 #content .side-comment .comment-balloon div[class^='comment-wrapper-']{ 116 #content .side-comment .comment-balloon div[class^='comment-wrapper-']{
@@ -172,12 +169,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -172,12 +169,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
172 left: 5px; 169 left: 5px;
173 border-style: solid; 170 border-style: solid;
174 border-width: 10px 5px 0; 171 border-width: 10px 5px 0;
175 - border-color: #bdbdbd transparent; 172 + border-color: #b5b5b5 transparent;
176 display: block; 173 display: block;
177 width: 0; 174 width: 0;
178 } 175 }
179 176
180 -.comment-count{ 177 +.comment-count-container {
181 position: relative; 178 position: relative;
182 top: 3px; 179 top: 3px;
183 } 180 }
@@ -231,9 +228,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -231,9 +228,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
231 .side-comment .comment-wrapper-1 { 228 .side-comment .comment-wrapper-1 {
232 margin-left: 36px; 229 margin-left: 36px;
233 } 230 }
234 -#article .side-comment .article-comments-list .comment-replies {  
235 - padding-left: 25px;  
236 -}  
237 #article .side-comment .comment-picture { 231 #article .side-comment .comment-picture {
238 width: 100%; 232 width: 100%;
239 height: auto; 233 height: auto;
@@ -246,9 +240,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -246,9 +240,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
246 .side-comment .formlabel[for='comment_body'] { 240 .side-comment .formlabel[for='comment_body'] {
247 display: none; 241 display: none;
248 } 242 }
249 -.side-comment > div > div {  
250 - background: #FFFFFF;  
251 -}  
252 .side-comment .comment_form p { 243 .side-comment .comment_form p {
253 display: none; 244 display: none;
254 } 245 }
@@ -257,7 +248,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -257,7 +248,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
257 padding-bottom: 15px; 248 padding-bottom: 15px;
258 } 249 }
259 250
260 -.side-comment .comment-count { 251 +.side-comment .comment-count-container {
261 bg-color: #b3b2d4; 252 bg-color: #b3b2d4;
262 } 253 }
263 254
@@ -265,22 +256,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -265,22 +256,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
265 height: 50px; 256 height: 50px;
266 } 257 }
267 258
268 -.comment-paragraph-comments{  
269 - background: lightblue;  
270 - padding: 5px;  
271 - width: 150px;  
272 - margin-top: 10px;  
273 - color: white;  
274 - font-weight: bold;  
275 - text-align: center;  
276 -}  
277 -  
278 .single-border{ 259 .single-border{
279 border-style: solid; 260 border-style: solid;
280 border-width: 2px; 261 border-width: 2px;
281 } 262 }
282 263
283 -.comment-paragraph-slide-left .comments { 264 +.comment-paragraph-plugin .comments {
284 position: relative; 265 position: relative;
285 display: table; 266 display: table;
286 } 267 }
@@ -289,7 +270,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -289,7 +270,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
289 background-color: rgb(236, 236, 236); 270 background-color: rgb(236, 236, 236);
290 } 271 }
291 272
292 -.comment-paragraph-group-comments{ 273 +.side-comment {
293 position: absolute; 274 position: absolute;
294 right: -296px; 275 right: -296px;
295 top: 0px; 276 top: 0px;
@@ -297,11 +278,11 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -297,11 +278,11 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
297 z-index: 199; 278 z-index: 199;
298 } 279 }
299 280
300 -.article-body.comment-paragraph-slide-left { 281 +.comment-paragraph-plugin.comment-paragraph-slide-left {
301 position: relative; 282 position: relative;
302 width: 80%; 283 width: 80%;
303 } 284 }
304 -.article-body { 285 +.comment-paragraph-plugin {
305 width: 100%; 286 width: 100%;
306 transition: width 0.3s ease-in-out; 287 transition: width 0.3s ease-in-out;
307 } 288 }
@@ -320,3 +301,44 @@ div[class^=&#39;comment-paragraph-loading-&#39;] { @@ -320,3 +301,44 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
320 padding-right: 10px; 301 padding-right: 10px;
321 margin-left: -36px; 302 margin-left: -36px;
322 } 303 }
  304 +
  305 +.comment-paragraph-plugin .no-comments-yet .comment-count {
  306 + display: none;
  307 +}
  308 +
  309 +.comment-paragraph-plugin .no-comments-yet:after {
  310 + content: "+";
  311 +}
  312 +#content .comment-paragraph-plugin .no-comments-yet {
  313 + font-size: 100%;
  314 + opacity: 1;
  315 +}
  316 +
  317 +#content .comment-paragraph-plugin .display-comment-form {
  318 + text-decoration: none;
  319 + color: gray;
  320 +}
  321 +
  322 +#content .comment-paragraph-plugin .display-comment-form:hover {
  323 + color: rgb(95, 95, 95);
  324 +}
  325 +
  326 +#content .comment-paragraph-plugin .side-comment .article-comments-list .comment-replies .comment-replies {
  327 + padding-left: 0;
  328 +}
  329 +#content .comment-paragraph-plugin .side-comment .article-comments-list .comment-replies {
  330 + padding-left: 25px;
  331 +}
  332 +
  333 +#content .comment-paragraph-plugin #cancel-comment, #content .comment-paragraph-plugin .icon-add {
  334 + background: none;
  335 + border: none;
  336 +}
  337 +#content .comment-paragraph-plugin #cancel-comment:hover, #content .comment-paragraph-plugin .icon-add:hover {
  338 + background: none;
  339 + color: black;
  340 + border: none;
  341 +}
  342 +#content .comment-paragraph-plugin .button-bar {
  343 + margin: 5px 0;
  344 +}
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_admin_controller_test.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/comment_paragraph_plugin_admin_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class CommentParagraphPluginAdminController; def rescue_action(e) raise e end; end
  6 +
  7 +class CommentParagraphPluginAdminControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @environment = Environment.default
  11 + user_login = create_admin_user(@environment)
  12 + login_as(user_login)
  13 + @environment.enabled_plugins = ['CommentParagraphPlugin']
  14 + @environment.save!
  15 + @plugin_settings = Noosfero::Plugin::Settings.new(@environment, CommentParagraphPlugin)
  16 + end
  17 + attr_reader :plugin_settings, :environment
  18 +
  19 + should 'access index action' do
  20 + get :index
  21 + assert_response :success
  22 + end
  23 +
  24 + should 'update comment paragraph plugin settings' do
  25 + assert_not_equal 'manual', plugin_settings.get_setting(:activation_mode)
  26 + post :index, :settings => { :activation_mode => 'manual' }
  27 + environment.reload
  28 + assert_equal 'manual', plugin_settings.get_setting(:activation_mode)
  29 + end
  30 +
  31 + should 'get article types previously selected' do
  32 + plugin_settings.activation_mode = 'manual'
  33 + plugin_settings.save!
  34 + get :index
  35 + assert_tag :input, :attributes => { :value => 'manual', :checked => 'checked' }
  36 + end
  37 +
  38 +end
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb
@@ -7,40 +7,32 @@ class CommentParagraphPluginProfileController; def rescue_action(e) raise e end; @@ -7,40 +7,32 @@ class CommentParagraphPluginProfileController; def rescue_action(e) raise e end;
7 class CommentParagraphPluginProfileControllerTest < ActionController::TestCase 7 class CommentParagraphPluginProfileControllerTest < ActionController::TestCase
8 8
9 def setup 9 def setup
10 - @controller = CommentParagraphPluginProfileController.new  
11 - @request = ActionController::TestRequest.new  
12 - @response = ActionController::TestResponse.new  
13 -  
14 @profile = create_user('testuser').person 10 @profile = create_user('testuser').person
15 @article = profile.articles.build(:name => 'test') 11 @article = profile.articles.build(:name => 'test')
16 @article.save! 12 @article.save!
17 end 13 end
18 - attr_reader :article  
19 - attr_reader :profile 14 + attr_reader :article, :profile
20 15
21 should 'be able to show paragraph comments' do 16 should 'be able to show paragraph comments' do
22 - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_id => 0)  
23 - xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_id => 0  
24 - assert_template 'comment_paragraph_plugin_profile/view_comments'  
25 - assert_match /comments_list_paragraph_0/, @response.body  
26 - assert_match /\"comment-count-0\", \"1\"/, @response.body 17 + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_uuid => 0)
  18 + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_uuid => 0
  19 + assert_select "#comment-#{comment.id}"
27 end 20 end
28 21
29 should 'do not show global comments' do 22 should 'do not show global comments' do
30 - fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :paragraph_id => nil)  
31 - fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_id => 0)  
32 - xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_id => 0  
33 - assert_template 'comment_paragraph_plugin_profile/view_comments'  
34 - assert_match /comments_list_paragraph_0/, @response.body  
35 - assert_match /\"comment-count-0\", \"1\"/, @response.body 23 + global_comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'global comment', :body => 'global', :paragraph_uuid => nil)
  24 + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_uuid => 0)
  25 + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_uuid => 0
  26 + assert_select "#comment-#{global_comment.id}", 0
  27 + assert_select "#comment-#{comment.id}"
36 end 28 end
37 29
38 should 'be able to show all comments of a paragraph' do 30 should 'be able to show all comments of a paragraph' do
39 - comment1 = fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'a comment', :paragraph_id => 0)  
40 - comment2 = fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :author_id => profile, :title => 'b comment', :body => 'b comment', :paragraph_id => 0)  
41 - comment3 = fast_create(Comment, :created_at => Time.now - 3.days, :source_id => article, :author_id => profile, :title => 'c comment', :body => 'c comment', :paragraph_id => 0)  
42 - comment4 = fast_create(Comment, :created_at => Time.now - 4.days, :source_id => article, :author_id => profile, :title => 'd comment', :body => 'd comment', :paragraph_id => 0)  
43 - xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_id => 0 31 + fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'a comment', :paragraph_uuid => 0)
  32 + fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :author_id => profile, :title => 'b comment', :body => 'b comment', :paragraph_uuid => 0)
  33 + fast_create(Comment, :created_at => Time.now - 3.days, :source_id => article, :author_id => profile, :title => 'c comment', :body => 'c comment', :paragraph_uuid => 0)
  34 + fast_create(Comment, :created_at => Time.now - 4.days, :source_id => article, :author_id => profile, :title => 'd comment', :body => 'd comment', :paragraph_uuid => 0)
  35 + xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :paragraph_uuid => 0
44 assert_match /a comment/, @response.body 36 assert_match /a comment/, @response.body
45 assert_match /b comment/, @response.body 37 assert_match /b comment/, @response.body
46 assert_match /c comment/, @response.body 38 assert_match /c comment/, @response.body
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_public_controller_test.rb
@@ -8,30 +8,23 @@ class CommentParagraphPluginPublicController; def rescue_action(e) raise e end; @@ -8,30 +8,23 @@ class CommentParagraphPluginPublicController; def rescue_action(e) raise e end;
8 class CommentParagraphPluginPublicControllerTest < ActionController::TestCase 8 class CommentParagraphPluginPublicControllerTest < ActionController::TestCase
9 9
10 def setup 10 def setup
11 - @controller = CommentParagraphPluginPublicController.new  
12 - @request = ActionController::TestRequest.new  
13 - @response = ActionController::TestResponse.new  
14 -  
15 @profile = create_user('testuser').person 11 @profile = create_user('testuser').person
16 @article = profile.articles.build(:name => 'test') 12 @article = profile.articles.build(:name => 'test')
17 @article.save! 13 @article.save!
18 end 14 end
19 - attr_reader :article  
20 - attr_reader :profile  
21 - 15 + attr_reader :article, :profile
22 16
23 - should 'be able to return paragraph_id for a comment' do  
24 - comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_id => 0) 17 + should 'be able to return paragraph_uuid for a comment' do
  18 + comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala', :paragraph_uuid => 0)
25 cid = comment.id 19 cid = comment.id
26 xhr :get, :comment_paragraph, :id => cid 20 xhr :get, :comment_paragraph, :id => cid
27 - assert_match /\{\"paragraph_id\":0\}/, @response.body 21 + assert_equal({'paragraph_uuid' => '0'}, ActiveSupport::JSON.decode(@response.body))
28 end 22 end
29 23
30 - should 'return paragraph_id=null for a global comment' do 24 + should 'return paragraph_uuid=null for a global comment' do
31 comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala' ) 25 comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala' )
32 xhr :get, :comment_paragraph, :id => comment.id 26 xhr :get, :comment_paragraph, :id => comment.id
33 - assert_match /\{\"paragraph_id\":null\}/, @response.body 27 + assert_equal({'paragraph_uuid' => nil}, ActiveSupport::JSON.decode(@response.body))
34 end 28 end
35 29
36 -  
37 end 30 end
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_test.rb
@@ -1,38 +0,0 @@ @@ -1,38 +0,0 @@
1 -require File.dirname(__FILE__) + '/../../../../test/test_helper'  
2 -require File.dirname(__FILE__) + '/../../controllers/comment_paragraph_plugin_admin_controller'  
3 -  
4 -# Re-raise errors caught by the controller.  
5 -class CommentParagraphPluginAdminController; def rescue_action(e) raise e end; end  
6 -  
7 -class CommentParagraphPluginAdminControllerTest < ActionController::TestCase  
8 -  
9 - def setup  
10 - @environment = Environment.default  
11 - user_login = create_admin_user(@environment)  
12 - login_as(user_login)  
13 - @environment.enabled_plugins = ['CommentParagraphPlugin']  
14 - @environment.save!  
15 - @plugin_settings = Noosfero::Plugin::Settings.new(@environment, CommentParagraphPlugin)  
16 - end  
17 -  
18 - should 'access index action' do  
19 - get :index  
20 - assert_template 'index'  
21 - assert_response :success  
22 - end  
23 -  
24 - should 'update comment paragraph plugin settings' do  
25 - assert_nil @plugin_settings.get_setting(:auto_marking_article_types)  
26 - post :index, :settings => { :auto_marking_article_types => ['TinyMceArticle'] }  
27 - @environment.reload  
28 - assert_not_nil @plugin_settings.get_setting(:auto_marking_article_types)  
29 - end  
30 -  
31 - should 'get article types previously selected' do  
32 - post :index, :settings => { :auto_marking_article_types => ['TinyMceArticle', 'TextileArticle'] }  
33 - get :index  
34 - assert_tag :input, :attributes => { :value => 'TinyMceArticle' }  
35 - assert_tag :input, :attributes => { :value => 'TextileArticle' }  
36 - end  
37 -  
38 -end  
plugins/comment_paragraph/test/functional/content_viewer_controller_test.rb
@@ -11,7 +11,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -11,7 +11,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
11 11
12 def setup 12 def setup
13 @profile = fast_create(Community) 13 @profile = fast_create(Community)
14 - @page = fast_create(Article, :profile_id => @profile.id, :body => "<div class=\"macro\" data-macro-paragraph_id=\"0\" data-macro='comment_paragraph_plugin/allow_comment' ></div>") 14 + @page = fast_create(Article, :profile_id => @profile.id, :body => "<div class=\"macro\" data-macro-paragraph_uuid=\"0\" data-macro='comment_paragraph_plugin/allow_comment' ></div>")
15 @environment = Environment.default 15 @environment = Environment.default
16 @environment.enable_plugin(CommentParagraphPlugin) 16 @environment.enable_plugin(CommentParagraphPlugin)
17 end 17 end
@@ -19,7 +19,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -19,7 +19,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
19 attr_reader :page 19 attr_reader :page
20 20
21 should 'parse article body and render comment paragraph view' do 21 should 'parse article body and render comment paragraph view' do
22 - comment1 = fast_create(Comment, :paragraph_id => 0, :source_id => page.id) 22 + comment1 = fast_create(Comment, :paragraph_uuid => 0, :source_id => page.id)
23 get :view_page, @page.url 23 get :view_page, @page.url
24 assert_tag 'div', :attributes => {:class => 'comment_paragraph'} 24 assert_tag 'div', :attributes => {:class => 'comment_paragraph'}
25 end 25 end
plugins/comment_paragraph/test/unit/allow_comment_test.rb
@@ -15,11 +15,11 @@ class AllowCommentTest &lt; ActiveSupport::TestCase @@ -15,11 +15,11 @@ class AllowCommentTest &lt; ActiveSupport::TestCase
15 should 'parse contents to include comment paragraph view' do 15 should 'parse contents to include comment paragraph view' do
16 profile = fast_create(Community) 16 profile = fast_create(Community)
17 article = fast_create(Article, :profile_id => profile.id) 17 article = fast_create(Article, :profile_id => profile.id)
18 - comment = fast_create(Comment, :paragraph_id => 1, :source_id => article.id) 18 + comment = fast_create(Comment, :paragraph_uuid => 1, :source_id => article.id)
19 inner_html = 'inner' 19 inner_html = 'inner'
20 - content = macro.parse({:paragraph_id => comment.paragraph_id}, inner_html, article) 20 + content = macro.parse({:paragraph_uuid => comment.paragraph_uuid}, inner_html, article)
21 21
22 - expects(:render).with({:partial => 'comment_paragraph_plugin_profile/comment_paragraph', :locals => {:paragraph_id => comment.paragraph_id, :article_id => article.id, :inner_html => inner_html, :count => 1, :profile_identifier => profile.identifier} }) 22 + expects(:render).with({:partial => 'comment_paragraph_plugin_profile/comment_paragraph', :locals => {:paragraph_uuid => comment.paragraph_uuid, :article_id => article.id, :inner_html => inner_html, :count => 1, :profile_identifier => profile.identifier} })
23 instance_eval(&content) 23 instance_eval(&content)
24 end 24 end
25 25
plugins/comment_paragraph/test/unit/article_test.rb
@@ -6,21 +6,37 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -6,21 +6,37 @@ class ArticleTest &lt; ActiveSupport::TestCase
6 def setup 6 def setup
7 profile = fast_create(Community) 7 profile = fast_create(Community)
8 @article = fast_create(Article, :profile_id => profile.id) 8 @article = fast_create(Article, :profile_id => profile.id)
  9 + @environment = Environment.default
  10 + @environment.enable_plugin(CommentParagraphPlugin)
9 end 11 end
10 12
11 - attr_reader :article 13 + attr_reader :article, :environment
12 14
13 should 'return paragraph comments from article' do 15 should 'return paragraph comments from article' do
14 - comment1 = fast_create(Comment, :paragraph_id => 1, :source_id => article.id)  
15 - comment2 = fast_create(Comment, :paragraph_id => nil, :source_id => article.id) 16 + comment1 = fast_create(Comment, :paragraph_uuid => 1, :source_id => article.id)
  17 + comment2 = fast_create(Comment, :paragraph_uuid => nil, :source_id => article.id)
16 assert_equal [comment1], article.paragraph_comments 18 assert_equal [comment1], article.paragraph_comments
17 end 19 end
18 20
19 should 'allow save if comment paragraph macro is not removed for paragraph with comments' do 21 should 'allow save if comment paragraph macro is not removed for paragraph with comments' do
20 - article.body = "<div class=\"macro\" data-macro-paragraph_id=0></div>"  
21 - comment1 = fast_create(Comment, :paragraph_id => 0, :source_id => article.id) 22 + article.body = "<div class=\"macro\" data-macro-paragraph_uuid=0></div>"
  23 + comment1 = fast_create(Comment, :paragraph_uuid => 0, :source_id => article.id)
22 assert article.save 24 assert article.save
23 end 25 end
24 26
  27 + should 'not parse html if the plugin is not enabled' do
  28 + article.body = "<p>paragraph 1</p><p>paragraph 2</p>"
  29 + environment.disable_plugin(CommentParagraphPlugin)
  30 + assert !environment.plugin_enabled?(CommentParagraphPlugin)
  31 + article.save!
  32 + assert_equal "<p>paragraph 1</p><p>paragraph 2</p>", article.body
  33 + end
  34 +
  35 + should 'parse html if the plugin is not enabled' do
  36 + article.body = "<p>paragraph 1</p><p>paragraph 2</p>"
  37 + article.expects(:comment_paragraph_plugin_enabled?).returns(true)
  38 + article.save!
  39 + assert_match /data-macro='comment_paragraph_plugin\/allow_comment'/, article.body
  40 + end
25 41
26 end 42 end
plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb
@@ -29,9 +29,9 @@ class CommentParagraphPluginTest &lt; ActiveSupport::TestCase @@ -29,9 +29,9 @@ class CommentParagraphPluginTest &lt; ActiveSupport::TestCase
29 should 'not add comment_paragraph_selected_area if comment_paragraph_selected_area is blank' do 29 should 'not add comment_paragraph_selected_area if comment_paragraph_selected_area is blank' do
30 comment = Comment.new 30 comment = Comment.new
31 comment.comment_paragraph_selected_area = "" 31 comment.comment_paragraph_selected_area = ""
32 - comment.paragraph_id = 2 32 + comment.paragraph_uuid = 2
33 cpp = CommentParagraphPlugin.new 33 cpp = CommentParagraphPlugin.new
34 - prok = cpp.comment_form_extra_contents({:comment=>comment, :paragraph_id=>4}) 34 + prok = cpp.comment_form_extra_contents({:comment=>comment, :paragraph_uuid=>4})
35 assert_nil /comment_paragraph_selected_area/.match(prok.call.inspect) 35 assert_nil /comment_paragraph_selected_area/.match(prok.call.inspect)
36 end 36 end
37 37
plugins/comment_paragraph/test/unit/comment_test.rb
@@ -10,16 +10,16 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -10,16 +10,16 @@ class CommentTest &lt; ActiveSupport::TestCase
10 attr_reader :article 10 attr_reader :article
11 11
12 should 'return comments that belongs to a specified paragraph' do 12 should 'return comments that belongs to a specified paragraph' do
13 - comment1 = fast_create(Comment, :paragraph_id => 1, :source_id => article.id)  
14 - comment2 = fast_create(Comment, :paragraph_id => nil, :source_id => article.id)  
15 - comment3 = fast_create(Comment, :paragraph_id => 2, :source_id => article.id)  
16 - assert_equal [comment1], article.comments.in_paragraph(1) 13 + comment1 = fast_create(Comment, :paragraph_uuid => '1', :source_id => article.id)
  14 + comment2 = fast_create(Comment, :paragraph_uuid => nil, :source_id => article.id)
  15 + comment3 = fast_create(Comment, :paragraph_uuid => '2', :source_id => article.id)
  16 + assert_equal [comment1], article.comments.in_paragraph('1')
17 end 17 end
18 18
19 should 'return comments that do not belongs to any paragraph' do 19 should 'return comments that do not belongs to any paragraph' do
20 - comment1 = fast_create(Comment, :paragraph_id => 1, :source_id => article.id)  
21 - comment2 = fast_create(Comment, :paragraph_id => nil, :source_id => article.id)  
22 - comment3 = fast_create(Comment, :paragraph_id => 2, :source_id => article.id) 20 + comment1 = fast_create(Comment, :paragraph_uuid => '1', :source_id => article.id)
  21 + comment2 = fast_create(Comment, :paragraph_uuid => nil, :source_id => article.id)
  22 + comment3 = fast_create(Comment, :paragraph_uuid => '2', :source_id => article.id)
23 assert_equal [comment2], article.comments.without_paragraph 23 assert_equal [comment2], article.comments.without_paragraph
24 end 24 end
25 25
plugins/comment_paragraph/views/comment/comment_extra.html.erb
1 <input type="hidden" value="<%= comment.comment_paragraph_selected_area%>" class="paragraph_comment_area" /> 1 <input type="hidden" value="<%= comment.comment_paragraph_selected_area%>" class="paragraph_comment_area" />
2 -<input type="hidden" value="<%= comment.paragraph_id%>" class="paragraph_id" /><input type="hidden" value="<%= comment.comment_paragraph_selected_content%>" class="paragraph_selected_content" /> 2 +<input type="hidden" value="<%= comment.paragraph_uuid%>" class="paragraph_uuid" /><input type="hidden" value="<%= comment.comment_paragraph_selected_content%>" class="paragraph_selected_content" />
3 <input type="hidden" value="<%= comment.comment_paragraph_selected_content%>" class="paragraph_selected_content" /> 3 <input type="hidden" value="<%= comment.comment_paragraph_selected_content%>" class="paragraph_selected_content" />
plugins/comment_paragraph/views/comment_paragraph_plugin_admin/index.html.erb
1 -<% extend CommentParagraphPlugin::CommentParagraphHelper %> 1 +<div class="comment-paragraph-plugin-settings">
  2 + <h1><%= _("Comment Paragraph Plugin Settings") %></h1>
2 3
3 -<h1><%= _("Comment paragraph plugin settings") %></h1> 4 + <%= form_for(:settings) do |f| %>
4 5
5 -<%= form_for(:settings) do |f| %> 6 + <div class="activation-mode">
  7 + <h4><%= _('Activation Mode') %></h4>
  8 + <div class="auto">
  9 + <%= f.radio_button(:activation_mode, 'auto') %> <%= _('Auto') %>
  10 + </div>
  11 + <div>
  12 + <%= f.radio_button(:activation_mode, 'manual') %> <%= _('Manual') %>
  13 + </div>
  14 + </div>
6 15
7 -<%= hidden_field_tag 'settings[auto_marking_article_types][]' %> 16 + <% button_bar do %>
  17 + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %>
  18 + <% end %>
8 19
9 -<table id="auto_marking_article_types_conf" border="0">  
10 - <tr>  
11 - <th align="left"><%= _('Article type') %></th>  
12 - <th><%= _('Automatic marking active') %></th>  
13 - </tr>  
14 - <tr style="background-color: #EEE; border-bottom: 2px solid #000;">  
15 - <td><span style="font-style: italic;"><%= _('Check/Uncheck All') %></span></td>  
16 - <td align="center"><%= check_box_tag 'article_active', '' %></td>  
17 - </tr>  
18 - <% @article_types.each do |type| %>  
19 - <tr>  
20 - <td><%= _(type[:short_description]) %></td>  
21 - <td align="center"><%= check_box_tag 'settings[auto_marking_article_types][]', type[:class_name], auto_marking_enabled?(@settings, type[:class_name]) %></td>  
22 - </tr>  
23 <% end %> 20 <% end %>
24 -</table>  
25 -  
26 - <% button_bar do %>  
27 - <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %>  
28 - <% end %>  
29 -  
30 -<% end %>  
31 -  
32 -<%= javascript_include_tag 'plugins/comment_paragraph/comment_paragraph_admin' %> 21 +</div>
plugins/comment_paragraph/views/comment_paragraph_plugin_profile/_comment_paragraph.html.erb
1 -<div class="comment-paragraph-plugin comments">  
2 - <div class="comment_paragraph" id="comment_paragraph_<%= paragraph_id %>" data-paragraph="<%= paragraph_id %>"> 1 +<div class="comment-paragraph-plugin comments" id="comment-paragraph-plugin_<%= paragraph_uuid %>" data-paragraph="<%= paragraph_uuid %>">
  2 + <div class="comment_paragraph">
3 <%= inner_html %> 3 <%= inner_html %>
4 </div> 4 </div>
5 <div class="side-comments-counter-container"> 5 <div class="side-comments-counter-container">
6 - <div class="side-comments-counter" id="side_comments_counter_<%= paragraph_id %>" data-paragraph="<%= paragraph_id %>">  
7 - <span id="comment-count-<%= paragraph_id %>" class='comment-count'>  
8 - <%= count %> 6 + <div class="side-comments-counter">
  7 + <span class='comment-count-container <%= count==0 ? 'no-comments-yet':'' %>'>
  8 + <span class="comment-count"><%= count %></span>
9 </span> 9 </span>
10 </div> 10 </div>
11 </div> 11 </div>
12 -<div class="comment-paragraph-group-comments">  
13 - <%=  
14 - url = { :profile => profile_identifier, :controller => 'comment_paragraph_plugin_profile', :action => 'view_comments', :paragraph_id => paragraph_id, :article_id => article_id}  
15 - link_to_remote(  
16 - '',  
17 - {  
18 - :url => url,  
19 - :method => :post,  
20 - :condition => "!toggleParagraph(#{paragraph_id})",  
21 - :complete => "loadCompleted(#{paragraph_id})"  
22 - },  
23 - {  
24 - :id => "link_to_ajax_comments_#{paragraph_id}",  
25 - :'data-url' => url_for(url)  
26 - }  
27 - )%>  
28 12
29 - <div class="side-comment" id="side_comment_<%= paragraph_id %>" data-paragraph="<%= paragraph_id %>" style="display:none">  
30 - <div class="comment-paragraph-loading-<%= paragraph_id %>">  
31 - <div class="comments_list_toggle_paragraph_<%= paragraph_id %>" >  
32 - <div class="article-comments-list" id="comments_list_paragraph_<%= paragraph_id %>">  
33 - <div class="loading"></div>  
34 - </div>  
35 - <div class ="article-comments-list-more" id="comments_list_paragraph_<%= paragraph_id %>_more"></div>  
36 - <div id="page-comment-form-<%= paragraph_id %>" class='post_comment_box closed'>  
37 - <%= render :partial => 'comment/comment_form', :locals => {:comment => Comment.new, :display_link => true, :cancel_triggers_hide => true, :paragraph_id => paragraph_id}%>  
38 - </div>  
39 - </div>  
40 - </div> 13 + <% load_comments_url = url_for({:profile => profile_identifier, :controller => 'comment_paragraph_plugin_profile', :action => 'view_comments', :paragraph_uuid => paragraph_uuid, :article_id => article_id}) %>
  14 +
  15 + <div class="side-comment" data-comment_paragraph_url="<%= load_comments_url %>">
  16 + <div class="article-comments-list">
  17 + <div class="loading"></div>
  18 + </div>
  19 + <div class ="article-comments-list-more"></div>
  20 + <div class='post_comment_box closed'>
  21 + <%= render :partial => 'comment/comment_form', :locals => {:comment => Comment.new, :display_link => true, :cancel_triggers_hide => true, :paragraph_uuid => paragraph_uuid}%>
  22 + </div>
41 </div> 23 </div>
42 </div> 24 </div>
43 -</div>  
44 -  
45 -  
46 -  
47 -  
48 -  
plugins/comment_paragraph/views/comment_paragraph_plugin_profile/view_comments.rjs
@@ -1,2 +0,0 @@ @@ -1,2 +0,0 @@
1 -page.replace_html "comments_list_paragraph_#{@paragraph_id}", :partial => 'comment/comment.html.erb', :collection => @comments  
2 -page.replace_html "comment-count-#{@paragraph_id}", @comments_count