From 089311f7d65a32404b0a37583f8dd821f1c98fc8 Mon Sep 17 00:00:00 2001 From: Carlos Purificacao Date: Thu, 9 Jun 2016 13:31:53 -0300 Subject: [PATCH] Initial version --- plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb | 12 ++++++++++++ plugins/comment_paragraph/lib/comment_paragraph_plugin.rb | 13 ++++++++++--- plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb | 16 ++++++++++++++++ plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb | 14 ++++++++++++++ plugins/comment_paragraph/test/unit/api_test.rb | 14 ++++++++++++++ plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb | 14 ++++++++++++-- 7 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb diff --git a/plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb b/plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb index 09b4b98..98791be 100644 --- a/plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb +++ b/plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb @@ -21,4 +21,16 @@ class CommentParagraphPluginProfileController < CommentController } end + include CommentParagraphPlugin::CommentsReport + + def export_comments + article_id = params[:id] + article = profile.articles.find(article_id) + result = export_comments_csv(article) + filename = "comments_for_article#{article_id}_#{DateTime.now.to_i}.csv" + send_data result, + :type => 'text/csv; charset=UTF-8; header=present', + :disposition => "attachment; filename=#{filename}" + end + end diff --git a/plugins/comment_paragraph/lib/comment_paragraph_plugin.rb b/plugins/comment_paragraph/lib/comment_paragraph_plugin.rb index 3f29a81..c4a1753 100644 --- a/plugins/comment_paragraph/lib/comment_paragraph_plugin.rb +++ b/plugins/comment_paragraph/lib/comment_paragraph_plugin.rb @@ -47,12 +47,19 @@ class CommentParagraphPlugin < Noosfero::Plugin def article_extra_toolbar_buttons(article) user = context.send :user return [] if !article.comment_paragraph_plugin_enabled? || !article.allow_edit?(user) || article.kind_of?(CommentParagraphPlugin::Discussion) - { + buttons = [ + { :title => article.comment_paragraph_plugin_activated? ? _('Deactivate Comments') : _('Activate Comments'), :url => {:controller => 'comment_paragraph_plugin_myprofile', :profile => article.profile.identifier, :action => 'toggle_activation', :id => article.id}, :icon => :toggle_comment_paragraph - } - + } + ] + buttons << { + :title => _('Export Comments'), + :url => {:controller => 'comment_paragraph_plugin_profile', :profile => article.profile.identifier, :action => 'export_comments', :id => article.id}, + :icon => :toggle_comment_paragraph + } if article.comment_paragraph_plugin_activated? + buttons end def self.api_mount_points diff --git a/plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb b/plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb index 2176fb0..d263db3 100644 --- a/plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb +++ b/plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb @@ -1,9 +1,14 @@ +require_relative 'comments_report' + # Can't be called Api as will result in: # warning: toplevel constant Api referenced by CommentParagraphPlugin::Api # To fix this CommentParagraphPlugin should be a module class CommentParagraphPlugin::API < Grape::API + MAX_PER_PAGE = 20 + helpers CommentParagraphPlugin::CommentsReport + resource :articles do paginate max_per_page: MAX_PER_PAGE get ':id/comment_paragraph_plugin/comments' do @@ -31,5 +36,16 @@ class CommentParagraphPlugin::API < Grape::API comments = select_filtered_collection_of(article, :comments, params) comments.group(:paragraph_uuid).count end + + get ":id/comment_paragraph_plugin/export" do + article = find_article(environment.articles, params[:id]) + result = export_comments_csv(article) + filename = "comments_for_article#{article.id}_#{DateTime.now.to_i}.csv" + content_type 'text/csv; charset=UTF-8; header=present' + env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is" + header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}" + result + end + end end diff --git a/plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb b/plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb new file mode 100644 index 0000000..3c7b884 --- /dev/null +++ b/plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb @@ -0,0 +1,53 @@ +require 'csv' + +module CommentParagraphPlugin::CommentsReport + + #FIXME make this test + def export_comments_csv(article) + comments_map = article.comments.group_by { |comment| comment.paragraph_uuid } + @export = [] + doc = Nokogiri::HTML(article.body) + paragraph_id = 1 + doc.css("[data-macro-paragraph_uuid]").map do |paragraph| + uuid = paragraph.attributes['data-macro-paragraph_uuid'].value + comments_for_paragraph = comments_map[uuid] + if comments_for_paragraph + # Put comments for the paragraph + comments_for_paragraph.each do | comment | + @export << create_comment_element(comment, paragraph, paragraph_id) + end + else # There are no comments for this paragraph + @export << create_comment_element(nil, paragraph, paragraph_id) + end + paragraph_id += 1 + end + # Now we need to put all other comments that are not attached to a paragraph + comments_without_paragrah = comments_map[nil] || [] + comments_without_paragrah.each do | comment | + @export << create_comment_element(comment, nil, nil) + end + return _("No comments for article[%{id}]: %{path}\n\n") % {:id => article.id, :path => article.path} if @export.empty? + + column_names = @export.first.keys + CSV.generate(force_quotes: true) do |csv| + csv << column_names + @export.each { |x| csv << x.values } + end + end + + private + + def create_comment_element(comment, paragraph, paragraph_id) + { + paragraph_id: paragraph_id, + paragraph_text: paragraph.present? ? paragraph.text.strip : nil, + comment_id: comment.present? ? comment.id : '-', + comment_reply_to: comment.present? ? comment.reply_of_id : '-', + comment_title: comment.present? ? comment.title : '-', + comment_content: comment.present? ? comment.body : '-', + comment_author_name: comment.present? ? comment.author_name : '-', + comment_author_email: comment.present? ? comment.author_email : '-' + } + end + +end diff --git a/plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb b/plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb index 86aaeac..ca9d057 100644 --- a/plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb +++ b/plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb @@ -50,4 +50,18 @@ class CommentParagraphPluginProfileControllerTest < ActionController::TestCase assert_select "#comment_paragraph_uuid[value=?]", '0' end + should 'export comments as CSV' do + comment1 = fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'a comment', :paragraph_uuid => nil) + comment2 = fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :author_id => profile, :title => 'b comment', :body => 'b comment', :paragraph_uuid => nil) + xhr :get, :export_comments, :profile => @profile.identifier, :id => article.id + assert_equal 'text/csv; charset=UTF-8; header=present', @response.content_type + lines = @response.body.split("\n") + assert_equal '"paragraph_id","paragraph_text","comment_id","comment_reply_to","comment_title","comment_content","comment_author_name","comment_author_email"', lines.first + assert_equal "\"\",\"\",\"#{comment2.id}\",\"\",\"b comment\",\"b comment\",\"#{comment2.author_name}\",\"#{comment2.author_email}\"", lines.second + end + + should 'not export any comments as CSV' do + xhr :get, :export_comments, :profile => @profile.identifier, :id => article.id + assert_equal "No comments for article[#{article.id}]: #{article.path}", @response.body.split("\n")[0] + end end diff --git a/plugins/comment_paragraph/test/unit/api_test.rb b/plugins/comment_paragraph/test/unit/api_test.rb index 6e7a9df..57c282d 100644 --- a/plugins/comment_paragraph/test/unit/api_test.rb +++ b/plugins/comment_paragraph/test/unit/api_test.rb @@ -90,4 +90,18 @@ class APITest < ActiveSupport::TestCase assert_equal "CommentParagraphPlugin::Discussion", json["article"]["type"] assert json["article"]["setting"]["comment_paragraph_plugin_activate"] end + + should 'export comments' do + login_api + article = fast_create(Article, :profile_id => person.id, :name => "Some thing") + comment1 = fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :title => 'a comment', :body => 'a comment', :paragraph_uuid => nil) + comment2 = fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :title => 'b comment', :body => 'b comment', :paragraph_uuid => nil) + get "/api/v1/articles/#{article.id}/comment_paragraph_plugin/export?#{params.to_query}" + assert_equal 200, last_response.status + assert_equal 'text/csv; charset=UTF-8; header=present', last_response.content_type + lines = last_response.body.split("\n") + assert_equal '"paragraph_id","paragraph_text","comment_id","comment_reply_to","comment_title","comment_content","comment_author_name","comment_author_email"', lines.first + assert_equal "\"\",\"\",\"#{comment2.id}\",\"\",\"b comment\",\"b comment\",\"#{comment2.author_name}\",\"#{comment2.author_email}\"", lines.second + end + end diff --git a/plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb b/plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb index 07f6c24..e6344cc 100644 --- a/plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb +++ b/plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb @@ -71,7 +71,7 @@ class CommentParagraphPluginTest < ActiveSupport::TestCase article.expects(:allow_edit?).with(user).returns(true) article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(false) - assert_equal 'Activate Comments', plugin.article_extra_toolbar_buttons(article)[:title] + assert_equal 'Activate Comments', plugin.article_extra_toolbar_buttons(article).first[:title] end should 'display Deactivate Comments title if comment paragraph plugin is deactivated' do @@ -81,7 +81,17 @@ class CommentParagraphPluginTest < ActiveSupport::TestCase article.expects(:allow_edit?).with(user).returns(true) article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(true) - assert_equal 'Deactivate Comments', plugin.article_extra_toolbar_buttons(article)[:title] + assert_equal 'Deactivate Comments', plugin.article_extra_toolbar_buttons(article).first[:title] + end + + should 'display export comments button when comment paragraph plugin is activated' do + profile = fast_create(Profile) + article = fast_create(Article, :profile_id => profile.id) + article.expects(:comment_paragraph_plugin_enabled?).returns(true) + article.expects(:allow_edit?).with(user).returns(true) + article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(true) + + assert_includes plugin.article_extra_toolbar_buttons(article).map {|b| b[:title]}, 'Export Comments' end should 'not display button to toggle comment paragraph if article is a discussion' do -- libgit2 0.21.2