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 3  
4 4 def index
5 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 6 if request.post?
16   - @settings.settings[:auto_marking_article_types].reject! { |type| type.blank? }
17 7 @settings.save!
18   - redirect_to :controller => 'plugins', :action => 'index'
  8 + session[:notice] = _('Settings successfuly saved')
19 9 end
20 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 12 end
... ...
plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb
... ... @@ -3,11 +3,12 @@ class CommentParagraphPluginProfileController < ProfileController
3 3  
4 4 def view_comments
5 5 @article_id = params[:article_id]
6   - @paragraph_id = params[:paragraph_id]
  6 + @paragraph_uuid = params[:paragraph_uuid]
7 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 9 @comments_count = @comments.count
10 10 @comments = @comments.without_reply
  11 + render :partial => 'comment/comment.html.erb', :collection => @comments
11 12 end
12 13  
13 14 end
... ...
plugins/comment_paragraph/controllers/public/comment_paragraph_plugin_public_controller.rb
... ... @@ -3,7 +3,7 @@ class CommentParagraphPluginPublicController < PublicController
3 3  
4 4 def comment_paragraph
5 5 @comment = Comment.find(params[:id])
6   - render :json => { :paragraph_id => @comment.paragraph_id }
  6 + render :json => { :paragraph_uuid => @comment.paragraph_uuid }
7 7 end
8 8  
9 9 end
... ...
plugins/comment_paragraph/db/migrate/20140715201649_add_paragraph_id_to_comment.rb
... ... @@ -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 @@
  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 14  
15 15 def comment_form_extra_contents(args)
16 16 comment = args[:comment]
17   - paragraph_id = comment.paragraph_id || args[:paragraph_id]
  17 + paragraph_uuid = comment.paragraph_uuid || args[:paragraph_uuid]
18 18 proc {
19 19 arr = []
20 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 22 arr << hidden_field_tag('comment[comment_paragraph_selected_area]', comment.comment_paragraph_selected_area) unless comment.comment_paragraph_selected_area.blank?
23 23 arr << hidden_field_tag('comment[comment_paragraph_selected_content]', comment.comment_paragraph_selected_content) unless comment.comment_paragraph_selected_content.blank?
24 24 arr
... ... @@ -40,54 +40,8 @@ class CommentParagraphPlugin &lt; Noosfero::Plugin
40 40 true
41 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 45 end
92 46  
93 47 end
... ...
plugins/comment_paragraph/lib/comment_paragraph_plugin/comment_paragraph_helper.rb
... ... @@ -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 3 class CommentParagraphPlugin::AllowComment < Noosfero::Plugin::Macro
  4 +
5 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 7 end
13 8  
14 9 def parse(params, inner_html, source)
15   - paragraph_id = params[:paragraph_id].to_i
  10 + paragraph_uuid = params[:paragraph_uuid]
16 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 14 proc {
20 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 18 end
24 19 end
... ...
plugins/comment_paragraph/lib/ext/article.rb
... ... @@ -2,16 +2,54 @@ require_dependency &#39;article&#39;
2 2  
3 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 41 end
14 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 2  
3 3 class Comment
4 4  
5   - scope :without_paragraph, :conditions => {:paragraph_id => nil }
  5 + scope :without_paragraph, :conditions => {:paragraph_uuid => nil }
6 6  
7 7 settings_items :comment_paragraph_selected_area, :type => :string
8 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 17 before_validation do |comment|
18 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   -div.article_comments {
2   - background-color:#dddddd;
3   - border-style: solid;
4   - border-color:#bbbbbb;
5   - border-width:2px;
6   -}
7 0 \ No newline at end of file
plugins/comment_paragraph/public/comment_paragraph.js
... ... @@ -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   -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 1 jQuery(document).ready(function($) {
15 2 //Quit if does not detect a comment for that plugin
16 3 if($('.comment_paragraph').size() < 1)
17 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 6 $(document).keyup(function(e) {
29 7 // on press ESC key...
30 8 if (e.which == 27) {
31   - // closing side comment box
32 9 hideCommentBox();
33 10 }
34 11 });
35 12  
36   - setPlusIfZeroComments($);
37 13 $('.display-comment-form').unbind();
38 14 $('.display-comment-form').click(function(){
39 15 var $button = $(this);
... ... @@ -49,15 +25,18 @@ jQuery(document).ready(function($) {
49 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 37 function hideCommentBox() {
59 38 $("div.side-comment").hide();
60   - $('.article-body').removeClass('comment-paragraph-slide-left');
  39 + $('.comment-paragraph-plugin').removeClass('comment-paragraph-slide-left');
61 40 $('.comments').removeClass('selected');
62 41 }
63 42  
... ... @@ -76,60 +55,47 @@ jQuery(document).ready(function($) {
76 55 <div align="center" class="triangle-right" >Comentar</div>\
77 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 61 hideAllSelectedAreasExcept(paragraphId);
83 62 hideCommentBox();
84   - $(this).closest('.comments').addClass('selected');
85   - $('.article-body').addClass('comment-paragraph-slide-left');
86   - $('#side_comment_' + paragraphId).show();
87 63 $('#comment-bubble').removeClass('visible');
  64 + container.addClass('comment-paragraph-slide-left selected');
  65 + container.find('.side-comment').show();
88 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 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 93 function hideAllSelectedAreasExcept(clickedParagraph){
129 94 $(".comment_paragraph").each(function(){
130   - paragraph = $(this).data('paragraph');
  95 + paragraph = $(this).closest('.comment-paragraph-plugin').data('paragraph');
131 96 if(paragraph != clickedParagraph){
132 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 120 //highlight area from the paragraph
155 121 $('.comment_paragraph').mouseup(function(event) {
156 122  
157   - if($('.comment-paragraph-slide-left').size() > 0){
158   - hideCommentBox();
159   - }
  123 + hideCommentBox();
160 124  
161 125 //Don't do anything if there is no selected text
162 126 if (getSelectionText().length == 0) {
163 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 133 setCommentBubblePosition( event.pageX, event.pageY );
169 134  
170 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 137 $("#comment-bubble").addClass('visible');
175 138  
176 139 var rootElement = $(this).get(0);
... ... @@ -182,9 +145,9 @@ jQuery(document).ready(function($) {
182 145 } catch(e) {
183 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 151 if (form.find('input.selected_area').length === 0){
189 152 $('<input>').attr({
190 153 class: 'selected_area',
... ... @@ -197,7 +160,6 @@ jQuery(document).ready(function($) {
197 160 }
198 161 //Register the content being selected at input.comment_paragraph_selected_content
199 162 var selected_content = getSelectionText();
200   - if(selected_content.length > 0)
201 163 if (form.find('input.selected_content').length === 0){
202 164 $('<input>').attr({
203 165 class: 'selected_content',
... ... @@ -209,6 +171,7 @@ jQuery(document).ready(function($) {
209 171 form.find('input.selected_content').val(selected_content)
210 172 }
211 173 rootElement.focus();
  174 + cssApplier.toggleSelection();
212 175 });
213 176  
214 177 function processAnchor(){
... ... @@ -216,16 +179,14 @@ jQuery(document).ready(function($) {
216 179 if(anchor.length==0) return;
217 180 var val = anchor.split('-'); //anchor format = #comment-\d+
218 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 183 var comment_id = val[1];
221 184 if(!/^\d+$/.test(comment_id)) return; //test for integer
222   - comment_paragraph_anchor = anchor;
  185 +
223 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 190 button.click();
230 191 });
231 192 }
... ... @@ -234,8 +195,8 @@ jQuery(document).ready(function($) {
234 195  
235 196 $(document).on('mouseenter', 'li.article-comment', function() {
236 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 201 if(selected_area != ""){
241 202 rangy.deserializeSelection(selected_area, rootElement);
... ... @@ -244,30 +205,6 @@ jQuery(document).ready(function($) {
244 205 });
245 206  
246 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 9 width: 90px;
10 10 text-decoration: none;
11 11 visibility: hidden;
  12 + cursor: pointer;
12 13 }
13 14  
14 15 div.article-comments-list-more{
... ... @@ -53,15 +54,15 @@ div.article-comments-list-more{
53 54 padding:15px;
54 55 margin:1em 0 3em;
55 56 color:#fff;
56   - background:#075698; /* default background for browsers without gradient support */
  57 + background:#717171; /* default background for browsers without gradient support */
57 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 66 font-weight: bold;
66 67 }
67 68  
... ... @@ -72,7 +73,7 @@ div.article-comments-list-more{
72 73 left: 50px;
73 74 border-width: 20px 0 0 20px;
74 75 border-style: solid;
75   - border-color: #424242 transparent;
  76 + border-color: #1F1F1F transparent;
76 77 display: block;
77 78 width: 0;
78 79 }
... ... @@ -99,21 +100,17 @@ div.article-comments-list-more{
99 100 }
100 101  
101 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 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 116 #content .side-comment .comment-balloon div[class^='comment-wrapper-']{
... ... @@ -172,12 +169,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
172 169 left: 5px;
173 170 border-style: solid;
174 171 border-width: 10px 5px 0;
175   - border-color: #bdbdbd transparent;
  172 + border-color: #b5b5b5 transparent;
176 173 display: block;
177 174 width: 0;
178 175 }
179 176  
180   -.comment-count{
  177 +.comment-count-container {
181 178 position: relative;
182 179 top: 3px;
183 180 }
... ... @@ -231,9 +228,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
231 228 .side-comment .comment-wrapper-1 {
232 229 margin-left: 36px;
233 230 }
234   -#article .side-comment .article-comments-list .comment-replies {
235   - padding-left: 25px;
236   -}
237 231 #article .side-comment .comment-picture {
238 232 width: 100%;
239 233 height: auto;
... ... @@ -246,9 +240,6 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
246 240 .side-comment .formlabel[for='comment_body'] {
247 241 display: none;
248 242 }
249   -.side-comment > div > div {
250   - background: #FFFFFF;
251   -}
252 243 .side-comment .comment_form p {
253 244 display: none;
254 245 }
... ... @@ -257,7 +248,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
257 248 padding-bottom: 15px;
258 249 }
259 250  
260   -.side-comment .comment-count {
  251 +.side-comment .comment-count-container {
261 252 bg-color: #b3b2d4;
262 253 }
263 254  
... ... @@ -265,22 +256,12 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
265 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 259 .single-border{
279 260 border-style: solid;
280 261 border-width: 2px;
281 262 }
282 263  
283   -.comment-paragraph-slide-left .comments {
  264 +.comment-paragraph-plugin .comments {
284 265 position: relative;
285 266 display: table;
286 267 }
... ... @@ -289,7 +270,7 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
289 270 background-color: rgb(236, 236, 236);
290 271 }
291 272  
292   -.comment-paragraph-group-comments{
  273 +.side-comment {
293 274 position: absolute;
294 275 right: -296px;
295 276 top: 0px;
... ... @@ -297,11 +278,11 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
297 278 z-index: 199;
298 279 }
299 280  
300   -.article-body.comment-paragraph-slide-left {
  281 +.comment-paragraph-plugin.comment-paragraph-slide-left {
301 282 position: relative;
302 283 width: 80%;
303 284 }
304   -.article-body {
  285 +.comment-paragraph-plugin {
305 286 width: 100%;
306 287 transition: width 0.3s ease-in-out;
307 288 }
... ... @@ -320,3 +301,44 @@ div[class^=&#39;comment-paragraph-loading-&#39;] {
320 301 padding-right: 10px;
321 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 @@
  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 7 class CommentParagraphPluginProfileControllerTest < ActionController::TestCase
8 8  
9 9 def setup
10   - @controller = CommentParagraphPluginProfileController.new
11   - @request = ActionController::TestRequest.new
12   - @response = ActionController::TestResponse.new
13   -
14 10 @profile = create_user('testuser').person
15 11 @article = profile.articles.build(:name => 'test')
16 12 @article.save!
17 13 end
18   - attr_reader :article
19   - attr_reader :profile
  14 + attr_reader :article, :profile
20 15  
21 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 20 end
28 21  
29 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 28 end
37 29  
38 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 36 assert_match /a comment/, @response.body
45 37 assert_match /b comment/, @response.body
46 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 8 class CommentParagraphPluginPublicControllerTest < ActionController::TestCase
9 9  
10 10 def setup
11   - @controller = CommentParagraphPluginPublicController.new
12   - @request = ActionController::TestRequest.new
13   - @response = ActionController::TestResponse.new
14   -
15 11 @profile = create_user('testuser').person
16 12 @article = profile.articles.build(:name => 'test')
17 13 @article.save!
18 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 19 cid = comment.id
26 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 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 25 comment = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'lalala' )
32 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 28 end
35 29  
36   -
37 30 end
... ...
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_test.rb
... ... @@ -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 11  
12 12 def setup
13 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 15 @environment = Environment.default
16 16 @environment.enable_plugin(CommentParagraphPlugin)
17 17 end
... ... @@ -19,7 +19,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
19 19 attr_reader :page
20 20  
21 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 23 get :view_page, @page.url
24 24 assert_tag 'div', :attributes => {:class => 'comment_paragraph'}
25 25 end
... ...
plugins/comment_paragraph/test/unit/allow_comment_test.rb
... ... @@ -15,11 +15,11 @@ class AllowCommentTest &lt; ActiveSupport::TestCase
15 15 should 'parse contents to include comment paragraph view' do
16 16 profile = fast_create(Community)
17 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 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 23 instance_eval(&content)
24 24 end
25 25  
... ...
plugins/comment_paragraph/test/unit/article_test.rb
... ... @@ -6,21 +6,37 @@ class ArticleTest &lt; ActiveSupport::TestCase
6 6 def setup
7 7 profile = fast_create(Community)
8 8 @article = fast_create(Article, :profile_id => profile.id)
  9 + @environment = Environment.default
  10 + @environment.enable_plugin(CommentParagraphPlugin)
9 11 end
10 12  
11   - attr_reader :article
  13 + attr_reader :article, :environment
12 14  
13 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 18 assert_equal [comment1], article.paragraph_comments
17 19 end
18 20  
19 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 24 assert article.save
23 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 42 end
... ...
plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb
... ... @@ -29,9 +29,9 @@ class CommentParagraphPluginTest &lt; ActiveSupport::TestCase
29 29 should 'not add comment_paragraph_selected_area if comment_paragraph_selected_area is blank' do
30 30 comment = Comment.new
31 31 comment.comment_paragraph_selected_area = ""
32   - comment.paragraph_id = 2
  32 + comment.paragraph_uuid = 2
33 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 35 assert_nil /comment_paragraph_selected_area/.match(prok.call.inspect)
36 36 end
37 37  
... ...
plugins/comment_paragraph/test/unit/comment_test.rb
... ... @@ -10,16 +10,16 @@ class CommentTest &lt; ActiveSupport::TestCase
10 10 attr_reader :article
11 11  
12 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 17 end
18 18  
19 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 23 assert_equal [comment2], article.comments.without_paragraph
24 24 end
25 25  
... ...
plugins/comment_paragraph/views/comment/comment_extra.html.erb
1 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 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 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 3 <%= inner_html %>
4 4 </div>
5 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 9 </span>
10 10 </div>
11 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 23 </div>
42 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   -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