Commit 6e82bdc7062af8f0447fff19593054948cbeb5e5

Authored by Rodrigo Souto
1 parent 144d5783

[otw] products action... =/

app/controllers/public/search_controller.rb
... ... @@ -8,6 +8,7 @@ class SearchController < PublicController
8 8 before_filter :load_category
9 9 before_filter :load_search_assets
10 10 before_filter :load_query
  11 + before_filter :load_search_engine
11 12  
12 13 # Backwards compatibility with old URLs
13 14 def redirect_asset_param
... ... @@ -18,7 +19,7 @@ class SearchController < PublicController
18 19 no_design_blocks
19 20  
20 21 def facets_browse
21   - @asset = params[:asset]
  22 + @asset = params[:asset].to_sym
22 23 @asset_class = asset_class(@asset)
23 24  
24 25 @facets_only = true
... ... @@ -31,11 +32,12 @@ class SearchController < PublicController
31 32 end
32 33  
33 34 def articles
34   - if !@empty_query
35   - full_text_search ['public:true']
  35 + if @search_engine && !@empty_query
  36 + full_text_search
36 37 else
37 38 @results[@asset] = @environment.articles.public.send(@filter).paginate(paginate_options)
38 39 end
  40 + render :template => 'search/search_page'
39 41 end
40 42  
41 43 def contents
... ... @@ -43,49 +45,51 @@ class SearchController < PublicController
43 45 end
44 46  
45 47 def people
46   - if !@empty_query
47   - full_text_search ['public:true']
  48 + if @search_engine && !@empty_query
  49 + full_text_search
48 50 else
49 51 @results[@asset] = visible_profiles(Person).send(@filter).paginate(paginate_options)
50 52 end
  53 + render :template => 'search/search_page'
51 54 end
52 55  
53 56 def products
54   - public_filters = ['public:true', 'enabled:true']
55   - if !@empty_query
56   - full_text_search public_filters
  57 + if @search_engine && !@empty_query
  58 + full_text_search
57 59 else
58   - @one_page = true
59 60 @geosearch = logged_in? && current_user.person.lat && current_user.person.lng
60 61  
61 62 extra_limit = LIST_SEARCH_LIMIT*5
62 63 sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'}
63 64 if @geosearch
64   - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit,
  65 + full_text_search :sql_options => sql_options, :extra_limit => extra_limit,
65 66 :alternate_query => "{!boost b=recip(geodist(),#{"%e" % (1.to_f/DistBoost)},1,1)}",
66 67 :radius => DistFilt, :latitude => current_user.person.lat, :longitude => current_user.person.lng
67 68 else
68   - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit,
  69 + full_text_search :sql_options => sql_options, :extra_limit => extra_limit,
69 70 :boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)']
70 71 end
71 72 end
  73 + render :template => 'search/search_page'
72 74 end
73 75  
74 76 def enterprises
75   - if !@empty_query
76   - full_text_search ['public:true']
  77 + if @search_engine && !@empty_query
  78 + full_text_search
77 79 else
78 80 @filter_title = _('Enterprises from network')
79 81 @results[@asset] = visible_profiles(Enterprise, [{:products => :product_category}]).paginate(paginate_options)
80 82 end
  83 + render :template => 'search/search_page'
81 84 end
82 85  
83 86 def communities
84   - if !@empty_query
85   - full_text_search ['public:true']
  87 + if @search_engine && !@empty_query
  88 + full_text_search
86 89 else
87 90 @results[@asset] = visible_profiles(Community).send(@filter).paginate(paginate_options)
88 91 end
  92 + render :template => 'search/search_page'
89 93 end
90 94  
91 95 def events
... ... @@ -104,7 +108,7 @@ class SearchController < PublicController
104 108 environment.events.by_day(@selected_day)
105 109 end
106 110  
107   - if !@empty_query
  111 + if @search_engine && !@empty_query
108 112 full_text_search
109 113 else
110 114 @results[@asset] = date_range ? environment.events.by_range(date_range) : environment.events
... ... @@ -189,6 +193,7 @@ class SearchController < PublicController
189 193 def load_query
190 194 @asset = params[:action].to_sym
191 195 @order ||= [@asset]
  196 + params[:display] ||= 'list'
192 197 @results ||= {}
193 198 @filter = filter
194 199 @filter_title = filter_description(@asset, @filter)
... ... @@ -211,6 +216,10 @@ class SearchController < PublicController
211 216 end
212 217 end
213 218  
  219 + def load_search_engine
  220 + @search_engine = @plugins.first_plugin(:search_engine?)
  221 + end
  222 +
214 223 FILTERS = %w(
215 224 more_recent
216 225 more_active
... ... @@ -260,9 +269,7 @@ class SearchController < PublicController
260 269 if map_search?
261 270 MAP_SEARCH_LIMIT
262 271 elsif !multiple_search?
263   - if [:people, :communities].include? @asset
264   - BLOCKS_SEARCH_LIMIT
265   - elsif @asset == :enterprises and @empty_query
  272 + if [:people, :communities, :enterprises].include? @asset
266 273 BLOCKS_SEARCH_LIMIT
267 274 else
268 275 LIST_SEARCH_LIMIT
... ... @@ -273,41 +280,12 @@ class SearchController < PublicController
273 280 end
274 281  
275 282 def paginate_options(page = params[:page])
276   - page = 1 if multiple_search? or params[:display] == 'map'
  283 + page = 1 if multiple_search? or @display == 'map'
277 284 { :per_page => limit, :page => page }
278 285 end
279 286  
280   - def full_text_search(filters = [], options = {})
281   - paginate_options = paginate_options(params[:page])
282   - asset_class = asset_class(@asset)
283   - solr_options = options
284   - pg_options = paginate_options(params[:page])
285   -
286   - if !multiple_search?
287   - if !@results_only and asset_class.respond_to? :facets
288   - solr_options.merge! asset_class.facets_find_options(params[:facet])
289   - solr_options[:all_facets] = true
290   - end
291   - solr_options[:filter_queries] ||= []
292   - solr_options[:filter_queries] += filters
293   - solr_options[:filter_queries] << "environment_id:#{environment.id}"
294   - solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category
295   -
296   - solr_options[:boost_functions] ||= []
297   - params[:order_by] = nil if params[:order_by] == 'none'
298   - if params[:order_by]
299   - order = SortOptions[@asset][params[:order_by].to_sym]
300   - raise "Unknown order by" if order.nil?
301   - order[:solr_opts].each do |opt, value|
302   - solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
303   - end
304   - end
305   - end
306   -
307   - ret = asset_class.find_by_contents(@query, paginate_options, solr_options)
308   - @results[@asset] = ret[:results]
309   - @facets = ret[:facets]
310   - @all_facets = ret[:all_facets]
  287 + def full_text_search(options = {})
  288 + @results[@asset] = @plugins.first(:full_text_search, @asset, @query, @category, paginate_options(params[:page]))
311 289 end
312 290  
313 291 private
... ...
app/helpers/search_helper.rb
... ... @@ -2,7 +2,7 @@ module SearchHelper
2 2  
3 3 MAP_SEARCH_LIMIT = 2000
4 4 LIST_SEARCH_LIMIT = 20
5   - BLOCKS_SEARCH_LIMIT = 18
  5 + BLOCKS_SEARCH_LIMIT = 24
6 6 MULTIPLE_SEARCH_LIMIT = 8
7 7 DistFilt = 200
8 8 DistBoost = 50
... ... @@ -50,7 +50,7 @@ module SearchHelper
50 50 end
51 51  
52 52 def map_search?
53   - !@empty_query and !multiple_search? and params[:display] == 'map'
  53 + !multiple_search? and params[:display] == 'map'
54 54 end
55 55  
56 56 def search_page_title(title, category = nil)
... ... @@ -66,8 +66,12 @@ module SearchHelper
66 66 :align => 'center', :class => 'search-category-context') if category
67 67 end
68 68  
69   - def display_results(map_capable = false)
70   - if map_capable and map_search?
  69 + def map_capable?(asset)
  70 + [:enterprises, :products].include?(asset)
  71 + end
  72 +
  73 + def display_results(asset)
  74 + if map_capable?(asset) and map_search?
71 75 partial = 'google_maps'
72 76 klass = 'map'
73 77 else
... ... @@ -78,12 +82,6 @@ module SearchHelper
78 82 content_tag('div', render(:partial => partial), :class => "map-or-list-search-results #{klass}")
79 83 end
80 84  
81   - def display_map_list_button
82   - button(:search, params[:display] == 'map' ? _('Display in list') : _('Display in map'),
83   - params.merge(:display => (params[:display] == 'map' ? 'list' : 'map')),
84   - :class => "map-toggle-button" )
85   - end
86   -
87 85 def city_with_state(city)
88 86 if city and city.kind_of?(City)
89 87 s = city.parent
... ... @@ -97,17 +95,6 @@ module SearchHelper
97 95 end
98 96 end
99 97  
100   - def facets_menu(asset, _facets)
101   - @asset_class = asset_class(asset)
102   - @facets = _facets
103   - render(:partial => 'facets_menu')
104   - end
105   -
106   - def facets_unselect_menu(asset)
107   - @asset_class = asset_class(asset)
108   - render(:partial => 'facets_unselect_menu')
109   - end
110   -
111 98 def facet_javascript(input_id, facet, array)
112 99 array = [] if array.nil?
113 100 hintText = _('Type in an option')
... ... @@ -117,94 +104,6 @@ module SearchHelper
117 104 #{jquery_token_input_messages_json(hintText)}});")
118 105 end
119 106  
120   - def facet_link_html(facet, params, value, label, count)
121   - params = params ? params.dup : {}
122   - has_extra = label.kind_of?(Array)
123   - link_label = has_extra ? label[0] : label
124   - id = facet[:solr_field].to_s
125   - params[:facet] ||= {}
126   - params[:facet][id] ||= {}
127   - params[:page] = {} if params[:page]
128   -
129   - selected = facet[:label_id].nil? ? params[:facet][id] == value : params[:facet][id][facet[:label_id]].to_a.include?(value)
130   -
131   - if count > 0
132   - url = params.merge(:facet => params[:facet].merge(
133   - id => facet[:label_id].nil? ? value : params[:facet][id].merge( facet[:label_id] => params[:facet][id][facet[:label_id]].to_a | [value] )
134   - ))
135   - else
136   - # preserve others filters and change this filter
137   - url = params.merge(:facet => params[:facet].merge(
138   - id => facet[:label_id].nil? ? value : { facet[:label_id] => value }
139   - ))
140   - end
141   -
142   - content_tag 'div', link_to(link_label, url, :class => 'facet-result-link-label') +
143   - content_tag('span', (has_extra ? label[1] : ''), :class => 'facet-result-extra-label') +
144   - (count > 0 ? content_tag('span', " (#{count})", :class => 'facet-result-count') : ''),
145   - :class => 'facet-menu-item' + (selected ? ' facet-result-link-selected' : '')
146   - end
147   -
148   - def facet_selecteds_html_for(environment, klass, params)
149   - def name_with_extra(klass, facet, value)
150   - name = klass.facet_result_name(facet, value)
151   - name = name[0] + name[1] if name.kind_of?(Array)
152   - name
153   - end
154   -
155   - ret = []
156   - params = params.dup
157   - params[:facet].each do |id, value|
158   - facet = klass.facet_by_id(id.to_sym)
159   - next unless facet
160   - if value.kind_of?(Hash)
161   - label_hash = facet[:label].call(environment)
162   - value.each do |label_id, value|
163   - facet[:label_id] = label_id
164   - facet[:label] = label_hash[label_id]
165   - value.to_a.each do |value|
166   - ret << [facet[:label], name_with_extra(klass, facet, value),
167   - params.merge(:facet => params[:facet].merge(id => params[:facet][id].merge(label_id => params[:facet][id][label_id].to_a.reject{ |v| v == value })))]
168   - end
169   - end
170   - else
171   - ret << [klass.facet_label(facet), name_with_extra(klass, facet, value),
172   - params.merge(:facet => params[:facet].reject{ |k,v| k == id })]
173   - end
174   - end
175   -
176   - ret.map do |label, name, url|
177   - content_tag('div', content_tag('span', label, :class => 'facet-selected-label') +
178   - content_tag('span', name, :class => 'facet-selected-name') +
179   - link_to('', url, :class => 'facet-selected-remove', :title => 'remove facet'), :class => 'facet-selected')
180   - end.join
181   - end
182   -
183   - def order_by(asset)
184   - options = SortOptions[asset].map do |name, options|
185   - next if options[:if] and ! instance_eval(&options[:if])
186   - [_(options[:label]), name.to_s]
187   - end.compact
188   -
189   - content_tag('div', _('Sort results by ') +
190   - select_tag(asset.to_s + '[order]', options_for_select(options, params[:order_by] || 'none'),
191   - {:onchange => "window.location = jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}),
192   - :class => "search-ordering")
193   - end
194   -
195   - def label_total_found(asset, total_found)
196   - labels = {
197   - :products => _("%s products offers found"),
198   - :articles => _("%s articles found"),
199   - :events => _("%s events found"),
200   - :people => _("%s people found"),
201   - :enterprises => _("%s enterprises found"),
202   - :communities => _("%s communities found"),
203   - }
204   - content_tag('span', labels[asset] % total_found,
205   - :class => "total-pages-found") if labels[asset]
206   - end
207   -
208 107 def asset_class(asset)
209 108 asset.to_s.singularize.camelize.constantize
210 109 end
... ... @@ -213,4 +112,19 @@ module SearchHelper
213 112 asset_class(asset).table_name
214 113 end
215 114  
  115 + def display_filter(asset, display, float = 'right')
  116 + if map_capable?(asset)
  117 + list_link = display == 'list' ? _('List') : link_to(_('List'), params.merge(:display => 'list'))
  118 + map_link = display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))
  119 + content_tag('div',
  120 + content_tag('strong', _('Display')) + ': ' +
  121 + list_link +
  122 + ' | ' +
  123 + map_link,
  124 + :id => 'search-display-filter',
  125 + :style => "float: #{float}"
  126 + )
  127 + end
  128 + end
  129 +
216 130 end
... ...
app/views/search/_display_results.rhtml
1 1 <div id="search-results" class="<%= !multiple_search? ? 'only-one-result-box' : 'multiple-results-boxes' %>">
2 2 <% @order.each do |name| %>
3 3 <% results = @results[name] %>
4   - <% empty = results.nil? || results.empty? %>
5 4  
6   - <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if empty %>">
7   - <% if not empty %>
  5 + <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if results.blank? %>">
  6 + <% if !results.blank? %>
8 7 <% partial = partial_for_class(results.first.class.class_name.constantize) %>
9 8  
10 9 <% if multiple_search? %>
... ...
app/views/search/_facets_menu.rhtml
... ... @@ -1,36 +0,0 @@
1   -<% less_options_limit = 8 %>
2   -
3   -<div id="facets-menu">
4   - <% @asset_class.map_facets_for(environment).each do |facet| %>
5   -
6   - <div id="facet-menu-<%= facet[:id].to_s %>" class="facet-menu">
7   - <div class="facet-menu-label">
8   - <%= @asset_class.facet_label(facet) %>
9   - </div>
10   -
11   - <% results = @asset_class.map_facet_results(facet, params[:facet], @facets, @all_facets, :limit => less_options_limit) %>
12   - <% facet_count = results.total_entries %>
13   -
14   - <% if facet_count > 0 %>
15   - <div class="facet-menu-options facet-menu-more-options" style="display: none">
16   - </div>
17   -
18   - <div class="facet-menu-options facet-menu-less-options">
19   - <% results.each do |id, label, count| %>
20   - <%= facet_link_html(facet, params, id, label, count) %><br />
21   - <% end %>
22   - </div> <br />
23   -
24   - <% if facet_count > less_options_limit %>
25   - <%= link_to_function _("Options"),
26   - "facet_options_toggle('#{facet[:id].to_s}', '#{url_for(params.merge(:action => 'facets_browse', :facet_id => facet[:id], :asset => @asset, :escape => false))}'); " +
27   - "jQuery(this).toggleClass('facet-less-options')", :class => "facet-options-toggle" %>
28   - <br />
29   - <% end %>
30   -
31   - <% else %>
32   - <span class="facet-any-result-found"><%= _("No filter available") %></span>
33   - <% end %>
34   - </div>
35   - <% end %>
36   -</div>
app/views/search/_profile.rhtml
1 1 <li class="search-profile-item">
2   -<% if @empty_query or multiple_search? or !profile.enterprise? %>
  2 +<% if @empty_query || multiple_search? || !profile.enterprise? || !@search_engine %>
3 3 <%= profile_image_link profile, :portrait, 'div',
4 4 @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %>
5 5 <% else %>
... ...
app/views/search/_results_header.rhtml
1 1 <div class="search-results-header <%= "search-no-results" if @results[@asset].nil? or @results[@asset].length == 0 %>">
2   - <% if !@empty_query %>
3   - <div class="search-results-header-information">
4   - <% if @results[@asset].total_entries > 0 %>
5   - <%= label_total_found(@asset, @results[@asset].total_entries) %>
6   - <% if params[:display] != 'map' %>
7   - <span class="current-page"><%= _("Showing page %s of %s") % [@results[@asset].current_page, @results[@asset].total_pages] %></span>
8   - <% end %>
9   - <% end %>
10   - </div>
11   -
12   - <div class="search-results-header-facets-order-by">
13   - <%= facets_unselect_menu(@asset) %>
14   - <%= order_by(@asset) if params[:display] != 'map' %>
15   - </div>
16   - <% else %>
17   - <div id='search-filter-title'><%= @filter_title if @filter_title %></div>
18   - <% end %>
19   -
  2 + <div id='search-filter-title'><%= @filter_title if @filter_title %></div>
  3 + <%= display_filter(@asset, params[:display]) if map_capable?(@asset) %>
20 4 <div style="clear: both"></div>
21 5 </div>
... ...
app/views/search/articles.rhtml
... ... @@ -1,17 +0,0 @@
1   -<%= search_page_title( @titles[:articles], @category ) %>
2   -
3   -<div id="search-column-left">
4   - <% if !@empty_query %>
5   - <%= facets_menu(:articles, @facets) %>
6   - <% end %>
7   -</div>
8   -
9   -<div id="search-column-right">
10   - <%= render :partial => 'search_form', :locals => { :hint => _('Type the title, author or content desired') } %>
11   - <%= render :partial => 'results_header' %>
12   -
13   - <%= display_results %>
14   - <%= pagination_links @results[:articles] %>
15   -</div>
16   -
17   -<div style="clear: both"></div>
app/views/search/communities.rhtml
... ... @@ -1,25 +0,0 @@
1   -<%= search_page_title( @titles[:communities], @category ) %>
2   -
3   -<div id='search-column-left'>
4   - <% if logged_in? %>
5   - <% button_bar do %>
6   - <%# FIXME shouldn't the user create the community in the current environment instead of going to its home environment? %>
7   - <%= button(:add, __('New community'), user.url.merge(:controller => 'memberships', :action => 'new_community', :profile => user.identifier)) %>
8   - <% end %>
9   - <% end %>
10   -
11   - <% if !@empty_query %>
12   - <%= facets_menu(:communities, @facets) %>
13   - <% end %>
14   -</div>
15   -
16   -<div id='search-column-right'>
17   - <%= render :partial => 'search_form', :locals => { :hint => _("Type words about the community you're looking for") } %>
18   - <%= render :partial => 'results_header' %>
19   -
20   - <%= display_results %>
21   - <%= pagination_links @results.values.first %>
22   -</div>
23   -
24   -<div style="clear: both"></div>
25   -
app/views/search/contents.rhtml
... ... @@ -1 +0,0 @@
1   -articles.rhtml
2 0 \ No newline at end of file
app/views/search/enterprises.rhtml
... ... @@ -1,28 +0,0 @@
1   -<%= search_page_title( @titles[:enterprises], @category ) %>
2   -
3   -<div id="search-column-left">
4   - <% if logged_in? && environment.enabled?('enterprise_registration') %>
5   - <% button_bar do %>
6   - <%= button(:add, __('New enterprise'), {:controller => 'enterprise_registration'}) %>
7   - <% end %>
8   - <% end %>
9   -
10   - <% if !@empty_query %>
11   - <% button_bar do %>
12   - <%= display_map_list_button %>
13   - <% end %>
14   - <%= facets_menu(:enterprises, @facets) %>
15   - <% end %>
16   -</div>
17   -
18   -<div id="search-column-right">
19   - <%= render :partial => 'search_form', :locals => { :hint => _("Type words about the enterprise you're looking for") } %>
20   - <%= render :partial => 'results_header' %>
21   -
22   - <%= display_results(true) %>
23   - <% if params[:display] != 'map' %>
24   - <%= pagination_links @results[:enterprises] %>
25   - <% end %>
26   -</div>
27   -
28   -<div style="clear: both"></div>
app/views/search/events.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'events/agenda' %>
... ...
app/views/search/events.rhtml
... ... @@ -1,3 +0,0 @@
1   -<%= search_page_title( Environment.default.name + "'s " + @titles[:events], @category ) %>
2   -
3   -<%= render :partial => 'events/agenda' %>
app/views/search/index.rhtml
... ... @@ -7,7 +7,7 @@
7 7 <%= search_page_title(_('Search Results'), @category) %>
8 8 <%= render :partial => 'search_form', :locals => { :hint => '' } %>
9 9 <%= category_context(@category, params) %>
10   - <%= display_results %>
  10 + <%= display_results(@asset) %>
11 11  
12 12 <div id="category-childs">
13 13 <% if @category %>
... ...
app/views/search/people.rhtml
... ... @@ -1,19 +0,0 @@
1   -<%= search_page_title( @titles[:people], @category ) %>
2   -
3   -<div id='search-column-left'>
4   - <% if !@empty_query %>
5   - <%= facets_menu(:people, @facets) %>
6   - <% end %>
7   -</div>
8   -
9   -<div id='search-column-right'>
10   - <%= render :partial => 'search_form', :locals => { :hint => _("Type words about the person you're looking for") } %>
11   - <%= render :partial => 'results_header' %>
12   -
13   - <%= display_results %>
14   - <% if params[:display] != 'map' %>
15   - <%= pagination_links @results.values.first %>
16   - <% end %>
17   -</div>
18   -
19   -<div style="clear: both"></div>
app/views/search/products.rhtml
... ... @@ -1,26 +0,0 @@
1   -<%= search_page_title( @titles[:products], @category ) %>
2   -
3   -<div id="search-column-left">
4   - <% if !@empty_query %>
5   - <% button_bar do %>
6   - <%= display_map_list_button %>
7   -<% end %>
8   - <%= facets_menu(:products, @facets) %>
9   -<% end %>
10   -</div>
11   -
12   -<div id="search-column-right">
13   - <%= render :partial => 'search_form', :locals => { :hint => _('Type the product, service, city or qualifier desired') } %>
14   - <%= render :partial => 'results_header' %>
15   -
16   - <%= display_results(true) %>
17   - <% if !@one_page and params[:display] != 'map' %>
18   - <%= pagination_links @results[:products] %>
19   -<% end %>
20   -</div>
21   -
22   -<% javascript_tag do %>
23   - jQuery('.search-product-price-details').altBeautify();
24   -<% end %>
25   -
26   -<div style="clear: both"></div>
app/views/search/search_page.html.erb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +<%= search_page_title( @titles[@asset], @category ) %>
  2 +
  3 +<%= render :partial => 'results_header' %>
  4 +
  5 +<%= display_results(@asset) %>
  6 +<% if params[:display] != 'map' %>
  7 + <%= pagination_links @results[@asset] %>
  8 +<% end %>
  9 +
  10 +<div style="clear: both"></div>
  11 +
  12 +<% if @asset == :product %>
  13 + <% javascript_tag do %>
  14 + jQuery('.search-product-price-details').altBeautify();
  15 + <% end %>
  16 +<% end %>
... ...
lib/noosfero/plugin.rb
... ... @@ -351,6 +351,17 @@ class Noosfero::Plugin
351 351 nil
352 352 end
353 353  
  354 + # -> Specifies plugin that works as a search engine
  355 + # returns = true/false
  356 + def search_engine?
  357 + false
  358 + end
  359 +
  360 + # -> Realizes a full text search
  361 + # returns = whatever the plugin needs to render the view
  362 + def full_text_search(asset, query, category, paginate_options)
  363 + end
  364 +
354 365 def method_missing(method, *args, &block)
355 366 # This is a generic hotspot for all controllers on Noosfero.
356 367 # If any plugin wants to define filters to run on any controller, the name of
... ...
plugins/solr/dependencies.rb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +require 'active_record'
  2 +require 'acts_as_searchable'
  3 +require 'acts_as_faceted'
... ...
plugins/solr/lib/solr_plugin.rb
  1 +require_dependency 'solr_plugin/search_helper'
  2 +
1 3 class SolrPlugin < Noosfero::Plugin
2 4  
  5 + include SolrPlugin::SearchHelper
  6 +
3 7 def self.plugin_name
4 8 "Solr"
5 9 end
... ... @@ -8,6 +12,16 @@ class SolrPlugin &lt; Noosfero::Plugin
8 12 _("Uses Solr as search engine.")
9 13 end
10 14  
  15 + def search_engine?
  16 + true
  17 + end
  18 +
  19 + def full_text_search(asset, query, category, paginate_options)
  20 + asset_class = asset_class(asset)
  21 + solr_options = solr_options(asset, category)
  22 + asset_class.find_by_contents(query, paginate_options, solr_options)
  23 + end
  24 +
11 25 end
12 26  
13 27 Dir[File.join(SolrPlugin.root_path, 'lib', 'ext', '*.rb')].each {|file| require_dependency file }
... ...
plugins/solr/lib/solr_plugin/results_helper.rb 0 → 100644
... ... @@ -0,0 +1,113 @@
  1 +class SolrPlugin < Noosfero::Plugin
  2 + module ResultsHelper
  3 + def set_results_variables
  4 + if @results[@asset].kind_of?(Hash)
  5 + ret = @results[@asset]
  6 + @results[@asset] = ret[:results]
  7 + @facets = ret[:facets]
  8 + @all_facets = ret[:all_facets]
  9 + end
  10 + end
  11 +
  12 + def order_by(asset)
  13 + options = SolrPlugin::SortOptions[asset].map do |name, options|
  14 + next if options[:if] && !instance_eval(&options[:if])
  15 + [_(options[:label]), name.to_s]
  16 + end.compact
  17 +
  18 + content_tag('div', _('Sort results by ') +
  19 + select_tag(asset.to_s + '[order]', options_for_select(options, params[:order_by] || 'none'),
  20 + {:onchange => "window.location = jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}
  21 + ),
  22 + :class => "search-ordering"
  23 + )
  24 + end
  25 +
  26 + def label_total_found(asset, total_found)
  27 + labels = {
  28 + :products => _("%s products offers found"),
  29 + :articles => _("%s articles found"),
  30 + :events => _("%s events found"),
  31 + :people => _("%s people found"),
  32 + :enterprises => _("%s enterprises found"),
  33 + :communities => _("%s communities found"),
  34 + }
  35 + content_tag('span', labels[asset] % total_found,
  36 + :class => "total-pages-found") if labels[asset]
  37 + end
  38 +
  39 + def facets_menu(asset, _facets)
  40 + @asset_class = asset_class(asset)
  41 + @facets = _facets
  42 + render(:partial => 'facets_menu')
  43 + end
  44 +
  45 + def facets_unselect_menu(asset)
  46 + @asset_class = asset_class(asset)
  47 + render(:partial => 'facets_unselect_menu')
  48 + end
  49 +
  50 + def facet_selecteds_html_for(environment, klass, params)
  51 + def name_with_extra(klass, facet, value)
  52 + name = klass.facet_result_name(facet, value)
  53 + name = name[0] + name[1] if name.kind_of?(Array)
  54 + name
  55 + end
  56 +
  57 + ret = []
  58 + params = params.dup
  59 + params[:facet].each do |id, value|
  60 + facet = klass.facet_by_id(id.to_sym)
  61 + next unless facet
  62 + if value.kind_of?(Hash)
  63 + label_hash = facet[:label].call(environment)
  64 + value.each do |label_id, value|
  65 + facet[:label_id] = label_id
  66 + facet[:label] = label_hash[label_id]
  67 + value.to_a.each do |value|
  68 + ret << [facet[:label], name_with_extra(klass, facet, value),
  69 + params.merge(:facet => params[:facet].merge(id => params[:facet][id].merge(label_id => params[:facet][id][label_id].to_a.reject{ |v| v == value })))]
  70 + end
  71 + end
  72 + else
  73 + ret << [klass.facet_label(facet), name_with_extra(klass, facet, value),
  74 + params.merge(:facet => params[:facet].reject{ |k,v| k == id })]
  75 + end
  76 + end
  77 +
  78 + ret.map do |label, name, url|
  79 + content_tag('div', content_tag('span', label, :class => 'facet-selected-label') +
  80 + content_tag('span', name, :class => 'facet-selected-name') +
  81 + link_to('', url, :class => 'facet-selected-remove', :title => 'remove facet'), :class => 'facet-selected')
  82 + end.join
  83 + end
  84 +
  85 + def facet_link_html(facet, params, value, label, count)
  86 + params = params ? params.dup : {}
  87 + has_extra = label.kind_of?(Array)
  88 + link_label = has_extra ? label[0] : label
  89 + id = facet[:solr_field].to_s
  90 + params[:facet] ||= {}
  91 + params[:facet][id] ||= {}
  92 + params[:page] = {} if params[:page]
  93 +
  94 + selected = facet[:label_id].nil? ? params[:facet][id] == value : params[:facet][id][facet[:label_id]].to_a.include?(value)
  95 +
  96 + if count > 0
  97 + url = params.merge(:facet => params[:facet].merge(
  98 + id => facet[:label_id].nil? ? value : params[:facet][id].merge( facet[:label_id] => params[:facet][id][facet[:label_id]].to_a | [value] )
  99 + ))
  100 + else
  101 + # preserve others filters and change this filter
  102 + url = params.merge(:facet => params[:facet].merge(
  103 + id => facet[:label_id].nil? ? value : { facet[:label_id] => value }
  104 + ))
  105 + end
  106 +
  107 + content_tag 'div', link_to(link_label, url, :class => 'facet-result-link-label') +
  108 + content_tag('span', (has_extra ? label[1] : ''), :class => 'facet-result-extra-label') +
  109 + (count > 0 ? content_tag('span', " (#{count})", :class => 'facet-result-count') : ''),
  110 + :class => 'facet-menu-item' + (selected ? ' facet-result-link-selected' : '')
  111 + end
  112 + end
  113 +end
... ...
plugins/solr/lib/solr_plugin/search_helper.rb 0 → 100644
... ... @@ -0,0 +1,83 @@
  1 +class SolrPlugin < Noosfero::Plugin
  2 +
  3 + SortOptions = {
  4 + :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  5 + :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
  6 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  7 + :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng },
  8 + :solr_opts => {:sort => "geodist() asc",
  9 + :latitude => proc{ current_user.person.lat }, :longitude => proc{ current_user.person.lng }}},
  10 + ],
  11 + :events => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  12 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  13 + ],
  14 + :articles => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  15 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  16 + :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
  17 + ],
  18 + :enterprises => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  19 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  20 + ],
  21 + :people => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  22 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  23 + ],
  24 + :communities => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  25 + :name, {:label => _('Name'), :solr_opts => {:sort => 'solr_plugin_name_sortable asc'}},
  26 + ],
  27 + }
  28 +
  29 + module SearchHelper
  30 + def asset_class(asset)
  31 + asset.to_s.singularize.camelize.constantize
  32 + end
  33 +
  34 + def asset_table(asset)
  35 + asset_class(asset).table_name
  36 + end
  37 +
  38 + def multiple_search?
  39 + ['index', 'category_index'].include?(context.params[:action])
  40 + end
  41 +
  42 + def filters(asset)
  43 + case asset
  44 + when :products
  45 + ['solr_plugin_public:true']
  46 + when :events
  47 + []
  48 + else
  49 + ['solr_plugin_public:true']
  50 + end
  51 + end
  52 +
  53 + def results_only?
  54 + context.params[:action] == 'index'
  55 + end
  56 +
  57 + def solr_options(asset, category)
  58 + asset_class = asset_class(asset)
  59 + solr_options = {}
  60 + if !multiple_search?
  61 + if !results_only? and asset_class.respond_to? :facets
  62 + solr_options.merge! asset_class.facets_find_options(context.params[:facet])
  63 + solr_options[:all_facets] = true
  64 + end
  65 + solr_options[:filter_queries] ||= []
  66 + solr_options[:filter_queries] += filters(asset)
  67 + solr_options[:filter_queries] << "environment_id:#{context.environment.id}"
  68 + solr_options[:filter_queries] << asset_class.facet_category_query.call(category) if category
  69 +
  70 + solr_options[:boost_functions] ||= []
  71 + context.params[:order_by] = nil if context.params[:order_by] == 'none'
  72 + if context.params[:order_by]
  73 + order = SolrPlugin::SortOptions[asset][context.params[:order_by].to_sym]
  74 + raise "Unknown order by" if order.nil?
  75 + order[:solr_opts].each do |opt, value|
  76 + solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
  77 + end
  78 + end
  79 + end
  80 + solr_options
  81 + end
  82 + end
  83 +end
... ...
plugins/solr/test/unit/article_test.rb 0 → 100644
... ... @@ -0,0 +1,115 @@
  1 +require 'test_helper'
  2 +
  3 +class ArticleTest < ActiveSupport::TestCase
  4 + def setup
  5 + @environment = Environment.default
  6 + @environment.enable_plugin(SolrPlugin)
  7 + @profile = create_user('testing').person
  8 + end
  9 +
  10 + attr_accessor :environment, :profile
  11 +
  12 + should 'act as faceted' do
  13 + person = fast_create(Person)
  14 + cat = Category.create!(:name => 'hardcore', :environment_id => Environment.default.id)
  15 + a = Article.create!(:name => 'black flag review', :profile_id => person.id)
  16 + a.add_category(cat, true)
  17 + a.save!
  18 + assert_equal Article.type_name, Article.facet_by_id(:solr_plugin_f_type)[:proc].call(a.send(:solr_plugin_f_type))
  19 + assert_equal Person.type_name, Article.facet_by_id(:solr_plugin_f_profile_type)[:proc].call(a.send(:solr_plugin_f_profile_type))
  20 + assert_equal a.published_at, a.send(:solr_plugin_f_published_at)
  21 + assert_equal ['hardcore'], a.send(:solr_plugin_f_category)
  22 + assert_equal "solr_plugin_category_filter:\"#{cat.id}\"", Article.facet_category_query.call(cat)
  23 + end
  24 +
  25 + should 'act as searchable' do
  26 + TestSolr.enable
  27 + person = fast_create(Person, :name => "Hiro", :address => 'U-Stor-It @ Inglewood, California',
  28 + :nickname => 'Protagonist')
  29 + person2 = fast_create(Person, :name => "Raven")
  30 + category = fast_create(Category, :name => "science fiction", :acronym => "sf", :abbreviation => "sci-fi")
  31 + a = Article.create!(:name => 'a searchable article about bananas', :profile_id => person.id,
  32 + :body => 'the body talks about mosquitos', :abstract => 'and the abstract is about beer',
  33 + :filename => 'not_a_virus.exe')
  34 + a.add_category(category)
  35 + c = a.comments.build(:title => 'snow crash', :author => person2, :body => 'wanna try some?')
  36 + c.save!
  37 +
  38 + # fields
  39 + assert_includes Article.find_by_contents('bananas')[:results].docs, a
  40 + assert_includes Article.find_by_contents('mosquitos')[:results].docs, a
  41 + assert_includes Article.find_by_contents('beer')[:results].docs, a
  42 + assert_includes Article.find_by_contents('not_a_virus.exe')[:results].docs, a
  43 + # filters
  44 + assert_includes Article.find_by_contents('bananas', {}, {:filter_queries => ["solr_plugin_public:true"]})[:results].docs, a
  45 + assert_not_includes Article.find_by_contents('bananas', {}, {:filter_queries => ["solr_plugin_public:false"]})[:results].docs, a
  46 + assert_includes Article.find_by_contents('bananas', {}, {:filter_queries => ["environment_id:\"#{Environment.default.id}\""]})[:results].docs, a
  47 + assert_includes Article.find_by_contents('bananas', {}, {:filter_queries => ["profile_id:\"#{person.id}\""]})[:results].docs, a
  48 + # includes
  49 + assert_includes Article.find_by_contents('Hiro')[:results].docs, a
  50 + assert_includes Article.find_by_contents("person-#{person.id}")[:results].docs, a
  51 + assert_includes Article.find_by_contents("California")[:results].docs, a
  52 + assert_includes Article.find_by_contents("Protagonist")[:results].docs, a
  53 +# FIXME: After merging with AI1826, searching on comments is not working
  54 +# assert_includes Article.find_by_contents("snow")[:results].docs, a
  55 +# assert_includes Article.find_by_contents("try some")[:results].docs, a
  56 +# assert_includes Article.find_by_contents("Raven")[:results].docs, a
  57 +#
  58 +# FIXME: After merging with AI1826, searching on categories is not working
  59 +# assert_includes Article.find_by_contents("science")[:results].docs, a
  60 +# assert_includes Article.find_by_contents(category.slug)[:results].docs, a
  61 +# assert_includes Article.find_by_contents("sf")[:results].docs, a
  62 +# assert_includes Article.find_by_contents("sci-fi")[:results].docs, a
  63 + end
  64 +
  65 + should 'boost name matches' do
  66 + TestSolr.enable
  67 + person = fast_create(Person)
  68 + in_body = Article.create!(:name => 'something', :profile_id => person.id, :body => 'bananas in the body!')
  69 + in_name = Article.create!(:name => 'bananas in the name!', :profile_id => person.id)
  70 + assert_equal [in_name, in_body], Article.find_by_contents('bananas')[:results].docs
  71 + end
  72 +
  73 + should 'boost if profile is enabled' do
  74 + TestSolr.enable
  75 + person2 = fast_create(Person, :enabled => false)
  76 + art_profile_disabled = Article.create!(:name => 'profile disabled', :profile_id => person2.id)
  77 + person1 = fast_create(Person, :enabled => true)
  78 + art_profile_enabled = Article.create!(:name => 'profile enabled', :profile_id => person1.id)
  79 + assert_equal [art_profile_enabled, art_profile_disabled], Article.find_by_contents('profile')[:results].docs
  80 + end
  81 +
  82 + should 'index comments body together with article' do
  83 + TestSolr.enable
  84 + owner = create_user('testuser').person
  85 + art = fast_create(TinyMceArticle, :profile_id => owner.id, :name => 'ytest')
  86 + c1 = Comment.create(:title => 'test comment', :body => 'anything', :author => owner, :source => art); c1.save!
  87 +
  88 + assert_includes Article.find_by_contents('anything')[:results], art
  89 + end
  90 +
  91 + should 'index by schema name when database is postgresql' do
  92 + TestSolr.enable
  93 + uses_postgresql 'schema_one'
  94 + art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id)
  95 + assert_equal [art1], Article.find_by_contents('thing')[:results].docs
  96 + uses_postgresql 'schema_two'
  97 + art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id)
  98 + assert_not_includes Article.find_by_contents('thing')[:results], art1
  99 + assert_includes Article.find_by_contents('thing')[:results], art2
  100 + uses_postgresql 'schema_one'
  101 + assert_includes Article.find_by_contents('thing')[:results], art1
  102 + assert_not_includes Article.find_by_contents('thing')[:results], art2
  103 + uses_sqlite
  104 + end
  105 +
  106 + should 'not index by schema name when database is not postgresql' do
  107 + TestSolr.enable
  108 + uses_sqlite
  109 + art1 = Article.create!(:name => 'some thing', :profile_id => @profile.id)
  110 + assert_equal [art1], Article.find_by_contents('thing')[:results].docs
  111 + art2 = Article.create!(:name => 'another thing', :profile_id => @profile.id)
  112 + assert_includes Article.find_by_contents('thing')[:results], art1
  113 + assert_includes Article.find_by_contents('thing')[:results], art2
  114 + end
  115 +end
... ...
plugins/solr/test/unit/environment_test.rb 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +require 'test_helper'
  2 +
  3 +class EnvironmentTest < ActiveSupport::TestCase
  4 + def setup
  5 + @environment = Environment.default
  6 + @environment.enable_plugin(SolrPlugin)
  7 + end
  8 +
  9 + attr_accessor :environment
  10 +
  11 + should 'find by contents from articles' do
  12 + TestSolr.enable
  13 + env = fast_create(Environment)
  14 + env.enable_plugin(SolrPlugin)
  15 + assert_nothing_raised do
  16 + env.articles.find_by_contents('')[:results]
  17 + end
  18 + end
  19 +
  20 + should 'return more than 10 enterprises by contents' do
  21 + TestSolr.enable
  22 + Enterprise.destroy_all
  23 + ('1'..'20').each do |n|
  24 + Enterprise.create!(:name => 'test ' + n, :identifier => 'test_' + n)
  25 + end
  26 +
  27 + assert_equal 20, environment.enterprises.find_by_contents('test')[:results].total_entries
  28 + end
  29 +end
... ...
plugins/solr/test/unit/event_test.rb 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +require 'test_helper'
  2 +
  3 +class EventTest < ActiveSupport::TestCase
  4 + def setup
  5 + @environment = Environment.default
  6 + @environment.enable_plugin(SolrPlugin)
  7 + @profile = create_user('testing').person
  8 + end
  9 +
  10 + attr_accessor :environment, :profile
  11 +
  12 + should 'be indexed by title' do
  13 + TestSolr.enable
  14 + e = Event.create!(:name => 'my surprisingly nice event', :start_date => Date.new(2008, 06, 06), :profile => profile)
  15 + assert_includes Event.find_by_contents('surprisingly')[:results], e
  16 + end
  17 +
  18 + should 'be indexed by body' do
  19 + TestSolr.enable
  20 + e = Event.create!(:name => 'bli', :start_date => Date.new(2008, 06, 06), :profile => profile, :body => 'my surprisingly long description about my freaking nice event')
  21 + assert_includes Event.find_by_contents('surprisingly')[:results], e
  22 + end
  23 +end
... ...
plugins/solr/test/unit/text_article_test.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +require 'test_helper'
  2 +
  3 +class TextArticleTest < ActiveSupport::TestCase
  4 + def setup
  5 + @environment = Environment.default
  6 + @environment.enable_plugin(SolrPlugin)
  7 + end
  8 +
  9 + attr_accessor :environment
  10 +
  11 + should 'found TextileArticle by TextArticle indexes' do
  12 + TestSolr.enable
  13 + person = create_user('testuser').person
  14 + article = TextileArticle.create!(:name => 'found article test', :profile => person)
  15 + assert_equal TextileArticle.find_by_contents('found')[:results].docs, TextArticle.find_by_contents('found')[:results].docs
  16 + end
  17 +end
... ...
plugins/solr/test/unit/tiny_mce_article_test.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +require 'test_helper'
  2 +
  3 +class TinyMceArticleTest < ActiveSupport::TestCase
  4 + def setup
  5 + @environment = Environment.default
  6 + @environment.enable_plugin(SolrPlugin)
  7 + @profile = create_user('testing').person
  8 + end
  9 +
  10 + attr_accessor :environment, :profile
  11 +
  12 + should 'be found when searching for articles by query' do
  13 + TestSolr.enable
  14 + tma = TinyMceArticle.create!(:name => 'test tinymce article', :body => '---', :profile => profile)
  15 + assert_includes TinyMceArticle.find_by_contents('article')[:results], tma
  16 + assert_includes Article.find_by_contents('article')[:results], tma
  17 + end
  18 +end
... ...
plugins/solr/views/search/.communities.rhtml.swp 0 → 100644
No preview for this file type
plugins/solr/views/search/.people.rhtml.swp 0 → 100644
No preview for this file type
plugins/solr/views/search/_facets.html.erb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<% if logged_in? %>
  2 + <% button_bar do %>
  3 + <%# FIXME shouldn't the user create the community in the current environment instead of going to its home environment? %>
  4 + <%= button(:add, __('New community'), user.url.merge(:controller => 'memberships', :action => 'new_community', :profile => user.identifier)) if @asset == :communities %>
  5 + <%= button(:add, __('New enterprise'), {:controller => 'enterprise_registration'}) if @asset == :enterprises && environment.enabled?('enterprise_registration') %>
  6 + <% end %>
  7 +<% end %>
  8 +<% if !@empty_query %>
  9 + <%= facets_menu(@asset, @facets) %>
  10 +<% end %>
... ...
plugins/solr/views/search/_facets_menu.html.erb 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +<% less_options_limit = 8 %>
  2 +
  3 +<div id="facets-menu">
  4 + <% @asset_class.map_facets_for(environment).each do |facet| %>
  5 +
  6 + <div id="facet-menu-<%= facet[:id].to_s %>" class="facet-menu">
  7 + <div class="facet-menu-label">
  8 + <%= @asset_class.facet_label(facet) %>
  9 + </div>
  10 +
  11 + <% results = @asset_class.map_facet_results(facet, params[:facet], @facets, @all_facets, :limit => less_options_limit) %>
  12 + <% facet_count = results.total_entries %>
  13 +
  14 + <% if facet_count > 0 %>
  15 + <div class="facet-menu-options facet-menu-more-options" style="display: none">
  16 + </div>
  17 +
  18 + <div class="facet-menu-options facet-menu-less-options">
  19 + <% results.each do |id, label, count| %>
  20 + <%= facet_link_html(facet, params, id, label, count) %><br />
  21 + <% end %>
  22 + </div> <br />
  23 +
  24 + <% if facet_count > less_options_limit %>
  25 + <%= link_to_function _("Options"),
  26 + "facet_options_toggle('#{facet[:id].to_s}', '#{url_for(params.merge(:action => 'facets_browse', :facet_id => facet[:id], :asset => @asset, :escape => false))}'); " +
  27 + "jQuery(this).toggleClass('facet-less-options')", :class => "facet-options-toggle" %>
  28 + <br />
  29 + <% end %>
  30 +
  31 + <% else %>
  32 + <span class="facet-any-result-found"><%= _("No filter available") %></span>
  33 + <% end %>
  34 + </div>
  35 + <% end %>
  36 +</div>
... ...
plugins/solr/views/search/_results.html.erb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +<%= render :partial => 'search_form', :locals => { :hint => _("Type words about the %s you're looking for") % @asset.to_s.singularize } %>
  2 +<%= render :partial => 'results_header' %>
  3 +
  4 +<%= display_results(@asset) %>
  5 +<% if params[:display] != 'map' %>
  6 + <%= pagination_links @results[@asset] %>
  7 +<% end %>
... ...
plugins/solr/views/search/_results_header.html.erb 0 → 100644
... ... @@ -0,0 +1,22 @@
  1 +<div class="search-results-header <%= "search-no-results" if @results[@asset].nil? or @results[@asset].length == 0 %>">
  2 + <% if !@empty_query %>
  3 + <div class="search-results-header-information">
  4 + <% if @results[@asset].total_entries > 0 %>
  5 + <%= label_total_found(@asset, @results[@asset].total_entries) %>
  6 + <% if params[:display] != 'map' %>
  7 + <span class="current-page"><%= _("Showing page %s of %s") % [@results[@asset].current_page, @results[@asset].total_pages] %></span>
  8 + <% end %>
  9 + <% end %>
  10 + </div>
  11 +
  12 + <div class="search-results-header-facets-order-by">
  13 + <%= facets_unselect_menu(@asset) %>
  14 + <%= order_by(@asset) if params[:display] != 'map' %>
  15 + </div>
  16 + <% else %>
  17 + <div id='search-filter-title'><%= @filter_title if @filter_title %></div>
  18 + <% end %>
  19 + <% float = !@empty_query && params[:display] == 'list' ? 'left' : 'right' %>
  20 + <%= display_filter(@asset, params[:display], float) if map_capable?(@asset) %>
  21 + <div style="clear: both"></div>
  22 +</div>
... ...
plugins/solr/views/search/search_page.html.erb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +<% extend SolrPlugin::ResultsHelper %>
  2 +<% set_results_variables %>
  3 +
  4 +<%= search_page_title( @titles[@asset], @category ) %>
  5 +
  6 +<% if !@empty_query %>
  7 + <div id='search-column-left'>
  8 + <%= render :partial => 'facets' %>
  9 + </div>
  10 +
  11 + <div id='search-column-right'>
  12 + <%= render :partial => 'results' %>
  13 + </div>
  14 +<% else %>
  15 + <%= render :partial => 'results' %>
  16 +<% end %>
  17 +
  18 +<div style="clear: both"></div>
  19 +
  20 +<% if @asset == :products %>
  21 + <% javascript_tag do %>
  22 + jQuery('.search-product-price-details').altBeautify();
  23 + <% end %>
  24 +<% end %>
... ...
public/stylesheets/search.css
... ... @@ -647,6 +647,7 @@ li.search-product-item hr {
647 647 font-weight: bold;
648 648 font-size: 130%;
649 649 line-height: 35px;
  650 + float: left;
650 651 }
651 652 .search-results-header.search-no-results {
652 653 border-bottom: 0px;
... ... @@ -665,6 +666,9 @@ li.search-product-item hr {
665 666 color: #ff0000
666 667 }
667 668  
  669 +#search-display-filter {
  670 + margin-top: 20px;
  671 +}
668 672  
669 673 /* Search field and button */
670 674  
... ...