##// END OF EJS Templates
Option to search open issues only (#10734)....
Jean-Philippe Lang -
r13476:0ed895388b89
parent child
Show More
@@ -24,6 +24,7 class SearchController < ApplicationController
24 @all_words = params[:all_words] ? params[:all_words].present? : true
24 @all_words = params[:all_words] ? params[:all_words].present? : true
25 @titles_only = params[:titles_only] ? params[:titles_only].present? : false
25 @titles_only = params[:titles_only] ? params[:titles_only].present? : false
26 @search_attachments = params[:attachments].presence || '0'
26 @search_attachments = params[:attachments].presence || '0'
27 @open_issues = params[:open_issues] ? params[:open_issues].present? : false
27
28
28 # quick jump to an issue
29 # quick jump to an issue
29 if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
30 if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
@@ -56,7 +57,7 class SearchController < ApplicationController
56
57
57 fetcher = Redmine::Search::Fetcher.new(
58 fetcher = Redmine::Search::Fetcher.new(
58 @question, User.current, @scope, projects_to_search,
59 @question, User.current, @scope, projects_to_search,
59 :all_words => @all_words, :titles_only => @titles_only, :attachments => @search_attachments,
60 :all_words => @all_words, :titles_only => @titles_only, :attachments => @search_attachments, :open_issues => @open_issues,
60 :cache => params[:page].present?
61 :cache => params[:page].present?
61 )
62 )
62
63
@@ -47,7 +47,8 class Issue < ActiveRecord::Base
47 acts_as_customizable
47 acts_as_customizable
48 acts_as_watchable
48 acts_as_watchable
49 acts_as_searchable :columns => ['subject', "#{table_name}.description"],
49 acts_as_searchable :columns => ['subject', "#{table_name}.description"],
50 :preload => [:project, :status, :tracker]
50 :preload => [:project, :status, :tracker],
51 :scope => lambda {|options| options[:open_issues] ? self.open : self.all}
51
52
52 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"},
53 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"},
53 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
54 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
@@ -20,6 +20,7
20 <fieldset class="collapsible collapsed">
20 <fieldset class="collapsible collapsed">
21 <legend onclick="toggleFieldset(this);"><%= l(:label_options) %></legend>
21 <legend onclick="toggleFieldset(this);"><%= l(:label_options) %></legend>
22 <div id="options-content" style="display:none;">
22 <div id="options-content" style="display:none;">
23 <p><label><%= check_box_tag 'open_issues', 1, @open_issues %> <%= l(:label_search_open_issues_only) %></label></p>
23 <p>
24 <p>
24 <label><%= radio_button_tag 'attachments', '0', @search_attachments == '0' %> <%= l(:label_search_attachments_no) %></label>
25 <label><%= radio_button_tag 'attachments', '0', @search_attachments == '0' %> <%= l(:label_search_attachments_no) %></label>
25 <label><%= radio_button_tag 'attachments', '1', @search_attachments == '1' %> <%= l(:label_search_attachments_yes) %></label>
26 <label><%= radio_button_tag 'attachments', '1', @search_attachments == '1' %> <%= l(:label_search_attachments_yes) %></label>
@@ -930,6 +930,7 en:
930 label_search_attachments_yes: Search attachment filenames and descriptions
930 label_search_attachments_yes: Search attachment filenames and descriptions
931 label_search_attachments_no: Do not search attachments
931 label_search_attachments_no: Do not search attachments
932 label_search_attachments_only: Search attachments only
932 label_search_attachments_only: Search attachments only
933 label_search_open_issues_only: Open issues only
933
934
934 button_login: Login
935 button_login: Login
935 button_submit: Submit
936 button_submit: Submit
@@ -950,6 +950,7 fr:
950 label_search_attachments_yes: Rechercher les noms et descriptions de fichiers
950 label_search_attachments_yes: Rechercher les noms et descriptions de fichiers
951 label_search_attachments_no: Ne pas rechercher les fichiers
951 label_search_attachments_no: Ne pas rechercher les fichiers
952 label_search_attachments_only: Rechercher les fichiers uniquement
952 label_search_attachments_only: Rechercher les fichiers uniquement
953 label_search_open_issues_only: Demandes ouvertes uniquement
953
954
954 button_login: Connexion
955 button_login: Connexion
955 button_submit: Soumettre
956 button_submit: Soumettre
@@ -89,7 +89,7 module Redmine
89
89
90 unless options[:attachments] == 'only'
90 unless options[:attachments] == 'only'
91 r = fetch_ranks_and_ids(
91 r = fetch_ranks_and_ids(
92 search_scope(user, projects).
92 search_scope(user, projects, options).
93 where(search_tokens_condition(columns, tokens, options[:all_words])),
93 where(search_tokens_condition(columns, tokens, options[:all_words])),
94 options[:limit]
94 options[:limit]
95 )
95 )
@@ -109,7 +109,7 module Redmine
109 visibility = clauses.join(' OR ')
109 visibility = clauses.join(' OR ')
110
110
111 r |= fetch_ranks_and_ids(
111 r |= fetch_ranks_and_ids(
112 search_scope(user, projects).
112 search_scope(user, projects, options).
113 joins(:custom_values).
113 joins(:custom_values).
114 where(visibility).
114 where(visibility).
115 where(search_tokens_condition(["#{CustomValue.table_name}.value"], tokens, options[:all_words])),
115 where(search_tokens_condition(["#{CustomValue.table_name}.value"], tokens, options[:all_words])),
@@ -121,7 +121,7 module Redmine
121
121
122 if !options[:titles_only] && searchable_options[:search_journals]
122 if !options[:titles_only] && searchable_options[:search_journals]
123 r |= fetch_ranks_and_ids(
123 r |= fetch_ranks_and_ids(
124 search_scope(user, projects).
124 search_scope(user, projects, options).
125 joins(:journals).
125 joins(:journals).
126 where("#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes)})", false).
126 where("#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes)})", false).
127 where(search_tokens_condition(["#{Journal.table_name}.notes"], tokens, options[:all_words])),
127 where(search_tokens_condition(["#{Journal.table_name}.notes"], tokens, options[:all_words])),
@@ -133,7 +133,7 module Redmine
133
133
134 if searchable_options[:search_attachments] && (options[:titles_only] ? options[:attachments] == 'only' : options[:attachments] != '0')
134 if searchable_options[:search_attachments] && (options[:titles_only] ? options[:attachments] == 'only' : options[:attachments] != '0')
135 r |= fetch_ranks_and_ids(
135 r |= fetch_ranks_and_ids(
136 search_scope(user, projects).
136 search_scope(user, projects, options).
137 joins(:attachments).
137 joins(:attachments).
138 where(search_tokens_condition(["#{Attachment.table_name}.filename", "#{Attachment.table_name}.description"], tokens, options[:all_words])),
138 where(search_tokens_condition(["#{Attachment.table_name}.filename", "#{Attachment.table_name}.description"], tokens, options[:all_words])),
139 options[:limit]
139 options[:limit]
@@ -180,7 +180,7 module Redmine
180 private :fetch_ranks_and_ids
180 private :fetch_ranks_and_ids
181
181
182 # Returns the search scope for user and projects
182 # Returns the search scope for user and projects
183 def search_scope(user, projects)
183 def search_scope(user, projects, options={})
184 if projects.is_a?(Array) && projects.empty?
184 if projects.is_a?(Array) && projects.empty?
185 # no results
185 # no results
186 return none
186 return none
@@ -188,7 +188,7 module Redmine
188
188
189 scope = (searchable_options[:scope] || self)
189 scope = (searchable_options[:scope] || self)
190 if scope.is_a? Proc
190 if scope.is_a? Proc
191 scope = scope.call
191 scope = scope.call(options)
192 end
192 end
193
193
194 if respond_to?(:visible) && !searchable_options.has_key?(:permission)
194 if respond_to?(:visible) && !searchable_options.has_key?(:permission)
@@ -209,6 +209,15 class SearchControllerTest < ActionController::TestCase
209 assert_equal 2, results.size
209 assert_equal 2, results.size
210 end
210 end
211
211
212 def test_search_open_issues
213 Issue.generate! :subject => 'search_open'
214 Issue.generate! :subject => 'search_open', :status_id => 5
215
216 get :index, :id => 1, :q => 'search_open', :open_issues => '1'
217 results = assigns(:results)
218 assert_equal 1, results.size
219 end
220
212 def test_search_all_words
221 def test_search_all_words
213 # 'all words' is on by default
222 # 'all words' is on by default
214 get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1'
223 get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1'
General Comments 0
You need to be logged in to leave comments. Login now