mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-28 19:29:38 +00:00
Adds issue filters on parent/subtasks (#6118).
git-svn-id: http://svn.redmine.org/redmine/trunk@14304 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
3077ed8d3a
commit
98f2b30ac5
@ -24,7 +24,7 @@ module QueriesHelper
|
||||
ungrouped = []
|
||||
grouped = {}
|
||||
query.available_filters.map do |field, field_options|
|
||||
if field_options[:type] == :relation
|
||||
if [:tree, :relation].include?(field_options[:type])
|
||||
group = :label_related_issues
|
||||
elsif field =~ /^(.+)\./
|
||||
# association filters
|
||||
|
||||
@ -241,6 +241,8 @@ class IssueQuery < Query
|
||||
IssueRelation::TYPES.each do |relation_type, options|
|
||||
add_available_filter relation_type, :type => :relation, :label => options[:name]
|
||||
end
|
||||
add_available_filter "parent_id", :type => :tree, :label => :field_parent_issue
|
||||
add_available_filter "child_id", :type => :tree, :label => :label_subtask_plural
|
||||
|
||||
Tracker.disabled_core_fields(trackers).each {|field|
|
||||
delete_available_filter field
|
||||
@ -451,6 +453,47 @@ class IssueQuery < Query
|
||||
"#{Issue.table_name}.is_private #{op} (#{va})"
|
||||
end
|
||||
|
||||
def sql_for_parent_id_field(field, operator, value)
|
||||
case operator
|
||||
when "="
|
||||
"#{Issue.table_name}.parent_id = #{value.first.to_i}"
|
||||
when "~"
|
||||
root_id, lft, rgt = Issue.where(:id => value.first.to_i).pluck(:root_id, :lft, :rgt).first
|
||||
if root_id && lft && rgt
|
||||
"#{Issue.table_name}.root_id = #{root_id} AND #{Issue.table_name}.lft > #{lft} AND #{Issue.table_name}.rgt < #{rgt}"
|
||||
else
|
||||
"1=0"
|
||||
end
|
||||
when "!*"
|
||||
"#{Issue.table_name}.parent_id IS NULL"
|
||||
when "*"
|
||||
"#{Issue.table_name}.parent_id IS NOT NULL"
|
||||
end
|
||||
end
|
||||
|
||||
def sql_for_child_id_field(field, operator, value)
|
||||
case operator
|
||||
when "="
|
||||
parent_id = Issue.where(:id => value.first.to_i).pluck(:parent_id).first
|
||||
if parent_id
|
||||
"#{Issue.table_name}.id = #{parent_id}"
|
||||
else
|
||||
"1=0"
|
||||
end
|
||||
when "~"
|
||||
root_id, lft, rgt = Issue.where(:id => value.first.to_i).pluck(:root_id, :lft, :rgt).first
|
||||
if root_id && lft && rgt
|
||||
"#{Issue.table_name}.root_id = #{root_id} AND #{Issue.table_name}.lft < #{lft} AND #{Issue.table_name}.rgt > #{rgt}"
|
||||
else
|
||||
"1=0"
|
||||
end
|
||||
when "!*"
|
||||
"#{Issue.table_name}.rgt - #{Issue.table_name}.lft = 1"
|
||||
when "*"
|
||||
"#{Issue.table_name}.rgt - #{Issue.table_name}.lft > 1"
|
||||
end
|
||||
end
|
||||
|
||||
def sql_for_relations(field, operator, value, options={})
|
||||
relation_options = IssueRelation::TYPES[field]
|
||||
return relation_options unless relation_options
|
||||
|
||||
@ -216,7 +216,8 @@ class Query < ActiveRecord::Base
|
||||
:text => [ "~", "!~", "!*", "*" ],
|
||||
:integer => [ "=", ">=", "<=", "><", "!*", "*" ],
|
||||
:float => [ "=", ">=", "<=", "><", "!*", "*" ],
|
||||
:relation => ["=", "=p", "=!p", "!p", "!*", "*"]
|
||||
:relation => ["=", "=p", "=!p", "!p", "!*", "*"],
|
||||
:tree => ["=", "~", "!*", "*"]
|
||||
}
|
||||
|
||||
class_attribute :available_columns
|
||||
|
||||
@ -217,6 +217,7 @@ function buildFilterRow(field, operator, values) {
|
||||
break;
|
||||
case "integer":
|
||||
case "float":
|
||||
case "tree":
|
||||
tr.find('td.values').append(
|
||||
'<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
|
||||
' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
|
||||
|
||||
@ -879,6 +879,46 @@ class QueryTest < ActiveSupport::TestCase
|
||||
assert_equal [issue1], find_issues_with_query(query)
|
||||
end
|
||||
|
||||
def test_filter_on_parent
|
||||
Issue.delete_all
|
||||
parent = Issue.generate_with_descendants!
|
||||
|
||||
|
||||
query = IssueQuery.new(:name => '_')
|
||||
query.filters = {"parent_id" => {:operator => '=', :values => [parent.id.to_s]}}
|
||||
assert_equal parent.children.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"parent_id" => {:operator => '~', :values => [parent.id.to_s]}}
|
||||
assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"parent_id" => {:operator => '*', :values => ['']}}
|
||||
assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"parent_id" => {:operator => '!*', :values => ['']}}
|
||||
assert_equal [parent.id], find_issues_with_query(query).map(&:id).sort
|
||||
end
|
||||
|
||||
def test_filter_on_child
|
||||
Issue.delete_all
|
||||
parent = Issue.generate_with_descendants!
|
||||
child, leaf = parent.children.sort_by(&:id)
|
||||
grandchild = child.children.first
|
||||
|
||||
|
||||
query = IssueQuery.new(:name => '_')
|
||||
query.filters = {"child_id" => {:operator => '=', :values => [grandchild.id.to_s]}}
|
||||
assert_equal [child.id], find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"child_id" => {:operator => '~', :values => [grandchild.id.to_s]}}
|
||||
assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"child_id" => {:operator => '*', :values => ['']}}
|
||||
assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
|
||||
query.filters = {"child_id" => {:operator => '!*', :values => ['']}}
|
||||
assert_equal [grandchild, leaf].map(&:id).sort, find_issues_with_query(query).map(&:id).sort
|
||||
end
|
||||
|
||||
def test_statement_should_be_nil_with_no_filters
|
||||
q = IssueQuery.new(:name => '_')
|
||||
q.filters = {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user