Commit f8fcdd69eb8771706a0e916ce027732cfde6a35c

Authored by AntonioTerceiro
1 parent 1089c991

ActionItem48: filtering search: user can select to search in the current filter …

…or the whole site, /and/ in specific assets (articles, comments, people  etc)


git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1612 3f533792-8f58-4932-b0fe-aaf55b0a4547
app/controllers/application.rb
@@ -103,10 +103,12 @@ class ApplicationController < ActionController::Base @@ -103,10 +103,12 @@ class ApplicationController < ActionController::Base
103 end 103 end
104 104
105 def load_category 105 def load_category
106 - path = params[:category_path].join('/')  
107 - @category = environment.categories.find_by_path(path)  
108 - if @category.nil?  
109 - render_not_found(path) 106 + unless params[:category_path].blank?
  107 + path = params[:category_path].join('/')
  108 + @category = environment.categories.find_by_path(path)
  109 + if @category.nil?
  110 + render_not_found(path)
  111 + end
110 end 112 end
111 end 113 end
112 114
app/controllers/public/search_controller.rb
@@ -2,6 +2,10 @@ class SearchController < ApplicationController @@ -2,6 +2,10 @@ class SearchController < ApplicationController
2 2
3 helper TagsHelper 3 helper TagsHelper
4 4
  5 + before_filter :load_category
  6 + before_filter :prepare_filter
  7 + before_filter :check_search_whole_site
  8 +
5 protected 9 protected
6 10
7 def search(finder, query) 11 def search(finder, query)
@@ -10,40 +14,43 @@ class SearchController < ApplicationController @@ -10,40 +14,43 @@ class SearchController < ApplicationController
10 end 14 end
11 end 15 end
12 16
  17 + def prepare_filter
  18 + @finder = @category || @environment
  19 + end
  20 +
  21 + def check_search_whole_site
  22 + if params[:search_whole_site] == 'yes'
  23 + redirect_to params.merge(:category_path => [], :search_whole_site => nil)
  24 + end
  25 + end
  26 +
13 public 27 public
14 28
15 include SearchHelper 29 include SearchHelper
16 30
17 ###################################################### 31 ######################################################
18 32
  33 + SEARCH_IN = [
  34 + [ :articles, _('Articles') ],
  35 + [ :comments, _('Comments') ],
  36 + [ :enterprises, _('Enterprises') ],
  37 + [ :people, _('People') ],
  38 + [ :communities, _('Communities') ],
  39 + [ :products, _('Products') ]
  40 + ]
  41 +
19 def index 42 def index
20 @query = params[:query] || '' 43 @query = params[:query] || ''
21 @filtered_query = remove_stop_words(@query) 44 @filtered_query = remove_stop_words(@query)
22 45
23 - @finder ||= @environment  
24 -  
25 @results = {} 46 @results = {}
26 @names = {} 47 @names = {}
27 - [  
28 - [ :articles, _('Articles') ],  
29 - [ :comments, _('Comments') ],  
30 - [ :enterprises, _('Enterprises') ],  
31 - [ :people, _('People') ],  
32 - [ :communities, _('Communities') ],  
33 - [ :products, _('Products') ]  
34 - ].each do |key, description| 48 + SEARCH_IN.each do |key, description|
35 @results[key] = search(@finder.send(key), @filtered_query) if params[:find_in].nil? || params[:find_in].empty? || params[:find_in].include?(key.to_s) 49 @results[key] = search(@finder.send(key), @filtered_query) if params[:find_in].nil? || params[:find_in].empty? || params[:find_in].include?(key.to_s)
36 @names[key] = description 50 @names[key] = description
37 end 51 end
38 end 52 end
39 53
40 - before_filter :load_category, :only => :filter  
41 - def filter  
42 - @finder = @category  
43 - index  
44 - render :action => 'index'  
45 - end  
46 -  
47 ####################################################### 54 #######################################################
48 55
49 def tags 56 def tags
@@ -61,6 +68,7 @@ class SearchController < ApplicationController @@ -61,6 +68,7 @@ class SearchController < ApplicationController
61 ####################################################### 68 #######################################################
62 69
63 def popup 70 def popup
  71 + @search_in = SEARCH_IN
64 render :action => 'popup', :layout => false 72 render :action => 'popup', :layout => false
65 end 73 end
66 74
app/views/layouts/application.rhtml
@@ -99,7 +99,7 @@ @@ -99,7 +99,7 @@
99 <%= render :file => 'shared/user_menu' %> 99 <%= render :file => 'shared/user_menu' %>
100 <%= 100 <%=
101 lightbox_link_to '<span class="icon-menu-search"></span>'+ _('Search'), 101 lightbox_link_to '<span class="icon-menu-search"></span>'+ _('Search'),
102 - { :controller => 'search', :action => 'popup' }, :id => 'open_search' 102 + { :controller => 'search', :action => 'popup', :category_path => (@category ? @category.explode_path : []) }, :id => 'open_search'
103 %> 103 %>
104 </div><!-- id='user_box' --> 104 </div><!-- id='user_box' -->
105 105
app/views/search/index.rhtml
1 -<h2> <%= _('Search results for "%s"') % @query %> </h2> 1 +<h2> <%= @category ? (_('Search results for "%{query}" in %{category}') % { :query => @query, :category => @category.full_name}) : (_('Search results for "%s"') % @query) %> </h2>
2 2
3 <% @results.each do |name,results| %> 3 <% @results.each do |name,results| %>
4 <% if !results.nil? and !results.empty? %> 4 <% if !results.nil? and !results.empty? %>
app/views/search/popup.rhtml
1 <h2><%= _('Search %s') % @environment.name %></h2> 1 <h2><%= _('Search %s') % @environment.name %></h2>
2 2
3 -<% form_tag(:action => 'index') do%> 3 +<% form_tag({:action => 'index', :category_path => (@category ? @category.explode_path : [])}, :method => 'get') do%>
4 4
5 <div id='search-field' style='text-align: center;'> 5 <div id='search-field' style='text-align: center;'>
6 <%= text_field_tag('query', '', :size => 50) %> 6 <%= text_field_tag('query', '', :size => 50) %>
7 <%= submit_button(:search, _('Search')) %> 7 <%= submit_button(:search, _('Search')) %>
8 </div> 8 </div>
9 9
10 - <h3><%= _('Search options') %></h3> 10 + <% if @category %>
  11 + <h3><%= _('Search in:') %></h3>
  12 + <ul>
  13 + <li>
  14 + <%= radio_button_tag :search_whole_site, 'no', true %>
  15 + <span><%= _('Only in %{category}') % { :category => @category.full_name } %></span>
  16 + </li>
  17 + <li>
  18 + <%= radio_button_tag :search_whole_site, 'yes' %>
  19 + <span><%= _('Whole site') %></span>
  20 + </li>
  21 + </ul>
  22 + <% end %>
  23 +
  24 + <h3><%= _('Search for:') %></h3>
  25 +
  26 + <ul>
  27 + <% @search_in.each do |thing, name| %>
  28 + <li>
  29 + <%= check_box_tag 'find_in[]', thing.to_s, true %>
  30 + <span><%= name %></span>
  31 + </li>
  32 + <% end %>
  33 + </ul>
11 34
12 35
13 <% button_bar do %> 36 <% button_bar do %>
lib/noosfero.rb
@@ -9,13 +9,6 @@ module Noosfero @@ -9,13 +9,6 @@ module Noosfero
9 Regexp.new(pattern) 9 Regexp.new(pattern)
10 end 10 end
11 11
12 - def self.pattern_for_controllers_from_design_blocks  
13 - items = Dir.glob(File.join(RAILS_ROOT, 'app', 'design_blocks', '*', 'controllers', '*_controller.rb')).map do |item|  
14 - item.gsub(/^.*\/([^\/]+)_controller.rb$/, '\1')  
15 - end.join('|')  
16 - Regexp.new(items.blank? ? '' : ('(' + items + ')'))  
17 - end  
18 -  
19 class << self 12 class << self
20 attr_accessor :locales 13 attr_accessor :locales
21 attr_accessor :default_locale 14 attr_accessor :default_locale
test/functional/search_controller_test.rb
@@ -63,7 +63,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -63,7 +63,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
63 art2 = person.articles.build(:name => 'another article to be found') 63 art2 = person.articles.build(:name => 'another article to be found')
64 art2.save! 64 art2.save!
65 65
66 - get :filter, :category_path => [ 'my-category' ], :query => 'article found', :find_in => [ 'articles' ] 66 + get :index, :category_path => [ 'my-category' ], :query => 'article found', :find_in => [ 'articles' ]
67 67
68 assert_includes assigns(:results)[:articles], art1 68 assert_includes assigns(:results)[:articles], art1
69 assert_not_includes assigns(:results)[:articles], art2 69 assert_not_includes assigns(:results)[:articles], art2
@@ -95,7 +95,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -95,7 +95,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
95 art2 = person.articles.build(:name => 'another article to be found') 95 art2 = person.articles.build(:name => 'another article to be found')
96 art2.save! 96 art2.save!
97 comment2 = art2.comments.build(:title => 'comment to be found', :body => 'hfyfyh', :author => person); comment2.save! 97 comment2 = art2.comments.build(:title => 'comment to be found', :body => 'hfyfyh', :author => person); comment2.save!
98 - get 'filter', :category_path => ['my-category'], :query => 'found', :find_in => [ 'comments' ] 98 + get :index, :category_path => ['my-category'], :query => 'found', :find_in => [ 'comments' ]
99 99
100 assert_includes assigns(:results)[:comments], comment1 100 assert_includes assigns(:results)[:comments], comment1
101 assert_not_includes assigns(:results)[:comments], comment2 101 assert_not_includes assigns(:results)[:comments], comment2
@@ -116,7 +116,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -116,7 +116,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
116 # not in category 116 # not in category
117 ent2 = Enterprise.create!(:name => 'testing enterprise 2', :identifier => 'test2') 117 ent2 = Enterprise.create!(:name => 'testing enterprise 2', :identifier => 'test2')
118 118
119 - get :filter, :category_path => [ 'my-category' ], :query => 'testing', :find_in => [ 'enterprises' ] 119 + get :index, :category_path => [ 'my-category' ], :query => 'testing', :find_in => [ 'enterprises' ]
120 120
121 assert_includes assigns(:results)[:enterprises], ent1 121 assert_includes assigns(:results)[:enterprises], ent1
122 assert_not_includes assigns(:results)[:enterprises], ent2 122 assert_not_includes assigns(:results)[:enterprises], ent2
@@ -135,7 +135,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -135,7 +135,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
135 c = Category.create!(:name => 'my category', :environment => Environment.default) 135 c = Category.create!(:name => 'my category', :environment => Environment.default)
136 p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.categories << c; p1.save! 136 p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.categories << c; p1.save!
137 p2 = create_user('people_2').person; p2.name = 'another beautiful person'; p2.save! 137 p2 = create_user('people_2').person; p2.name = 'another beautiful person'; p2.save!
138 - get :filter, :category_path => [ 'my-category' ], :query => 'beautiful', :find_in => [ 'people' ] 138 + get :index, :category_path => [ 'my-category' ], :query => 'beautiful', :find_in => [ 'people' ]
139 assert_includes assigns(:results)[:people], p1 139 assert_includes assigns(:results)[:people], p1
140 assert_not_includes assigns(:results)[:people], p2 140 assert_not_includes assigns(:results)[:people], p2
141 end 141 end
@@ -154,7 +154,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -154,7 +154,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
154 c1 = Community.create!(:name => 'a beautiful community', :identifier => 'bea_comm', :environment => Environment.default) 154 c1 = Community.create!(:name => 'a beautiful community', :identifier => 'bea_comm', :environment => Environment.default)
155 c2 = Community.create!(:name => 'another beautiful community', :identifier => 'an_bea_comm', :environment => Environment.default) 155 c2 = Community.create!(:name => 'another beautiful community', :identifier => 'an_bea_comm', :environment => Environment.default)
156 c1.categories << c; c1.save! 156 c1.categories << c; c1.save!
157 - get :filter, :category_path => [ 'my-category' ], :query => 'beautiful', :find_in => [ 'communities' ] 157 + get :index, :category_path => [ 'my-category' ], :query => 'beautiful', :find_in => [ 'communities' ]
158 assert_includes assigns(:results)[:communities], c1 158 assert_includes assigns(:results)[:communities], c1
159 assert_not_includes assigns(:results)[:communities], c2 159 assert_not_includes assigns(:results)[:communities], c2
160 end 160 end
@@ -174,7 +174,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -174,7 +174,7 @@ class SearchControllerTest &lt; Test::Unit::TestCase
174 ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2') 174 ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2')
175 prod1 = ent1.products.create!(:name => 'a beautiful product') 175 prod1 = ent1.products.create!(:name => 'a beautiful product')
176 prod2 = ent2.products.create!(:name => 'another beautiful product') 176 prod2 = ent2.products.create!(:name => 'another beautiful product')
177 - get 'filter', :category_path => ['my-category'], :query => 'beautiful', :find_in => ['products'] 177 + get :index, :category_path => ['my-category'], :query => 'beautiful', :find_in => ['products']
178 assert_includes assigns(:results)[:products], prod1 178 assert_includes assigns(:results)[:products], prod1
179 assert_not_includes assigns(:results)[:products], prod2 179 assert_not_includes assigns(:results)[:products], prod2
180 end 180 end
@@ -206,4 +206,59 @@ class SearchControllerTest &lt; Test::Unit::TestCase @@ -206,4 +206,59 @@ class SearchControllerTest &lt; Test::Unit::TestCase
206 end 206 end
207 end 207 end
208 208
  209 + should 'present options of where to search' do
  210 + get :popup
  211 + names = {
  212 + :articles => 'Articles',
  213 + :comments => 'Comments',
  214 + :people => 'People',
  215 + :enterprises => 'Enterprises',
  216 + :communities => 'Communities',
  217 + :products => 'Products',
  218 + }
  219 + names.each do |thing,description|
  220 + assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => "find_in[]", :value => thing.to_s, :checked => 'checked' }
  221 + assert_tag :tag => 'span', :content => description
  222 + end
  223 + end
  224 +
  225 + should 'not display option to choose where to search when not inside filter' do
  226 + get :popup
  227 + assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'search_whole_site', :value => 'yes' }
  228 + end
  229 +
  230 + should 'display option to choose searching in whole site or in current category' do
  231 + parent = Category.create!(:name => 'cat', :environment => Environment.default)
  232 + Category.create!(:name => 'sub', :environment => Environment.default, :parent => parent)
  233 +
  234 + get :popup, :category_path => [ 'cat', 'sub']
  235 + assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'search_whole_site', :value => 'yes' }
  236 + assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'search_whole_site', :value => 'no', :checked => 'checked' }
  237 + end
  238 +
  239 + should 'search in whole site when told so' do
  240 + parent = Category.create!(:name => 'randomcat', :environment => Environment.default)
  241 + Category.create!(:name => 'randomchild', :environment => Environment.default, :parent => parent)
  242 +
  243 + get :index, :category_path => [ 'randomcat', 'randomchild' ], :query => 'some random query', :search_whole_site => 'yes'
  244 +
  245 + # search_whole_site must be removed to precent a infinite redirect loop
  246 + assert_redirected_to :action => 'index', :category_path => [], :query => 'some random query', :search_whole_site => nil
  247 + end
  248 +
  249 + should 'submit form to root when not inside a filter' do
  250 + get :popup
  251 + assert_tag :tag => 'form', :attributes => { :action => '/search' }
  252 + end
  253 +
  254 + should 'submit form to category path when inside a filter' do
  255 + get :popup, :category_path => Category.create!(:name => 'mycat', :environment => Environment.default).explode_path
  256 + assert_tag :tag => 'form', :attributes => { :action => '/search/index/mycat' }
  257 + end
  258 +
  259 + should 'use GET method to search' do
  260 + get :popup
  261 + assert_tag :tag => 'form' , :attributes => { :method => 'get' }
  262 + end
  263 +
209 end 264 end