Implemented for PostgreSQL only for now. git-svn-id: http://svn.redmine.org/redmine/trunk@17724 e93f8b46-1217-0410-a6f0-8f06a7374b81tags/4.1.0
items.each do |item| | items.each do |item| | ||||
group_name = group_count = nil | group_name = group_count = nil | ||||
if query.grouped? | if query.grouped? | ||||
group = query.group_by_column.value(item) | |||||
group = query.group_by_column.group_value(item) | |||||
if first || group != previous_group | if first || group != previous_group | ||||
if group.blank? && group != false | if group.blank? && group != false | ||||
group_name = "(#{l(:label_blank_value)})" | group_name = "(#{l(:label_blank_value)})" |
QueryColumn.new(:subject, :sortable => "#{Issue.table_name}.subject"), | QueryColumn.new(:subject, :sortable => "#{Issue.table_name}.subject"), | ||||
QueryColumn.new(:author, :sortable => lambda {User.fields_for_order_statement("authors")}, :groupable => true), | QueryColumn.new(:author, :sortable => lambda {User.fields_for_order_statement("authors")}, :groupable => true), | ||||
QueryColumn.new(:assigned_to, :sortable => lambda {User.fields_for_order_statement}, :groupable => true), | QueryColumn.new(:assigned_to, :sortable => lambda {User.fields_for_order_statement}, :groupable => true), | ||||
QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default_order => 'desc'), | |||||
TimestampQueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default_order => 'desc', :groupable => true), | |||||
QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true), | QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true), | ||||
QueryColumn.new(:fixed_version, :sortable => lambda {Version.fields_for_order_statement}, :groupable => true), | QueryColumn.new(:fixed_version, :sortable => lambda {Version.fields_for_order_statement}, :groupable => true), | ||||
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date", :groupable => true), | QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date", :groupable => true), | ||||
" WHERE subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)", | " WHERE subtasks.root_id = #{Issue.table_name}.root_id AND subtasks.lft >= #{Issue.table_name}.lft AND subtasks.rgt <= #{Issue.table_name}.rgt), 0)", | ||||
:default_order => 'desc'), | :default_order => 'desc'), | ||||
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true), | QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true), | ||||
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'), | |||||
QueryColumn.new(:closed_on, :sortable => "#{Issue.table_name}.closed_on", :default_order => 'desc'), | |||||
TimestampQueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc', :groupable => true), | |||||
TimestampQueryColumn.new(:closed_on, :sortable => "#{Issue.table_name}.closed_on", :default_order => 'desc', :groupable => true), | |||||
QueryColumn.new(:last_updated_by, :sortable => lambda {User.fields_for_order_statement("last_journal_user")}), | QueryColumn.new(:last_updated_by, :sortable => lambda {User.fields_for_order_statement("last_journal_user")}), | ||||
QueryColumn.new(:relations, :caption => :label_related_issues), | QueryColumn.new(:relations, :caption => :label_related_issues), | ||||
QueryColumn.new(:attachments, :caption => :label_attachment_plural), | QueryColumn.new(:attachments, :caption => :label_attachment_plural), |
object.send name | object.send name | ||||
end | end | ||||
# Returns the group that object belongs to when grouping query results | |||||
def group_value(object) | |||||
value(object) | |||||
end | |||||
def css_classes | def css_classes | ||||
name | name | ||||
end | end | ||||
end | end | ||||
class TimestampQueryColumn < QueryColumn | |||||
def groupable | |||||
if @groupable | |||||
Redmine::Database.timestamp_to_date(sortable, User.current.time_zone) | |||||
end | |||||
end | |||||
def group_value(object) | |||||
if time = value(object) | |||||
User.current.time_to_date(time) | |||||
end | |||||
end | |||||
end | |||||
class QueryAssociationColumn < QueryColumn | class QueryAssociationColumn < QueryColumn | ||||
def initialize(association, attribute, options={}) | def initialize(association, attribute, options={}) |
end | end | ||||
end | end | ||||
# Returns a SQL statement to cast a timestamp column to a date given a time zone | |||||
# Returns nil if not implemented for the current database | |||||
def timestamp_to_date(column, time_zone) | |||||
if postgresql? | |||||
if time_zone | |||||
identifier = ActiveSupport::TimeZone.find_tzinfo(time_zone.name).identifier | |||||
"(#{column}::timestamptz AT TIME ZONE '#{identifier}')::date" | |||||
else | |||||
"#{column}::date" | |||||
end | |||||
end | |||||
end | |||||
# Resets database information | # Resets database information | ||||
def reset | def reset | ||||
@postgresql_unaccent = nil | @postgresql_unaccent = nil |
issue_list(issues) do |issue, level| | issue_list(issues) do |issue, level| | ||||
if query.grouped? && | if query.grouped? && | ||||
(group = query.group_by_column.value(issue)) != previous_group | |||||
(group = query.group_by_column.group_value(issue)) != previous_group | |||||
pdf.SetFontStyle('B',10) | pdf.SetFontStyle('B',10) | ||||
group_label = group.blank? ? 'None' : group.to_s.dup | group_label = group.blank? ? 'None' : group.to_s.dup | ||||
group_label << " (#{result_count_by_group[group]})" | group_label << " (#{result_count_by_group[group]})" |
end | end | ||||
end | end | ||||
def test_index_grouped_by_created_on | |||||
skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on} | |||||
get :index, :params => { | |||||
:set_filter => 1, | |||||
:group_by => 'created_on' | |||||
} | |||||
assert_response :success | |||||
assert_select 'tr.group span.name', :text => '07/19/2006' do | |||||
assert_select '+ span.count', :text => '2' | |||||
end | |||||
end | |||||
def test_index_grouped_by_created_on_as_pdf | |||||
skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on} | |||||
get :index, :params => { | |||||
:set_filter => 1, | |||||
:group_by => 'created_on', | |||||
:format => 'pdf' | |||||
} | |||||
assert_response :success | |||||
assert_equal 'application/pdf', response.content_type | |||||
end | |||||
def test_index_with_query_grouped_by_list_custom_field | def test_index_with_query_grouped_by_list_custom_field | ||||
get :index, :params => { | get :index, :params => { | ||||
:project_id => 1, | :project_id => 1, |