]> source.dussan.org Git - redmine.git/commitdiff
Add "Any searchable text" filter for issues (#38402).
authorGo MAEDA <maeda@farend.jp>
Wed, 5 Apr 2023 09:22:34 +0000 (09:22 +0000)
committerGo MAEDA <maeda@farend.jp>
Wed, 5 Apr 2023 09:22:34 +0000 (09:22 +0000)
Patch by Go MAEDA and Holger Just.

git-svn-id: https://svn.redmine.org/redmine/trunk@22164 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/issue_query.rb
app/models/query.rb
config/locales/en.yml
public/javascripts/application.js
test/unit/query_test.rb

index 9f541cc5463742f009684678510d026d251e49a1..1c60c6b61f5acb333954f9d79831131e44734038 100644 (file)
@@ -272,6 +272,8 @@ class IssueQuery < Query
 
     add_available_filter "issue_id", :type => :integer, :label => :label_issue
 
+    add_available_filter "any_searchable", :type => :search
+
     Tracker.disabled_core_fields(trackers).each do |field|
       delete_available_filter field
     end
@@ -774,6 +776,33 @@ class IssueQuery < Query
     sql_for_field(field, operator, value, Project.table_name, "status")
   end
 
+  def sql_for_any_searchable_field(field, operator, value)
+    question = value.first
+
+    # Fetch search results only from the selected and visible (sub-)projects
+    project_scope = Project.allowed_to(:view_issues)
+    if project
+      projects = project_scope.where(project_statement)
+    elsif has_filter?('project_id')
+      projects = project_scope.where(
+        sql_for_field('project_id', operator_for('project_id'), values_for('project_id'), Project.table_name, 'id')
+      )
+    else
+      projects = nil
+    end
+
+    fetcher = Redmine::Search::Fetcher.new(
+      question, User.current, ['issue'], projects, attachments: '0'
+    )
+    ids = fetcher.result_ids.map(&:last)
+    if ids.present?
+      sw = operator == '!~' ? 'NOT' : ''
+      "#{Issue.table_name}.id #{sw} IN (#{ids.join(',')})"
+    else
+      '1=0'
+    end
+  end
+
   def find_assigned_to_id_filter_values(values)
     Principal.visible.where(:id => values).map {|p| [p.name, p.id.to_s]}
   end
index 473ea4d866a1bbb33a1242f6993489227097b2aa..289d683f6505768ac6f33d156ba7cdd2e9918b11 100644 (file)
@@ -325,6 +325,7 @@ class Query < ActiveRecord::Base
     :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ],
     :string => [ "~", "=", "!~", "!", "^", "$", "!*", "*" ],
     :text => [  "~", "!~", "^", "$", "!*", "*" ],
+    :search => [ "~", "!~" ],
     :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
     :float => [ "=", ">=", "<=", "><", "!*", "*" ],
     :relation => ["=", "!", "=p", "=!p", "!p", "*o", "!o", "!*", "*"],
index 2e1378ff7b463baead645d1f917d9016c6477597..678aab66dc127b9dcb64ad7394ca8a8d47a79322 100644 (file)
@@ -417,6 +417,7 @@ en:
   field_default_issue_query: Default issue query
   field_default_project_query: Default project query
   field_default_time_entry_activity: Default spent time activity
+  field_any_searchable: Any searchable text
 
   setting_app_title: Application title
   setting_welcome_text: Welcome text
index 7b2e7725e13bb76e94552ff466a5524ef7cbeb06..6d01dc2b9502109f172fe4054ae75589d4497977 100644 (file)
@@ -220,6 +220,7 @@ function buildFilterRow(field, operator, values) {
     break;
   case "string":
   case "text":
+  case "search":
     tr.find('td.values').append(
       '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
     );
index b41aa507c4ab55e3488b24678d14f988a418770b..2b02a1e07d0b5e02fab3c02aa817173f2ee239e9 100644 (file)
@@ -844,6 +844,36 @@ class QueryTest < ActiveSupport::TestCase
     assert_equal [1, 3], find_issues_with_query(query).map(&:id).sort
   end
 
+  def test_fileter_any_searchable
+    User.current = User.find(1)
+    query = IssueQuery.new(
+      :name => '_',
+      :filters => {
+        'any_searchable' => {
+          :operator => '~',
+          :values => ['recipe']
+        }
+      }
+    )
+    result = find_issues_with_query(query)
+    assert_equal [1, 2, 3], result.map(&:id).sort
+  end
+
+  def test_fileter_any_searchable_should_search_searchable_custom_fields
+    User.current = User.find(1)
+    query = IssueQuery.new(
+      :name => '_',
+      :filters => {
+        'any_searchable' => {
+          :operator => '~',
+          :values => ['125']
+        }
+      }
+    )
+    result = find_issues_with_query(query)
+    assert_equal [1, 3], result.map(&:id).sort
+  end
+
   def test_filter_updated_by
     user = User.generate!
     Journal.create!(:user_id => user.id, :journalized => Issue.find(2), :notes => 'Notes')