diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 96a8341d0b..74174210e2 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -72,7 +72,7 @@ class IssuesController < ApplicationController
:title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}")
end
format.csv do
- @issues = @query.issues(:limit => Setting.issues_export_limit.to_i)
+ @issues = @query.issues(:limit => Setting.issues_export_limit.to_i, :with_notes => (params[:with_notes] == '1'))
send_data(query_to_csv(@issues, @query, params[:csv]),
:type => 'text/csv; header=present', :filename => 'issues.csv')
end
diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb
index 9b223f84a7..0849a396ef 100644
--- a/app/helpers/queries_helper.rb
+++ b/app/helpers/queries_helper.rb
@@ -320,11 +320,23 @@ module QueriesHelper
columns = query.columns
Redmine::Export::CSV.generate(:encoding => params[:encoding]) do |csv|
+ journal_columns = IssueQuery.journal_columns if params[:with_notes] == '1'
+
# csv header fields
- csv << columns.map {|c| c.caption.to_s}
+ csv << columns.map {|c| c.caption.to_s} + (journal_columns || []).map{|c| c.caption.to_s}
# csv lines
items.each do |item|
- csv << columns.map {|c| csv_content(c, item)}
+ if journal_columns
+ item.journals_with_notes.each_with_index do |journal, index|
+ if index == 0
+ csv << columns.map {|c| csv_content(c, item)} + journal_columns.map {|c| csv_content(c, journal)}
+ else
+ csv << columns.map {|c| csv_content(c, item) if c.name == :id } + journal_columns.map {|c| csv_content(c, journal)}
+ end
+ end
+ else
+ csv << columns.map {|c| csv_content(c, item)}
+ end
end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 7ce04ad64b..7c9d414c48 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -262,6 +262,7 @@ class Issue < ActiveRecord::Base
@total_estimated_hours = nil
@last_updated_by = nil
@last_notes = nil
+ @journals_with_notes = nil
base_reload(*args)
end
@@ -1166,11 +1167,21 @@ class Issue < ActiveRecord::Base
def last_notes
if @last_notes
@last_notes
+ elsif @journals_with_notes.first.notes
+ @journals_with_notes.first.notes
else
journals.where.not(notes: '').reorder(:id => :desc).first.try(:notes)
end
end
+ def journals_with_notes
+ if @journals_with_notes
+ @journals_with_notes
+ else
+ journals.where.not(notes: '').reorder(:id => :asc)
+ end
+ end
+
# Preloads relations for a collection of issues
def self.load_relations(issues)
if issues.any?
@@ -1261,8 +1272,15 @@ class Issue < ActiveRecord::Base
end
# Preloads visible last notes for a collection of issues
- def self.load_visible_last_notes(issues, user=User.current)
+ def self.load_visible_last_notes(issues, user=User.current, has_notes=false)
if issues.any?
+ if has_notes
+ issues.each do |issue|
+ issue.instance_variable_set("@last_notes", issue.journals_with_notes.last.notes)
+ end
+ return
+ end
+
issue_ids = issues.map(&:id)
journal_ids = Journal.joins(issue: :project).
where(:journalized_type => 'Issue', :journalized_id => issue_ids).
@@ -1280,6 +1298,22 @@ class Issue < ActiveRecord::Base
end
end
+ # Preloads visible journals_with_notes for a collection of issues
+ def self.load_visible_journals_with_notes(issues, user=User.current)
+ if issues.any?
+ issue_ids = issues.map(&:id)
+ journals = Journal.joins(issue: :project).
+ where(:journalized_type => 'Issue', :journalized_id => issue_ids).
+ where(Journal.visible_notes_condition(user, :skip_pre_condition => true)).
+ where.not(notes: '').
+ reorder(id: :asc)
+
+ issues.each do |issue|
+ issue.instance_variable_set("@journals_with_notes", journals.where(journalized_id: issue.id))
+ end
+ end
+ end
+
# Finds an issue relation given its id.
def find_relation(relation_id)
IssueRelation.where("issue_to_id = ? OR issue_from_id = ?", id, id).find(relation_id)
diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb
index efd0ad0f1d..62c6b8e8f0 100644
--- a/app/models/issue_query.rb
+++ b/app/models/issue_query.rb
@@ -323,6 +323,19 @@ class IssueQuery < Query
@available_columns
end
+ def self.journal_columns
+ columns =
+ [
+ QueryColumn.new(:id, :caption => :label_notes_id, :inline => false),
+ QueryColumn.new(:notes, :caption => :field_notes, :inline => false),
+ QueryColumn.new(:user, :caption => :label_notes_author, :inline => false),
+ QueryColumn.new(:created_on, :caption => :label_notes_created_on, :inline => false)
+ ]
+ if User.current.allowed_to?(:set_notes_private, nil, :global => true)
+ columns << QueryColumn.new(:private_notes, :caption => :field_private_notes, :inline => false)
+ end
+ end
+
def default_columns_names
@default_columns_names ||= begin
default_columns = Setting.issue_list_default_columns.map(&:to_sym)
@@ -405,8 +418,11 @@ class IssueQuery < Query
if has_column?(:relations)
Issue.load_visible_relations(issues)
end
+ if options[:with_notes]
+ Issue.load_visible_journals_with_notes(issues)
+ end
if has_column?(:last_notes)
- Issue.load_visible_last_notes(issues)
+ Issue.load_visible_last_notes(issues, User.current, options[:with_notes])
end
issues
rescue ::ActiveRecord::StatementInvalid => e
diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb
index 880c953eaa..e7ad729c89 100644
--- a/app/views/issues/index.html.erb
+++ b/app/views/issues/index.html.erb
@@ -55,6 +55,7 @@
<% @query.available_block_columns.each do |column| %>
<% end %>
+
<% end %>
<%= export_csv_encoding_select_tag %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 952138bf4e..6815081b3e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1121,6 +1121,10 @@ en:
label_display_type_board: Board
label_my_bookmarks: My bookmarks
label_assign_to_me: Assign to me
+ label_all_notes: All notes
+ label_notes_id: Notes-#
+ label_notes_author: Notes author
+ label_notes_created_on: Notes created
button_login: Login
button_submit: Submit