@@ -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