diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2015-06-13 10:56:44 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2015-06-13 10:56:44 +0000 |
commit | 98f2b30ac5871b684a6690be6449283926f3ef2a (patch) | |
tree | 017d0b458c1c70bd21ba2dea64d8d04186ec85fc | |
parent | 3077ed8d3a79fc613f31ecd47418fcec291cfd18 (diff) | |
download | redmine-98f2b30ac5871b684a6690be6449283926f3ef2a.tar.gz redmine-98f2b30ac5871b684a6690be6449283926f3ef2a.zip |
Adds issue filters on parent/subtasks (#6118).
git-svn-id: http://svn.redmine.org/redmine/trunk@14304 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r-- | app/helpers/queries_helper.rb | 2 | ||||
-rw-r--r-- | app/models/issue_query.rb | 43 | ||||
-rw-r--r-- | app/models/query.rb | 3 | ||||
-rw-r--r-- | public/javascripts/application.js | 1 | ||||
-rw-r--r-- | test/unit/query_test.rb | 40 |
5 files changed, 87 insertions, 2 deletions
diff --git a/app/helpers/queries_helper.rb b/app/helpers/queries_helper.rb index be99da114..ec2b8383f 100644 --- a/app/helpers/queries_helper.rb +++ b/app/helpers/queries_helper.rb @@ -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 diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index b8cad3242..20ea59630 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -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 diff --git a/app/models/query.rb b/app/models/query.rb index 0e6064fc6..cac43a4e4 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -216,7 +216,8 @@ class Query < ActiveRecord::Base :text => [ "~", "!~", "!*", "*" ], :integer => [ "=", ">=", "<=", "><", "!*", "*" ], :float => [ "=", ">=", "<=", "><", "!*", "*" ], - :relation => ["=", "=p", "=!p", "!p", "!*", "*"] + :relation => ["=", "=p", "=!p", "!p", "!*", "*"], + :tree => ["=", "~", "!*", "*"] } class_attribute :available_columns diff --git a/public/javascripts/application.js b/public/javascripts/application.js index a3ead6b23..0a12bc026 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -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>' diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index fdddba8cc..64cb8d151 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -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 = {} |