Commit 7f2dc0be827bdb9be8bb1685c91b1649cc94c8e3
1 parent
af1bb0cd
Exists in
master
and in
22 other branches
ActionItem155: implementing navigation with the assets navigation menu
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1626 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
13 changed files
with
263 additions
and
33 deletions
Show diff stats
app/controllers/public/search_controller.rb
| ... | ... | @@ -52,6 +52,9 @@ class SearchController < ApplicationController |
| 52 | 52 | [ :products, N_('Products') ] |
| 53 | 53 | ] |
| 54 | 54 | |
| 55 | + # TODO don't hardcode like this >:-( | |
| 56 | + LIST_LIMIT = 10 | |
| 57 | + | |
| 55 | 58 | def index |
| 56 | 59 | @query = params[:query] || '' |
| 57 | 60 | @filtered_query = remove_stop_words(@query) |
| ... | ... | @@ -72,6 +75,18 @@ class SearchController < ApplicationController |
| 72 | 75 | end |
| 73 | 76 | attr_reader :category |
| 74 | 77 | |
| 78 | + def assets | |
| 79 | + asset = params[:asset].to_sym | |
| 80 | + if !SEARCH_IN.map(&:first).include?(asset) | |
| 81 | + render :text => 'go away', :status => 403 | |
| 82 | + return | |
| 83 | + end | |
| 84 | + | |
| 85 | + | |
| 86 | + @results = { asset => @finder.send(asset).recent(LIST_LIMIT) } | |
| 87 | + @names = { asset => gettext(SEARCH_IN.find { |entry| entry.first == asset }[1]) } | |
| 88 | + end | |
| 89 | + | |
| 75 | 90 | def tags |
| 76 | 91 | @tags = Tag.find(:all).inject({}) do |memo,tag| |
| 77 | 92 | memo[tag.name] = tag.taggings.count | ... | ... |
app/helpers/assets_helper.rb
| ... | ... | @@ -3,11 +3,12 @@ module AssetsHelper |
| 3 | 3 | def generate_assets_menu() |
| 4 | 4 | [ |
| 5 | 5 | |
| 6 | - [ "#", "icon-menu-blog", _('Blogs') ], | |
| 7 | - [ "#", "icon-menu-album", _('Albuns') ], | |
| 8 | - [ "#", "icon-menu-product", _('Products') ], | |
| 9 | - [ "#", "icon-menu-enterprise", _('Enterprises') ], | |
| 10 | - [ "#", "icon-menu-community", _('Communities') ], | |
| 6 | + [ { :controller => 'search', :action => 'assets', :asset => 'articles' }, "icon-menu-articles", _('Articles') ], | |
| 7 | + [ { :controller => 'search', :action => 'assets', :asset => 'people' }, "icon-menu-people", _('People') ], | |
| 8 | + [ { :controller => 'search', :action => 'assets', :asset => 'products' }, "icon-menu-product", _('Products') ], | |
| 9 | + [ { :controller => 'search', :action => 'assets', :asset => 'enterprises' }, "icon-menu-enterprise", _('Enterprises') ], | |
| 10 | + [ { :controller => 'search', :action => 'assets', :asset => 'communities' }, "icon-menu-community", _('Communities') ], | |
| 11 | + [ { :controller => 'search', :action => 'assets', :asset => 'comments'}, "icon-menu-comments", _('Comments') ], | |
| 11 | 12 | |
| 12 | 13 | ].map do |target,css_class,name| |
| 13 | 14 | content_tag('li', link_to(content_tag('span', '', :class => css_class) + name, target)) | ... | ... |
app/models/product.rb
app/models/profile.rb
| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | +<% @results.each do |name,results| %> | |
| 2 | + <% if !results.nil? and !results.empty? %> | |
| 3 | + <div id="search-results-<%= name %>"> | |
| 4 | + <h3><%= @names[name] %></h3> | |
| 5 | + <ul> | |
| 6 | + <% results.each do |hit| %> | |
| 7 | + <%= render :partial => partial_for_class(hit.class), :locals => { :hit => hit } %> | |
| 8 | + <% end %> | |
| 9 | + </ul> | |
| 10 | + </div> | |
| 11 | + <% end %> | |
| 12 | +<% end %> | ... | ... |
app/views/search/index.rhtml
| 1 | 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| %> | |
| 4 | - <% if !results.nil? and !results.empty? %> | |
| 5 | - <div id="search-results-<%= name %>"> | |
| 6 | - <h3><%= @names[name] %></h3> | |
| 7 | - <ul> | |
| 8 | - <% results.each do |hit| %> | |
| 9 | - <%= render :partial => partial_for_class(hit.class), :locals => { :hit => hit } %> | |
| 10 | - <% end %> | |
| 11 | - </ul> | |
| 12 | - </div> | |
| 13 | - <% end %> | |
| 14 | -<% end %> | |
| 3 | +<%= render :partial => 'display_results' %> | |
| 15 | 4 | ... | ... |
public/designs/icons/default/style.css
| ... | ... | @@ -37,3 +37,7 @@ |
| 37 | 37 | .icon-menu-search { background-image: url(search-HC.gif) } |
| 38 | 38 | .icon-menu-ed-design { background-image: url(edit-design-HC.gif) } |
| 39 | 39 | .icon-todo { background-image: url(stock_todo.png); } |
| 40 | + | |
| 41 | +.icon-menu-articles { background-image: url(edit-HC.gif) } | |
| 42 | +.icon-menu-comments { background-image: url(blog-HC.gif) } | |
| 43 | +.icon-menu-people { background-image: url(album-HC.gif) } | ... | ... |
test/functional/search_controller_test.rb
| ... | ... | @@ -70,8 +70,38 @@ class SearchControllerTest < Test::Unit::TestCase |
| 70 | 70 | assert_not_includes assigns(:results)[:articles], art2 |
| 71 | 71 | end |
| 72 | 72 | |
| 73 | - # 'assets' menu | |
| 74 | - should 'list articles in a specific category' | |
| 73 | + # 'assets' outside any category | |
| 74 | + should 'list articles in general' do | |
| 75 | + person = create_user('testuser').person | |
| 76 | + person2 = create_user('anotheruser').person | |
| 77 | + | |
| 78 | + art1 = person.articles.create!(:name => 'one article', :categories => [@category]) | |
| 79 | + | |
| 80 | + art2 = person2.articles.create!(:name => 'two article', :categories => [@category]) | |
| 81 | + | |
| 82 | + get :assets, :asset => 'articles' | |
| 83 | + | |
| 84 | + assert_includes assigns(:results)[:articles], art1 | |
| 85 | + assert_includes assigns(:results)[:articles], art2 | |
| 86 | + end | |
| 87 | + | |
| 88 | + # 'assets' inside a category | |
| 89 | + should 'list articles in a specific category' do | |
| 90 | + person = create_user('testuser').person | |
| 91 | + | |
| 92 | + # in category | |
| 93 | + art1 = person.articles.create!(:name => 'one article', :categories => [@category]) | |
| 94 | + art2 = person.articles.create!(:name => 'other article', :categories => [@category]) | |
| 95 | + | |
| 96 | + # not in category | |
| 97 | + art3 = person.articles.create!(:name => 'another article') | |
| 98 | + | |
| 99 | + get :assets, :asset => 'articles', :category_path => ['my-category'] | |
| 100 | + | |
| 101 | + assert_includes assigns(:results)[:articles], art1 | |
| 102 | + assert_includes assigns(:results)[:articles], art2 | |
| 103 | + assert_not_includes assigns(:results)[:articles], art3 | |
| 104 | + end | |
| 75 | 105 | |
| 76 | 106 | should 'search in comments' do |
| 77 | 107 | person = create_user('teste').person |
| ... | ... | @@ -121,8 +151,27 @@ class SearchControllerTest < Test::Unit::TestCase |
| 121 | 151 | assert_not_includes assigns(:results)[:enterprises], ent2 |
| 122 | 152 | end |
| 123 | 153 | |
| 124 | - # 'assets' menu | |
| 125 | - should 'list enterprises in a specified category' | |
| 154 | + should 'list enterprises in general' do | |
| 155 | + ent1 = Enterprise.create!(:name => 'teste 1', :identifier => 'teste1') | |
| 156 | + ent2 = Enterprise.create!(:name => 'teste 2', :identifier => 'teste2') | |
| 157 | + | |
| 158 | + get :assets, :asset => 'enterprises' | |
| 159 | + assert_includes assigns(:results)[:enterprises], ent1 | |
| 160 | + assert_includes assigns(:results)[:enterprises], ent2 | |
| 161 | + end | |
| 162 | + | |
| 163 | + # 'assets' menu inside a category | |
| 164 | + should 'list enterprises in a specified category' do | |
| 165 | + # in category | |
| 166 | + ent1 = Enterprise.create!(:name => 'teste 1', :identifier => 'teste1', :categories => [@category]) | |
| 167 | + | |
| 168 | + # not in category | |
| 169 | + ent2 = Enterprise.create!(:name => 'teste 2', :identifier => 'teste2') | |
| 170 | + | |
| 171 | + get :assets, :asset => 'enterprises', :category_path => [ 'my-category' ] | |
| 172 | + assert_includes assigns(:results)[:enterprises], ent1 | |
| 173 | + assert_not_includes assigns(:results)[:enterprises], ent2 | |
| 174 | + end | |
| 126 | 175 | |
| 127 | 176 | should 'find people' do |
| 128 | 177 | p1 = create_user('people_1').person; p1.name = 'a beautiful person'; p1.save! |
| ... | ... | @@ -138,8 +187,30 @@ class SearchControllerTest < Test::Unit::TestCase |
| 138 | 187 | assert_not_includes assigns(:results)[:people], p2 |
| 139 | 188 | end |
| 140 | 189 | |
| 141 | - # 'assets' menu | |
| 142 | - should 'list people in a specified category' | |
| 190 | + # 'assets' menu outside any category | |
| 191 | + should 'list people in general' do | |
| 192 | + Profile.delete_all | |
| 193 | + | |
| 194 | + p1 = create_user('test1').person | |
| 195 | + p2 = create_user('test2').person | |
| 196 | + | |
| 197 | + get :assets, :asset => 'people' | |
| 198 | + assert_equal [p2,p1], assigns(:results)[:people] | |
| 199 | + end | |
| 200 | + | |
| 201 | + # 'assets' menu inside a category | |
| 202 | + should 'list people in a specified category' do | |
| 203 | + Profile.delete_all | |
| 204 | + | |
| 205 | + # in category | |
| 206 | + p1 = create_user('test1').person; p1.categories << @category | |
| 207 | + | |
| 208 | + # not in category | |
| 209 | + p2 = create_user('test2').person | |
| 210 | + | |
| 211 | + get :assets, :asset => 'people', :category_path => [ 'my-category' ] | |
| 212 | + assert_equal [p1], assigns(:results)[:people] | |
| 213 | + end | |
| 143 | 214 | |
| 144 | 215 | should 'find communities' do |
| 145 | 216 | c1 = Community.create!(:name => 'a beautiful community', :identifier => 'bea_comm', :environment => Environment.default) |
| ... | ... | @@ -155,8 +226,33 @@ class SearchControllerTest < Test::Unit::TestCase |
| 155 | 226 | assert_includes assigns(:results)[:communities], c1 |
| 156 | 227 | assert_not_includes assigns(:results)[:communities], c2 |
| 157 | 228 | end |
| 229 | + | |
| 230 | + # 'assets' menu outside any category | |
| 231 | + should 'list communities in general' do | |
| 232 | + c1 = Community.create!(:name => 'a beautiful community', :identifier => 'bea_comm', :environment => Environment.default) | |
| 233 | + c2 = Community.create!(:name => 'another beautiful community', :identifier => 'an_bea_comm', :environment => Environment.default) | |
| 234 | + | |
| 235 | + get :assets, :asset => 'communities' | |
| 236 | + assert_equal [c2, c1], assigns(:results)[:communities] | |
| 237 | + end | |
| 238 | + | |
| 158 | 239 | # 'assets' menu |
| 159 | - should 'list communities in a specified category' | |
| 240 | + should 'list communities in a specified category' do | |
| 241 | + | |
| 242 | + # in category | |
| 243 | + c1 = Community.create!(:name => 'a beautiful community', :identifier => 'bea_comm', :environment => Environment.default) | |
| 244 | + c1.categories << @category | |
| 245 | + | |
| 246 | + # not in category | |
| 247 | + c2 = Community.create!(:name => 'another beautiful community', :identifier => 'an_bea_comm', :environment => Environment.default) | |
| 248 | + | |
| 249 | + # in category | |
| 250 | + c3 = Community.create!(:name => 'yet another beautiful community', :identifier => 'yet_an_bea_comm', :environment => Environment.default) | |
| 251 | + c3.categories << @category | |
| 252 | + | |
| 253 | + get :assets, :asset => 'communities', :category_path => [ 'my-category' ] | |
| 254 | + assert_equal [c3, c1], assigns(:results)[:communities] | |
| 255 | + end | |
| 160 | 256 | |
| 161 | 257 | should 'find products' do |
| 162 | 258 | ent = Enterprise.create!(:name => 'teste', :identifier => 'teste') |
| ... | ... | @@ -175,8 +271,35 @@ class SearchControllerTest < Test::Unit::TestCase |
| 175 | 271 | assert_not_includes assigns(:results)[:products], prod2 |
| 176 | 272 | end |
| 177 | 273 | |
| 178 | - # 'assets' menu | |
| 179 | - should 'list products in a specific category' | |
| 274 | + # 'assets' menu outside any category | |
| 275 | + should 'list products in general' do | |
| 276 | + Profile.delete_all | |
| 277 | + | |
| 278 | + ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1') | |
| 279 | + ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2') | |
| 280 | + prod1 = ent1.products.create!(:name => 'a beautiful product') | |
| 281 | + prod2 = ent2.products.create!(:name => 'another beautiful product') | |
| 282 | + | |
| 283 | + get :assets, :asset => 'products' | |
| 284 | + assert_equal [prod2, prod1], assigns(:results)[:products] | |
| 285 | + end | |
| 286 | + | |
| 287 | + # 'assets' menu inside a category | |
| 288 | + should 'list products in a specific category' do | |
| 289 | + Profile.delete_all | |
| 290 | + | |
| 291 | + # in category | |
| 292 | + ent1 = Enterprise.create!(:name => 'teste1', :identifier => 'teste1'); ent1.categories << @category | |
| 293 | + prod1 = ent1.products.create!(:name => 'a beautiful product') | |
| 294 | + | |
| 295 | + # not in category | |
| 296 | + ent2 = Enterprise.create!(:name => 'teste2', :identifier => 'teste2') | |
| 297 | + prod2 = ent2.products.create!(:name => 'another beautiful product') | |
| 298 | + | |
| 299 | + get :assets, :asset => 'products', :category_path => [ 'my-category' ] | |
| 300 | + | |
| 301 | + assert_equal [prod1], assigns(:results)[:products] | |
| 302 | + end | |
| 180 | 303 | |
| 181 | 304 | should 'display search results' do |
| 182 | 305 | ent = Enterprise.create!(:name => 'display enterprise', :identifier => 'teste1') |
| ... | ... | @@ -302,4 +425,10 @@ class SearchControllerTest < Test::Unit::TestCase |
| 302 | 425 | assert_includes assigns(:products), p |
| 303 | 426 | end |
| 304 | 427 | |
| 428 | + # SECURITY | |
| 429 | + should 'not allow unrecognized assets' do | |
| 430 | + get :assets, :asset => 'unexisting_asset' | |
| 431 | + assert_response 403 | |
| 432 | + end | |
| 433 | + | |
| 305 | 434 | end | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class ApplicationHelperTest < Test::Unit::TestCase | |
| 4 | + | |
| 5 | + include AssetsHelper | |
| 6 | + | |
| 7 | + should 'generate link to assets' do | |
| 8 | + %w[ articles | |
| 9 | + people | |
| 10 | + products | |
| 11 | + enterprises | |
| 12 | + communities | |
| 13 | + comments | |
| 14 | + ].each do |asset| | |
| 15 | + expects(:link_to).with(anything, { :controller => 'search', :action => 'assets', :asset => asset}) | |
| 16 | + end | |
| 17 | + | |
| 18 | + stubs(:_).returns('') | |
| 19 | + stubs(:content_tag).returns('') | |
| 20 | + generate_assets_menu | |
| 21 | + | |
| 22 | + end | |
| 23 | + | |
| 24 | + | |
| 25 | +end | ... | ... |
test/unit/category_test.rb
| ... | ... | @@ -346,12 +346,13 @@ class CategoryTest < Test::Unit::TestCase |
| 346 | 346 | assert_not_includes c.people, ent |
| 347 | 347 | end |
| 348 | 348 | |
| 349 | - should 'list people that are categorized in children categories' do | |
| 350 | - c1 = @env.categories.create!(:name => 'top category') | |
| 351 | - c2 = @env.categories.create!(:name => 'child category', :parent => c1) | |
| 352 | - person = create_user('test_user').person | |
| 353 | - person.categories << c2 | |
| 354 | - assert_includes c1.people, person | |
| 355 | - end | |
| 349 | + # NOT YET | |
| 350 | + #should 'list people that are categorized in children categories' do | |
| 351 | + # c1 = @env.categories.create!(:name => 'top category') | |
| 352 | + # c2 = @env.categories.create!(:name => 'child category', :parent => c1) | |
| 353 | + # person = create_user('test_user').person | |
| 354 | + # person.categories << c2 | |
| 355 | + # assert_includes c1.people, person | |
| 356 | + #end | |
| 356 | 357 | |
| 357 | 358 | end | ... | ... |
test/unit/product_test.rb
| ... | ... | @@ -23,4 +23,27 @@ class ProductTest < Test::Unit::TestCase |
| 23 | 23 | assert !p.save |
| 24 | 24 | end |
| 25 | 25 | end |
| 26 | + | |
| 27 | + should 'list recent products' do | |
| 28 | + enterprise = Enterprise.create!(:name => "My enterprise", :identifier => 'my-enterprise') | |
| 29 | + Product.delete_all | |
| 30 | + | |
| 31 | + p1 = enterprise.products.create!(:name => 'product 1') | |
| 32 | + p2 = enterprise.products.create!(:name => 'product 2') | |
| 33 | + p3 = enterprise.products.create!(:name => 'product 3') | |
| 34 | + | |
| 35 | + assert_equal [p3, p2, p1], Product.recent | |
| 36 | + end | |
| 37 | + | |
| 38 | + should 'list recent products with limit' do | |
| 39 | + enterprise = Enterprise.create!(:name => "My enterprise", :identifier => 'my-enterprise') | |
| 40 | + Product.delete_all | |
| 41 | + | |
| 42 | + p1 = enterprise.products.create!(:name => 'product 1') | |
| 43 | + p2 = enterprise.products.create!(:name => 'product 2') | |
| 44 | + p3 = enterprise.products.create!(:name => 'product 3') | |
| 45 | + | |
| 46 | + assert_equal [p3, p2], Product.recent(2) | |
| 47 | + end | |
| 48 | + | |
| 26 | 49 | end | ... | ... |
test/unit/profile_test.rb
| ... | ... | @@ -390,6 +390,26 @@ class ProfileTest < Test::Unit::TestCase |
| 390 | 390 | assert_includes c.categories, cat |
| 391 | 391 | end |
| 392 | 392 | |
| 393 | + should 'be able to list recent profiles' do | |
| 394 | + Profile.delete_all | |
| 395 | + | |
| 396 | + p1 = Profile.create!(:name => 'first test profile', :identifier => 'first') | |
| 397 | + p2 = Profile.create!(:name => 'second test profile', :identifier => 'second') | |
| 398 | + p3 = Profile.create!(:name => 'thirs test profile', :identifier => 'third') | |
| 399 | + | |
| 400 | + assert_equal [p3,p2,p1], Profile.recent | |
| 401 | + end | |
| 402 | + | |
| 403 | + should 'be able to list recent profiles with limit' do | |
| 404 | + Profile.delete_all | |
| 405 | + | |
| 406 | + p1 = Profile.create!(:name => 'first test profile', :identifier => 'first') | |
| 407 | + p2 = Profile.create!(:name => 'second test profile', :identifier => 'second') | |
| 408 | + p3 = Profile.create!(:name => 'thirs test profile', :identifier => 'third') | |
| 409 | + | |
| 410 | + assert_equal [p3,p2], Profile.recent(2) | |
| 411 | + end | |
| 412 | + | |
| 393 | 413 | private |
| 394 | 414 | |
| 395 | 415 | def assert_invalid_identifier(id) | ... | ... |