diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index dc27cd47b..8c6eb1f84 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -189,6 +189,8 @@ class IssueQuery < Query add_available_filter "done_ratio", :type => :integer + add_available_filter "notes", :type => :text + if User.current.allowed_to?(:set_issues_private, nil, :global => true) || User.current.allowed_to?(:set_own_issues_private, nil, :global => true) add_available_filter( @@ -564,6 +566,14 @@ class IssueQuery < Query "(#{nl} #{sql_for_field("fixed_version_id", "=", version_ids, Issue.table_name, "fixed_version_id")})" end + def sql_for_notes_field(field, operator, value) + subquery = "SELECT 1 FROM #{Journal.table_name}" + + " WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id" + + " AND (#{sql_for_field field, operator.ends_with?("~") ? "~" : "*", value, Journal.table_name, 'notes'})" + + " AND (#{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)})" + "#{operator.starts_with?("!") ? "NOT EXISTS" : "EXISTS"} (#{subquery})" + end + def sql_for_is_private_field(field, operator, value) op = (operator == "=" ? 'IN' : 'NOT IN') va = diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index a6dff724c..4793de424 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -803,6 +803,43 @@ class QueryTest < ActiveSupport::TestCase end end + def test_filter_notes + user = User.generate! + Journal.create!(:user_id => user.id, :journalized => Issue.find(2), :notes => 'Notes') + Journal.create!(:user_id => user.id, :journalized => Issue.find(3), :notes => 'Notes') + + issue_journals = Issue.find(1).journals.sort + assert_equal ['Journal notes', 'Some notes with Redmine links: #2, r2.'], issue_journals.map(&:notes) + assert_equal [false, false], issue_journals.map(&:private_notes) + + query = IssueQuery.new(:name => '_') + filter_name = "notes" + assert_include filter_name, query.available_filters.keys + + query.filters = {filter_name => {:operator => '~', :values => ['Notes']}} + assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort + + query.filters = {filter_name => {:operator => '!~', :values => ['Notes']}} + assert_equal (Issue.ids.sort - [1, 2, 3]), find_issues_with_query(query).map(&:id).sort + end + + def test_filter_notes_should_ignore_private_notes_that_are_not_visible + user = User.generate! + Journal.create!(:user_id => user.id, :journalized => Issue.find(2), :notes => 'Notes', :private_notes => true) + Journal.create!(:user_id => user.id, :journalized => Issue.find(3), :notes => 'Notes') + + issue_journals = Issue.find(1).journals.sort + assert_equal ['Journal notes', 'Some notes with Redmine links: #2, r2.'], issue_journals.map(&:notes) + assert_equal [false, false], issue_journals.map(&:private_notes) + + query = IssueQuery.new(:name => '_') + filter_name = "notes" + assert_include filter_name, query.available_filters.keys + + query.filters = {filter_name => {:operator => '~', :values => ['Notes']}} + assert_equal [1, 3], find_issues_with_query(query).map(&:id).sort + end + def test_filter_updated_by user = User.generate! Journal.create!(:user_id => user.id, :journalized => Issue.find(2), :notes => 'Notes')