mirror of
https://github.com/meineerde/redmine.git
synced 2026-03-03 07:51:54 +00:00
Ability to filter issues blocked by any/no open issues (#16621).
Patch by Arthur Andersen. git-svn-id: http://svn.redmine.org/redmine/trunk@14809 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
8123006bb3
commit
d3d7678c76
@ -535,6 +535,9 @@ class IssueQuery < Query
|
||||
op = (operator == "!p" ? 'NOT IN' : 'IN')
|
||||
comp = (operator == "=!p" ? '<>' : '=')
|
||||
"#{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})"
|
||||
when "*o", "!o"
|
||||
op = (operator == "!o" ? 'NOT IN' : 'IN')
|
||||
"#{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}))"
|
||||
end
|
||||
|
||||
if relation_options[:sym] == field && !options[:reverse]
|
||||
|
||||
@ -203,7 +203,9 @@ class Query < ActiveRecord::Base
|
||||
"!~" => :label_not_contains,
|
||||
"=p" => :label_any_issues_in_project,
|
||||
"=!p" => :label_any_issues_not_in_project,
|
||||
"!p" => :label_no_issues_in_project
|
||||
"!p" => :label_no_issues_in_project,
|
||||
"*o" => :label_any_open_issues,
|
||||
"!o" => :label_no_open_issues
|
||||
}
|
||||
|
||||
class_attribute :operators_by_filter_type
|
||||
@ -218,7 +220,7 @@ class Query < ActiveRecord::Base
|
||||
:text => [ "~", "!~", "!*", "*" ],
|
||||
:integer => [ "=", ">=", "<=", "><", "!*", "*" ],
|
||||
:float => [ "=", ">=", "<=", "><", "!*", "*" ],
|
||||
:relation => ["=", "=p", "=!p", "!p", "!*", "*"],
|
||||
:relation => ["=", "=p", "=!p", "!p", "*o", "!o", "!*", "*"],
|
||||
:tree => ["=", "~", "!*", "*"]
|
||||
}
|
||||
|
||||
@ -281,7 +283,7 @@ class Query < ActiveRecord::Base
|
||||
# filter requires one or more values
|
||||
(values_for(field) and !values_for(field).first.blank?) or
|
||||
# filter doesn't require any value
|
||||
["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
|
||||
["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "*o", "!o"].include? operator_for(field)
|
||||
end if filters
|
||||
end
|
||||
|
||||
|
||||
@ -1061,6 +1061,8 @@ en-GB:
|
||||
permission_view_private_notes: View private notes
|
||||
permission_set_notes_private: Set notes as private
|
||||
label_no_issues_in_project: no issues in project
|
||||
label_any_open_issues: any open issues
|
||||
label_no_open_issues: no open issues
|
||||
label_any: all
|
||||
label_last_n_weeks: last %{count} weeks
|
||||
setting_cross_project_subtasks: Allow cross-project subtasks
|
||||
|
||||
@ -712,6 +712,8 @@ en:
|
||||
label_any_issues_in_project: any issues in project
|
||||
label_any_issues_not_in_project: any issues not in project
|
||||
label_no_issues_in_project: no issues in project
|
||||
label_any_open_issues: any open issues
|
||||
label_no_open_issues: no open issues
|
||||
label_day_plural: days
|
||||
label_repository: Repository
|
||||
label_repository_new: New repository
|
||||
|
||||
@ -732,6 +732,8 @@ fr:
|
||||
label_any_issues_in_project: une demande du projet
|
||||
label_any_issues_not_in_project: une demande hors du projet
|
||||
label_no_issues_in_project: aucune demande du projet
|
||||
label_any_open_issues: une demande ouverte
|
||||
label_no_open_issues: aucune demande ouverte
|
||||
label_day_plural: jours
|
||||
label_repository: Dépôt
|
||||
label_repository_new: Nouveau dépôt
|
||||
|
||||
@ -275,6 +275,8 @@ function toggleOperator(field) {
|
||||
case "y":
|
||||
case "o":
|
||||
case "c":
|
||||
case "*o":
|
||||
case "!o":
|
||||
enableValues(field, []);
|
||||
break;
|
||||
case "><":
|
||||
|
||||
@ -846,6 +846,34 @@ class QueryTest < ActiveSupport::TestCase
|
||||
assert_not_include 3, ids
|
||||
end
|
||||
|
||||
def test_filter_on_relations_with_any_open_issues
|
||||
IssueRelation.delete_all
|
||||
# Issue 1 is blocked by 8, which is closed
|
||||
IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
|
||||
# Issue 2 is blocked by 3, which is open
|
||||
IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
|
||||
|
||||
query = IssueQuery.new(:name => '_')
|
||||
query.filters = {"blocked" => {:operator => "*o", :values => ['']}}
|
||||
ids = find_issues_with_query(query).map(&:id)
|
||||
assert_equal [], ids & [1]
|
||||
assert_include 2, ids
|
||||
end
|
||||
|
||||
def test_filter_on_relations_with_no_open_issues
|
||||
IssueRelation.delete_all
|
||||
# Issue 1 is blocked by 8, which is closed
|
||||
IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(1), :issue_to => Issue.find(8))
|
||||
# Issue 2 is blocked by 3, which is open
|
||||
IssueRelation.create!(:relation_type => "blocked", :issue_from => Issue.find(2), :issue_to => Issue.find(3))
|
||||
|
||||
query = IssueQuery.new(:name => '_')
|
||||
query.filters = {"blocked" => {:operator => "!o", :values => ['']}}
|
||||
ids = find_issues_with_query(query).map(&:id)
|
||||
assert_equal [], ids & [2]
|
||||
assert_include 1, ids
|
||||
end
|
||||
|
||||
def test_filter_on_relations_with_no_issues
|
||||
IssueRelation.delete_all
|
||||
IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user