Commit 158f4315b129053c2f079311527b8c7a2a019c0c
Committed by
Victor Costa
1 parent
ee8510cb
Exists in
profile_api_improvements
and in
1 other branch
comment_paragraph: add method to export comments
Showing
8 changed files
with
153 additions
and
5 deletions
Show diff stats
plugins/comment_paragraph/controllers/profile/comment_paragraph_plugin_profile_controller.rb
| ... | ... | @@ -21,4 +21,16 @@ class CommentParagraphPluginProfileController < CommentController |
| 21 | 21 | } |
| 22 | 22 | end |
| 23 | 23 | |
| 24 | + include CommentParagraphPlugin::CommentsReport | |
| 25 | + | |
| 26 | + def export_comments | |
| 27 | + article_id = params[:id] | |
| 28 | + article = profile.articles.find(article_id) | |
| 29 | + result = export_comments_csv(article) | |
| 30 | + filename = "comments_for_article#{article_id}_#{DateTime.now.to_i}.csv" | |
| 31 | + send_data result, | |
| 32 | + :type => 'text/csv; charset=UTF-8; header=present', | |
| 33 | + :disposition => "attachment; filename=#{filename}" | |
| 34 | + end | |
| 35 | + | |
| 24 | 36 | end | ... | ... |
plugins/comment_paragraph/lib/comment_paragraph_plugin.rb
| ... | ... | @@ -47,12 +47,19 @@ class CommentParagraphPlugin < Noosfero::Plugin |
| 47 | 47 | def article_extra_toolbar_buttons(article) |
| 48 | 48 | user = context.send :user |
| 49 | 49 | return [] if !article.comment_paragraph_plugin_enabled? || !article.allow_edit?(user) || article.kind_of?(CommentParagraphPlugin::Discussion) |
| 50 | - { | |
| 50 | + buttons = [ | |
| 51 | + { | |
| 51 | 52 | :title => article.comment_paragraph_plugin_activated? ? _('Deactivate Comments') : _('Activate Comments'), |
| 52 | 53 | :url => {:controller => 'comment_paragraph_plugin_myprofile', :profile => article.profile.identifier, :action => 'toggle_activation', :id => article.id}, |
| 53 | 54 | :icon => :toggle_comment_paragraph |
| 54 | - } | |
| 55 | - | |
| 55 | + } | |
| 56 | + ] | |
| 57 | + buttons << { | |
| 58 | + :title => _('Export Comments'), | |
| 59 | + :url => {:controller => 'comment_paragraph_plugin_profile', :profile => article.profile.identifier, :action => 'export_comments', :id => article.id}, | |
| 60 | + :icon => :toggle_comment_paragraph | |
| 61 | + } if article.comment_paragraph_plugin_activated? | |
| 62 | + buttons | |
| 56 | 63 | end |
| 57 | 64 | |
| 58 | 65 | def self.api_mount_points | ... | ... |
plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb
| 1 | +require_relative 'comments_report' | |
| 2 | + | |
| 1 | 3 | # Can't be called Api as will result in: |
| 2 | 4 | # warning: toplevel constant Api referenced by CommentParagraphPlugin::Api |
| 3 | 5 | # To fix this CommentParagraphPlugin should be a module |
| 4 | 6 | class CommentParagraphPlugin::API < Grape::API |
| 7 | + | |
| 5 | 8 | MAX_PER_PAGE = 20 |
| 6 | 9 | |
| 10 | + helpers CommentParagraphPlugin::CommentsReport | |
| 11 | + | |
| 7 | 12 | resource :articles do |
| 8 | 13 | paginate max_per_page: MAX_PER_PAGE |
| 9 | 14 | get ':id/comment_paragraph_plugin/comments' do |
| ... | ... | @@ -31,5 +36,16 @@ class CommentParagraphPlugin::API < Grape::API |
| 31 | 36 | comments = select_filtered_collection_of(article, :comments, params) |
| 32 | 37 | comments.group(:paragraph_uuid).count |
| 33 | 38 | end |
| 39 | + | |
| 40 | + get ":id/comment_paragraph_plugin/export" do | |
| 41 | + article = find_article(environment.articles, params[:id]) | |
| 42 | + result = export_comments_csv(article) | |
| 43 | + filename = "comments_for_article#{article.id}_#{DateTime.now.to_i}.csv" | |
| 44 | + content_type 'text/csv; charset=UTF-8; header=present' | |
| 45 | + env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is" | |
| 46 | + header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}" | |
| 47 | + result | |
| 48 | + end | |
| 49 | + | |
| 34 | 50 | end |
| 35 | 51 | end | ... | ... |
plugins/comment_paragraph/lib/comment_paragraph_plugin/comments_report.rb
0 → 100644
| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | +require 'csv' | |
| 2 | + | |
| 3 | +module CommentParagraphPlugin::CommentsReport | |
| 4 | + | |
| 5 | + def export_comments_csv(article) | |
| 6 | + comments_map = article.comments.group_by { |comment| comment.paragraph_uuid } | |
| 7 | + @export = [] | |
| 8 | + doc = Nokogiri::HTML(article.body) | |
| 9 | + paragraph_id = 1 | |
| 10 | + doc.css("[data-macro-paragraph_uuid]").map do |paragraph| | |
| 11 | + uuid = paragraph.attributes['data-macro-paragraph_uuid'].value | |
| 12 | + comments_for_paragraph = comments_map[uuid] | |
| 13 | + if comments_for_paragraph | |
| 14 | + # Put comments for the paragraph | |
| 15 | + comments_for_paragraph.each do | comment | | |
| 16 | + @export << create_comment_element(comment, paragraph, paragraph_id) | |
| 17 | + end | |
| 18 | + else # There are no comments for this paragraph | |
| 19 | + @export << create_comment_element(nil, paragraph, paragraph_id) | |
| 20 | + end | |
| 21 | + paragraph_id += 1 | |
| 22 | + end | |
| 23 | + # Now we need to put all other comments that are not attached to a paragraph | |
| 24 | + comments_without_paragrah = comments_map[nil] || [] | |
| 25 | + comments_without_paragrah.each do | comment | | |
| 26 | + @export << create_comment_element(comment, nil, nil) | |
| 27 | + end | |
| 28 | + return _("No comments for article[%{id}]: %{path}\n\n") % {:id => article.id, :path => article.path} if @export.empty? | |
| 29 | + | |
| 30 | + column_names = @export.first.keys | |
| 31 | + CSV.generate(force_quotes: true) do |csv| | |
| 32 | + csv << column_names | |
| 33 | + @export.each { |x| csv << x.values } | |
| 34 | + end | |
| 35 | + end | |
| 36 | + | |
| 37 | + private | |
| 38 | + | |
| 39 | + def create_comment_element(comment, paragraph, paragraph_id) | |
| 40 | + { | |
| 41 | + paragraph_id: paragraph_id, | |
| 42 | + paragraph_text: paragraph.present? ? paragraph.text.strip : nil, | |
| 43 | + comment_id: comment.present? ? comment.id : '-', | |
| 44 | + comment_reply_to: comment.present? ? comment.reply_of_id : '-', | |
| 45 | + comment_title: comment.present? ? comment.title : '-', | |
| 46 | + comment_content: comment.present? ? comment.body : '-', | |
| 47 | + comment_author_name: comment.present? ? comment.author_name : '-', | |
| 48 | + comment_author_email: comment.present? ? comment.author_email : '-' | |
| 49 | + } | |
| 50 | + end | |
| 51 | + | |
| 52 | +end | ... | ... |
plugins/comment_paragraph/test/functional/comment_paragraph_plugin_profile_controller_test.rb
| ... | ... | @@ -50,4 +50,18 @@ class CommentParagraphPluginProfileControllerTest < ActionController::TestCase |
| 50 | 50 | assert_select "#comment_paragraph_uuid[value=?]", '0' |
| 51 | 51 | end |
| 52 | 52 | |
| 53 | + should 'export comments as CSV' do | |
| 54 | + 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) | |
| 55 | + 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) | |
| 56 | + xhr :get, :export_comments, :profile => @profile.identifier, :id => article.id | |
| 57 | + assert_equal 'text/csv; charset=UTF-8; header=present', @response.content_type | |
| 58 | + lines = @response.body.split("\n") | |
| 59 | + assert_equal '"paragraph_id","paragraph_text","comment_id","comment_reply_to","comment_title","comment_content","comment_author_name","comment_author_email"', lines.first | |
| 60 | + assert_equal "\"\",\"\",\"#{comment2.id}\",\"\",\"b comment\",\"b comment\",\"#{comment2.author_name}\",\"#{comment2.author_email}\"", lines.second | |
| 61 | + end | |
| 62 | + | |
| 63 | + should 'not export any comments as CSV' do | |
| 64 | + xhr :get, :export_comments, :profile => @profile.identifier, :id => article.id | |
| 65 | + assert_equal "No comments for article[#{article.id}]: #{article.path}", @response.body.split("\n")[0] | |
| 66 | + end | |
| 53 | 67 | end | ... | ... |
plugins/comment_paragraph/test/unit/api_test.rb
| ... | ... | @@ -90,4 +90,18 @@ class APITest < ActiveSupport::TestCase |
| 90 | 90 | assert_equal "CommentParagraphPlugin::Discussion", json["article"]["type"] |
| 91 | 91 | assert json["article"]["setting"]["comment_paragraph_plugin_activate"] |
| 92 | 92 | end |
| 93 | + | |
| 94 | + should 'export comments' do | |
| 95 | + login_api | |
| 96 | + article = fast_create(Article, :profile_id => person.id, :name => "Some thing") | |
| 97 | + comment1 = fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :title => 'a comment', :body => 'a comment', :paragraph_uuid => nil) | |
| 98 | + comment2 = fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :title => 'b comment', :body => 'b comment', :paragraph_uuid => nil) | |
| 99 | + get "/api/v1/articles/#{article.id}/comment_paragraph_plugin/export?#{params.to_query}" | |
| 100 | + assert_equal 200, last_response.status | |
| 101 | + assert_equal 'text/csv; charset=UTF-8; header=present', last_response.content_type | |
| 102 | + lines = last_response.body.split("\n") | |
| 103 | + assert_equal '"paragraph_id","paragraph_text","comment_id","comment_reply_to","comment_title","comment_content","comment_author_name","comment_author_email"', lines.first | |
| 104 | + assert_equal "\"\",\"\",\"#{comment2.id}\",\"\",\"b comment\",\"b comment\",\"#{comment2.author_name}\",\"#{comment2.author_email}\"", lines.second | |
| 105 | + end | |
| 106 | + | |
| 93 | 107 | end | ... | ... |
plugins/comment_paragraph/test/unit/comment_paragraph_plugin_test.rb
| ... | ... | @@ -71,7 +71,7 @@ class CommentParagraphPluginTest < ActiveSupport::TestCase |
| 71 | 71 | article.expects(:allow_edit?).with(user).returns(true) |
| 72 | 72 | article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(false) |
| 73 | 73 | |
| 74 | - assert_equal 'Activate Comments', plugin.article_extra_toolbar_buttons(article)[:title] | |
| 74 | + assert_equal 'Activate Comments', plugin.article_extra_toolbar_buttons(article).first[:title] | |
| 75 | 75 | end |
| 76 | 76 | |
| 77 | 77 | should 'display Deactivate Comments title if comment paragraph plugin is deactivated' do |
| ... | ... | @@ -81,7 +81,17 @@ class CommentParagraphPluginTest < ActiveSupport::TestCase |
| 81 | 81 | article.expects(:allow_edit?).with(user).returns(true) |
| 82 | 82 | article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(true) |
| 83 | 83 | |
| 84 | - assert_equal 'Deactivate Comments', plugin.article_extra_toolbar_buttons(article)[:title] | |
| 84 | + assert_equal 'Deactivate Comments', plugin.article_extra_toolbar_buttons(article).first[:title] | |
| 85 | + end | |
| 86 | + | |
| 87 | + should 'display export comments button when comment paragraph plugin is activated' do | |
| 88 | + profile = fast_create(Profile) | |
| 89 | + article = fast_create(Article, :profile_id => profile.id) | |
| 90 | + article.expects(:comment_paragraph_plugin_enabled?).returns(true) | |
| 91 | + article.expects(:allow_edit?).with(user).returns(true) | |
| 92 | + article.expects(:comment_paragraph_plugin_activated?).at_least_once.returns(true) | |
| 93 | + | |
| 94 | + assert_includes plugin.article_extra_toolbar_buttons(article).map {|b| b[:title]}, 'Export Comments' | |
| 85 | 95 | end |
| 86 | 96 | |
| 87 | 97 | should 'not display button to toggle comment paragraph if article is a discussion' do | ... | ... |
plugins/comment_paragraph/test/unit/comments_report_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | +require_relative '../test_helper' | |
| 2 | + | |
| 3 | +class CommentsReportTest < ActiveSupport::TestCase | |
| 4 | + | |
| 5 | + include CommentParagraphPlugin::CommentsReport | |
| 6 | + | |
| 7 | + def setup | |
| 8 | + profile = fast_create(Community) | |
| 9 | + @article = fast_create(Article, :profile_id => profile.id) | |
| 10 | + end | |
| 11 | + | |
| 12 | + attr_reader :article | |
| 13 | + | |
| 14 | + should 'export comments in csv format with the first line as a header' do | |
| 15 | + comment1 = fast_create(Comment, :created_at => Time.now - 1.days, :source_id => article, :title => 'a comment', :body => 'a comment', :paragraph_uuid => nil) | |
| 16 | + comment2 = fast_create(Comment, :created_at => Time.now - 2.days, :source_id => article, :title => 'b comment', :body => 'b comment', :paragraph_uuid => nil) | |
| 17 | + csv = export_comments_csv(article) | |
| 18 | + lines = csv.split("\n") | |
| 19 | + assert_equal '"paragraph_id","paragraph_text","comment_id","comment_reply_to","comment_title","comment_content","comment_author_name","comment_author_email"', lines.first | |
| 20 | + assert_equal "\"\",\"\",\"#{comment2.id}\",\"\",\"b comment\",\"b comment\",\"#{comment2.author_name}\",\"#{comment2.author_email}\"", lines.second | |
| 21 | + end | |
| 22 | + | |
| 23 | +end | ... | ... |