##// END OF EJS Templates
Ability to filter issues blocked by any/no open issues (#16621)....
Jean-Philippe Lang -
r14427:d3d7678c7689
parent child
Show More
@@ -535,6 +535,9 class IssueQuery < Query
535 535 op = (operator == "!p" ? 'NOT IN' : 'IN')
536 536 comp = (operator == "=!p" ? '<>' : '=')
537 537 "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
538 when "*o", "!o"
539 op = (operator == "!o" ? 'NOT IN' : 'IN')
540 "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{self.class.connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.status_id IN (SELECT id FROM #{IssueStatus.table_name} WHERE is_closed=#{self.class.connection.quoted_false}))"
538 541 end
539 542
540 543 if relation_options[:sym] == field && !options[:reverse]
@@ -203,7 +203,9 class Query < ActiveRecord::Base
203 203 "!~" => :label_not_contains,
204 204 "=p" => :label_any_issues_in_project,
205 205 "=!p" => :label_any_issues_not_in_project,
206 "!p" => :label_no_issues_in_project
206 "!p" => :label_no_issues_in_project,
207 "*o" => :label_any_open_issues,
208 "!o" => :label_no_open_issues
207 209 }
208 210
209 211 class_attribute :operators_by_filter_type
@@ -218,7 +220,7 class Query < ActiveRecord::Base
218 220 :text => [ "~", "!~", "!*", "*" ],
219 221 :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
220 222 :float => [ "=", ">=", "<=", "><", "!*", "*" ],
221 :relation => ["=", "=p", "=!p", "!p", "!*", "*"],
223 :relation => ["=", "=p", "=!p", "!p", "*o", "!o", "!*", "*"],
222 224 :tree => ["=", "~", "!*", "*"]
223 225 }
224 226
@@ -281,7 +283,7 class Query < ActiveRecord::Base
281 283 # filter requires one or more values
282 284 (values_for(field) and !values_for(field).first.blank?) or
283 285 # filter doesn't require any value
284 ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
286 ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "*o", "!o"].include? operator_for(field)
285 287 end if filters
286 288 end
287 289
@@ -1061,6 +1061,8 en-GB:
1061 1061 permission_view_private_notes: View private notes
1062 1062 permission_set_notes_private: Set notes as private
1063 1063 label_no_issues_in_project: no issues in project
1064 label_any_open_issues: any open issues
1065 label_no_open_issues: no open issues
1064 1066 label_any: all
1065 1067 label_last_n_weeks: last %{count} weeks
1066 1068 setting_cross_project_subtasks: Allow cross-project subtasks
@@ -712,6 +712,8 en:
712 712 label_any_issues_in_project: any issues in project
713 713 label_any_issues_not_in_project: any issues not in project
714 714 label_no_issues_in_project: no issues in project
715 label_any_open_issues: any open issues
716 label_no_open_issues: no open issues
715 717 label_day_plural: days
716 718 label_repository: Repository
717 719 label_repository_new: New repository
@@ -732,6 +732,8 fr:
732 732 label_any_issues_in_project: une demande du projet
733 733 label_any_issues_not_in_project: une demande hors du projet
734 734 label_no_issues_in_project: aucune demande du projet
735 label_any_open_issues: une demande ouverte
736 label_no_open_issues: aucune demande ouverte
735 737 label_day_plural: jours
736 738 label_repository: Dépôt
737 739 label_repository_new: Nouveau dépôt
@@ -275,6 +275,8 function toggleOperator(field) {
275 275 case "y":
276 276 case "o":
277 277 case "c":
278 case "*o":
279 case "!o":
278 280 enableValues(field, []);
279 281 break;
280 282 case "><":
@@ -846,6 +846,34 class QueryTest < ActiveSupport::TestCase
846 846 assert_not_include 3, ids
847 847 end
848 848
849 def test_filter_on_relations_with_any_open_issues
850 IssueRelation.delete_all
851 # Issue 1 is blocked by 8, which is closed
852 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
853 # Issue 2 is blocked by 3, which is open
854 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
855
856 query = IssueQuery.new(:name => '_')
857 query.filters = {"blocked" => {:operator => "*o", :values => ['']}}
858 ids = find_issues_with_query(query).map(&:id)
859 assert_equal [], ids & [1]
860 assert_include 2, ids
861 end
862
863 def test_filter_on_relations_with_no_open_issues
864 IssueRelation.delete_all
865 # Issue 1 is blocked by 8, which is closed
866 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
867 # Issue 2 is blocked by 3, which is open
868 IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
869
870 query = IssueQuery.new(:name => '_')
871 query.filters = {"blocked" => {:operator => "!o", :values => ['']}}
872 ids = find_issues_with_query(query).map(&:id)
873 assert_equal [], ids & [2]
874 assert_include 1, ids
875 end
876
849 877 def test_filter_on_relations_with_no_issues
850 878 IssueRelation.delete_all
851 879 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
General Comments 0
You need to be logged in to leave comments. Login now