Commit f8fcdd69eb8771706a0e916ce027732cfde6a35c
1 parent
1089c991
Exists in
master
and in
23 other branches
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
Showing
7 changed files
with
119 additions
and
38 deletions
Show diff stats
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 < Test::Unit::TestCase | @@ -63,7 +63,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -95,7 +95,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -116,7 +116,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -135,7 +135,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -154,7 +154,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -174,7 +174,7 @@ class SearchControllerTest < 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 < Test::Unit::TestCase | @@ -206,4 +206,59 @@ class SearchControllerTest < 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 |