[noosfero/noosfero][next] 2 commits: Option to filter by template in search

Victor Costa gitlab at gitlab.com
Thu Mar 26 10:11:02 BRT 2015


Victor Costa pushed to next at Noosfero / noosfero


Commits:
eaaf3e5e by Leandro Nunes dos Santos at 2015-03-26T09:49:16Z
Option to filter by template in search

- - - - -
d9020ffa by Victor Costa at 2015-03-26T13:10:57Z
Merge branch 'search_template_filter' into 'next'

Search template filter

See merge request !522

- - - - -


13 changed files:

- app/controllers/public/search_controller.rb
- app/helpers/layout_helper.rb
- app/helpers/search_helper.rb
- app/models/profile.rb
- app/views/search/_search_content.html.erb
- app/views/search/_search_form.html.erb
- lib/noosfero/plugin.rb
- public/javascripts/search.js
- public/stylesheets/search.css
- + public/stylesheets/selectordie-theme.css
- test/functional/search_controller_test.rb
- test/unit/profile_test.rb
- test/unit/search_helper_test.rb


Changes:

=====================================
app/controllers/public/search_controller.rb
=====================================
--- a/app/controllers/public/search_controller.rb
+++ b/app/controllers/public/search_controller.rb
@@ -9,6 +9,7 @@ class SearchController < PublicController
   before_filter :load_search_assets, :except => :suggestions
   before_filter :load_query, :except => :suggestions
   before_filter :load_order, :except => :suggestions
+  before_filter :load_templates, :except => :suggestions
 
   # Backwards compatibility with old URLs
   def redirect_asset_param
@@ -210,6 +211,11 @@ class SearchController < PublicController
     end
   end
 
+  def load_templates
+    @templates = {}
+    @templates[@asset] = environment.send(@asset.to_s).templates if [:people, :enterprises, :communities].include?(@asset)
+  end
+
   def limit
     if map_search?(@searches)
       MAP_SEARCH_LIMIT
@@ -230,7 +236,7 @@ class SearchController < PublicController
   end
 
   def full_text_search
-    @searches[@asset] = find_by_contents(@asset, environment, @scope, @query, paginate_options, {:category => @category, :filter => @order})
+    @searches[@asset] = find_by_contents(@asset, environment, @scope, @query, paginate_options, {:category => @category, :filter => @order, :template_id => params[:template_id]})
   end
 
   private

=====================================
app/helpers/layout_helper.rb
=====================================
--- a/app/helpers/layout_helper.rb
+++ b/app/helpers/layout_helper.rb
@@ -49,6 +49,7 @@ module LayoutHelper
       'selectordie',
       'inputosaurus',
       'chat',
+      'selectordie-theme',
       pngfix_stylesheet_path,
     ] + tokeninput_stylesheets
     plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }

=====================================
app/helpers/search_helper.rb
=====================================
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -148,4 +148,11 @@ module SearchHelper
     link_to(@enabled_searches[asset], "/search/#{asset}")
   end
 
+  def assets_submenu(asset)
+    return '' if @templates[asset].blank? || @templates[asset].length == 1
+    options = @templates[asset].map {|template| [template.name, template.id]}
+    options = options_for_select([[_('Choose a template'), nil]] + options, selected: (params[:template_id]))
+    select_tag('template_id', options, :id => 'submenu')
+  end
+
 end

=====================================
app/models/profile.rb
=====================================
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -85,7 +85,15 @@ class Profile < ActiveRecord::Base
   #FIXME: these will work only if the subclass is already loaded
   scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
   scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
-  scope :templates, {:conditions => {:is_template => true}}
+  scope :templates, lambda { |template_id = nil|
+    conditions = {:conditions => {:is_template => true}}
+    conditions[:conditions].merge!({:id => template_id}) unless template_id.nil?
+    conditions
+  }
+
+  scope :with_templates, lambda { |templates|
+    {:conditions => {:template_id => templates}}
+  }
   scope :no_templates, {:conditions => {:is_template => false}}
 
   def members

=====================================
app/views/search/_search_content.html.erb
=====================================
--- a/app/views/search/_search_content.html.erb
+++ b/app/views/search/_search_content.html.erb
@@ -1,4 +1,8 @@
 <div id='search-content'>
+  <div class='total'>
+    <%= _('Total of %s results ') % @searches[@asset][:results].total_entries.inspect %>
+  </div>
+
 <%= display_results(@searches, @asset) %>
 <% if params[:display] != 'map' %>
   <%= pagination_links @searches[@asset][:results] %>

=====================================
app/views/search/_search_form.html.erb
=====================================
--- a/app/views/search/_search_form.html.erb
+++ b/app/views/search/_search_form.html.erb
@@ -5,8 +5,12 @@
     <div id='search-header'>
       <%= assets_menu(@asset) %>
       <%= filters(@asset) %>
+      <div class="clear"></div>
     </div>
 
+    <div id='search-subheader'>
+      <%= assets_submenu(@asset) %>
+    </div>
     <div class="search-field">
       <span class="formfield">
         <%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %>

=====================================
lib/noosfero/plugin.rb
=====================================
--- a/lib/noosfero/plugin.rb
+++ b/lib/noosfero/plugin.rb
@@ -556,6 +556,7 @@ class Noosfero::Plugin
   # own use in specific views
   def find_by_contents(asset, scope, query, paginate_options={}, options={})
     scope = scope.like_search(query, options) unless query.blank?
+    scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
     scope = scope.send(options[:filter]) unless options[:filter].blank?
     {:results => scope.paginate(paginate_options)}
   end

=====================================
public/javascripts/search.js
=====================================
--- a/public/javascripts/search.js
+++ b/public/javascripts/search.js
@@ -15,9 +15,17 @@
     $('form.search_form').submit();
   });
 
+  // Filter submenu
+  $('#search-subheader select').change(function(){
+    $('form.search_form').submit();
+  });
+
   // Custom styled select
   $('#search-filters select').selectOrDie();
 
+  // Custom styled select
+  $('#search-subheader select').selectOrDie();
+
   // Form Ajax submission
   $('form.search_form').submit(function () {
     $.ajax({

=====================================
public/stylesheets/search.css
=====================================
--- a/public/stylesheets/search.css
+++ b/public/stylesheets/search.css
@@ -953,7 +953,7 @@ ul#assets-menu {
   text-align: justify;
   text-justify: distribute-all-lines; /* distribute items in IE */
   list-style-type: none;
-  margin: 5px 0 13px;
+  margin: 5px 0px 10px 0px;
   padding: 0;
   width: 500px;
   float: left;
@@ -984,6 +984,15 @@ ul#assets-menu li.selected a {
   color: #EF2929;
   font-weight: bold;
 }
+ul#assets-links li.selected a {
+  border-bottom: 4px solid #dd4b39;
+  padding-bottom: 6px;
+}
+
+ul#assets-links li.selected a {
+  color: #dd4b39;
+  font-weight: bold;
+}
 
 #search-filters {
   float: right;
@@ -1037,3 +1046,13 @@ ul#assets-menu li.selected a {
   border-bottom:1px solid #ccc;
   margin-bottom: 10px;
 }
+
+#search-header{
+  border-bottom: 1px solid #ebebeb;
+}
+
+#search-content .total{
+  color: #808080;
+  line-height: 20px;
+  font-style: oblique;
+}

=====================================
public/stylesheets/selectordie-theme.css
=====================================
--- /dev/null
+++ b/public/stylesheets/selectordie-theme.css
@@ -0,0 +1,75 @@
+/* Default custom select styles */
+
+#search-subheader div.sod_select {
+  display: inline-block;
+  vertical-align: middle;
+  position: relative;
+  text-align: left;
+  background: #fff;
+  z-index: 100;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  background: transparent;
+  max-width: 400px;
+}
+
+#search-subheader div.sod_select:focus {
+  outline: none; /* For better accessibility add a style for this in your skin */
+}
+
+#search-subheader .sod_select select {
+  display: none;
+}
+
+#search-subheader .sod_label::after {
+  font-family: Arial, 'Liberation Sans', sans-serif;
+  font-weight: bold;
+  content: '+';
+  left: 0px;
+  -webkit-transform: translate3d(0,-50%,0) rotate3d(0,0,1,0deg);;
+  transform: translate3d(0,-50%,0) rotate3d(0,0,1,0deg);;
+  -webkit-transition: -webkit-transform 0.5s;
+  transition: transform 0.5s;
+  position: absolute;
+  top: 50%;
+  font-size: 2.1em;
+}
+
+#search-subheader .sod_select.open .sod_label::after {
+  -webkit-transform: translate3d(0,-50%,0) rotate3d(0,0,1,225deg);
+  transform: translate3d(0,-50%,0) rotate3d(0,0,1,225deg);
+}
+
+/* Changes on select or die*/
+#search-subheader .sod_select{
+  border: none;
+  padding-top: 10px;
+  padding-left: 20px;
+  padding-bottom: 10px;
+  width: auto;
+  font-weight: normal;
+  text-transform: none;
+  font-size: 12px;
+}
+
+#search-subheader .sod_select.open{
+}
+
+#search-subheader .sod_select .sod_list{
+  border: 1px solid #ebebeb;
+  margin-left: -1px;
+  width: auto;
+}
+
+#search-subheader .sod_select:before,
+#search-subheader  .sod_select:after {
+  content: "";
+}
+
+#search-subheader .sod_select.focus {
+  box-shadow: none;
+}

=====================================
test/functional/search_controller_test.rb
=====================================
--- a/test/functional/search_controller_test.rb
+++ b/test/functional/search_controller_test.rb
@@ -13,14 +13,14 @@ class SearchControllerTest < ActionController::TestCase
     @request.stubs(:ssl?).returns(false)
     @response   = ActionController::TestResponse.new
 
-    @category = Category.create!(:name => 'my-category', :environment => Environment.default)
+    @environment = Environment.default
+    @category = Category.create!(:name => 'my-category', :environment => @environment)
 
-    env = Environment.default
-    domain = env.domains.first
+    domain = @environment.domains.first
     if !domain
       domain = Domain.create!(:name => "127.0.0.1")
-      env.domains = [domain]
-      env.save!
+      @environment.domains = [domain]
+      @environment.save!
     end
     domain.google_maps_key = 'ENVIRONMENT_KEY'
     domain.save!
@@ -37,6 +37,8 @@ class SearchControllerTest < ActionController::TestCase
     Person.any_instance.stubs(:user).returns(user)
   end
 
+  attr_reader :environment
+
   def create_article_with_optional_category(name, profile, category = nil)
     fast_create(Article, {:name => name, :profile_id => profile.id }, :search => true, :category => category)
   end
@@ -651,6 +653,122 @@ class SearchControllerTest < ActionController::TestCase
     assert_equal [st1,st2].to_json, response.body
   end
 
+  should 'templates variable be an hash in articles asset' do
+    get :articles
+    assert assigns(:templates).kind_of?(Hash)
+  end
+
+  should 'not load people templates in articles asset' do
+    t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    get :articles
+    assert_nil assigns(:templates)[:people]
+  end
+
+  should 'not load communities templates in articles asset' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    get :articles
+    assert_nil assigns(:templates)[:communities]
+  end
+
+  should 'not load enterprises templates in articles asset' do
+    t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    get :articles
+    assert_nil assigns(:templates)[:enterprises]
+  end
+
+  should 'templates variable be equals to people templates in people assert' do
+    t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    get :people
+
+    assert_equivalent [t1,t2], assigns(:templates)[:people]
+  end
+
+  should 'not load communities templates in people asset' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    get :people
+    assert_nil assigns(:templates)[:communities]
+  end
+
+  should 'not load enterprises templates in people asset' do
+    t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    get :people
+    assert_nil assigns(:templates)[:enterprises]
+  end
+
+  should 'templates variable be equals to communities templates in communities assert' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    get :communities
+
+    assert_equivalent [t1,t2], assigns(:templates)[:communities]
+  end
+
+  should 'not load people templates in communities asset' do
+    t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    get :communities
+    assert_nil assigns(:templates)[:people]
+  end
+
+  should 'not load enterprises templates in communities asset' do
+    t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    get :communities
+    assert_nil assigns(:templates)[:enterprises]
+  end
+
+  should 'templates variable be equals to enterprises templates in enterprises assert' do
+    t1 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Enterprise, :is_template => true, :environment_id => environment.id)
+    get :enterprises
+
+    assert_equivalent [t1,t2], assigns(:templates)[:enterprises]
+  end
+
+  should 'not load communities templates in enterprises asset' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    get :enterprises
+    assert_nil assigns(:templates)[:communities]
+  end
+
+  should 'not load people templates in enterprises asset' do
+    t1 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Person, :is_template => true, :environment_id => environment.id)
+    get :enterprises
+    assert_nil assigns(:templates)[:people]
+  end
+
+  should 'list all community of on specific template' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    c1 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 1', :created_at => DateTime.now - 2)
+    c2 = fast_create(Community, :template_id => t2.id, :name => 'Testing community 2', :created_at => DateTime.now - 1)
+    c3 = fast_create(Community, :template_id => t1.id, :name => 'Testing community 3')
+    c4 = fast_create(Community, :name => 'Testing community 3')
+
+    get :communities, :template_id => t1.id
+    assert_equivalent [c1,c3] , assigns(:searches)[:communities][:results]
+  end
+
+  should 'list all communities of no template is passed' do
+    t1 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    t2 = fast_create(Community, :is_template => true, :environment_id => environment.id)
+    c1 = create(Community, :template_id => t1.id, :name => 'Testing community 1', :created_at => DateTime.now - 2)
+    c2 = create(Community, :template_id => t2.id, :name => 'Testing community 2', :created_at => DateTime.now - 1)
+    c3 = create(Community, :template_id => t1.id, :name => 'Testing community 3')
+    c4 = create(Community, :name => 'Testing community 3')
+
+    get :communities, :template_id => nil
+    assert_equivalent [t1,t2,c1,c2,c3,c4] , assigns(:searches)[:communities][:results]
+  end
+
   protected
 
   def create_event(profile, options)

=====================================
test/unit/profile_test.rb
=====================================
--- a/test/unit/profile_test.rb
+++ b/test/unit/profile_test.rb
@@ -1406,6 +1406,71 @@ class ProfileTest < ActiveSupport::TestCase
     assert_not_includes environment.profiles.templates, profile
   end
 
+  should 'return an specific template when specified' do
+    environment = Environment.default
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    profile = fast_create(Profile)
+
+    assert_equal [t1], environment.profiles.templates(t1)
+    assert_equal [t2], environment.profiles.templates(t2)
+  end
+
+  should 'not return a template when and invalid template is specified' do
+    environment = Environment.default
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    t3 = fast_create(Profile)
+
+    assert_equal [], environment.profiles.templates(t3)
+  end
+
+  should 'return profiles of specified template passing object' do
+    environment = Environment.default
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    p1 = fast_create(Profile, :template_id => t1.id)
+    p2 = fast_create(Profile, :template_id => t2.id)
+    p3 = fast_create(Profile, :template_id => t1.id)
+
+    assert_equivalent [p1,p3], environment.profiles.with_templates(t1)
+  end
+
+  should 'return profiles of specified template passing id' do
+    environment = Environment.default
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    p1 = fast_create(Profile, :template_id => t1.id)
+    p2 = fast_create(Profile, :template_id => t2.id)
+    p3 = fast_create(Profile, :template_id => t1.id)
+
+    assert_equivalent [p1,p3], environment.profiles.with_templates(t1.id)
+  end
+
+  should 'return profiles of a list of specified templates' do
+    environment = Environment.default
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    t3 = fast_create(Profile, :is_template => true)
+    p1 = fast_create(Profile, :template_id => t1.id)
+    p2 = fast_create(Profile, :template_id => t2.id)
+    p3 = fast_create(Profile, :template_id => t3.id)
+
+    assert_equivalent [p1,p2], environment.profiles.with_templates([t1,t2])
+  end
+
+  should 'return all profiles without any template if nil is passed as parameter' do
+    environment = Environment.default
+    Profile.delete_all
+    t1 = fast_create(Profile, :is_template => true)
+    t2 = fast_create(Profile, :is_template => true)
+    p1 = fast_create(Profile, :template_id => t1.id)
+    p2 = fast_create(Profile, :template_id => t2.id)
+    p3 = fast_create(Profile)
+
+    assert_equivalent [t1,t2,p3], environment.profiles.with_templates(nil)
+  end
+
   should 'return a list of profiles that are not templates' do
     environment = Environment.default
     p1 = fast_create(Profile, :is_template => false)

=====================================
test/unit/search_helper_test.rb
=====================================
--- a/test/unit/search_helper_test.rb
+++ b/test/unit/search_helper_test.rb
@@ -3,6 +3,9 @@ require_relative "../test_helper"
 class SearchHelperTest < ActiveSupport::TestCase
 
   include SearchHelper
+  include ActionView::Helpers::FormOptionsHelper
+  include ActionView::Helpers::FormTagHelper
+
 
   should 'return whether on a multiple search' do
     stubs(:params).returns({:action => 'index', :display => 'map'})
@@ -122,4 +125,84 @@ class SearchHelperTest < ActiveSupport::TestCase
     end
   end
 
+  should 'return an empty string in assets_submenu for articles assets' do
+    @templates = {}
+    assert_equal '', assets_submenu(:articles)
+    @templates = {:articles => nil}
+    assert_equal '', assets_submenu(:articles)
+  end
+
+  should 'return an empty string in assets_submenu for people asset without template' do
+    @templates = {:people => nil}
+    assert_equal '', assets_submenu(:people)
+
+    @templates = {:people => []}
+    assert_equal '', assets_submenu(:people)
+  end
+
+  should 'return an empty string in assets_submenu for people asset with only one template' do
+    t = fast_create(Person, :is_template => true)
+    @templates = {:people => [t]}
+    assert_equal '', assets_submenu(:people)
+  end
+
+  should 'return a select of templates for people asset with more then one template' do
+    t1 = fast_create(Person, :is_template => true)
+    t2 = fast_create(Person, :is_template => true)
+    @templates = {:people => [t1,t2]}
+    SearchHelperTest.any_instance.stubs(:params).returns({})
+    assert_match /select/, assets_submenu(:people)
+    assert_match /#{t1.name}/, assets_submenu(:people)
+    assert_match /#{t2.name}/, assets_submenu(:people)
+  end
+
+  should 'return an empty string in assets_submenu for communities asset without template' do
+    @templates = {:communities => nil}
+    assert_equal '', assets_submenu(:communities)
+
+    @templates = {:communities => []}
+    assert_equal '', assets_submenu(:communities)
+  end
+
+  should 'return an empty string in assets_submenu for communities asset with only one template' do
+    t = fast_create(Community, :is_template => true)
+    @templates = {:communities => [t]}
+    assert_equal '', assets_submenu(:communities)
+  end
+
+  should 'return a select of templates for communities asset with more then one template' do
+    t1 = fast_create(Community, :is_template => true)
+    t2 = fast_create(Community, :is_template => true)
+    @templates = {:communities => [t1,t2]}
+    SearchHelperTest.any_instance.stubs(:params).returns({})
+    assert_match /select/, assets_submenu(:communities)
+    assert_match /#{t1.name}/, assets_submenu(:communities)
+    assert_match /#{t2.name}/, assets_submenu(:communities)
+  end
+
+  should 'return an empty string in assets_submenu for enterprises asset without template' do
+    @templates = {:enterprises => nil}
+    assert_equal '', assets_submenu(:enterprises)
+
+    @templates = {:enterprises => []}
+    assert_equal '', assets_submenu(:enterprises)
+  end
+
+  should 'return an empty string in assets_submenu for enterprises asset with only one template' do
+    t = fast_create(Enterprise, :is_template => true)
+    @templates = {:enterprises => [t]}
+    assert_equal '', assets_submenu(:enterprises)
+  end
+
+  should 'return a select of templates for enterprises asset with more then one template' do
+    t1 = fast_create(Enterprise, :is_template => true)
+    t2 = fast_create(Enterprise, :is_template => true)
+    @templates = {:enterprises => [t1,t2]}
+    SearchHelperTest.any_instance.stubs(:params).returns({})
+    assert_match /select/, assets_submenu(:enterprises)
+    assert_match /#{t1.name}/, assets_submenu(:enterprises)
+    assert_match /#{t2.name}/, assets_submenu(:enterprises)
+  end
+
+
 end


View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/d50ac31c1ff602ba6cbc13dab4c7738936127833...d9020ffa19055b914d11160109ed2092011dde50
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150326/88e53d0c/attachment-0001.html>


More information about the Noosfero-dev mailing list