@@ -535,6 +535,9 class IssueQuery < Query | |||||
535 | op = (operator == "!p" ? 'NOT IN' : 'IN') |
|
535 | op = (operator == "!p" ? 'NOT IN' : 'IN') | |
536 | comp = (operator == "=!p" ? '<>' : '=') |
|
536 | comp = (operator == "=!p" ? '<>' : '=') | |
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})" |
|
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 | end |
|
541 | end | |
539 |
|
542 | |||
540 | if relation_options[:sym] == field && !options[:reverse] |
|
543 | if relation_options[:sym] == field && !options[:reverse] |
@@ -203,7 +203,9 class Query < ActiveRecord::Base | |||||
203 | "!~" => :label_not_contains, |
|
203 | "!~" => :label_not_contains, | |
204 | "=p" => :label_any_issues_in_project, |
|
204 | "=p" => :label_any_issues_in_project, | |
205 | "=!p" => :label_any_issues_not_in_project, |
|
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 | class_attribute :operators_by_filter_type |
|
211 | class_attribute :operators_by_filter_type | |
@@ -218,7 +220,7 class Query < ActiveRecord::Base | |||||
218 | :text => [ "~", "!~", "!*", "*" ], |
|
220 | :text => [ "~", "!~", "!*", "*" ], | |
219 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
221 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], | |
220 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
222 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], | |
221 | :relation => ["=", "=p", "=!p", "!p", "!*", "*"], |
|
223 | :relation => ["=", "=p", "=!p", "!p", "*o", "!o", "!*", "*"], | |
222 | :tree => ["=", "~", "!*", "*"] |
|
224 | :tree => ["=", "~", "!*", "*"] | |
223 | } |
|
225 | } | |
224 |
|
226 | |||
@@ -281,7 +283,7 class Query < ActiveRecord::Base | |||||
281 | # filter requires one or more values |
|
283 | # filter requires one or more values | |
282 | (values_for(field) and !values_for(field).first.blank?) or |
|
284 | (values_for(field) and !values_for(field).first.blank?) or | |
283 | # filter doesn't require any value |
|
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 | end if filters |
|
287 | end if filters | |
286 | end |
|
288 | end | |
287 |
|
289 |
@@ -1061,6 +1061,8 en-GB: | |||||
1061 | permission_view_private_notes: View private notes |
|
1061 | permission_view_private_notes: View private notes | |
1062 | permission_set_notes_private: Set notes as private |
|
1062 | permission_set_notes_private: Set notes as private | |
1063 | label_no_issues_in_project: no issues in project |
|
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 | label_any: all |
|
1066 | label_any: all | |
1065 | label_last_n_weeks: last %{count} weeks |
|
1067 | label_last_n_weeks: last %{count} weeks | |
1066 | setting_cross_project_subtasks: Allow cross-project subtasks |
|
1068 | setting_cross_project_subtasks: Allow cross-project subtasks |
@@ -712,6 +712,8 en: | |||||
712 | label_any_issues_in_project: any issues in project |
|
712 | label_any_issues_in_project: any issues in project | |
713 | label_any_issues_not_in_project: any issues not in project |
|
713 | label_any_issues_not_in_project: any issues not in project | |
714 | label_no_issues_in_project: no issues in project |
|
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 | label_day_plural: days |
|
717 | label_day_plural: days | |
716 | label_repository: Repository |
|
718 | label_repository: Repository | |
717 | label_repository_new: New repository |
|
719 | label_repository_new: New repository |
@@ -732,6 +732,8 fr: | |||||
732 | label_any_issues_in_project: une demande du projet |
|
732 | label_any_issues_in_project: une demande du projet | |
733 | label_any_issues_not_in_project: une demande hors du projet |
|
733 | label_any_issues_not_in_project: une demande hors du projet | |
734 | label_no_issues_in_project: aucune demande du projet |
|
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 | label_day_plural: jours |
|
737 | label_day_plural: jours | |
736 | label_repository: DΓ©pΓ΄t |
|
738 | label_repository: DΓ©pΓ΄t | |
737 | label_repository_new: Nouveau dΓ©pΓ΄t |
|
739 | label_repository_new: Nouveau dΓ©pΓ΄t |
@@ -275,6 +275,8 function toggleOperator(field) { | |||||
275 | case "y": |
|
275 | case "y": | |
276 | case "o": |
|
276 | case "o": | |
277 | case "c": |
|
277 | case "c": | |
|
278 | case "*o": | |||
|
279 | case "!o": | |||
278 | enableValues(field, []); |
|
280 | enableValues(field, []); | |
279 | break; |
|
281 | break; | |
280 | case "><": |
|
282 | case "><": |
@@ -846,6 +846,34 class QueryTest < ActiveSupport::TestCase | |||||
846 | assert_not_include 3, ids |
|
846 | assert_not_include 3, ids | |
847 | end |
|
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 | def test_filter_on_relations_with_no_issues |
|
877 | def test_filter_on_relations_with_no_issues | |
850 | IssueRelation.delete_all |
|
878 | IssueRelation.delete_all | |
851 | IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) |
|
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