Commit 50def8451caa76a3e69203359c069c08c6585038
Exists in
master
and in
29 other branches
Merge remote branch 'noosfero-bsc/new-search-merge'
Conflicts: app/controllers/application.rb app/controllers/public/browse_controller.rb app/helpers/application_helper.rb app/helpers/display_helper.rb app/models/environment_finder.rb app/models/product.rb app/views/layouts/_javascript.rhtml app/views/layouts/application-ng.rhtml public/javascripts/application.js public/stylesheets/application.css test/functional/browse_controller_test.rb test/functional/search_controller_test.rb vendor/plugins/acts_as_solr_reloaded/lib/tasks/solr.rake
Showing
129 changed files
with
7962 additions
and
5141 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 129 files displayed.
app/controllers/application.rb
1 | 1 | require 'application_controller' |
2 | + | |
3 | +# his is the application's main controller. Features defined here are | |
4 | +# available in all controllers. | |
5 | +class ApplicationController < ActionController::Base | |
6 | + | |
7 | + before_filter :change_pg_schema | |
8 | + | |
9 | + include ApplicationHelper | |
10 | + layout :get_layout | |
11 | + def get_layout | |
12 | + theme_option(:layout) || 'application' | |
13 | + end | |
14 | + | |
15 | + filter_parameter_logging :password | |
16 | + | |
17 | + def log_processing | |
18 | + super | |
19 | + return unless ENV['RAILS_ENV'] == 'production' | |
20 | + if logger && logger.info? | |
21 | + logger.info(" HTTP Referer: #{request.referer}") | |
22 | + logger.info(" User Agent: #{request.user_agent}") | |
23 | + logger.info(" Accept-Language: #{request.headers['HTTP_ACCEPT_LANGUAGE']}") | |
24 | + end | |
25 | + end | |
26 | + | |
27 | + helper :document | |
28 | + helper :language | |
29 | + | |
30 | + def self.no_design_blocks | |
31 | + @no_design_blocks = true | |
32 | + end | |
33 | + def self.uses_design_blocks? | |
34 | + !@no_design_blocks | |
35 | + end | |
36 | + def uses_design_blocks? | |
37 | + !@no_design_blocks && self.class.uses_design_blocks? | |
38 | + end | |
39 | + | |
40 | + # Be sure to include AuthenticationSystem in Application Controller instead | |
41 | + include AuthenticatedSystem | |
42 | + include PermissionCheck | |
43 | + | |
44 | + def self.require_ssl(*options) | |
45 | + before_filter :check_ssl, *options | |
46 | + end | |
47 | + def check_ssl | |
48 | + return true if (request.ssl? || ENV['RAILS_ENV'] == 'development') | |
49 | + redirect_to_ssl | |
50 | + end | |
51 | + def redirect_to_ssl | |
52 | + if environment.enable_ssl | |
53 | + redirect_to(params.merge(:protocol => 'https://', :host => ssl_hostname)) | |
54 | + true | |
55 | + else | |
56 | + false | |
57 | + end | |
58 | + end | |
59 | + | |
60 | + def self.refuse_ssl(*options) | |
61 | + before_filter :avoid_ssl, *options | |
62 | + end | |
63 | + def avoid_ssl | |
64 | + if (!request.ssl? || ENV['RAILS_ENV'] == 'development') | |
65 | + true | |
66 | + else | |
67 | + redirect_to(params.merge(:protocol => 'http://')) | |
68 | + false | |
69 | + end | |
70 | + end | |
71 | + | |
72 | + before_filter :set_locale | |
73 | + def set_locale | |
74 | + FastGettext.available_locales = Noosfero.available_locales | |
75 | + FastGettext.default_locale = Noosfero.default_locale | |
76 | + FastGettext.set_locale(params[:lang] || session[:lang] || Noosfero.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') | |
77 | + if params[:lang] | |
78 | + session[:lang] = params[:lang] | |
79 | + end | |
80 | + end | |
81 | + | |
82 | + include NeedsProfile | |
83 | + | |
84 | + before_filter :detect_stuff_by_domain | |
85 | + before_filter :init_noosfero_plugins | |
86 | + attr_reader :environment | |
87 | + | |
88 | + before_filter :load_terminology | |
89 | + | |
90 | + # declares that the given <tt>actions</tt> cannot be accessed by other HTTP | |
91 | + # method besides POST. | |
92 | + def self.post_only(actions, redirect = { :action => 'index'}) | |
93 | + verify :method => :post, :only => actions, :redirect_to => redirect | |
94 | + end | |
95 | + | |
96 | + helper_method :current_person, :current_person | |
97 | + | |
98 | + def change_pg_schema | |
99 | + if Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql? | |
100 | + Noosfero::MultiTenancy.db_by_host = request.host | |
101 | + end | |
102 | + end | |
103 | + | |
104 | + protected | |
105 | + | |
106 | + def boxes_editor? | |
107 | + false | |
108 | + end | |
109 | + | |
110 | + def content_editor? | |
111 | + false | |
112 | + end | |
113 | + | |
114 | + def user | |
115 | + current_user.person if logged_in? | |
116 | + end | |
117 | + | |
118 | + alias :current_person :user | |
119 | + | |
120 | + # TODO: move this logic somewhere else (Domain class?) | |
121 | + def detect_stuff_by_domain | |
122 | + @domain = Domain.find_by_name(request.host) | |
123 | + if @domain.nil? | |
124 | + @environment = Environment.default | |
125 | + else | |
126 | + @environment = @domain.environment | |
127 | + @profile = @domain.profile | |
128 | + end | |
129 | + end | |
130 | + | |
131 | + def init_noosfero_plugins | |
132 | + @plugins = Noosfero::Plugin::Manager.new(self) | |
133 | + @plugins.enabled_plugins.map(&:class).each do |plugin| | |
134 | + prepend_view_path(plugin.view_path) | |
135 | + end | |
136 | + init_noosfero_plugins_controller_filters | |
137 | + end | |
138 | + | |
139 | + # This is a generic method that initialize any possible filter defined by a | |
140 | + # plugin to the current controller being initialized. | |
141 | + def init_noosfero_plugins_controller_filters | |
142 | + @plugins.enabled_plugins.each do |plugin| | |
143 | + plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter| | |
144 | + self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {})) | |
145 | + self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block]) | |
146 | + end | |
147 | + end | |
148 | + end | |
149 | + | |
150 | + def load_terminology | |
151 | + # cache terminology for performance | |
152 | + @@terminology_cache ||= {} | |
153 | + @@terminology_cache[environment.id] ||= environment.terminology | |
154 | + Noosfero.terminology = @@terminology_cache[environment.id] | |
155 | + end | |
156 | + | |
157 | + def render_not_found(path = nil) | |
158 | + @no_design_blocks = true | |
159 | + @path ||= request.path | |
160 | + render :template => 'shared/not_found.rhtml', :status => 404, :layout => get_layout | |
161 | + end | |
162 | + alias :render_404 :render_not_found | |
163 | + | |
164 | + def render_access_denied(message = nil, title = nil) | |
165 | + @no_design_blocks = true | |
166 | + @message = message | |
167 | + @title = title | |
168 | + render :template => 'shared/access_denied.rhtml', :status => 403 | |
169 | + end | |
170 | + | |
171 | +end | ... | ... |
app/controllers/public/browse_controller.rb
... | ... | @@ -1,79 +0,0 @@ |
1 | -class BrowseController < PublicController | |
2 | - | |
3 | - no_design_blocks | |
4 | - | |
5 | - FILTERS = %w( | |
6 | - more_recent | |
7 | - more_active | |
8 | - more_popular | |
9 | - more_comments | |
10 | - more_views | |
11 | - ) | |
12 | - | |
13 | - def per_page | |
14 | - 27 | |
15 | - end | |
16 | - | |
17 | - def people | |
18 | - @filter = filter | |
19 | - @title = self.filter_description(params[:action] + '_' + @filter ) | |
20 | - | |
21 | - @results = @environment.people.visible.send(@filter) | |
22 | - | |
23 | - if !params[:query].blank? | |
24 | - @results = @results.find_by_contents(params[:query], {:per_page => per_page, :page => params[:page]})[:results] | |
25 | - else | |
26 | - @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) | |
27 | - end | |
28 | - end | |
29 | - | |
30 | - def communities | |
31 | - @filter = filter | |
32 | - @title = self.filter_description(params[:action] + '_' + @filter ) | |
33 | - | |
34 | - @results = @environment.communities.visible.send(@filter) | |
35 | - | |
36 | - if !params[:query].blank? | |
37 | - @results = @results.find_by_contents(params[:query], {:per_page => per_page, :page => params[:page]})[:results] | |
38 | - else | |
39 | - @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) | |
40 | - end | |
41 | - end | |
42 | - | |
43 | - def contents | |
44 | - @filter = filter | |
45 | - @title = self.filter_description(params[:action] + '_' + @filter ) | |
46 | - | |
47 | - @results = @environment.articles.published.text_articles.send(@filter) | |
48 | - | |
49 | - if !params[:query].blank? | |
50 | - @results = @results.find_by_contents(params[:query])[:results] | |
51 | - end | |
52 | - @results = @results.compact.paginate(:per_page => per_page, :page => params[:page]) | |
53 | - end | |
54 | - | |
55 | - protected | |
56 | - | |
57 | - def filter | |
58 | - if FILTERS.include?(params[:filter]) | |
59 | - params[:filter] | |
60 | - else | |
61 | - 'more_recent' | |
62 | - end | |
63 | - end | |
64 | - | |
65 | - def filter_description(str) | |
66 | - { | |
67 | - 'people_more_recent' => _('More recent people'), | |
68 | - 'people_more_active' => _('More active people'), | |
69 | - 'people_more_popular' => _('More popular people'), | |
70 | - 'communities_more_recent' => _('More recent communities'), | |
71 | - 'communities_more_active' => _('More active communities'), | |
72 | - 'communities_more_popular' => _('More popular communities'), | |
73 | - 'contents_more_recent' => _('More recent contents'), | |
74 | - 'contents_more_views' => _('Most viewed contents'), | |
75 | - 'contents_more_comments' => _('Most commented contents'), | |
76 | - }[str] || str | |
77 | - end | |
78 | - | |
79 | -end |
... | ... | @@ -0,0 +1,28 @@ |
1 | +class MapBalloonController < PublicController | |
2 | + | |
3 | + before_filter :profile, :only => [:person, :enterprise, :community] | |
4 | + | |
5 | + def product | |
6 | + @product = Product.find(params[:id]) | |
7 | + render :action => 'product', :layout => false | |
8 | + end | |
9 | + | |
10 | + def person | |
11 | + render :action => 'profile', :layout => false | |
12 | + end | |
13 | + | |
14 | + def enterprise | |
15 | + render :action => 'profile', :layout => false | |
16 | + end | |
17 | + | |
18 | + def community | |
19 | + render :action => 'profile', :layout => false | |
20 | + end | |
21 | + | |
22 | + protected | |
23 | + | |
24 | + def profile | |
25 | + @profile = Profile.find(params[:id]) | |
26 | + end | |
27 | + | |
28 | +end | ... | ... |
app/controllers/public/search_controller.rb
1 | 1 | class SearchController < PublicController |
2 | 2 | |
3 | + MAP_SEARCH_LIMIT = 2000 | |
4 | + LIST_SEARCH_LIMIT = 20 | |
5 | + BLOCKS_SEARCH_LIMIT = 18 | |
6 | + MULTIPLE_SEARCH_LIMIT = 8 | |
7 | + | |
3 | 8 | helper TagsHelper |
9 | + include SearchHelper | |
10 | + include ActionView::Helpers::NumberHelper | |
4 | 11 | |
5 | 12 | before_filter :load_category |
6 | - before_filter :prepare_filter | |
7 | - before_filter :check_search_whole_site | |
8 | 13 | before_filter :load_search_assets |
9 | - before_filter :check_valid_assets, :only => [ :assets ] | |
14 | + before_filter :load_query | |
10 | 15 | |
11 | 16 | no_design_blocks |
12 | 17 | |
13 | - protected | |
18 | + def facets_browse | |
19 | + @asset = params[:asset] | |
20 | + @asset_class = asset_class(@asset) | |
14 | 21 | |
15 | - def load_search_assets | |
16 | - @search_in = where_to_search | |
17 | - @searching = {} | |
18 | - @search_in.each do |key, name| | |
19 | - @searching[key] = (params[:asset].blank? && (params[:find_in].nil? || params[:find_in].empty? || params[:find_in].include?(key.to_s))) || (params[:asset] == key.to_s) | |
22 | + @facets_only = true | |
23 | + send(@asset) | |
24 | + | |
25 | + @facet = @asset_class.map_facets_for(environment).find { |facet| facet[:id] == params[:facet_id] } | |
26 | + raise 'Facet not found' if @facet.nil? | |
27 | + | |
28 | + render :layout => false | |
29 | + end | |
30 | + | |
31 | + def articles | |
32 | + @filter = params[:filter] ? filter : nil | |
33 | + @filter_title = params[:filter] ? filter_description(@asset, @filter) : nil | |
34 | + if !@empty_query | |
35 | + full_text_search ['public:true'] | |
36 | + elsif params[:filter] | |
37 | + @results[@asset] = @environment.articles.public.send(@filter).paginate(paginate_options) | |
20 | 38 | end |
21 | 39 | end |
22 | 40 | |
23 | - def prepare_filter | |
24 | - if @category | |
25 | - @noosfero_finder = CategoryFinder.new(@category) | |
41 | + def contents | |
42 | + redirect_to params.merge(:action => :articles) | |
43 | + end | |
44 | + | |
45 | + def people | |
46 | + if !@empty_query | |
47 | + full_text_search ['public:true'] | |
26 | 48 | else |
27 | - @noosfero_finder = EnvironmentFinder.new(@environment) | |
49 | + @results[@asset] = @environment.people.visible.send(@filter).paginate(paginate_options) | |
50 | + @facets = {} | |
51 | + end | |
52 | + end | |
53 | + | |
54 | + def products | |
55 | + if !@empty_query | |
56 | + full_text_search ['public:true'] | |
28 | 57 | end |
29 | 58 | end |
30 | 59 | |
31 | - def check_search_whole_site | |
32 | - if params[:search_whole_site_yes] or params[:search_whole_site] == 'yes' | |
33 | - redirect_to params.merge(:category_path => [], :search_whole_site => nil, :search_whole_site_yes => nil) | |
60 | + def enterprises | |
61 | + if !@empty_query | |
62 | + full_text_search ['public:true'] | |
63 | + else | |
64 | + @filter_title = _('Enterprises from network') | |
65 | + @results[@asset] = @environment.enterprises.visible.paginate(paginate_options) | |
34 | 66 | end |
35 | 67 | end |
36 | 68 | |
37 | - def check_valid_assets | |
38 | - @asset = params[:asset].to_sym | |
39 | - if !where_to_search.map(&:first).include?(@asset) | |
40 | - render :text => 'go away', :status => 403 | |
41 | - return | |
69 | + def communities | |
70 | + if !@empty_query | |
71 | + full_text_search ['public:true'] | |
72 | + else | |
73 | + @results[@asset] = @environment.communities.visible.send(@filter).paginate(paginate_options) | |
42 | 74 | end |
43 | 75 | end |
44 | 76 | |
45 | 77 | def events |
46 | 78 | @category_id = @category ? @category.id : nil |
47 | 79 | |
80 | + if params[:year] || params[:month] | |
81 | + date = Date.new(year.to_i, month.to_i, 1) | |
82 | + date_range = (date - 1.month)..(date + 1.month).at_end_of_month | |
83 | + end | |
84 | + | |
85 | + if @query.blank? | |
86 | + # Ignore pagination for asset events | |
87 | + if date_range | |
88 | + @results[@asset] = Event.send('find', :all, | |
89 | + :conditions => [ | |
90 | + 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day', | |
91 | + {:start_day => date_range.first, :end_day => date_range.last} | |
92 | + ]) | |
93 | + else | |
94 | + @results[@asset] = Event.send('find', :all) | |
95 | + end | |
96 | + else | |
97 | + full_text_search | |
98 | + end | |
99 | + | |
48 | 100 | @selected_day = nil |
49 | 101 | @events_of_the_day = [] |
50 | 102 | date = build_date(params[:year], params[:month], params[:day]) |
... | ... | @@ -58,118 +110,27 @@ class SearchController < PublicController |
58 | 110 | end |
59 | 111 | end |
60 | 112 | |
61 | - events = @results[:events] | |
62 | - | |
113 | + events = @results[@asset] | |
63 | 114 | @calendar = populate_calendar(date, events) |
64 | 115 | @previous_calendar = populate_calendar(date - 1.month, events) |
65 | 116 | @next_calendar = populate_calendar(date + 1.month, events) |
66 | 117 | end |
67 | 118 | |
68 | - def people | |
69 | - #nothing, just to enable | |
70 | - end | |
71 | - def enterprises | |
72 | - load_product_categories_menu(:enterprises) | |
73 | - @categories_menu = true | |
74 | - end | |
75 | - def communities | |
76 | - #nothing, just to enable | |
77 | - end | |
78 | - def articles | |
79 | - #nothins, just to enable | |
80 | - end | |
81 | - | |
82 | - def products | |
83 | - load_product_categories_menu(:products) | |
84 | - @categories_menu = true | |
85 | - end | |
86 | - | |
87 | - def load_product_categories_menu(asset) | |
88 | - @results[asset].uniq! | |
89 | - # REFACTOR DUPLICATED CODE inner loop doing the same thing that outter loop | |
90 | - | |
91 | - if !@query.blank? || @region && !params[:radius].blank? | |
92 | - ret = @noosfero_finder.find(asset, @query, calculate_find_options(asset, nil, params[:page], @product_category, @region, params[:radius], params[:year], params[:month]).merge({:limit => :all})) | |
93 | - @result_ids = ret.is_a?(Hash) ? ret[:results] : ret | |
94 | - end | |
95 | - | |
96 | - end | |
97 | - | |
98 | - def calculate_find_options(asset, limit, page, product_category, region, radius, year, month) | |
99 | - result = { :product_category => product_category, :per_page => limit, :page => page } | |
100 | - if [:enterprises, :people, :products].include?(asset) && region | |
101 | - result.merge!(:within => radius, :region => region.id) | |
102 | - end | |
103 | - | |
104 | - if month || year | |
105 | - date = Date.new(year.to_i, month.to_i, 1) | |
106 | - result[:date_range] = (date - 1.month)..(date + 1.month).at_end_of_month | |
107 | - end | |
108 | - | |
109 | - result | |
110 | - end | |
111 | - | |
112 | - # limit the number of results per page | |
113 | - # TODO: dont hardcore like this | |
114 | - def limit | |
115 | - searching = @searching.values.select{|v|v} | |
116 | - if params[:display] == 'map' | |
117 | - 2000 | |
118 | - else | |
119 | - (searching.size == 1) ? 20 : 6 | |
120 | - end | |
121 | - end | |
122 | - | |
123 | - public | |
124 | - | |
125 | - include SearchHelper | |
126 | - | |
127 | - ###################################################### | |
128 | - | |
129 | - def where_to_search | |
130 | - [ | |
131 | - [ :articles, N_('Articles') ], | |
132 | - [ :enterprises, N_('Enterprises') ], | |
133 | - [ :people, N_('People') ], | |
134 | - [ :communities, N_('Communities') ], | |
135 | - [ :products, N_('Products') ], | |
136 | - [ :events, N_('Events') ] | |
137 | - ].select {|key, name| !environment.enabled?('disable_asset_' + key.to_s) } | |
138 | - end | |
139 | - | |
140 | - def cities | |
141 | - @cities = City.find(:all, :order => 'name', :conditions => ['parent_id = ? and lat is not null and lng is not null', params[:state_id]]) | |
142 | - render :action => 'cities', :layout => false | |
143 | - end | |
144 | - | |
145 | - def complete_region | |
146 | - # FIXME this logic should be in the model | |
147 | - @regions = Region.find(:all, :conditions => [ '(name like ? or name like ?) and lat is not null and lng is not null', '%' + params[:region][:name] + '%', '%' + params[:region][:name].capitalize + '%' ]) | |
148 | - render :action => 'complete_region', :layout => false | |
149 | - end | |
150 | - | |
151 | 119 | def index |
152 | - @query = params[:query] || '' | |
153 | - @product_category = ProductCategory.find(params[:product_category]) if params[:product_category] | |
154 | - | |
155 | - @region = City.find_by_id(params[:city]) if !params[:city].blank? && params[:city] =~ /^\d+$/ | |
156 | - | |
157 | - # how many assets we are searching for? | |
158 | - number_of_result_assets = @searching.values.select{|v| v}.size | |
159 | - | |
160 | 120 | @results = {} |
161 | - @facets = {} | |
162 | 121 | @order = [] |
163 | 122 | @names = {} |
123 | + @results_only = true | |
164 | 124 | |
165 | - where_to_search.select { |key,description| @searching[key] }.each do |key, description| | |
125 | + @enabled_searchs.select { |key,description| @searching[key] }.each do |key, description| | |
126 | + load_query | |
127 | + @asset = key | |
128 | + send(key) | |
166 | 129 | @order << key |
167 | - find_options = calculate_find_options(key, limit, params[:page], @product_category, @region, params[:radius], params[:year], params[:month]); | |
168 | - ret = @noosfero_finder.find(key, @query, find_options) | |
169 | - @results[key] = ret.is_a?(Hash) ? ret[:results] : ret | |
170 | - @facets[key] = ret.is_a?(Hash) ? ret[:facets] : {} | |
171 | 130 | @names[key] = getterm(description) |
172 | 131 | end |
132 | + @asset = nil | |
133 | + @facets = {} | |
173 | 134 | |
174 | 135 | if @results.keys.size == 1 |
175 | 136 | specific_action = @results.keys.first |
... | ... | @@ -180,34 +141,32 @@ class SearchController < PublicController |
180 | 141 | return |
181 | 142 | end |
182 | 143 | end |
183 | - | |
184 | - render :action => 'index' | |
185 | 144 | end |
186 | 145 | |
187 | - alias :assets :index | |
188 | - | |
189 | - ####################################################### | |
146 | + def assets | |
147 | + params[:action] = params[:asset].is_a?(Array) ? :index : params.delete(:asset) | |
148 | + redirect_to params | |
149 | + end | |
190 | 150 | |
191 | 151 | # view the summary of one category |
192 | 152 | def category_index |
193 | 153 | @results = {} |
194 | 154 | @order = [] |
195 | 155 | @names = {} |
156 | + limit = MULTIPLE_SEARCH_LIMIT | |
196 | 157 | [ |
197 | - [ :people, _('People'), @noosfero_finder.recent('people', limit) ], | |
198 | - [ :enterprises, __('Enterprises'), @noosfero_finder.recent('enterprises', limit) ], | |
199 | - [ :products, _('Products'), @noosfero_finder.recent('products', limit) ], | |
200 | - [ :events, _('Upcoming events'), @noosfero_finder.upcoming_events({:per_page => limit}) ], | |
201 | - [ :communities, __('Communities'), @noosfero_finder.recent('communities', limit) ], | |
202 | - [ :most_commented_articles, _('Most commented articles'), @noosfero_finder.most_commented_articles(limit) ], | |
203 | - [ :articles, _('Articles'), @noosfero_finder.recent('text_articles', limit) ] | |
204 | - ].each do |key, name, list| | |
205 | - @order << key | |
206 | - @results[key] = list | |
207 | - @names[key] = name | |
158 | + [ :people, _('People'), :recent_people ], | |
159 | + [ :enterprises, _('Enterprises'), :recent_enterprises ], | |
160 | + [ :products, _('Products'), :recent_products ], | |
161 | + [ :events, _('Upcoming events'), :upcoming_events ], | |
162 | + [ :communities, _('Communities'), :recent_communities ], | |
163 | + [ :articles, _('Contents'), :recent_articles ] | |
164 | + ].each do |asset, name, filter| | |
165 | + @order << asset | |
166 | + @results[asset] = @category.send(filter, limit) | |
167 | + @names[asset] = name | |
208 | 168 | end |
209 | 169 | end |
210 | - attr_reader :category | |
211 | 170 | |
212 | 171 | def tags |
213 | 172 | @tags_cache_key = "tags_env_#{environment.id.to_s}" |
... | ... | @@ -224,21 +183,123 @@ class SearchController < PublicController |
224 | 183 | end |
225 | 184 | end |
226 | 185 | |
186 | + def events_by_day | |
187 | + @selected_day = build_date(params[:year], params[:month], params[:day]) | |
188 | + @events_of_the_day = environment.events.by_day(@selected_day) | |
189 | + render :partial => 'events/events_by_day' | |
190 | + end | |
191 | + | |
227 | 192 | ####################################################### |
193 | + protected | |
194 | + | |
195 | + def load_query | |
196 | + @asset = params[:action].to_sym | |
197 | + @order ||= [@asset] | |
198 | + @results ||= {} | |
199 | + @filter = filter | |
200 | + @filter_title = filter_description(@asset, @filter) | |
201 | + | |
202 | + @query = params[:query] || '' | |
203 | + @empty_query = @category.nil? && @query.blank? | |
204 | + end | |
228 | 205 | |
229 | - def popup | |
230 | - @regions = Region.find(:all).select{|r|r.lat && r.lng} | |
231 | - render :action => 'popup', :layout => false | |
206 | + def load_category | |
207 | + unless params[:category_path].blank? | |
208 | + path = params[:category_path].join('/') | |
209 | + @category = environment.categories.find_by_path(path) | |
210 | + if @category.nil? | |
211 | + render_not_found(path) | |
212 | + else | |
213 | + @category_id = @category.id | |
214 | + end | |
215 | + end | |
232 | 216 | end |
233 | 217 | |
234 | - def events_by_day | |
235 | - @selected_day = build_date(params[:year], params[:month], params[:day]) | |
236 | - if params[:category_id] and Category.exists?(params[:category_id]) | |
237 | - @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(params[:category_id])) | |
218 | + FILTERS = %w( | |
219 | + more_recent | |
220 | + more_active | |
221 | + more_popular | |
222 | + ) | |
223 | + def filter | |
224 | + if FILTERS.include?(params[:filter]) | |
225 | + params[:filter] | |
238 | 226 | else |
239 | - @events_of_the_day = environment.events.by_day(@selected_day) | |
227 | + 'more_recent' | |
240 | 228 | end |
241 | - render :partial => 'events/events_by_day' | |
229 | + end | |
230 | + | |
231 | + def filter_description(asset, filter) | |
232 | + { | |
233 | + 'articles_more_recent' => _('More recent contents from network'), | |
234 | + 'articles_more_popular' => _('More read contents from network'), | |
235 | + 'people_more_recent' => _('More recent people from network'), | |
236 | + 'people_more_active' => _('More active people from network'), | |
237 | + 'people_more_popular' => _('More popular people from network'), | |
238 | + 'communities_more_recent' => _('More recent communities from network'), | |
239 | + 'communities_more_active' => _('More active communities from network'), | |
240 | + 'communities_more_popular' => _('More popular communities from network'), | |
241 | + }[asset.to_s + '_' + filter] | |
242 | + end | |
243 | + | |
244 | + def load_search_assets | |
245 | + @enabled_searchs = [ | |
246 | + [ :articles, _('Contents') ], | |
247 | + [ :enterprises, _('Enterprises') ], | |
248 | + [ :people, _('People') ], | |
249 | + [ :communities, _('Communities') ], | |
250 | + [ :products, _('Products and Services') ], | |
251 | + [ :events, _('Events') ] | |
252 | + ].select {|key, name| !environment.enabled?('disable_asset_' + key.to_s) } | |
253 | + | |
254 | + @searching = {} | |
255 | + @titles = {} | |
256 | + @enabled_searchs.each do |key, name| | |
257 | + @titles[key] = name | |
258 | + @searching[key] = params[:action] == 'index' || params[:action] == key.to_s | |
259 | + end | |
260 | + end | |
261 | + | |
262 | + def limit | |
263 | + searching = @searching.values.select{ |v| v } | |
264 | + if params[:display] == 'map' | |
265 | + MAP_SEARCH_LIMIT | |
266 | + elsif searching.size <= 1 | |
267 | + if [:people, :communities].include? @asset | |
268 | + BLOCKS_SEARCH_LIMIT | |
269 | + elsif @asset == :enterprises and @empty_query | |
270 | + BLOCKS_SEARCH_LIMIT | |
271 | + else | |
272 | + LIST_SEARCH_LIMIT | |
273 | + end | |
274 | + else | |
275 | + MULTIPLE_SEARCH_LIMIT | |
276 | + end | |
277 | + end | |
278 | + | |
279 | + def paginate_options(page = params[:page]) | |
280 | + { :per_page => limit, :page => page } | |
281 | + end | |
282 | + | |
283 | + def full_text_search(filters = []) | |
284 | + paginate_options = paginate_options(params[:page]) | |
285 | + asset_class = asset_class(@asset) | |
286 | + | |
287 | + solr_options = {} | |
288 | + if !@results_only and asset_class.methods.include?('facets') | |
289 | + solr_options.merge! asset_class.facets_find_options(params[:facet]) | |
290 | + solr_options[:all_facets] = true | |
291 | + solr_options[:limit] = 0 if @facets_only | |
292 | + solr_options[:facets][:browse] << asset_class.facet_category_query.call(@category) if @category and asset_class.facet_category_query | |
293 | + end | |
294 | + solr_options[:order] = params[:order_by] if params[:order_by] | |
295 | + solr_options[:filter_queries] ||= [] | |
296 | + solr_options[:filter_queries] += filters | |
297 | + solr_options[:filter_queries] << "environment_id:#{environment.id}" | |
298 | + | |
299 | + ret = asset_class.find_by_contents(@query, paginate_options, solr_options) | |
300 | + @results[@asset] = ret[:results] | |
301 | + @facets = ret[:facets] | |
302 | + @all_facets = ret[:all_facets] | |
242 | 303 | end |
243 | 304 | |
244 | 305 | end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -574,7 +574,7 @@ module ApplicationHelper |
574 | 574 | end |
575 | 575 | extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) |
576 | 576 | links = links_for_balloon(profile) |
577 | - content_tag tag, | |
577 | + content_tag('div', content_tag(tag, | |
578 | 578 | (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") + |
579 | 579 | link_to( |
580 | 580 | content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + |
... | ... | @@ -584,7 +584,7 @@ module ApplicationHelper |
584 | 584 | :class => 'profile_link url', |
585 | 585 | :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name, |
586 | 586 | :title => profile.name ), |
587 | - :class => 'vcard' | |
587 | + :class => 'vcard'), :class => 'common-profile-list-block') | |
588 | 588 | end |
589 | 589 | |
590 | 590 | def gravatar_url_for(email, options = {}) |
... | ... | @@ -890,22 +890,6 @@ module ApplicationHelper |
890 | 890 | result |
891 | 891 | end |
892 | 892 | |
893 | - def search_page_title(title, options={}) | |
894 | - title = "<h1>" + title + "</h1>" | |
895 | - title += "<h2 class='query'>" + _("Searched for '%s'") % options[:query] + "</h2>" if !options[:query].blank? | |
896 | - title += "<h2 class='query'>" + _("In category %s") % options[:category] + "</h2>" if !options[:category].blank? | |
897 | - title += "<h2 class='query'>" + _("within %d km from %s") % [options[:distance], options[:region]] + "</h2>" if !options[:distance].blank? && !options[:region].blank? | |
898 | - title += "<h2 class='query'>" + _("%d results found") % options[:total_results] + "</h2>" if !options[:total_results].blank? | |
899 | - title | |
900 | - end | |
901 | - | |
902 | - def search_page_link_to_all(options={}) | |
903 | - if options[:category] | |
904 | - title = "<div align='center'>" + _('In all categories') + "</div>" | |
905 | - link_to title, :action => 'assets', :asset => options[:asset], :category_path => [] | |
906 | - end | |
907 | - end | |
908 | - | |
909 | 893 | def template_stylesheet_path |
910 | 894 | if profile.nil? |
911 | 895 | "/designs/templates/#{environment.layout_template}/stylesheets/style.css" |
... | ... | @@ -982,6 +966,7 @@ module ApplicationHelper |
982 | 966 | def noosfero_stylesheets |
983 | 967 | [ |
984 | 968 | 'application', |
969 | + 'search', | |
985 | 970 | 'thickbox', |
986 | 971 | 'lightbox', |
987 | 972 | 'colorpicker', |
... | ... | @@ -1100,33 +1085,46 @@ module ApplicationHelper |
1100 | 1085 | ") : '') |
1101 | 1086 | end |
1102 | 1087 | |
1103 | - def browse_people_menu | |
1088 | + def search_contents_menu | |
1089 | + links = [ | |
1090 | + {s_('contents|More Recent') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_recent'})}}, | |
1091 | + {s_('contents|More Read') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_popular'})}} | |
1092 | + ] | |
1093 | + if logged_in? | |
1094 | + links.push(_('New Content') => lightbox_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) | |
1095 | + end | |
1096 | + | |
1097 | + link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-contents'), {:controller => "search", :action => 'contents', :category_path => ''}, :id => 'submenu-contents') + | |
1098 | + link_to(content_tag(:span, _('Contents Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-contents-trigger') | |
1099 | + end | |
1100 | + | |
1101 | + def search_people_menu | |
1104 | 1102 | links = [ |
1105 | - {s_('people|More Recent') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_recent'})}}, | |
1106 | - {s_('people|More Active') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_active'})}}, | |
1107 | - {s_('people|More Popular') => {:href => url_for({:controller => 'browse', :action => 'people', :filter => 'more_popular'})}} | |
1103 | + {s_('people|More Recent') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_recent'})}}, | |
1104 | + {s_('people|More Active') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_active'})}}, | |
1105 | + {s_('people|More Popular') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_popular'})}} | |
1108 | 1106 | ] |
1109 | 1107 | if logged_in? |
1110 | 1108 | links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) |
1111 | 1109 | links.push(_('Invite friends') => {:href => url_for({:profile => current_user.login, :controller => 'invite', :action => 'friends'})}) |
1112 | 1110 | end |
1113 | 1111 | |
1114 | - link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "browse", :action => 'people'}, :id => 'submenu-people') + | |
1112 | + link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "search", :action => 'people', :category_path => ''}, :id => 'submenu-people') + | |
1115 | 1113 | link_to(content_tag(:span, _('People Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger') |
1116 | 1114 | end |
1117 | 1115 | |
1118 | - def browse_communities_menu | |
1116 | + def search_communities_menu | |
1119 | 1117 | links = [ |
1120 | - {s_('communities|More Recent') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_recent'})}}, | |
1121 | - {s_('communities|More Active') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_active'})}}, | |
1122 | - {s_('communities|More Popular') => {:href => url_for({:controller => 'browse', :action => 'communities', :filter => 'more_popular'})}} | |
1118 | + {s_('communities|More Recent') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_recent'})}}, | |
1119 | + {s_('communities|More Active') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_active'})}}, | |
1120 | + {s_('communities|More Popular') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_popular'})}} | |
1123 | 1121 | ] |
1124 | 1122 | if logged_in? |
1125 | 1123 | links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})}) |
1126 | 1124 | links.push(_('New community') => {:href => url_for({:profile => current_user.login, :controller => 'memberships', :action => 'new_community'})}) |
1127 | 1125 | end |
1128 | 1126 | |
1129 | - link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "browse", :action => 'communities'}, :id => 'submenu-communities') + | |
1127 | + link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "search", :action => 'communities'}, :id => 'submenu-communities') + | |
1130 | 1128 | link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') |
1131 | 1129 | end |
1132 | 1130 | |
... | ... | @@ -1330,4 +1328,8 @@ module ApplicationHelper |
1330 | 1328 | end |
1331 | 1329 | end |
1332 | 1330 | |
1331 | + def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) | |
1332 | + "hintText: '#{hintText}', noResultsText: '#{noResultsText}', searchingText: '#{searchingText}'" | |
1333 | + end | |
1334 | + | |
1333 | 1335 | end | ... | ... |
app/helpers/display_helper.rb
... | ... | @@ -26,15 +26,19 @@ module DisplayHelper |
26 | 26 | product.enterprise.enabled? ? product.enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => product) : product.enterprise.url |
27 | 27 | end |
28 | 28 | |
29 | - def link_to_category(category, full = true) | |
29 | + def link_to_tag(tag, html_options = {}) | |
30 | + link_to tag.name, {:controller => 'search', :action => 'tag', :tag => tag.name}, html_options | |
31 | + end | |
32 | + | |
33 | + def link_to_category(category, full = true, html_options = {}) | |
30 | 34 | return _('Uncategorized product') unless category |
31 | 35 | name = full ? category.full_name(' → ') : category.name |
32 | - link_to name, Noosfero.url_options.merge({:controller => 'search', :action => 'category_index', :category_path => category.path.split('/'),:host => category.environment.default_hostname }) | |
36 | + link_to name, Noosfero.url_options.merge({:controller => 'search', :action => 'category_index', :category_path => category.path.split('/'),:host => category.environment.default_hostname }), html_options | |
33 | 37 | end |
34 | 38 | |
35 | 39 | def link_to_product_category(category) |
36 | 40 | if category |
37 | - link_to(category.name, :controller => 'search', :action => 'assets', :asset => 'products', :product_category => category.id, :host => category.environment.default_hostname) | |
41 | + link_to(category.name, :controller => 'search', :action => 'products', :category_path => category.explode_path) | |
38 | 42 | else |
39 | 43 | _('Uncategorized product') |
40 | 44 | end | ... | ... |
app/helpers/lightbox_helper.rb
... | ... | @@ -22,10 +22,7 @@ module LightboxHelper |
22 | 22 | def lightbox_options(options, lightbox_type = 'lbOn') |
23 | 23 | the_class = lightbox_type |
24 | 24 | the_class << " #{options[:class]}" if options.has_key?(:class) |
25 | - options.merge( | |
26 | - :class => the_class, | |
27 | - :onclick => 'alert("%s"); return false' % _('Please, try again when the page loading completes.') | |
28 | - ) | |
25 | + options.merge(:class => the_class) | |
29 | 26 | end |
30 | 27 | |
31 | 28 | def lightbox? | ... | ... |
app/helpers/product_category_viewer_helper.rb
app/helpers/search_helper.rb
... | ... | @@ -3,116 +3,160 @@ module SearchHelper |
3 | 3 | # FIXME remove it after search_controler refactored |
4 | 4 | include EventsHelper |
5 | 5 | |
6 | - def relevance_for(hit) | |
7 | - n = (hit.ferret_score if hit.respond_to?(:ferret_score)) | |
8 | - n ||= 1.0 | |
9 | - (n * 100.0).round | |
6 | + def search_page_title(title, category = nil) | |
7 | + title = "<h1>" + title | |
8 | + title += '<small>' + category.name + '</small>' if category | |
9 | + title + "</h1>" | |
10 | 10 | end |
11 | 11 | |
12 | - def display_results(use_map = true) | |
12 | + def category_context(category, url) | |
13 | + content_tag('div', category.full_name + _(', ') + | |
14 | + link_to(_('search in all categories'), | |
15 | + url.merge(:category_path => [], :action => (params[:action] == 'category_index' ? 'index' : params[:action]) )), | |
16 | + :align => 'center', :class => 'search-category-context') if category | |
17 | + end | |
13 | 18 | |
14 | - unless use_map && GoogleMaps.enabled?(environment.default_hostname) | |
15 | - return render(:partial => 'display_results') | |
19 | + def display_results(use_map = false) | |
20 | + if params[:display] == 'map' && use_map && GoogleMaps.enabled?(environment.default_hostname) | |
21 | + partial = 'google_maps' | |
22 | + klass = 'map' | |
23 | + else | |
24 | + partial = 'display_results' | |
25 | + klass = 'list' | |
16 | 26 | end |
17 | 27 | |
18 | - data = | |
19 | - if params[:display] == 'map' | |
20 | - { | |
21 | - :partial => 'google_maps', | |
22 | - :toggle => button(:search, _('Display in list'), params.merge(:display => 'list'), :class => "map-toggle-button" ), | |
23 | - :class => 'map' , | |
24 | - } | |
25 | - else | |
26 | - { | |
27 | - :partial => 'display_results', | |
28 | - :toggle => button(:search, _('Display in map'), params.merge(:display => 'map'), :class => "map-toggle-button" ), | |
29 | - :class => 'list' , | |
30 | - } | |
31 | - end | |
28 | + content_tag('div', render(:partial => partial), :class => "map-or-list-search-results #{klass}") | |
29 | + end | |
32 | 30 | |
33 | - content_tag('div', data[:toggle] + (render :partial => data[:partial]), :class => "map-or-list-search-results #{data[:class]}") | |
31 | + def display_map_list_button | |
32 | + button(:search, params[:display] == 'map' ? _('Display in list') : _('Display in map'), | |
33 | + params.merge(:display => (params[:display] == 'map' ? 'list' : 'map')), | |
34 | + :class => "map-toggle-button" ) if GoogleMaps.enabled?(environment.default_hostname) | |
34 | 35 | end |
35 | 36 | |
36 | - def display_item_map_info(item) | |
37 | - if item.kind_of?(Profile) | |
38 | - display_profile_info(item) | |
39 | - elsif item.kind_of?(Product) | |
40 | - display_product_info(item) | |
37 | + def city_with_state(city) | |
38 | + s = city.parent | |
39 | + if city and city.kind_of?(City) and s and s.kind_of?(State) and s.acronym | |
40 | + city.name + ', ' + s.acronym | |
41 | + else | |
42 | + city.name | |
41 | 43 | end |
42 | 44 | end |
45 | + | |
46 | + def facets_menu(asset, _facets) | |
47 | + @asset_class = asset_class(asset) | |
48 | + @facets = _facets | |
49 | + render(:partial => 'facets_menu') | |
50 | + end | |
51 | + | |
52 | + def facets_unselect_menu(asset) | |
53 | + @asset_class = asset_class(asset) | |
54 | + render(:partial => 'facets_unselect_menu') | |
55 | + end | |
43 | 56 | |
44 | - def display_profile_info(profile) | |
45 | - data = '' | |
46 | - unless profile.contact_email.nil? | |
47 | - data << content_tag('strong', _('E-Mail: ')) + profile.contact_email + '<br/>' | |
48 | - end | |
49 | - unless profile.contact_phone.nil? | |
50 | - data << content_tag('strong', _('Phone(s): ')) + profile.contact_phone + '<br/>' | |
51 | - end | |
52 | - unless profile.region.nil? | |
53 | - data << content_tag('strong', _('Location: ')) + profile.region.name + '<br/>' | |
54 | - end | |
55 | - unless profile.address.nil? | |
56 | - data << content_tag('strong', _('Address: ')) + profile.address + '<br/>' | |
57 | - end | |
58 | - unless profile.products.empty? | |
59 | - data << content_tag('strong', _('Products/Services: ')) + profile.products.map{|i| link_to(i.name, :controller => 'manage_products', :profile => profile.identifier, :action => 'show', :id => i.id)}.join(', ') + '<br/>' | |
60 | - end | |
61 | - if profile.respond_to?(:distance) and !profile.distance.nil? | |
62 | - data << content_tag('strong', _('Distance: ')) + "%.2f%" % profile.distance + '<br/>' | |
63 | - end | |
64 | - content_tag('table', | |
65 | - content_tag('tr', | |
66 | - content_tag('td', content_tag('div', profile_image(profile, :thumb), :class => 'profile-info-picture')) + | |
67 | - content_tag('td', content_tag('strong', link_to(profile.name, url_for(profile.url))) + '<br/>' + data | |
68 | - ) | |
69 | - ), | |
70 | - :class => 'profile-info' | |
71 | - ) | |
57 | + def facet_javascript(input_id, facet, array) | |
58 | + hintText = _('Type in an option') | |
59 | + text_field_tag('facet['+input_id+']', '', :id => input_id) + | |
60 | + javascript_tag("jQuery.TokenList(jQuery('##{input_id}'), #{array.to_json}, | |
61 | + {searchDelay: 0, permanentDropdown: true, theme: 'facet', dontAdd: true, preventDuplicates: true, | |
62 | + #{jquery_token_input_messages_json(hintText)}});") | |
72 | 63 | end |
73 | 64 | |
74 | - def display_product_info(product) | |
75 | - data = '' | |
76 | - unless product.price.nil? | |
77 | - data << content_tag('strong', _('Price: ')) + product.price + '<br/>' | |
78 | - end | |
79 | - unless product.enterprise.nil? | |
80 | - data << content_tag('strong', _('Provider: ')) + link_to_profile(product.enterprise.name, product.enterprise.identifier) | |
81 | - end | |
82 | - unless product.product_category.nil? | |
83 | - data << content_tag('strong', _('Category: ')) + link_to(product.product_category.name, :controller => 'search', :action => 'assets', :asset => 'products', :product_category => product.product_category.id) | |
65 | + def facet_link_html(facet, params, value, label, count) | |
66 | + params = params.dup | |
67 | + has_extra = label.kind_of?(Array) | |
68 | + link_label = has_extra ? label[0] : label | |
69 | + id = facet[:solr_field].to_s | |
70 | + params[:facet] ||= {} | |
71 | + params[:facet][id] ||= {} | |
72 | + | |
73 | + selected = facet[:label_id].nil? ? params[:facet][id] == value : params[:facet][id][facet[:label_id]].to_a.include?(value) | |
74 | + | |
75 | + if count > 0 | |
76 | + url = params.merge(:facet => params[:facet].merge( | |
77 | + id => facet[:label_id].nil? ? value : params[:facet][id].merge( facet[:label_id] => params[:facet][id][facet[:label_id]].to_a.push(value) ) | |
78 | + )) | |
79 | + else | |
80 | + url = params.merge(:facet => { | |
81 | + id => facet[:label_id].nil? ? value : { facet[:label_id] => value } | |
82 | + }) | |
84 | 83 | end |
85 | - content_tag('table', | |
86 | - content_tag('tr', | |
87 | - content_tag('td', content_tag('div', image_tag(product.image ? product.image.public_filename(:thumb) : '/images/icons-app/product-default-pic-portrait.png'), :class => 'profile-info-picture')) + | |
88 | - content_tag('td', content_tag('strong', link_to(product.name, :controller => 'catalog', :profile => product.enterprise.identifier, :action => 'show', :id => product)) + '<br/>' + data) | |
89 | - ), :class => 'profile-info') | |
84 | + | |
85 | + content_tag 'div', link_to(link_label, url, :class => 'facet-result-link-label') + | |
86 | + content_tag('span', (has_extra ? label[1] : ''), :class => 'facet-result-extra-label') + | |
87 | + (count > 0 ? content_tag('span', " (#{count})", :class => 'facet-result-count') : ''), | |
88 | + :class => 'facet-menu-item' + (selected ? ' facet-result-link-selected' : '') | |
90 | 89 | end |
91 | 90 | |
92 | - def product_categories_menu(asset, product_category, object_ids = nil) | |
93 | - cats = ProductCategory.menu_categories(@product_category, environment) | |
94 | - cats += cats.select { |c| c.children_count > 0 }.map(&:children).flatten | |
95 | - product_categories_ids = cats.map(&:id) | |
96 | - | |
97 | - counts = @noosfero_finder.product_categories_count(asset, product_categories_ids, object_ids) | |
98 | - | |
99 | - product_categories_menu = ProductCategory.menu_categories(product_category, environment).map do |cat| | |
100 | - hits = counts[cat.id] | |
101 | - childs = [] | |
102 | - if hits | |
103 | - if cat.children_count > 0 | |
104 | - childs = cat.children.map do |child| | |
105 | - child_hits = counts[child.id] | |
106 | - [child, child_hits] | |
107 | - end.select{|child, child_hits| child_hits } | |
108 | - else | |
109 | - childs = [] | |
91 | + def facet_selecteds_html_for(environment, klass, params) | |
92 | + def name_with_extra(klass, facet, value) | |
93 | + name = klass.facet_result_name(facet, value) | |
94 | + name = name[0] + name[1] if name.kind_of?(Array) | |
95 | + name | |
96 | + end | |
97 | + | |
98 | + ret = [] | |
99 | + params = params.dup | |
100 | + params[:facet].each do |id, value| | |
101 | + facet = klass.facet_by_id(id.to_sym) | |
102 | + if value.kind_of?(Hash) | |
103 | + label_hash = facet[:label].call(environment) | |
104 | + value.each do |label_id, value| | |
105 | + facet[:label_id] = label_id | |
106 | + facet[:label] = label_hash[label_id] | |
107 | + value.to_a.each do |value| | |
108 | + ret << [facet[:label], name_with_extra(klass, facet, value), | |
109 | + params.merge(:facet => params[:facet].merge(id => params[:facet][id].merge(label_id => params[:facet][id][label_id].to_a.reject{ |v| v == value })))] | |
110 | + end | |
110 | 111 | end |
112 | + else | |
113 | + ret << [klass.facet_label(facet), name_with_extra(klass, facet, value), | |
114 | + params.merge(:facet => params[:facet].reject{ |k,v| k == id })] | |
111 | 115 | end |
112 | - [cat, hits, childs] | |
113 | - end.select{|cat, hits| hits } | |
116 | + end | |
117 | + | |
118 | + ret.map do |label, name, url| | |
119 | + content_tag('div', content_tag('span', label, :class => 'facet-selected-label') + | |
120 | + content_tag('span', name, :class => 'facet-selected-name') + | |
121 | + link_to('', url, :class => 'facet-selected-remove'), :class => 'facet-selected') | |
122 | + end.join | |
123 | + end | |
124 | + | |
125 | + def order_by(asset) | |
126 | + options = { | |
127 | + :products => [[_('Relevance'), ''], [_('Name'), 'name_or_category_sort asc'], [_('Lower price'), 'price_sort asc'], [_('Higher price'), 'price_sort desc']], | |
128 | + :events => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']], | |
129 | + :articles => [[_('Relevance'), ''], [_('Name'), 'name_sort asc'], [_('Most recent'), 'updated_at desc']], | |
130 | + :enterprises => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']], | |
131 | + :people => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']], | |
132 | + :communities => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']], | |
133 | + } | |
134 | + | |
135 | + content_tag('div', _('Sort results by ') + | |
136 | + select_tag(asset.to_s + '[order]', options_for_select(options[asset], params[:order_by]), | |
137 | + {:onchange => "window.location=jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}), | |
138 | + :class => "search-ordering") | |
139 | + end | |
114 | 140 | |
115 | - render(:partial => 'product_categories_menu', :object => product_categories_menu) | |
141 | + def label_total_found(asset, total_found) | |
142 | + labels = { | |
143 | + :products => _("%s products offers found"), | |
144 | + :articles => _("%s articles found"), | |
145 | + :events => _("%s events found"), | |
146 | + :people => _("%s people found"), | |
147 | + :enterprises => _("%s enterprises found"), | |
148 | + :communities => _("%s communities found"), | |
149 | + } | |
150 | + content_tag('span', labels[asset] % total_found, | |
151 | + :class => "total-pages-found") if labels[asset] | |
152 | + end | |
153 | + | |
154 | + def asset_class(asset) | |
155 | + asset.to_s.singularize.camelize.constantize | |
156 | + end | |
157 | + | |
158 | + def asset_table(asset) | |
159 | + asset_class(asset).table_name | |
116 | 160 | end |
117 | 161 | |
118 | 162 | end | ... | ... |
app/models/article.rb
... | ... | @@ -2,6 +2,12 @@ require 'hpricot' |
2 | 2 | |
3 | 3 | class Article < ActiveRecord::Base |
4 | 4 | |
5 | + # use for internationalizable human type names in search facets | |
6 | + # reimplement on subclasses | |
7 | + def self.type_name | |
8 | + _('Content') | |
9 | + end | |
10 | + | |
5 | 11 | track_actions :create_article, :after_create, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && !a.image? }, :custom_target => :action_tracker_target |
6 | 12 | track_actions :update_article, :before_update, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? && (a.body_changed? || a.name_changed?) }, :custom_target => :action_tracker_target |
7 | 13 | track_actions :remove_article, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.is_trackable? }, :custom_target => :action_tracker_target |
... | ... | @@ -125,8 +131,6 @@ class Article < ActiveRecord::Base |
125 | 131 | |
126 | 132 | acts_as_versioned |
127 | 133 | |
128 | - acts_as_searchable :additional_fields => [ :comment_data ] | |
129 | - | |
130 | 134 | def comment_data |
131 | 135 | comments.map {|item| [item.title, item.body].join(' ') }.join(' ') |
132 | 136 | end |
... | ... | @@ -141,13 +145,31 @@ class Article < ActiveRecord::Base |
141 | 145 | {:conditions => [ 'parent_id is null and profile_id = ?', profile.id ]} |
142 | 146 | } |
143 | 147 | |
148 | + named_scope :public, | |
149 | + :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ] | |
150 | + | |
151 | + named_scope :more_recent, | |
152 | + :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ? AND | |
153 | + ((articles.type != ?) OR articles.type is NULL)", | |
154 | + true, true, true, true, 'RssFeed' | |
155 | + ], | |
156 | + :order => 'articles.published_at desc, articles.id desc' | |
157 | + | |
158 | + # retrives the most commented articles, sorted by the comment count (largest | |
159 | + # first) | |
160 | + def self.most_commented(limit) | |
161 | + paginate(:order => 'comments_count DESC', :page => 1, :per_page => limit) | |
162 | + end | |
163 | + | |
164 | + named_scope :more_popular, :order => 'hits DESC' | |
165 | + | |
144 | 166 | # retrieves the latest +limit+ articles, sorted from the most recent to the |
145 | 167 | # oldest. |
146 | 168 | # |
147 | 169 | # Only includes articles where advertise == true |
148 | - def self.recent(limit, extra_conditions = {}) | |
170 | + def self.recent(limit = nil, extra_conditions = {}) | |
149 | 171 | # FIXME this method is a horrible hack |
150 | - options = { :limit => limit, | |
172 | + options = { :page => 1, :per_page => limit, | |
151 | 173 | :conditions => [ |
152 | 174 | "advertise = ? AND |
153 | 175 | published = ? AND |
... | ... | @@ -165,20 +187,14 @@ class Article < ActiveRecord::Base |
165 | 187 | options.delete(:include) |
166 | 188 | end |
167 | 189 | if extra_conditions == {} |
168 | - self.find(:all, options) | |
190 | + self.paginate(options) | |
169 | 191 | else |
170 | 192 | with_scope :find => {:conditions => extra_conditions} do |
171 | - self.find(:all, options) | |
193 | + self.paginate(options) | |
172 | 194 | end |
173 | 195 | end |
174 | 196 | end |
175 | 197 | |
176 | - # retrives the most commented articles, sorted by the comment count (largest | |
177 | - # first) | |
178 | - def self.most_commented(limit) | |
179 | - find(:all, :order => 'comments_count DESC', :limit => limit) | |
180 | - end | |
181 | - | |
182 | 198 | # produces the HTML code that is to be displayed as this article's contents. |
183 | 199 | # |
184 | 200 | # The implementation in this class just provides the +body+ attribute as the |
... | ... | @@ -561,6 +577,81 @@ class Article < ActiveRecord::Base |
561 | 577 | |
562 | 578 | private |
563 | 579 | |
580 | + # FIXME: workaround for development env. | |
581 | + # Subclasses aren't (re)loaded, and acts_as_solr | |
582 | + # depends on subclasses method to search | |
583 | + # see http://stackoverflow.com/questions/4138957/activerecordsubclassnotfound-error-when-using-sti-in-rails/4139245 | |
584 | + UploadedFile | |
585 | + TextArticle | |
586 | + TinyMceArticle | |
587 | + TextileArticle | |
588 | + Folder | |
589 | + EnterpriseHomepage | |
590 | + Gallery | |
591 | + Blog | |
592 | + Forum | |
593 | + Event | |
594 | + | |
595 | + def self.f_type_proc(klass) | |
596 | + klass.constantize.type_name | |
597 | + end | |
598 | + def self.f_profile_type_proc(klass) | |
599 | + klass.constantize.type_name | |
600 | + end | |
601 | + | |
602 | + def f_type | |
603 | + #join common types | |
604 | + case self.class.name | |
605 | + when 'TinyMceArticle', 'TextileArticle' | |
606 | + TextArticle.name | |
607 | + else | |
608 | + self.class.name | |
609 | + end | |
610 | + end | |
611 | + def f_profile_type | |
612 | + self.profile.class.name | |
613 | + end | |
614 | + def f_published_at | |
615 | + self.published_at | |
616 | + end | |
617 | + def f_category | |
618 | + self.categories.collect(&:name) | |
619 | + end | |
620 | + def name_sort | |
621 | + name | |
622 | + end | |
623 | + def public | |
624 | + self.public? | |
625 | + end | |
626 | + def environment_id | |
627 | + profile.environment_id | |
628 | + end | |
629 | + public | |
630 | + | |
631 | + acts_as_faceted :fields => { | |
632 | + :f_type => {:label => _('Type'), :proc => proc{|klass| f_type_proc(klass)}}, | |
633 | + :f_published_at => {:type => :date, :label => _('Published date'), :queries => {'[* TO NOW-1YEARS/DAY]' => _("Older than one year"), | |
634 | + '[NOW-1YEARS TO NOW/DAY]' => _("Last year"), '[NOW-1MONTHS TO NOW/DAY]' => _("Last month"), '[NOW-7DAYS TO NOW/DAY]' => _("Last week"), '[NOW-1DAYS TO NOW/DAY]' => _("Last day")}, | |
635 | + :queries_order => ['[NOW-1DAYS TO NOW/DAY]', '[NOW-7DAYS TO NOW/DAY]', '[NOW-1MONTHS TO NOW/DAY]', '[NOW-1YEARS TO NOW/DAY]', '[* TO NOW-1YEARS/DAY]']}, | |
636 | + :f_profile_type => {:label => _('Profile'), :proc => proc{|klass| f_profile_type_proc(klass)}}, | |
637 | + :f_category => {:label => _('Categories')}}, | |
638 | + :category_query => proc { |c| "f_category:\"#{c.name}\"" }, | |
639 | + :order => [:f_type, :f_published_at, :f_profile_type, :f_category] | |
640 | + | |
641 | + acts_as_searchable :additional_fields => [ | |
642 | + {:name => {:type => :string}}, | |
643 | + {:public => {:type => :boolean}}, | |
644 | + {:environment_id => {:type => :integer}}, | |
645 | + ] + facets_fields_for_solr, | |
646 | + :exclude_fields => [:setting], | |
647 | + :include => [:profile], | |
648 | + :facets => facets_option_for_solr, | |
649 | + :boost => proc {|a| 10 if a.profile.enabled}, | |
650 | + :if => proc{|a| ! ['RssFeed'].include?(a.class.name)} | |
651 | + handle_asynchronously :solr_save | |
652 | + | |
653 | + private | |
654 | + | |
564 | 655 | def sanitize_tag_list |
565 | 656 | sanitizer = HTML::FullSanitizer.new |
566 | 657 | self.tag_list.names.map!{|i| strip_tag_name sanitizer.sanitize(i) } | ... | ... |
app/models/blog.rb
app/models/category.rb
... | ... | @@ -36,18 +36,38 @@ class Category < ActiveRecord::Base |
36 | 36 | { :conditions => [ "type IN (?) OR type IS NULL", types.reject{ |t| t.blank? } ] } |
37 | 37 | } |
38 | 38 | |
39 | + def recent_people(limit = 10) | |
40 | + self.people.paginate(:order => 'created_at DESC, id DESC', :page => 1, :per_page => limit) | |
41 | + end | |
42 | + | |
43 | + def recent_enterprises(limit = 10) | |
44 | + self.enterprises.paginate(:order => 'created_at DESC, id DESC', :page => 1, :per_page => limit) | |
45 | + end | |
46 | + | |
47 | + def recent_communities(limit = 10) | |
48 | + self.communities.paginate(:order => 'created_at DESC, id DESC', :page => 1, :per_page => limit) | |
49 | + end | |
50 | + | |
51 | + def recent_products(limit = 10) | |
52 | + self.products.paginate(:order => 'created_at DESC, id DESC', :page => 1, :per_page => limit) | |
53 | + end | |
54 | + | |
39 | 55 | def recent_articles(limit = 10) |
40 | 56 | self.articles.recent(limit) |
41 | 57 | end |
42 | 58 | |
43 | 59 | def recent_comments(limit = 10) |
44 | - comments.find(:all, :order => 'created_at DESC, comments.id DESC', :limit => limit) | |
60 | + comments.paginate(:all, :order => 'created_at DESC, comments.id DESC', :page => 1, :per_page => limit) | |
45 | 61 | end |
46 | 62 | |
47 | 63 | def most_commented_articles(limit = 10) |
48 | 64 | self.articles.most_commented(limit) |
49 | 65 | end |
50 | 66 | |
67 | + def upcoming_events(limit = 10) | |
68 | + self.events.find(:all, :conditions => [ 'start_date >= ?', Date.today ], :order => 'start_date') | |
69 | + end | |
70 | + | |
51 | 71 | def display_in_menu? |
52 | 72 | display_in_menu |
53 | 73 | end | ... | ... |
app/models/category_finder.rb
... | ... | @@ -1,146 +0,0 @@ |
1 | -class CategoryFinder | |
2 | - | |
3 | - def initialize(cat) | |
4 | - @category = cat | |
5 | - @category_id = @category.id | |
6 | - end | |
7 | - | |
8 | - attr_reader :category_id | |
9 | - | |
10 | - def find(asset, query='', options={}) | |
11 | - @region = Region.find_by_id(options.delete(:region)) if options.has_key?(:region) | |
12 | - if @region && options[:within] | |
13 | - options[:origin] = [@region.lat, @region.lng] | |
14 | - else | |
15 | - options.delete(:within) | |
16 | - end | |
17 | - | |
18 | - date_range = options.delete(:date_range) | |
19 | - | |
20 | - options = {:page => 1, :per_page => options.delete(:limit)}.merge(options) | |
21 | - | |
22 | - if asset == :events | |
23 | - finder_method = 'find' | |
24 | - options.delete(:page) | |
25 | - options.delete(:per_page) | |
26 | - else | |
27 | - finder_method = 'paginate' | |
28 | - end | |
29 | - | |
30 | - if query.blank? | |
31 | - options.delete(:facets) | |
32 | - asset_class(asset).send(finder_method, :all, options_for_find(asset_class(asset), {:order => "#{asset_table(asset)}.name"}.merge(options), date_range)) | |
33 | - else | |
34 | - pg_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)} | |
35 | - solr_options = {:facets => options.delete(:facets)} | |
36 | - asset_class(asset).find_by_contents(query, pg_options, solr_options, options_for_find(asset_class(asset), options, date_range))[:results] | |
37 | - end | |
38 | - end | |
39 | - | |
40 | - def recent(asset, limit = nil) | |
41 | - find(asset, nil, :limit => limit, :order => 'created_at DESC, id DESC') | |
42 | - end | |
43 | - | |
44 | - def most_commented_articles(limit=10, options={}) | |
45 | - options = {:page => 1, :per_page => limit, :order => 'comments_count DESC'}.merge(options) | |
46 | - Article.paginate(:all, options_for_find(Article, options)) | |
47 | - end | |
48 | - | |
49 | - def current_events(year, month, options={}) | |
50 | - options.delete(:page) | |
51 | - options.delete(:per_page) | |
52 | - | |
53 | - range = Event.date_range(year, month) | |
54 | - | |
55 | - Event.find(:all, {:include => :categories, :conditions => { 'categories.id' => category_id, :start_date => range }}.merge(options)) | |
56 | - end | |
57 | - | |
58 | - def upcoming_events(options = {}) | |
59 | - options.delete(:page) | |
60 | - options.delete(:per_page) | |
61 | - | |
62 | - Event.find(:all, {:include => :categories, :conditions => [ 'categories.id = ? and start_date >= ?', category_id, Date.today ], :order => 'start_date' }.merge(options)) | |
63 | - end | |
64 | - | |
65 | - def product_categories_count(asset, product_categories_ids, objects_ids=nil) | |
66 | - conditions = [ "product_categorizations.category_id in (?) and #{ProfileCategorization.table_name}.category_id = ?", product_categories_ids, category_id] | |
67 | - | |
68 | - if asset == :products | |
69 | - if objects_ids | |
70 | - conditions[0] += ' and product_categorizations.product_id in (?)' | |
71 | - conditions << objects_ids | |
72 | - end | |
73 | - ProductCategory.find( | |
74 | - :all, | |
75 | - :select => 'categories.id, count(*) as total', | |
76 | - :joins => "inner join product_categorizations on (product_categorizations.category_id = categories.id) inner join products on (products.id = product_categorizations.product_id) inner join #{ProfileCategorization.table_name} on (#{ProfileCategorization.table_name}.profile_id = products.enterprise_id)", | |
77 | - :group => 'categories.id', | |
78 | - :conditions => conditions | |
79 | - ) | |
80 | - elsif asset == :enterprises | |
81 | - if objects_ids | |
82 | - conditions[0] += ' and products.enterprise_id in (?)' | |
83 | - conditions << objects_ids | |
84 | - end | |
85 | - ProductCategory.find( | |
86 | - :all, | |
87 | - :select => 'categories.id, count(distinct products.enterprise_id) as total', | |
88 | - :joins => "inner join product_categorizations on (product_categorizations.category_id = categories.id) inner join products on (products.id = product_categorizations.product_id) inner join #{ProfileCategorization.table_name} on (#{ProfileCategorization.table_name}.profile_id = products.enterprise_id)", | |
89 | - :group => 'categories.id', | |
90 | - :conditions => conditions | |
91 | - ) | |
92 | - else | |
93 | - raise ArgumentError, 'only products and enterprises supported' | |
94 | - end.inject({}) do |results,pc| | |
95 | - results[pc.id]= pc.total.to_i | |
96 | - results | |
97 | - end | |
98 | - end | |
99 | - | |
100 | - protected | |
101 | - | |
102 | - def options_for_find(klass, options={}, date_range = nil) | |
103 | - if defined? options[:product_category] | |
104 | - prod_cat = options.delete(:product_category) | |
105 | - end | |
106 | - | |
107 | - case klass.name | |
108 | - when 'Comment' | |
109 | - {:joins => 'inner join articles_categories on articles_categories.article_id = comments.article_id', :conditions => ['articles_categories.category_id = (?)', category_id]}.merge!(options) | |
110 | - when 'Product' | |
111 | - if prod_cat | |
112 | - {:joins => 'inner join categories_profiles on products.enterprise_id = categories_profiles.profile_id inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => ['categories_profiles.category_id = (?) and product_categorizations.category_id = (?)', category_id, prod_cat.id]}.merge!(options) | |
113 | - else | |
114 | - {:joins => 'inner join categories_profiles on products.enterprise_id = categories_profiles.profile_id', :conditions => ['categories_profiles.category_id = (?)', category_id]}.merge!(options) | |
115 | - end | |
116 | - when 'Article', 'TextArticle' | |
117 | - {:joins => 'inner join articles_categories on (articles_categories.article_id = articles.id)', :conditions => ['articles_categories.category_id = (?)', category_id]}.merge!(options) | |
118 | - when 'Event' | |
119 | - conditions = | |
120 | - if date_range | |
121 | - ['articles_categories.category_id = (:category_id) and (start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day)', {:category_id => category_id, :start_day => date_range.first, :end_day => date_range.last} ] | |
122 | - else | |
123 | - ['articles_categories.category_id = (?) ', category_id ] | |
124 | - end | |
125 | - {:joins => 'inner join articles_categories on (articles_categories.article_id = articles.id)', :conditions => conditions}.merge!(options) | |
126 | - when 'Enterprise' | |
127 | - if prod_cat | |
128 | - {:joins => 'inner join categories_profiles on (categories_profiles.profile_id = profiles.id) inner join products on (products.enterprise_id = profiles.id) inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => ['categories_profiles.category_id = (?) and product_categorizations.category_id = (?)', category_id, prod_cat.id]}.merge!(options) | |
129 | - else | |
130 | - {:joins => 'inner join categories_profiles on (categories_profiles.profile_id = profiles.id)', :conditions => ['categories_profiles.category_id = (?)', category_id]}.merge!(options) | |
131 | - end | |
132 | - when 'Person', 'Community' | |
133 | - {:joins => 'inner join categories_profiles on (categories_profiles.profile_id = profiles.id)', :conditions => ['categories_profiles.category_id = (?)', category_id]}.merge!(options) | |
134 | - else | |
135 | - raise "unreconized class #{klass.name}" | |
136 | - end | |
137 | - end | |
138 | - | |
139 | - def asset_class(asset) | |
140 | - asset.to_s.singularize.camelize.constantize | |
141 | - end | |
142 | - | |
143 | - def asset_table(asset) | |
144 | - asset_class(asset).table_name | |
145 | - end | |
146 | -end |
app/models/certifier.rb
... | ... | @@ -2,9 +2,12 @@ class Certifier < ActiveRecord::Base |
2 | 2 | |
3 | 3 | belongs_to :environment |
4 | 4 | |
5 | - has_many :qualifier_certifiers | |
5 | + has_many :qualifier_certifiers, :dependent => :destroy | |
6 | 6 | has_many :qualifiers, :through => :qualifier_certifiers |
7 | 7 | |
8 | + has_many :product_qualifiers, :dependent => :destroy | |
9 | + has_many :products, :through => :product_qualifiers, :source => :product | |
10 | + | |
8 | 11 | validates_presence_of :environment_id |
9 | 12 | validates_presence_of :name |
10 | 13 | ... | ... |
app/models/communities_block.rb
... | ... | @@ -21,7 +21,7 @@ class CommunitiesBlock < ProfileListBlock |
21 | 21 | end |
22 | 22 | when Environment |
23 | 23 | lambda do |
24 | - link_to s_('communities|View all'), :controller => 'browse', :action => 'communities' | |
24 | + link_to s_('communities|View all'), :controller => 'search', :action => 'communities' | |
25 | 25 | end |
26 | 26 | else |
27 | 27 | '' | ... | ... |
app/models/community.rb
app/models/enterprise.rb
... | ... | @@ -2,6 +2,10 @@ |
2 | 2 | # only enterprises can offer products and services. |
3 | 3 | class Enterprise < Organization |
4 | 4 | |
5 | + def self.type_name | |
6 | + _('Enterprise') | |
7 | + end | |
8 | + | |
5 | 9 | N_('Enterprise') |
6 | 10 | |
7 | 11 | has_many :products, :dependent => :destroy, :order => 'name ASC' |
... | ... | @@ -163,6 +167,10 @@ class Enterprise < Organization |
163 | 167 | end |
164 | 168 | end |
165 | 169 | |
170 | + def control_panel_settings_button | |
171 | + {:title => __('Enterprise Info and settings'), :icon => 'edit-profile-enterprise'} | |
172 | + end | |
173 | + | |
166 | 174 | settings_items :enable_contact_us, :type => :boolean, :default => true |
167 | 175 | |
168 | 176 | def enable_contact? | ... | ... |
app/models/enterprise_homepage.rb
app/models/environment.rb
... | ... | @@ -247,6 +247,10 @@ class Environment < ActiveRecord::Base |
247 | 247 | |
248 | 248 | settings_items :enabled_plugins, :type => Array, :default => [] |
249 | 249 | |
250 | + settings_items :search_hints, :type => Hash, :default => {} | |
251 | + | |
252 | + settings_items :top_level_category_as_facet_ids, :type => Array, :default => [] | |
253 | + | |
250 | 254 | def news_amount_by_folder=(amount) |
251 | 255 | settings[:news_amount_by_folder] = amount.to_i |
252 | 256 | end |
... | ... | @@ -353,11 +357,11 @@ class Environment < ActiveRecord::Base |
353 | 357 | end |
354 | 358 | |
355 | 359 | def terminology |
356 | - if self.settings[:terminology] | |
357 | - self.settings[:terminology].constantize.instance | |
358 | - else | |
360 | + #if self.settings[:terminology] | |
361 | + #self.settings[:terminology].constantize.instance | |
362 | + #else | |
359 | 363 | Noosfero.terminology |
360 | - end | |
364 | + #end | |
361 | 365 | end |
362 | 366 | |
363 | 367 | def terminology=(value) | ... | ... |
app/models/environment_finder.rb
... | ... | @@ -1,115 +0,0 @@ |
1 | -class EnvironmentFinder | |
2 | - | |
3 | - def initialize env | |
4 | - @environment = env | |
5 | - end | |
6 | - | |
7 | - def find(asset, query = nil, options={}, finder_method = 'paginate') | |
8 | - @region = Region.find_by_id(options.delete(:region)) if options.has_key?(:region) | |
9 | - if @region && options[:within] | |
10 | - options[:origin] = [@region.lat, @region.lng] | |
11 | - else | |
12 | - options.delete(:within) | |
13 | - end | |
14 | - | |
15 | - product_category = options.delete(:product_category) | |
16 | - | |
17 | - date_range = options.delete(:date_range) | |
18 | - | |
19 | - # FIXME this test is in more than one place | |
20 | - if finder_method == 'paginate' | |
21 | - options = {:page => 1, :per_page => options.delete(:limit)}.merge(options) | |
22 | - end | |
23 | - | |
24 | - if query.blank? | |
25 | - options.delete(:facets) | |
26 | - | |
27 | - # FIXME this test is in more than one place | |
28 | - if finder_method == 'paginate' | |
29 | - options = {:order => "#{asset_table(asset)}.name"}.merge(options) | |
30 | - end | |
31 | - if product_category && asset == :products | |
32 | - @environment.send(asset).send(finder_method, :all, options.merge(:include => 'product_categorizations', :conditions => ['product_categorizations.category_id = (?)', product_category.id])) | |
33 | - elsif product_category && asset == :enterprises | |
34 | - @environment.send(asset).send(finder_method, :all, options.merge( :order => 'profiles.name', :joins => 'inner join products on (products.enterprise_id = profiles.id) inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => ['product_categorizations.category_id = (?)', product_category.id])) | |
35 | - else | |
36 | - if asset == :events | |
37 | - # Ignore pagination for asset events | |
38 | - options.delete(:per_page) | |
39 | - options.delete(:page) | |
40 | - if date_range | |
41 | - @environment.send(asset).send('find', :all, options.merge(:conditions => [ | |
42 | - 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day', | |
43 | - {:start_day => date_range.first, :end_day => date_range.last} | |
44 | - ])) | |
45 | - else | |
46 | - @environment.send(asset).send('find', :all, options) | |
47 | - end | |
48 | - else | |
49 | - @environment.send(asset).send(finder_method, :all, options) | |
50 | - end | |
51 | - end | |
52 | - else | |
53 | - pg_options = {:page => options.delete(:page), :per_page => options.delete(:per_page)} | |
54 | - solr_options = {:facets => options.delete(:facets)} | |
55 | - if product_category && asset == :products | |
56 | - # SECURITY no risk of SQL injection, since product_category_ids comes from trusted source | |
57 | - ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options.merge({:include => 'product_categorizations', :conditions => 'product_categorizations.category_id = (%s)' % product_category.id })) | |
58 | - elsif product_category && asset == :enterprises | |
59 | - ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options.merge(:joins => 'inner join products on products.enterprise_id = profiles.id inner join product_categorizations on (product_categorizations.product_id = products.id)', :include => 'products', :conditions => "product_categorizations.category_id = (#{product_category.id})")) | |
60 | - else | |
61 | - ret = @environment.send(asset).find_by_contents(query, pg_options, solr_options, options) | |
62 | - end | |
63 | - if solr_options[:facets].nil? | |
64 | - ret[:results] | |
65 | - else | |
66 | - ret | |
67 | - end | |
68 | - end | |
69 | - end | |
70 | - | |
71 | - def recent(asset, limit = nil) | |
72 | - find(asset, nil, :limit => limit) | |
73 | - end | |
74 | - | |
75 | - def product_categories_count(asset, product_categories_ids, objects_ids=nil) | |
76 | - conditions = ['product_categorizations.category_id in (?)', product_categories_ids] | |
77 | - | |
78 | - if asset == :products | |
79 | - if objects_ids | |
80 | - conditions[0] += ' and product_categorizations.product_id in (?)' | |
81 | - conditions << objects_ids | |
82 | - end | |
83 | - ProductCategory.find(:all, :select => 'categories.id, count(*) as total', :joins => 'inner join product_categorizations on (product_categorizations.category_id = categories.id)', :group => 'categories.id', :conditions => conditions ) | |
84 | - elsif asset == :enterprises | |
85 | - if objects_ids | |
86 | - conditions[0] += ' and products.enterprise_id in (?)' | |
87 | - conditions << objects_ids | |
88 | - end | |
89 | - ProductCategory.find( | |
90 | - :all, | |
91 | - :select => 'categories.id, count(distinct products.enterprise_id) as total', | |
92 | - :joins => 'inner join product_categorizations on (product_categorizations.category_id = categories.id) inner join products on (products.id = product_categorizations.product_id)', | |
93 | - :group => 'categories.id', | |
94 | - :conditions => conditions | |
95 | - ) | |
96 | - else | |
97 | - raise ArgumentError, 'only products and enterprises supported' | |
98 | - end.inject({}) do |results,pc| | |
99 | - results[pc.id]= pc.total.to_i | |
100 | - results | |
101 | - end | |
102 | - | |
103 | - end | |
104 | - | |
105 | - protected | |
106 | - | |
107 | - def asset_class(asset) | |
108 | - asset.to_s.singularize.camelize.constantize | |
109 | - end | |
110 | - | |
111 | - def asset_table(asset) | |
112 | - asset_class(asset).table_name | |
113 | - end | |
114 | - | |
115 | -end |
app/models/event.rb
app/models/folder.rb
app/models/forum.rb
app/models/gallery.rb
app/models/people_block.rb
app/models/person.rb
app/models/product.rb
1 | 1 | class Product < ActiveRecord::Base |
2 | 2 | belongs_to :enterprise |
3 | + has_one :region, :through => :enterprise | |
4 | + | |
3 | 5 | belongs_to :product_category |
4 | - has_many :product_categorizations | |
5 | - has_many :product_qualifiers | |
6 | - has_many :qualifiers, :through => :product_qualifiers | |
6 | + | |
7 | 7 | has_many :inputs, :dependent => :destroy, :order => 'position' |
8 | 8 | has_many :price_details, :dependent => :destroy |
9 | 9 | has_many :production_costs, :through => :price_details |
10 | 10 | |
11 | + has_many :product_qualifiers, :dependent => :destroy | |
12 | + has_many :qualifiers, :through => :product_qualifiers | |
13 | + has_many :certifiers, :through => :product_qualifiers | |
14 | + | |
11 | 15 | validates_uniqueness_of :name, :scope => :enterprise_id, :allow_nil => true |
12 | 16 | validates_presence_of :product_category_id |
13 | 17 | validates_associated :product_category |
... | ... | @@ -28,17 +32,6 @@ class Product < ActiveRecord::Base |
28 | 32 | p.enterprise.product_updated if p.enterprise |
29 | 33 | end |
30 | 34 | |
31 | - after_save do |p| | |
32 | - if (p.product_category && !ProductCategorization.find(:first, :conditions => {:category_id => p.product_category.id, :product_id => p.id})) || (!p.product_category) | |
33 | - ProductCategorization.remove_all_for(p) | |
34 | - if p.product_category | |
35 | - ProductCategorization.add_category_to_product(p.product_category, p) | |
36 | - end | |
37 | - end | |
38 | - end | |
39 | - | |
40 | - acts_as_searchable :fields => [ :name, :description, :category_full_name ] | |
41 | - | |
42 | 35 | xss_terminate :only => [ :name ], :on => 'validation' |
43 | 36 | xss_terminate :only => [ :description ], :with => 'white_list', :on => 'validation' |
44 | 37 | |
... | ... | @@ -90,9 +83,11 @@ class Product < ActiveRecord::Base |
90 | 83 | end |
91 | 84 | |
92 | 85 | def enterprise_updated(e) |
93 | - self.lat = e.lat | |
94 | - self.lng = e.lng | |
95 | - save! | |
86 | + if self.lat != e.lat or self.lng != e.lng | |
87 | + self.lat = e.lat | |
88 | + self.lng = e.lng | |
89 | + save! | |
90 | + end | |
96 | 91 | end |
97 | 92 | |
98 | 93 | def url |
... | ... | @@ -100,7 +95,7 @@ class Product < ActiveRecord::Base |
100 | 95 | end |
101 | 96 | |
102 | 97 | def public? |
103 | - enterprise.public_profile | |
98 | + enterprise.public? | |
104 | 99 | end |
105 | 100 | |
106 | 101 | def formatted_value(method) |
... | ... | @@ -213,4 +208,64 @@ class Product < ActiveRecord::Base |
213 | 208 | url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_inputs_cost', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options)) |
214 | 209 | end |
215 | 210 | |
211 | + private | |
212 | + def name_or_category | |
213 | + name ? name : product_category.name | |
214 | + end | |
215 | + def price_sort | |
216 | + (price.nil? or price.zero?) ? 999999999.9 : price | |
217 | + end | |
218 | + def f_category | |
219 | + self.product_category.name | |
220 | + end | |
221 | + def f_region | |
222 | + self.enterprise.region.id if self.enterprise.region | |
223 | + end | |
224 | + def self.f_region_proc(id) | |
225 | + c = Region.find(id) | |
226 | + s = c.parent | |
227 | + if c and c.kind_of?(City) and s and s.kind_of?(State) and s.acronym | |
228 | + [c.name, ', ' + s.acronym] | |
229 | + else | |
230 | + c.name | |
231 | + end | |
232 | + end | |
233 | + def self.f_qualifier_proc(id) | |
234 | + pq = ProductQualifier.find(id) | |
235 | + if pq.certifier | |
236 | + [pq.qualifier.name, _(' cert. ') + pq.certifier.name] | |
237 | + else | |
238 | + pq.qualifier.name | |
239 | + end | |
240 | + end | |
241 | + def f_qualifier | |
242 | + product_qualifier_ids | |
243 | + end | |
244 | + def public | |
245 | + self.public? | |
246 | + end | |
247 | + def environment_id | |
248 | + enterprise.environment_id | |
249 | + end | |
250 | + public | |
251 | + | |
252 | + acts_as_faceted :fields => { | |
253 | + :f_category => {:label => _('Related products')}, | |
254 | + :f_region => {:label => _('City'), :proc => proc { |id| f_region_proc(id) }}, | |
255 | + :f_qualifier => {:label => _('Qualifiers'), :proc => proc { |id| f_qualifier_proc(id) }}}, | |
256 | + :category_query => proc { |c| "f_category:\"#{c.name}\"" }, | |
257 | + :order => [:f_category, :f_region, :f_qualifier] | |
258 | + | |
259 | + acts_as_searchable :additional_fields => [ | |
260 | + {:name => {:type => :text, :boost => 5.0}}, | |
261 | + {:price_sort => {:type => :decimal}}, | |
262 | + {:public => {:type => :boolean}}, | |
263 | + {:environment_id => {:type => :integer}}, | |
264 | + {:name_or_category => {:type => :string, :as => :name_or_category_sort, :boost => 2.0}}, | |
265 | + :category_full_name ] + facets.keys.map{|i| {i => :facet}}, | |
266 | + :include => [:enterprise, :qualifiers, :certifiers, :product_category], | |
267 | + :boost => proc {|p| 10 if p.enterprise.enabled}, | |
268 | + :facets => facets.keys | |
269 | + handle_asynchronously :solr_save | |
270 | + | |
216 | 271 | end | ... | ... |
app/models/product_categorization.rb
... | ... | @@ -1,13 +0,0 @@ |
1 | -class ProductCategorization < ActiveRecord::Base | |
2 | - belongs_to :product_category, :foreign_key => 'category_id' | |
3 | - belongs_to :product | |
4 | - | |
5 | - extend Categorization | |
6 | - | |
7 | - class << self | |
8 | - alias :add_category_to_product :add_category_to_object | |
9 | - def object_id_column | |
10 | - :product_id | |
11 | - end | |
12 | - end | |
13 | -end |
app/models/profile.rb
... | ... | @@ -3,6 +3,12 @@ |
3 | 3 | # which by default is the one returned by Environment:default. |
4 | 4 | class Profile < ActiveRecord::Base |
5 | 5 | |
6 | + # use for internationalizable human type names in search facets | |
7 | + # reimplement on subclasses | |
8 | + def self.type_name | |
9 | + _('Profile') | |
10 | + end | |
11 | + | |
6 | 12 | module Roles |
7 | 13 | def self.admin(env_id) |
8 | 14 | find_role('admin', env_id) |
... | ... | @@ -70,8 +76,6 @@ class Profile < ActiveRecord::Base |
70 | 76 | |
71 | 77 | acts_as_having_boxes |
72 | 78 | |
73 | - acts_as_searchable :additional_fields => [ :extra_data_for_index ] | |
74 | - | |
75 | 79 | acts_as_taggable |
76 | 80 | |
77 | 81 | def self.qualified_column_names |
... | ... | @@ -179,6 +183,15 @@ class Profile < ActiveRecord::Base |
179 | 183 | |
180 | 184 | has_many :abuse_complaints, :foreign_key => 'requestor_id' |
181 | 185 | |
186 | + def top_level_categorization | |
187 | + ret = {} | |
188 | + self.profile_categorizations.each do |c| | |
189 | + p = c.category.top_ancestor | |
190 | + ret[p] = (ret[p] || []) + [c.category] | |
191 | + end | |
192 | + ret | |
193 | + end | |
194 | + | |
182 | 195 | def interests |
183 | 196 | categories.select {|item| !item.is_a?(Region)} |
184 | 197 | end |
... | ... | @@ -818,18 +831,66 @@ private :generate_url, :url_options |
818 | 831 | name |
819 | 832 | end |
820 | 833 | |
821 | - protected | |
834 | + private | |
835 | + def self.f_categories_label_proc(environment) | |
836 | + ids = environment.top_level_category_as_facet_ids | |
837 | + r = Category.find(ids) | |
838 | + map = {} | |
839 | + ids.map{ |id| map[id.to_s] = r.detect{|c| c.id == id}.name } | |
840 | + map | |
841 | + end | |
842 | + def self.f_categories_proc(facet, id) | |
843 | + id = id.to_i | |
844 | + c = Category.find(id) | |
845 | + c.name if c.top_ancestor.id == facet[:label_id].to_i or facet[:label_id] == 0 | |
846 | + end | |
847 | + def f_categories | |
848 | + category_ids | |
849 | + end | |
822 | 850 | |
823 | - def followed_by?(person) | |
824 | - person.is_member_of?(self) | |
825 | - end | |
851 | + def f_type | |
852 | + self.class.name | |
853 | + end | |
854 | + def self.f_type_proc(klass) | |
855 | + klass.constantize.type_name | |
856 | + end | |
857 | + def name_sort | |
858 | + name | |
859 | + end | |
860 | + def public | |
861 | + self.public? | |
862 | + end | |
863 | + public | |
826 | 864 | |
827 | - def display_private_info_to?(user) | |
828 | - if user.nil? | |
829 | - false | |
830 | - else | |
831 | - (user == self) || (user.is_admin?(self.environment)) || user.is_admin?(self) || user.memberships.include?(self) | |
832 | - end | |
865 | + acts_as_faceted :fields => { | |
866 | + :f_type => {:label => _('Type'), :type_if => proc { |klass| klass.kind_of?(Enterprise) }, :proc => proc { |id| f_type_proc(id) }}, | |
867 | + :f_categories => {:multi => true, :proc => proc {|facet, id| f_categories_proc(facet, id)}, | |
868 | + :label => proc { |env| f_categories_label_proc(env) }, :label_abbrev => proc { |env| f_categories_label_abbrev_proc(env) }}}, | |
869 | + :category_query => proc { |c| "f_categories:#{c.id}" }, | |
870 | + :order => [:f_type, :f_categories] | |
871 | + | |
872 | + acts_as_searchable :additional_fields => [ | |
873 | + {:name_sort => {:type => :string}}, | |
874 | + {:public => {:type => :boolean}}, | |
875 | + :extra_data_for_index ] + facets.keys.map{|i| {i => :facet}}, | |
876 | + :boost => proc {|p| 10 if p.enabled}, | |
877 | + :facets => facets.keys | |
878 | + handle_asynchronously :solr_save | |
879 | + | |
880 | + def control_panel_settings_button | |
881 | + {:title => _('Profile Info and settings'), :icon => 'edit-profile'} | |
882 | + end | |
883 | + | |
884 | + def followed_by?(person) | |
885 | + person.is_member_of?(self) | |
886 | + end | |
887 | + | |
888 | + def display_private_info_to?(user) | |
889 | + if user.nil? | |
890 | + false | |
891 | + else | |
892 | + (user == self) || (user.is_admin?(self.environment)) || user.is_admin?(self) || user.memberships.include?(self) | |
833 | 893 | end |
894 | + end | |
834 | 895 | |
835 | 896 | end | ... | ... |
app/models/qualifier.rb
... | ... | @@ -2,14 +2,15 @@ class Qualifier < ActiveRecord::Base |
2 | 2 | |
3 | 3 | belongs_to :environment |
4 | 4 | |
5 | - has_many :qualifier_certifiers | |
5 | + has_many :qualifier_certifiers, :dependent => :destroy | |
6 | 6 | has_many :certifiers, :through => :qualifier_certifiers |
7 | 7 | |
8 | + has_many :product_qualifiers, :dependent => :destroy | |
9 | + has_many :products, :through => :product_qualifiers, :source => :product | |
10 | + | |
8 | 11 | validates_presence_of :environment_id |
9 | 12 | validates_presence_of :name |
10 | 13 | |
11 | - has_many :product_qualifiers, :dependent => :destroy | |
12 | - | |
13 | 14 | def <=>(b) |
14 | 15 | self.name.downcase.transliterate <=> b.name.downcase.transliterate |
15 | 16 | end | ... | ... |
app/models/qualifier_certifier.rb
app/models/raw_html_article.rb
app/models/rss_feed.rb
app/models/text_article.rb
app/models/textile_article.rb
app/models/tiny_mce_article.rb
app/models/uploaded_file.rb
... | ... | @@ -4,6 +4,10 @@ |
4 | 4 | # of the file itself is kept. (FIXME?) |
5 | 5 | class UploadedFile < Article |
6 | 6 | |
7 | + def self.type_name | |
8 | + _('File') | |
9 | + end | |
10 | + | |
7 | 11 | track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? } |
8 | 12 | |
9 | 13 | include ShortFilename | ... | ... |
app/views/browse/_article.rhtml
... | ... | @@ -1,11 +0,0 @@ |
1 | -<li class="<%= 'browse-results-type-content ' + icon_for_article(result) %>"> | |
2 | - <strong><%= link_to(result.title, result.view_url) %></strong> | |
3 | - <div class="item_meta"> | |
4 | - <span class="item_by"> | |
5 | - <%= _('by %s') % link_to(result.author.name, result.author.url) %> | |
6 | - </span> | |
7 | - <span class="extra-info"> | |
8 | - <%= (@filter == 'more_recent' ? result.send(@filter + '_label') + show_date(result.created_at) : result.send(@filter + '_label')) %> | |
9 | - </span> | |
10 | - </div> | |
11 | -</li> |
app/views/browse/_display_results.rhtml
... | ... | @@ -1,19 +0,0 @@ |
1 | -<div id="browse-results"> | |
2 | - | |
3 | - <div class='browse-results-innerbox'> | |
4 | - <% if @results.empty? %> | |
5 | - <div class="browse-results-type-empty"> | |
6 | - <div> <%= _('None') %> </div> | |
7 | - </div><!-- end class="browse-results-innerbox" --> | |
8 | - <% end %> | |
9 | - <ul class='common-profile-list-block'> | |
10 | - <% @results.each do |result| %> | |
11 | - <%= render :partial => partial_for_class(result.class), :locals => {:result => result} %> | |
12 | - <% end %> | |
13 | - </ul> | |
14 | - <br style='clear: both;'> | |
15 | - </div> | |
16 | - | |
17 | - <br style="clear:both" /> | |
18 | -</div><!-- end id="browse-results" --> | |
19 | - |
app/views/browse/_person.rhtml
app/views/browse/_profile.rhtml
... | ... | @@ -1 +0,0 @@ |
1 | -<%= profile_image_link result, :portrait, 'li', @filter == 'more_recent' ? result.send(@filter + '_label') + show_date(result.created_at) : result.send(@filter + '_label') %> |
app/views/browse/_search_form.rhtml
... | ... | @@ -1,10 +0,0 @@ |
1 | -<% form_tag( { :controller => 'browse', :action => action}, :method => 'get', :class => 'search_form' ) do %> | |
2 | - | |
3 | - <div class="search-field"> | |
4 | - <span class="formfield"> | |
5 | - <%= text_field_tag 'query', @query, :size => 50 %> | |
6 | - </span> | |
7 | - <%= submit_button(:search, _('Search')) %> | |
8 | - </div> | |
9 | - | |
10 | -<% end %> |
app/views/browse/communities.rhtml
app/views/browse/contents.rhtml
app/views/browse/people.rhtml
app/views/events/events.rhtml
1 | -<h1 id='agenda-title'> | |
2 | - <div id='agenda-toolbar'> | |
3 | - <%= button :back, _('Back to %s') % profile.name, profile.url %> | |
4 | - <% if user && user.has_permission?('post_content', profile) %> | |
5 | - <%= button :new, _('New event'), myprofile_url(:controller => 'cms', :action => 'new', :type => 'Event') %> | |
6 | - <% end %> | |
7 | - </div> | |
8 | - <%= _("%s's events") % profile.name %> | |
9 | -</h1> | |
1 | +<h1 id='agenda-title'><%= _("%s's events") % profile.name %></h1> | |
2 | + | |
3 | +<div id='agenda-toolbar'> | |
4 | + <%= button :back, _('Back to %s') % profile.name, profile.url %> | |
5 | + <% if user && user.has_permission?('post_content', profile) %> | |
6 | + <%= button :new, _('New event'), myprofile_url(:controller => 'cms', :action => 'new', :type => 'Event') %> | |
7 | + <% end %> | |
8 | +</div> | |
9 | + | |
10 | +<div style="clear: both"></div> | |
10 | 11 | |
11 | 12 | <%= render :partial => 'agenda' %> | ... | ... |
app/views/layouts/_javascript.rhtml
1 | -<%= javascript_include_tag :defaults, 'jquery-latest.js', 'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery.cookie', 'reflection', 'add-and-join', 'jquery.tokeninput', 'report-abuse','colorbox', 'jquery-validation/jquery.validate', 'catalog', 'manage-products', :cache => 'cache-general' %> | |
1 | +<%= javascript_include_tag :defaults, 'jquery-latest.js', | |
2 | +'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', | |
3 | +'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.form.js', | |
4 | +'jquery.cookie', 'reflection', 'add-and-join', 'jquery.tokeninput', | |
5 | +'jquery.ba-bbq.min.js', 'report-abuse','colorbox', 'jquery-validation/jquery.validate', 'catalog', | |
6 | +'manage-products', :cache => 'cache-general' %> | |
2 | 7 | <% language = FastGettext.locale %> |
3 | -<%= javascript_include_tag 'jquery-validation/localization/messages_'+language, 'jquery-validation/localization/methods_'+language %> | |
8 | +<%= javascript_include_tag 'jquery-validation/localization/messages_'+language, | |
9 | + 'jquery-validation/localization/methods_'+language %> | ... | ... |
app/views/layouts/application-ng.rhtml
... | ... | @@ -12,6 +12,8 @@ |
12 | 12 | <%= stylesheet_link_tag template_stylesheet_path %> |
13 | 13 | <%= stylesheet_link_tag icon_theme_stylesheet_path %> |
14 | 14 | <%= stylesheet_link_tag jquery_ui_theme_stylesheet_path %> |
15 | + <%= stylesheet_link_tag "token-input" %> | |
16 | + <%= stylesheet_link_tag "token-input-facet" %> | |
15 | 17 | <% @plugins.enabled_plugins.each do |plugin| %> |
16 | 18 | <% if plugin.stylesheet? %> |
17 | 19 | <%= stylesheet_tag plugin.class.public_path('style.css'), {} %> |
... | ... | @@ -63,16 +65,10 @@ |
63 | 65 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> |
64 | 66 | </div> |
65 | 67 | </span> |
66 | - <form action="/search" class="search_form clean" method="get" id="top-search"> | |
67 | - <input name="query" size="15" value="<%=_('Search...')%>" | |
68 | - onfocus="this.form.className='focused'; | |
69 | - if(this.value=='<%=_('Search...')%>'){this.value=''}" | |
70 | - onblur="this.form.className=''; | |
71 | - if(/^\s*$/.test(this.value)){ | |
72 | - this.value='<%=_('Search...')%>'; | |
73 | - this.form.className='clean' | |
74 | - }" /> | |
68 | + <form action="/search" class="search_form" method="get" class="clean"> | |
69 | + <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | |
75 | 70 | <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> |
71 | + <%= javascript_tag 'jQuery("#user form input").hint();' %> | |
76 | 72 | </form> |
77 | 73 | </div><!-- end id="user" --> |
78 | 74 | ... | ... |
... | ... | @@ -0,0 +1,28 @@ |
1 | +<div id="balloon"> | |
2 | + <table class='profile-info'> | |
3 | + <tr> | |
4 | + <td><div class='profile-info-picture'><%= profile_image(@profile, :thumb) %></div></td> | |
5 | + <td> | |
6 | + <strong><%= link_to(@profile.name, url_for(@profile.url)) %></strong><br/> | |
7 | + <% unless @profile.contact_email.nil? %> | |
8 | + <strong><%= _('E-Mail: ') + @profile.contact_email %></strong><br/> | |
9 | + <% end %> | |
10 | + <% unless @profile.contact_phone.nil? %> | |
11 | + <strong><%= _('Phone(s): ') + @profile.contact_phone %></strong><br/> | |
12 | + <% end %> | |
13 | + <% unless @profile.region.nil? %> | |
14 | + <strong><%= _('Location: ') + @profile.region.name %></strong><br/> | |
15 | + <% end %> | |
16 | + <% unless @profile.address.nil? %> | |
17 | + <strong><%= _('Address: ') + @profile.address %></strong><br/> | |
18 | + <% end %> | |
19 | + <% unless @profile.products.empty? %> | |
20 | + <strong><%= _('Products/Services: ') + @profile.products.map{|i| link_to(i.name, :controller => 'manage_products', :profile => @profile.identifier, :action => 'show', :id => i.id)}.join(', ') %></strong><br/> | |
21 | + <% end %> | |
22 | + <% if @profile.respond_to?(:distance) and !@profile.distance.nil? %> | |
23 | + <strong><%= _('Distance: ') + "%.2f%" % @profile.distance %></strong><br/> | |
24 | + <% end %> | |
25 | + </td> | |
26 | + </tr> | |
27 | + </table> | |
28 | +</div> | ... | ... |
app/views/search/_article.rhtml
1 | -<li class="<%= icon_for_article(article) %>"> | |
2 | - <strong><%= link_to(article.title, article.view_url) %></strong> | |
3 | - <div class="item_meta"> | |
4 | - <% if article.last_changed_by %> | |
5 | - <span class="cat_item_by"> | |
6 | - <%= _('by %s') % link_to(article.last_changed_by.name, article.last_changed_by.url) %> | |
7 | - </span> | |
8 | - <% end %> | |
9 | - <span class="cat_item_update"><%= _('Last update: %s.') % show_date(article.updated_at) %></span> | |
1 | +<li class="search-article-item article-item"> | |
2 | + <%= link_to(article.title, article.url, :class => "search-result-title") %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => article %> | |
10 | 5 | </div> |
6 | + <div class="search-content-second-column"> | |
7 | + | |
8 | + </div> | |
9 | + | |
10 | + <div style="clear:both"></div> | |
11 | 11 | </li> | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<% article = article_author %> | |
2 | + | |
3 | +<div class="search-article-author"> | |
4 | + <div class="search-article-author-name"> | |
5 | + <span class="search-field-label"><%= _("Author") %></span> | |
6 | + <%= link_to_profile article.profile.name, article.profile.identifier %> | |
7 | + </div> | |
8 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<div class="search-article-categories"> | |
2 | + <span class="search-field-label"><%= _('Categories') %></span> | |
3 | + <span class="search-article-categories-container"> | |
4 | + <% article_categories.each do |category| %> | |
5 | + <%= link_to_category category, false, :class => "search-article-category" %> | |
6 | + <% end %> | |
7 | + <span class="search-field-none"><%= _('None') if article_categories.empty? %></span> | |
8 | + </span> | |
9 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<% article = article_common %> | |
2 | +<% show_description = true if show_description.nil? %> | |
3 | + | |
4 | +<%= render :partial => 'article_author', :object => article %> | |
5 | +<%= render :partial => 'article_description', :object => article if show_description %> | |
6 | +<%= render :partial => 'article_tags', :object => article.tags %> | |
7 | +<%= render :partial => 'article_categories', :object => article.categories %> | |
8 | +<%= render :partial => 'article_last_change', :object => article %> | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<% article = article_description %> | |
2 | + | |
3 | +<div class="search-article-description"> | |
4 | + <span class="search-field-label"><%= _("Description") %></span> | |
5 | + <% if !article.body.blank? %> | |
6 | + <% body_stripped = strip_tags(article.body.to_s) %> | |
7 | + <span class="search-article-body"><%= excerpt(body_stripped, body_stripped.first(3), 200) %></span> | |
8 | + <% else %> | |
9 | + <span class="search-field-none"><%= _('None') %></span> | |
10 | + <% end %> | |
11 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<% article = article_last_change %> | |
2 | + | |
3 | +<div class="search-article-author-changes"> | |
4 | + <% if article.last_changed_by && article.last_changed_by != article.profile %> | |
5 | + <span><%= _('by %s') % link_to(article.last_changed_by.name, article.last_changed_by.url) %> <%= _(' at %s.') % show_date(article.updated_at) %></span> | |
6 | + <% else %> | |
7 | + <span><%= _('Last update: %s.') % show_date(article.updated_at) %></span> | |
8 | + <% end %> | |
9 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<div class="search-article-tags"> | |
2 | + <span class="search-field-label"><%= _('Tags') %></span> | |
3 | + <span class="search-article-tags-container"> | |
4 | + <% article_tags.each do |tag| %> | |
5 | + <%= link_to_tag tag, :class => "search-article-tag" %> | |
6 | + <% end %> | |
7 | + <span class="search-field-none"><%= _('None') if article_tags.empty? %></span> | |
8 | + </span> | |
9 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +<li class="search-blog article-item"> | |
2 | + <%= link_to blog.title, blog.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => blog %> | |
5 | + </div> | |
6 | + <div class="search-content-second-column"> | |
7 | + <div class="search-blog-items"> | |
8 | + <span class="search-field-label"><%= _("Last posts") %></span> | |
9 | + <% r = blog.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
10 | + <% r.each do |a| %> | |
11 | + <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %> | |
12 | + <% end %> | |
13 | + <span class="search-field-none"><%= _('None') if r.empty? %></span> | |
14 | + </div> | |
15 | + | |
16 | + <%= render :partial => 'article_author', :object => blog %> | |
17 | + <%= render :partial => 'article_tags', :object => blog.tags %> | |
18 | + <%= render :partial => 'article_categories', :object => blog.categories %> | |
19 | + <%= render :partial => 'article_last_change', :object => blog %> | |
20 | + </div> | |
21 | + | |
22 | + <div style="clear: both;"/></div> | |
23 | +</li> | ... | ... |
app/views/search/_display_results.rhtml
1 | 1 | <div id="search-results" class="<%= 'only-one-result-box' if @results.size == 1 %>"> |
2 | 2 | |
3 | -<% | |
4 | - pos2 = :odd # allow to format in a two columns layout | |
5 | - pos3 = 3 # allow to format in a thre columns layout | |
6 | -%> | |
7 | -<% @order.each do |name| %> | |
8 | - <% results = @results[name] %> | |
9 | - <% | |
10 | - pos3 += 1; pos3 = 1 if pos3 > 3 | |
11 | - pos2==:odd ? pos2=:even : pos2=:odd | |
12 | - %> | |
13 | - <% if !results.nil? and !results.empty? %> | |
14 | - <div class="search-results-<%= name %> search-results-box <%= pos2 %> <%= 'col%s_of3' % pos3.to_s %>"> | |
15 | - <% if @controller.action_name != 'assets' %> | |
16 | - <% if @results.size != 1 %> | |
17 | - <h3> | |
18 | - <%= @names[name] %> | |
19 | - </h3> | |
20 | - <% end %> | |
21 | - <%# FIXME: don't hardcode an asset like this %> | |
22 | - <% if name == :most_commented_articles %> | |
23 | - <%= link_to( results.respond_to?(:total_entries) ? _('see all (%d)') % results.total_entries : _('see all...'), | |
24 | - params.merge(:action => 'index', | |
25 | - :asset => 'articles' ), | |
26 | - :class => 'see-more' ) if @results.size > 1 %> | |
27 | - | |
28 | - <% else %> | |
29 | - <%= link_to( results.respond_to?(:total_entries) ? _('see all (%d)') % results.total_entries : _('see all...'), | |
30 | - params.merge(:action => 'index', | |
31 | - :asset => name ), | |
32 | - :class => 'see-more' ) if @results.size > 1 %> | |
3 | + <% @order.each do |name| %> | |
4 | + <% results = @results[name] %> | |
5 | + <% if !results.nil? and !results.empty? %> | |
6 | + <div class="search-results-<%= name %> search-results-box"> | |
7 | + | |
8 | + <% if @results.size > 1 %> | |
9 | + <h3><%= @names[name] %></h3> | |
10 | + <%= link_to(results.respond_to?(:total_entries) ? _('see all (%d)') % results.total_entries : _('see all...'), | |
11 | + params.merge(:action => name), :class => 'see-more' ) %> | |
33 | 12 | <% end %> |
34 | - <% end %> | |
35 | - <% partial = partial_for_class results.first.class %> | |
36 | - <div class="search-results-innerbox search-results-type-<%= partial %> <%= 'common-profile-list-block' if partial == 'profile' %>"> | |
37 | - <div class="search-results-innerbox2"><!-- the innerbox2 is a workarround for MSIE --> | |
38 | - <ul> | |
39 | - <% hit_pos = 0 %> | |
40 | - <% results.each do |hit| %> | |
41 | - <% next if hit.respond_to?(:visible) && !hit.visible? %> | |
42 | - <%= render :partial => partial_for_class(hit.class), | |
43 | - | |
44 | - :object => hit, | |
45 | - :locals => { :pos => ( hit_pos += 1 ) } %> | |
46 | - <% end %> | |
47 | - </ul> | |
48 | - <hr /> | |
49 | - </div><!-- end class="search-results-innerbox2" --> | |
50 | - </div><!-- end class="search-results-innerbox" --> | |
51 | - </div><!-- end class="search-results-<%= name %>" --> | |
52 | - <% else %> | |
53 | - <div class="search-results-<%= name %> search-results-empty search-results-box <%= pos2 %> <%= 'col%s_of3' % pos3.to_s %>"> | |
54 | - <% if @controller.action_name != 'assets' %> | |
55 | - <% if @results.size != 1 %> | |
13 | + | |
14 | + <% partial = partial_for_class(results.first.class.class_name.constantize) %> | |
15 | + <div class="search-results-innerbox search-results-type-<%= partial %> <%= 'common-profile-list-block' if partial == 'profile' %>"> | |
16 | + <div class="search-results-innerbox2"><!-- the innerbox2 is a workarround for MSIE --> | |
17 | + <ul> | |
18 | + <% results.each do |hit| %> | |
19 | + <%= render :partial => partial_for_class(hit.class), :object => hit %> | |
20 | + <% end %> | |
21 | + </ul> | |
22 | + <hr /> | |
23 | + </div><!-- end class="search-results-innerbox2" --> | |
24 | + </div><!-- end class="search-results-innerbox" --> | |
25 | + | |
26 | + </div><!-- end class="search-results-<%= name %>" --> | |
27 | + <% else %> | |
28 | + <div class="search-results-<%= name %> search-results-empty search-results-box"> | |
29 | + <% if @results.size > 1 %> | |
56 | 30 | <h3><%= @names[name] %></h3> |
57 | 31 | <% end %> |
58 | - <% end %> | |
59 | - <div class="search-results-innerbox search-results-type-empty"> | |
60 | - <div> <%= _('None') %> </div> | |
61 | - <hr /> | |
62 | - </div><!-- end class="search-results-innerbox" --> | |
63 | - </div><!-- end class="search-results-<%= name %>" --> | |
32 | + <div class="search-results-innerbox search-results-type-empty"> | |
33 | + <div> <%= _('None') %> </div> | |
34 | + <hr /> | |
35 | + </div><!-- end class="search-results-innerbox" --> | |
36 | + </div><!-- end class="search-results-<%= name %>" --> | |
37 | + <% end %> | |
64 | 38 | <% end %> |
65 | -<% end %> | |
66 | - | |
67 | -<br style="clear:both" /> | |
39 | + | |
40 | + <div style="clear:both"></div> | |
68 | 41 | </div><!-- end id="search-results" --> |
69 | 42 | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<%= render :partial => 'text_article', :object => enterprise_homepage %> | ... | ... |
app/views/search/_event.rhtml
1 | -<li class="<%= icon_for_article(event) %>"> | |
2 | - <strong><%= link_to(event.title, event.url) %></strong> | |
3 | - <div class="item_meta"> | |
4 | - <%= show_period(event.start_date, event.end_date) %> | |
1 | +<li class="search-event-item article-item"> | |
2 | + <%= link_to(event.title, event.url, :class => "search-result-title") %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => event %> | |
5 | 5 | </div> |
6 | + <div class="search-content-second-column"> | |
7 | + <% if event.start_date %> | |
8 | + <div class="searc-article-event-date"> | |
9 | + <span class="search-field-label"><%= _('Start date') %></span> | |
10 | + <span class="article-item-date"><%= event.start_date %></span> | |
11 | + </div> | |
12 | + <% end %> | |
13 | + <% if event.end_date %> | |
14 | + <div class="searc-article-event-date"> | |
15 | + <span class="search-field-label"><%= _('End date') %></span> | |
16 | + <span class="article-item-date"><%= event.end_date %></span> | |
17 | + </div> | |
18 | + <% end %> | |
19 | + | |
20 | + <%= render :partial => 'article_common', :object => event %> | |
21 | + </div> | |
22 | + | |
23 | + <div style="clear: both;"/></div> | |
6 | 24 | </li> | ... | ... |
... | ... | @@ -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,20 @@ |
1 | +<li class="search-folder-item article-item"> | |
2 | + <%= link_to folder.title, folder.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => folder %> | |
5 | + </div> | |
6 | + <div class="search-content-second-column"> | |
7 | + <div class="search-folder-items"> | |
8 | + <span class="search-field-label"><%= _("Last items") %></span> | |
9 | + <% r = folder.children.last(3) %> | |
10 | + <% r.each do |a| %> | |
11 | + <%= link_to a.title, a.view_url, :class => 'search-folder-sample-item '+icon_for_article(a) %> | |
12 | + <% end %> | |
13 | + <span class="search-field-none"><%= _('None') if r.empty? %></span> | |
14 | + </div> | |
15 | + | |
16 | + <%= render :partial => 'article_common', :object => folder %> | |
17 | + </div> | |
18 | + | |
19 | + <div style="clear:both"></div> | |
20 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +<li class="search-forum-item article-item"> | |
2 | + <%= link_to forum.title, forum.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => forum %> | |
5 | + </div> | |
6 | + <div class="search-content-second-column"> | |
7 | + <div class="search-forum-items"> | |
8 | + <span class="search-field-label"><%= _("Last topics") %></span> | |
9 | + <% r = forum.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
10 | + <% r.each do |a| %> | |
11 | + <%= link_to a.title, a.view_url, :class => 'search-forum-sample-item '+icon_for_article(a) %> | |
12 | + <% end %> | |
13 | + <span class="search-field-none"><%= _('None') if r.empty? %></span> | |
14 | + </div> | |
15 | + | |
16 | + <%= render :partial => 'article_common', :object => forum %> | |
17 | + </div> | |
18 | + | |
19 | + <div style="clear:both"></div> | |
20 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +<li class="search-gallery article-item"> | |
2 | + <%= link_to gallery.title, gallery.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => gallery %> | |
5 | + </div> | |
6 | + <div class="search-content-second-column"> | |
7 | + <%= render :partial => 'article_common', :object => gallery %> | |
8 | + </div> | |
9 | + | |
10 | + <div style="clear: both"></div> | |
11 | +</li> | |
12 | + | ... | ... |
app/views/search/_google_maps.rhtml
1 | -<%= content_tag('script', '', :src => GoogleMaps.api_url(environment.default_hostname), :type => 'text/javascript') %> | |
2 | - | |
3 | - | |
1 | +<div style="clear: both;"/></div> | |
4 | 2 | <div style='text-align: center;'> |
5 | 3 | <div id="map"></div> |
6 | 4 | </div> |
7 | 5 | |
8 | -<script type='text/javascript'> | |
9 | -var points = {}; | |
10 | - | |
11 | -function putMarker(lat, lng, title, summary) { | |
12 | - var point_str = lat + ":" + lng; | |
13 | - | |
14 | - if (points[point_str]) { | |
15 | - lng += (Math.random() - 0.5) * 0.02; | |
16 | - lat += (Math.random() - 0.5) * 0.02; | |
17 | - } else { | |
18 | - points[point_str] = true; | |
19 | - } | |
20 | - | |
21 | - var point = new GLatLng(lat, lng); | |
22 | - var options = { 'title' : title, 'icon' : icon }; | |
23 | - var marker = new GMarker(point, options); | |
24 | - map.addOverlay(marker); | |
25 | - GEvent.addListener(marker, 'click', function() { | |
26 | - map.openInfoWindowHtml(point, summary); | |
27 | - }); | |
28 | - bounds.extend(point); | |
29 | -} | |
30 | - | |
31 | -window.unload = function() { | |
32 | - GUnload(); | |
33 | -}; | |
34 | - | |
35 | -if (GBrowserIsCompatible()) { | |
36 | - var map = new GMap2(document.getElementById("map")); | |
37 | - | |
38 | - new GKeyboardHandler(map); | |
39 | - map.addControl(new GLargeMapControl()); | |
40 | - map.addControl(new GMapTypeControl()); | |
41 | - | |
42 | - centerPoint = new GLatLng(-15.0, -50.1419); | |
43 | - map.setCenter(centerPoint, <%= GoogleMaps.initial_zoom.to_json %>); | |
44 | - var bounds = new GLatLngBounds(); | |
45 | - | |
46 | - var baseIcon = new GIcon(); | |
47 | - baseIcon.iconSize=new GSize(32,32); | |
48 | - baseIcon.shadowSize=new GSize(36,32); | |
49 | - baseIcon.iconAnchor=new GPoint(16,32); | |
50 | - baseIcon.infoWindowAnchor=new GPoint(16,0); | |
51 | - <% | |
52 | - icon = default_or_themed_icon("/images/icons-map/enterprise.png") | |
53 | - icon_shadow = default_or_themed_icon("/images/icons-map/enterprise_shadow.png") | |
54 | - %> | |
55 | - var icon = new GIcon(baseIcon, "<%= icon %>", null, "<%= icon_shadow %>"); | |
6 | +<%= content_tag('script', '', :src => GoogleMaps.api_url(environment.default_hostname), :type => 'text/javascript') %> | |
7 | +<%= javascript_include_tag('google_maps') %> | |
56 | 8 | |
57 | 9 | <% |
58 | - @results.each do |name,results| | |
59 | - results.each do |item| | |
60 | - if item.lat && item.lng | |
61 | - %> | |
62 | - putMarker(<%= item.lat.to_json %>, <%= item.lng.to_json %>, <%= item.name.to_json %>, <%= display_item_map_info(item).to_json %>); | |
63 | - <% | |
64 | - end | |
65 | - end | |
66 | - end | |
10 | + icon = default_or_themed_icon("/images/icons-map/enterprise.png") | |
11 | + icon_shadow = default_or_themed_icon("/images/icons-map/enterprise_shadow.png") | |
67 | 12 | %> |
68 | -} | |
69 | 13 | |
70 | - map.setZoom(map.getBoundsZoomLevel(bounds)); | |
71 | - map.setCenter(bounds.getCenter()); | |
14 | +<script type='text/javascript'> | |
15 | + mapLoad(<%= GoogleMaps.initial_zoom.to_json %>); | |
16 | + | |
17 | + mapBaseIcon = new GIcon(); | |
18 | + mapBaseIcon.iconSize=new GSize(32,32); | |
19 | + mapBaseIcon.shadowSize=new GSize(36,32); | |
20 | + mapBaseIcon.iconAnchor=new GPoint(16,32); | |
21 | + mapBaseIcon.infoWindowAnchor=new GPoint(16,0); | |
22 | + icon = new GIcon(mapBaseIcon, "<%= icon %>", null, "<%= icon_shadow %>"); | |
23 | + | |
24 | + <% @results.each do |name,results| %> | |
25 | + <% results.each do |item| %> | |
26 | + <% if item.lat && item.lng %> | |
27 | + mapPutMarker(<%= item.lat.to_json %>, <%= item.lng.to_json %>, <%= item.name.to_json %>, icon, | |
28 | + '<%= url_for(:controller => :map_balloon, :action => name.to_s.singularize, :id => item.id) %>'); | |
29 | + <% end %> | |
30 | + <% end %> | |
31 | + <% end %> | |
32 | + | |
33 | + mapCenter(); | |
72 | 34 | </script> | ... | ... |
... | ... | @@ -0,0 +1,47 @@ |
1 | +<div class="search-image-container"> | |
2 | + | |
3 | + <% if image.is_a? UploadedFile %> | |
4 | + <% extension = image.filename[(image.filename.rindex('.')+1)..-1].downcase %> | |
5 | + <% if ['jpg', 'jpeg', 'gif', 'png', 'tiff', 'svg'].include? extension %> | |
6 | + <%= link_to '', image.view_url, :class => "search-image-pic", :style => 'background-image: url(%s)'% image.public_filename(:thumb) %> | |
7 | + <% if image.width && image.height %> | |
8 | + <% javascript_tag do %> | |
9 | + image = jQuery('script').last().parent().find('.search-image-pic'); | |
10 | + des_width = parseInt(image.css('width')); | |
11 | + des_height = parseInt(image.css('height')); | |
12 | + | |
13 | + width = <%= image.width %>; | |
14 | + height = <%= image.height %>; | |
15 | + scale_factor = width > height ? des_width/width : des_height/height; | |
16 | + | |
17 | + image.css({'width' : scale_factor*width +'px', 'height' : scale_factor*height+'px'}); | |
18 | + <% end %> | |
19 | + <% end %> | |
20 | + <% elsif ['pdf'].include? extension %> | |
21 | + <%= link_to '', image.view_url, :class => 'search-image-pic icon-application-pdf' %> | |
22 | + <% elsif ['doc', 'docx', 'odt', 'rtf', 'txt', 'html', 'htm'].include? extension %> | |
23 | + <%= link_to '', image.view_url, :class => 'search-image-pic icon-application-vnd-oasis-opendocument-text' %> | |
24 | + <% elsif ['xls', 'xlsx', 'ods', 'csv', 'tsv', 'tab'].include? extension %> | |
25 | + <%= link_to '', image.view_url, :class => 'search-image-pic icon-application-vnd-oasis-opendocument-spreadsheet' %> | |
26 | + <% end %> | |
27 | + <% elsif image.is_a? Gallery %> | |
28 | + <div class="search-gallery-items"> | |
29 | + <% r = image.children.find(:all, :order => :updated_at, :conditions => ['type = ?', 'UploadedFile']).last(3) %> | |
30 | + <% if r.length > 0 %> | |
31 | + <% r.each do |i| %> | |
32 | + <%= link_to '', i.view_url, :class => "search-image-pic", :style => 'background-image: url(%s)'% i.public_filename(:thumb) %> | |
33 | + <% end %> | |
34 | + <% else %> | |
35 | + <div class="search-no-image"><%= _('No image') %></div> | |
36 | + <% end %> | |
37 | + </div> | |
38 | + <% elsif image.is_a? Product %> | |
39 | + <% if image.image %> | |
40 | + <%= link_to '', product_path(image), :class => "search-image-pic", :style => 'background-image: url(%s)'% image.default_image(:thumb) %> | |
41 | + <% else %> | |
42 | + <div class="search-no-image"><%= _('No image') %></div> | |
43 | + <% end %> | |
44 | + <% else %> | |
45 | + <div class="search-content-type-icon icon-content-<%=image.class.to_s.underscore.dasherize%>"></div> | |
46 | + <% end %> | |
47 | +</div> | ... | ... |
app/views/search/_product.rhtml
1 | -<%# FIXME add more information %> | |
2 | - | |
3 | -<% | |
4 | -product_item_pos = 0 if ! product_item_pos | |
5 | -product_item_pos += 1 | |
6 | -%> | |
7 | - | |
8 | 1 | <% extra_content = @plugins.map(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> |
9 | 2 | <% extra_properties = @plugins.map(:asset_product_properties, product)%> |
10 | 3 | |
11 | -<li class="product-item <%= ( pos % 2 == 0 ) ? 'odd' : 'even' %>"> | |
12 | - <%= link_to_product product, :class => 'product-pic', :style => 'background-image:url(%s)' % product.default_image(:minor) %> | |
13 | - <strong> | |
14 | - <%= link_to_product product %> | |
15 | - </strong> | |
16 | - <ul> | |
17 | - <li> <%= _('Price: %s') % (product.price ? product.price : _('Not informed')) %> </li> | |
18 | - <% if product.enterprise && product.display_supplier_on_search? %> | |
19 | - <li> <%= _('Supplier: %s') % link_to_homepage(product.enterprise.name, product.enterprise.identifier) %> </li> | |
20 | - <% end %> | |
4 | +<li class="search-product-item"> | |
5 | + <div class="search-product-item-first-column"> | |
6 | + <%= render :partial => 'image', :object => product %> | |
21 | 7 | |
22 | - <li> <%= _('Category:') + ' ' + link_to_product_category(product.product_category) %> </li> | |
8 | + <% if product.available %> | |
9 | + <% if product.price && product.price > 0 %> | |
10 | + <% has_discount = product.discount && product.discount > 0 %> | |
11 | + <% if product.price %> | |
12 | + <span class="search-product-price-textid"><%=_("from") if has_discount %></span><%= price_span(product.price, :class => "search-product-price " + (has_discount ? 'with-discount' : '')) %> | |
13 | + <% if has_discount %> | |
14 | + <span class="search-product-price-textid"><%=_("by")%></span><%= price_span(product.price_with_discount, :class => "search-product-price") %> | |
15 | + <% end %> | |
16 | + <% if product.unit %> | |
17 | + <span class="search-product-unit"> <%= _('/') %> <%= product.unit.name %></span> | |
18 | + <% end %> | |
19 | + <% end %> | |
20 | + <div class="search-product-inputs-info"> | |
21 | + <% if product.inputs.count > product.inputs.collect(&:is_from_solidarity_economy).count(nil) %> | |
22 | + <% se_i = t_i = 0 %> | |
23 | + <% product.inputs.each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy } %> | |
24 | + <% p = case (se_i.to_f/t_i)*100 when 0..24.999 then ["0", _("0%")]; when 25..49.999 then ["25", _("25%")]; when 50..74.999 then ["50", _("50%")]; when 75..100 then ["75", _("100%")]; end %> | |
25 | + <div class="search-product-percentage-from-solidarity-economy search-product-ecosol-percentage-icon-<%=p[0]%>" title="<%=_('Percentage of inputs from solidarity economy')%>"> | |
26 | + <%= p[1] %> | |
27 | + </div> | |
28 | + <% end %> | |
23 | 29 | |
24 | - <% extra_properties.each do |property| %> | |
25 | - <li><%= property[:name] + ': ' + instance_eval(&property[:content]) %></li> | |
30 | + <% if product.inputs.count == product.inputs.collect(&:has_price_details?).count(true) %> | |
31 | + <% title = product.inputs.map{ |i| | |
32 | + '<div class="search-product-input-dots-to-price">' + | |
33 | + '<div class="search-product-input-name">' + i.product_category.name + '</div>' + | |
34 | + price_span(i.price_per_unit*i.amount_used, :class => 'search-product-input-price') + | |
35 | + '</div>' }.join('') %> | |
36 | + <%= link_to_function _("Open Price"), '', :title => title, :class => "search-product-price-details" %> | |
37 | + <% end %> | |
38 | + </div> | |
39 | + <% end %> | |
40 | + <% else %> | |
41 | + <span class="product-not-available"><%= _('Not available') %></div> | |
26 | 42 | <% end %> |
27 | - </ul> | |
43 | + | |
44 | + </div> | |
45 | + <div class="search-product-item-second-column"> | |
46 | + <%= link_to_product product, :class => 'search-result-title' %> | |
47 | + <div class="search-product-supplier"> | |
48 | + <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage(product.enterprise.name, product.enterprise.identifier) %> | |
49 | + </div> | |
50 | + <div class="search-product-description"> | |
51 | + <% if product.description %> | |
52 | + <% desc_stripped = strip_tags(product.description) %> | |
53 | + <span class="search-field-label"><%= _('Description') %> </span><%= excerpt(desc_stripped, desc_stripped.first(3), 300) %> | |
54 | + <% end %> | |
55 | + </div> | |
56 | + </div> | |
57 | + <div class="search-product-item-third-column"> | |
58 | + <div class="search-product-region"> | |
59 | + <% if product.enterprise.region %> | |
60 | + <span class="search-field-label"><%= _('City') %></span> | |
61 | + <br /><%= city_with_state(product.enterprise.region) %> | |
62 | + <% end %> | |
63 | + </div> | |
64 | + <div class="search-product-qualifiers"> | |
65 | + <% if product.product_qualifiers.count > 0 %> | |
66 | + <span class="search-field-label"><%= _('Qualifiers') %></span> | |
67 | + <% product.product_qualifiers.each do |pq| %> | |
68 | + <% if pq.qualifier %> | |
69 | + <span class="search-product-qualifier"><%= pq.qualifier.name + (pq.certifier.nil? ? _(";") : '') %></span> | |
70 | + <% end %> | |
71 | + <% if pq.certifier %> | |
72 | + <span class="search-product-certifier"> <%= _('cert. ') + pq.certifier.name + _(";") %></span> | |
73 | + <% end %> | |
74 | + <% end %> | |
75 | + <% end %> | |
76 | + </div> | |
77 | + </div> | |
28 | 78 | |
29 | 79 | <%= extra_content.join('\n') %> |
80 | + <% extra_properties.each do |property| %> | |
81 | + <div><%= property[:name] + ': ' + instance_eval(&property[:content]) %></div> | |
82 | + <% end %> | |
30 | 83 | |
84 | + <br /><br /> | |
31 | 85 | </li> | ... | ... |
app/views/search/_product_categories_menu.rhtml
... | ... | @@ -1,42 +0,0 @@ |
1 | -<% if @product_category %> | |
2 | - <h3 class="current-cat-path"> | |
3 | - <%= @product_category.hierarchy.map {|cat| ((cat == @product_category) ? content_tag('span', cat.name) : link_to((cat.name), params.merge({:product_category => cat.id}))) }.join(' → ') %> | |
4 | - </h3> | |
5 | -<% end %> | |
6 | - | |
7 | -<% if product_categories_menu %> | |
8 | - | |
9 | -<div id="product-categories-menu"> | |
10 | - <ul> | |
11 | - <% if product_categories_menu.empty? %> | |
12 | - <% if @product_category %> | |
13 | - <li class="cat-empty"> <%= _('There is no sub-categories for %s.') % @product_category.name %> </li> | |
14 | - <% else %> | |
15 | - <li class="cat-empty"> <%= _('There is no categories.') %> </li> | |
16 | - <% end %> | |
17 | - <% end %> | |
18 | - <% product_categories_menu.each do |cat, hits, childs| %> | |
19 | - <li class="cat-parent" > | |
20 | - <%= link_to( | |
21 | - cat.name + " " + content_tag('small', "(#{hits})"), | |
22 | - params.merge({:product_category => cat.id}) | |
23 | - ) %> | |
24 | - <% if !childs.blank? %> | |
25 | - <div> | |
26 | - <ul> | |
27 | - <% childs.each do |child, child_hits| %> | |
28 | - <li class="cat-child"> <%= link_to( | |
29 | - child.name + " " + content_tag('small', "(#{child_hits})"), | |
30 | - params.merge({:product_category => child.id}) | |
31 | - ) %> </li> | |
32 | - <% end %> | |
33 | - </ul> | |
34 | - </div> | |
35 | - <% end %> | |
36 | - </li> | |
37 | - <% end %> | |
38 | - </ul> | |
39 | -</div> | |
40 | - | |
41 | -<% end %> | |
42 | - |
app/views/search/_profile.rhtml
1 | -<%= profile_image_link profile, :portrait %> | |
1 | +<li class="search-profile-item"> | |
2 | + <% if @empty_query or @results.size > 1 or !profile.enterprise? %> | |
3 | + <%= profile_image_link profile, :portrait, 'div' %> | |
4 | + <% else %> | |
5 | + <div class="search-enterprise-item"> | |
6 | + <div class="search-enterprise-item-column-left"> | |
7 | + <%= profile_image_link profile, :portrait, 'div' %> | |
8 | + </div> | |
9 | + <div class="search-enterprise-item-column-right"> | |
10 | + <%= link_to_homepage(profile.name, profile.identifier, :class => "search-result-title") %> | |
11 | + <div class="search-enterprise-description"> | |
12 | + <% if profile.description %> | |
13 | + <% body_stripped = strip_tags(profile.description) %> | |
14 | + <% elsif profile.home_page and profile.home_page.body %> | |
15 | + <% body_stripped = strip_tags(profile.home_page.body) %> | |
16 | + <% end %> | |
17 | + <%= excerpt(body_stripped, body_stripped.first(3), 200) if body_stripped %> | |
18 | + </div> | |
19 | + <div class="search-enterprise-region"> | |
20 | + <span class="search-enterprise-region-label"><%= _("City") %></span> | |
21 | + <% if profile.region %> | |
22 | + <span class="search-enterprise-region-name"><%= city_with_state(profile.region) %></span> | |
23 | + <% else %> | |
24 | + <% end %> | |
25 | + </div> | |
26 | + <% if !profile.description.blank? %> | |
27 | + <div><%= profile.description %></div><br /> | |
28 | + <% end %> | |
29 | + | |
30 | + <div class="search-enterprise-categorization"> | |
31 | + <% profile.top_level_categorization.each do |parent, children| %> | |
32 | + <div class="search-enterprise-category-<%=parent.id%> search-enterprise-category"> | |
33 | + <span class="search-enterprise-categorization-parent"><%= parent.name %></span> | |
34 | + <span class="search-enterprise-categorization-children"><%= children.collect(&:name).join(', ') %></span> | |
35 | + </div> | |
36 | + <% end %> | |
37 | + </div> | |
38 | + </div> | |
39 | + <hr class="clearfix" /> | |
40 | + </div> | |
41 | + <% end %> | |
42 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
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 | + <%= label_total_found(@asset, @results[@asset].total_entries) %> | |
5 | + <% if params[:display] != 'map' %> | |
6 | + <span class="current-page"><%= _("Showing page %s of %s") % [@results[@asset].current_page, @results[@asset].total_pages] %></span> | |
7 | + <% end %> | |
8 | + </div> | |
9 | + | |
10 | + <div class="search-results-header-facets-order-by"> | |
11 | + <%= facets_unselect_menu(@asset) %> | |
12 | + <%= order_by(@asset) if params[:display] != 'map' %> | |
13 | + </div> | |
14 | + <% else %> | |
15 | + <div id='search-filter-title'><%= @filter_title if @filter_title %></div> | |
16 | + <% end %> | |
17 | + | |
18 | + <div style="clear: both"></div> | |
19 | +</div> | ... | ... |
app/views/search/_search_form.rhtml
1 | 1 | <div class='search-form'> |
2 | -<% simple_search = false unless defined? simple_search %> | |
3 | 2 | |
4 | -<% form_tag( { :controller => 'search', :action => 'index', :asset => nil, :category_path => ( @category ? @category.explode_path : [] ) }, | |
5 | - :method => 'get', :class => 'search_form' ) do %> | |
6 | - <%= '<h3>%s</h3>' % form_title if defined? form_title %> | |
7 | - | |
8 | - <%= hidden_field_tag :display, params[:display] %> | |
9 | - | |
10 | - <%= hidden_field_tag :asset, params[:asset] %> | |
11 | - | |
12 | - <div class="search-field"> | |
13 | - <span class="formfield"> | |
14 | - <%= text_field_tag 'query', @query, :id => ( lightbox? ? 'popup-search-input' : '' ), :size => 50 %> | |
15 | - <%= javascript_tag 'setTimeout("$(\"popup-search-input\").focus()", 10 )' if lightbox? %> | |
16 | - </span> | |
17 | - <%= submit_button(:search, _('Search'), :name => :search_whole_site_no) %> | |
18 | - <% if @category %> | |
19 | - <%= submit_button(:search, _('Search in whole site'), :name => :search_whole_site_yes) %> | |
20 | - <% end %> | |
21 | - </div> | |
22 | - | |
23 | - <div id='advanced-search-options' style="display: <%= simple_search ? 'none' : 'block' %>"> | |
24 | - <div class="search-options search-within"> | |
25 | - <h4><%= _('Search within:') %></h4> | |
26 | - <br style='clear:left'/> | |
27 | - <div> | |
28 | - <span class="formfield"> | |
29 | - <%= select_city %> | |
30 | - </span> | |
31 | - <span class="formfield"> | |
32 | - <%= labelled_select(_('Distance:'), 'radius', :first, :last, nil, [15, 30, 50, 100, 150, 200, 300, 400, 500, 1000].map{|n|[n, n.to_s + 'km']}) %> | |
33 | - </span> | |
3 | + <% form_tag( { :controller => 'search', :action => @asset ? @asset : 'index', :asset => nil, :category_path => ( @category ? @category.explode_path : [] ) }, | |
4 | + :method => 'get', :class => 'search_form' ) do %> | |
5 | + | |
6 | + <%= hidden_field_tag :display, params[:display] %> | |
7 | + | |
8 | + <div class="search-field"> | |
9 | + <span class="formfield"> | |
10 | + <%= text_field_tag 'query', @query, :id => 'search-input', :size => 50 %> | |
11 | + <%= javascript_tag "jQuery('#search-input').attr('title', \"#{hint}\").hint()" if defined?(hint) %> | |
12 | + <%= javascript_tag "jQuery('.search_form').submit(function() { | |
13 | + if (jQuery('#search-input').val().length < 3) { | |
14 | + jQuery('#search-empty-query-error').slideDown(200).delay(2500).slideUp(200); | |
15 | + return false; | |
16 | + } | |
17 | + });" %> | |
18 | + </span> | |
19 | + | |
20 | + <%= submit_button(:search, _('Search')) %> | |
21 | + | |
22 | + <div id="search-empty-query-error"> | |
23 | + <%= _("Type more than 2 characters to start a search") %> | |
34 | 24 | </div> |
35 | - </div><!-- fim class="search-options" --> | |
36 | - | |
37 | - <div class="search-options search-for"> | |
38 | - <h4><%= _('Search for:') %></h4> | |
39 | - <ul> | |
40 | - <% @search_in.map { |t,n| [t,getterm(n)] } . | |
41 | - sort_by(&:last).each do |thing, name| %> | |
42 | - <li> | |
43 | - <%= labelled_check_box name, 'find_in[]', thing.to_s, @searching[thing.to_sym] %> | |
44 | - </li> | |
45 | - <% end %> | |
46 | - </ul> | |
47 | - <br style="clear:both" /> | |
48 | - </div><!-- fim class="search-options" --> | |
49 | - </div><!-- end id="advanced-search-options" --> | |
25 | + </div> | |
26 | + | |
27 | + <% if @empty_query %> | |
28 | + <% hint = environment.search_hints[@asset] %> | |
29 | + <% if hint and !hint.blank? %> | |
30 | + <span class="search-hint"><%= hint %></span> | |
31 | + <% end %> | |
32 | + <% end %> | |
50 | 33 | |
51 | - <% if simple_search %> | |
52 | - <%= link_to_function(_('More options'), nil, :id => 'advanced_search_link') do |page| | |
53 | - page['advanced_search_link'].hide | |
54 | - page['advanced-search-options'].toggle | |
55 | - end %> | |
56 | 34 | <% end %> |
57 | 35 | |
58 | - <% if lightbox?; button_bar do %> | |
59 | - <%= lightbox_close_button _('Close') %> | |
60 | - <% end; end %> | |
61 | - | |
62 | -<% end %> | |
63 | - | |
64 | -</div> <!-- id="search-form" --> | |
36 | + <div style="clear: both"></div> | |
37 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<li class="search-text-article-item article-item"> | |
2 | + <%= link_to(text_article.title, text_article.url, :class => "search-result-title") %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => text_article %> | |
5 | + </div> | |
6 | + <div class="search-content-second-column"> | |
7 | + <%= render :partial => 'article_common', :object => text_article %> | |
8 | + </div> | |
9 | + | |
10 | + <div style="clear: both"></div> | |
11 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,37 @@ |
1 | +<li class="search-uploaded-file-item article-item"> | |
2 | + <%= link_to uploaded_file.filename, uploaded_file.view_url, :class => 'search-result-title' %> | |
3 | + <hr class="clear" /> | |
4 | + | |
5 | + <div class="search-content-first-column"> | |
6 | + <%= render :partial => 'image', :object => uploaded_file %> | |
7 | + </div> | |
8 | + | |
9 | + <div class="search-uploaded-file-second-column"> | |
10 | + <%= render :partial => 'article_author', :object => uploaded_file %> | |
11 | + | |
12 | + <div class="search-uploaded-file-description"> | |
13 | + <% if !uploaded_file.body.blank? %> | |
14 | + <span class="search-field-label"><%= _("Description") %></span> | |
15 | + <% body = strip_tags(uploaded_file.body.to_s) %> | |
16 | + <%= excerpt(body, body.first(3), 200) %> | |
17 | + <% end %> | |
18 | + </div> | |
19 | + | |
20 | + <div class="search-uploaded-file-parent"> | |
21 | + <% if uploaded_file.parent && uploaded_file.parent.published? %> | |
22 | + <% if uploaded_file.parent.gallery? %> | |
23 | + <span class="search-field-label"><%= _("Gallery") %></span> | |
24 | + <% else %> | |
25 | + <span class="search-field-label"><%= _("Folder") %></span> | |
26 | + <% end %> | |
27 | + <%= link_to uploaded_file.parent.name, {:controller => 'content_viewer', :profile => uploaded_file.profile.identifier, :action => 'view_page', :page => [uploaded_file.parent.slug]} %> | |
28 | + <% end %> | |
29 | + </div> | |
30 | + | |
31 | + <%= render :partial => 'article_tags', :object => uploaded_file.tags %> | |
32 | + <%= render :partial => 'article_categories', :object => uploaded_file.categories %> | |
33 | + <%= render :partial => 'article_last_change', :object => uploaded_file %> | |
34 | + </div> | |
35 | + | |
36 | + <div style="clear:both"></div> | |
37 | +</li> | ... | ... |
app/views/search/articles.rhtml
1 | -<%= search_page_title( _('Articles'), { :query => @query, | |
2 | - :category => @category ? @category.name : nil, | |
3 | - :total_results => @total_results, | |
4 | - :region => @region ? @region.name : nil, | |
5 | - :distance => @radius } ) %> | |
1 | +<%= search_page_title( @titles[:articles], @category ) %> | |
6 | 2 | |
7 | -<%= search_page_link_to_all( { :asset => params[:asset], | |
8 | - :category => @category }) %> | |
3 | +<div id="search-column-left"> | |
4 | + <% if !@empty_query %> | |
5 | + <%= facets_menu(:articles, @facets) %> | |
6 | + <% end %> | |
7 | +</div> | |
9 | 8 | |
10 | -<%= render :partial => 'search_form', :locals => { :form_title => @query.blank? ? _('Search') : _("Refine your search"), :simple_search => true } %> | |
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' %> | |
11 | 12 | |
12 | -<%# FIXME ARMENGUE %> | |
13 | -<%= display_results(false) %> | |
13 | + <% if !@empty_query or @filter %> | |
14 | + <%= display_results %> | |
15 | + <%= pagination_links @results.values.first %> | |
16 | + <% end %> | |
17 | +</div> | |
14 | 18 | |
15 | -<%= pagination_links @results.values.first %> | |
16 | - | |
17 | -<br style="clear:both" /> | |
19 | +<div style="clear: both"></div> | ... | ... |
app/views/search/category_index.rhtml
... | ... | @@ -1,23 +0,0 @@ |
1 | -<div id="view-category"> | |
2 | - | |
3 | - <div id="category-image"><%= image_tag(@category.image.public_filename(:thumb), :id => 'category-image') if @category.image %></div> | |
4 | - <h1 id="category-name"><%= @category.name %></h1> | |
5 | - | |
6 | - <%= render :partial => 'display_results' %> | |
7 | - | |
8 | - <div id="category-childs"> | |
9 | - <h2> <%= _('Sub-categories') %> </h2> | |
10 | - <% if @category.children.empty? %> | |
11 | - <strong id="cat-no-child"><%= _('No sub-categories') %></strong> | |
12 | - <% else %> | |
13 | - <ul> | |
14 | - <% @category.children.each do |c| %> | |
15 | - <li> <%= link_to_category c, false %> </li> | |
16 | - <% end %> | |
17 | - </ul> | |
18 | - <% end %> | |
19 | - </div><!-- end id="child-categories" --> | |
20 | - | |
21 | -<br style="clear:both" /> | |
22 | -</div><!-- end id="view-category" --> | |
23 | - |
app/views/search/cities.rhtml
app/views/search/communities.rhtml
1 | -<%= search_page_title( __('Communities'), { :query => @query, | |
2 | - :category => @category ? @category.name : nil, | |
3 | - :total_results => @total_results, | |
4 | - :region => @region ? @region.name : nil, | |
5 | - :distance => @radius } ) %> | |
1 | +<%= search_page_title( @titles[:communities], @category ) %> | |
6 | 2 | |
7 | -<%= search_page_link_to_all( { :asset => params[:asset], | |
8 | - :category => @category }) %> | |
9 | -<%= render :partial => 'search_form', :locals => { :form_title => @query.blank? ? _('Search') : _("Refine your search"), :simple_search => true } %> | |
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')) %> | |
8 | + <% end %> | |
9 | + <% end %> | |
10 | 10 | |
11 | -<% if logged_in? %> | |
12 | - <% button_bar do %> | |
13 | - <%# FIXME shouldn't the user create the community in the current environment instead of going to its home environment? %> | |
14 | - <%= button(:add, __('New community'), user.url.merge(:controller => 'memberships', :action => 'new_community')) %> | |
11 | + <% if !@empty_query %> | |
12 | + <%= facets_menu(:communities, @facets) %> | |
15 | 13 | <% end %> |
16 | -<% end %> | |
14 | +</div> | |
17 | 15 | |
18 | -<div id='search-results-and-pages'> | |
19 | - <%# FIXME ARMENGUE %> | |
20 | - <%= display_results(false) %> | |
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' %> | |
21 | 19 | |
20 | + <%= display_results %> | |
22 | 21 | <%= pagination_links @results.values.first %> |
23 | 22 | </div> |
24 | 23 | |
25 | -<br style="clear:both" /> | |
24 | +<div style="clear: both"></div> | |
26 | 25 | ... | ... |
app/views/search/complete_region.rhtml
app/views/search/enterprises.rhtml
1 | -<h1> | |
2 | - <% if !@query.blank? %> | |
3 | - <%=h @category ? (__('Enterprise results for "%{query}" in "%{category}"') % { :query => @query, :category => @category.name}) : (__('Enterprise results for "%s"') % @query) %> | |
4 | - <% else %> | |
5 | - <%=h @category ? (__('Enterprises in "%s"') % @category.name) : __('Enterprises') %> | |
6 | - <% end %> | |
7 | -</h1> | |
8 | - | |
9 | -<% if @radius && @region %> | |
10 | - <h2><%=h (_('Within %s km from %s') % [@radius, @region.name]) %><h2> | |
11 | -<% end %> | |
12 | - | |
13 | -<%= search_page_link_to_all( { :asset => params[:asset], | |
14 | - :category => @category }) %> | |
15 | - | |
16 | -<%= render :partial => 'search_form', :locals => { :form_title => _("Refine your search"), :simple_search => true } %> | |
1 | +<%= search_page_title( @titles[:enterprises], @category ) %> | |
17 | 2 | |
18 | -<% if logged_in? && environment.enabled?('enterprise_registration') %> | |
19 | - <% button_bar do %> | |
20 | - <%= button(:add, __('New enterprise'), {:controller => 'enterprise_registration'}) %> | |
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 %> | |
21 | 8 | <% end %> |
22 | -<% end %> | |
23 | 9 | |
24 | -<% if @categories_menu %> | |
25 | -<div class="has_cat_list"> | |
26 | -<% end %> | |
27 | - | |
28 | -<% cache(:action => 'assets', :asset => 'enterprises', :category_path => params[:category_path], :query => @query, :product_category => @product_category, :region => @region, :radius => params[:radius]) do %> | |
29 | - <%= product_categories_menu(:enterprises, @product_category, @result_ids) %> | |
30 | -<% end %> | |
31 | - | |
32 | -<%= display_results %> | |
10 | + <% if !@empty_query %> | |
11 | + <% button_bar do %> | |
12 | + <%= display_map_list_button %> | |
13 | + <% end %> | |
14 | + <%= facets_menu(:enterprises, @facets) %> | |
15 | + <% end %> | |
16 | +</div> | |
33 | 17 | |
34 | -<% if @categories_menu %> | |
35 | -</div><!-- class="has_cat_list" --> | |
36 | -<% end %> | |
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' %> | |
37 | 21 | |
38 | -<%= pagination_links @results[:enterprises] %> | |
22 | + <%= display_results(true) %> | |
23 | + <% if params[:display] != 'map' %> | |
24 | + <%= pagination_links @results[:enterprises] %> | |
25 | + <% end %> | |
26 | +</div> | |
39 | 27 | |
40 | -<br style="clear:both" /> | |
28 | +<div style="clear: both"></div> | ... | ... |
app/views/search/events.rhtml
... | ... | @@ -0,0 +1,8 @@ |
1 | +<% results = @asset_class.map_facet_results(@facet, params[:facet], @facets, @all_facets) %> | |
2 | + | |
3 | +<% array = [] %> | |
4 | +<% @asset_class.facet_result_sort(@facet, results, :alphabetically).each do |id, label, count| %> | |
5 | + <% array << {:id => id, :name => facet_link_html(@facet, params.merge(:controller => 'search', :action => @asset), id, label, count)} %> | |
6 | +<% end %> | |
7 | + | |
8 | +<%= facet_javascript('facet-input-'+@facet[:id].to_s, @facet, array) %> | ... | ... |
app/views/search/index.rhtml
1 | -<div id="search-page"> | |
1 | +<div id="search-page" class="<%= "view-category" if @category %>"> | |
2 | 2 | |
3 | -<%= search_page_title(_('Search Results'), :query => CGI.escapeHTML(@query), :category => @category ? @category.name : nil, :total_results => @total_results) %> | |
3 | + <% if @category %> | |
4 | + <div id="category-image"><%= image_tag(@category.image.public_filename(:thumb), :id => 'category-image') if @category.image %></div> | |
5 | + <% end %> | |
4 | 6 | |
5 | -<%= render :partial => 'search_form', :locals => { :form_title => _("Refine your search"), :simple_search => true } %> | |
7 | + <%= search_page_title(_('Search Results'), @category) %> | |
8 | + <%= render :partial => 'search_form', :locals => { :hint => '' } %> | |
9 | + <%= category_context(@category, params) %> | |
10 | + <%= display_results %> | |
11 | + | |
12 | + <div id="category-childs"> | |
13 | + <% if @category %> | |
14 | + <h2> <%= _('Sub-categories') %> </h2> | |
15 | + <% if @category.children.empty? %> | |
16 | + <strong id="cat-no-child"><%= _('No sub-categories') %></strong> | |
17 | + <% else %> | |
18 | + <ul> | |
19 | + <% @category.children.each do |c| %> | |
20 | + <li> <%= link_to_category c, false %> </li> | |
21 | + <% end %> | |
22 | + </ul> | |
23 | + <% end %> | |
24 | + <% end %> | |
25 | + </div> | |
6 | 26 | |
7 | -<%= render :partial => 'display_results' %> | |
27 | +</div> | |
8 | 28 | |
9 | -</div><!-- end id="search-page" --> | |
10 | -<br style="clear:both" /> | |
29 | +<div style="clear: both"></div> | ... | ... |
app/views/search/people.rhtml
1 | -<%= search_page_title( _('People'), { :query => @query, | |
2 | - :category => @category ? @category.name : nil, | |
3 | - :total_results => @total_results, | |
4 | - :region => @region ? @region.name : nil, | |
5 | - :distance => @radius } ) %> | |
1 | +<%= search_page_title( @titles[:people], @category ) %> | |
6 | 2 | |
7 | -<%= search_page_link_to_all( { :asset => params[:asset], | |
8 | - :category => @category }) %> | |
3 | +<div id='search-column-left'> | |
4 | + <% if !@empty_query %> | |
5 | + <%= facets_menu(:people, @facets) %> | |
6 | + <% end %> | |
7 | +</div> | |
9 | 8 | |
10 | -<%= render :partial => 'search_form', :locals => { :form_title => @query.blank? ? _('Search') : _("Refine your search"), :simple_search => true } %> | |
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' %> | |
11 | 12 | |
12 | -<%# FIXME ARMENGUE %> | |
13 | -<%= display_results(false) %> | |
13 | + <%= display_results %> | |
14 | + <% if params[:display] != 'map' %> | |
15 | + <%= pagination_links @results.values.first %> | |
16 | + <% end %> | |
17 | +</div> | |
14 | 18 | |
15 | -<%= pagination_links @results.values.first %> | |
16 | - | |
17 | -<br style="clear:both" /> | |
19 | +<div style="clear: both"></div> | ... | ... |
app/views/search/popup.rhtml
app/views/search/products.rhtml
1 | -<%= search_page_title( _('Products and Services'), { :query => @query, | |
2 | - :category => @category ? @category.name : nil, | |
3 | - :total_results => @total_results, | |
4 | - :region => @region ? @region.name : nil, | |
5 | - :distance => @radius } ) %> | |
6 | - | |
7 | -<%= search_page_link_to_all( { :asset => params[:asset], | |
8 | - :category => @category }) %> | |
9 | - | |
10 | -<%= render :partial => 'search_form', :locals => { :form_title => _("Refine your search"), :simple_search => true } %> | |
11 | - | |
12 | -<% if @categories_menu %> | |
13 | -<div class="has_cat_list"> | |
14 | -<% end %> | |
15 | - | |
16 | -<% cache(:action => 'assets', :asset => 'products', :category_path => params[:category_path], :query => @query, :product_category => @product_category, :region => @region, :radius => params[:radius]) do %> | |
17 | - <%= product_categories_menu(:products, @product_category, @result_ids) %> | |
18 | -<% end %> | |
19 | - | |
20 | -<%= display_results %> | |
21 | - | |
22 | -<% if @categories_menu %> | |
23 | -</div><!-- class="has_cat_list" --> | |
24 | -<% end %> | |
25 | - | |
26 | -<%= pagination_links @results[:products] %> | |
27 | - | |
28 | -<br style="clear:both" /> | |
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 | + <% if !@empty_query %> | |
17 | + <%= display_results(true) %> | |
18 | + <% if params[:display] != 'map' %> | |
19 | + <%= pagination_links @results[:products] %> | |
20 | + <% end %> | |
21 | + <% end %> | |
22 | +</div> | |
23 | + | |
24 | +<div style="clear: both"></div> | ... | ... |
app/views/search/tag.rhtml
config/initializers/dependencies.rb
config/routes.rb
... | ... | @@ -52,10 +52,6 @@ ActionController::Routing::Routes.draw do |map| |
52 | 52 | # search |
53 | 53 | map.connect 'search/:action/*category_path', :controller => 'search' |
54 | 54 | |
55 | - # Browse | |
56 | - map.connect 'browse/:action/:filter', :controller => 'browse' | |
57 | - map.connect 'browse/:action', :controller => 'browse' | |
58 | - | |
59 | 55 | # events |
60 | 56 | map.events 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/ |
61 | 57 | map.events 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/ |
... | ... | @@ -85,6 +81,9 @@ ActionController::Routing::Routes.draw do |map| |
85 | 81 | # contact |
86 | 82 | map.contact 'contact/:profile/:action/:id', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ |
87 | 83 | |
84 | + # map balloon | |
85 | + map.contact 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/ | |
86 | + | |
88 | 87 | # chat |
89 | 88 | map.chat 'chat/:action/:id', :controller => 'chat' |
90 | 89 | map.chat 'chat/:action', :controller => 'chat' | ... | ... |
db/migrate/20110810123648_add_acronym_and_abbreviation_to_category.rb
0 → 100644
... | ... | @@ -0,0 +1,11 @@ |
1 | +class AddAcronymAndAbbreviationToCategory < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_column :categories, :acronym, :string | |
4 | + add_column :categories, :abbreviation, :string | |
5 | + end | |
6 | + | |
7 | + def self.down | |
8 | + remove_column :categories, :abbreviation | |
9 | + remove_column :categories, :acronym | |
10 | + end | |
11 | +end | ... | ... |
db/migrate/20110814172228_drop_product_categorization.rb
0 → 100644
db/schema.rb
... | ... | @@ -175,6 +175,8 @@ ActiveRecord::Schema.define(:version => 20111004184104) do |
175 | 175 | t.integer "children_count", :default => 0 |
176 | 176 | t.boolean "accept_products", :default => true |
177 | 177 | t.integer "image_id" |
178 | + t.string "acronym" | |
179 | + t.string "abbreviation" | |
178 | 180 | end |
179 | 181 | |
180 | 182 | create_table "categories_profiles", :id => false, :force => true do |t| |
... | ... | @@ -452,9 +454,9 @@ ActiveRecord::Schema.define(:version => 20111004184104) do |
452 | 454 | |
453 | 455 | create_table "roles", :force => true do |t| |
454 | 456 | t.string "name" |
457 | + t.text "permissions" | |
455 | 458 | t.string "key" |
456 | 459 | t.boolean "system", :default => false |
457 | - t.text "permissions" | |
458 | 460 | t.integer "environment_id" |
459 | 461 | end |
460 | 462 | ... | ... |
... | ... | @@ -0,0 +1,219 @@ |
1 | +module ActsAsFaceted | |
2 | + | |
3 | + module ClassMethods | |
4 | + end | |
5 | + | |
6 | + module ActsMethods | |
7 | + # Example: | |
8 | + # | |
9 | + #acts_as_faceted :fields => { | |
10 | + # :f_type => {:label => _('Type'), :proc => proc{|klass| f_type_proc(klass)}}, | |
11 | + # :f_published_at => {:type => :date, :label => _('Published date'), :queries => {'[* TO NOW-1YEARS/DAY]' => _("Older than one year"), | |
12 | + # '[NOW-1YEARS TO NOW/DAY]' => _("Last year"), '[NOW-1MONTHS TO NOW/DAY]' => _("Last month"), '[NOW-7DAYS TO NOW/DAY]' => _("Last week"), '[NOW-1DAYS TO NOW/DAY]' => _("Last day")}}, | |
13 | + # :f_profile_type => {:label => _('Author'), :proc => proc{|klass| f_profile_type_proc(klass)}}, | |
14 | + # :f_category => {:label => _('Categories')}}, | |
15 | + # :order => [:f_type, :f_published_at, :f_profile_type, :f_category] | |
16 | + # | |
17 | + #acts_as_searchable :additional_fields => [ {:name => {:type => :string, :as => :name_sort, :boost => 5.0}} ] + facets_fields_for_solr, | |
18 | + # :exclude_fields => [:setting], | |
19 | + # :include => [:profile], | |
20 | + # :facets => facets_option_for_solr, | |
21 | + # :if => proc{|a| ! ['RssFeed'].include?(a.class.name)} | |
22 | + def acts_as_faceted(options) | |
23 | + extend ClassMethods | |
24 | + extend ActsAsSolr::CommonMethods | |
25 | + | |
26 | + cattr_accessor :facets | |
27 | + cattr_accessor :facets_order | |
28 | + cattr_accessor :to_solr_fields_names | |
29 | + cattr_accessor :facets_results_containers | |
30 | + cattr_accessor :solr_fields_names | |
31 | + cattr_accessor :facets_option_for_solr | |
32 | + cattr_accessor :facets_fields_for_solr | |
33 | + cattr_accessor :facet_category_query | |
34 | + | |
35 | + self.facets = options[:fields] | |
36 | + self.facets_order = options[:order] || facets | |
37 | + self.facets_results_containers = {:fields => 'facet_fields', :queries => 'facet_queries', :ranges => 'facet_ranges'} | |
38 | + self.facets_option_for_solr = Hash[facets.select{ |id,data| ! data.has_key?(:queries) }].keys | |
39 | + self.facets_fields_for_solr = facets.map{ |id,data| {id => data[:type] || :facet} } | |
40 | + self.solr_fields_names = facets.map{ |id,data| id.to_s + '_' + get_solr_field_type(data[:type] || :facet) } | |
41 | + self.facet_category_query = options[:category_query] | |
42 | + | |
43 | + # A hash to retrieve the field key for the solr facet string returned | |
44 | + # :field_name => "field_name_facet" | |
45 | + self.to_solr_fields_names = Hash[facets.keys.zip(solr_fields_names)] | |
46 | + | |
47 | + def facet_by_id(id) | |
48 | + {:id => id}.merge(facets[id]) if facets[id] | |
49 | + end | |
50 | + | |
51 | + def map_facets_for(environment) | |
52 | + list = facets_order ? facets_order : facets.keys | |
53 | + list.map do |id| | |
54 | + facet = facet_by_id(id) | |
55 | + next if facet[:type_if] and !facet[:type_if].call(self.new) | |
56 | + | |
57 | + if facet[:multi] | |
58 | + facet[:label].call(environment).map do |label_id, label| | |
59 | + facet.merge({:id => facet[:id].to_s+'_'+label_id.to_s, :solr_field => facet[:id], :label_id => label_id, :label => label}) | |
60 | + end | |
61 | + else | |
62 | + facet.merge(:id => facet[:id].to_s, :solr_field => facet[:id]) | |
63 | + end | |
64 | + end.compact.flatten | |
65 | + end | |
66 | + | |
67 | + def map_facet_results(facet, facet_params, facets_data, unfiltered_facets_data = {}, options = {}) | |
68 | + facets_data ||= {} | |
69 | + solr_facet = to_solr_fields_names[facet[:solr_field]] | |
70 | + | |
71 | + if facet[:queries] | |
72 | + container = facets_data[facets_results_containers[:queries]] | |
73 | + facet_data = (container.nil? or container.empty?) ? [] : container.select{ |k,v| k.starts_with? solr_facet } | |
74 | + container = unfiltered_facets_data[facets_results_containers[:queries]] | |
75 | + unfiltered_facet_data = (container.nil? or container.empty?) ? [] : container.select{ |k,v| k.starts_with? solr_facet } | |
76 | + else | |
77 | + container = facets_data[facets_results_containers[:fields]] | |
78 | + facet_data = (container.nil? or container.empty?) ? [] : container[solr_facet] || [] | |
79 | + container = unfiltered_facets_data[facets_results_containers[:fields]] | |
80 | + unfiltered_facet_data = (container.nil? or container.empty?) ? [] : container[solr_facet] || [] | |
81 | + end | |
82 | + | |
83 | + if !unfiltered_facets_data.blank? and !facet_params.blank? | |
84 | + f = Hash[Array(facet_data)] | |
85 | + zeros = [] | |
86 | + facet_data = unfiltered_facet_data.map do |id, count| | |
87 | + count = f[id] | |
88 | + if count.nil? | |
89 | + zeros.push [id, 0] | |
90 | + nil | |
91 | + else | |
92 | + [id, count] | |
93 | + end | |
94 | + end.compact + zeros | |
95 | + end | |
96 | + | |
97 | + facet_count = facet_data.length | |
98 | + | |
99 | + if facet[:queries] | |
100 | + result = facet_data.map do |id, count| | |
101 | + q = id[id.index(':')+1,id.length] | |
102 | + label = facet_result_name(facet, q) | |
103 | + [q, label, count] if count > 0 | |
104 | + end.compact | |
105 | + result = facet[:queries_order].map{ |id| result.detect{ |rid, label, count| rid == id } }.compact if facet[:queries_order] | |
106 | + elsif facet[:proc] | |
107 | + if facet[:label_id] | |
108 | + result = facet_data.map do |id, count| | |
109 | + name = facet_result_name(facet, id) | |
110 | + [id, name, count] if name | |
111 | + end.compact | |
112 | + # FIXME limit is NOT improving performance in this case :( | |
113 | + facet_count = result.length | |
114 | + result = result.first(options[:limit]) if options[:limit] | |
115 | + else | |
116 | + facet_data = facet_data.first(options[:limit]) if options[:limit] | |
117 | + result = facet_data.map { |id, count| [id, facet_result_name(facet, id), count] } | |
118 | + end | |
119 | + else | |
120 | + facet_data = facet_data.first(options[:limit]) if options[:limit] | |
121 | + result = facet_data.map { |id, count| [id, facet_result_name(facet, id), count] } | |
122 | + end | |
123 | + | |
124 | + sorted = facet_result_sort(facet, result, options[:sort]) | |
125 | + | |
126 | + # length can't be used if limit option is given; | |
127 | + # total_entries comes to help | |
128 | + sorted.class.send(:define_method, :total_entries, proc { facet_count }) | |
129 | + | |
130 | + sorted | |
131 | + end | |
132 | + | |
133 | + def facet_result_sort(facet, facets_data, sort_by = nil) | |
134 | + if facet[:queries_order] | |
135 | + facets_data | |
136 | + elsif sort_by == :alphabetically | |
137 | + facets_data.sort{ |a,b| a[1] <=> b[1] } | |
138 | + elsif sort_by == :count | |
139 | + facets_data.sort{ |a,b| -1*(a[2] <=> b[2]) } | |
140 | + else | |
141 | + facets_data | |
142 | + end | |
143 | + end | |
144 | + | |
145 | + def facet_result_name(facet, data) | |
146 | + if facet[:queries] | |
147 | + gettext(facet[:queries][data]) | |
148 | + elsif facet[:proc] | |
149 | + if facet[:multi] | |
150 | + facet[:label_id] ||= 0 | |
151 | + facet[:proc].call(facet, data) | |
152 | + else | |
153 | + gettext(facet[:proc].call(data)) | |
154 | + end | |
155 | + else | |
156 | + data | |
157 | + end | |
158 | + end | |
159 | + | |
160 | + def facet_label(facet) | |
161 | + _ facet[:label] | |
162 | + end | |
163 | + | |
164 | + def facets_find_options(facets_selected = {}, options = {}) | |
165 | + browses = [] | |
166 | + facets_selected ||= {} | |
167 | + facets_selected.map do |id, value| | |
168 | + if value.kind_of?(Hash) | |
169 | + value.map do |label_id, value| | |
170 | + value.to_a.each do |value| | |
171 | + browses << id.to_s + ':' + (facets[id.to_sym][:queries] ? value : '"'+value.to_s+'"') | |
172 | + end | |
173 | + end | |
174 | + else | |
175 | + browses << id.to_s + ':' + (facets[id.to_sym][:queries] ? value : '"'+value.to_s+'"') | |
176 | + end | |
177 | + end.flatten | |
178 | + | |
179 | + {:facets => {:zeros => false, :sort => :count, | |
180 | + :fields => facets_option_for_solr, | |
181 | + :browse => browses, | |
182 | + :query => facets.map { |f, options| options[:queries].keys.map { |q| f.to_s + ':' + q } if options[:queries] }.compact.flatten, | |
183 | + } | |
184 | + } | |
185 | + end | |
186 | + end | |
187 | + end | |
188 | + | |
189 | +end | |
190 | + | |
191 | +ActiveRecord::Base.extend ActsAsFaceted::ActsMethods | |
192 | + | |
193 | +# from https://github.com/rubyworks/facets/blob/master/lib/core/facets/enumerable/graph.rb | |
194 | +module Enumerable | |
195 | + def graph(&yld) | |
196 | + if yld | |
197 | + h = {} | |
198 | + each do |*kv| | |
199 | + r = yld[*kv] | |
200 | + case r | |
201 | + when Hash | |
202 | + nk, nv = *r.to_a[0] | |
203 | + when Range | |
204 | + nk, nv = r.first, r.last | |
205 | + else | |
206 | + nk, nv = *r | |
207 | + end | |
208 | + h[nk] = nv | |
209 | + end | |
210 | + h | |
211 | + else | |
212 | + Enumerator.new(self,:graph) | |
213 | + end | |
214 | + end | |
215 | + | |
216 | + # Alias for #graph, which stands for "map hash". | |
217 | + alias_method :mash, :graph | |
218 | +end | |
219 | + | ... | ... |
lib/acts_as_searchable.rb
... | ... | @@ -4,16 +4,16 @@ module ActsAsSearchable |
4 | 4 | ACTS_AS_SEARCHABLE_ENABLED = true unless defined? ACTS_AS_SEARCHABLE_ENABLED |
5 | 5 | |
6 | 6 | def acts_as_searchable(options = {}) |
7 | - if ACTS_AS_SEARCHABLE_ENABLED | |
8 | - if (!options[:fields]) | |
9 | - options[:additional_fields] |= [{:schema_name => :string}] | |
10 | - else | |
11 | - options[:fields] << {:schema_name => :string} | |
12 | - end | |
13 | - acts_as_solr options | |
14 | - extend FindByContents | |
15 | - send :include, InstanceMethods | |
7 | + return if !ACTS_AS_SEARCHABLE_ENABLED | |
8 | + | |
9 | + if (!options[:fields]) | |
10 | + options[:additional_fields] |= [{:schema_name => :string}] | |
11 | + else | |
12 | + options[:fields] << {:schema_name => :string} | |
16 | 13 | end |
14 | + acts_as_solr options | |
15 | + extend FindByContents | |
16 | + send :include, InstanceMethods | |
17 | 17 | end |
18 | 18 | |
19 | 19 | module InstanceMethods |
... | ... | @@ -31,14 +31,20 @@ module ActsAsSearchable |
31 | 31 | def find_by_contents(query, pg_options = {}, options = {}, db_options = {}) |
32 | 32 | pg_options[:page] ||= 1 |
33 | 33 | pg_options[:per_page] ||= 20 |
34 | - options[:limit] = pg_options[:per_page].to_i*pg_options[:page].to_i | |
35 | - options[:scores] = true; | |
36 | - | |
34 | + options[:limit] ||= pg_options[:per_page].to_i*pg_options[:page].to_i | |
35 | + options[:scores] ||= true; | |
36 | + all_facets_enabled = options.delete(:all_facets) | |
37 | 37 | query = !schema_name.empty? ? "+schema_name:\"#{schema_name}\" AND #{query}" : query |
38 | + results = [] | |
39 | + facets = all_facets = {} | |
40 | + | |
38 | 41 | solr_result = find_by_solr(query, options) |
39 | - if solr_result.nil? | |
40 | - results = facets = [] | |
41 | - else | |
42 | + if all_facets_enabled | |
43 | + options[:facets][:browse] = nil | |
44 | + all_facets = find_by_solr(query, options.merge(:limit => 0)).facets | |
45 | + end | |
46 | + | |
47 | + if !solr_result.nil? | |
42 | 48 | facets = options.include?(:facets) ? solr_result.facets : [] |
43 | 49 | |
44 | 50 | if db_options.empty? |
... | ... | @@ -61,7 +67,7 @@ module ActsAsSearchable |
61 | 67 | results = results.paginate(pg_options.merge(:total_entries => solr_result.total)) |
62 | 68 | end |
63 | 69 | |
64 | - {:results => results, :facets => facets} | |
70 | + {:results => results, :facets => facets, :all_facets => all_facets} | |
65 | 71 | end |
66 | 72 | end |
67 | 73 | end | ... | ... |
public/designs/themes/base/navigation.rhtml
1 | 1 | <li> |
2 | - <%= browse_people_menu %> | |
2 | + <%= search_people_menu %> | |
3 | 3 | </li> |
4 | 4 | <li> |
5 | - <%= browse_communities_menu %> | |
5 | + <%= search_communities_menu %> | |
6 | 6 | </li> |
7 | 7 | <li> |
8 | - <%= browse_contents_menu %> | |
8 | + <%= search_contents_menu %> | |
9 | 9 | </li> |
10 | -<li><a href="/assets/events"><span class='icon-menu-events'><%= _('Events') %></span></a></li> | |
10 | +<li><a href="/search/events"><span class='icon-menu-events'><%= _('Events') %></span></a></li> | ... | ... |
public/designs/themes/base/style.css
1 | 1 | /* ==> button.css <== */ |
2 | 2 | |
3 | - | |
4 | 3 | .button { |
5 | 4 | -moz-border-radius: 3px; |
6 | 5 | -webkit-border-radius: 3px; |
... | ... | @@ -108,14 +107,14 @@ body, th, td, input { |
108 | 107 | margin-left: 20px; |
109 | 108 | } |
110 | 109 | |
111 | -#user form input { | |
110 | +#user form input .blur { | |
112 | 111 | width: 160px; |
113 | 112 | border: 1px solid #BBB; |
114 | 113 | -moz-border-radius: 3px; |
115 | 114 | -webkit-border-radius: 3px; |
116 | 115 | color: #CCC; |
117 | 116 | } |
118 | -#user form.focused input { | |
117 | +#user form input { | |
119 | 118 | border: 1px solid #888; |
120 | 119 | color: #555; |
121 | 120 | } |
... | ... | @@ -502,11 +501,11 @@ div#notice { |
502 | 501 | } |
503 | 502 | |
504 | 503 | #content .profile-list li a, |
505 | -#content .common-profile-list-block li a { | |
504 | +#content .common-profile-list-block .vcard li a { | |
506 | 505 | color: #555; |
507 | 506 | } |
508 | 507 | #content .profile-list li a:hover, |
509 | -#content .common-profile-list-block li a:hover { | |
508 | +#content .common-profile-list-block .vcard li a:hover { | |
510 | 509 | color: #000; |
511 | 510 | text-decoration: none; |
512 | 511 | } | ... | ... |