Adds no_issue_in_project operator for relations filter (#3265).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10559 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2012-10-04 18:10:41 +00:00
parent 44137cb1d4
commit b9d7c22297
5 changed files with 27 additions and 6 deletions

View File

@ -115,7 +115,8 @@ class Query < ActiveRecord::Base
"~" => :label_contains,
"!~" => :label_not_contains,
"=p" => :label_any_issues_in_project,
"=!p" => :label_any_issues_not_in_project}
"=!p" => :label_any_issues_not_in_project,
"!p" => :label_no_issues_in_project}
cattr_reader :operators
@ -129,7 +130,7 @@ class Query < ActiveRecord::Base
:text => [ "~", "!~", "!*", "*" ],
:integer => [ "=", ">=", "<=", "><", "!*", "*" ],
:float => [ "=", ">=", "<=", "><", "!*", "*" ],
:relation => ["=", "=p", "=!p", "!*", "*"]}
:relation => ["=", "=p", "=!p", "!p", "!*", "*"]}
cattr_reader :operators_by_filter_type
@ -807,14 +808,15 @@ class Query < ActiveRecord::Base
when "=", "!"
op = (operator == "=" ? 'IN' : 'NOT IN')
"#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})"
when "=p", "=!p"
op = (operator == "=p" ? '=' : '<>')
"#{Issue.table_name}.id IN (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{op} #{value.first.to_i})"
when "=p", "=!p", "!p"
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 = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})"
end
if relation_options[:sym] == field && !options[:reverse]
sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)]
sqls.join(["!", "!*"].include?(operator) ? " AND " : " OR ")
sqls.join(["!", "!*", "!p"].include?(operator) ? " AND " : " OR ")
else
sql
end

View File

@ -674,6 +674,7 @@ en:
label_not_contains: doesn't contain
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_day_plural: days
label_repository: Repository
label_repository_new: New repository

View File

@ -664,6 +664,7 @@ fr:
label_not_contains: ne contient pas
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_day_plural: jours
label_repository: Dépôt
label_repository_new: Nouveau dépôt

View File

@ -260,6 +260,7 @@ function toggleOperator(field) {
break;
case "=p":
case "=!p":
case "!p":
enableValues(field, [1]);
break;
default:

View File

@ -672,6 +672,22 @@ class QueryTest < ActiveSupport::TestCase
assert_equal [1], find_issues_with_query(query).map(&:id).sort
end
def test_filter_on_relations_with_no_issues_in_a_project
IssueRelation.delete_all
with_settings :cross_project_issue_relations => '1' do
IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first)
IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first)
IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3))
end
query = Query.new(:name => '_')
query.filters = {"relates" => {:operator => '!p', :values => ['2']}}
ids = find_issues_with_query(query).map(&:id).sort
assert_include 2, ids
assert_not_include 1, ids
assert_not_include 3, 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))