@@ -24,7 +24,7 module QueriesHelper | |||||
24 | ungrouped = [] |
|
24 | ungrouped = [] | |
25 | grouped = {} |
|
25 | grouped = {} | |
26 | query.available_filters.map do |field, field_options| |
|
26 | query.available_filters.map do |field, field_options| | |
27 | if field_options[:type] == :relation |
|
27 | if [:tree, :relation].include?(field_options[:type]) | |
28 | group = :label_related_issues |
|
28 | group = :label_related_issues | |
29 | elsif field =~ /^(.+)\./ |
|
29 | elsif field =~ /^(.+)\./ | |
30 | # association filters |
|
30 | # association filters |
@@ -241,6 +241,8 class IssueQuery < Query | |||||
241 | IssueRelation::TYPES.each do |relation_type, options| |
|
241 | IssueRelation::TYPES.each do |relation_type, options| | |
242 | add_available_filter relation_type, :type => :relation, :label => options[:name] |
|
242 | add_available_filter relation_type, :type => :relation, :label => options[:name] | |
243 | end |
|
243 | end | |
|
244 | add_available_filter "parent_id", :type => :tree, :label => :field_parent_issue | |||
|
245 | add_available_filter "child_id", :type => :tree, :label => :label_subtask_plural | |||
244 |
|
246 | |||
245 | Tracker.disabled_core_fields(trackers).each {|field| |
|
247 | Tracker.disabled_core_fields(trackers).each {|field| | |
246 | delete_available_filter field |
|
248 | delete_available_filter field | |
@@ -451,6 +453,47 class IssueQuery < Query | |||||
451 | "#{Issue.table_name}.is_private #{op} (#{va})" |
|
453 | "#{Issue.table_name}.is_private #{op} (#{va})" | |
452 | end |
|
454 | end | |
453 |
|
455 | |||
|
456 | def sql_for_parent_id_field(field, operator, value) | |||
|
457 | case operator | |||
|
458 | when "=" | |||
|
459 | "#{Issue.table_name}.parent_id = #{value.first.to_i}" | |||
|
460 | when "~" | |||
|
461 | root_id, lft, rgt = Issue.where(:id => value.first.to_i).pluck(:root_id, :lft, :rgt).first | |||
|
462 | if root_id && lft && rgt | |||
|
463 | "#{Issue.table_name}.root_id = #{root_id} AND #{Issue.table_name}.lft > #{lft} AND #{Issue.table_name}.rgt < #{rgt}" | |||
|
464 | else | |||
|
465 | "1=0" | |||
|
466 | end | |||
|
467 | when "!*" | |||
|
468 | "#{Issue.table_name}.parent_id IS NULL" | |||
|
469 | when "*" | |||
|
470 | "#{Issue.table_name}.parent_id IS NOT NULL" | |||
|
471 | end | |||
|
472 | end | |||
|
473 | ||||
|
474 | def sql_for_child_id_field(field, operator, value) | |||
|
475 | case operator | |||
|
476 | when "=" | |||
|
477 | parent_id = Issue.where(:id => value.first.to_i).pluck(:parent_id).first | |||
|
478 | if parent_id | |||
|
479 | "#{Issue.table_name}.id = #{parent_id}" | |||
|
480 | else | |||
|
481 | "1=0" | |||
|
482 | end | |||
|
483 | when "~" | |||
|
484 | root_id, lft, rgt = Issue.where(:id => value.first.to_i).pluck(:root_id, :lft, :rgt).first | |||
|
485 | if root_id && lft && rgt | |||
|
486 | "#{Issue.table_name}.root_id = #{root_id} AND #{Issue.table_name}.lft < #{lft} AND #{Issue.table_name}.rgt > #{rgt}" | |||
|
487 | else | |||
|
488 | "1=0" | |||
|
489 | end | |||
|
490 | when "!*" | |||
|
491 | "#{Issue.table_name}.rgt - #{Issue.table_name}.lft = 1" | |||
|
492 | when "*" | |||
|
493 | "#{Issue.table_name}.rgt - #{Issue.table_name}.lft > 1" | |||
|
494 | end | |||
|
495 | end | |||
|
496 | ||||
454 | def sql_for_relations(field, operator, value, options={}) |
|
497 | def sql_for_relations(field, operator, value, options={}) | |
455 | relation_options = IssueRelation::TYPES[field] |
|
498 | relation_options = IssueRelation::TYPES[field] | |
456 | return relation_options unless relation_options |
|
499 | return relation_options unless relation_options |
@@ -216,7 +216,8 class Query < ActiveRecord::Base | |||||
216 | :text => [ "~", "!~", "!*", "*" ], |
|
216 | :text => [ "~", "!~", "!*", "*" ], | |
217 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
217 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], | |
218 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
218 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], | |
219 | :relation => ["=", "=p", "=!p", "!p", "!*", "*"] |
|
219 | :relation => ["=", "=p", "=!p", "!p", "!*", "*"], | |
|
220 | :tree => ["=", "~", "!*", "*"] | |||
220 | } |
|
221 | } | |
221 |
|
222 | |||
222 | class_attribute :available_columns |
|
223 | class_attribute :available_columns |
@@ -217,6 +217,7 function buildFilterRow(field, operator, values) { | |||||
217 | break; |
|
217 | break; | |
218 | case "integer": |
|
218 | case "integer": | |
219 | case "float": |
|
219 | case "float": | |
|
220 | case "tree": | |||
220 | tr.find('td.values').append( |
|
221 | tr.find('td.values').append( | |
221 | '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' + |
|
222 | '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' + | |
222 | ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>' |
|
223 | ' <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 | |||||
879 | assert_equal [issue1], find_issues_with_query(query) |
|
879 | assert_equal [issue1], find_issues_with_query(query) | |
880 | end |
|
880 | end | |
881 |
|
881 | |||
|
882 | def test_filter_on_parent | |||
|
883 | Issue.delete_all | |||
|
884 | parent = Issue.generate_with_descendants! | |||
|
885 | ||||
|
886 | ||||
|
887 | query = IssueQuery.new(:name => '_') | |||
|
888 | query.filters = {"parent_id" => {:operator => '=', :values => [parent.id.to_s]}} | |||
|
889 | assert_equal parent.children.map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
890 | ||||
|
891 | query.filters = {"parent_id" => {:operator => '~', :values => [parent.id.to_s]}} | |||
|
892 | assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
893 | ||||
|
894 | query.filters = {"parent_id" => {:operator => '*', :values => ['']}} | |||
|
895 | assert_equal parent.descendants.map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
896 | ||||
|
897 | query.filters = {"parent_id" => {:operator => '!*', :values => ['']}} | |||
|
898 | assert_equal [parent.id], find_issues_with_query(query).map(&:id).sort | |||
|
899 | end | |||
|
900 | ||||
|
901 | def test_filter_on_child | |||
|
902 | Issue.delete_all | |||
|
903 | parent = Issue.generate_with_descendants! | |||
|
904 | child, leaf = parent.children.sort_by(&:id) | |||
|
905 | grandchild = child.children.first | |||
|
906 | ||||
|
907 | ||||
|
908 | query = IssueQuery.new(:name => '_') | |||
|
909 | query.filters = {"child_id" => {:operator => '=', :values => [grandchild.id.to_s]}} | |||
|
910 | assert_equal [child.id], find_issues_with_query(query).map(&:id).sort | |||
|
911 | ||||
|
912 | query.filters = {"child_id" => {:operator => '~', :values => [grandchild.id.to_s]}} | |||
|
913 | assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
914 | ||||
|
915 | query.filters = {"child_id" => {:operator => '*', :values => ['']}} | |||
|
916 | assert_equal [parent, child].map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
917 | ||||
|
918 | query.filters = {"child_id" => {:operator => '!*', :values => ['']}} | |||
|
919 | assert_equal [grandchild, leaf].map(&:id).sort, find_issues_with_query(query).map(&:id).sort | |||
|
920 | end | |||
|
921 | ||||
882 | def test_statement_should_be_nil_with_no_filters |
|
922 | def test_statement_should_be_nil_with_no_filters | |
883 | q = IssueQuery.new(:name => '_') |
|
923 | q = IssueQuery.new(:name => '_') | |
884 | q.filters = {} |
|
924 | q.filters = {} |
General Comments 0
You need to be logged in to leave comments.
Login now