diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e2ddd3df5a0dd1fe4bf4591d36f9e3c7c6ef376f..4a957a9cb8c86a544e4d013d62730649a44aff77 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -540,16 +540,24 @@ class ProjectsController < ApplicationController end def search - @token = params[:token] + @question = params[:q] || "" + @question.strip! + @all_words = params[:all_words] || (params[:submit] ? false : true) @scope = params[:scope] || (params[:submit] ? [] : %w(issues news documents) ) - - if @token and @token.length > 2 - @token.strip! - like_token = "%#{@token}%" + if !@question.empty? + # tokens must be at least 3 character long + @tokens = @question.split.uniq.select {|w| w.length > 2 } + # no more than 5 tokens to search for + @tokens.slice! 5..-1 if @tokens.size > 5 + # strings used in sql like statement + like_tokens = @tokens.collect {|w| "%#{w}%"} + operator = @all_words ? " AND " : " OR " + limit = 10 @results = [] - @results += @project.issues.find(:all, :include => :author, :conditions => ["issues.subject like ? or issues.description like ?", like_token, like_token] ) if @scope.include? 'issues' - @results += @project.news.find(:all, :conditions => ["news.title like ? or news.description like ?", like_token, like_token], :include => :author ) if @scope.include? 'news' - @results += @project.documents.find(:all, :conditions => ["title like ? or description like ?", like_token, like_token] ) if @scope.include? 'documents' + @results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(issues.subject) like ? OR LOWER(issues.description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues' + @results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(news.title) like ? OR LOWER(news.description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news' + @results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents' + @question = @tokens.join(" ") end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index a6c033d0ffc70dede88079b559f890441ff7efb9..694dd91241be5045d585264dc4eca64f14bea987 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -16,8 +16,14 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module ProjectsHelper - def result_overview(text, token) - match = excerpt(text, token) - match ? highlight(match, token) : truncate(text, 150) + + def highlight_tokens(text, tokens) + return text unless tokens && !tokens.empty? + regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE + result = '' + text.split(regexp).each_with_index do |words, i| + result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight')) + end + result end end diff --git a/app/views/projects/search.rhtml b/app/views/projects/search.rhtml index df95ee3ae7cf1d3d090ae51568332cf631ad8f5f..e699d8731c7c008efdcc92ec769e4bd81685c24b 100644 --- a/app/views/projects/search.rhtml +++ b/app/views/projects/search.rhtml @@ -2,10 +2,11 @@ <div class="box"> <% form_tag({:action => 'search', :id => @project}, :method => :get) do %> -<p><%= text_field_tag 'token', @token, :size => 30 %> +<p><%= text_field_tag 'q', @question, :size => 30 %> <%= check_box_tag 'scope[]', 'issues', (@scope.include? 'issues') %> <label><%= l(:label_issue_plural) %></label> <%= check_box_tag 'scope[]', 'news', (@scope.include? 'news') %> <label><%= l(:label_news_plural) %></label> -<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %> <label><%= l(:label_document_plural) %></label></p> +<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %> <label><%= l(:label_document_plural) %></label><br /> +<%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %></p> <%= submit_tag l(:button_submit), :name => 'submit' %> <% end %> </div> @@ -16,16 +17,16 @@ <% @results.each do |e| %> <li><p> <% if e.is_a? Issue %> - <%= link_to "#{e.tracker.name} ##{e.id}", :controller => 'issues', :action => 'show', :id => e %>: <%= highlight(h(e.subject), @token) %><br /> - <%= result_overview(e.description, @token) %><br /> + <%= link_to "#{e.tracker.name} ##{e.id}", :controller => 'issues', :action => 'show', :id => e %>: <%= highlight_tokens(h(e.subject), @tokens) %><br /> + <%= highlight_tokens(e.description, @tokens) %><br /> <i><%= e.author.name %>, <%= format_time(e.created_on) %></i> <% elsif e.is_a? News %> - <%=l(:label_news)%>: <%= link_to highlight(h(e.title), @token), :controller => 'news', :action => 'show', :id => e %><br /> - <%= result_overview(e.description, @token) %><br /> + <%=l(:label_news)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'news', :action => 'show', :id => e %><br /> + <%= highlight_tokens(e.description, @tokens) %><br /> <i><%= e.author.name %>, <%= format_time(e.created_on) %></i> <% elsif e.is_a? Document %> - <%=l(:label_document)%>: <%= link_to highlight(h(e.title), @token), :controller => 'documents', :action => 'show', :id => e %><br /> - <%= result_overview(e.description, @token) %><br /> + <%=l(:label_document)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'documents', :action => 'show', :id => e %><br /> + <%= highlight_tokens(e.description, @tokens) %><br /> <i><%= format_time(e.created_on) %></i> <% end %> </p></li> diff --git a/lang/de.yml b/lang/de.yml index 69cc23df72babcc1a5e105ea729cb1658fd91cc0..cb253b3836941c3c5b78abe730067b5fe8928fe5 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -321,6 +321,7 @@ label_roadmap: Roadmap label_search: Suche label_result: %d Resultat label_result_plural: %d Resultate +label_all_words: Alle Wörter button_login: Einloggen button_submit: Einreichen diff --git a/lang/en.yml b/lang/en.yml index c8026e6295e9d1c1e82a238ea7f0a42ffdead821..20a43e56459c41ee4e8bb60644e1d1b53d940394 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -321,6 +321,7 @@ label_roadmap: Roadmap label_search: Search label_result: %d result label_result_plural: %d results +label_all_words: All words button_login: Login button_submit: Submit diff --git a/lang/es.yml b/lang/es.yml index 79c96adf48d8d238cad7fbbc2290cd764c48a878..3004470e66febbeeb9a6372b4d3b8538ec046183 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -321,6 +321,7 @@ label_roadmap: Roadmap label_search: Búsqueda label_result: %d resultado label_result_plural: %d resultados +label_all_words: Todas las palabras button_login: Conexión button_submit: Someter diff --git a/lang/fr.yml b/lang/fr.yml index 90e2c6628f6bbdc5b83f0c045a3384dec278f029..fba9cb9fbb8c8c5f881a3ee5b59ad6f5305fe131 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -321,6 +321,7 @@ label_roadmap: Roadmap label_search: Recherche label_result: %d résultat label_result_plural: %d résultats +label_all_words: Tous les mots button_login: Connexion button_submit: Soumettre diff --git a/lang/ja.yml b/lang/ja.yml index b473f4c0aa1db6dcec806f357aa156838f43ce5c..86dcd7f3f1383e0c813c78b6fe6e7de7f314e8be 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -322,6 +322,7 @@ label_roadmap: ãƒãƒ¼ãƒ‰ãƒžãƒƒãƒ— label_search: 検索 label_result: %d 件ã®çµæžœ label_result_plural: %d 件ã®çµæžœ +label_all_words: ã™ã¹ã¦ã®å˜èªž button_login: ãƒã‚°ã‚¤ãƒ³ button_submit: 変更 diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 732349adf1b565ed6e3d83da2ae45d0651a8f9ee..40997af979fb846c329e32f9208e024bd2cad367 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -243,7 +243,7 @@ legend {color: #505050;} hr { border:0; border-top: dotted 1px #fff; border-bottom: dotted 1px #c0c0c0; } table p {margin:0; padding:0;} -strong.highlight { background-color: #FCFD8D;} +.highlight { background-color: #FCFD8D;} div.square { border: 1px solid #999;