From eaaf3e5e2abb0ae79db449d63c4e4bbd8536f456 Mon Sep 17 00:00:00 2001 From: Leandro Nunes dos Santos Date: Fri, 15 Aug 2014 14:55:54 -0300 Subject: [PATCH] Option to filter by template in search --- app/controllers/public/search_controller.rb | 8 +++++++- app/helpers/layout_helper.rb | 1 + app/helpers/search_helper.rb | 7 +++++++ app/models/profile.rb | 10 +++++++++- app/views/search/_search_content.html.erb | 4 ++++ app/views/search/_search_form.html.erb | 4 ++++ lib/noosfero/plugin.rb | 1 + public/javascripts/search.js | 8 ++++++++ public/stylesheets/search.css | 21 ++++++++++++++++++++- public/stylesheets/selectordie-theme.css | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/functional/search_controller_test.rb | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- test/unit/profile_test.rb | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/unit/search_helper_test.rb | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 407 insertions(+), 8 deletions(-) create mode 100644 public/stylesheets/selectordie-theme.css diff --git a/app/controllers/public/search_controller.rb b/app/controllers/public/search_controller.rb index efc7164..4f69836 100644 --- 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 diff --git a/app/helpers/layout_helper.rb b/app/helpers/layout_helper.rb index aec2c0b..43f40fc 100644 --- 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') } diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index a28a224..4b8313c 100644 --- 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 diff --git a/app/models/profile.rb b/app/models/profile.rb index b5540c4..3cb60d8 100644 --- 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 diff --git a/app/views/search/_search_content.html.erb b/app/views/search/_search_content.html.erb index 8d81b7b..c226a98 100644 --- a/app/views/search/_search_content.html.erb +++ b/app/views/search/_search_content.html.erb @@ -1,4 +1,8 @@
+
+ <%= _('Total of %s results ') % @searches[@asset][:results].total_entries.inspect %> +
+ <%= display_results(@searches, @asset) %> <% if params[:display] != 'map' %> <%= pagination_links @searches[@asset][:results] %> diff --git a/app/views/search/_search_form.html.erb b/app/views/search/_search_form.html.erb index a98abb0..6ca673f 100644 --- a/app/views/search/_search_form.html.erb +++ b/app/views/search/_search_form.html.erb @@ -5,8 +5,12 @@
<%= assets_menu(@asset) %> <%= filters(@asset) %> +
+
+ <%= assets_submenu(@asset) %> +
<%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %> diff --git a/lib/noosfero/plugin.rb b/lib/noosfero/plugin.rb index a98643e..59710f4 100644 --- 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 diff --git a/public/javascripts/search.js b/public/javascripts/search.js index 1c42038..36b6241 100644 --- 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({ diff --git a/public/stylesheets/search.css b/public/stylesheets/search.css index 841e78b..56f881f 100644 --- 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; +} diff --git a/public/stylesheets/selectordie-theme.css b/public/stylesheets/selectordie-theme.css new file mode 100644 index 0000000..55bd7c6 --- /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; +} diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb index e90aa0b..4f79e92 100644 --- 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) diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb index 1a0f915..8777f77 100644 --- 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) diff --git a/test/unit/search_helper_test.rb b/test/unit/search_helper_test.rb index 88a1922..eb15a26 100644 --- 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 -- libgit2 0.21.2