Commit d0aadb3e84a74ebe9313dd04845088b95d2be2ac

Authored by Rodrigo Souto
2 parents 51314a6f f4012a36

Merge branch 'master' into custom-forms

Showing 331 changed files with 14300 additions and 8252 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 331 files displayed.

@@ -22,6 +22,7 @@ Diego Araújo <diegoamc90@gmail.com> @@ -22,6 +22,7 @@ Diego Araújo <diegoamc90@gmail.com>
22 Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> 22 Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
23 Fernanda Lopes <nanda.listas+psl@gmail.com> 23 Fernanda Lopes <nanda.listas+psl@gmail.com>
24 Grazieno Pellegrino <grazieno@gmail.com> 24 Grazieno Pellegrino <grazieno@gmail.com>
  25 +Isaac Canan <isaac@intelletto.com.br>
25 Italo Valcy <italo@dcc.ufba.br> 26 Italo Valcy <italo@dcc.ufba.br>
26 João da Silva <jaodsilv@linux.ime.usp.br> 27 João da Silva <jaodsilv@linux.ime.usp.br>
27 João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br> 28 João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>
INSTALL.varnish
@@ -15,6 +15,10 @@ Noosfero was tested with Varnish 2.x. If you are using a Debian Lenny (and you @@ -15,6 +15,10 @@ Noosfero was tested with Varnish 2.x. If you are using a Debian Lenny (and you
15 should, unless Debian already released Squeeze by now), make sure you install 15 should, unless Debian already released Squeeze by now), make sure you install
16 varnish from the lenny-backports suite. 16 varnish from the lenny-backports suite.
17 17
  18 +Install the RPAF apache module (or skip this step if not using apache):
  19 +
  20 + # apt-get install libapache2-mod-rpaf
  21 +
18 3) Enable varnish logging: 22 3) Enable varnish logging:
19 23
20 3a) Edit /etc/default/varnishncsa and uncomment the line that contains: 24 3a) Edit /etc/default/varnishncsa and uncomment the line that contains:
app/controllers/admin/licenses_controller.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +class LicensesController < AdminController
  2 + protect 'manage_environment_licenses', :environment
  3 +
  4 + def index
  5 + @licenses = environment.licenses
  6 + end
  7 +
  8 + def create
  9 + @license = License.new(params[:license])
  10 + if request.post?
  11 + begin
  12 + @license.environment = environment
  13 + @license.save!
  14 + session[:notice] = _('License created')
  15 + redirect_to :action => 'index'
  16 + rescue
  17 + session[:notice] = _('License could not be created')
  18 + end
  19 + end
  20 + end
  21 +
  22 + def edit
  23 + @license = environment.licenses.find(params[:license_id])
  24 + if request.post?
  25 + begin
  26 + @license.update_attributes!(params[:license])
  27 + session[:notice] = _('License updated')
  28 + redirect_to :action => 'index'
  29 + rescue
  30 + session[:notice] = _('License could not be updated')
  31 + end
  32 + end
  33 + end
  34 +
  35 + def remove
  36 + @license = environment.licenses.find(params[:license_id])
  37 + if request.post?
  38 + begin
  39 + @license.destroy
  40 + session[:notice] = _('License removed')
  41 + rescue
  42 + session[:notice] = _('License could not be removed')
  43 + end
  44 + else
  45 + session[:notice] = _('License could not be removed')
  46 + end
  47 + redirect_to :action => 'index'
  48 + end
  49 +
  50 +end
app/controllers/admin/templates_controller.rb 0 → 100644
@@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
  1 +class TemplatesController < AdminController
  2 + protect 'manage_environment_templates', :environment
  3 +
  4 + def create_person_template
  5 + if request.post?
  6 + begin
  7 + identifier = params[:name].to_slug
  8 + password = Digest::MD5.hexdigest(rand.to_s)
  9 + template = User.new(:login => identifier, :email => identifier+'@templates.noo', :password => password, :password_confirmation => password, :person_data => {:name => params[:name], :is_template => true})
  10 + template.save!
  11 + session[:notice] = _('New template created')
  12 + redirect_to :action => 'index'
  13 + rescue
  14 + @error = _('Name has already been taken')
  15 + end
  16 + end
  17 + end
  18 +
  19 + def create_community_template
  20 + if request.post?
  21 + begin
  22 + create_organization_template(Community)
  23 + session[:notice] = _('New template created')
  24 + redirect_to :action => 'index'
  25 + rescue
  26 + @error = _('Name has already been taken')
  27 + end
  28 + end
  29 + end
  30 +
  31 + def create_enterprise_template
  32 + if request.post?
  33 + begin
  34 + create_organization_template(Enterprise)
  35 + session[:notice] = _('New template created')
  36 + redirect_to :action => 'index'
  37 + rescue
  38 + @error = _('Name has already been taken')
  39 + end
  40 + end
  41 + end
  42 +
  43 + private
  44 +
  45 + def create_organization_template(klass)
  46 + identifier = params[:name].to_slug
  47 + template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true)
  48 + template.save!
  49 + end
  50 +
  51 +end
  52 +
app/controllers/application_controller.rb
1 class ApplicationController < ActionController::Base 1 class ApplicationController < ActionController::Base
2 2
3 before_filter :setup_multitenancy 3 before_filter :setup_multitenancy
  4 + before_filter :detect_stuff_by_domain
  5 + before_filter :init_noosfero_plugins
4 6
5 include ApplicationHelper 7 include ApplicationHelper
6 layout :get_layout 8 layout :get_layout
@@ -51,8 +53,6 @@ class ApplicationController &lt; ActionController::Base @@ -51,8 +53,6 @@ class ApplicationController &lt; ActionController::Base
51 53
52 include NeedsProfile 54 include NeedsProfile
53 55
54 - before_filter :detect_stuff_by_domain  
55 - before_filter :init_noosfero_plugins  
56 attr_reader :environment 56 attr_reader :environment
57 57
58 before_filter :load_terminology 58 before_filter :load_terminology
app/controllers/public/content_viewer_controller.rb
@@ -19,7 +19,7 @@ class ContentViewerController &lt; ApplicationController @@ -19,7 +19,7 @@ class ContentViewerController &lt; ApplicationController
19 unless @page 19 unless @page
20 page_from_old_path = profile.articles.find_by_old_path(path) 20 page_from_old_path = profile.articles.find_by_old_path(path)
21 if page_from_old_path 21 if page_from_old_path
22 - redirect_to :profile => profile.identifier, :page => page_from_old_path.explode_path 22 + redirect_to profile.url.merge(:page => page_from_old_path.explode_path)
23 return 23 return
24 end 24 end
25 end 25 end
@@ -99,6 +99,14 @@ class ContentViewerController &lt; ApplicationController @@ -99,6 +99,14 @@ class ContentViewerController &lt; ApplicationController
99 @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow] 99 @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow]
100 end 100 end
101 101
  102 + @unfollow_form = params[:unfollow] && params[:unfollow] == 'true'
  103 + if params[:unfollow] && params[:unfollow] == 'commit' && request.post?
  104 + @page.followers -= [params[:email]]
  105 + if @page.save
  106 + session[:notice] = _("Notification of new comments to '%s' was successfully canceled") % params[:email]
  107 + end
  108 + end
  109 +
102 @comments = @page.comments(true).as_thread 110 @comments = @page.comments(true).as_thread
103 @comments_count = @page.comments.count 111 @comments_count = @page.comments.count
104 if params[:slideshow] 112 if params[:slideshow]
app/controllers/public/search_controller.rb
@@ -4,10 +4,17 @@ class SearchController &lt; PublicController @@ -4,10 +4,17 @@ class SearchController &lt; PublicController
4 include SearchHelper 4 include SearchHelper
5 include ActionView::Helpers::NumberHelper 5 include ActionView::Helpers::NumberHelper
6 6
  7 + before_filter :redirect_asset_param, :except => [:facets_browse, :assets]
7 before_filter :load_category 8 before_filter :load_category
8 before_filter :load_search_assets 9 before_filter :load_search_assets
9 before_filter :load_query 10 before_filter :load_query
10 11
  12 + # Backwards compatibility with old URLs
  13 + def redirect_asset_param
  14 + return unless params.has_key?(:asset)
  15 + redirect_to params.merge(:action => params.delete(:asset))
  16 + end
  17 +
11 no_design_blocks 18 no_design_blocks
12 19
13 def facets_browse 20 def facets_browse
@@ -243,17 +250,16 @@ class SearchController &lt; PublicController @@ -243,17 +250,16 @@ class SearchController &lt; PublicController
243 @searching = {} 250 @searching = {}
244 @titles = {} 251 @titles = {}
245 @enabled_searches.each do |key, name| 252 @enabled_searches.each do |key, name|
246 - @titles[key] = name 253 + @titles[key] = _(name)
247 @searching[key] = params[:action] == 'index' || params[:action] == key.to_s 254 @searching[key] = params[:action] == 'index' || params[:action] == key.to_s
248 end 255 end
249 @names = @titles if @names.nil? 256 @names = @titles if @names.nil?
250 end 257 end
251 258
252 def limit 259 def limit
253 - searching = @searching.values.select{ |v| v }  
254 - if params[:display] == 'map' 260 + if map_search?
255 MAP_SEARCH_LIMIT 261 MAP_SEARCH_LIMIT
256 - elsif searching.size <= 1 262 + elsif !multiple_search?
257 if [:people, :communities].include? @asset 263 if [:people, :communities].include? @asset
258 BLOCKS_SEARCH_LIMIT 264 BLOCKS_SEARCH_LIMIT
259 elsif @asset == :enterprises and @empty_query 265 elsif @asset == :enterprises and @empty_query
@@ -267,31 +273,34 @@ class SearchController &lt; PublicController @@ -267,31 +273,34 @@ class SearchController &lt; PublicController
267 end 273 end
268 274
269 def paginate_options(page = params[:page]) 275 def paginate_options(page = params[:page])
  276 + page = 1 if multiple_search? or params[:display] == 'map'
270 { :per_page => limit, :page => page } 277 { :per_page => limit, :page => page }
271 end 278 end
272 279
273 def full_text_search(filters = [], options = {}) 280 def full_text_search(filters = [], options = {})
274 paginate_options = paginate_options(params[:page]) 281 paginate_options = paginate_options(params[:page])
275 asset_class = asset_class(@asset) 282 asset_class = asset_class(@asset)
276 -  
277 solr_options = options 283 solr_options = options
278 - if !@results_only and asset_class.respond_to? :facets  
279 - solr_options.merge! asset_class.facets_find_options(params[:facet])  
280 - solr_options[:all_facets] = true  
281 - solr_options[:limit] = 0 if @facets_only  
282 - end  
283 - solr_options[:filter_queries] ||= []  
284 - solr_options[:filter_queries] += filters  
285 - solr_options[:filter_queries] << "environment_id:#{environment.id}"  
286 - solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category  
287 -  
288 - solr_options[:boost_functions] ||= []  
289 - params[:order_by] = nil if params[:order_by] == 'none'  
290 - if params[:order_by]  
291 - order = SortOptions[@asset][params[:order_by].to_sym]  
292 - raise "Unknown order by" if order.nil?  
293 - order[:solr_opts].each do |opt, value|  
294 - solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value 284 + pg_options = paginate_options(params[:page])
  285 +
  286 + if !multiple_search?
  287 + if !@results_only and asset_class.respond_to? :facets
  288 + solr_options.merge! asset_class.facets_find_options(params[:facet])
  289 + solr_options[:all_facets] = true
  290 + end
  291 + solr_options[:filter_queries] ||= []
  292 + solr_options[:filter_queries] += filters
  293 + solr_options[:filter_queries] << "environment_id:#{environment.id}"
  294 + solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category
  295 +
  296 + solr_options[:boost_functions] ||= []
  297 + params[:order_by] = nil if params[:order_by] == 'none'
  298 + if params[:order_by]
  299 + order = SortOptions[@asset][params[:order_by].to_sym]
  300 + raise "Unknown order by" if order.nil?
  301 + order[:solr_opts].each do |opt, value|
  302 + solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
  303 + end
295 end 304 end
296 end 305 end
297 306
app/helpers/application_helper.rb
@@ -10,6 +10,8 @@ module ApplicationHelper @@ -10,6 +10,8 @@ module ApplicationHelper
10 10
11 include ThickboxHelper 11 include ThickboxHelper
12 12
  13 + include ColorboxHelper
  14 +
13 include BoxesHelper 15 include BoxesHelper
14 16
15 include FormsHelper 17 include FormsHelper
@@ -1076,24 +1078,24 @@ module ApplicationHelper @@ -1076,24 +1078,24 @@ module ApplicationHelper
1076 1078
1077 def search_contents_menu 1079 def search_contents_menu
1078 links = [ 1080 links = [
1079 - {s_('contents|More Recent') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_recent'})}},  
1080 - {s_('contents|More Viewed') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_popular'})}},  
1081 - {s_('contents|Most Commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}} 1081 + {s_('contents|More recent') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_recent'})}},
  1082 + {s_('contents|More viewed') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_popular'})}},
  1083 + {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}}
1082 ] 1084 ]
1083 if logged_in? 1085 if logged_in?
1084 - links.push(_('New Content') => lightbox_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) 1086 + links.push(_('New content') => colorbox_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})}))
1085 end 1087 end
1086 1088
1087 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => ''}, :id => 'submenu-contents') + 1089 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => ''}, :id => 'submenu-contents') +
1088 - link_to(content_tag(:span, _('Contents Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-contents-trigger') 1090 + link_to(content_tag(:span, _('Contents menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-contents-trigger')
1089 end 1091 end
1090 alias :browse_contents_menu :search_contents_menu 1092 alias :browse_contents_menu :search_contents_menu
1091 1093
1092 def search_people_menu 1094 def search_people_menu
1093 links = [ 1095 links = [
1094 - {s_('people|More Recent') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_recent'})}},  
1095 - {s_('people|More Active') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_active'})}},  
1096 - {s_('people|More Popular') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_popular'})}} 1096 + {s_('people|More recent') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_recent'})}},
  1097 + {s_('people|More active') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_active'})}},
  1098 + {s_('people|More popular') => {:href => url_for({:controller => 'search', :action => 'people', :filter => 'more_popular'})}}
1097 ] 1099 ]
1098 if logged_in? 1100 if logged_in?
1099 links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})}) 1101 links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})})
@@ -1101,15 +1103,15 @@ module ApplicationHelper @@ -1101,15 +1103,15 @@ module ApplicationHelper
1101 end 1103 end
1102 1104
1103 link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "search", :action => 'people', :category_path => ''}, :id => 'submenu-people') + 1105 link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "search", :action => 'people', :category_path => ''}, :id => 'submenu-people') +
1104 - link_to(content_tag(:span, _('People Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger') 1106 + link_to(content_tag(:span, _('People menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-people-trigger')
1105 end 1107 end
1106 alias :browse_people_menu :search_people_menu 1108 alias :browse_people_menu :search_people_menu
1107 1109
1108 def search_communities_menu 1110 def search_communities_menu
1109 links = [ 1111 links = [
1110 - {s_('communities|More Recent') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_recent'})}},  
1111 - {s_('communities|More Active') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_active'})}},  
1112 - {s_('communities|More Popular') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_popular'})}} 1112 + {s_('communities|More recent') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_recent'})}},
  1113 + {s_('communities|More active') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_active'})}},
  1114 + {s_('communities|More popular') => {:href => url_for({:controller => 'search', :action => 'communities', :filter => 'more_popular'})}}
1113 ] 1115 ]
1114 if logged_in? 1116 if logged_in?
1115 links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})}) 1117 links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})})
@@ -1117,7 +1119,7 @@ module ApplicationHelper @@ -1117,7 +1119,7 @@ module ApplicationHelper
1117 end 1119 end
1118 1120
1119 link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "search", :action => 'communities'}, :id => 'submenu-communities') + 1121 link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "search", :action => 'communities'}, :id => 'submenu-communities') +
1120 - link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger') 1122 + link_to(content_tag(:span, _('Communities menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger')
1121 end 1123 end
1122 alias :browse_communities_menu :search_communities_menu 1124 alias :browse_communities_menu :search_communities_menu
1123 1125
@@ -1170,6 +1172,10 @@ module ApplicationHelper @@ -1170,6 +1172,10 @@ module ApplicationHelper
1170 ], :class => 'limited-text-area') 1172 ], :class => 'limited-text-area')
1171 end 1173 end
1172 1174
  1175 + def expandable_text_area(object_name, method, text_area_id, options = {})
  1176 + text_area(object_name, method, { :id => text_area_id, :onkeyup => "grow_text_area('#{text_area_id}')" }.merge(options))
  1177 + end
  1178 +
1173 def pluralize_without_count(count, singular, plural = nil) 1179 def pluralize_without_count(count, singular, plural = nil)
1174 count == 1 ? singular : (plural || singular.pluralize) 1180 count == 1 ? singular : (plural || singular.pluralize)
1175 end 1181 end
@@ -1318,4 +1324,70 @@ module ApplicationHelper @@ -1318,4 +1324,70 @@ module ApplicationHelper
1318 _("Are you sure that you want to remove the item \"#{article.name}\"?") 1324 _("Are you sure that you want to remove the item \"#{article.name}\"?")
1319 end 1325 end
1320 end 1326 end
  1327 +
  1328 + def template_options(klass, field_name)
  1329 + return '' if klass.templates.count == 0
  1330 + return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1
  1331 +
  1332 + counter = 0
  1333 + radios = klass.templates.map do |template|
  1334 + counter += 1
  1335 + content_tag('li', labelled_radio_button(template.name, "#{field_name}[template_id]", template.id, counter==1))
  1336 + end.join("\n")
  1337 +
  1338 + content_tag('div', content_tag('span', _('Template:')) +
  1339 + content_tag('ul', radios, :style => 'list-style: none; padding-left: 0; margin-top: 0.5em;'),
  1340 + :id => 'template-options',
  1341 + :style => 'margin-top: 1em'
  1342 + )
  1343 + end
  1344 +
  1345 + def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {})
  1346 + options[:min_chars] ||= 3
  1347 + options[:hint_text] ||= _("Type in a search term")
  1348 + options[:no_results_text] ||= _("No results")
  1349 + options[:searching_text] ||= _("Searching...")
  1350 + options[:search_delay] ||= 1000
  1351 + options[:prevent_duplicates] ||= true
  1352 + options[:backspace_delete_item] ||= false
  1353 + options[:focus] ||= false
  1354 + options[:avoid_enter] ||= true
  1355 + options[:on_result] ||= 'null'
  1356 + options[:on_add] ||= 'null'
  1357 + options[:on_delete] ||= 'null'
  1358 + options[:on_ready] ||= 'null'
  1359 +
  1360 + result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id})))
  1361 + result +=
  1362 + "
  1363 + <script type='text/javascript'>
  1364 + jQuery('##{element_id}')
  1365 + .tokenInput('#{url_for(search_action)}', {
  1366 + minChars: #{options[:min_chars].to_json},
  1367 + prePopulate: #{options[:pre_populate].to_json},
  1368 + hintText: #{options[:hint_text].to_json},
  1369 + noResultsText: #{options[:no_results_text].to_json},
  1370 + searchingText: #{options[:searching_text].to_json},
  1371 + searchDelay: #{options[:serach_delay].to_json},
  1372 + preventDuplicates: #{options[:prevent_duplicates].to_json},
  1373 + backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
  1374 + queryParam: #{name.to_json},
  1375 + tokenLimit: #{options[:token_limit].to_json},
  1376 + onResult: #{options[:on_result]},
  1377 + onAdd: #{options[:on_add]},
  1378 + onDelete: #{options[:on_delete]},
  1379 + onReady: #{options[:on_ready]},
  1380 + })
  1381 + "
  1382 + result += options[:focus] ? ".focus();" : ";"
  1383 + if options[:avoid_enter]
  1384 + result += "jQuery('#token-input-#{element_id}')
  1385 + .live('keydown', function(event){
  1386 + if(event.keyCode == '13') return false;
  1387 + });"
  1388 + end
  1389 + result += "</script>"
  1390 + result
  1391 + end
  1392 +
1321 end 1393 end
app/helpers/colorbox_helper.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +module ColorboxHelper
  2 +
  3 + def colorbox_close_button(text, options = {})
  4 + button(:close, text, '#', colorbox_options(options, :close))
  5 + end
  6 +
  7 + def colorbox_button(type, label, url, options = {})
  8 + button(type, label, url, colorbox_options(options))
  9 + end
  10 +
  11 + # options must be an HTML options hash as passed to link_to etc.
  12 + #
  13 + # returns a new hash with colorbox class added. Keeps existing classes.
  14 + def colorbox_options(options, type=nil)
  15 + the_class = 'colorbox'
  16 + the_class += "-#{type.to_s}" unless type.nil?
  17 + the_class << " #{options[:class]}" if options.has_key?(:class)
  18 + options.merge(:class => the_class)
  19 + end
  20 +
  21 +end
app/helpers/search_helper.rb
@@ -18,7 +18,7 @@ module SearchHelper @@ -18,7 +18,7 @@ module SearchHelper
18 18
19 SortOptions = { 19 SortOptions = {
20 :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, 20 :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
21 - :more_recent, {:label => _('More Recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}}, 21 + :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
22 :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, 22 :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
23 :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng }, 23 :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng },
24 :solr_opts => {:sort => "geodist() asc", 24 :solr_opts => {:sort => "geodist() asc",
@@ -45,6 +45,14 @@ module SearchHelper @@ -45,6 +45,14 @@ module SearchHelper
45 # FIXME remove it after search_controler refactored 45 # FIXME remove it after search_controler refactored
46 include EventsHelper 46 include EventsHelper
47 47
  48 + def multiple_search?
  49 + ['index', 'category_index'].include?(params[:action]) or @results.size > 1
  50 + end
  51 +
  52 + def map_search?
  53 + !@query.blank? and !multiple_search? and params[:display] == 'map'
  54 + end
  55 +
48 def search_page_title(title, category = nil) 56 def search_page_title(title, category = nil)
49 title = "<h1>" + title 57 title = "<h1>" + title
50 title += '<small>' + category.name + '</small>' if category 58 title += '<small>' + category.name + '</small>' if category
@@ -58,8 +66,8 @@ module SearchHelper @@ -58,8 +66,8 @@ module SearchHelper
58 :align => 'center', :class => 'search-category-context') if category 66 :align => 'center', :class => 'search-category-context') if category
59 end 67 end
60 68
61 - def display_results(use_map = false)  
62 - if params[:display] == 'map' && use_map 69 + def display_results(map_capable = false)
  70 + if map_capable and map_search?
63 partial = 'google_maps' 71 partial = 'google_maps'
64 klass = 'map' 72 klass = 'map'
65 else 73 else
app/models/article.rb
@@ -34,9 +34,12 @@ class Article &lt; ActiveRecord::Base @@ -34,9 +34,12 @@ class Article &lt; ActiveRecord::Base
34 settings_items :display_hits, :type => :boolean, :default => true 34 settings_items :display_hits, :type => :boolean, :default => true
35 settings_items :author_name, :type => :string, :default => "" 35 settings_items :author_name, :type => :string, :default => ""
36 settings_items :allow_members_to_edit, :type => :boolean, :default => false 36 settings_items :allow_members_to_edit, :type => :boolean, :default => false
  37 + settings_items :followers, :type => Array, :default => []
37 38
38 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' 39 belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id'
39 40
  41 + belongs_to :license
  42 +
40 has_many :translations, :class_name => 'Article', :foreign_key => :translation_of_id 43 has_many :translations, :class_name => 'Article', :foreign_key => :translation_of_id
41 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id 44 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id
42 before_destroy :rotate_translations 45 before_destroy :rotate_translations
@@ -51,6 +54,11 @@ class Article &lt; ActiveRecord::Base @@ -51,6 +54,11 @@ class Article &lt; ActiveRecord::Base
51 end 54 end
52 end 55 end
53 56
  57 + after_destroy :destroy_activity
  58 + def destroy_activity
  59 + self.activity.destroy if self.activity
  60 + end
  61 +
54 xss_terminate :only => [ :name ], :on => 'validation', :with => 'white_list' 62 xss_terminate :only => [ :name ], :on => 'validation', :with => 'white_list'
55 63
56 named_scope :in_category, lambda { |category| 64 named_scope :in_category, lambda { |category|
app/models/comment.rb
@@ -75,11 +75,30 @@ class Comment &lt; ActiveRecord::Base @@ -75,11 +75,30 @@ class Comment &lt; ActiveRecord::Base
75 article.comments_updated if article.kind_of?(Article) 75 article.comments_updated if article.kind_of?(Article)
76 end 76 end
77 77
78 - after_create do |comment|  
79 - if comment.source.kind_of?(Article) && comment.article.notify_comments? && !comment.article.profile.notification_emails.empty?  
80 - Comment::Notifier.deliver_mail(comment) 78 + after_create :new_follower
  79 + def new_follower
  80 + if source.kind_of?(Article)
  81 + article.followers += [author_email]
  82 + article.followers -= article.profile.notification_emails
  83 + article.followers.uniq!
  84 + article.save
  85 + end
  86 + end
  87 +
  88 + after_create :notify_by_mail
  89 + def notify_by_mail
  90 + if source.kind_of?(Article) && article.notify_comments?
  91 + if !article.profile.notification_emails.empty?
  92 + Comment::Notifier.deliver_mail(self)
  93 + end
  94 + emails = article.followers - [author_email]
  95 + if !emails.empty?
  96 + Comment::Notifier.deliver_mail_to_followers(self, emails)
  97 + end
81 end 98 end
  99 + end
82 100
  101 + after_create do |comment|
83 if comment.source.kind_of?(Article) 102 if comment.source.kind_of?(Article)
84 comment.article.create_activity if comment.article.activity.nil? 103 comment.article.create_activity if comment.article.activity.nil?
85 if comment.article.activity 104 if comment.article.activity
@@ -138,6 +157,22 @@ class Comment &lt; ActiveRecord::Base @@ -138,6 +157,22 @@ class Comment &lt; ActiveRecord::Base
138 :environment => profile.environment.name, 157 :environment => profile.environment.name,
139 :url => profile.environment.top_url 158 :url => profile.environment.top_url
140 end 159 end
  160 + def mail_to_followers(comment, emails)
  161 + profile = comment.article.profile
  162 + bcc emails
  163 + from "#{profile.environment.name} <#{profile.environment.contact_email}>"
  164 + subject _("[%s] %s commented on a content of %s") % [profile.environment.name, comment.author_name, profile.short_name]
  165 + body :recipient => profile.nickname || profile.name,
  166 + :sender => comment.author_name,
  167 + :sender_link => comment.author_link,
  168 + :article_title => comment.article.name,
  169 + :comment_url => comment.url,
  170 + :unsubscribe_url => comment.article.view_url.merge({:unfollow => true}),
  171 + :comment_title => comment.title,
  172 + :comment_body => comment.body,
  173 + :environment => profile.environment.name,
  174 + :url => profile.environment.top_url
  175 + end
141 end 176 end
142 177
143 def rejected? 178 def rejected?
app/models/community.rb
@@ -61,10 +61,10 @@ class Community &lt; Organization @@ -61,10 +61,10 @@ class Community &lt; Organization
61 61
62 def name=(value) 62 def name=(value)
63 super(value) 63 super(value)
64 - self.identifier = value.to_slug 64 + self.identifier ||= value.to_slug
65 end 65 end
66 66
67 - def template 67 + def default_template
68 environment.community_template 68 environment.community_template
69 end 69 end
70 70
@@ -88,7 +88,7 @@ class Community &lt; Organization @@ -88,7 +88,7 @@ class Community &lt; Organization
88 end 88 end
89 89
90 def activities 90 def activities
91 - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC") 91 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} and action_tracker.verb != 'join_community' and action_tracker.verb != 'leave_scrap' UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC")
92 end 92 end
93 93
94 end 94 end
app/models/enterprise.rb
@@ -154,13 +154,14 @@ class Enterprise &lt; Organization @@ -154,13 +154,14 @@ class Enterprise &lt; Organization
154 true 154 true
155 end 155 end
156 156
157 - def template  
158 - if enabled?  
159 - environment.enterprise_template  
160 - else  
161 - environment.inactive_enterprise_template  
162 - end 157 + def default_template
  158 + environment.enterprise_template
  159 + end
  160 +
  161 + def template_with_inactive_enterprise
  162 + !enabled? ? environment.inactive_enterprise_template : template_without_inactive_enterprise
163 end 163 end
  164 + alias_method_chain :template, :inactive_enterprise
164 165
165 def control_panel_settings_button 166 def control_panel_settings_button
166 {:title => __('Enterprise Info and settings'), :icon => 'edit-profile-enterprise'} 167 {:title => __('Enterprise Info and settings'), :icon => 'edit-profile-enterprise'}
app/models/environment.rb
@@ -24,6 +24,8 @@ class Environment &lt; ActiveRecord::Base @@ -24,6 +24,8 @@ class Environment &lt; ActiveRecord::Base
24 'manage_environment_roles' => N_('Manage environment roles'), 24 'manage_environment_roles' => N_('Manage environment roles'),
25 'manage_environment_validators' => N_('Manage environment validators'), 25 'manage_environment_validators' => N_('Manage environment validators'),
26 'manage_environment_users' => N_('Manage environment users'), 26 'manage_environment_users' => N_('Manage environment users'),
  27 + 'manage_environment_templates' => N_('Manage environment templates'),
  28 + 'manage_environment_licenses' => N_('Manage environment licenses'),
27 } 29 }
28 30
29 module Roles 31 module Roles
@@ -158,6 +160,7 @@ class Environment &lt; ActiveRecord::Base @@ -158,6 +160,7 @@ class Environment &lt; ActiveRecord::Base
158 has_many :products, :through => :enterprises 160 has_many :products, :through => :enterprises
159 has_many :people 161 has_many :people
160 has_many :communities 162 has_many :communities
  163 + has_many :licenses
161 164
162 has_many :categories 165 has_many :categories
163 has_many :display_categories, :class_name => 'Category', :conditions => 'display_color is not null and parent_id is null', :order => 'display_color' 166 has_many :display_categories, :class_name => 'Category', :conditions => 'display_color is not null and parent_id is null', :order => 'display_color'
@@ -719,12 +722,12 @@ class Environment &lt; ActiveRecord::Base @@ -719,12 +722,12 @@ class Environment &lt; ActiveRecord::Base
719 722
720 def create_templates 723 def create_templates
721 pre = self.name.to_slug + '_' 724 pre = self.name.to_slug + '_'
722 - ent_id = Enterprise.create!(:name => 'Enterprise template', :identifier => pre + 'enterprise_template', :environment => self, :visible => false).id  
723 - inactive_enterprise_tmpl = Enterprise.create!(:name => 'Inactive Enterprise template', :identifier => pre + 'inactive_enterprise_template', :environment => self, :visible => false)  
724 - com_id = Community.create!(:name => 'Community template', :identifier => pre + 'community_template', :environment => self, :visible => false).id 725 + ent_id = Enterprise.create!(:name => 'Enterprise template', :identifier => pre + 'enterprise_template', :environment => self, :visible => false, :is_template => true).id
  726 + inactive_enterprise_tmpl = Enterprise.create!(:name => 'Inactive Enterprise template', :identifier => pre + 'inactive_enterprise_template', :environment => self, :visible => false, :is_template => true)
  727 + com_id = Community.create!(:name => 'Community template', :identifier => pre + 'community_template', :environment => self, :visible => false, :is_template => true).id
725 pass = Digest::MD5.hexdigest rand.to_s 728 pass = Digest::MD5.hexdigest rand.to_s
726 user = User.create!(:login => (pre + 'person_template'), :email => (pre + 'template@template.noo'), :password => pass, :password_confirmation => pass, :environment => self).person 729 user = User.create!(:login => (pre + 'person_template'), :email => (pre + 'template@template.noo'), :password => pass, :password_confirmation => pass, :environment => self).person
727 - user.update_attributes(:visible => false, :name => "Person template") 730 + user.update_attributes(:visible => false, :name => "Person template", :is_template => true)
728 usr_id = user.id 731 usr_id = user.id
729 self.settings[:enterprise_template_id] = ent_id 732 self.settings[:enterprise_template_id] = ent_id
730 self.inactive_enterprise_template = inactive_enterprise_tmpl 733 self.inactive_enterprise_template = inactive_enterprise_tmpl
@@ -740,6 +743,18 @@ class Environment &lt; ActiveRecord::Base @@ -740,6 +743,18 @@ class Environment &lt; ActiveRecord::Base
740 end 743 end
741 end 744 end
742 745
  746 + after_create :create_default_licenses
  747 + def create_default_licenses
  748 + License.create!(:name => 'CC (by)', :url => 'http://creativecommons.org/licenses/by/3.0/legalcode', :environment => self)
  749 + License.create!(:name => 'CC (by-nd)', :url => 'http://creativecommons.org/licenses/by-nd/3.0/legalcode', :environment => self)
  750 + License.create!(:name => 'CC (by-sa)', :url => 'http://creativecommons.org/licenses/by-sa/3.0/legalcode', :environment => self)
  751 + License.create!(:name => 'CC (by-nc)', :url => 'http://creativecommons.org/licenses/by-nc/3.0/legalcode', :environment => self)
  752 + License.create!(:name => 'CC (by-nc-nd)', :url => 'http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', :environment => self)
  753 + License.create!(:name => 'CC (by-nc-sa)', :url => 'http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', :environment => self)
  754 + License.create!(:name => 'Free Art', :url => 'http://artlibre.org/licence/lal/en', :environment => self)
  755 + License.create!(:name => 'GNU FDL', :url => 'http://www.gnu.org/licenses/fdl-1.3.txt', :environment => self)
  756 + end
  757 +
743 def highlighted_products_with_image(options = {}) 758 def highlighted_products_with_image(options = {})
744 Product.find(:all, {:conditions => {:highlighted => true, :enterprise_id => self.enterprises.find(:all, :select => :id) }, :joins => :image}.merge(options)) 759 Product.find(:all, {:conditions => {:highlighted => true, :enterprise_id => self.enterprises.find(:all, :select => :id) }, :joins => :image}.merge(options))
745 end 760 end
app/models/input.rb
@@ -9,6 +9,8 @@ class Input &lt; ActiveRecord::Base @@ -9,6 +9,8 @@ class Input &lt; ActiveRecord::Base
9 9
10 belongs_to :unit 10 belongs_to :unit
11 11
  12 + named_scope :relevant_to_price, :conditions => { :relevant_to_price => true }
  13 +
12 include FloatHelper 14 include FloatHelper
13 15
14 def price_per_unit=(value) 16 def price_per_unit=(value)
app/models/license.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class License < ActiveRecord::Base
  2 + belongs_to :environment
  3 + has_many :content, :class_name => 'Article', :foreign_key => 'license_id'
  4 +
  5 + validates_presence_of :name, :environment
  6 + validates_presence_of :slug, :if => lambda {|license| license.name.present?}
  7 + validates_uniqueness_of :slug, :scope => :environment_id
  8 +
  9 + before_validation do |license|
  10 + license.slug ||= license.name.to_slug if license.name.present?
  11 + end
  12 +end
app/models/location_block.rb
1 class LocationBlock < Block 1 class LocationBlock < Block
2 2
3 - settings_items :zoom, :type => :integer , :default => 4  
4 - settings_items :map_type, :type => :string , :default => 'roadmap' 3 + settings_items :zoom, :type => :integer, :default => 4
  4 + settings_items :map_type, :type => :string, :default => 'roadmap'
5 5
6 def self.description 6 def self.description
7 _('Location map') 7 _('Location map')
@@ -12,18 +12,10 @@ class LocationBlock &lt; Block @@ -12,18 +12,10 @@ class LocationBlock &lt; Block
12 end 12 end
13 13
14 def content(args={}) 14 def content(args={})
  15 + block = self
15 profile = self.owner 16 profile = self.owner
16 - title = self.title  
17 - if profile.lat  
18 - block_title(title) +  
19 - content_tag('div',  
20 - '<img src="http://maps.google.com/maps/api/staticmap?center=' + profile.lat.to_s() +  
21 - ',' + profile.lng.to_s() + '&zoom=' + zoom.to_s() +  
22 - '&size=190x250&maptype=' + map_type + '&markers=' + profile.lat.to_s() + ',' +  
23 - profile.lng.to_s() + ',green' + '&sensor=false"/>',  
24 - :class => 'the-localization-map' )  
25 - else  
26 - content_tag('i', _('This profile has no geographical position registered.')) 17 + lambda do
  18 + render :file => 'blocks/location', :locals => {:block => block, :profile => profile}
27 end 19 end
28 end 20 end
29 21
app/models/mailing.rb
@@ -9,7 +9,11 @@ class Mailing &lt; ActiveRecord::Base @@ -9,7 +9,11 @@ class Mailing &lt; ActiveRecord::Base
9 xss_terminate :only => [ :subject, :body ], :with => 'white_list', :on => 'validation' 9 xss_terminate :only => [ :subject, :body ], :with => 'white_list', :on => 'validation'
10 10
11 after_create do |mailing| 11 after_create do |mailing|
12 - Delayed::Job.enqueue MailingJob.new(mailing.id) 12 + mailing.schedule
  13 + end
  14 +
  15 + def schedule
  16 + Delayed::Job.enqueue MailingJob.new(self.id)
13 end 17 end
14 18
15 def generate_from 19 def generate_from
@@ -30,8 +34,14 @@ class Mailing &lt; ActiveRecord::Base @@ -30,8 +34,14 @@ class Mailing &lt; ActiveRecord::Base
30 34
31 def deliver 35 def deliver
32 each_recipient do |recipient| 36 each_recipient do |recipient|
33 - Mailing::Sender.deliver_mail(self, recipient.email)  
34 - self.mailing_sents.create(:person => recipient) 37 + begin
  38 + Mailing::Sender.deliver_mail(self, recipient.email)
  39 + self.mailing_sents.create(:person => recipient)
  40 + rescue Exception
  41 + # FIXME should not discard errors silently. An idea is to collect all
  42 + # errors and generate a task (notification) for the +source+
  43 + # (environment/organization) listing these errors.
  44 + end
35 end 45 end
36 end 46 end
37 47
app/models/organization.rb
@@ -77,6 +77,7 @@ class Organization &lt; Profile @@ -77,6 +77,7 @@ class Organization &lt; Profile
77 state 77 state
78 country 78 country
79 tag_list 79 tag_list
  80 + template_id
80 ] 81 ]
81 82
82 def self.fields 83 def self.fields
app/models/person.rb
@@ -22,7 +22,22 @@ class Person &lt; Profile @@ -22,7 +22,22 @@ class Person &lt; Profile
22 super 22 super
23 end 23 end
24 24
25 - named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } } 25 + acts_as_having_hotspots
  26 +
  27 + named_scope :members_of, lambda { |resources|
  28 + resources = [resources] if !resources.kind_of?(Array)
  29 + conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ')
  30 + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] }
  31 + }
  32 +
  33 + def has_permission_with_plugins?(permission, profile)
  34 + permissions = [has_permission_without_plugins?(permission, profile)]
  35 + permissions += enabled_plugins.map do |plugin|
  36 + plugin.has_permission?(self, permission, profile)
  37 + end
  38 + permissions.include?(true)
  39 + end
  40 + alias_method_chain :has_permission?, :plugins
26 41
27 def memberships 42 def memberships
28 Profile.memberships_of(self) 43 Profile.memberships_of(self)
@@ -285,7 +300,7 @@ class Person &lt; Profile @@ -285,7 +300,7 @@ class Person &lt; Profile
285 end 300 end
286 end 301 end
287 302
288 - def template 303 + def default_template
289 environment.person_template 304 environment.person_template
290 end 305 end
291 306
@@ -443,7 +458,7 @@ class Person &lt; Profile @@ -443,7 +458,7 @@ class Person &lt; Profile
443 end 458 end
444 459
445 def activities 460 def activities
446 - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} ORDER BY updated_at DESC") 461 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' ORDER BY updated_at DESC")
447 end 462 end
448 463
449 protected 464 protected
app/models/price_detail.rb
@@ -4,9 +4,13 @@ class PriceDetail &lt; ActiveRecord::Base @@ -4,9 +4,13 @@ class PriceDetail &lt; ActiveRecord::Base
4 validates_presence_of :product_id 4 validates_presence_of :product_id
5 5
6 belongs_to :production_cost 6 belongs_to :production_cost
7 - validates_presence_of :production_cost_id 7 + validates_presence_of :production_cost
8 validates_uniqueness_of :production_cost_id, :scope => :product_id 8 validates_uniqueness_of :production_cost_id, :scope => :product_id
9 9
  10 + def name
  11 + production_cost.name
  12 + end
  13 +
10 def price 14 def price
11 self[:price] || 0 15 self[:price] || 0
12 end 16 end
app/models/product.rb
@@ -158,7 +158,7 @@ class Product &lt; ActiveRecord::Base @@ -158,7 +158,7 @@ class Product &lt; ActiveRecord::Base
158 158
159 def inputs_cost 159 def inputs_cost
160 return 0 if inputs.empty? 160 return 0 if inputs.empty?
161 - inputs.map(&:cost).inject { |sum,price| sum + price } 161 + inputs.relevant_to_price.map(&:cost).inject { |sum,price| sum + price }
162 end 162 end
163 163
164 def total_production_cost 164 def total_production_cost
@@ -201,6 +201,7 @@ class Product &lt; ActiveRecord::Base @@ -201,6 +201,7 @@ class Product &lt; ActiveRecord::Base
201 self.inputs(true).each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy } 201 self.inputs(true).each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy }
202 t_i = 1 if t_i == 0 # avoid division by 0 202 t_i = 1 if t_i == 0 # avoid division by 0
203 p = case (se_i.to_f/t_i)*100 203 p = case (se_i.to_f/t_i)*100
  204 + when 0 then [0, '']
204 when 0..24.999 then [0, _("0%")]; 205 when 0..24.999 then [0, _("0%")];
205 when 25..49.999 then [25, _("25%")]; 206 when 25..49.999 then [25, _("25%")];
206 when 50..74.999 then [50, _("50%")]; 207 when 50..74.999 then [50, _("50%")];
app/models/production_cost.rb
@@ -5,4 +5,5 @@ class ProductionCost &lt; ActiveRecord::Base @@ -5,4 +5,5 @@ class ProductionCost &lt; ActiveRecord::Base
5 validates_presence_of :name 5 validates_presence_of :name
6 validates_length_of :name, :maximum => 30, :allow_blank => true 6 validates_length_of :name, :maximum => 30, :allow_blank => true
7 validates_uniqueness_of :name, :scope => [:owner_id, :owner_type] 7 validates_uniqueness_of :name, :scope => [:owner_id, :owner_type]
  8 +
8 end 9 end
app/models/profile.rb
@@ -60,20 +60,33 @@ class Profile &lt; ActiveRecord::Base @@ -60,20 +60,33 @@ class Profile &lt; ActiveRecord::Base
60 } 60 }
61 61
62 acts_as_accessible 62 acts_as_accessible
  63 + acts_as_having_hotspots
63 64
64 named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } 65 named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } }
65 #FIXME: these will work only if the subclass is already loaded 66 #FIXME: these will work only if the subclass is already loaded
66 named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 67 named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
67 named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 68 named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
  69 + named_scope :templates, :conditions => {:is_template => true}
68 70
69 def members 71 def members
70 - Person.members_of(self) 72 + scopes = dispatch_scopes(:organization_members, self)
  73 + scopes << Person.members_of(self)
  74 + scopes.size == 1 ? scopes.first : Person.or_scope(scopes)
71 end 75 end
72 76
73 def members_count 77 def members_count
74 - members.count('DISTINCT(profiles.id)') 78 + members.count
75 end 79 end
76 80
  81 + class << self
  82 + def count_with_distinct(*args)
  83 + options = args.last || {}
  84 + count_without_distinct(:id, {:distinct => true}.merge(options))
  85 + end
  86 + alias_method_chain :count, :distinct
  87 + end
  88 +
  89 +
77 def members_by_role(role) 90 def members_by_role(role)
78 Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 91 Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id])
79 end 92 end
@@ -98,6 +111,7 @@ class Profile &lt; ActiveRecord::Base @@ -98,6 +111,7 @@ class Profile &lt; ActiveRecord::Base
98 has_many :action_tracker_notifications, :foreign_key => 'profile_id' 111 has_many :action_tracker_notifications, :foreign_key => 'profile_id'
99 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC' 112 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC'
100 has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy 113 has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy
  114 + belongs_to :template, :class_name => 'Profile', :foreign_key => 'template_id'
101 115
102 # FIXME ugly workaround 116 # FIXME ugly workaround
103 def self.human_attribute_name(attrib) 117 def self.human_attribute_name(attrib)
@@ -204,7 +218,7 @@ class Profile &lt; ActiveRecord::Base @@ -204,7 +218,7 @@ class Profile &lt; ActiveRecord::Base
204 end 218 end
205 219
206 belongs_to :region 220 belongs_to :region
207 - 221 +
208 def location(separator = ' - ') 222 def location(separator = ' - ')
209 myregion = self.region 223 myregion = self.region
210 if myregion 224 if myregion
@@ -274,8 +288,14 @@ class Profile &lt; ActiveRecord::Base @@ -274,8 +288,14 @@ class Profile &lt; ActiveRecord::Base
274 validates_format_of :identifier, :with => IDENTIFIER_FORMAT, :if => lambda { |profile| !profile.identifier.blank? } 288 validates_format_of :identifier, :with => IDENTIFIER_FORMAT, :if => lambda { |profile| !profile.identifier.blank? }
275 validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS 289 validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS
276 validates_uniqueness_of :identifier, :scope => :environment_id 290 validates_uniqueness_of :identifier, :scope => :environment_id
277 -  
278 validates_length_of :nickname, :maximum => 16, :allow_nil => true 291 validates_length_of :nickname, :maximum => 16, :allow_nil => true
  292 + validate :valid_template
  293 +
  294 + def valid_template
  295 + if template_id.present? and !template.is_template
  296 + errors.add(:template, _('is not a template.'))
  297 + end
  298 + end
279 299
280 before_create :set_default_environment 300 before_create :set_default_environment
281 def set_default_environment 301 def set_default_environment
@@ -285,12 +305,12 @@ class Profile &lt; ActiveRecord::Base @@ -285,12 +305,12 @@ class Profile &lt; ActiveRecord::Base
285 true 305 true
286 end 306 end
287 307
288 - # registar callback for creating boxes after the object is created. 308 + # registar callback for creating boxes after the object is created.
289 after_create :create_default_set_of_boxes 309 after_create :create_default_set_of_boxes
290 310
291 # creates the initial set of boxes when the profile is created. Can be 311 # creates the initial set of boxes when the profile is created. Can be
292 # overriden for each subclass to create a custom set of boxes for its 312 # overriden for each subclass to create a custom set of boxes for its
293 - # instances. 313 + # instances.
294 def create_default_set_of_boxes 314 def create_default_set_of_boxes
295 if template 315 if template
296 apply_template(template, :copy_articles => false) 316 apply_template(template, :copy_articles => false)
@@ -322,10 +342,15 @@ class Profile &lt; ActiveRecord::Base @@ -322,10 +342,15 @@ class Profile &lt; ActiveRecord::Base
322 end 342 end
323 343
324 # this method should be overwritten to provide the correct template 344 # this method should be overwritten to provide the correct template
325 - def template 345 + def default_template
326 nil 346 nil
327 end 347 end
328 348
  349 + def template_with_default
  350 + template_without_default || default_template
  351 + end
  352 + alias_method_chain :template, :default
  353 +
329 def apply_template(template, options = {:copy_articles => true}) 354 def apply_template(template, options = {:copy_articles => true})
330 copy_blocks_from(template) 355 copy_blocks_from(template)
331 copy_articles_from(template) if options[:copy_articles] 356 copy_articles_from(template) if options[:copy_articles]
@@ -405,7 +430,7 @@ class Profile &lt; ActiveRecord::Base @@ -405,7 +430,7 @@ class Profile &lt; ActiveRecord::Base
405 430
406 # returns +false+ 431 # returns +false+
407 def person? 432 def person?
408 - self.kind_of?(Person) 433 + self.kind_of?(Person)
409 end 434 end
410 435
411 def enterprise? 436 def enterprise?
@@ -513,7 +538,7 @@ private :generate_url, :url_options @@ -513,7 +538,7 @@ private :generate_url, :url_options
513 538
514 after_create :insert_default_article_set 539 after_create :insert_default_article_set
515 def insert_default_article_set 540 def insert_default_article_set
516 - if template 541 + if template
517 copy_articles_from template 542 copy_articles_from template
518 else 543 else
519 default_set_of_articles.each do |article| 544 default_set_of_articles.each do |article|
@@ -583,7 +608,7 @@ private :generate_url, :url_options @@ -583,7 +608,7 @@ private :generate_url, :url_options
583 raise _("%s can't have members") % self.class.name 608 raise _("%s can't have members") % self.class.name
584 end 609 end
585 end 610 end
586 - 611 +
587 def remove_member(person) 612 def remove_member(person)
588 self.disaffiliate(person, Profile::Roles.all_roles(environment.id)) 613 self.disaffiliate(person, Profile::Roles.all_roles(environment.id))
589 end 614 end
@@ -880,7 +905,7 @@ private :generate_url, :url_options @@ -880,7 +905,7 @@ private :generate_url, :url_options
880 905
881 def self.f_enabled_proc(enabled) 906 def self.f_enabled_proc(enabled)
882 enabled = enabled == "true" ? true : false 907 enabled = enabled == "true" ? true : false
883 - enabled ? _('Enabled') : _('Not enabled') 908 + enabled ? s_('facets|Enabled') : s_('facets|Not enabled')
884 end 909 end
885 def f_enabled 910 def f_enabled
886 self.enabled 911 self.enabled
@@ -909,7 +934,7 @@ private :generate_url, :url_options @@ -909,7 +934,7 @@ private :generate_url, :url_options
909 acts_as_searchable :fields => facets_fields_for_solr + [:extra_data_for_index, 934 acts_as_searchable :fields => facets_fields_for_solr + [:extra_data_for_index,
910 # searched fields 935 # searched fields
911 {:name => {:type => :text, :boost => 2.0}}, 936 {:name => {:type => :text, :boost => 2.0}},
912 - {:identifier => :text}, {:address => :text}, {:nickname => :text}, 937 + {:identifier => :text}, {:nickname => :text},
913 # filtered fields 938 # filtered fields
914 {:public => :boolean}, {:environment_id => :integer}, 939 {:public => :boolean}, {:environment_id => :integer},
915 {:category_filter => :integer}, 940 {:category_filter => :integer},
@@ -929,7 +954,7 @@ private :generate_url, :url_options @@ -929,7 +954,7 @@ private :generate_url, :url_options
929 954
930 def control_panel_settings_button 955 def control_panel_settings_button
931 {:title => _('Profile Info and settings'), :icon => 'edit-profile'} 956 {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
932 - end 957 + end
933 958
934 def followed_by?(person) 959 def followed_by?(person)
935 person.is_member_of?(self) 960 person.is_member_of?(self)
app/models/profile_list_block.rb
@@ -25,7 +25,7 @@ class ProfileListBlock &lt; Block @@ -25,7 +25,7 @@ class ProfileListBlock &lt; Block
25 end 25 end
26 26
27 def profile_count 27 def profile_count
28 - profiles.visible.count('DISTINCT(profiles.id)') 28 + profiles.visible.count
29 end 29 end
30 30
31 # the title of the block. Probably will be overriden in subclasses. 31 # the title of the block. Probably will be overriden in subclasses.
app/models/uploaded_file.rb
@@ -8,7 +8,7 @@ class UploadedFile &lt; Article @@ -8,7 +8,7 @@ class UploadedFile &lt; Article
8 _('File') 8 _('File')
9 end 9 end
10 10
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? }, :custom_target => :action_tracker_target 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? }, :custom_target => :parent
12 12
13 include ShortFilename 13 include ShortFilename
14 14
@@ -144,9 +144,4 @@ class UploadedFile &lt; Article @@ -144,9 +144,4 @@ class UploadedFile &lt; Article
144 def uploaded_file? 144 def uploaded_file?
145 true 145 true
146 end 146 end
147 -  
148 - def action_tracker_target  
149 - self  
150 - end  
151 -  
152 end 147 end
app/models/user.rb
@@ -21,12 +21,11 @@ class User &lt; ActiveRecord::Base @@ -21,12 +21,11 @@ class User &lt; ActiveRecord::Base
21 end 21 end
22 end 22 end
23 23
24 - before_create :make_activation_code  
25 -  
26 before_create do |user| 24 before_create do |user|
27 if user.environment.nil? 25 if user.environment.nil?
28 user.environment = Environment.default 26 user.environment = Environment.default
29 end 27 end
  28 + user.send(:make_activation_code) unless user.environment.enabled?('skip_new_user_email_confirmation')
30 end 29 end
31 30
32 after_create do |user| 31 after_create do |user|
@@ -35,7 +34,7 @@ class User &lt; ActiveRecord::Base @@ -35,7 +34,7 @@ class User &lt; ActiveRecord::Base
35 user.person.name ||= user.login 34 user.person.name ||= user.login
36 user.person.visible = false unless user.activated? 35 user.person.visible = false unless user.activated?
37 user.person.save! 36 user.person.save!
38 - if user.environment && user.environment.enabled?('skip_new_user_email_confirmation') 37 + if user.environment.enabled?('skip_new_user_email_confirmation')
39 user.activate 38 user.activate
40 end 39 end
41 end 40 end
@@ -114,10 +113,11 @@ class User &lt; ActiveRecord::Base @@ -114,10 +113,11 @@ class User &lt; ActiveRecord::Base
114 113
115 # Activates the user in the database. 114 # Activates the user in the database.
116 def activate 115 def activate
  116 + return false unless self.person
117 self.activated_at = Time.now.utc 117 self.activated_at = Time.now.utc
118 self.activation_code = nil 118 self.activation_code = nil
119 self.person.visible = true 119 self.person.visible = true
120 - self.person.save! && self.save 120 + self.person.save! && self.save!
121 end 121 end
122 122
123 def activated? 123 def activated?
app/views/account/_signup_form.rhtml
@@ -69,6 +69,8 @@ @@ -69,6 +69,8 @@
69 69
70 <div id="signup-form-profile"> 70 <div id="signup-form-profile">
71 71
  72 + <%= template_options(Person, 'profile_data') %>
  73 +
72 <% labelled_fields_for :profile_data, @person do |f| %> 74 <% labelled_fields_for :profile_data, @person do |f| %>
73 <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %> 75 <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %>
74 <% end %> 76 <% end %>
app/views/admin_panel/edit_templates.rhtml
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<h1><%= _('Edit Templates') %></h1>  
2 -  
3 -<ul>  
4 -<% [[_('Edit Person Template'), environment.person_template],  
5 - [_('Edit Community Template'), environment.community_template],  
6 - [__('Edit Enterprise Template'), environment.enterprise_template],  
7 - [__('Edit Inactive Enterprise Template'), environment.inactive_enterprise_template]].select{|i| i[1]}.each do |row| %>  
8 -<li><%= link_to row[0], :controller => 'profile_editor', :profile => row[1].identifier %></li>  
9 -<% end %>  
10 -</ul>  
app/views/admin_panel/index.rhtml
@@ -12,9 +12,10 @@ @@ -12,9 +12,10 @@
12 <tr><td><%= link_to _('Manage User roles'), :controller => 'role' %></td></tr> 12 <tr><td><%= link_to _('Manage User roles'), :controller => 'role' %></td></tr>
13 <tr><td><%= link_to _('Manage users'), :controller => 'users' %></td></tr> 13 <tr><td><%= link_to _('Manage users'), :controller => 'users' %></td></tr>
14 <tr><td><%= link_to _('Manage Validators by region'), :controller => 'region_validators' %></td></tr> 14 <tr><td><%= link_to _('Manage Validators by region'), :controller => 'region_validators' %></td></tr>
15 - <tr><td><%= link_to _('Edit Templates'), :action => 'edit_templates' %></td></tr> 15 + <tr><td><%= link_to _('Edit Templates'), :controller => 'templates' %></td></tr>
16 <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> 16 <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr>
17 <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> 17 <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr>
  18 + <tr><td><%= link_to _('Manage Licenses'), :controller =>'licenses' %></td></tr>
18 <% @plugins.dispatch(:admin_panel_links).each do |link| %> 19 <% @plugins.dispatch(:admin_panel_links).each do |link| %>
19 <tr><td><%= link_to link[:title], link[:url] %></td></tr> 20 <tr><td><%= link_to link[:title], link[:url] %></td></tr>
20 <% end %> 21 <% end %>
app/views/blocks/location.html.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<% if profile.lat %>
  2 + <%= block_title block.title %>
  3 + <div class='the-localization-map'>
  4 + <img src="http://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
  5 + </div>
  6 +</div>
  7 +<% else %>
  8 + <i><%= _('This profile has no geographical position registered.') %></i>
  9 +<% end %>
app/views/catalog/index.rhtml
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 <div> 56 <div>
57 <div class="arrow"></div> 57 <div class="arrow"></div>
58 <div class="content" id="product-price-composition"> 58 <div class="content" id="product-price-composition">
59 - <% product.inputs.each do |i| %> 59 + <% product.inputs.relevant_to_price.each do |i| %>
60 <div class="search-product-input-dots-to-price"> 60 <div class="search-product-input-dots-to-price">
61 <div class="search-product-input-name"><%= i.product_category.name %></div> 61 <div class="search-product-input-name"><%= i.product_category.name %></div>
62 <%= price_span i.cost, :class => 'search-product-input-price' %> 62 <%= price_span i.cost, :class => 'search-product-input-price' %>
app/views/cms/_blog.rhtml
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 6
7 <%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %> 7 <%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %>
8 8
  9 +<%= render :partial => 'general_fields' %>
  10 +
9 <script type="text/javascript"> 11 <script type="text/javascript">
10 function submit_button(index) { 12 function submit_button(index) {
11 return $("article_slug").form.select("input.submit")[index]; 13 return $("article_slug").form.select("input.submit")[index];
app/views/cms/_event.rhtml
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 5
6 <%= required f.text_field('name', :size => '64') %> 6 <%= required f.text_field('name', :size => '64') %>
7 7
  8 +<%= render :partial => 'general_fields' %>
8 <%= render :partial => 'translatable' %> 9 <%= render :partial => 'translatable' %>
9 10
10 <%= labelled_form_field(_('Start date'), pick_date(:article, :start_date)) %> 11 <%= labelled_form_field(_('Start date'), pick_date(:article, :start_date)) %>
app/views/cms/_folder.rhtml
1 <%= required_fields_message %> 1 <%= required_fields_message %>
2 2
3 <%= required f.text_field('name', :size => '64') %> 3 <%= required f.text_field('name', :size => '64') %>
  4 +<%= render :partial => 'general_fields' %>
4 5
5 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %> 6 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %>
app/views/cms/_forum.rhtml
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 6
7 <%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %> 7 <%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %>
8 8
  9 +<%= render :partial => 'general_fields' %>
  10 +
9 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :cols => 64, :rows => 10)) %> 11 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :cols => 64, :rows => 10)) %>
10 12
11 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, [5, 10, 20, 50, 100])) %> 13 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, [5, 10, 20, 50, 100])) %>
app/views/cms/_gallery.rhtml
@@ -2,4 +2,6 @@ @@ -2,4 +2,6 @@
2 2
3 <%= required f.text_field('name', :size => '64') %> 3 <%= required f.text_field('name', :size => '64') %>
4 4
  5 +<%= render :partial => 'general_fields' %>
  6 +
5 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %> 7 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %>
app/views/cms/_general_fields.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %>
app/views/cms/_published_article.rhtml
1 <%= f.text_field 'name', :size => '64' %> 1 <%= f.text_field 'name', :size => '64' %>
  2 +<%= render :partial => 'general_fields' %>
2 3
3 <p><%= _('This is a republication of "%s", by %s.') % [link_to(h(@article.reference_article.name), @article.reference_article.url), @article.reference_article.profile.name] %></p> 4 <p><%= _('This is a republication of "%s", by %s.') % [link_to(h(@article.reference_article.name), @article.reference_article.url), @article.reference_article.profile.name] %></p>
app/views/cms/_raw_html_article.rhtml
@@ -2,5 +2,6 @@ @@ -2,5 +2,6 @@
2 2
3 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> 3 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %>
4 4
  5 +<%= render :partial => 'general_fields' %>
5 <%= render :partial => 'translatable' %> 6 <%= render :partial => 'translatable' %>
6 <%= render :partial => 'shared/lead_and_body' %> 7 <%= render :partial => 'shared/lead_and_body' %>
app/views/cms/_rss_feed.rhtml
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 2
3 <%= required f.text_field(:name) %> 3 <%= required f.text_field(:name) %>
4 4
  5 +<%= render :partial => 'general_fields' %>
  6 +
5 <%= required labelled_form_field(_('Limit of articles'), text_field(:article, :limit)) %> 7 <%= required labelled_form_field(_('Limit of articles'), text_field(:article, :limit)) %>
6 8
7 <%= labelled_form_field(_('Include in RSS Feed only posts from language:'), f.select(:language, [[_('All'), nil ]] + Noosfero.locales.map { |k,v| [v, k]})) %> 9 <%= labelled_form_field(_('Include in RSS Feed only posts from language:'), f.select(:language, [[_('All'), nil ]] + Noosfero.locales.map { |k,v| [v, k]})) %>
app/views/cms/_textile_article.rhtml
@@ -4,5 +4,6 @@ @@ -4,5 +4,6 @@
4 4
5 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72')) %> 5 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72')) %>
6 6
  7 +<%= render :partial => 'general_fields' %>
7 <%= render :partial => 'translatable' %> 8 <%= render :partial => 'translatable' %>
8 <%= render :partial => 'shared/lead_and_body' %> 9 <%= render :partial => 'shared/lead_and_body' %>
app/views/cms/_tiny_mce_article.rhtml
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 <div> 5 <div>
6 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> 6 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %>
7 7
  8 + <%= render :partial => 'general_fields' %>
8 <%= render :partial => 'translatable' %> 9 <%= render :partial => 'translatable' %>
9 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true} %> 10 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true} %>
10 </div> 11 </div>
app/views/cms/select_article_type.rhtml
@@ -13,4 +13,4 @@ @@ -13,4 +13,4 @@
13 </ul> 13 </ul>
14 <br style="clear:both" /> 14 <br style="clear:both" />
15 15
16 -<%= lightbox_close_button(_('Cancel')) %> 16 +<%= colorbox_close_button(_('Cancel')) %>
app/views/cms/view.rhtml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <% button_bar(:style => 'margin-bottom: 1em;') do %> 5 <% button_bar(:style => 'margin-bottom: 1em;') do %>
6 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> 6 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %>
7 7
8 - <%= lightbox_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %> 8 + <%= colorbox_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %>
9 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %> 9 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %>
10 <% end %> 10 <% end %>
11 11
app/views/comment/notifier/mail_to_followers.rhtml 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +<%= _('Hi!') %>
  2 +
  3 +<%= word_wrap(_('%{sender} (%{sender_link}) commented on the content "%{article_title}".') % { :sender => @sender, :sender_link => url_for(@sender_link), :article_title => @article_title }) %>
  4 +
  5 +<%= word_wrap(_('Title: %s') % @comment_title) if @comment_title %>
  6 +
  7 +<%= _("Comment:") %>
  8 +-------------------------------------------------------------------------------
  9 +<%= word_wrap(@comment_body) %>
  10 +-------------------------------------------------------------------------------
  11 +
  12 +<%= _('Click on the address below to view this comment:') %>
  13 +<%= url_for @comment_url %>
  14 +
  15 +<%= _('Click on the address below to cancel the notification of new comments:') %>
  16 +<%= url_for @unsubscribe_url %>
  17 +
  18 +<%= _("Greetings,") %>
  19 +
  20 +--
  21 +<%= _('%s team.') % @environment %>
  22 +<%= url_for @url %>
app/views/content_viewer/_article_toolbar.rhtml
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)), 33 :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)),
34 :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }), 34 :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }),
35 :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %> 35 :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %>
36 - <%= lightbox_remote_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> 36 + <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %>
37 <% end %> 37 <% end %>
38 38
39 <% if @page.accept_uploads? && @page.allow_create?(user) %> 39 <% if @page.accept_uploads? && @page.allow_create?(user) %>
app/views/content_viewer/_confirm_unfollow.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<% if @unfollow_form %>
  2 +<div class='unfollow-article'>
  3 + <h1><%= _('Cancel notification of new comments') %></h1>
  4 + <p><%= _("Fill in the following field with your e-mail if you don't want to be notified when this content receives new comments anymore.") %></p>
  5 + <% form_tag(@page.view_url.merge({:only_path => true}), {:method => 'post', :class => 'comment_form'}) do %>
  6 + <%= hidden_field_tag(:unfollow, 'commit') %>
  7 + <%= labelled_form_field(_('Enter your e-Mail'), text_field_tag(:email, nil, {:size => 40})) %>
  8 + <% button_bar do %>
  9 + <%= submit_button(:ok, _('Cancel notifications for e-mail above') ) %>
  10 + <% end %>
  11 + <% end %>
  12 +</div>
  13 +<% end %>
app/views/content_viewer/view_page.rhtml
@@ -6,12 +6,30 @@ @@ -6,12 +6,30 @@
6 6
7 <div id="article" class="<%= @page.css_class_name %>"> 7 <div id="article" class="<%= @page.css_class_name %>">
8 8
  9 +<%= render :partial => 'confirm_unfollow' %>
  10 +
9 <div id="article-toolbar"></div> 11 <div id="article-toolbar"></div>
10 12
11 <script type="text/javascript"> 13 <script type="text/javascript">
12 - <%= remote_function :update => "article-toolbar", :url => @page.url.merge({ :toolbar => true, :only_path => true }), :complete => "$$('#article-toolbar .remote-lbOn').each(function(link) { new lightbox(link); }); jQuery('#article-toolbar .simplemenu-trigger').click(function(e) { e.stopPropagation(); })" %> 14 + <%= remote_function :update => "article-toolbar", :url => @page.url.merge({ :toolbar => true, :only_path => true }) %>
13 </script> 15 </script>
14 16
  17 +<% if @page.display_hits? || @page.license.present? %>
  18 + <div id='article-sub-header'>
  19 + <% if @page.display_hits? %>
  20 + <div id="article-hits">
  21 + <%= n_('Viewed one time', 'Viewed %{num} times', @page.hits) % { :num => @page.hits } %>
  22 + </div>
  23 + <% end %>
  24 +
  25 + <% if @page.license.present? %>
  26 + <div id="article-license">
  27 + <%= _('Licensed under %s') % (@page.license.url.present? ? link_to(@page.license.name, @page.license.url, :target => '_blank') : @page.license.name) %>
  28 + </div>
  29 + <% end %>
  30 + </div>
  31 +<% end %>
  32 +
15 <% if !@page.tags.empty? %> 33 <% if !@page.tags.empty? %>
16 <div id="article-tags"> 34 <div id="article-tags">
17 <%= _("This article's tags:") %> 35 <%= _("This article's tags:") %>
@@ -19,12 +37,6 @@ @@ -19,12 +37,6 @@
19 </div> 37 </div>
20 <% end %> 38 <% end %>
21 39
22 -<% if @page.display_hits? %>  
23 - <div id="article-hits">  
24 - <%= n_('Viewed one time', 'Viewed %{num} times', @page.hits) % { :num => @page.hits } %>  
25 - </div>  
26 -<% end %>  
27 -  
28 <% if @page.parent && !@page.parent.path.blank? %> 40 <% if @page.parent && !@page.parent.path.blank? %>
29 <div id="article-parent"> 41 <div id="article-parent">
30 <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %> 42 <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %>
app/views/edit_template/index.rhtml
@@ -1,14 +0,0 @@ @@ -1,14 +0,0 @@
1 -mexendo o contedudo para ver como fica a parada toda  
2 -mexendo o contedudo para ver como fica a parada toda  
3 -mexendo o contedudo para ver como fica a parada toda  
4 -mexendo o contedudo para ver como fica a parada toda  
5 -mexendo o contedudo para ver como fica a parada toda  
6 -mexendo o contedudo para ver como fica a parada toda  
7 -mexendo o contedudo para ver como fica a parada toda  
8 -mexendo o contedudo para ver como fica a parada toda  
9 -mexendo o contedudo para ver como fica a parada toda  
10 -mexendo o contedudo para ver como fica a parada toda  
11 -mexendo o contedudo para ver como fica a parada toda  
12 -mexendo o contedudo para ver como fica a parada toda  
13 -mexendo o contedudo para ver como fica a parada toda  
14 -  
app/views/enterprise_registration/basic_information.rhtml
@@ -28,6 +28,14 @@ @@ -28,6 +28,14 @@
28 <%= hidden_field_tag 'create_enterprise[target_id]', environment.id %> 28 <%= hidden_field_tag 'create_enterprise[target_id]', environment.id %>
29 <% end %> 29 <% end %>
30 30
  31 + <% @plugins.dispatch(:enterprise_registration_hidden_fields).each do |field| %>
  32 + <% field.each do |key, value| %>
  33 + <%= f.hidden_field(key, :value => value) %>
  34 + <% end %>
  35 + <% end %>
  36 +
  37 + <%= template_options(Enterprise, 'create_enterprise')%>
  38 +
31 <% button_bar do %> 39 <% button_bar do %>
32 <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %> 40 <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %>
33 <% end %> 41 <% end %>
app/views/licenses/_form.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<%= error_messages_for :license %>
  2 +
  3 +<% form_for :license, @license do |f| %>
  4 + <%= hidden_field_tag(:license_id, params[:license_id]) %>
  5 + <%= required labelled_form_field(_('Name'), f.text_field(:name)) %>
  6 + <%= labelled_form_field(_('License url'), f.text_field(:url)) %>
  7 +
  8 + <% button_bar do %>
  9 + <%= submit_button('save', _('Save'))%>
  10 + <%= button('cancel', _('Cancel'), {:action => 'index'})%>
  11 + <% end %>
  12 +<% end %>
app/views/licenses/create.html.erb 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +<h1><%= _('New license') %></h1>
  2 +<%= render :partial => 'form' %>
app/views/licenses/edit.html.erb 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +<h1><%= _('Edit license') %></h1>
  2 +<%= render :partial => 'form' %>
app/views/licenses/index.html.erb 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +<h1><%= _('Manage licenses') %></h1>
  2 +<table style='overflow: hidden;'>
  3 + <tr>
  4 + <th style='width: 25%'><%= _('Name') %></th>
  5 + <th style='width: 60%'><%= _('Url reference') %></th>
  6 + <th style='width: 15%'><%= _('Actions') %></th>
  7 + </tr>
  8 + <% @licenses.each do |license| %>
  9 + <tr>
  10 + <td title="<%= license.name%>"><%= truncate(license.name, :length => 19) %></td>
  11 + <td title="<%= license.url %>"><%= license.url.present? ? link_to(truncate(license.url, :length => 60), license.url, :target => '_blank') : '' %></td>
  12 + <td style='white-space: nowrap;'>
  13 + <%= button_without_text :edit, _('Edit'), :action => 'edit', :license_id => license.id %>
  14 + <%= button_without_text :remove, _('Remove'), {:action => 'remove', :license_id => license.id}, :method => 'post', :confirm => _('Are you sure you want to remove this license?') %></td>
  15 + </tr>
  16 + <% end %>
  17 +</table>
  18 +
  19 +<% button_bar do %>
  20 + <%= button(:add, _('Add a new license'), :action => 'create')%>
  21 + <%= button :back, _('Back to admin panel'), :controller => 'admin_panel' %>
  22 +<% end %>
app/views/maps/_google_map.js.erb
@@ -5,27 +5,113 @@ var marker; @@ -5,27 +5,113 @@ var marker;
5 var center; 5 var center;
6 var move = true; 6 var move = true;
7 var previousCenter; 7 var previousCenter;
  8 +var mapZoom = 15;
  9 +var delay_autocomplete = 500;
8 10
9 -function getAddress(latlng) { 11 +function pointToAddress(latlng) {
10 $('location-fields').addClassName("loading"); 12 $('location-fields').addClassName("loading");
11 13
12 - if (latlng != null) {  
13 - geocoder.geocode( {'latLng': latlng}, showAddress);  
14 - } 14 + if (latlng == null)
  15 + return;
  16 +
  17 + geocoder.geocode( {'latLng': latlng}, function(results, status) {
  18 + if (status != google.maps.GeocoderStatus.OK) {
  19 + alert("<%=_("Address not found, reason:")%>" + statusErrorMessage(status));
  20 + return;
  21 + }
  22 +
  23 + var place = results[0];
  24 +
  25 + $('location-fields').removeClassName("loading");
  26 +
  27 + var position = marker.getPosition();
  28 + $('profile_data_lat').value = position.lat();
  29 + $('profile_data_lng').value = position.lng();
  30 +
  31 + form = jQuery('#location-form')[0];
  32 + form.lat = marker.getPosition().lat();
  33 + form.lng = marker.getPosition().lng();
  34 +
  35 + var components_len = place.address_components.size();
  36 + if (components_len < 2)
  37 + return;
  38 +
  39 + var country_code = "";
  40 + var state = "";
  41 + var city = "";
  42 + var zip_code = "";
  43 + var route = "";
  44 + var number = "";
  45 + var sublocality = "";
  46 + var address = "";
  47 +
  48 + var i;
  49 + var has_postal_code = false;
  50 + for (i=0; i < components_len; i++) {
  51 + type = place.address_components[i].types[0];
  52 + if (type == 'postal_code')
  53 + has_postal_code = true;
  54 + }
  55 +
  56 + for (i=0; i < components_len; i++) {
  57 + type = place.address_components[i].types[0];
  58 + value = place.address_components[i];
  59 +
  60 + if (type == 'country')
  61 + country_code = value.short_name;
  62 + else if (type == 'administrative_area_level_1')
  63 + state = value.long_name;
  64 + else if (type == 'locality')
  65 + city = value.long_name;
  66 + else if (type == 'postal_code')
  67 + zip_code = value.short_name;
  68 + if (has_postal_code) {
  69 + if (type == "route")
  70 + route = value.long_name;
  71 + else if (type == "street_number")
  72 + number = value.short_name;
  73 + else if (type == 'sublocality')
  74 + sublocality = value.long_name;
  75 + }
  76 + }
  77 +
  78 + // build address
  79 + if (route) {
  80 + address = route;
  81 + if (number)
  82 + address = address + ', ' + number;
  83 + if (sublocality && sublocality != city)
  84 + address = address + ', ' + sublocality;
  85 + }
  86 +
  87 + if (country_code)
  88 + $('profile_data_country').value = country_code;
  89 + if (state)
  90 + $('profile_data_state').value = state;
  91 + if (city)
  92 + $('profile_data_city').value = city;
  93 + if (zip_code)
  94 + $('profile_data_zip_code').value = zip_code;
  95 + if (address)
  96 + $('profile_data_address').value = address;
  97 +
  98 + map.setCenter(marker.getPosition());
  99 + });
15 } 100 }
16 101
17 -function codeAddress() { 102 +function addressToPoint() {
18 $('location-fields').addClassName("loading"); 103 $('location-fields').addClassName("loading");
19 104
20 var country_option = $('profile_data_country').value; 105 var country_option = $('profile_data_country').value;
21 - var address = $('profile_data_address').value + "-" + $('profile_data_zip_code').value + "," + $('profile_data_city').value+ "-" + $('profile_data_state').value + "," + country_option; 106 + var address = $('profile_data_address').value + ", " + $('profile_data_zip_code').value + ", "
  107 + + $('profile_data_city').value+ ", " + $('profile_data_state').value + ", " + country_option;
22 108
23 if (geocoder) { 109 if (geocoder) {
24 - geocoder.geocode( { 'address': address}, function(results, status) { 110 + geocoder.geocode({ 'address': address}, function(results, status) {
25 if (status == google.maps.GeocoderStatus.OK) { 111 if (status == google.maps.GeocoderStatus.OK) {
26 map.setCenter(results[0].geometry.location); 112 map.setCenter(results[0].geometry.location);
27 marker.setPosition(results[0].geometry.location); 113 marker.setPosition(results[0].geometry.location);
28 - getAddress(marker.getPosition()); 114 + pointToAddress(marker.getPosition());
29 115
30 $('profile_data_lat').value = results[0].geometry.location.lat(); 116 $('profile_data_lat').value = results[0].geometry.location.lat();
31 $('profile_data_lng').value = results[0].geometry.location.lng(); 117 $('profile_data_lng').value = results[0].geometry.location.lng();
@@ -33,17 +119,15 @@ function codeAddress() { @@ -33,17 +119,15 @@ function codeAddress() {
33 enable_save(); 119 enable_save();
34 } else { 120 } else {
35 $('location-fields').removeClassName("loading"); 121 $('location-fields').removeClassName("loading");
36 - alert('<%=_("Address not found, reason:")%>' + translate_status(status)); 122 + alert('<%=_("Address not found, reason:")%>' + statusErrorMessage(status));
37 } 123 }
38 }); 124 });
39 } 125 }
40 126
41 - map.setZoom(11);  
42 -  
43 return false; 127 return false;
44 } 128 }
45 129
46 -function translate_status(status) 130 +function statusErrorMessage(status)
47 { 131 {
48 var translated_status = ''; 132 var translated_status = '';
49 133
@@ -59,136 +143,42 @@ function translate_status(status) @@ -59,136 +143,42 @@ function translate_status(status)
59 return translated_status; 143 return translated_status;
60 } 144 }
61 145
62 -function getAddressData() {  
63 - var text = '';  
64 - var fields = [  
65 - 'profile_data_country',  
66 - 'profile_data_state',  
67 - 'profile_data_city',  
68 - 'profile_data_address',  
69 - 'profile_data_zip_code'  
70 - ];  
71 - for (var i = 0; i < fields.length; i++) {  
72 - var field = fields[i];  
73 - if ($(field)) {  
74 - text += $(field).value + " ";  
75 - }  
76 - }  
77 - return text;  
78 -}  
79 -  
80 -function showAddress(results, status) {  
81 -  
82 - if (status == google.maps.GeocoderStatus.OK) {  
83 - map.setCenter(results[0].geometry.location);  
84 - updateFields(results[0]);  
85 -  
86 - } else {  
87 - alert("<%=_("Address not found, reason:")%>" + translate_status(status));  
88 - }  
89 -  
90 -}  
91 -  
92 -function updateFields(place) {  
93 - var position = marker.getPosition();  
94 - $('profile_data_lat').value = position.lat();  
95 - $('profile_data_lng').value = position.lng();  
96 - $('location-fields').removeClassName("loading");  
97 -  
98 - form = jQuery('#location-form')[0];  
99 - form.lat = marker.getPosition().lat();  
100 - form.lng = marker.getPosition().lng();  
101 -  
102 - var components_len = place.address_components.size();  
103 -  
104 - if(components_len < 2)  
105 - {  
106 - return false;  
107 - }  
108 -  
109 - var components = place.address_components;  
110 - var address = "";  
111 - var zip_code = "";  
112 - var city = "";  
113 - var state = "";  
114 - var country_code = "";  
115 - var i = 0;  
116 -  
117 - for( i =0 ; i < components_len; i ++)  
118 - {  
119 -  
120 - if (components[i].types[0] == 'country')  
121 - country_code = components[i].short_name;  
122 - else if (components[i].types[0] == 'administrative_area_level_1')  
123 - state = components[i].long_name;  
124 - else if (components[i].types[0] == 'locality')  
125 - city = components[i].long_name;  
126 - else if (components[i].types[0] == 'sublocality')  
127 - address = components[i].long_name + "-" + address;  
128 - else if (components[i].types[0] == "route")  
129 - address = components[i].long_name + address;  
130 - else if (components[i].types[0] == "street_number")  
131 - address = address + "," + components[i].short_name ;  
132 - else if (components[i].types[0] == 'postal_code')  
133 - zip_code = components[i].short_name;  
134 - }  
135 -  
136 - $('profile_data_country').value = country_code;  
137 - $('profile_data_state').value = state;  
138 - $('profile_data_address').value = address;  
139 - $('profile_data_city').value = city;  
140 - $('profile_data_zip_code').value = zip_code;  
141 -}  
142 -  
143 -  
144 -function initialize_map() { 146 +function initializeMap() {
145 geocoder = new google.maps.Geocoder(); 147 geocoder = new google.maps.Geocoder();
146 148
147 var lat = <%= profile.lat || 'false' %>; 149 var lat = <%= profile.lat || 'false' %>;
148 var lng = <%= profile.lng || 'false' %>; 150 var lng = <%= profile.lng || 'false' %>;
149 -  
150 if ( !(lat && lng) ) { 151 if ( !(lat && lng) ) {
151 lat = -15.7605361485013; 152 lat = -15.7605361485013;
152 lng = -47.933349609375; 153 lng = -47.933349609375;
153 } 154 }
154 155
155 - var latlng = new google.maps.LatLng(lat,lng);  
156 -  
157 - var myOptions = {  
158 - zoom: 8,  
159 - center: latlng,  
160 - mapTypeId: google.maps.MapTypeId.ROADMAP  
161 - }  
162 -  
163 - center = latlng;  
164 -  
165 - map = new google.maps.Map(document.getElementById("location-map"), myOptions);  
166 -  
167 - continueLoadMapV3()  
168 -}  
169 -  
170 -function continueLoadMapV3() { 156 + var center = new google.maps.LatLng(lat,lng);;
  157 + map = new google.maps.Map(document.getElementById("location-map"), {
  158 + zoom: mapZoom,
  159 + center: center,
  160 + mapTypeId: google.maps.MapTypeId.HYBRID
  161 + });
171 162
172 - marker = new google.maps.Marker({  
173 - position: center,  
174 - map: map,  
175 - draggable: true  
176 - }); 163 + marker = new google.maps.Marker({
  164 + position: center,
  165 + map: map,
  166 + draggable: true
  167 + });
177 168
178 - google.maps.event.addListener(marker, "dragend", function() {  
179 - move = false;  
180 - getAddress(marker.getPosition());  
181 - enable_save();  
182 - }); 169 + google.maps.event.addListener(marker, "dragend", function() {
  170 + move = false;
  171 + pointToAddress(marker.getPosition());
  172 + map.setCenter(marker.getPosition());
  173 + enable_save();
  174 + });
183 175
184 } 176 }
185 177
186 -window.onload = initialize_map;  
187 -  
188 -var delay_autocomplete = 500;  
189 -  
190 jQuery.noConflict(); 178 jQuery.noConflict();
191 -jQuery(document).ready(function (){ 179 +jQuery(document).ready(function () {
  180 +
  181 + initializeMap();
192 182
193 jQuery.widget( "custom.catcomplete",jQuery.ui.autocomplete, { 183 jQuery.widget( "custom.catcomplete",jQuery.ui.autocomplete, {
194 _renderMenu: function( ul, items ) { 184 _renderMenu: function( ul, items ) {
@@ -204,7 +194,6 @@ jQuery(document).ready(function (){ @@ -204,7 +194,6 @@ jQuery(document).ready(function (){
204 } 194 }
205 }); 195 });
206 196
207 -  
208 jQuery("#profile_data_city").catcomplete({ 197 jQuery("#profile_data_city").catcomplete({
209 source: "../maps/search_city", 198 source: "../maps/search_city",
210 minLength: 3, 199 minLength: 3,
@@ -219,21 +208,13 @@ jQuery(document).ready(function (){ @@ -219,21 +208,13 @@ jQuery(document).ready(function (){
219 }); 208 });
220 209
221 jQuery("#profile_data_city").keyup(function(){ 210 jQuery("#profile_data_city").keyup(function(){
222 -  
223 disable_save(); 211 disable_save();
224 -  
225 }); 212 });
226 -  
227 jQuery("#profile_data_state").keyup(function(){ 213 jQuery("#profile_data_state").keyup(function(){
228 -  
229 disable_save(); 214 disable_save();
230 -  
231 }); 215 });
232 -  
233 jQuery("#profile_data_country").change(function(){ 216 jQuery("#profile_data_country").change(function(){
234 -  
235 disable_save(); 217 disable_save();
236 -  
237 }); 218 });
238 219
239 }); 220 });
app/views/maps/edit_location.rhtml
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <%= labelled_form_field _('ZIP code'), text_field(:profile_data, :zip_code) %> 12 <%= labelled_form_field _('ZIP code'), text_field(:profile_data, :zip_code) %>
13 <%= labelled_form_field _('Address (street and number)'), text_field(:profile_data, :address) %> 13 <%= labelled_form_field _('Address (street and number)'), text_field(:profile_data, :address) %>
14 <% button_bar do %> 14 <% button_bar do %>
15 - <%= button_to_function :search, _('Locate in the map'), "codeAddress()", :title => _("Locate the address informed above in the map below (note that you'll probably need to adjust the marker to get a precise position)") %> 15 + <%= button_to_function :search, _('Locate in the map'), "addressToPoint()", :title => _("Locate the address informed above in the map below (note that you'll probably need to adjust the marker to get a precise position)") %>
16 <%= submit_button 'save', _('Save') %> 16 <%= submit_button 'save', _('Save') %>
17 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 17 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
18 <% end %> 18 <% end %>
app/views/memberships/index.rhtml
@@ -8,30 +8,6 @@ @@ -8,30 +8,6 @@
8 <%= button :back, _('Go back'), :controller => 'profile_editor' %> 8 <%= button :back, _('Go back'), :controller => 'profile_editor' %>
9 <% end %> 9 <% end %>
10 10
11 -<ul>  
12 -<% for membership in @memberships %>  
13 - <li>  
14 - <div class='common-profile-list-block'>  
15 - <%= profile_image_link(membership, :portrait, 'div') %>  
16 - </div>  
17 - <span class='profile-details'>  
18 - <strong><%= membership.name %></strong><br/>  
19 - <%= _('Role: %s') % rolename_for(profile, membership) %> <br/>  
20 - <%= _('Type: %s') % getterm(membership.class.identification) %> <br/>  
21 - <%= _('Description: %s') % membership.description + '<br/>' if membership.community? %>  
22 - <%= _('Members: %s') % membership.members_count.to_s %> <br/>  
23 - <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/>  
24 - <% button_bar do %>  
25 - <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %>  
26 - <%= button 'menu-logout', _('Leave community'), membership.leave_url(true), :class => 'leave-community' %>  
27 - <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %>  
28 - <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %>  
29 - <% end %>  
30 - <% end %>  
31 - </span>  
32 - <br class="may-clear" />  
33 - </li>  
34 -<% end %>  
35 -</ul> 11 +<%= render :partial => 'shared/list_groups', :locals => {:groups => @memberships} %>
36 12
37 </div> 13 </div>
app/views/memberships/new_community.rhtml
@@ -16,6 +16,12 @@ @@ -16,6 +16,12 @@
16 16
17 <%= required f.text_field(:name) %> 17 <%= required f.text_field(:name) %>
18 18
  19 + <% @plugins.dispatch(:new_community_hidden_fields).each do |field| %>
  20 + <% field.each do |key, value| %>
  21 + <%= f.hidden_field(key, :value => value) %>
  22 + <% end %>
  23 + <% end %>
  24 +
19 <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %> 25 <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %>
20 26
21 <% f.fields_for :image_builder, @community.image do |i| %> 27 <% f.fields_for :image_builder, @community.image do |i| %>
@@ -38,6 +44,8 @@ @@ -38,6 +44,8 @@
38 </div> 44 </div>
39 </div> 45 </div>
40 46
  47 + <%= template_options(Community, 'community')%>
  48 +
41 <% button_bar do %> 49 <% button_bar do %>
42 <%= submit_button(:save, _('Create')) %> 50 <%= submit_button(:save, _('Create')) %>
43 <%= button(:cancel, _('Cancel'), :action => 'index') %> 51 <%= button(:cancel, _('Cancel'), :action => 'index') %>
app/views/profile/_profile_comment_form.rhtml
@@ -3,15 +3,17 @@ @@ -3,15 +3,17 @@
3 <p class='profile-wall-reply'> 3 <p class='profile-wall-reply'>
4 <% update_area = tab_action == 'wall' ? 'profile_activities' : 'network-activities' %> 4 <% update_area = tab_action == 'wall' ? 'profile_activities' : 'network-activities' %>
5 <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_comment_on_activity', :tab_action => tab_action}, :html => { :class => 'profile-wall-reply-form', 'data-update' => update_area } do %> 5 <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_comment_on_activity', :tab_action => tab_action}, :html => { :class => 'profile-wall-reply-form', 'data-update' => update_area } do %>
6 - <%= text_area :comment, :body, {:id => "reply_content_#{activity.id}",  
7 - :cols => 50,  
8 - :rows => 1,  
9 - :class => 'submit-with-keypress',  
10 - :title => _('Leave your comment'),  
11 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
12 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),  
13 - :value => _('Leave your comment'),  
14 - :style => 'color: #ccc' } %> 6 + <%= expandable_text_area :comment,
  7 + :body,
  8 + "reply_content_#{activity.id}",
  9 + :cols => 50,
  10 + :rows => 1,
  11 + :class => 'submit-with-keypress',
  12 + :title => _('Leave your comment'),
  13 + :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),
  14 + :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),
  15 + :value => _('Leave your comment'),
  16 + :style => 'color: #ccc' %>
15 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %> 17 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %>
16 <% end %> 18 <% end %>
17 </p> 19 </p>
app/views/profile/_profile_scrap_reply_form.rhtml
@@ -2,15 +2,16 @@ @@ -2,15 +2,16 @@
2 <div id='profile-wall-reply-form-<%= scrap.id%>' style='display:none'> 2 <div id='profile-wall-reply-form-<%= scrap.id%>' style='display:none'>
3 <p class='profile-wall-reply'> 3 <p class='profile-wall-reply'>
4 <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap'}, :update => "profile_activities", :html => { :class => 'profile-wall-reply-form'} do %> 4 <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap'}, :update => "profile_activities", :html => { :class => 'profile-wall-reply-form'} do %>
5 - <%= text_area :scrap, :content, { :id => "reply_content_#{scrap.id}",  
6 - :cols => 50,  
7 - :rows => 1,  
8 - :class => 'submit-with-keypress',  
9 - :title => _('Leave your comment'),  
10 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
11 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),  
12 - :value => _('Leave your comment')  
13 - } %> 5 + <%= expandable_text_area :scrap,
  6 + :content,
  7 + "reply_content_#{scrap.id}",
  8 + :cols => 50,
  9 + :rows => 1,
  10 + :class => 'submit-with-keypress',
  11 + :title => _('Leave your comment'),
  12 + :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),
  13 + :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?),
  14 + :value => _('Leave your comment') %>
14 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %> 15 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %>
15 <%= hidden_field_tag 'receiver_id', scrap.sender.id %> 16 <%= hidden_field_tag 'receiver_id', scrap.sender.id %>
16 <% end %> 17 <% end %>
app/views/profile/_upload_image.rhtml
@@ -6,15 +6,9 @@ @@ -6,15 +6,9 @@
6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
7 <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> 7 <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p>
8 <div class='profile-wall-actions'> 8 <div class='profile-wall-actions'>
9 - <%= link_to(s_('profile|Comment'), '#', { :class => 'focus-on-comment'}) unless activity.get_view_url.size == 1 %>  
10 <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %> 9 <%= link_to_remote(content_tag(:span, _('Remove')), :confirm => _('Are you sure?'), :url =>{:action => 'remove_activity', :activity_id => activity.id}, :update => "profile-activity-item-#{activity.id}") if logged_in? && current_person == @profile %>
11 </div> 10 </div>
12 </div> 11 </div>
13 </div> 12 </div>
14 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> 13 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
15 -  
16 -<% if activity.get_view_url.size == 1 %>  
17 - <%= render :partial => 'profile_comments', :locals => { :activity => activity, :tab_action => tab_action } %>  
18 -<% end %>  
19 -  
20 <br/> 14 <br/>
app/views/profile/index.rhtml
@@ -29,7 +29,6 @@ @@ -29,7 +29,6 @@
29 <% if logged_in? && current_person.follows?(@profile) %> 29 <% if logged_in? && current_person.follows?(@profile) %>
30 <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %> 30 <% tabs << {:title => _('Wall'), :id => 'profile-wall', :content => (render :partial => 'profile_wall')} %>
31 <% end %> 31 <% end %>
32 - <% tabs << {:title => _('What\'s new'), :id => 'profile-network', :content => (render :partial => 'profile_network')} %>  
33 <% elsif @profile.person? %> 32 <% elsif @profile.person? %>
34 <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %> 33 <% tabs << {:title => _('Profile'), :id => 'person-profile', :content => (render :partial => 'person_profile')} %>
35 <% if logged_in? && current_person.follows?(@profile) %> 34 <% if logged_in? && current_person.follows?(@profile) %>
app/views/profile_editor/edit.rhtml
@@ -4,6 +4,12 @@ @@ -4,6 +4,12 @@
4 4
5 <% labelled_form_for :profile_data, @profile, :html => { :id => 'profile-data', :multipart => true } do |f| %> 5 <% labelled_form_for :profile_data, @profile, :html => { :id => 'profile-data', :multipart => true } do |f| %>
6 6
  7 + <% if user.has_permission?('manage_environment_templates', profile.environment) %>
  8 + <div id="profile-is-template">
  9 + <%= labelled_check_box(_('This profile is a template'), 'profile_data[is_template]', true, @profile.is_template) %>
  10 + </div>
  11 + <% end %>
  12 +
7 <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %> 13 <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %>
8 14
9 <% unless @profile.person? && @environment.active_person_fields.include?('image') %> 15 <% unless @profile.person? && @environment.active_person_fields.include?('image') %>
app/views/search/_display_results.rhtml
1 -<div id="search-results" class="<%= @results.size == 1 ? 'only-one-result-box' : 'multiple-results-boxes' %>"> 1 +<div id="search-results" class="<%= !multiple_search? ? 'only-one-result-box' : 'multiple-results-boxes' %>">
2 <% @order.each do |name| %> 2 <% @order.each do |name| %>
3 <% results = @results[name] %> 3 <% results = @results[name] %>
4 <% empty = results.nil? || results.empty? %> 4 <% empty = results.nil? || results.empty? %>
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 <% if not empty %> 7 <% if not empty %>
8 <% partial = partial_for_class(results.first.class.class_name.constantize) %> 8 <% partial = partial_for_class(results.first.class.class_name.constantize) %>
9 9
10 - <% if @results.size > 1 %> 10 + <% if multiple_search? %>
11 <h3><%= @names[name] %></h3> 11 <h3><%= @names[name] %></h3>
12 <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %> 12 <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %>
13 <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %> 13 <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %>
@@ -22,9 +22,10 @@ @@ -22,9 +22,10 @@
22 </ul> 22 </ul>
23 </div> 23 </div>
24 <% else %> 24 <% else %>
25 - <% if @results.size > 1 %> 25 + <% if multiple_search? %>
26 <h3><%= @names[name] %></h3> 26 <h3><%= @names[name] %></h3>
27 <% end %> 27 <% end %>
  28 +
28 <div class="search-results-innerbox search-results-type-empty"> 29 <div class="search-results-innerbox search-results-type-empty">
29 <div> <%= _('None') %> </div> 30 <div> <%= _('None') %> </div>
30 </div> 31 </div>
app/views/search/_product.rhtml
@@ -27,9 +27,9 @@ @@ -27,9 +27,9 @@
27 <% end %> 27 <% end %>
28 28
29 <% if product.price_described? %> 29 <% if product.price_described? %>
30 - <% title = (product.inputs + product.price_details).map{ |i| 30 + <% title = (product.inputs.relevant_to_price + product.price_details).map{ |i|
31 '<div class="search-product-input-dots-to-price">' + 31 '<div class="search-product-input-dots-to-price">' +
32 - '<div class="search-product-input-name">' + i.product_category.name + '</div>' + 32 + '<div class="search-product-input-name">' + i.name + '</div>' +
33 price_span(i.price, :class => 'search-product-input-price') + 33 price_span(i.price, :class => 'search-product-input-price') +
34 '</div>' }.join('') %> 34 '</div>' }.join('') %>
35 <%= link_to_function _("Open Price"), '', :title => title, :class => "search-product-price-details" %> 35 <%= link_to_function _("Open Price"), '', :title => title, :class => "search-product-price-details" %>
app/views/search/_profile.rhtml
1 <li class="search-profile-item"> 1 <li class="search-profile-item">
2 -<% if @empty_query or @results.size > 1 or !profile.enterprise? %> 2 +<% if @empty_query or multiple_search? or !profile.enterprise? %>
3 <%= profile_image_link profile, :portrait, 'div', 3 <%= profile_image_link profile, :portrait, 'div',
4 @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %> 4 @filter == 'more_recent' ? profile.send(@filter + '_label') + show_date(profile.created_at) : profile.send(@filter + '_label') %>
5 <% else %> 5 <% else %>
app/views/shared/_list_groups.html.erb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +<ul id="groups-list">
  2 +<% for group in groups %>
  3 + <li>
  4 + <div class='common-profile-list-block'>
  5 + <%= profile_image_link(group, :portrait, 'div') %>
  6 + </div>
  7 + <span class='profile-details'>
  8 + <strong><%= group.name %></strong><br/>
  9 + <%= _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by_resource_id(group.id) %>
  10 + <%= _('Type: %s') % getterm(group.class.identification) %> <br/>
  11 + <%= _('Description: %s') % group.description + '<br/>' if group.community? %>
  12 + <%= _('Members: %s') % group.members_count.to_s %> <br/>
  13 + <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/>
  14 + <% button_bar do %>
  15 + <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %>
  16 + <%= button 'menu-logout', _('Leave community'), group.leave_url(true), :class => 'leave-community' %>
  17 + <% if (group.community? && user.has_permission?(:destroy_profile, group)) %>
  18 + <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => group.identifier } %>
  19 + <% end %>
  20 + <% end %>
  21 + </span>
  22 + <br class="may-clear" />
  23 + </li>
  24 +<% end %>
  25 +</ul>
  26 +
app/views/tasks/processed.rhtml
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 <ul> 7 <ul>
8 <% @tasks.each do |item| %> 8 <% @tasks.each do |item| %>
9 <li> 9 <li>
10 - <strong><%= item.information %></strong> <br/> 10 + <strong><%= task_information(item) %></strong> <br/>
11 <small> 11 <small>
12 <%= _('Created:') +' '+ show_date(item.created_at) %> 12 <%= _('Created:') +' '+ show_date(item.created_at) %>
13 &nbsp; &#151; &nbsp; 13 &nbsp; &#151; &nbsp;
app/views/templates/_create_template_form.html.erb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +<% if @error %>
  2 + <div class="errorExplanation" id="errorExplanation">
  3 + <h2><%= _('The template could not be saved') %></h2>
  4 + <p><%= _('There were problems with the following fields:') %> </p>
  5 + <ul>
  6 + <li><%= @error %></li>
  7 + </ul>
  8 + </div>
  9 +<% end %>
  10 +
  11 +<% form_tag do %>
  12 + <%= labelled_text_field(_('Name')+': ', :name)%>
  13 +
  14 + <% button_bar do %>
  15 + <%= submit_button('save', _('Save'))%>
  16 + <%= button('cancel', _('Cancel'), {:action => 'index'})%>
  17 + <% end %>
  18 +<% end %>
  19 +
app/views/templates/create_community_template.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<% title = case @kind
  2 + when 'person'
  3 +
  4 + when 'community'
  5 +
  6 + when 'enterprise'
  7 + _('Create enterprise template')
  8 +end %>
  9 +
  10 +<h1><%= _('Create community template') %></h1>
  11 +
  12 +<%= render :partial => 'create_template_form' %>
app/views/templates/create_enterprise_template.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h1><%= _('Create enterprise template') %></h1>
  2 +
  3 +<%= render :partial => 'create_template_form' %>
app/views/templates/create_person_template.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<% title = case @kind
  2 + when 'person'
  3 +
  4 + when 'community'
  5 + _('Create community template')
  6 + when 'enterprise'
  7 + _('Create enterprise template')
  8 +end %>
  9 +
  10 +<h1><%= _('Create person template') %></h1>
  11 +
  12 +<%= render :partial => 'create_template_form' %>
app/views/templates/index.html.erb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +<h1><%= _('Edit Templates') %></h1>
  2 +
  3 +<%= _('Manage the templates used on creation of profiles') %>
  4 +
  5 +<% list_of_templates = [[_('Person') , Person.templates , 'person' ],
  6 + [_('Community') , Community.templates , 'community' ],
  7 + [_('Enterprise'), Enterprise.templates, 'enterprise']] %>
  8 +
  9 +<% list_of_templates.each do |title, templates, kind|%>
  10 + <div class='template-kind'>
  11 + <h2><%= title %></h2>
  12 + <%= button :add, _('New...'), {:action => "create_#{kind}_template"}, :title => _("Create a new template for %s") % title.downcase %>
  13 + <ul>
  14 + <% templates.each do |template| %>
  15 + <li>
  16 + <%= image_tag "icons-app/#{kind}-icon.png" %>
  17 + <%= link_to(template.name, {:controller => 'profile_editor', :profile => template.identifier}, :title => _('Edit template "%s"') % template.name ) %>
  18 + </li>
  19 + <% end %>
  20 + </ul>
  21 + </div>
  22 +<% end %>
  23 +
  24 +<% button_bar do %>
  25 + <%= button :back, _('Back to admin panel'), :controller => 'admin_panel' %>
  26 +<% end %>
config/initializers/action_tracker.rb
@@ -23,7 +23,28 @@ ActionTrackerConfig.verbs = { @@ -23,7 +23,28 @@ ActionTrackerConfig.verbs = {
23 }, 23 },
24 24
25 :upload_image => { 25 :upload_image => {
26 - :description => lambda { n_('uploaded 1 image<br />%{thumbnails}<br style="clear: both;" />', 'uploaded %{num} images<br />%{thumbnails}<br style="clear: both;" />', get_view_url.size) % { :num => get_view_url.size, :thumbnails => '{{ta.collect_group_with_index(:thumbnail_path){ |t,i| content_tag(:span, link_to(image_tag(t), ta.get_view_url[i]))}.last(3).join}}' } }, 26 + :description => lambda do
  27 + total = get_view_url.size
  28 + n_('uploaded 1 image', 'uploaded %d images', total) % total +
  29 + '<br />{{'+
  30 + 'ta.collect_group_with_index(:thumbnail_path) { |t,i|' +
  31 + " if ( #{total} == 1 );" +
  32 + ' link_to( image_tag(t), ta.get_view_url[i], :class => \'upimg\' );' +
  33 + ' else;' +
  34 + " pos = #{total}-i;" +
  35 + ' morethen2 = pos>2 ? \'morethen2\' : \'\';' +
  36 + ' morethen5 = pos>5 ? \'morethen5\' : \'\';' +
  37 + ' t = t.gsub(/(.*)(display)(.*)/, \'\\1thumb\\3\');' +
  38 + ' link_to( \'&nbsp;\', ta.get_view_url[i],' +
  39 + ' :style => "background-image:url(#{t})",' +
  40 + ' :class => "upimg pos#{pos} #{morethen2} #{morethen5}" );' +
  41 + ' end' +
  42 + '}.reverse.join}}' +
  43 + ( total > 5 ?
  44 + '<span class="more" onclick="this.parentNode.className+=\' show-all\'">' +
  45 + '&hellip;</span>' : '' ) +
  46 + '<br style="clear: both;" />'
  47 + end,
27 :type => :groupable 48 :type => :groupable
28 }, 49 },
29 50
config/initializers/plugins.rb
1 require 'noosfero/plugin' 1 require 'noosfero/plugin'
  2 +require 'noosfero/plugin/acts_as_having_hotspots'
2 require 'noosfero/plugin/manager' 3 require 'noosfero/plugin/manager'
3 require 'noosfero/plugin/context' 4 require 'noosfero/plugin/context'
4 require 'noosfero/plugin/active_record' 5 require 'noosfero/plugin/active_record'
db/migrate/20120710033223_add_template_and_is_template_fields.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class AddTemplateAndIsTemplateFields < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :profiles, :is_template, :boolean, :default => false
  4 + add_column :profiles, :template_id, :integer
  5 + end
  6 +
  7 + def self.down
  8 + remove_column :profiles, :is_template
  9 + remove_column :profiles, :template_id
  10 + end
  11 +end
db/migrate/20120710062802_fill_is_template_field_on_basic_templates.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class FillIsTemplateFieldOnBasicTemplates < ActiveRecord::Migration
  2 + def self.up
  3 + update("update profiles set is_template = (1=1) where identifier like '%_template'")
  4 + end
  5 +
  6 + def self.down
  7 + say('This migration can\'t be reverted.')
  8 + end
  9 +end
db/migrate/20120713073641_create_licenses.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class CreateLicenses < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :licenses do |t|
  4 + t.string :name, :null => false
  5 + t.string :slug, :null => false
  6 + t.string :url
  7 + t.references :environment, :null => false
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + drop_table :licenses
  13 + end
  14 +end
db/migrate/20120713082741_add_license_to_article.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class AddLicenseToArticle < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :articles, :license_id, :integer
  4 + add_column :article_versions, :license_id, :integer
  5 + end
  6 +
  7 + def self.down
  8 + remove_column :articles, :license_id
  9 + remove_column :article_versions, :license_id
  10 + end
  11 +end
db/migrate/20120716161506_add_manage_environment_license_to_admin_role.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class AddManageEnvironmentLicenseToAdminRole < ActiveRecord::Migration
  2 + def self.up
  3 + Environment.all.map(&:id).each do |id|
  4 + role = Environment::Roles.admin(id)
  5 + role.permissions << 'manage_environment_licenses'
  6 + role.save!
  7 + end
  8 + end
  9 +
  10 + def self.down
  11 + Environment.all.map(&:id).each do |id|
  12 + role = Environment::Roles.admin(id)
  13 + role.permissions -= ['manage_environment_licenses']
  14 + role.save!
  15 + end
  16 + end
  17 +end
db/migrate/20120718145131_add_manage_environment_templates_to_admin_role.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class AddManageEnvironmentTemplatesToAdminRole < ActiveRecord::Migration
  2 + def self.up
  3 + Environment.all.map(&:id).each do |id|
  4 + role = Environment::Roles.admin(id)
  5 + role.permissions << 'manage_environment_templates'
  6 + role.save!
  7 + end
  8 + end
  9 +
  10 + def self.down
  11 + Environment.all.map(&:id).each do |id|
  12 + role = Environment::Roles.admin(id)
  13 + role.permissions -= ['manage_environment_templates']
  14 + role.save!
  15 + end
  16 + end
  17 +end
db/migrate/20120718162001_create_default_licenses.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +class CreateDefaultLicenses < ActiveRecord::Migration
  2 + def self.up
  3 + Environment.all.each do |environment|
  4 + License.create!(:name => 'CC (by)', :url => 'http://creativecommons.org/licenses/by/3.0/legalcode', :environment => environment)
  5 + License.create!(:name => 'CC (by-nd)', :url => 'http://creativecommons.org/licenses/by-nd/3.0/legalcode', :environment => environment)
  6 + License.create!(:name => 'CC (by-sa)', :url => 'http://creativecommons.org/licenses/by-sa/3.0/legalcode', :environment => environment)
  7 + License.create!(:name => 'CC (by-nc)', :url => 'http://creativecommons.org/licenses/by-nc/3.0/legalcode', :environment => environment)
  8 + License.create!(:name => 'CC (by-nc-nd)', :url => 'http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', :environment => environment)
  9 + License.create!(:name => 'CC (by-nc-sa)', :url => 'http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', :environment => environment)
  10 + License.create!(:name => 'Free Art', :url => 'http://artlibre.org/licence/lal/en', :environment => environment)
  11 + License.create!(:name => 'GNU FDL', :url => 'http://www.gnu.org/licenses/fdl-1.3.txt', :environment => environment)
  12 + end
  13 + end
  14 +
  15 + def self.down
  16 + licenses = []
  17 + licenses += License.find(:all, :conditions => {:name => 'CC (by)'})
  18 + licenses += License.find(:all, :conditions => {:name => 'CC (by-nd)'})
  19 + licenses += License.find(:all, :conditions => {:name => 'CC (by-sa)'})
  20 + licenses += License.find(:all, :conditions => {:name => 'CC (by-nc)'})
  21 + licenses += License.find(:all, :conditions => {:name => 'CC (by-nc-nd)'})
  22 + licenses += License.find(:all, :conditions => {:name => 'CC (by-nc-sa)'})
  23 + licenses += License.find(:all, :conditions => {:name => 'Free Art'})
  24 + licenses += License.find(:all, :conditions => {:name => 'GNU FDL'})
  25 + licenses.compact.map(&:destroy)
  26 + end
  27 +end
db/migrate/20120813163139_set_activation_code_to_nil_if_already_activated.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class SetActivationCodeToNilIfAlreadyActivated < ActiveRecord::Migration
  2 + def self.up
  3 + update("UPDATE users SET activation_code = null WHERE activated_at IS NOT NULL")
  4 + end
  5 +
  6 + def self.down
  7 + say('Can not be reverted.')
  8 + end
  9 +end
db/migrate/20120818030329_remove_action_tracker_with_target_nil.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class RemoveActionTrackerWithTargetNil < ActiveRecord::Migration
  2 + def self.up
  3 + select_all("SELECT id FROM action_tracker").each do |tracker|
  4 + activity = ActionTracker::Record.find_by_id(tracker['id'])
  5 + if activity && activity.target.nil?
  6 + activity.destroy
  7 + end
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + say "this migration can't be reverted"
  13 + end
  14 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20120411132751) do 12 +ActiveRecord::Schema.define(:version => 20120818030329) do
13 13
14 create_table "abuse_reports", :force => true do |t| 14 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 15 t.integer "reporter_id"
@@ -85,6 +85,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -85,6 +85,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
85 t.integer "translation_of_id" 85 t.integer "translation_of_id"
86 t.string "language" 86 t.string "language"
87 t.string "source_name" 87 t.string "source_name"
  88 + t.integer "license_id"
88 end 89 end
89 90
90 create_table "articles", :force => true do |t| 91 create_table "articles", :force => true do |t|
@@ -125,6 +126,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -125,6 +126,7 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
125 t.integer "translation_of_id" 126 t.integer "translation_of_id"
126 t.string "language" 127 t.string "language"
127 t.string "source_name" 128 t.string "source_name"
  129 + t.integer "license_id"
128 end 130 end
129 131
130 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" 132 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id"
@@ -314,6 +316,13 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -314,6 +316,13 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
314 add_index "inputs", ["product_category_id"], :name => "index_inputs_on_product_category_id" 316 add_index "inputs", ["product_category_id"], :name => "index_inputs_on_product_category_id"
315 add_index "inputs", ["product_id"], :name => "index_inputs_on_product_id" 317 add_index "inputs", ["product_id"], :name => "index_inputs_on_product_id"
316 318
  319 + create_table "licenses", :force => true do |t|
  320 + t.string "name", :null => false
  321 + t.string "slug", :null => false
  322 + t.string "url"
  323 + t.integer "environment_id", :null => false
  324 + end
  325 +
317 create_table "mailing_sents", :force => true do |t| 326 create_table "mailing_sents", :force => true do |t|
318 t.integer "mailing_id" 327 t.integer "mailing_id"
319 t.integer "person_id" 328 t.integer "person_id"
@@ -425,6 +434,8 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do @@ -425,6 +434,8 @@ ActiveRecord::Schema.define(:version =&gt; 20120411132751) do
425 t.boolean "validated", :default => true 434 t.boolean "validated", :default => true
426 t.string "cnpj" 435 t.string "cnpj"
427 t.string "national_region_code" 436 t.string "national_region_code"
  437 + t.boolean "is_template", :default => false
  438 + t.integer "template_id"
428 end 439 end
429 440
430 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" 441 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id"
debian/changelog
  1 +noosfero (0.38.2) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Antonio Terceiro <terceiro@colivre.coop.br> Wed, 05 Sep 2012 10:07:58 -0300
  6 +
  7 +noosfero (0.38.1) unstable; urgency=low
  8 +
  9 + * Bugfixes release
  10 +
  11 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Sat, 18 Aug 2012 07:49:59 -0300
  12 +
  13 +noosfero (0.38.0) unstable; urgency=low
  14 +
  15 + * Features version release
  16 +
  17 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Tue, 31 Jul 2012 19:51:43 -0300
  18 +
1 noosfero (0.37.0) unstable; urgency=low 19 noosfero (0.37.0) unstable; urgency=low
2 20
3 * Features version release 21 * Features version release
debian/control
@@ -47,11 +47,12 @@ Depends: @@ -47,11 +47,12 @@ Depends:
47 memcached, 47 memcached,
48 debconf, 48 debconf,
49 dbconfig-common, 49 dbconfig-common,
50 - postgresql,  
51 adduser, 50 adduser,
52 exim4 | mail-transport-agent, 51 exim4 | mail-transport-agent,
53 ${misc:Depends} 52 ${misc:Depends}
54 -Recommends: postgresql-client 53 +Recommends:
  54 + postgresql,
  55 + postgresql-client
55 Description: free web-based platform for social networks 56 Description: free web-based platform for social networks
56 Noosfero is a web platform for social and solidarity economy networks with 57 Noosfero is a web platform for social and solidarity economy networks with
57 blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective 58 blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective
@@ -61,8 +62,7 @@ Description: free web-based platform for social networks @@ -61,8 +62,7 @@ Description: free web-based platform for social networks
61 62
62 Package: noosfero-apache 63 Package: noosfero-apache
63 Architecture: all 64 Architecture: all
64 -Depends: apache2, debconf  
65 -Suggests: noosfero 65 +Depends: apache2, debconf, noosfero
66 Description: free web-based platform for social networks (apache frontend) 66 Description: free web-based platform for social networks (apache frontend)
67 Noosfero is a web platform for social and solidarity economy networks with 67 Noosfero is a web platform for social and solidarity economy networks with
68 blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective 68 blog, e-Porfolios, CMS, RSS, thematic discussion, events agenda and collective
debian/thin.yml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 pid: tmp/pids/thin.pid 2 pid: tmp/pids/thin.pid
3 address: 127.0.0.1 3 address: 127.0.0.1
4 user: noosfero 4 user: noosfero
5 -timeout: 30 5 +timeout: 0
6 port: 50000 6 port: 50000
7 log: log/thin.log 7 log: log/thin.log
8 max_conns: 1024 8 max_conns: 1024
etc/logrotate.d/noosfero
1 -/var/log/noosfero/*.log /home/noosfero/current/log/*.log { 1 +/var/log/noosfero/*.log {
2 daily 2 daily
3 missingok 3 missingok
4 rotate 30 4 rotate 30
etc/noosfero/varnish-noosfero.vcl
1 sub vcl_recv { 1 sub vcl_recv {
  2 + if (req.request == "GET" || req.request == "HEAD") {
2 if (req.http.Cookie) { 3 if (req.http.Cookie) {
3 - # We only care about the "_noosfero_session.*" cookie, used for  
4 - # authentication.  
5 - if (req.http.Cookie ~ "_noosfero_session.*" ) {  
6 - return (pass);  
7 - }  
8 - # Else strip all cookies 4 + # We only care about the "_noosfero_session.*" cookie, used for
  5 + # authentication.
  6 + if (req.http.Cookie !~ "_noosfero_session.*" ) {
  7 + # strip all cookies
9 unset req.http.Cookie; 8 unset req.http.Cookie;
  9 + }
10 } 10 }
  11 + }
11 } 12 }
12 13
13 sub vcl_error { 14 sub vcl_error {
features/edit_environment_templates.feature
1 Feature: edit environment templates 1 Feature: edit environment templates
2 As an administrator 2 As an administrator
3 - I want edit templates 3 + I want to edit templates
4 4
5 Background: 5 Background:
6 Given that the default environment have all profile templates 6 Given that the default environment have all profile templates
@@ -9,37 +9,37 @@ Feature: edit environment templates @@ -9,37 +9,37 @@ Feature: edit environment templates
9 Given I am logged in as admin 9 Given I am logged in as admin
10 When I follow "Administration" 10 When I follow "Administration"
11 And I follow "Edit Templates" 11 And I follow "Edit Templates"
12 - Then I should see "Edit Person Template" link  
13 - And I should see "Edit Community Template" link  
14 - And I should see "Edit Enterprise Template" link  
15 - And I should see "Edit Inactive Enterprise Template" link 12 + Then I should see "Person template" link
  13 + And I should see "Community template" link
  14 + And I should see "Enterprise template" link
  15 + And I should see "Inactive Enterprise template" link
16 16
17 Scenario: Go to control panel of person template 17 Scenario: Go to control panel of person template
18 Given I am logged in as admin 18 Given I am logged in as admin
19 When I follow "Administration" 19 When I follow "Administration"
20 And I follow "Edit Templates" 20 And I follow "Edit Templates"
21 - And I follow "Edit Person Template" 21 + And I follow "Person template"
22 Then I should be on Person template's control panel 22 Then I should be on Person template's control panel
23 23
24 Scenario: Go to control panel of enterprise template 24 Scenario: Go to control panel of enterprise template
25 Given I am logged in as admin 25 Given I am logged in as admin
26 When I follow "Administration" 26 When I follow "Administration"
27 And I follow "Edit Templates" 27 And I follow "Edit Templates"
28 - And I follow "Edit Enterprise Template" 28 + And I follow "Enterprise template"
29 Then I should be on Enterprise template's control panel 29 Then I should be on Enterprise template's control panel
30 30
31 Scenario: Go to control panel of inactive enterprise template 31 Scenario: Go to control panel of inactive enterprise template
32 Given I am logged in as admin 32 Given I am logged in as admin
33 When I follow "Administration" 33 When I follow "Administration"
34 And I follow "Edit Templates" 34 And I follow "Edit Templates"
35 - And I follow "Edit Inactive Enterprise Template" 35 + And I follow "Inactive enterprise template"
36 Then I should be on Inactive Enterprise template's control panel 36 Then I should be on Inactive Enterprise template's control panel
37 37
38 Scenario: Go to control panel of community template 38 Scenario: Go to control panel of community template
39 Given I am logged in as admin 39 Given I am logged in as admin
40 When I follow "Administration" 40 When I follow "Administration"
41 And I follow "Edit Templates" 41 And I follow "Edit Templates"
42 - And I follow "Edit Community Template" 42 + And I follow "Community template"
43 Then I should be on Community template's control panel 43 Then I should be on Community template's control panel
44 44
45 Scenario: Not see link to edit an unexistent template 45 Scenario: Not see link to edit an unexistent template
@@ -47,7 +47,7 @@ Feature: edit environment templates @@ -47,7 +47,7 @@ Feature: edit environment templates
47 And I am logged in as admin 47 And I am logged in as admin
48 When I follow "Administration" 48 When I follow "Administration"
49 And I follow "Edit Templates" 49 And I follow "Edit Templates"
50 - Then I should see "Edit Person Template" link  
51 - And I should see "Edit Community Template" link  
52 - And I should see "Edit Enterprise Template" link  
53 - And I should not see "Edit Inactive Enterprise Template" link 50 + Then I should see "Person template" link
  51 + And I should see "Community template" link
  52 + And I should see "Enterprise template" link
  53 + And I should not see "Inactive enterprise template" link
features/private_profile.feature
@@ -30,16 +30,6 @@ Feature: private profiles @@ -30,16 +30,6 @@ Feature: private profiles
30 When I go to shygirl's homepage 30 When I go to shygirl's homepage
31 Then I should not see "Add friend" 31 Then I should not see "Add friend"
32 32
33 - Scenario: viewing a private community profile shouldn't show the news if not logged or not a member  
34 - Given I am on Safernet's homepage  
35 - Then I should not see "What's new"  
36 - And I am logged in as "joao"  
37 - When I am on Safernet's homepage  
38 - Then I should not see "What's new"  
39 - And "joao" is a member of "Safernet"  
40 - When I am on Safernet's homepage  
41 - Then I should see "What's new"  
42 -  
43 Scenario: person private profiles should not display sensible information 33 Scenario: person private profiles should not display sensible information
44 Given I am logged in as "joao" 34 Given I am logged in as "joao"
45 When I go to shygirl's homepage 35 When I go to shygirl's homepage
features/step_definitions/mezuro_steps.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +Then /^I directly delete content with name "([^\"]*)" for testing purposes$/ do |content_name|
  2 + Article.find_by_name(content_name).destroy
  3 +end
  4 +
  5 +Then /^I should be at the url "([^\"]*)"$/ do |url|
  6 + if response.class.to_s == 'Webrat::SeleniumResponse'
  7 + URI.parse(response.selenium.get_location).path.should == url
  8 + else
  9 + URI.parse(current_url).path.should == url
  10 + end
  11 +end
  12 +
  13 +Then /^I don't fill anything$/ do
  14 +end
lib/noosfero.rb
@@ -2,7 +2,7 @@ require &#39;fast_gettext&#39; @@ -2,7 +2,7 @@ require &#39;fast_gettext&#39;
2 2
3 module Noosfero 3 module Noosfero
4 PROJECT = 'noosfero' 4 PROJECT = 'noosfero'
5 - VERSION = '0.37.0' 5 + VERSION = '0.38.2'
6 6
7 def self.pattern_for_controllers_in_directory(dir) 7 def self.pattern_for_controllers_in_directory(dir)
8 disjunction = controllers_in_directory(dir).join('|') 8 disjunction = controllers_in_directory(dir).join('|')
lib/noosfero/plugin.rb
@@ -256,4 +256,29 @@ class Noosfero::Plugin @@ -256,4 +256,29 @@ class Noosfero::Plugin
256 nil 256 nil
257 end 257 end
258 258
  259 + # -> Extends organization list of members
  260 + # returns = An instance of ActiveRecord::NamedScope::Scope retrieved through
  261 + # Person.members_of method.
  262 + def organization_members(organization)
  263 + nil
  264 + end
  265 +
  266 + # -> Extends person permission access
  267 + # returns = boolean
  268 + def has_permission?(person, permission, target)
  269 + nil
  270 + end
  271 +
  272 + # -> Adds hidden_fields to the new community view
  273 + # returns = {key => value}
  274 + def new_community_hidden_fields
  275 + nil
  276 + end
  277 +
  278 + # -> Adds hidden_fields to the enterprise registration view
  279 + # returns = {key => value}
  280 + def enterprise_registration_hidden_fields
  281 + nil
  282 + end
  283 +
259 end 284 end
lib/noosfero/plugin/acts_as_having_hotspots.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +module ActsAsHavingHotspots
  2 + module ClassMethods
  3 + # Adding this feature to a class demands that it defines an instance method
  4 + # 'environment' that returns the environment associated with the instance.
  5 + def acts_as_having_hotspots
  6 + send :include, InstanceMethods
  7 + end
  8 +
  9 + module InstanceMethods
  10 + # Dispatches +event+ to each enabled plugin and collect the results.
  11 + #
  12 + # Returns an Array containing the objects returned by the event method in
  13 + # each plugin. This array is compacted (i.e. nils are removed) and flattened
  14 + # (i.e. elements of arrays are added to the resulting array). For example, if
  15 + # the enabled plugins return 1, 0, nil, and [1,2,3], then this method will
  16 + # return [1,0,1,2,3]
  17 + #
  18 + def dispatch(event, *args)
  19 + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact.flatten
  20 + end
  21 +
  22 + # Dispatch without flatten since scopes are executed if you run flatten on them
  23 + def dispatch_scopes(event, *args)
  24 + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact
  25 + end
  26 +
  27 + def enabled_plugins
  28 + Thread.current[:enabled_plugins] ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin_name|
  29 + plugin = plugin_name.constantize.new
  30 + plugin.context = context
  31 + plugin
  32 + end
  33 + end
  34 +
  35 + if !method_defined?(:context)
  36 + define_method(:context) do
  37 + Noosfero::Plugin::Context.new
  38 + end
  39 + end
  40 + end
  41 + end
  42 +end
  43 +
  44 +ActiveRecord::Base.send(:extend, ActsAsHavingHotspots::ClassMethods)
lib/noosfero/plugin/context.rb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # controller that can be accessed by plugins 2 # controller that can be accessed by plugins
3 class Noosfero::Plugin::Context 3 class Noosfero::Plugin::Context
4 4
5 - def initialize(controller) 5 + def initialize(controller = ApplicationController.new)
6 @controller = controller 6 @controller = controller
7 end 7 end
8 8
lib/noosfero/plugin/manager.rb
1 class Noosfero::Plugin::Manager 1 class Noosfero::Plugin::Manager
2 2
3 - attr_reader :context 3 + extend ActsAsHavingHotspots::ClassMethods
  4 + acts_as_having_hotspots
4 5
5 - def initialize(controller)  
6 - @context = Noosfero::Plugin::Context.new(controller)  
7 - end 6 + attr_reader :context
8 7
  8 + delegate :environment, :to => :context
9 delegate :each, :to => :enabled_plugins 9 delegate :each, :to => :enabled_plugins
10 include Enumerable 10 include Enumerable
11 11
12 - # Dispatches +event+ to each enabled plugin and collect the results.  
13 - #  
14 - # Returns an Array containing the objects returned by the event method in  
15 - # each plugin. This array is compacted (i.e. nils are removed) and flattened  
16 - # (i.e. elements of arrays are added to the resulting array). For example, if  
17 - # the enabled plugins return 1, 0, nil, and [1,2,3], then this method will  
18 - # return [1,0,1,2,3]  
19 - #  
20 - def dispatch(event, *args)  
21 - map { |plugin| plugin.send(event, *args) }.compact.flatten  
22 - end  
23 -  
24 - def enabled_plugins  
25 - @enabled_plugins ||= (Noosfero::Plugin.all & context.environment.enabled_plugins).map do |plugin|  
26 - p = plugin.constantize.new  
27 - p.context = context  
28 - p 12 + def initialize(controller)
  13 + @context = Noosfero::Plugin::Context.new(controller)
  14 + Thread.current[:enabled_plugins] = (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin_name|
  15 + plugin = plugin_name.constantize.new
  16 + plugin.context = context
  17 + plugin
29 end 18 end
30 end 19 end
31 20