Commit 6e82bdc7062af8f0447fff19593054948cbeb5e5
1 parent
144d5783
Exists in
master
and in
29 other branches
[otw] products action... =/
Showing
34 changed files
with
604 additions
and
338 deletions
Show diff stats
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
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> |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'events/agenda' %> | ... | ... |
app/views/search/events.rhtml
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> |
... | ... | @@ -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/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 < 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 } | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
No preview for this file type
No preview for this file type
... | ... | @@ -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 %> | ... | ... |
... | ... | @@ -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> | ... | ... |
... | ... | @@ -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 %> | ... | ... |
... | ... | @@ -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> | ... | ... |
... | ... | @@ -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 | ... | ... |