Commit 1182476c928ed1bd9d07130ae292298eb8236526

Authored by Victor Costa
2 parents b1a79e13 d5f224bb

Merge branch 'rails235' into rails3

* rails235: (168 commits)
  L10n: support for custom locales
  enhancements: visualization of suggested usernames
  Allowing translation for url checking string
  Removed unnecessary lines on test
  Removed unit tests from functionals file
  Fixed html and test syntax
  Removed needless condition
  Fixed suggestions of usernames
  Test files should ends with "_test.rb"
  Added pagination on events_by_day on profile agenda
  Fix missing variable in funcional test
  Fix unit tests
  Change routes from embed controller
  Remove unused code
  Autocomplete fields on page load
  Blocks can returns a block of code to be evaluated
  Avoid randomness on tests
  comment-group-plugin: avoid randomness on tests
  community-track-plugin: fix tests by creating a profile with default boxes
  anti-spam-plugin-wrapper: ensure to load concrete wrappers
  ...

Conflicts:
	app/helpers/application_helper.rb
	app/models/comment.rb
	app/models/contact.rb
	app/models/event.rb
	app/models/mailing.rb
	app/models/organization.rb
	app/models/organization_mailing.rb
	app/models/pending_task_notifier.rb
	app/models/person.rb
	app/models/profile.rb
	app/models/scrap.rb
	app/models/task_mailer.rb
	app/models/user.rb
	app/views/account/_signup_form.rhtml
	app/views/blocks/profile_image.rhtml
	app/views/blocks/profile_info.rhtml
	app/views/box_organizer/_link_list_block.rhtml
	app/views/box_organizer/edit.rhtml
	app/views/features/_manage_community_fields.rhtml
	app/views/features/_manage_enterprise_fields.rhtml
	app/views/features/_manage_person_fields.rhtml
	app/views/features/index.rhtml
	app/views/layouts/application-ng.rhtml
	app/views/users/_users_list.rhtml
	db/schema.rb
	features/forum.feature
	lib/feed_handler.rb
	lib/noosfero/plugin.rb
	plugins/community_track/test/functional/community_track_plugin_content_viewer_controller_test.rb
	plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
	plugins/spaminator/lib/spaminator_plugin/mailer.rb
	test/functional/content_viewer_controller_test.rb
	test/functional/profile_controller_test.rb
	test/functional/profile_design_controller_test.rb
	test/functional/search_controller_test.rb
	test/unit/contact_sender_test.rb
	test/unit/content_viewer_helper_test.rb
	test/unit/environment_mailing_test.rb
	test/unit/mailing_test.rb
	test/unit/organization_mailing_test.rb
	test/unit/person_test.rb
	test/unit/profile_test.rb
	test/unit/uploaded_file_test.rb
	vendor/plugins/action_tracker/lib/action_tracker_model.rb
Showing 269 changed files with 5981 additions and 843 deletions   Show diff stats
@@ -7,6 +7,7 @@ Developers @@ -7,6 +7,7 @@ Developers
7 ========== 7 ==========
8 8
9 Alan Freihof Tygel <alantygel@gmail.com> 9 Alan Freihof Tygel <alantygel@gmail.com>
  10 +alcampelo <alcampelo@alcampelo.(none)>
10 Alessandro Palmeira <alessandro.palmeira@gmail.com> 11 Alessandro Palmeira <alessandro.palmeira@gmail.com>
11 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> 12 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
12 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> 13 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
@@ -38,6 +39,7 @@ Alessandro Palmeira + João M. M. Silva &lt;alessandro.palmeira@gmail.com&gt; @@ -38,6 +39,7 @@ Alessandro Palmeira + João M. M. Silva &lt;alessandro.palmeira@gmail.com&gt;
38 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> 39 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
39 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> 40 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
40 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> 41 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
  42 +Ana Losnak <analosnak@gmail.com>
41 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 43 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
42 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 44 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
43 Antonio Terceiro <terceiro@colivre.coop.br> 45 Antonio Terceiro <terceiro@colivre.coop.br>
@@ -85,6 +87,7 @@ Daniel Alves + Rafael Manzo &lt;rr.manzo@gmail.com&gt; @@ -85,6 +87,7 @@ Daniel Alves + Rafael Manzo &lt;rr.manzo@gmail.com&gt;
85 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> 87 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
86 Daniel Bucher <daniel.bucher88@gmail.com> 88 Daniel Bucher <daniel.bucher88@gmail.com>
87 Daniel Cunha <daniel@colivre.coop.br> 89 Daniel Cunha <daniel@colivre.coop.br>
  90 +David Carlos <ddavidcarlos1392@gmail.com>
88 diegoamc <diegoamc90@gmail.com> 91 diegoamc <diegoamc90@gmail.com>
89 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> 92 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
90 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> 93 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>
@@ -114,12 +117,16 @@ Diego Martinez &lt;diegoamc90@gmail.com&gt; @@ -114,12 +117,16 @@ Diego Martinez &lt;diegoamc90@gmail.com&gt;
114 Diego Martinez <diego@diego-K55A.(none)> 117 Diego Martinez <diego@diego-K55A.(none)>
115 Diego + Renan <renanteruoc@gmail.com> 118 Diego + Renan <renanteruoc@gmail.com>
116 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 119 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
  120 +Fabio Teixeira <fabio1079@gmail.com>
117 Fernanda Lopes <nanda.listas+psl@gmail.com> 121 Fernanda Lopes <nanda.listas+psl@gmail.com>
118 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> 122 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>
119 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> 123 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>
120 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> 124 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
121 Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> 125 Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>
  126 +Gabriela Navarro <navarro1703@gmail.com>
122 Grazieno Pellegrino <grazieno@gmail.com> 127 Grazieno Pellegrino <grazieno@gmail.com>
  128 +Gust <darksshades@hotmail.com>
  129 +Hugo Melo <hugo@riseup.net>
123 Isaac Canan <isaac@intelletto.com.br> 130 Isaac Canan <isaac@intelletto.com.br>
124 Italo Valcy <italo@dcc.ufba.br> 131 Italo Valcy <italo@dcc.ufba.br>
125 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> 132 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
@@ -202,6 +209,7 @@ Renan Teruo + Diego Araujo &lt;renanteruoc@gmail.com&gt; @@ -202,6 +209,7 @@ Renan Teruo + Diego Araujo &lt;renanteruoc@gmail.com&gt;
202 Renan Teruo + Diego Araújo <renanteruoc@gmail.com> 209 Renan Teruo + Diego Araújo <renanteruoc@gmail.com>
203 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 210 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
204 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 211 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
  212 +Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>
205 Rodrigo Souto <diguliu@gmail.com> 213 Rodrigo Souto <diguliu@gmail.com>
206 Rodrigo Souto <rodrigo@colivre.coop.br> 214 Rodrigo Souto <rodrigo@colivre.coop.br>
207 Ronny Kursawe <kursawe.ronny@googlemail.com> 215 Ronny Kursawe <kursawe.ronny@googlemail.com>
app/controllers/admin/environment_design_controller.rb
@@ -3,6 +3,8 @@ class EnvironmentDesignController &lt; BoxOrganizerController @@ -3,6 +3,8 @@ class EnvironmentDesignController &lt; BoxOrganizerController
3 protect 'edit_environment_design', :environment 3 protect 'edit_environment_design', :environment
4 4
5 def available_blocks 5 def available_blocks
  6 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  7 + # the Noosfero core soon, see ActionItem3045
6 @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 8 @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
7 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) 9 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
8 end 10 end
app/controllers/admin/users_controller.rb
@@ -45,6 +45,20 @@ class UsersController &lt; AdminController @@ -45,6 +45,20 @@ class UsersController &lt; AdminController
45 redirect_to :action => :index, :q => params[:q], :filter => params[:filter] 45 redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
46 end 46 end
47 47
  48 +
  49 + def destroy_user
  50 + if request.post?
  51 + person = environment.people.find_by_id(params[:id])
  52 + if person && person.destroy
  53 + session[:notice] = _('The profile was deleted.')
  54 + else
  55 + session[:notice] = _('Could not remove profile')
  56 + end
  57 + end
  58 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  59 + end
  60 +
  61 +
48 def download 62 def download
49 respond_to do |format| 63 respond_to do |format|
50 format.html 64 format.html
app/controllers/box_organizer_controller.rb
@@ -80,6 +80,22 @@ class BoxOrganizerController &lt; ApplicationController @@ -80,6 +80,22 @@ class BoxOrganizerController &lt; ApplicationController
80 render :action => 'edit', :layout => false 80 render :action => 'edit', :layout => false
81 end 81 end
82 82
  83 + def search_autocomplete
  84 + if request.xhr? and params[:query]
  85 + search = params[:query]
  86 + path_list = if boxes_holder.is_a?(Environment) && boxes_holder.enabled?('use_portal_community') && boxes_holder.portal_community
  87 + boxes_holder.portal_community.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{portal}/"+content.path }
  88 + elsif boxes_holder.is_a?(Profile)
  89 + boxes_holder.articles.find(:all, :conditions=>"name ILIKE '%#{search}%' or path ILIKE '%#{search}%'", :limit=>20).map { |content| "/{profile}/"+content.path }
  90 + else
  91 + []
  92 + end
  93 + render :json => path_list.to_json
  94 + else
  95 + redirect_to "/"
  96 + end
  97 + end
  98 +
83 def save 99 def save
84 @block = boxes_holder.blocks.find(params[:id]) 100 @block = boxes_holder.blocks.find(params[:id])
85 @block.update_attributes(params[:block]) 101 @block.update_attributes(params[:block])
@@ -99,6 +115,12 @@ class BoxOrganizerController &lt; ApplicationController @@ -99,6 +115,12 @@ class BoxOrganizerController &lt; ApplicationController
99 end 115 end
100 end 116 end
101 117
  118 + def clone_block
  119 + block = Block.find(params[:id])
  120 + block.duplicate
  121 + redirect_to :action => 'index'
  122 + end
  123 +
102 protected :boxes_editor? 124 protected :boxes_editor?
103 125
104 end 126 end
app/controllers/embed_controller.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class EmbedController < ApplicationController
  2 + layout 'embed'
  3 +
  4 + def block
  5 + @block = Block.find(params[:id])
  6 + if !@block.embedable? || !@block.visible?
  7 + render 'unavailable.rhtml', :status => 403
  8 + end
  9 + rescue ActiveRecord::RecordNotFound
  10 + render 'not_found.rhtml', :status => 404
  11 + end
  12 +
  13 +end
app/controllers/my_profile/cms_controller.rb
@@ -24,10 +24,16 @@ class CmsController &lt; MyProfileController @@ -24,10 +24,16 @@ class CmsController &lt; MyProfileController
24 (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) 24 (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))
25 end 25 end
26 26
27 - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile| 27 + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile|
28 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) 28 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))
29 end 29 end
30 30
  31 + protect_if :only => :new do |c, user, profile|
  32 + article = profile.articles.find_by_id(c.params[:parent_id])
  33 + (!article.nil? && (article.allow_create?(user) || article.parent.allow_create?(user))) ||
  34 + (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))
  35 + end
  36 +
31 protect_if :only => [:destroy, :publish] do |c, user, profile| 37 protect_if :only => [:destroy, :publish] do |c, user, profile|
32 profile.articles.find(c.params[:id]).allow_post_content?(user) 38 profile.articles.find(c.params[:id]).allow_post_content?(user)
33 end 39 end
@@ -220,11 +226,10 @@ class CmsController &lt; MyProfileController @@ -220,11 +226,10 @@ class CmsController &lt; MyProfileController
220 226
221 def update_categories 227 def update_categories
222 @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new 228 @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new
  229 + @categories = @toplevel_categories = environment.top_level_categories
223 if params[:category_id] 230 if params[:category_id]
224 @current_category = Category.find(params[:category_id]) 231 @current_category = Category.find(params[:category_id])
225 @categories = @current_category.children 232 @categories = @current_category.children
226 - else  
227 - @categories = environment.top_level_categories.select{|i| !i.children.empty?}  
228 end 233 end
229 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false 234 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false
230 end 235 end
app/controllers/my_profile/maps_controller.rb
@@ -31,23 +31,11 @@ class MapsController &lt; MyProfileController @@ -31,23 +31,11 @@ class MapsController &lt; MyProfileController
31 end 31 end
32 32
33 def search_city 33 def search_city
34 -  
35 - term = params[:term];  
36 -  
37 - regions = NationalRegion.search_city(term + "%", true).map {|r|{ :label => r.city , :category => r.state}}  
38 -  
39 - render :json => regions  
40 - 34 + render :json => MapsHelper.search_city(params[:term])
41 end 35 end
42 36
43 def search_state 37 def search_state
44 -  
45 - term = params[:term];  
46 -  
47 - regions = NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}}  
48 -  
49 - render :json => regions  
50 - 38 + render :json => MapsHelper.search_state(params[:term])
51 end 39 end
52 40
53 end 41 end
app/controllers/my_profile/profile_design_controller.rb
@@ -55,10 +55,4 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -55,10 +55,4 @@ class ProfileDesignController &lt; BoxOrganizerController
55 blocks 55 blocks
56 end 56 end
57 57
58 - def clone  
59 - block = Block.find(params[:id])  
60 - block.duplicate  
61 - redirect_to :action => 'index'  
62 - end  
63 -  
64 end 58 end
app/controllers/my_profile/profile_editor_controller.rb
@@ -55,11 +55,10 @@ class ProfileEditorController &lt; MyProfileController @@ -55,11 +55,10 @@ class ProfileEditorController &lt; MyProfileController
55 55
56 def update_categories 56 def update_categories
57 @object = profile 57 @object = profile
  58 + @categories = @toplevel_categories = environment.top_level_categories
58 if params[:category_id] 59 if params[:category_id]
59 @current_category = Category.find(params[:category_id]) 60 @current_category = Category.find(params[:category_id])
60 @categories = @current_category.children 61 @categories = @current_category.children
61 - else  
62 - @categories = environment.top_level_categories.select{|i| !i.children.empty?}  
63 end 62 end
64 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false 63 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false
65 end 64 end
app/controllers/public/account_controller.rb
@@ -69,6 +69,8 @@ class AccountController &lt; ApplicationController @@ -69,6 +69,8 @@ class AccountController &lt; ApplicationController
69 session[:notice] = _("This environment doesn't allow user registration.") 69 session[:notice] = _("This environment doesn't allow user registration.")
70 end 70 end
71 71
  72 + store_location(request.referer) unless params[:return_to] or session[:return_to]
  73 +
72 @block_bot = !!session[:may_be_a_bot] 74 @block_bot = !!session[:may_be_a_bot]
73 @invitation_code = params[:invitation_code] 75 @invitation_code = params[:invitation_code]
74 begin 76 begin
@@ -77,6 +79,7 @@ class AccountController &lt; ApplicationController @@ -77,6 +79,7 @@ class AccountController &lt; ApplicationController
77 @user.environment = environment 79 @user.environment = environment
78 @terms_of_use = environment.terms_of_use 80 @terms_of_use = environment.terms_of_use
79 @user.person_data = params[:profile_data] 81 @user.person_data = params[:profile_data]
  82 + @user.return_to = session[:return_to]
80 @person = Person.new(params[:profile_data]) 83 @person = Person.new(params[:profile_data])
81 @person.environment = @user.environment 84 @person.environment = @user.environment
82 if request.post? 85 if request.post?
@@ -98,7 +101,7 @@ class AccountController &lt; ApplicationController @@ -98,7 +101,7 @@ class AccountController &lt; ApplicationController
98 end 101 end
99 if @user.activated? 102 if @user.activated?
100 self.current_user = @user 103 self.current_user = @user
101 - redirect_to '/' 104 + go_to_signup_initial_page
102 else 105 else
103 @register_pending = true 106 @register_pending = true
104 end 107 end
@@ -247,15 +250,19 @@ class AccountController &lt; ApplicationController @@ -247,15 +250,19 @@ class AccountController &lt; ApplicationController
247 end 250 end
248 end 251 end
249 252
250 - def check_url 253 + def check_valid_name
251 @identifier = params[:identifier] 254 @identifier = params[:identifier]
252 valid = Person.is_available?(@identifier, environment) 255 valid = Person.is_available?(@identifier, environment)
253 if valid 256 if valid
254 @status = _('This login name is available') 257 @status = _('This login name is available')
255 @status_class = 'validated' 258 @status_class = 'validated'
256 - else 259 + elsif !@identifier.empty?
  260 + @suggested_usernames = suggestion_based_on_username(@identifier)
257 @status = _('This login name is unavailable') 261 @status = _('This login name is unavailable')
258 @status_class = 'invalid' 262 @status_class = 'invalid'
  263 + else
  264 + @status_class = 'invalid'
  265 + @status = _('This field can\'t be blank')
259 end 266 end
260 render :partial => 'identifier_status' 267 render :partial => 'identifier_status'
261 end 268 end
@@ -288,6 +295,23 @@ class AccountController &lt; ApplicationController @@ -288,6 +295,23 @@ class AccountController &lt; ApplicationController
288 render :text => user_data.to_json, :layout => false, :content_type => "application/javascript" 295 render :text => user_data.to_json, :layout => false, :content_type => "application/javascript"
289 end 296 end
290 297
  298 + def search_cities
  299 + if request.xhr? and params[:state_name] and params[:city_name]
  300 + render :json => MapsHelper.search_city(params[:city_name], params[:state_name])
  301 + else
  302 + render :json => [].to_json
  303 + end
  304 + end
  305 +
  306 + def search_state
  307 + if request.xhr? and params[:state_name]
  308 + render :json => MapsHelper.search_state(params[:state_name])
  309 + else
  310 + render :json => [].to_json
  311 + end
  312 + end
  313 +
  314 +
291 protected 315 protected
292 316
293 def redirect? 317 def redirect?
@@ -368,32 +392,29 @@ class AccountController &lt; ApplicationController @@ -368,32 +392,29 @@ class AccountController &lt; ApplicationController
368 end 392 end
369 393
370 def go_to_initial_page 394 def go_to_initial_page
  395 + if params[:redirection]
  396 + session[:return_to] = @user.return_to
  397 + @user.return_to = nil
  398 + @user.save
  399 + end
  400 +
371 if params[:return_to] 401 if params[:return_to]
372 redirect_to params[:return_to] 402 redirect_to params[:return_to]
373 elsif environment.enabled?('allow_change_of_redirection_after_login') 403 elsif environment.enabled?('allow_change_of_redirection_after_login')
374 - case user.preferred_login_redirection  
375 - when 'keep_on_same_page'  
376 - redirect_back_or_default(user.admin_url)  
377 - when 'site_homepage'  
378 - redirect_to :controller => :home  
379 - when 'user_profile_page'  
380 - redirect_to user.public_profile_url  
381 - when 'user_homepage'  
382 - redirect_to user.url  
383 - when 'user_control_panel'  
384 - redirect_to user.admin_url  
385 - else  
386 - redirect_back_or_default(user.admin_url)  
387 - end 404 + check_redirection_options(user, user.preferred_login_redirection, user.admin_url)
388 else 405 else
389 if environment == current_user.environment 406 if environment == current_user.environment
390 - redirect_back_or_default(user.admin_url) 407 + check_redirection_options(user, environment.redirection_after_login, user.admin_url)
391 else 408 else
392 redirect_back_or_default(:controller => 'home') 409 redirect_back_or_default(:controller => 'home')
393 end 410 end
394 end 411 end
395 end 412 end
396 413
  414 + def go_to_signup_initial_page
  415 + check_redirection_options(user, user.environment.redirection_after_signup, user.url)
  416 + end
  417 +
397 def redirect_if_logged_in 418 def redirect_if_logged_in
398 if logged_in? 419 if logged_in?
399 go_to_initial_page 420 go_to_initial_page
@@ -409,4 +430,22 @@ class AccountController &lt; ApplicationController @@ -409,4 +430,22 @@ class AccountController &lt; ApplicationController
409 user 430 user
410 end 431 end
411 432
  433 + protected
  434 +
  435 + def check_redirection_options(user, condition, default)
  436 + case condition
  437 + when 'keep_on_same_page'
  438 + redirect_back_or_default(user.admin_url)
  439 + when 'site_homepage'
  440 + redirect_to :controller => :home
  441 + when 'user_profile_page'
  442 + redirect_to user.public_profile_url
  443 + when 'user_homepage'
  444 + redirect_to user.url
  445 + when 'user_control_panel'
  446 + redirect_to user.admin_url
  447 + else
  448 + redirect_back_or_default(default)
  449 + end
  450 + end
412 end 451 end
app/controllers/public/content_viewer_controller.rb
@@ -52,7 +52,7 @@ class ContentViewerController &lt; ApplicationController @@ -52,7 +52,7 @@ class ContentViewerController &lt; ApplicationController
52 end 52 end
53 53
54 # At this point the page will be showed 54 # At this point the page will be showed
55 - @page.hit 55 + @page.hit unless user_is_a_bot?
56 56
57 @page = FilePresenter.for @page 57 @page = FilePresenter.for @page
58 58
@@ -113,6 +113,15 @@ class ContentViewerController &lt; ApplicationController @@ -113,6 +113,15 @@ class ContentViewerController &lt; ApplicationController
113 @comments = @plugins.filter(:unavailable_comments, @comments) 113 @comments = @plugins.filter(:unavailable_comments, @comments)
114 @comments_count = @comments.count 114 @comments_count = @comments.count
115 @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] ) 115 @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )
  116 + @comment_order = params[:comment_order].nil? ? 'oldest' : params[:comment_order]
  117 +
  118 + if request.xhr? and params[:comment_order]
  119 + if @comment_order == 'newest'
  120 + @comments = @comments.reverse
  121 + end
  122 +
  123 + return render :partial => 'comment/comment', :collection => @comments
  124 + end
116 125
117 if params[:slideshow] 126 if params[:slideshow]
118 render :action => 'slideshow', :layout => 'slideshow' 127 render :action => 'slideshow', :layout => 'slideshow'
@@ -178,4 +187,13 @@ class ContentViewerController &lt; ApplicationController @@ -178,4 +187,13 @@ class ContentViewerController &lt; ApplicationController
178 allowed 187 allowed
179 end 188 end
180 189
  190 + def user_is_a_bot?
  191 + user_agent= request.env["HTTP_USER_AGENT"]
  192 + user_agent.blank? ||
  193 + user_agent.match(/bot/) ||
  194 + user_agent.match(/spider/) ||
  195 + user_agent.match(/crawler/) ||
  196 + user_agent.match(/\(.*https?:\/\/.*\)/)
  197 + end
  198 +
181 end 199 end
app/controllers/public/events_controller.rb
@@ -7,11 +7,11 @@ class EventsController &lt; PublicController @@ -7,11 +7,11 @@ class EventsController &lt; PublicController
7 @date = build_date(params[:year], params[:month], params[:day]) 7 @date = build_date(params[:year], params[:month], params[:day])
8 8
9 if !params[:year] && !params[:month] && !params[:day] 9 if !params[:year] && !params[:month] && !params[:day]
10 - @events = profile.events.next_events_from_month(@date) 10 + @events = profile.events.next_events_from_month(@date).paginate(:per_page => per_page, :page => params[:page])
11 end 11 end
12 12
13 if params[:year] || params[:month] 13 if params[:year] || params[:month]
14 - @events = profile.events.by_month(@date) 14 + @events = profile.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
15 end 15 end
16 16
17 events_in_range = profile.events.by_range((@date - 1.month).at_beginning_of_month .. (@date + 1.month).at_end_of_month) 17 events_in_range = profile.events.by_range((@date - 1.month).at_beginning_of_month .. (@date + 1.month).at_end_of_month)
@@ -21,7 +21,7 @@ class EventsController &lt; PublicController @@ -21,7 +21,7 @@ class EventsController &lt; PublicController
21 21
22 def events_by_day 22 def events_by_day
23 @date = build_date(params[:year], params[:month], params[:day]) 23 @date = build_date(params[:year], params[:month], params[:day])
24 - @events = profile.events.by_day(@date) 24 + @events = profile.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
25 render :partial => 'events' 25 render :partial => 'events'
26 end 26 end
27 27
@@ -29,4 +29,7 @@ class EventsController &lt; PublicController @@ -29,4 +29,7 @@ class EventsController &lt; PublicController
29 29
30 include EventsHelper 30 include EventsHelper
31 31
  32 + def per_page
  33 + 20
  34 + end
32 end 35 end
app/controllers/public/search_controller.rb
@@ -99,14 +99,14 @@ class SearchController &lt; PublicController @@ -99,14 +99,14 @@ class SearchController &lt; PublicController
99 @events = [] 99 @events = []
100 if params[:day] || !params[:year] && !params[:month] 100 if params[:day] || !params[:year] && !params[:month]
101 @events = @category ? 101 @events = @category ?
102 - environment.events.by_day(@date).in_category(Category.find(@category_id)) :  
103 - environment.events.by_day(@date) 102 + environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
  103 + environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
104 end 104 end
105 105
106 if params[:year] || params[:month] 106 if params[:year] || params[:month]
107 @events = @category ? 107 @events = @category ?
108 - environment.events.by_month(@date).in_category(Category.find(@category_id)) :  
109 - environment.events.by_month(@date) 108 + environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
  109 + environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
110 end 110 end
111 111
112 @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events 112 @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events
@@ -139,7 +139,7 @@ class SearchController &lt; PublicController @@ -139,7 +139,7 @@ class SearchController &lt; PublicController
139 139
140 def events_by_day 140 def events_by_day
141 @date = build_date(params[:year], params[:month], params[:day]) 141 @date = build_date(params[:year], params[:month], params[:day])
142 - @events = environment.events.by_day(@date) 142 + @events = environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
143 render :partial => 'events/events' 143 render :partial => 'events/events'
144 end 144 end
145 145
@@ -224,4 +224,8 @@ class SearchController &lt; PublicController @@ -224,4 +224,8 @@ class SearchController &lt; PublicController
224 @environment.send(klass.name.underscore.pluralize).visible.includes(relations) 224 @environment.send(klass.name.underscore.pluralize).visible.includes(relations)
225 end 225 end
226 226
  227 + def per_page
  228 + 20
  229 + end
  230 +
227 end 231 end
app/controllers/themes_controller.rb
@@ -12,7 +12,7 @@ class ThemesController &lt; ApplicationController @@ -12,7 +12,7 @@ class ThemesController &lt; ApplicationController
12 12
13 def index 13 def index
14 @environment = environment 14 @environment = environment
15 - @themes = environment.themes + Theme.approved_themes(target) 15 + @themes = (environment.themes + Theme.approved_themes(target)).sort_by { |t| t.name }
16 16
17 @current_theme = target.theme 17 @current_theme = target.theme
18 18
app/helpers/account_helper.rb
@@ -12,4 +12,17 @@ module AccountHelper @@ -12,4 +12,17 @@ module AccountHelper
12 _('Checking if e-mail address is already taken...') 12 _('Checking if e-mail address is already taken...')
13 end 13 end
14 end 14 end
  15 +
  16 + def suggestion_based_on_username(requested_username='')
  17 + return "" if requested_username.empty?
  18 + usernames = []
  19 + 3.times do
  20 + begin
  21 + valid_name = requested_username + rand(1000).to_s
  22 + end while (usernames.include?(valid_name) || !Person.is_available?(valid_name, environment))
  23 + usernames << valid_name
  24 + end
  25 + usernames
  26 + end
  27 +
15 end 28 end
app/helpers/application_helper.rb
@@ -605,49 +605,18 @@ module ApplicationHelper @@ -605,49 +605,18 @@ module ApplicationHelper
605 end 605 end
606 606
607 attr_reader :environment 607 attr_reader :environment
  608 +
608 def select_categories(object_name, title=nil, title_size=4) 609 def select_categories(object_name, title=nil, title_size=4)
609 return nil if environment.enabled?(:disable_categories) 610 return nil if environment.enabled?(:disable_categories)
610 if title.nil? 611 if title.nil?
611 title = _('Categories') 612 title = _('Categories')
612 end 613 end
613 614
614 - object = instance_variable_get("@#{object_name}")  
615 -  
616 - result = content_tag 'h'+title_size.to_s(), title  
617 - result << javascript_tag( 'function open_close_cat( link ) {  
618 - var div = link.parentNode.getElementsByTagName("div")[0];  
619 - var end = function(){  
620 - if ( div.style.display == "none" ) {  
621 - this.link.className="button icon-button icon-down"  
622 - } else {  
623 - this.link.className="button icon-button icon-up-red"  
624 - }  
625 - }  
626 - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } )  
627 - }')  
628 - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel|  
629 - next unless object.accept_category?(toplevel)  
630 - # FIXME  
631 - ([toplevel] + toplevel.children_for_menu).each do |cat|  
632 - if cat.top_level?  
633 - result << '<div class="categorie_box">'.html_safe  
634 - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )  
635 - result << content_tag('h5', toplevel.name)  
636 - result << '<div style="display:none"><ul class="categories">'.html_safe  
637 - else  
638 - checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"  
639 - result << content_tag('li', labelled_check_box(  
640 - cat.full_name_without_leading(1, " &rarr; "),  
641 - "#{object_name}[category_ids][]", cat.id,  
642 - object.category_ids.include?(cat.id), :id => checkbox_id,  
643 - :onchange => j('this.parentNode.className=(this.checked?"cat_checked":"")') ),  
644 - :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"  
645 - end  
646 - end  
647 - result << '</ul></div></div>'.html_safe  
648 - end 615 + @object = instance_variable_get("@#{object_name}")
  616 + @categories = environment.top_level_categories
649 617
650 - content_tag('div', result) 618 + @current_categories = environment.top_level_categories.select{|i| !i.children.empty?}
  619 + render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false
651 end 620 end
652 621
653 def theme_option(opt = nil) 622 def theme_option(opt = nil)
@@ -934,12 +903,11 @@ module ApplicationHelper @@ -934,12 +903,11 @@ module ApplicationHelper
934 903
935 def page_title 904 def page_title
936 (@page ? @page.title + ' - ' : '') + 905 (@page ? @page.title + ' - ' : '') +
937 - (profile ? profile.short_name + ' - ' : '') +  
938 (@topic ? @topic.title + ' - ' : '') + 906 (@topic ? @topic.title + ' - ' : '') +
939 (@section ? @section.title + ' - ' : '') + 907 (@section ? @section.title + ' - ' : '') +
940 (@toc ? _('Online Manual') + ' - ' : '') + 908 (@toc ? _('Online Manual') + ' - ' : '') +
941 (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + 909 (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +
942 - environment.name + 910 + (profile ? profile.short_name : environment.name) +
943 (@category ? " - #{@category.full_name}" : '') 911 (@category ? " - #{@category.full_name}" : '')
944 end 912 end
945 913
app/helpers/article_helper.rb
@@ -50,8 +50,14 @@ module ArticleHelper @@ -50,8 +50,14 @@ module ArticleHelper
50 'div', 50 'div',
51 check_box(:article, :display_versions) + 51 check_box(:article, :display_versions) +
52 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') 52 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions')
53 - ) : '') 53 + ) : '') +
54 54
  55 + (article.forum? && article.profile.community? ?
  56 + content_tag(
  57 + 'div',
  58 + check_box(:article, :allows_members_to_create_topics) +
  59 + content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics')
  60 + ) : '')
55 ) 61 )
56 end 62 end
57 63
app/helpers/boxes_helper.rb
@@ -65,7 +65,7 @@ module BoxesHelper @@ -65,7 +65,7 @@ module BoxesHelper
65 end 65 end
66 66
67 def display_box_content(box, main_content) 67 def display_box_content(box, main_content)
68 - context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params } 68 + context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user }
69 box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) 69 box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box)
70 end 70 end
71 71
@@ -212,13 +212,24 @@ module BoxesHelper @@ -212,13 +212,24 @@ module BoxesHelper
212 212
213 if !block.main? 213 if !block.main?
214 buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) 214 buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
215 - buttons << icon_button(:clone, _('Clone'), { :action => 'clone', :id => block.id }, { :method => 'post' }) 215 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
216 end 216 end
217 217
218 if block.respond_to?(:help) 218 if block.respond_to?(:help)
219 buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") 219 buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
220 end 220 end
221 221
  222 + if block.embedable?
  223 + embed_code = block.embed_code
  224 + embed_code = instance_eval(&embed_code) if embed_code.respond_to?(:call)
  225 + html = content_tag('div',
  226 + content_tag('h2', _('Embed block code')) +
  227 + content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') +
  228 + content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') +
  229 + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
  230 + buttons << thickbox_inline_popup_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html
  231 + end
  232 +
222 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar') 233 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
223 end 234 end
224 235
app/helpers/cache_counter_helper.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +module CacheCounterHelper
  2 + def update_cache_counter(name, object, value)
  3 + if object.present?
  4 + object.class.update_counters(object.id, name => value)
  5 + end
  6 + end
  7 +end
app/helpers/categories_helper.rb
@@ -48,4 +48,12 @@ module CategoriesHelper @@ -48,4 +48,12 @@ module CategoriesHelper
48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) 48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value)))
49 end 49 end
50 50
  51 + #FIXME make this test
  52 + def selected_category_link(cat)
  53 + content_tag('div', button_to_function_without_text(:remove, _('Remove'), nil) {|page| page["selected-category-#{cat.id}"].remove} +
  54 + link_to_function(cat.full_name(' &rarr; '), nil, :id => "remove-selected-category-#{cat.id}-button", :class => 'select-subcategory-link') {|page| page["selected-category-#{cat.id}"].remove},
  55 + :class => 'selected-category'
  56 + )
  57 + end
  58 +
51 end 59 end
app/helpers/comment_helper.rb
@@ -2,7 +2,6 @@ module CommentHelper @@ -2,7 +2,6 @@ module CommentHelper
2 2
3 def article_title(article, args = {}) 3 def article_title(article, args = {})
4 title = article.title 4 title = article.title
5 - title = article.display_title if article.kind_of?(UploadedFile) && article.image?  
6 title = content_tag('h1', h(title), :class => 'title') 5 title = content_tag('h1', h(title), :class => 'title')
7 if article.belongs_to_blog? 6 if article.belongs_to_blog?
8 unless args[:no_link] 7 unless args[:no_link]
@@ -22,6 +21,12 @@ module CommentHelper @@ -22,6 +21,12 @@ module CommentHelper
22 title 21 title
23 end 22 end
24 23
  24 + def comment_extra_contents(comment)
  25 + @plugins.dispatch(:comment_extra_contents, comment).collect do |extra_content|
  26 + extra_content.kind_of?(Proc) ? self.instance_eval(&extra_content) : extra_content
  27 + end.join('\n')
  28 + end
  29 +
25 def comment_actions(comment) 30 def comment_actions(comment)
26 url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) 31 url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id)
27 links = links_for_comment_actions(comment) 32 links = links_for_comment_actions(comment)
app/helpers/content_viewer_helper.rb
@@ -14,8 +14,7 @@ module ContentViewerHelper @@ -14,8 +14,7 @@ module ContentViewerHelper
14 end 14 end
15 15
16 def article_title(article, args = {}) 16 def article_title(article, args = {})
17 - title = article.display_title if article.kind_of?(UploadedFile) && article.image?  
18 - title = article.title if title.blank? 17 + title = article.title
19 title = content_tag('h1', h(title), :class => 'title') 18 title = content_tag('h1', h(title), :class => 'title')
20 if article.belongs_to_blog? || article.belongs_to_forum? 19 if article.belongs_to_blog? || article.belongs_to_forum?
21 unless args[:no_link] 20 unless args[:no_link]
@@ -52,15 +51,6 @@ module ContentViewerHelper @@ -52,15 +51,6 @@ module ContentViewerHelper
52 end 51 end
53 end 52 end
54 53
55 - def addthis_facebook_url(article)  
56 - "http://www.facebook.com/sharer.php?s=100&p[title]=%{title}&p[summary]=%{summary}&p[url]=%{url}&p[images][0]=%{image}" % {  
57 - :title => CGI.escape(article.title),  
58 - :url => CGI.escape(url_for(article.url)),  
59 - :summary => CGI.escape(truncate(strip_tags(article.body.to_s), :length => 300)),  
60 - :image => CGI.escape(article.body_images_paths.first.to_s)  
61 - }  
62 - end  
63 -  
64 def addthis_image_tag 54 def addthis_image_tag
65 if File.exists?(Rails.root.join('public', theme_path, 'images', 'addthis.gif')) 55 if File.exists?(Rails.root.join('public', theme_path, 'images', 'addthis.gif'))
66 image_tag(File.join(theme_path, 'images', 'addthis.gif'), :border => 0, :alt => '') 56 image_tag(File.join(theme_path, 'images', 'addthis.gif'), :border => 0, :alt => '')
app/helpers/layout_helper.rb
@@ -90,5 +90,8 @@ module LayoutHelper @@ -90,5 +90,8 @@ module LayoutHelper
90 end 90 end
91 end 91 end
92 92
  93 + def meta_description_tag(article=nil)
  94 + article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name
  95 + end
93 end 96 end
94 97
app/helpers/macros_helper.rb
@@ -20,14 +20,16 @@ module MacrosHelper @@ -20,14 +20,16 @@ module MacrosHelper
20 jQuery('<div>'+#{macro_configuration_dialog(macro).to_json}+'</div>').dialog({ 20 jQuery('<div>'+#{macro_configuration_dialog(macro).to_json}+'</div>').dialog({
21 title: #{macro_title(macro).to_json}, 21 title: #{macro_title(macro).to_json},
22 modal: true, 22 modal: true,
23 - buttons: [  
24 - {text: #{_('Ok').to_json}, click: function(){ 23 + buttons: {
  24 + #{_('Ok').to_json}: function(){
25 tinyMCE.activeEditor.execCommand('mceInsertContent', false, 25 tinyMCE.activeEditor.execCommand('mceInsertContent', false,
26 (function(dialog){ #{macro_generator(macro)} })(this)); 26 (function(dialog){ #{macro_generator(macro)} })(this));
27 jQuery(this).dialog('close'); 27 jQuery(this).dialog('close');
28 - }},  
29 - {text: #{_('Cancel').to_json}, click: function(){jQuery(this).dialog('close');}}  
30 - ] 28 + },
  29 + #{_('Cancel').to_json}: function(){
  30 + jQuery(this).dialog('close');
  31 + }
  32 + }
31 }); 33 });
32 }" 34 }"
33 end 35 end
@@ -57,7 +59,11 @@ module MacrosHelper @@ -57,7 +59,11 @@ module MacrosHelper
57 59
58 def macro_generator(macro) 60 def macro_generator(macro)
59 if macro.configuration[:generator] 61 if macro.configuration[:generator]
60 - macro.configuration[:generator] 62 + if macro.configuration[:generator].respond_to?(:call)
  63 + macro.configuration[:generator].call(macro)
  64 + else
  65 + macro.configuration[:generator]
  66 + end
61 else 67 else
62 macro_default_generator(macro) 68 macro_default_generator(macro)
63 end 69 end
@@ -66,8 +72,7 @@ module MacrosHelper @@ -66,8 +72,7 @@ module MacrosHelper
66 72
67 def macro_default_generator(macro) 73 def macro_default_generator(macro)
68 code = "var params = {};" 74 code = "var params = {};"
69 - configuration = macro_configuration(macro)  
70 - configuration[:params].map do |field| 75 + macro.configuration[:params].map do |field|
71 code += "params.#{field[:name]} = jQuery('*[name=#{field[:name]}]', dialog).val();" 76 code += "params.#{field[:name]} = jQuery('*[name=#{field[:name]}]', dialog).val();"
72 end 77 end
73 code + " 78 code + "
app/helpers/maps_helper.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +module MapsHelper
  2 + def self.search_city term, state=""
  3 + cities = if state.empty?
  4 + NationalRegion.search_city(term + "%", true)
  5 + else
  6 + NationalRegion.search_city(term + "%", true, state)
  7 + end
  8 + cities.map {|r|{ :label => r.city , :category => r.state}}
  9 + end
  10 +
  11 + def self.search_state term
  12 + NationalRegion.search_state(term + "%", true).map {|r|{ :label => r.state}}
  13 + end
  14 +end
app/helpers/person_notifier_helper.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +module PersonNotifierHelper
  2 +
  3 + include ApplicationHelper
  4 +
  5 + private
  6 +
  7 + def path_to_image(source)
  8 + top_url + source
  9 + end
  10 +
  11 + def top_url
  12 + top_url = @profile.environment ? @profile.environment.top_url : ''
  13 + end
  14 +
  15 +end
app/helpers/token_helper.rb
@@ -27,7 +27,7 @@ module TokenHelper @@ -27,7 +27,7 @@ module TokenHelper
27 hintText: #{options[:hint_text].to_json}, 27 hintText: #{options[:hint_text].to_json},
28 noResultsText: #{options[:no_results_text].to_json}, 28 noResultsText: #{options[:no_results_text].to_json},
29 searchingText: #{options[:searching_text].to_json}, 29 searchingText: #{options[:searching_text].to_json},
30 - searchDelay: #{options[:serach_delay].to_json}, 30 + searchDelay: #{options[:search_delay].to_json},
31 preventDuplicates: #{options[:prevent_duplicates].to_json}, 31 preventDuplicates: #{options[:prevent_duplicates].to_json},
32 backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, 32 backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
33 queryParam: #{name.to_json}, 33 queryParam: #{name.to_json},
app/mailers/contact.rb
@@ -46,7 +46,7 @@ class Contact @@ -46,7 +46,7 @@ class Contact
46 to: contact.dest.notification_emails, 46 to: contact.dest.notification_emails,
47 reply_to: contact.email, 47 reply_to: contact.email,
48 subject: "[#{contact.dest.short_name(30)}] " + contact.subject, 48 subject: "[#{contact.dest.short_name(30)}] " + contact.subject,
49 - from: "#{contact.name} <#{contact.dest.environment.contact_email}>" 49 + from: "#{contact.name} <#{contact.dest.environment.noreply_email}>"
50 } 50 }
51 51
52 if contact.sender 52 if contact.sender
app/mailers/mailing.rb
@@ -20,7 +20,7 @@ class Mailing &lt; ActiveRecord::Base @@ -20,7 +20,7 @@ class Mailing &lt; ActiveRecord::Base
20 end 20 end
21 21
22 def generate_from 22 def generate_from
23 - "#{source.name} <#{source.contact_email}>" 23 + "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>"
24 end 24 end
25 25
26 def generate_subject 26 def generate_subject
app/mailers/organization_mailing.rb
1 class OrganizationMailing < Mailing 1 class OrganizationMailing < Mailing
2 2
3 def generate_from 3 def generate_from
4 - "#{person.name} <#{source.environment.contact_email}>" 4 + "#{person.name} <#{source.environment.noreply_email}>"
5 end 5 end
6 6
7 def recipients(offset=0, limit=100) 7 def recipients(offset=0, limit=100)
app/mailers/pending_task_notifier.rb
@@ -11,7 +11,7 @@ class PendingTaskNotifier &lt; ActionMailer::Base @@ -11,7 +11,7 @@ class PendingTaskNotifier &lt; ActionMailer::Base
11 11
12 mail( 12 mail(
13 to: person.email, 13 to: person.email,
14 - from: "#{person.environment.name} <#{person.environment.contact_email}>", 14 + from: "#{person.environment.name} <#{person.environment.noreply_email}>",
15 subject: _("[%s] Pending tasks") % person.environment.name 15 subject: _("[%s] Pending tasks") % person.environment.name
16 ) 16 )
17 end 17 end
app/mailers/task_mailer.rb
@@ -52,7 +52,7 @@ class TaskMailer &lt; ActionMailer::Base @@ -52,7 +52,7 @@ class TaskMailer &lt; ActionMailer::Base
52 end 52 end
53 53
54 def self.generate_from(task) 54 def self.generate_from(task)
55 - "#{task.environment.name} <#{task.environment.contact_email}>" 55 + "#{task.environment.name} <#{task.environment.noreply_email}>"
56 end 56 end
57 57
58 def generate_environment_url(task, url = {}) 58 def generate_environment_url(task, url = {})
app/models/block.rb
@@ -18,17 +18,36 @@ class Block &lt; ActiveRecord::Base @@ -18,17 +18,36 @@ class Block &lt; ActiveRecord::Base
18 18
19 scope :enabled, :conditions => { :enabled => true } 19 scope :enabled, :conditions => { :enabled => true }
20 20
  21 + def embedable?
  22 + false
  23 + end
  24 +
  25 + def embed_code
  26 + me = self
  27 + lambda do
  28 + content_tag('iframe', '',
  29 + :src => url_for(:controller => 'embed', :action => 'block', :id => me.id, :only_path => false),
  30 + :frameborder => 0,
  31 + :width => 1024,
  32 + :height => 768,
  33 + :class => "embed block #{me.class.name.to_css_class}"
  34 + )
  35 + end
  36 + end
  37 +
21 # Determines whether a given block must be visible. Optionally a 38 # Determines whether a given block must be visible. Optionally a
22 # <tt>context</tt> must be specified. <tt>context</tt> must be a hash, and 39 # <tt>context</tt> must be specified. <tt>context</tt> must be a hash, and
23 # may contain the following keys: 40 # may contain the following keys:
24 # 41 #
25 # * <tt>:article</tt>: the article being viewed currently 42 # * <tt>:article</tt>: the article being viewed currently
26 # * <tt>:language</tt>: in which language the block will be displayed 43 # * <tt>:language</tt>: in which language the block will be displayed
  44 + # * <tt>:user</tt>: the logged user
27 def visible?(context = nil) 45 def visible?(context = nil)
28 return false if display == 'never' 46 return false if display == 'never'
29 47
30 if context 48 if context
31 return false if language != 'all' && language != context[:locale] 49 return false if language != 'all' && language != context[:locale]
  50 + return false unless display_to_user?(context[:user])
32 51
33 begin 52 begin
34 return self.send("display_#{display}", context) 53 return self.send("display_#{display}", context)
@@ -40,6 +59,10 @@ class Block &lt; ActiveRecord::Base @@ -40,6 +59,10 @@ class Block &lt; ActiveRecord::Base
40 true 59 true
41 end 60 end
42 61
  62 + def display_to_user?(user)
  63 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged')
  64 + end
  65 +
43 def display_always(context) 66 def display_always(context)
44 true 67 true
45 end 68 end
@@ -70,6 +93,14 @@ class Block &lt; ActiveRecord::Base @@ -70,6 +93,14 @@ class Block &lt; ActiveRecord::Base
70 # the homepage of its owner. 93 # the homepage of its owner.
71 settings_items :display, :type => :string, :default => 'always' 94 settings_items :display, :type => :string, :default => 'always'
72 95
  96 +
  97 + # The condition for displaying a block to users. It can assume the following values:
  98 + #
  99 + # * <tt>'all'</tt>: the block is always displayed
  100 + # * <tt>'logged'</tt>: the block is displayed to logged users only
  101 + # * <tt>'not_logged'</tt>: the block is displayed only to not logged users
  102 + settings_items :display_user, :type => :string, :default => 'all'
  103 +
73 # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment: 104 # The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment:
74 # 105 #
75 # * <tt>'all'</tt>: the block is always displayed 106 # * <tt>'all'</tt>: the block is always displayed
@@ -143,7 +174,7 @@ class Block &lt; ActiveRecord::Base @@ -143,7 +174,7 @@ class Block &lt; ActiveRecord::Base
143 end 174 end
144 175
145 alias :active_record_cache_key :cache_key 176 alias :active_record_cache_key :cache_key
146 - def cache_key(language='en') 177 + def cache_key(language='en', user=nil)
147 active_record_cache_key+'-'+language 178 active_record_cache_key+'-'+language
148 end 179 end
149 180
@@ -173,12 +204,20 @@ class Block &lt; ActiveRecord::Base @@ -173,12 +204,20 @@ class Block &lt; ActiveRecord::Base
173 'never' => _('Don\'t display'), 204 'never' => _('Don\'t display'),
174 } 205 }
175 206
176 - def display_options 207 + def display_options_available
177 DISPLAY_OPTIONS.keys 208 DISPLAY_OPTIONS.keys
178 end 209 end
179 210
180 - def display_option_label(option)  
181 - DISPLAY_OPTIONS[option] 211 + def display_options
  212 + DISPLAY_OPTIONS.slice(*display_options_available)
  213 + end
  214 +
  215 + def display_user_options
  216 + @display_user_options ||= {
  217 + 'all' => __('All users'),
  218 + 'logged' => __('Logged'),
  219 + 'not_logged' => __('Not logged'),
  220 + }
182 end 221 end
183 222
184 def duplicate 223 def duplicate
app/models/box.rb
@@ -28,6 +28,8 @@ class Box &lt; ActiveRecord::Base @@ -28,6 +28,8 @@ class Box &lt; ActiveRecord::Base
28 CategoriesBlock, 28 CategoriesBlock,
29 CommunitiesBlock, 29 CommunitiesBlock,
30 EnterprisesBlock, 30 EnterprisesBlock,
  31 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  32 + # the Noosfero core soon, see ActionItem3045
31 EnvironmentStatisticsBlock, 33 EnvironmentStatisticsBlock,
32 FansBlock, 34 FansBlock,
33 FavoriteEnterprisesBlock, 35 FavoriteEnterprisesBlock,
@@ -54,6 +56,8 @@ class Box &lt; ActiveRecord::Base @@ -54,6 +56,8 @@ class Box &lt; ActiveRecord::Base
54 CommunitiesBlock, 56 CommunitiesBlock,
55 DisabledEnterpriseMessageBlock, 57 DisabledEnterpriseMessageBlock,
56 EnterprisesBlock, 58 EnterprisesBlock,
  59 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  60 + # the Noosfero core soon, see ActionItem3045
57 EnvironmentStatisticsBlock, 61 EnvironmentStatisticsBlock,
58 FansBlock, 62 FansBlock,
59 FavoriteEnterprisesBlock, 63 FavoriteEnterprisesBlock,
app/models/comment.rb
@@ -170,6 +170,40 @@ class Comment &lt; ActiveRecord::Base @@ -170,6 +170,40 @@ class Comment &lt; ActiveRecord::Base
170 body || '' 170 body || ''
171 end 171 end
172 172
  173 + class Notifier < ActionMailer::Base
  174 + def mail(comment)
  175 + profile = comment.article.profile
  176 + recipients comment.notification_emails
  177 + from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
  178 + subject _("[%s] you got a new comment!") % [profile.environment.name]
  179 + body :recipient => profile.nickname || profile.name,
  180 + :sender => comment.author_name,
  181 + :sender_link => comment.author_link,
  182 + :article_title => comment.article.name,
  183 + :comment_url => comment.url,
  184 + :comment_title => comment.title,
  185 + :comment_body => comment.body,
  186 + :environment => profile.environment.name,
  187 + :url => profile.environment.top_url
  188 + end
  189 + def mail_to_followers(comment, emails)
  190 + profile = comment.article.profile
  191 + bcc emails
  192 + from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
  193 + subject _("[%s] %s commented on a content of %s") % [profile.environment.name, comment.author_name, profile.short_name]
  194 + body :recipient => profile.nickname || profile.name,
  195 + :sender => comment.author_name,
  196 + :sender_link => comment.author_link,
  197 + :article_title => comment.article.name,
  198 + :comment_url => comment.url,
  199 + :unsubscribe_url => comment.article.view_url.merge({:unfollow => true}),
  200 + :comment_title => comment.title,
  201 + :comment_body => comment.body,
  202 + :environment => profile.environment.name,
  203 + :url => profile.environment.top_url
  204 + end
  205 + end
  206 +
173 def rejected? 207 def rejected?
174 @rejected 208 @rejected
175 end 209 end
app/models/environment.rb
@@ -147,6 +147,18 @@ class Environment &lt; ActiveRecord::Base @@ -147,6 +147,18 @@ class Environment &lt; ActiveRecord::Base
147 end 147 end
148 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true 148 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true
149 149
  150 + def self.signup_redirection_options
  151 + {
  152 + 'keep_on_same_page' => _('Stays on the same page the user was before signup.'),
  153 + 'site_homepage' => _('Redirects the user to the environment homepage.'),
  154 + 'user_profile_page' => _('Redirects the user to his profile page.'),
  155 + 'user_homepage' => _('Redirects the user to his homepage.'),
  156 + 'user_control_panel' => _('Redirects the user to his control panel.')
  157 + }
  158 + end
  159 + validates_inclusion_of :redirection_after_signup, :in => Environment.signup_redirection_options.keys, :allow_nil => true
  160 +
  161 +
150 # ################################################# 162 # #################################################
151 # Relationships and applied behaviour 163 # Relationships and applied behaviour
152 # ################################################# 164 # #################################################
@@ -163,6 +175,8 @@ class Environment &lt; ActiveRecord::Base @@ -163,6 +175,8 @@ class Environment &lt; ActiveRecord::Base
163 175
164 # "left" area 176 # "left" area
165 env.boxes[1].blocks << LoginBlock.new 177 env.boxes[1].blocks << LoginBlock.new
  178 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  179 + # the Noosfero core soon, see ActionItem3045
166 env.boxes[1].blocks << EnvironmentStatisticsBlock.new 180 env.boxes[1].blocks << EnvironmentStatisticsBlock.new
167 env.boxes[1].blocks << RecentDocumentsBlock.new 181 env.boxes[1].blocks << RecentDocumentsBlock.new
168 182
@@ -580,7 +594,7 @@ class Environment &lt; ActiveRecord::Base @@ -580,7 +594,7 @@ class Environment &lt; ActiveRecord::Base
580 # only one environment can be the default one 594 # only one environment can be the default one
581 validates_uniqueness_of :is_default, :if => (lambda do |environment| environment.is_default? end), :message => N_('Only one Virtual Community can be the default one') 595 validates_uniqueness_of :is_default, :if => (lambda do |environment| environment.is_default? end), :message => N_('Only one Virtual Community can be the default one')
582 596
583 - validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |record| ! record.contact_email.blank? }) 597 + validates_format_of :contact_email, :noreply_email, :with => Noosfero::Constants::EMAIL_FORMAT, :allow_blank => true
584 598
585 xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation' 599 xss_terminate :only => [ :message_for_disabled_enterprise ], :with => 'white_list', :on => 'validation'
586 600
@@ -768,7 +782,7 @@ class Environment &lt; ActiveRecord::Base @@ -768,7 +782,7 @@ class Environment &lt; ActiveRecord::Base
768 end 782 end
769 783
770 def notification_emails 784 def notification_emails
771 - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) 785 + [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email)
772 end 786 end
773 787
774 after_create :create_templates 788 after_create :create_templates
app/models/environment_statistics_block.rb
  1 +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  2 +# the Noosfero core soon, see ActionItem3045
  3 +
1 class EnvironmentStatisticsBlock < Block 4 class EnvironmentStatisticsBlock < Block
2 5
3 def self.description 6 def self.description
4 - _('Environment stastistics') 7 + _('Environment stastistics (DEPRECATED)')
5 end 8 end
6 9
7 def default_title 10 def default_title
app/models/event.rb
@@ -43,15 +43,12 @@ class Event &lt; Article @@ -43,15 +43,12 @@ class Event &lt; Article
43 scope :next_events_from_month, lambda { |date| 43 scope :next_events_from_month, lambda { |date|
44 date_temp = date.strftime("%Y-%m-%d") 44 date_temp = date.strftime("%Y-%m-%d")
45 { :conditions => ["start_date >= ?","#{date_temp}"], 45 { :conditions => ["start_date >= ?","#{date_temp}"],
46 - :limit => 10,  
47 :order => 'start_date ASC' 46 :order => 'start_date ASC'
48 } 47 }
49 } 48 }
50 49
51 scope :by_month, lambda { |date| 50 scope :by_month, lambda { |date|
52 - date_temp = date.strftime("%Y-%m")  
53 { :conditions => ["EXTRACT(YEAR FROM start_date) = ? AND EXTRACT(MONTH FROM start_date) = ?",date.year,date.month], 51 { :conditions => ["EXTRACT(YEAR FROM start_date) = ? AND EXTRACT(MONTH FROM start_date) = ?",date.year,date.month],
54 - :limit => 10,  
55 :order => 'start_date ASC' 52 :order => 'start_date ASC'
56 } 53 }
57 } 54 }
app/models/forum.rb
@@ -7,6 +7,7 @@ class Forum &lt; Folder @@ -7,6 +7,7 @@ class Forum &lt; Folder
7 7
8 settings_items :terms_of_use, :type => :string, :default => "" 8 settings_items :terms_of_use, :type => :string, :default => ""
9 settings_items :has_terms_of_use, :type => :boolean, :default => false 9 settings_items :has_terms_of_use, :type => :boolean, :default => false
  10 + settings_items :allows_members_to_create_topics, :type => :boolean, :default => false
10 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' 11 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people'
11 12
12 before_save do |forum| 13 before_save do |forum|
@@ -68,4 +69,11 @@ class Forum &lt; Folder @@ -68,4 +69,11 @@ class Forum &lt; Folder
68 self.users_with_agreement.exists? user 69 self.users_with_agreement.exists? user
69 end 70 end
70 71
  72 + def can_create_topic?(user, profile)
  73 + return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics
  74 + end
  75 +
  76 + def allow_create?(user)
  77 + super || can_create_topic?(user, profile)
  78 + end
71 end 79 end
app/models/friendship.rb
1 class Friendship < ActiveRecord::Base 1 class Friendship < ActiveRecord::Base
2 track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :custom_user => :person 2 track_actions :new_friendship, :after_create, :keep_params => ["friend.name", "friend.url", "friend.profile_custom_icon"], :custom_user => :person
3 - 3 +
  4 + extend CacheCounterHelper
  5 +
4 belongs_to :person, :foreign_key => :person_id 6 belongs_to :person, :foreign_key => :person_id
5 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id' 7 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
  8 +
  9 + after_create do |friendship|
  10 + update_cache_counter(:friends_count, friendship.person, 1)
  11 + update_cache_counter(:friends_count, friendship.friend, 1)
  12 + end
  13 +
  14 + after_destroy do |friendship|
  15 + update_cache_counter(:friends_count, friendship.person, -1)
  16 + update_cache_counter(:friends_count, friendship.friend, -1)
  17 + end
6 end 18 end
app/models/layout_template.rb
@@ -16,15 +16,15 @@ class LayoutTemplate @@ -16,15 +16,15 @@ class LayoutTemplate
16 end 16 end
17 17
18 def name 18 def name
19 - @config['name'] 19 + _ @config['name']
20 end 20 end
21 21
22 def title 22 def title
23 - @config['title'] 23 + _ @config['title']
24 end 24 end
25 25
26 def description 26 def description
27 - @config['description'] 27 + _ @config['description']
28 end 28 end
29 29
30 def number_of_boxes 30 def number_of_boxes
app/models/link_list_block.rb
@@ -72,6 +72,8 @@ class LinkListBlock &lt; Block @@ -72,6 +72,8 @@ class LinkListBlock &lt; Block
72 def expand_address(address) 72 def expand_address(address)
73 add = if owner.respond_to?(:identifier) 73 add = if owner.respond_to?(:identifier)
74 address.gsub('{profile}', owner.identifier) 74 address.gsub('{profile}', owner.identifier)
  75 + elsif owner.is_a?(Environment) && owner.enabled?('use_portal_community') && owner.portal_community
  76 + address.gsub('{portal}', owner.portal_community.identifier)
75 else 77 else
76 address 78 address
77 end 79 end
app/models/main_block.rb
@@ -24,7 +24,7 @@ class MainBlock &lt; Block @@ -24,7 +24,7 @@ class MainBlock &lt; Block
24 false 24 false
25 end 25 end
26 26
27 - def display_options 27 + def display_options_available
28 ['always', 'except_home_page'] 28 ['always', 'except_home_page']
29 end 29 end
30 30
app/models/members_block.rb
@@ -38,4 +38,15 @@ class MembersBlock &lt; ProfileListBlock @@ -38,4 +38,15 @@ class MembersBlock &lt; ProfileListBlock
38 } 38 }
39 end 39 end
40 40
  41 + def cache_key(language='en', user=nil)
  42 + logged = ''
  43 + if user
  44 + logged += '-logged-in'
  45 + if user.is_member_of? self.owner
  46 + logged += '-member'
  47 + end
  48 + end
  49 + super + logged
  50 + end
  51 +
41 end 52 end
app/models/national_region.rb
@@ -12,7 +12,7 @@ class NationalRegion &lt; ActiveRecord::Base @@ -12,7 +12,7 @@ class NationalRegion &lt; ActiveRecord::Base
12 adtional_contions = ""; 12 adtional_contions = "";
13 13
14 if like 14 if like
15 - operator = "like" 15 + operator = "ilike"
16 find_return = :all 16 find_return = :all
17 end 17 end
18 18
@@ -41,7 +41,7 @@ class NationalRegion &lt; ActiveRecord::Base @@ -41,7 +41,7 @@ class NationalRegion &lt; ActiveRecord::Base
41 find_return = :first 41 find_return = :first
42 42
43 if like 43 if like
44 - operator = "like" 44 + operator = "ilike"
45 find_return = :all 45 find_return = :all
46 end 46 end
47 47
app/models/organization.rb
@@ -28,18 +28,7 @@ class Organization &lt; Profile @@ -28,18 +28,7 @@ class Organization &lt; Profile
28 28
29 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source' 29 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source'
30 30
31 - scope :more_popular,  
32 - :select => "#{Profile.qualified_column_names}, count(resource_id) as total",  
33 - :group => Profile.qualified_column_names,  
34 - :joins => "LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id",  
35 - :order => "total DESC"  
36 -  
37 - scope :more_active,  
38 - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",  
39 - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id",  
40 - :group => Profile.qualified_column_names,  
41 - :order => 'total DESC',  
42 - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago] 31 + scope :more_popular, :order => 'members_count DESC'
43 32
44 def validation_methodology 33 def validation_methodology
45 self.validation_info ? self.validation_info.validation_methodology : nil 34 self.validation_info ? self.validation_info.validation_methodology : nil
app/models/person.rb
@@ -59,18 +59,7 @@ class Person &lt; Profile @@ -59,18 +59,7 @@ class Person &lt; Profile
59 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' 59 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
60 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' 60 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
61 61
62 - scope :more_popular,  
63 - :select => "#{Profile.qualified_column_names}, count(friend_id) as total",  
64 - :group => Profile.qualified_column_names,  
65 - :joins => "LEFT OUTER JOIN friendships on profiles.id = friendships.person_id",  
66 - :order => "total DESC"  
67 -  
68 - scope :more_active,  
69 - :select => "#{Profile.qualified_column_names}, count(action_tracker.id) as total",  
70 - :joins => "LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id",  
71 - :group => Profile.qualified_column_names,  
72 - :order => 'total DESC',  
73 - :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago] 62 + scope :more_popular, :order => 'friends_count DESC'
74 63
75 scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*' 64 scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*'
76 scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*" 65 scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*"
@@ -492,6 +481,17 @@ class Person &lt; Profile @@ -492,6 +481,17 @@ class Person &lt; Profile
492 gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default) 481 gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default)
493 end 482 end
494 483
  484 + settings_items :last_notification, :type => DateTime
  485 + settings_items :notification_time, :type => :integer, :default => 0
  486 +
  487 + def notifier
  488 + @notifier ||= PersonNotifier.new(self)
  489 + end
  490 +
  491 + after_update do |person|
  492 + person.notifier.reschedule_next_notification_mail
  493 + end
  494 +
495 protected 495 protected
496 496
497 def followed_by?(profile) 497 def followed_by?(profile)
app/models/person_notifier.rb 0 → 100644
@@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
  1 +class PersonNotifier
  2 +
  3 + def initialize(person)
  4 + @person = person
  5 + end
  6 +
  7 + def self.schedule_all_next_notification_mail
  8 + Delayed::Job.enqueue(NotifyAllJob.new) unless NotifyAllJob.exists?
  9 + end
  10 +
  11 + def schedule_next_notification_mail
  12 + dispatch_notification_mail if !NotifyJob.exists?(@person.id)
  13 + end
  14 +
  15 + def dispatch_notification_mail
  16 + Delayed::Job.enqueue(NotifyJob.new(@person.id), nil, @person.notification_time.hours.from_now) if @person.notification_time>0
  17 + end
  18 +
  19 + def reschedule_next_notification_mail
  20 + return nil unless @person.setting_changed?(:notification_time) || @person.setting_changed?(:last_notification)
  21 + NotifyJob.find(@person.id).delete_all
  22 + schedule_next_notification_mail
  23 + end
  24 +
  25 + def notify
  26 + if @person.notification_time && @person.notification_time > 0
  27 + from = @person.last_notification || DateTime.now - @person.notification_time.hours
  28 + notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from])
  29 + Noosfero.with_locale @person.environment.default_language do
  30 + Mailer::deliver_content_summary(@person, notifications) unless notifications.empty?
  31 + end
  32 + @person.settings[:last_notification] = DateTime.now
  33 + @person.save!
  34 + end
  35 + end
  36 +
  37 + class NotifyAllJob
  38 + def self.exists?
  39 + Delayed::Job.where(:handler => "--- !ruby/object:PersonNotifier::NotifyAllJob {}\n\n").count > 0
  40 + end
  41 +
  42 + def perform
  43 + Person.find_each {|person| person.notifier.schedule_next_notification_mail }
  44 + end
  45 + end
  46 +
  47 + class NotifyJob < Struct.new(:person_id)
  48 +
  49 + def self.exists?(person_id)
  50 + !find(person_id).empty?
  51 + end
  52 +
  53 + def self.find(person_id)
  54 + Delayed::Job.where(:handler => "--- !ruby/struct:PersonNotifier::NotifyJob \nperson_id: #{person_id}\n")
  55 + end
  56 +
  57 + def perform
  58 + Person.find(person_id).notifier.notify
  59 + end
  60 +
  61 + def on_permanent_failure
  62 + person = Person.find(person_id)
  63 + person.notifier.dispatch_notification_mail
  64 + end
  65 +
  66 + end
  67 +
  68 + class Mailer < ActionMailer::Base
  69 +
  70 + add_template_helper(PersonNotifierHelper)
  71 +
  72 + def session
  73 + {:theme => nil}
  74 + end
  75 +
  76 + def content_summary(person, notifications)
  77 + @current_theme = 'default'
  78 + @profile = person
  79 + recipients person.email
  80 + from "#{@profile.environment.name} <#{@profile.environment.contact_email}>"
  81 + subject _("[%s] Network Activity") % [@profile.environment.name]
  82 + body :recipient => @profile.nickname || @profile.name,
  83 + :environment => @profile.environment.name,
  84 + :url => @profile.environment.top_url,
  85 + :notifications => notifications
  86 + content_type "text/html"
  87 + end
  88 + end
  89 +end
app/models/profile.rb
@@ -100,10 +100,6 @@ class Profile &lt; ActiveRecord::Base @@ -100,10 +100,6 @@ class Profile &lt; ActiveRecord::Base
100 members.order(:name) 100 members.order(:name)
101 end 101 end
102 102
103 - def members_count  
104 - members.count  
105 - end  
106 -  
107 class << self 103 class << self
108 def count_with_distinct(*args) 104 def count_with_distinct(*args)
109 options = args.last || {} 105 options = args.last || {}
@@ -126,10 +122,11 @@ class Profile &lt; ActiveRecord::Base @@ -126,10 +122,11 @@ class Profile &lt; ActiveRecord::Base
126 122
127 scope :visible, :conditions => { :visible => true } 123 scope :visible, :conditions => { :visible => true }
128 scope :public, :conditions => { :visible => true, :public_profile => true } 124 scope :public, :conditions => { :visible => true, :public_profile => true }
129 - # Subclasses must override these methods 125 +
  126 + # Subclasses must override this method
130 scope :more_popular 127 scope :more_popular
131 - scope :more_active  
132 128
  129 + scope :more_active, :order => 'activities_count DESC'
133 scope :more_recent, :order => "created_at DESC" 130 scope :more_recent, :order => "created_at DESC"
134 131
135 acts_as_trackable :dependent => :destroy 132 acts_as_trackable :dependent => :destroy
@@ -626,10 +623,10 @@ private :generate_url, :url_options @@ -626,10 +623,10 @@ private :generate_url, :url_options
626 # Adds a person as member of this Profile. 623 # Adds a person as member of this Profile.
627 def add_member(person) 624 def add_member(person)
628 if self.has_members? 625 if self.has_members?
629 - if self.closed? && members_count > 0 626 + if self.closed? && members.count > 0
630 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) 627 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person)
631 else 628 else
632 - self.affiliate(person, Profile::Roles.admin(environment.id)) if members_count == 0 629 + self.affiliate(person, Profile::Roles.admin(environment.id)) if members.count == 0
633 self.affiliate(person, Profile::Roles.member(environment.id)) 630 self.affiliate(person, Profile::Roles.member(environment.id))
634 end 631 end
635 else 632 else
app/models/scrap.rb
@@ -17,7 +17,7 @@ class Scrap &lt; ActiveRecord::Base @@ -17,7 +17,7 @@ class Scrap &lt; ActiveRecord::Base
17 17
18 scope :not_replies, :conditions => {:scrap_id => nil} 18 scope :not_replies, :conditions => {:scrap_id => nil}
19 19
20 - track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target 20 + track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target
21 21
22 track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver} 22 track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}
23 23
@@ -57,4 +57,21 @@ class Scrap &lt; ActiveRecord::Base @@ -57,4 +57,21 @@ class Scrap &lt; ActiveRecord::Base
57 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?) 57 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
58 end 58 end
59 59
  60 + class Notifier < ActionMailer::Base
  61 + def mail(scrap)
  62 + sender, receiver = scrap.sender, scrap.receiver
  63 + recipients receiver.email
  64 +
  65 + from "#{sender.environment.name} <#{sender.environment.noreply_email}>"
  66 + subject _("[%s] You received a scrap!") % [sender.environment.name]
  67 + body :recipient => receiver.name,
  68 + :sender => sender.name,
  69 + :sender_link => sender.url,
  70 + :scrap_content => scrap.content,
  71 + :wall_url => scrap.scrap_wall_url,
  72 + :environment => sender.environment.name,
  73 + :url => sender.environment.top_url
  74 + end
  75 + end
  76 +
60 end 77 end
app/models/text_article.rb
@@ -22,4 +22,23 @@ class TextArticle &lt; Article @@ -22,4 +22,23 @@ class TextArticle &lt; Article
22 def can_display_versions? 22 def can_display_versions?
23 true 23 true
24 end 24 end
  25 +
  26 + before_save :set_relative_path
  27 +
  28 + def set_relative_path
  29 + parsed = Hpricot(self.body.to_s)
  30 + parsed.search('img[@src]').map { |i| change_element_path(i, 'src') }
  31 + parsed.search('a[@href]').map { |i| change_element_path(i, 'href') }
  32 + self.body = parsed.to_s
  33 + end
  34 +
  35 + def change_element_path(el, attribute)
  36 + fullpath = /(https?):\/\/(#{environment.default_hostname})(:\d+)?(\/.*)/.match(el[attribute])
  37 + if fullpath
  38 + domain = fullpath[2]
  39 + path = fullpath[4]
  40 + el[attribute] = path if domain == environment.default_hostname
  41 + end
  42 + end
  43 +
25 end 44 end
app/models/theme.rb
@@ -42,17 +42,25 @@ class Theme @@ -42,17 +42,25 @@ class Theme
42 end 42 end
43 43
44 def approved_themes(owner) 44 def approved_themes(owner)
45 - Dir.glob(File.join(system_themes_dir, '*')).select do |item|  
46 - if File.exists?( File.join(item, 'theme.yml') )  
47 - config = YAML.load_file(File.join(item, 'theme.yml'))  
48 - (config['owner_type'] == owner.class.base_class.name) &&  
49 - (config['owner_id'] == owner.id) || config['public'] 45 + Dir.glob(File.join(system_themes_dir, '*')).map do |item|
  46 + next unless File.exists? File.join(item, 'theme.yml')
  47 + id = File.basename item
  48 + config = YAML.load_file File.join(item, 'theme.yml')
  49 +
  50 + approved = config['public']
  51 + unless approved
  52 + begin
  53 + approved = owner.kind_of?(config['owner_type'].constantize)
  54 + rescue
  55 + end
  56 + approved &&= config['owner_id'] == owner.id if config['owner_id'].present?
50 end 57 end
51 - end.map do |desc|  
52 - new(File.basename(desc)) 58 +
  59 + [id, config] if approved
  60 + end.compact.map do |id, config|
  61 + new id, config
53 end 62 end
54 end 63 end
55 -  
56 end 64 end
57 65
58 class DuplicatedIdentifier < Exception; end 66 class DuplicatedIdentifier < Exception; end
app/models/uploaded_file.rb
@@ -16,15 +16,12 @@ class UploadedFile &lt; Article @@ -16,15 +16,12 @@ class UploadedFile &lt; Article
16 16
17 include ShortFilename 17 include ShortFilename
18 18
19 - settings_items :title, :type => 'string'  
20 - xss_terminate :only => [ :title ]  
21 -  
22 - def title_with_default  
23 - title_without_default || short_filename(name, 60) 19 + def title
  20 + if self.name.present? then self.name else self.filename end
  21 + end
  22 + def title= value
  23 + self.name = value
24 end 24 end
25 - alias_method_chain :title, :default  
26 -  
27 - validates_size_of :title, :maximum => 60, :if => (lambda { |file| !file.title.blank? })  
28 25
29 sanitize_filename 26 sanitize_filename
30 27
@@ -36,10 +33,6 @@ class UploadedFile &lt; Article @@ -36,10 +33,6 @@ class UploadedFile &lt; Article
36 self.image? ? self.full_filename(:display).to_s.gsub(Rails.root.join('public').to_s, '') : nil 33 self.image? ? self.full_filename(:display).to_s.gsub(Rails.root.join('public').to_s, '') : nil
37 end 34 end
38 35
39 - def display_title  
40 - title.blank? ? name : title  
41 - end  
42 -  
43 def first_paragraph 36 def first_paragraph
44 '' 37 ''
45 end 38 end
@@ -113,7 +106,7 @@ class UploadedFile &lt; Article @@ -113,7 +106,7 @@ class UploadedFile &lt; Article
113 alias :orig_set_filename :filename= 106 alias :orig_set_filename :filename=
114 def filename=(value) 107 def filename=(value)
115 orig_set_filename(value) 108 orig_set_filename(value)
116 - self.name = self.filename 109 + self.name ||= self.filename
117 end 110 end
118 111
119 def download_headers 112 def download_headers
app/models/user.rb
@@ -63,6 +63,44 @@ class User &lt; ActiveRecord::Base @@ -63,6 +63,44 @@ class User &lt; ActiveRecord::Base
63 self.person.preferred_domain && self.person.preferred_domain.name || self.environment.default_hostname(true) 63 self.person.preferred_domain && self.person.preferred_domain.name || self.environment.default_hostname(true)
64 end 64 end
65 65
  66 + class Mailer < ActionMailer::Base
  67 + def activation_email_notify(user)
  68 + user_email = "#{user.login}@#{user.email_domain}"
  69 + recipients user_email
  70 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
  71 + subject _("[%{environment}] Welcome to %{environment} mail!") % { :environment => user.environment.name }
  72 + body :name => user.name,
  73 + :email => user_email,
  74 + :webmail => MailConf.webmail_url(user.login, user.email_domain),
  75 + :environment => user.environment.name,
  76 + :url => url_for(:host => user.environment.default_hostname, :controller => 'home')
  77 + end
  78 +
  79 + def activation_code(user)
  80 + recipients user.email
  81 +
  82 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
  83 + subject _("[%s] Activate your account") % [user.environment.name]
  84 + body :recipient => user.name,
  85 + :activation_code => user.activation_code,
  86 + :environment => user.environment.name,
  87 + :url => user.environment.top_url,
  88 + :redirection => (true if user.return_to)
  89 + end
  90 +
  91 + def signup_welcome_email(user)
  92 + email_body = user.environment.signup_welcome_text_body.gsub('{user_name}', user.name)
  93 + email_subject = user.environment.signup_welcome_text_subject
  94 +
  95 + content_type 'text/html'
  96 + recipients user.email
  97 +
  98 + from "#{user.environment.name} <#{user.environment.noreply_email}>"
  99 + subject email_subject.blank? ? _("Welcome to environment %s") % [user.environment.name] : email_subject
  100 + body email_body
  101 + end
  102 + end
  103 +
66 def signup! 104 def signup!
67 User.transaction do 105 User.transaction do
68 self.save! 106 self.save!
@@ -159,7 +197,7 @@ class User &lt; ActiveRecord::Base @@ -159,7 +197,7 @@ class User &lt; ActiveRecord::Base
159 encryption_methods[sym] = block 197 encryption_methods[sym] = block
160 end 198 end
161 199
162 - # the encryption method used for this instance 200 + # the encryption method used for this instance
163 def encryption_method 201 def encryption_method
164 (password_type || User.system_encryption_method).to_sym 202 (password_type || User.system_encryption_method).to_sym
165 end 203 end
@@ -202,7 +240,7 @@ class User &lt; ActiveRecord::Base @@ -202,7 +240,7 @@ class User &lt; ActiveRecord::Base
202 end 240 end
203 241
204 def remember_token? 242 def remember_token?
205 - remember_token_expires_at && Time.now.utc < remember_token_expires_at 243 + remember_token_expires_at && Time.now.utc < remember_token_expires_at
206 end 244 end
207 245
208 # These create and unset the fields required for remembering users between browser closes 246 # These create and unset the fields required for remembering users between browser closes
@@ -231,7 +269,7 @@ class User &lt; ActiveRecord::Base @@ -231,7 +269,7 @@ class User &lt; ActiveRecord::Base
231 raise IncorrectPassword unless self.authenticated?(current) 269 raise IncorrectPassword unless self.authenticated?(current)
232 self.force_change_password!(new, confirmation) 270 self.force_change_password!(new, confirmation)
233 end 271 end
234 - 272 +
235 # Changes the password of a user without asking for the old password. This 273 # Changes the password of a user without asking for the old password. This
236 # method is intended to be used by the "I forgot my password", and must be 274 # method is intended to be used by the "I forgot my password", and must be
237 # used with care. 275 # used with care.
@@ -302,7 +340,7 @@ class User &lt; ActiveRecord::Base @@ -302,7 +340,7 @@ class User &lt; ActiveRecord::Base
302 end 340 end
303 341
304 protected 342 protected
305 - # before filter 343 + # before filter
306 def encrypt_password 344 def encrypt_password
307 return if password.blank? 345 return if password.blank?
308 self.salt ||= Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record? 346 self.salt ||= Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
app/sweepers/profile_sweeper.rb
@@ -8,6 +8,8 @@ class ProfileSweeper # &lt; ActiveRecord::Observer @@ -8,6 +8,8 @@ class ProfileSweeper # &lt; ActiveRecord::Observer
8 end 8 end
9 9
10 def after_create(profile) 10 def after_create(profile)
  11 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  12 + # the Noosfero core soon, see ActionItem3045
11 expire_statistics_block_cache(profile) 13 expire_statistics_block_cache(profile)
12 end 14 end
13 15
@@ -29,6 +31,8 @@ protected @@ -29,6 +31,8 @@ protected
29 expire_blogs(profile) if profile.organization? 31 expire_blogs(profile) if profile.organization?
30 end 32 end
31 33
  34 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  35 + # the Noosfero core soon, see ActionItem3045
32 def expire_statistics_block_cache(profile) 36 def expire_statistics_block_cache(profile)
33 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } 37 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) }
34 BlockSweeper.expire_blocks(blocks) 38 BlockSweeper.expire_blocks(blocks)
app/views/account/_identifier_status.html.erb
1 <div class='status-identifier'> 1 <div class='status-identifier'>
2 - <p><span class='<%= @status_class %>'><%= @status %></span></p> 2 +
  3 + <span class='<%= @status_class %>'><%= @status %></span>
  4 + <% if @suggested_usernames %>
  5 + <div class='suggested_usernames'>
  6 + <%= _('Available: ') %>
  7 + <% @suggested_usernames.each do |username| %>
  8 + <a href='#'><%= username %></a>
  9 + <% end %>
  10 + </div>
  11 + <% end %>
3 <script type="text/javascript"> 12 <script type="text/javascript">
4 jQuery('#user_login').removeClass('<%= validation_classes %>'); 13 jQuery('#user_login').removeClass('<%= validation_classes %>');
5 jQuery('#user_login').addClass('<%= @status_class %>'); 14 jQuery('#user_login').addClass('<%= @status_class %>');
  15 + jQuery('.suggested_usernames a').click(function(e) {
  16 + e.preventDefault();
  17 +
  18 + fill_username(this.innerHTML);
  19 + });
6 </script> 20 </script>
7 </div> 21 </div>
app/views/account/_signup_form.html.erb
@@ -7,6 +7,8 @@ @@ -7,6 +7,8 @@
7 7
8 <% @profile_data = @person %> 8 <% @profile_data = @person %>
9 9
  10 +<%= javascript_include_tag('sign_up_password_rate') %>
  11 +
10 <%= error_messages_for :user, :person, :header_message => _('The account could not be created') %> 12 <%= error_messages_for :user, :person, :header_message => _('The account could not be created') %>
11 13
12 <%= labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form', :honeypot => true } do |f| %> 14 <%= labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form', :honeypot => true } do |f| %>
@@ -35,24 +37,30 @@ @@ -35,24 +37,30 @@
35 <%= required text_field(:user, :login, :id => 'user_login', 37 <%= required text_field(:user, :login, :id => 'user_login',
36 :onchange => 'this.value = convToValidUsername(this.value);') %> 38 :onchange => 'this.value = convToValidUsername(this.value);') %>
37 <div id='url-check'><p>&nbsp;</p></div> 39 <div id='url-check'><p>&nbsp;</p></div>
  40 + <span id='checking-message' class='checking' style='display:none'><%= _('Checking availability of login name...') %></span>
38 </div> 41 </div>
39 <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %> 42 <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %>
40 <br style="clear: both;" /> 43 <br style="clear: both;" />
41 </div> 44 </div>
42 </div> 45 </div>
43 - <%= observe_field 'user_login',  
44 - :url => { :action => 'check_url' },  
45 - :with => 'identifier',  
46 - :update => 'url-check',  
47 - :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking');  
48 - jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');",  
49 - :complete => "jQuery('#user_login').removeClass('checking')"  
50 - %>  
51 - 46 + <%= javascript_include_tag "signup_form" %>
52 <div id='signup-password'> 47 <div id='signup-password'>
53 <%= required f.password_field(:password, :id => 'user_pw') %> 48 <%= required f.password_field(:password, :id => 'user_pw') %>
54 <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %> 49 <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %>
55 - <div id='fake-check'><p>&nbsp;</p></div> 50 + <div id='password-rate'>
  51 + <p><span class="invalid hidden" id='result-short'>
  52 + <%=_('Short') %>
  53 + </span></p>
  54 + <p><span class="invalid hidden" id='result-bad'>
  55 + <%=_('Bad') %>
  56 + </span></p>
  57 + <p><span class="invalid hidden" id='result-good'>
  58 + <%=_('Good') %>
  59 + </span></p>
  60 + <p><span class="invalid hidden" id='result-strong'>
  61 + <%=_('Strong') %>
  62 + </span></p>
  63 + </div>
56 </div> 64 </div>
57 65
58 <div id='signup-password-confirmation'> 66 <div id='signup-password-confirmation'>
@@ -182,4 +190,9 @@ jQuery(function($) { @@ -182,4 +190,9 @@ jQuery(function($) {
182 else $(this).addClass('validated'); 190 else $(this).addClass('validated');
183 }); 191 });
184 }); 192 });
  193 +
  194 +function fill_username(element){
  195 + jQuery('#url-check').html("<p><span class='checking'><%= _('This login name is available') %></span></p>")
  196 + jQuery('#user_login').val(element).addClass('validated').removeClass('invalid')
  197 +}
185 </script> 198 </script>
app/views/admin_panel/_site_info.html.erb
1 <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> 1 <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %>
2 <%= labelled_form_field(_('Contact email'), text_field(:environment, :contact_email)) %> 2 <%= labelled_form_field(_('Contact email'), text_field(:environment, :contact_email)) %>
  3 +<%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %>
3 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> 4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %>
4 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> 5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %>
5 <%= required f.text_field(:reports_lower_bound, :size => 3) %> 6 <%= required f.text_field(:reports_lower_bound, :size => 3) %>
app/views/blocks/profile_image.html.erb
1 <div class="vcard"> 1 <div class="vcard">
2 2
3 -<p><%= block.title %></p> 3 +<% if block.title.present? %>
  4 + <p><%= block.title %></p>
  5 +<% end %>
4 6
5 <div class="profile-big-image"> 7 <div class="profile-big-image">
6 <div class="profile-big-image-inner1"> 8 <div class="profile-big-image-inner1">
app/views/box_organizer/_link_list_block.html.erb
  1 +<%= javascript_include_tag "edit-link-list.js" %>
  2 +
1 <strong><%= _('Links') %></strong> 3 <strong><%= _('Links') %></strong>
2 <div id='edit-link-list-block'> 4 <div id='edit-link-list-block'>
3 -<table id='links' class='noborder'>  
4 - <tr>  
5 - <th><%= _('Icon') %></th>  
6 - <th><%= _('Name') %></th>  
7 - <th><%= _('Address') %></th>  
8 - <th><%= _('Title') %></th>  
9 - <th><%= _('Target') %></th>  
10 - </tr>  
11 - <% for link in @block.links do %>  
12 - <tr>  
13 - <td><%= icon_selector(link['icon']) %></td>  
14 - <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>  
15 - <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>  
16 - <td><%= text_field_tag 'block[links][][title]', link[:title], :class => 'link-title' %></td>  
17 - <td><%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %></td>  
18 - </tr>  
19 - <% end %>  
20 -</table> 5 + <ul class='link-list-header'>
  6 + <li class='link-list-icon'><%= _('Icon') %></li>
  7 + <li class='link-list-name'><%= _('Name') %></li>
  8 + <li class='link-list-address'><%= _('Address') %></li>
  9 + <li class='link-list-target'><%= _('Target') %></li>
  10 + </ul>
  11 + <ul id="dropable-link-list">
  12 + <% for link in @block.links do %>
  13 + <li>
  14 + <ul class="link-list-row">
  15 + <li>
  16 + <%= icon_selector(link['icon']) %>
  17 + </li>
  18 + <li>
  19 + <%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %>
  20 + </li>
  21 + <li>
  22 + <%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %>
  23 + </li>
  24 + <li>
  25 + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>
  26 + </li>
  27 + <li>
  28 + <%= button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row") %>
  29 + </li>
  30 + </ul>
  31 + </li>
  32 + <% end %>
  33 + </ul>
  34 + <input type="hidden" id="page_url" value="<%=url_for(:action=>'search_autocomplete')%>" />
21 </div> 35 </div>
22 36
23 <%= link_to_function(_('New link'), nil, :class => 'button icon-add with-text') do |page| 37 <%= link_to_function(_('New link'), nil, :class => 'button icon-add with-text') do |page|
24 - page.insert_html :bottom, 'links', j(content_tag('tr',  
25 - content_tag('td', icon_selector('ok')) +  
26 - content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) +  
27 - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') +  
28 - content_tag('td', text_field_tag('block[links][][title]', '', :class => 'link-title')) +  
29 - content_tag('td', select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) 38 + page.insert_html :bottom, 'dropable-link-list', content_tag('li',
  39 + content_tag('ul',
  40 + content_tag('li', icon_selector('ok')) +
  41 + content_tag('li', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
  42 + content_tag('li', text_field_tag('block[links][][address]', nil, :class => 'link-address')) +
  43 + content_tag('li', select_tag('block[links][][target]',
  44 + options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) +
  45 + content_tag('li', button_without_text(:delete, _('Delete'), "#" , :class=>"delete-link-list-row")),
  46 + :class=>"link-list-row new_link_row")
30 ) + 47 ) +
31 - javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")) 48 + javascript_tag("new_link_action()")
32 end %> 49 end %>
app/views/box_organizer/edit.html.erb
@@ -7,13 +7,14 @@ @@ -7,13 +7,14 @@
7 7
8 <%= render :partial => partial_for_class(@block.class) %> 8 <%= render :partial => partial_for_class(@block.class) %>
9 9
10 - <%= labelled_form_field _('Display this block:'), '' %>  
11 - <div style='margin-left: 10px'>  
12 - <% @block.display_options.each do |option| %>  
13 - <%= radio_button(:block, :display, option) %>  
14 - <%= label_tag("block_display_#{option}", _(@block.display_option_label(option))) %>  
15 - <br/>  
16 - <% end %> 10 + <div class="display">
  11 + <%= labelled_form_field _('Display this block:'),
  12 + select_tag('block[display]', options_from_collection_for_select(@block.display_options, :first, :last, @block.display))
  13 + %>
  14 + </div>
  15 + <div class="display_user">
  16 + <%= labelled_form_field _('Display to users:'), '' %>
  17 + <%= select_tag('block[display_user]', options_from_collection_for_select(@block.display_user_options, :first, :last, @block.display_user)) %>
17 </div> 18 </div>
18 19
19 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %> 20 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %>
app/views/content_viewer/_addthis.rhtml 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +<div id="addThis">
  2 + <script type="text/javascript">
  3 + addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>';
  4 + addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>';
  5 + addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>';
  6 + </script>
  7 + <a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a>
  8 +</div>
app/views/content_viewer/_article_toolbar.html.erb
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 <%= expirable_button @page, :spread, content, url if url %> 26 <%= expirable_button @page, :spread, content, url if url %>
27 <% end %> 27 <% end %>
28 28
29 - <% if !@page.gallery? && @page.allow_create?(user) %> 29 + <% if !@page.gallery? && (@page.allow_create?(user) || (@page.parent && @page.parent.allow_create?(user))) %>
30 <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %> 30 <% if @page.translatable? && !@page.native_translation.language.blank? && !remove_content_button(:locale) %>
31 <% content = _('Add translation') %> 31 <% content = _('Add translation') %>
32 <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %> 32 <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %>
app/views/content_viewer/view_page.html.erb
@@ -43,21 +43,7 @@ @@ -43,21 +43,7 @@
43 <%= render :partial => 'shared/disabled_enterprise' %> 43 <%= render :partial => 'shared/disabled_enterprise' %>
44 44
45 <% if NOOSFERO_CONF['addthis_enabled'] %> 45 <% if NOOSFERO_CONF['addthis_enabled'] %>
46 -<div id="addThis">  
47 -<script type="text/javascript">  
48 - addthis_pub = '<%= escape_javascript( NOOSFERO_CONF['addthis_pub'] ) %>';  
49 - addthis_logo = '<%= escape_javascript( NOOSFERO_CONF['addthis_logo'] ) %>';  
50 - addthis_config = {  
51 - services_custom: {  
52 - name: 'Facebook',  
53 - url: '<%= addthis_facebook_url(@page) %>',  
54 - icon: 'http://cache.addthiscdn.com/icons/v1/thumbs/facebook.gif'  
55 - }  
56 - };  
57 - addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>';  
58 -</script>  
59 -<a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a>  
60 -</div> 46 + <%= render :partial => 'addthis' %>
61 <% end %> 47 <% end %>
62 48
63 <% cache(@page.cache_key(params, user, language)) do %> 49 <% cache(@page.cache_key(params, user, language)) do %>
@@ -84,6 +70,8 @@ @@ -84,6 +70,8 @@
84 70
85 <%= display_source_info(@page) %> 71 <%= display_source_info(@page) %>
86 72
  73 +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %>
  74 +
87 <div class="comments" id="comments_list"> 75 <div class="comments" id="comments_list">
88 76
89 <% if @page.accept_comments? || @comments_count > 0 %> 77 <% if @page.accept_comments? || @comments_count > 0 %>
@@ -92,8 +80,26 @@ @@ -92,8 +80,26 @@
92 </h3> 80 </h3>
93 <% end %> 81 <% end %>
94 82
95 - <% if @page.accept_comments? && @comments.count > 1 %> 83 + <% if @page.accept_comments? && @comments_count > 1 %>
96 <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") %> 84 <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") %>
  85 +
  86 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  87 + <%= javascript_include_tag "comment_order.js" %>
  88 + <div class="comment-order">
  89 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  90 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  91 + <% end %>
  92 + </div>
  93 + <% end %>
  94 +
  95 + <% if @page.accept_comments? and @comments.count > 1 %>
  96 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier)) %>
  97 + <%= javascript_include_tag "comment_order.js" %>
  98 + <div class="comment-order">
  99 + <% form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  100 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  101 + <% end %>
  102 + </div>
97 <% end %> 103 <% end %>
98 104
99 <ul class="article-comments-list"> 105 <ul class="article-comments-list">
app/views/embed/block.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= display_block(@block) %>
app/views/embed/not_found.rhtml 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<div id='not-found'>
  2 + <p>
  3 + <%= _('You may have clicked an expired link or mistyped the address.') %>
  4 + <%= _('If you clicked a link that was in another site, or was given to you by someone else, it would be nice if you tell them that their link is not valid anymore.') %>
  5 + </p>
  6 +</div>
app/views/embed/unavailable.rhtml 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<div id='unavailable'>
  2 + <p><%= _('Embed unavailable.') %></p>
  3 +</div>
app/views/events/_events.html.erb
1 -<%= list_events(@date, @events) %>  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +<%= list_events(@date, @events) %>
  3 +
  4 +<%= pagination_links @events, :param_name => 'page' %>
app/views/features/_manage_community_fields.html.erb
1 -<h2><%= _('Manage community fields') %></h2>  
2 -  
3 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %> 1 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %>
4 2
5 <table id='community_fields_conf'> 3 <table id='community_fields_conf'>
@@ -9,21 +7,37 @@ @@ -9,21 +7,37 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on creation?') %></th> 8 <th><%= _('Display on creation?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="community_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="community_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="community_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @community_fields.each do |field| %> 26 <% @community_fields.each do |field| %>
13 <tr> 27 <tr>
14 <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 28 <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 29
16 <td> 30 <td>
17 <%= hidden_field_tag "community_fields[#{field}][active]", false %> 31 <%= hidden_field_tag "community_fields[#{field}][active]", false %>
18 - <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "$('community_fields[#{field}][required]').disabled=$('community_fields[#{field}][signup]').disabled=!this.checked;" %> 32 + <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "active_action(this, 'community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
19 </td> 33 </td>
20 <td> 34 <td>
21 <%= hidden_field_tag "community_fields[#{field}][required]", false %> 35 <%= hidden_field_tag "community_fields[#{field}][required]", false %>
22 - <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "if(this.checked) $('community_fields[#{field}][signup]').checked = true;" %> 36 + <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "required_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
23 </td> 37 </td>
24 <td> 38 <td>
25 <%= hidden_field_tag "community_fields[#{field}][signup]", false %> 39 <%= hidden_field_tag "community_fields[#{field}][signup]", false %>
26 - <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "if(!this.checked) $('community_fields[#{field}][required]').checked = false;" %> 40 + <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "signup_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
27 </td> 41 </td>
28 42
29 </tr> 43 </tr>
@@ -31,18 +45,18 @@ @@ -31,18 +45,18 @@
31 </table> 45 </table>
32 46
33 <script type='text/javascript'> 47 <script type='text/javascript'>
34 - var trs = $$('#community_fields_conf tr'); 48 + var trs = jQuery('#community_fields_conf tr');
35 var tr, td2; 49 var tr, td2;
36 - for ( var i=0; tr=trs[i]; i++ ) { 50 + for ( var i=2; tr=trs[i]; i++ ) {
37 if ( td2 = tr.getElementsByTagName('td')[1] ) { 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38 - td2.getElementsByTagName('input')[0].onclick(); 52 + td2.getElementsByTagName('input')[1].onclick();
39 } 53 }
40 } 54 }
41 </script> 55 </script>
42 56
43 <div> 57 <div>
44 <% button_bar do %> 58 <% button_bar do %>
45 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %>
46 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 <% end %> 61 <% end %>
48 </div> 62 </div>
app/views/features/_manage_enterprise_fields.html.erb
1 -<h2><%= _('Manage enterprise fields') %></h2>  
2 -  
3 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %> 1 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %>
4 2
5 <table id='enterprise_fields_conf'> 3 <table id='enterprise_fields_conf'>
@@ -9,21 +7,37 @@ @@ -9,21 +7,37 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on registration?') %></th> 8 <th><%= _('Display on registration?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="enterprise_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="enterprise_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="enterprise_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @enterprise_fields.each do |field| %> 26 <% @enterprise_fields.each do |field| %>
13 <tr> 27 <tr>
14 28
15 <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 29 <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
16 <td> 30 <td>
17 <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %> 31 <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %>
18 - <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "$('enterprise_fields[#{field}][required]').disabled=$('enterprise_fields[#{field}][signup]').disabled=!this.checked;" %> 32 + <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "active_action(this, 'enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
19 </td> 33 </td>
20 <td> 34 <td>
21 <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %> 35 <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %>
22 - <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "if(this.checked) $('enterprise_fields[#{field}][signup]').checked = true;" %> 36 + <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "required_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
23 </td> 37 </td>
24 <td> 38 <td>
25 <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %> 39 <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %>
26 - <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "if(!this.checked) $('enterprise_fields[#{field}][required]').checked = false;" %> 40 + <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "signup_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
27 </td> 41 </td>
28 42
29 </tr> 43 </tr>
@@ -31,18 +45,18 @@ @@ -31,18 +45,18 @@
31 </table> 45 </table>
32 46
33 <script type='text/javascript'> 47 <script type='text/javascript'>
34 - var trs = $$('#enterprise_fields_conf tr'); 48 + var trs = jQuery('#enterprise_fields_conf tr');
35 var tr, td2; 49 var tr, td2;
36 - for ( var i=0; tr=trs[i]; i++ ) { 50 + for ( var i=2; tr=trs[i]; i++ ) {
37 if ( td2 = tr.getElementsByTagName('td')[1] ) { 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38 - td2.getElementsByTagName('input')[0].onclick(); 52 + td2.getElementsByTagName('input')[1].onclick();
39 } 53 }
40 } 54 }
41 </script> 55 </script>
42 56
43 <div> 57 <div>
44 <% button_bar do %> 58 <% button_bar do %>
45 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_enterprise_fields") %>
46 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 <% end %> 61 <% end %>
48 </div> 62 </div>
app/views/features/_manage_person_fields.html.erb
1 -<h2><%= _('Manage person fields') %></h2>  
2 -  
3 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %> 1 <%= labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %>
4 2
5 <table id='person_fields_conf'> 3 <table id='person_fields_conf'>
@@ -9,31 +7,48 @@ @@ -9,31 +7,48 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on signup?') %></th> 8 <th><%= _('Display on signup?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="person_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="person_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="person_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @person_fields.each do |field| %> 26 <% @person_fields.each do |field| %>
13 <tr> 27 <tr>
14 <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 28 <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 <td> 29 <td>
16 <%= hidden_field_tag "person_fields[#{field}][active]", false %> 30 <%= hidden_field_tag "person_fields[#{field}][active]", false %>
17 - <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "$('person_fields[#{field}][required]').disabled=$('person_fields[#{field}][signup]').disabled=!this.checked;" %> 31 + <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "active_action(this, 'person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
18 </td> 32 </td>
19 <td> 33 <td>
20 <%= hidden_field_tag "person_fields[#{field}][required]", false %> 34 <%= hidden_field_tag "person_fields[#{field}][required]", false %>
21 - <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "if(this.checked) $('person_fields[#{field}][signup]').checked = true;" %> 35 + <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "required_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
22 </td> 36 </td>
23 <td> 37 <td>
24 <%= hidden_field_tag "person_fields[#{field}][signup]", false %> 38 <%= hidden_field_tag "person_fields[#{field}][signup]", false %>
25 - <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "if(!this.checked) $('person_fields[#{field}][required]').checked = false;" %> 39 + <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "signup_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
26 </td> 40 </td>
27 </tr> 41 </tr>
28 <% end %> 42 <% end %>
29 </table> 43 </table>
30 44
31 <script type='text/javascript'>// <!-- 45 <script type='text/javascript'>// <!--
32 - var trs = $$('#person_fields_conf tr'); 46 + var trs = jQuery('#person_fields_conf tr');
  47 +
33 var tr, td2; 48 var tr, td2;
34 - for ( var i=0; tr=trs[i]; i++ ) { 49 + for ( var i=2; tr=trs[i]; i++ ) {
35 if ( td2 = tr.getElementsByTagName('td')[1] ) { 50 if ( td2 = tr.getElementsByTagName('td')[1] ) {
36 - td2.getElementsByTagName('input')[0].onclick(); 51 + td2.getElementsByTagName('input')[1].onclick();
37 } 52 }
38 } 53 }
39 // --> 54 // -->
@@ -41,7 +56,7 @@ @@ -41,7 +56,7 @@
41 56
42 <div> 57 <div>
43 <% button_bar do %> 58 <% button_bar do %>
44 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_person_fields") %>
45 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
46 <% end %> 61 <% end %>
47 </div> 62 </div>
app/views/features/index.html.erb
@@ -26,9 +26,13 @@ Check all the features you want to enable for your environment, uncheck all the @@ -26,9 +26,13 @@ Check all the features you want to enable for your environment, uncheck all the
26 26
27 <h2><%= _('Configure features') %></h2> 27 <h2><%= _('Configure features') %></h2>
28 28
  29 +<h3><%= _('Page to redirect after signup') %></h3>
  30 + <%= select 'environment', 'redirection_after_signup', Environment.signup_redirection_options.map{|key,value|[value,key]} %>
  31 +<hr/>
29 <h3><%= _('Page to redirect after login') %></h3> 32 <h3><%= _('Page to redirect after login') %></h3>
30 <%= select 'environment', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]} %> 33 <%= select 'environment', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]} %>
31 <hr/> 34 <hr/>
  35 +
32 <h3><%= _('Organization Approval Method') %></h3> 36 <h3><%= _('Organization Approval Method') %></h3>
33 <%= select_organization_approval_method('environment', 'organization_approval_method') %> 37 <%= select_organization_approval_method('environment', 'organization_approval_method') %>
34 <hr/> 38 <hr/>
app/views/features/manage_fields.html.erb
1 -<%= render :partial => 'manage_person_fields' %> 1 +<h1><%= _('Manage fields displayed for profiles') %></h1>
2 2
3 -<% if !environment.enabled?('disable_asset_enterprises') %>  
4 - <%= render :partial => 'manage_enterprise_fields' %> 3 +<% tabs = [] %>
  4 +<% tabs << {:title => _("Person's fields"), :id => 'person-fields',
  5 + :content => (render :partial => 'manage_person_fields')} %>
  6 +<% tabs << {:title => _("Community's fields"), :id => 'community-fields',
  7 + :content => (render :partial => 'manage_community_fields')} %>
  8 +<% unless environment.enabled?('disable_asset_enterprises') %>
  9 + <% tabs << {:title => _("Enterprise's fields"), :id => 'enterprise-fields',
  10 + :content => (render :partial => 'manage_enterprise_fields')} %>
5 <% end %> 11 <% end %>
6 12
7 -<%= render :partial => 'manage_community_fields' %> 13 +<%= render_tabs(tabs) %>
  14 +
  15 +<%= javascript_include_tag "manage-fields.js" %>
app/views/layouts/application-ng.html.erb
@@ -6,6 +6,27 @@ @@ -6,6 +6,27 @@
6 <!--<meta http-equiv="refresh" content="1"/>--> 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 <meta name="description" content="<%= @environment.name %>" /> 8 <meta name="description" content="<%= @environment.name %>" />
  9 +
  10 + <!-- Twitter Card -->
  11 + <meta name="twitter:card" value="summary">
  12 + <meta name="twitter:title" content="<%= h page_title %>">
  13 + <meta name="twitter:description" content="<%= meta_description_tag(@page) %>">
  14 +
  15 + <!-- Open Graph -->
  16 + <meta property="og:type" content="<%= @page ? 'article' : 'website' %>">
  17 + <meta property="og:url" content="<%= @page ? url_for(@page.url) : @environment.top_url %>">
  18 + <meta property="og:title" content="<%= h page_title %>">
  19 + <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>">
  20 + <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>">
  21 +
  22 + <% if @page %>
  23 + <meta property="article:published_time" content="<%= show_date(@page.published_at) %>">
  24 + <% @page.body_images_paths.each do |img| %>
  25 + <meta name="twitter:image" content="<%= img.to_s %>">
  26 + <meta property="og:image" content="<%= img.to_s %>">
  27 + <% end %>
  28 + <% end %>
  29 +
9 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" /> 30 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" />
10 <%= noosfero_javascript %> 31 <%= noosfero_javascript %>
11 <%= noosfero_stylesheets %> 32 <%= noosfero_stylesheets %>
app/views/layouts/embed.rhtml 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>">
  3 + <head>
  4 + <title>Noosfero embed block</title>
  5 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6 + <%= noosfero_stylesheets %>
  7 + <%= noosfero_javascript %>
  8 + </head>
  9 + <body class="<%= h body_classes %>">
  10 + <div id="embed">
  11 + <div id="wrap-1">
  12 + <div id="wrap-2">
  13 + <div id="content">
  14 + <div id="content-inner">
  15 + <div class="boxes" id="boxes">
  16 + <div class="box box-1" id="box-1">
  17 + <div class="blocks">
  18 + <%= yield %>
  19 + </div>
  20 + </div>
  21 + </div>
  22 + </div>
  23 + </div>
  24 + </div>
  25 + </div>
  26 + </div>
  27 +
  28 + <script type="text/javascript">
  29 + jQuery(document).ready(function(){
  30 + jQuery('a').attr('target','_blank');
  31 + });
  32 + </script>
  33 +
  34 + </body>
  35 +</html>
app/views/person_notifier/mailer/_add_member_in_community.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_comment.rhtml 0 → 100644
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +<% Comment %>
  2 +<% Profile %>
  3 +<% Person %>
  4 +
  5 +<table style="background: #f0f0f1;border-bottom: 1px solid #d2d2d2 !important;border-top: 1px solid #fff;margin-bottom: 0;">
  6 +<tr>
  7 + <td>
  8 + <% if comment.author %>
  9 + <%= link_to profile_image(comment.author, :minor),
  10 + comment.author_url,
  11 + :class => 'comment-picture',
  12 + :title => comment.author_name
  13 + %>
  14 + <% end %>
  15 + </td>
  16 + <td>
  17 + <%= comment.author.present? ? link_to(comment.author_name, comment.author.url, :style => "font-size: 12px; color: #333; font-weight: bold; text-decoration: none;") : content_tag('strong', comment.author_name) %>
  18 + <% unless comment.title.blank? %>
  19 + <span style="font-size: 12px;"><%= comment.title %></span><br/>
  20 + <% end %>
  21 + <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
  22 + <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span>
  23 + <br style="clear: both;" />
  24 +
  25 + <% unless comment.replies.blank? %>
  26 + <ul class="comment-replies">
  27 + <% comment.replies.each do |reply| %>
  28 + <%= render :partial => 'comment', :locals => { :comment => reply } %>
  29 + <% end %>
  30 + </ul>
  31 + <% end %>
  32 + </td>
  33 +</table>
app/views/person_notifier/mailer/_create_article.rhtml 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
  9 + <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
  10 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  11 + </p>
  12 + <p>
  13 + <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
  14 + <br/>
  15 + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
  16 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %>
  17 + </p>
  18 + <p><%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %></p>
  19 + </td>
  20 +</tr>
  21 +<tr>
  22 + <td></td>
  23 + <td>
  24 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  25 + </td>
  26 +</tr>
  27 +</table>
app/views/person_notifier/mailer/_default_activity.rhtml 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +<tr>
  14 + <td></td>
  15 + <td>
  16 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  17 + </td>
  18 +</tr>
  19 +</table>
app/views/person_notifier/mailer/_join_community.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_leave_scrap.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_leave_scrap_to_self.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/person_notifier/mailer/_new_friendship.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_profile_comments.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<% if activity.comments_count > 2 %>
  2 + <div style="font-size: 10px;">
  3 + <% if activity.params['url'].blank? %>
  4 + <%= _("%s comments") % activity.comments_count %>
  5 + <% else %>
  6 + <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %>
  7 + <% end %>
  8 + </div>
  9 +<% else %>
  10 + <ul>
  11 + <%= render :partial => 'comment', :collection => activity.comments %>
  12 + </ul>
  13 +<% end %>
app/views/person_notifier/mailer/_reply_scrap_on_self.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_leave_scrap.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/person_notifier/mailer/_upload_image.rhtml 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +<table>
  2 + <tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +</table>
  14 +<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
  15 +<br/>
app/views/person_notifier/mailer/content_summary.rhtml 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +<h3><%= _("%s's network activity") % @profile.name %></h3>
  2 +<br/>
  3 +<div>
  4 +<% @notifications.each do |activity| %>
  5 + <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">
  6 + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
  7 + </div>
  8 +<% end %>
  9 +</div>
  10 +
  11 +<div style="color:#444444;font-size:11px;">
  12 +<p><%= _("Greetings,") %></p>
  13 +<br/>
  14 +<p>--</p>
  15 +<p><%= _('%s team.') % @environment %></p>
  16 +<p><%= url_for @url %></p>
  17 +</div>
  18 +<br/>
app/views/profile_editor/_person.html.erb
@@ -19,3 +19,8 @@ @@ -19,3 +19,8 @@
19 <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %> 19 <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
20 20
21 <%= render :partial => 'person_form', :locals => {:f => f} %> 21 <%= render :partial => 'person_form', :locals => {:f => f} %>
  22 +
  23 + <h2><%= _('Notification options') %></h2>
  24 + <div>
  25 + <%= select_tag 'profile_data[notification_time]', options_for_select([[_('Disabled'), 0], [_('Hourly'), 1], [_('Half Day'), 12], [_('Daily'), 24]], @profile.notification_time) %>
  26 + </div>
app/views/profile_editor/_person_form.html.erb
@@ -19,8 +19,8 @@ @@ -19,8 +19,8 @@
19 <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> 19 <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %>
20 <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %> 20 <%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %>
21 <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> 21 <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %>
22 -<%= optional_field(@person, 'state', f.text_field(:state, :rel => _('State'))) %>  
23 -<%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> 22 +<%= optional_field(@person, 'state', f.text_field(:state, :id => 'state_field', :rel => _('State'))) %>
  23 +<%= optional_field(@person, 'city', f.text_field(:city, :id => 'city_field', :rel => _('City'))) %>
24 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> 24 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %>
25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> 25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> 26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %>
@@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
36 </div> 36 </div>
37 <% end %> 37 <% end %>
38 38
  39 +<%= javascript_include_tag('city_state_validation') %>
39 <script type='text/javascript'> 40 <script type='text/javascript'>
40 function toggle_text_field(id, span_id) { 41 function toggle_text_field(id, span_id) {
41 if ($(id).value == "Others") { 42 if ($(id).value == "Others") {
app/views/shared/_organization_custom_fields.html.erb
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 <%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %> 13 <%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %>
14 <%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %> 14 <%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %>
15 <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> 15 <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %>
16 -<%= optional_field(profile, 'city', f.text_field(:city)) %>  
17 -<%= optional_field(profile, 'state', f.text_field(:state)) %> 16 +<%= optional_field(profile, 'city', f.text_field(:city, :id =>'city_field')) %>
  17 +<%= optional_field(profile, 'state', f.text_field(:state,:id =>'state_field')) %>
18 <%= optional_field(profile, 'country', select_country(_('Country'), object_name, 'country', {:class => 'type-select'})) %> 18 <%= optional_field(profile, 'country', select_country(_('Country'), object_name, 'country', {:class => 'type-select'})) %>
19 <%= optional_field(profile, 'tag_list', f.text_field(:tag_list)) %> 19 <%= optional_field(profile, 'tag_list', f.text_field(:tag_list)) %>
20 20
@@ -29,3 +29,4 @@ @@ -29,3 +29,4 @@
29 <%= optional_field(profile, 'acronym', f.text_field(:acronym)) %> 29 <%= optional_field(profile, 'acronym', f.text_field(:acronym)) %>
30 <%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %> 30 <%= optional_field(profile, 'foundation_year', f.text_field(:foundation_year)) %>
31 <% end %> 31 <% end %>
  32 +<%= javascript_include_tag('city_state_validation') %>
app/views/shared/_select_categories.html.erb
1 -<div id="category-ajax-selector"> 1 +<% extend CategoriesHelper %>
  2 +
2 <% if !@current_category.nil? %> 3 <% if !@current_category.nil? %>
3 - <h3 class="box-title"><%= _('Current category:') %></h3>  
4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %> 4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %>
  5 + <%= hidden_field_tag "#{object_name}[category_ids][]", @current_category.id if multiple %>
  6 + <%= button_to_remote_without_text(:back, _('Back'),
  7 + { :update => "select-categories",
  8 + :url => { :action => 'update_categories', :id => @object },
  9 + :loaded => visual_effect(:highlight, "select-categories")
  10 + },
  11 + :id => 'cancel-category-button') %>
5 <% 12 <%
6 categories = [@current_category] 13 categories = [@current_category]
7 categories.push(@current_category) while @current_category = @current_category.parent 14 categories.push(@current_category) while @current_category = @current_category.parent
8 %> 15 %>
9 <%= categories.compact.reverse.map{|i| 16 <%= categories.compact.reverse.map{|i|
10 - link_to_remote(i.name, 17 + link_to_remote(i.name,
11 :update => "select-categories", 18 :update => "select-categories",
12 :url => { :action => 'update_categories', :category_id => i.id, :id => @object }, 19 :url => { :action => 'update_categories', :category_id => i.id, :id => @object },
13 :loaded => visual_effect(:highlight, "select-categories"), 20 :loaded => visual_effect(:highlight, "select-categories"),
14 :class => 'select-current-category-link')}.join(' &rarr; ') 21 :class => 'select-current-category-link')}.join(' &rarr; ')
15 %> 22 %>
16 - <strong>  
17 - <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page|  
18 - page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name + 23 + <%= button_to_function_without_text(:add, _('Add'), nil, :id => 'save-category-button') do |page|
  24 + page.insert_html :bottom, 'selected-categories', content_tag('div',
19 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) + 25 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) +
20 - button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{categories.first.id}-button") {|page| page["selected-category-#{categories.first.id}"].remove}, :id => "selected-category-#{categories.first.id}") 26 + selected_category_link(categories.first), :id => "selected-category-#{categories.first.id}")
  27 + page.replace_html 'select-categories', :partial => 'shared/select_subcategories',
  28 + :locals => {:object_name => object_name, :categories => @toplevel_categories}
21 end if multiple %> 29 end if multiple %>
22 - <%= button_to_remote_without_text(:cancel, _('Cancel'),  
23 - { :update => "select-categories",  
24 - :url => { :action => 'update_categories', :id => @object },  
25 - :loaded => visual_effect(:highlight, "select-categories")  
26 - },  
27 - :id => 'cancel-category-button') %>  
28 - </strong>  
29 -<% else %>  
30 - <h3 class="box-title"><%= _('Select a category:') %></h3>  
31 <% end %> 30 <% end %>
32 31
33 -<% if !@categories.empty? %>  
34 - <h3><%= _('Categories:') %></h3>  
35 - <% @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)}.each do |category| %>  
36 - <%= link_to_remote category.name,  
37 - { :update => "select-categories",  
38 - :url => { :action => "update_categories", :category_id => category.id, :id => @object},  
39 - :loaded => visual_effect(:highlight, "select-categories")  
40 - },  
41 - :class => 'select-subcategory-link',  
42 - :id => "select-category-#{category.id}-link"  
43 - %>  
44 - <% end %> &nbsp;  
45 -<% end %> 32 +<div class="toplevel-categories">
  33 + <%= render :partial => 'shared/select_subcategories', :locals => {:object_name => object_name, :categories => @categories} %>
46 </div> 34 </div>
app/views/shared/_select_categories_top.rhtml 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +<% categories_selected ||= nil %>
  2 +<% title ||= nil %>
  3 +
  4 +<% extend CategoriesHelper %>
  5 +
  6 +<%= content_tag "h#{title_size}", title, :class => "box-title" %>
  7 +
  8 +<%= hidden_field_tag "#{object_name}[category_ids][]", nil %>
  9 +
  10 +<div id="category-ajax-selector">
  11 +<% unless categories_selected.nil? %>
  12 +<div id="selected-categories">
  13 + <div class="label"><%= _('Selected categories:') %></div>
  14 + <% categories_selected.each do |cat| %>
  15 + <div id="selected-category-<%= cat.id %>">
  16 + <%= hidden_field_tag("#{object_name}[category_ids][]", cat.id) %>
  17 + <%= selected_category_link(cat) %>
  18 + </div>
  19 + <% end %>
  20 +</div>
  21 +<% end %>
  22 +<div id="select-categories">
  23 + <%= render :partial => 'shared/select_categories', :locals => {:object_name => object_name, :multiple => true, :categories_selected => categories_selected }, :layout => false %>
  24 +</div>
  25 +
  26 +</div>
app/views/shared/_select_subcategories.rhtml 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<% if !categories.nil? && !categories.empty? && !@object.nil? %>
  2 + <hr>
  3 + <div class="category-helper-label"><%= _('Click to select a category') %></div>
  4 +
  5 + <% categories.select{|i| @object.accept_category?(i)}.each do |category| %>
  6 +
  7 + <%= link_to_remote category.name,
  8 + { :update => "select-categories",
  9 + :url => { :action => "update_categories", :category_id => category.id, :id => @object},
  10 + :loaded => visual_effect(:highlight, "select-categories")
  11 + },
  12 + :class => 'select-subcategory-link',
  13 + :id => "select-category-#{category.id}-link"
  14 + %>
  15 + <% end %>
  16 +<% end %>
app/views/shared/block.html.erb
1 <% if block.cacheable? && use_cache %> 1 <% if block.cacheable? && use_cache %>
2 - <% cache_timeout(block.cache_key(language), block.timeout) do %> 2 + <% cache_timeout(block.cache_key(language, user), block.timeout) do %>
3 <%= display_block_content(block, user, main_content) %> 3 <%= display_block_content(block, user, main_content) %>
4 <% end %> 4 <% end %>
5 <% else %> 5 <% else %>
app/views/themes/_select_template.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 "/designs/templates/#{template.id}/thumbnail.png", 12 "/designs/templates/#{template.id}/thumbnail.png",
13 :alt => _('The "%s" template')) + 13 :alt => _('The "%s" template')) +
14 '<div class="opt-info">'.html_safe + 14 '<div class="opt-info">'.html_safe +
15 - content_tag('strong', template.name, :class => 'name') + 15 + content_tag('strong', template.name, :title => template.title, :class => 'name') +
16 ' <br/> '.html_safe 16 ' <br/> '.html_safe
17 17
18 if @current_template == template.id # selected 18 if @current_template == template.id # selected
app/views/user/mailer/activation_code.html.erb
1 <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %> 1 <%= _('Hi, %{recipient}!') % { :recipient => @recipient } %>
2 2
3 -<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment, :activation_url => @url + url_for(:controller => :account, :action => :activate, :activation_code => @activation_code) }) %> 3 +<%= word_wrap(_('Welcome to %{environment}! To activate your account, follow the link: %{activation_url}') % { :environment => @environment, :activation_url => @url + url_for(:controller => :account, :action => :activate, :activation_code => @activation_code, :redirection => @redirection) }) %>
4 4
5 <%= _("Greetings,") %> 5 <%= _("Greetings,") %>
6 6
app/views/users/_users_list.html.erb
1 <div class="environment-users-results-header"> 1 <div class="environment-users-results-header">
2 - <div id='environment-users-filter-title'><%= users_filter_title(@filter) %></div> 2 + <div id='environment-users-filter-title'><%= filter_title(@filter) %></div>
3 <%= filter_selector(@filter) %> 3 <%= filter_selector(@filter) %>
4 <div style="clear: both"></div> 4 <div style="clear: both"></div>
5 </div> 5 </div>
@@ -19,16 +19,17 @@ @@ -19,16 +19,17 @@
19 <td class='actions'> 19 <td class='actions'>
20 <div class="members-buttons-cell"> 20 <div class="members-buttons-cell">
21 <% if p.is_admin? %> 21 <% if p.is_admin? %>
22 - <%= button_without_text :'reset-admin-role', _('Reset admin role'), :action => 'reset_admin_role', :id => p, :q => @q, :filter => @filter %> 22 + <%= button_without_text :'reset-admin-role', _('Reset admin role'), {:action => 'reset_admin_role', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to reset this user as administrator?") %>
23 <% else %> 23 <% else %>
24 - <%= button_without_text :'set-admin-role', _('Set admin role'), :action => 'set_admin_role', :id => p, :q => @q, :filter => @filter %> 24 + <%= button_without_text :'set-admin-role', _('Set admin role'), {:action => 'set_admin_role', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to set this user as administrator?") %>
25 <% end %> 25 <% end %>
26 <% if !p.user.activated? %> 26 <% if !p.user.activated? %>
27 - <%= button_without_text :'activate-user', _('Activate user'), :action => 'activate', :id => p, :q => @q, :filter => @filter %> 27 + <%= button_without_text :'activate-user', _('Activate user'), {:action => 'activate', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to activate this user?") %>
28 <% else %> 28 <% else %>
29 - <%= button_without_text :'deactivate-user', _('Deactivate user'), :action => 'deactivate', :id => p, :q => @q, :filter => @filter %> 29 + <%= button_without_text :'deactivate-user', _('Deactivate user'), {:action => 'deactivate', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to deactivate this user?") %>
30 <% end %> 30 <% end %>
31 - </div> 31 + <%= button_without_text :'delete', _('Remove'), {:action => :destroy_user, :id => p, :q => @q}, :method => :post, :filter => @filter, :confirm => _("Do you want to remove this user?") %>
  32 + </div>
32 </td> 33 </td>
33 </tr> 34 </tr>
34 <% end %> 35 <% end %>
config/initializers/activities_counter_cache.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +if Delayed::Backend::ActiveRecord::Job.table_exists?
  2 + job = Delayed::Backend::ActiveRecord::Job.all :conditions => ['handler LIKE ?', "%ActivitiesCounterCacheJob%"]
  3 + if job.blank?
  4 + Delayed::Backend::ActiveRecord::Job.enqueue(ActivitiesCounterCacheJob.new, -3)
  5 + end
  6 +end
config/initializers/delayed_job_config.rb
1 require 'delayed_job' 1 require 'delayed_job'
2 Delayed::Worker.backend = :active_record 2 Delayed::Worker.backend = :active_record
3 Delayed::Worker.max_attempts = 2 3 Delayed::Worker.max_attempts = 2
4 -Delayed::Worker.max_run_time = 10.minutes 4 +
  5 +# TODO This is consuming ton of space on development with a postgres connection
  6 +# error on the jobs. This must be verified before going into production.
  7 +# Logging jobs backtraces
  8 +#class Delayed::Worker
  9 +# def handle_failed_job_with_loggin(job, error)
  10 +# handle_failed_job_without_loggin(job,error)
  11 +# Delayed::Worker.logger.error(error.message)
  12 +# Delayed::Worker.logger.error(error.backtrace.join("\n"))
  13 +# end
  14 +# alias_method_chain :handle_failed_job, :loggin
  15 +#end
config/initializers/noosfero_extensions.rb 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +require 'noosfero/role_assignment_ext'
  2 +require 'noosfero/action_tracker_ext'
config/initializers/person_notification.rb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +if Delayed::Backend::ActiveRecord::Job.table_exists?
  2 + PersonNotifier.schedule_all_next_notification_mail
  3 +end
config/routes.rb
@@ -31,6 +31,9 @@ Noosfero::Application.routes.draw do @@ -31,6 +31,9 @@ Noosfero::Application.routes.draw do
31 match 'thumbnails(/*stuff)' => 'not_found#nothing' 31 match 'thumbnails(/*stuff)' => 'not_found#nothing'
32 match 'user_themes(/*stuff)' => 'not_found#nothing' 32 match 'user_themes(/*stuff)' => 'not_found#nothing'
33 33
  34 + # embed controller
  35 + map.embed 'embed/:action/:id', :controller => 'embed', :id => /\d+/
  36 +
34 # online documentation 37 # online documentation
35 match 'doc' => 'doc#index', :as => :doc 38 match 'doc' => 'doc#index', :as => :doc
36 match 'doc/:section' => 'doc#section', :as => :doc_section 39 match 'doc/:section' => 'doc#section', :as => :doc_section
db/migrate/20140205191914_add_redirection_after_signup_to_environment.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddRedirectionAfterSignupToEnvironment < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :environments, :redirection_after_signup, :string, :default => 'keep_on_same_page'
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :environments, :redirection_after_signup
  8 + end
  9 +end
db/migrate/20140221142304_move_title_virtual_field_to_name_in_uploaded_file.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class MoveTitleVirtualFieldToNameInUploadedFile < ActiveRecord::Migration
  2 + def self.up
  3 + UploadedFile.find_each do |uploaded_file|
  4 + uploaded_file.name = uploaded_file.setting.delete :title
  5 + uploaded_file.send :update_without_callbacks
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + say "this migration can't be reverted"
  11 + end
  12 +end
db/migrate/20140303173209_move_contact_email_to_noreply_email_at_environment.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class MoveContactEmailToNoreplyEmailAtEnvironment < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :environments, :noreply_email, :string
  4 + Environment.reset_column_information
  5 +
  6 + Environment.find_each do |environment|
  7 + environment.noreply_email = environment.contact_email
  8 + environment.contact_email = nil
  9 + environment.save!
  10 + end
  11 + end
  12 +
  13 + def self.down
  14 + say "this migration can't be reverted"
  15 + end
  16 +end
db/migrate/20140312132212_add_indexes_for_article_search.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class AddIndexesForArticleSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :articles, :created_at
  4 + add_index :articles, :hits
  5 + add_index :articles, :comments_count
  6 + end
  7 +
  8 + def self.down
  9 + remove_index :articles, :created_at
  10 + remove_index :articles, :hits
  11 + remove_index :articles, :comments_count
  12 + end
  13 +end
db/migrate/20140312134218_add_indexes_for_profile_search.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddIndexesForProfileSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :profiles, :created_at
  4 + end
  5 +
  6 + def self.down
  7 + remove_index :profiles, :created_at
  8 + end
  9 +end
db/migrate/20140312141805_create_cache_counts_for_profiles.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class CreateCacheCountsForProfiles < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :profiles, :friends_count, :integer, :null => false, :default => 0
  4 + add_column :profiles, :members_count, :integer, :null => false, :default => 0
  5 + add_column :profiles, :activities_count, :integer, :null => false, :default => 0
  6 + add_index :profiles, :friends_count
  7 + add_index :profiles, :members_count
  8 + add_index :profiles, :activities_count
  9 + end
  10 +
  11 + def self.down
  12 + remove_column :profiles, :friends_count
  13 + remove_column :profiles, :members_count
  14 + remove_column :profiles, :activities_count
  15 + remove_index :profiles, :friends_count
  16 + remove_index :profiles, :members_count
  17 + remove_index :profiles, :activities_count
  18 + end
  19 +end
db/migrate/20140312144156_define_initial_value_for_profiles_friends_count.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class DefineInitialValueForProfilesFriendsCount < ActiveRecord::Migration
  2 + def self.up
  3 + friends_counts = execute("SELECT profiles.id, count(profiles.id) FROM profiles INNER JOIN friendships ON ( profiles.id = friendships.friend_id AND profiles.type = E'Person') GROUP BY profiles.id;")
  4 + friends_counts.each do |count|
  5 + execute("UPDATE profiles SET friends_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + execute("UPDATE profiles SET friends_count=0;")
  11 + end
  12 +end
db/migrate/20140312151857_define_initial_value_for_profiles_activities_count.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class DefineInitialValueForProfilesActivitiesCount < ActiveRecord::Migration
  2 + def self.up
  3 + person_activities_counts = execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= '#{30.days.ago.to_s(:db)}') AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")
  4 + organization_activities_counts = execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= '#{30.days.ago.to_s(:db)}') AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")
  5 + activities_counts = person_activities_counts.entries + organization_activities_counts.entries
  6 + activities_counts.each do |count|
  7 + execute("UPDATE profiles SET activities_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + execute("UPDATE profiles SET activities_count=0;")
  13 + end
  14 +end
db/migrate/20140312184749_add_return_to_to_users.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddReturnToToUsers < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :users, :return_to, :string
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :users, :return_to, :string
  8 + end
  9 +end
db/migrate/20140313213142_define_initial_value_for_profiles_members_count.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class DefineInitialValueForProfilesMembersCount < ActiveRecord::Migration
  2 + def self.up
  3 + members_counts = execute("SELECT profiles.id, count(profiles.id) FROM profiles LEFT OUTER JOIN role_assignments ON profiles.id = role_assignments.resource_id WHERE (profiles.type = 'Organization' OR profiles.type = 'Community' OR profiles.type = 'Enterprise') GROUP BY profiles.id;")
  4 + members_counts.each do |count|
  5 + execute("UPDATE profiles SET members_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + execute("UPDATE profiles SET members_count=0;")
  11 + end
  12 +end
db/migrate/20140314200103_add_indexes_for_products_search.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddIndexesForProductsSearch < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :products, :created_at
  4 + end
  5 +
  6 + def self.down
  7 + remove_index :products, :created_at
  8 + end
  9 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20140115190132) do 14 +ActiveRecord::Schema.define(:version => 20140314200103) do
15 15
16 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -142,6 +142,9 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do @@ -142,6 +142,9 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do
142 t.integer "position" 142 t.integer "position"
143 end 143 end
144 144
  145 + add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
  146 + add_index "articles", ["created_at"], :name => "index_articles_on_created_at"
  147 + add_index "articles", ["hits"], :name => "index_articles_on_hits"
145 add_index "articles", ["name"], :name => "index_articles_on_name" 148 add_index "articles", ["name"], :name => "index_articles_on_name"
146 add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id" 149 add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id"
147 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id" 150 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id"
@@ -285,6 +288,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do @@ -285,6 +288,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do
285 t.text "signup_welcome_text" 288 t.text "signup_welcome_text"
286 t.string "languages" 289 t.string "languages"
287 t.string "default_language" 290 t.string "default_language"
  291 + t.string "redirection_after_signup", :default => "keep_on_same_page"
  292 + t.string "noreply_email"
288 end 293 end
289 294
290 create_table "external_feeds", :force => true do |t| 295 create_table "external_feeds", :force => true do |t|
@@ -435,6 +440,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do @@ -435,6 +440,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do
435 t.boolean "archived", :default => false 440 t.boolean "archived", :default => false
436 end 441 end
437 442
  443 + add_index "products", ["created_at"], :name => "index_products_on_created_at"
438 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id" 444 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id"
439 add_index "products", ["profile_id"], :name => "index_products_on_profile_id" 445 add_index "products", ["profile_id"], :name => "index_products_on_profile_id"
440 446
@@ -473,10 +479,17 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do @@ -473,10 +479,17 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do
473 t.string "redirection_after_login" 479 t.string "redirection_after_login"
474 t.string "personal_website" 480 t.string "personal_website"
475 t.string "jabber_id" 481 t.string "jabber_id"
  482 + t.integer "friends_count", :default => 0, :null => false
  483 + t.integer "members_count", :default => 0, :null => false
  484 + t.integer "activities_count", :default => 0, :null => false
476 end 485 end
477 486
  487 + add_index "profiles", ["activities_count"], :name => "index_profiles_on_activities_count"
  488 + add_index "profiles", ["created_at"], :name => "index_profiles_on_created_at"
478 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" 489 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id"
  490 + add_index "profiles", ["friends_count"], :name => "index_profiles_on_friends_count"
479 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier" 491 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
  492 + add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
480 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id" 493 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
481 494
482 create_table "qualifier_certifiers", :force => true do |t| 495 create_table "qualifier_certifiers", :force => true do |t|
@@ -627,6 +640,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do @@ -627,6 +640,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140115190132) do
627 t.datetime "chat_status_at" 640 t.datetime "chat_status_at"
628 t.string "activation_code", :limit => 40 641 t.string "activation_code", :limit => 40
629 t.datetime "activated_at" 642 t.datetime "activated_at"
  643 + t.string "return_to"
630 end 644 end
631 645
632 create_table "validation_infos", :force => true do |t| 646 create_table "validation_infos", :force => true do |t|
debian/changelog
  1 +noosfero (0.47.0~rc1) squeeze-test; urgency=low
  2 +
  3 + * New features Release Candidate 1
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Thu, 20 Mar 2014 20:26:45 +0000
  6 +
  7 +noosfero (0.46.2) unstable; urgency=low
  8 +
  9 + * Bugfix release
  10 +
  11 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 19 Mar 2014 23:41:06 +0000
  12 +
1 noosfero (0.46.1) unstable; urgency=low 13 noosfero (0.46.1) unstable; urgency=low
2 14
3 * Bugfixes release 15 * Bugfixes release
features/balloon.feature
@@ -8,6 +8,7 @@ Feature: balloon @@ -8,6 +8,7 @@ Feature: balloon
8 And the following communities 8 And the following communities
9 | identifier | name | 9 | identifier | name |
10 | sample | Sample | 10 | sample | Sample |
  11 + And I am logged in as "joaosilva"
11 12
12 @selenium 13 @selenium
13 Scenario: I should not see trigger if not enabled 14 Scenario: I should not see trigger if not enabled
features/categories_block.feature
@@ -24,16 +24,12 @@ Feature: categories_block @@ -24,16 +24,12 @@ Feature: categories_block
24 | owner | type | 24 | owner | type |
25 | environment | CategoriesBlock | 25 | environment | CategoriesBlock |
26 And I am logged in as admin 26 And I am logged in as admin
  27 + And I go to /admin/environment_design
  28 + And display ".button-bar"
27 29
28 - # Note that this @ignore-hidden-elements only works for seeing hidden  
29 - # elements. It actually doesn't work for following hidden link or pressing  
30 - # hidden buttons. That's why it's necessary to use this display hack to show  
31 - # the link.  
32 - @selenium @ignore-hidden-elements 30 + @selenium
33 Scenario: List just product categories 31 Scenario: List just product categories
34 - Given I go to /admin/environment_design  
35 - And display ".categories-block .button-bar"  
36 - And I follow "Edit" within ".categories-block" 32 + Given I follow "Edit" within ".categories-block"
37 And I check "Product" 33 And I check "Product"
38 When I press "Save" 34 When I press "Save"
39 Then I should see "Food" 35 Then I should see "Food"
@@ -42,11 +38,9 @@ Feature: categories_block @@ -42,11 +38,9 @@ Feature: categories_block
42 And "Steak" should not be visible within "span#category-name" 38 And "Steak" should not be visible within "span#category-name"
43 And "Fiction" should not be visible within "span#category-name" 39 And "Fiction" should not be visible within "span#category-name"
44 40
45 - @selenium @ignore-hidden-elements 41 + @selenium
46 Scenario: Show submenu if it exists 42 Scenario: Show submenu if it exists
47 - Given I go to /admin/environment_design  
48 - And display ".categories-block .button-bar"  
49 - And I follow "Edit" within ".categories-block" 43 + Given I follow "Edit" within ".categories-block"
50 And I check "Product" 44 And I check "Product"
51 And I press "Save" 45 And I press "Save"
52 Then I should see "Food" 46 Then I should see "Food"
@@ -61,11 +55,9 @@ Feature: categories_block @@ -61,11 +55,9 @@ Feature: categories_block
61 And I should see "Steak" 55 And I should see "Steak"
62 And I should not see "Fiction" 56 And I should not see "Fiction"
63 57
64 - @selenium @ignore-hidden-elements 58 + @selenium
65 Scenario: Show only one submenu per time 59 Scenario: Show only one submenu per time
66 - Given I go to /admin/environment_design  
67 - And display ".categories-block .button-bar"  
68 - And I follow "Edit" within ".categories-block" 60 + Given I follow "Edit" within ".categories-block"
69 And I check "Product" 61 And I check "Product"
70 And I press "Save" 62 And I press "Save"
71 Then I should see "Book" 63 Then I should see "Book"
@@ -73,20 +65,16 @@ Feature: categories_block @@ -73,20 +65,16 @@ Feature: categories_block
73 When I follow "block_2_category_2" 65 When I follow "block_2_category_2"
74 Then I should see "Literature" 66 Then I should see "Literature"
75 67
76 - @selenium @ignore-hidden-elements 68 + @selenium
77 Scenario: List just general categories 69 Scenario: List just general categories
78 - Given I go to /admin/environment_design  
79 - And display ".categories-block .button-bar"  
80 - And I follow "Edit" within ".categories-block" 70 + Given I follow "Edit" within ".categories-block"
81 And I check "Generic category" 71 And I check "Generic category"
82 When I press "Save" 72 When I press "Save"
83 Then I should see "Wood" 73 Then I should see "Wood"
84 74
85 - @selenium @ignore-hidden-elements 75 + @selenium
86 Scenario: List just regions 76 Scenario: List just regions
87 - Given I go to /admin/environment_design  
88 - And display ".categories-block .button-bar"  
89 - And I follow "Edit" within ".categories-block" 77 + Given I follow "Edit" within ".categories-block"
90 And I check "Region" 78 And I check "Region"
91 When I press "Save" 79 When I press "Save"
92 Then I should see "Bahia" 80 Then I should see "Bahia"
features/comment.feature
@@ -39,7 +39,7 @@ Feature: comment @@ -39,7 +39,7 @@ Feature: comment
39 When I press "Post comment" 39 When I press "Post comment"
40 Then I should see "Hey ho, let's go" 40 Then I should see "Hey ho, let's go"
41 41
42 - @selenium 42 + @selenium-fixme
43 Scenario: redirect to right place after comment a picture 43 Scenario: redirect to right place after comment a picture
44 Given the following files 44 Given the following files
45 | owner | file | mime | 45 | owner | file | mime |
@@ -97,3 +97,41 @@ Feature: comment @@ -97,3 +97,41 @@ Feature: comment
97 Given I am on /booking/article-to-comment 97 Given I am on /booking/article-to-comment
98 And I follow "Post a comment" 98 And I follow "Post a comment"
99 Then "Post a comment" should not be visible within "#article" 99 Then "Post a comment" should not be visible within "#article"
  100 +
  101 + @selenium
  102 + Scenario: the newest post from a forum should be displayed first.
  103 + Given the following users
  104 + | login | name |
  105 + | joaosilva | Joao Silva |
  106 + And the following forums
  107 + | owner | name |
  108 + | joaosilva | Forum |
  109 + And the following articles
  110 + | owner | name | parent |
  111 + | joaosilva | Post one | Forum |
  112 + And the following comments
  113 + | article | author | title | body |
  114 + | Post one | joaosilva | Hi all | Hi all |
  115 + | Post one | joaosilva | Hello | Hello |
  116 + When I go to /joaosilva/forum/post-one
  117 + And I select "Newest first" from "comment_order" within ".comment-order"
  118 + Then I should see "Hello" within ".article-comment"
  119 +
  120 + @selenium
  121 + Scenario: the oldest post from a forum should be displayed first.
  122 + Given the following users
  123 + | login | name |
  124 + | joaosilva | Joao Silva |
  125 + And the following forums
  126 + | owner | name |
  127 + | joaosilva | Forum |
  128 + And the following articles
  129 + | owner | name | parent |
  130 + | joaosilva | Post one | Forum |
  131 + And the following comments
  132 + | article | author | title | body |
  133 + | Post one | joaosilva | Hi all | Hi all |
  134 + | Post one | joaosilva | Hello | Hello |
  135 + When I go to /joaosilva/forum/post-one
  136 + And I select "Oldest first" from "comment_order" within ".comment-order"
  137 + Then I should see "Hi all" within ".article-comment"
features/events.feature
@@ -244,3 +244,38 @@ Feature: events @@ -244,3 +244,38 @@ Feature: events
244 Given I am on /profile/josesilva/events/2009/10 244 Given I am on /profile/josesilva/events/2009/10
245 When I follow "Oktoberfest" 245 When I follow "Oktoberfest"
246 Then I should see "Oktoberfest" 246 Then I should see "Oktoberfest"
  247 +
  248 + Scenario: list events paginated for a specific profile for the month
  249 + Given I am logged in as admin
  250 + And the following users
  251 + | login |
  252 + | josemanuel |
  253 + And I am logged in as "josemanuel"
  254 + And the following events
  255 + | owner | name | start_date |
  256 + | josemanuel | Event 5 | 2009-10-12 |
  257 + | josemanuel | Event 3 | 2009-10-15 |
  258 + | josemanuel | Test Event | 2009-10-15 |
  259 + | josemanuel | Oktoberfest | 2009-10-19 |
  260 + | josemanuel | WikiSym | 2009-10-21 |
  261 + | josemanuel | Free Software | 2009-10-22 |
  262 + | josemanuel | Rachel Birthday | 2009-10-23 |
  263 + | josemanuel | Manuel Birthday | 2009-10-24 |
  264 + | josemanuel | Michelle Birthday | 2009-10-25 |
  265 + | josemanuel | Lecture Allien 10 | 2009-10-26 |
  266 + | josemanuel | Lecture Allien 11 | 2009-10-26 |
  267 + | josemanuel | Lecture Allien 12 | 2009-10-26 |
  268 + | josemanuel | Lecture Allien 13 | 2009-10-26 |
  269 + | josemanuel | Lecture Allien 14 | 2009-10-26 |
  270 + | josemanuel | Lecture Allien 15 | 2009-10-26 |
  271 + | josemanuel | Lecture Allien 16 | 2009-10-26 |
  272 + | josemanuel | Lecture Allien 17 | 2009-10-26 |
  273 + | josemanuel | Lecture Allien 18 | 2009-10-26 |
  274 + | josemanuel | Lecture Allien 19 | 2009-10-26 |
  275 + | josemanuel | Lecture Allien 20 | 2009-10-26 |
  276 + | josemanuel | Party On | 2009-10-27 |
  277 +
  278 + When I am on /profile/josemanuel/events/2009/10
  279 + Then I should not see "Party On" within "#agenda-items"
  280 + When I follow "Next"
  281 + Then I should see "Party On" within "#agenda-items"
features/forum.feature
@@ -166,3 +166,121 @@ Feature: forum @@ -166,3 +166,121 @@ Feature: forum
166 | Post one | joaosilva | Hi all | Hi all | 166 | Post one | joaosilva | Hi all | Hi all |
167 When I go to /joaosilva/forum 167 When I go to /joaosilva/forum
168 Then I should see "Joao" linking to "http://localhost/joaosilva/" 168 Then I should see "Joao" linking to "http://localhost/joaosilva/"
  169 +
  170 + @selenium
  171 + Scenario: community member should be able to see the discussion topic button
  172 + Given the following community
  173 + | identifier | name | owner |
  174 + | sample-community | Sample Community | joaosilva |
  175 + And the following forums
  176 + | owner | name |
  177 + | sample-community | Forum |
  178 + And the following users
  179 + | login | name |
  180 + | mariasilva | Maria Silva|
  181 + And "Maria Silva" is a member of "Sample Community"
  182 + And I am logged in as "joaosilva"
  183 + When I go to /sample-community/forum
  184 + And I follow "Configure forum"
  185 + And I check "Allow member to create topics"
  186 + And I press "Save"
  187 + And I am logged in as "mariasilva"
  188 + And I go to /sample-community/forum
  189 + Then I should see "New discussion topic"
  190 +
  191 + @selenium
  192 + Scenario: a non community member should not be able to see the discussion topic button
  193 + Given the following community
  194 + | identifier | name | owner |
  195 + | sample-community | Sample Community | joaosilva |
  196 + And the following forums
  197 + | owner | name |
  198 + | sample-community | Forum |
  199 + And the following users
  200 + | login | name |
  201 + | mariasilva | Maria Silva|
  202 + And I am logged in as "joaosilva"
  203 + When I go to /sample-community/forum
  204 + And I follow "Configure forum"
  205 + And I check "Allow member to create topics"
  206 + And I press "Save"
  207 + And I am logged in as "mariasilva"
  208 + And I go to /sample-community/forum
  209 + Then I should not see "New discussion topic"
  210 +
  211 + @selenium
  212 + Scenario: community member should not be able to see the discussion topic button
  213 + Given the following community
  214 + | identifier | name | owner |
  215 + | sample-community | Sample Community | joaosilva |
  216 + And the following forums
  217 + | owner | name |
  218 + | sample-community | Forum |
  219 + And the following users
  220 + | login | name |
  221 + | mariasilva | Maria Silva|
  222 + And "Maria Silva" is a member of "Sample Community"
  223 + And I am logged in as "joaosilva"
  224 + When I go to /sample-community/forum
  225 + And I follow "Configure forum"
  226 + And I uncheck "Allow member to create topics"
  227 + And I press "Save"
  228 + And I am logged in as "mariasilva"
  229 + And I go to /sample-community/forum
  230 + Then I should not see "New discussion topic"
  231 +
  232 + @selenium
  233 + Scenario: community member should be able to create a topic with the discussion topic button
  234 + Given the following community
  235 + | identifier | name | owner |
  236 + | sample-community | Sample Community | joaosilva |
  237 + And the following forums
  238 + | owner | name |
  239 + | sample-community | Forum |
  240 + And the following users
  241 + | login | name |
  242 + | mariasilva | Maria Silva|
  243 + And "Maria Silva" is a member of "Sample Community"
  244 + And I am logged in as "joaosilva"
  245 + When I go to /sample-community/forum
  246 + And I follow "Configure forum"
  247 + And I check "Allow member to create topics"
  248 + And I press "Save"
  249 + And I am logged in as "mariasilva"
  250 + And I go to /sample-community/forum
  251 + And I follow "New discussion topic"
  252 + And I follow "Text article with visual editor"
  253 + And I fill in "Title" with "Test"
  254 + And I press "Save"
  255 + Then I should see "Test"
  256 +
  257 + @selenium
  258 + Scenario: community member should be able to create a topic on a topic page
  259 + Given the following community
  260 + | identifier | name | owner |
  261 + | sample-community | Sample Community | joaosilva |
  262 + And the following forums
  263 + | owner | name |
  264 + | sample-community | Forum |
  265 + And the following users
  266 + | login | name |
  267 + | mariasilva | Maria Silva|
  268 + And "Maria Silva" is a member of "Sample Community"
  269 + And I am logged in as "joaosilva"
  270 + When I go to /sample-community/forum
  271 + And I follow "Configure forum"
  272 + And I check "Allow member to create topics"
  273 + And I press "Save"
  274 + And I am logged in as "mariasilva"
  275 + And I go to /sample-community/forum
  276 + And I follow "New discussion topic"
  277 + And I follow "Text article with visual editor"
  278 + And I fill in "Title" with "Test"
  279 + And I press "Save"
  280 + And I go to /sample-community/forum/test
  281 + And I follow "New discussion topic"
  282 + And I follow "Text article with visual editor"
  283 + And I fill in "Title" with "Test inside the topic page"
  284 + And I press "Save"
  285 + And I go to /sample-community/forum
  286 + Then I should see "Test inside the topic page"
169 \ No newline at end of file 287 \ No newline at end of file
features/manage_fields.feature 0 → 100644
@@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
  1 +Feature: check all manage fields
  2 + As an administrator
  3 + I want to check and uncheck all person, enterprise and community's fields
  4 +
  5 + Background:
  6 + Given the following users
  7 + | login | name |
  8 + | mariasilva | Maria Silva |
  9 + And the following enterprises
  10 + | identifier | owner | name | contact_email | contact_phone | enabled |
  11 + | paper-street | mariasilva | Paper Street | marial.silva@workerbees.org | (288) 555-0153 | true |
  12 + And the following community
  13 + | identifier | name |
  14 + | mycommunity | My Community |
  15 + And I am logged in as admin
  16 + And I go to /admin/features/manage_fields
  17 +
  18 + @selenium
  19 + Scenario: check all active person fields
  20 + Given I follow "Person's fields"
  21 + And I check "person_active"
  22 + And I press "save_person_fields"
  23 + When I go to admin_user's control panel
  24 + And I follow "Edit Profile"
  25 + Then I should see "Custom area of study"
  26 +
  27 + @selenium
  28 + Scenario: check all active enterprise fields
  29 + Given I follow "Enterprise's fields"
  30 + And I check "enterprise_active"
  31 + And I press "save_enterprise_fields"
  32 + When I go to paper-street's control panel
  33 + And I follow "Enterprise Info and settings"
  34 + Then I should see "Historic and current context"
  35 +
  36 + @selenium
  37 + Scenario: check all active community fields
  38 + Given I follow "Community's fields"
  39 + And I check "community_active"
  40 + And I press "save_community_fields"
  41 + When I go to mycommunity's control panel
  42 + And I follow "Community Info and settings"
  43 + Then I should see "Economic activity"
  44 +
  45 + @selenium
  46 + Scenario: uncheck Check/Uncheck All active person field
  47 + Given I follow "Person's fields"
  48 + And I check "person_active"
  49 + And I press "save_person_fields"
  50 + And I uncheck "person_active"
  51 + And I press "save_person_fields"
  52 + And I follow "Control panel"
  53 + When I follow "Edit Profile"
  54 + Then I should not see "Custom area of study"
  55 +
  56 + @selenium
  57 + Scenario: uncheck Check/Uncheck All active community field
  58 + Given I follow "Community's fields"
  59 + And I check "community_active"
  60 + And I press "save_community_fields"
  61 + And I uncheck "community_active"
  62 + And I press "save_community_fields"
  63 + When I go to mycommunity's control panel
  64 + And I follow "Community Info and settings"
  65 + Then I should not see "Economic activity"
  66 +
  67 + @selenium
  68 + Scenario: uncheck Check/Uncheck All active enterprise field
  69 + Given I follow "Enterprise's fields"
  70 + And I check "enterprise_active"
  71 + And I press "save_enterprise_fields"
  72 + And I uncheck "enterprise_active"
  73 + And I press "save_enterprise_fields"
  74 + When I go to paper-street's control panel
  75 + And I follow "Enterprise Info and settings"
  76 + Then I should not see "Historic and current context"
features/manage_users.feature 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +Feature: manage users
  2 + As an environment administrator
  3 + I want to manage users
  4 + In order to remove, activate, deactivate users, and set admin roles.
  5 +
  6 +Background:
  7 + Given the following users
  8 + | login | name |
  9 + | joaosilva | Joao Silva |
  10 + | paulosantos | Paulo Santos |
  11 + Given I am logged in as admin
  12 + Given I go to /admin/users
  13 +
  14 + @selenium
  15 + Scenario: deactive user
  16 + When I follow "Deactivate user" within "tr[title='Joao Silva']"
  17 + And I confirm the "Do you want to deactivate this user?" dialog
  18 + Then I should see "Activate user" within "tr[title='Joao Silva']"
  19 +
  20 + @selenium
  21 + Scenario: activate user
  22 + Given I follow "Deactivate user" within "tr[title='Paulo Santos']"
  23 + Given I confirm the "Do you want to deactivate this user?" dialog
  24 + When I follow "Activate user" within "tr[title='Paulo Santos']"
  25 + And I confirm the "Do you want to activate this user?" dialog
  26 + Then I should see "Deactivate user" within "tr[title='Paulo Santos']"
  27 +
  28 + @selenium
  29 + Scenario: remove user
  30 + When I follow "Remove" within "tr[title='Joao Silva']"
  31 + And I confirm the "Do you want to remove this user?" dialog
  32 + And I go to /admin/users
  33 + Then I should not see "Joao Silva"
  34 +
  35 + @selenium
  36 + Scenario: admin user
  37 + When I follow "Set admin role" within "tr[title='Joao Silva']"
  38 + And I confirm the "Do you want to set this user as administrator?" dialog
  39 + Then I should see "Reset admin role" within "tr[title='Joao Silva']"
  40 +
  41 + @selenium
  42 + Scenario: unadmin user
  43 + Given I follow "Set admin role" within "tr[title='Paulo Santos']"
  44 + And I confirm the "Do you want to set this user as administrator?" dialog
  45 + When I follow "Reset admin role" within "tr[title='Paulo Santos']"
  46 + And I confirm the "Do you want to reset this user as administrator?" dialog
  47 + Then I should see "Set admin role" within "tr[title='Paulo Santos']"
features/short_filename.feature
@@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
1 -Feature: sitemap  
2 - As a noosfero user  
3 - I want to list articles  
4 -  
5 - Background:  
6 - Given I am on the homepage  
7 - And the following users  
8 - | login | name |  
9 - | joaosilva | Joao Silva |  
10 - And the following files  
11 - | owner | file | mime |  
12 - | joaosilva | AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_PRETA_BAIXA.txt | text/plain |  
13 -  
14 - Scenario: view a folder page  
15 - When I am on /profile/joaosilva/sitemap  
16 - Then I should see "AGENDA_CULTURA_-_FESTA_DE_VAQUEIRO(...).txt"  
17 -  
18 - Scenario: view the CMS  
19 - Given I am logged in as "joaosilva"  
20 - When I am on /myprofile/joaosilva/cms  
21 - Then I should see "AGENDA_CULTURA_-_FESTA_DE_VAQUEIROS_PONTO_DE_SERRA_(...).txt"  
features/signup.feature
@@ -3,7 +3,7 @@ Feature: signup @@ -3,7 +3,7 @@ Feature: signup
3 I want to sign up to the site 3 I want to sign up to the site
4 So I can have fun using its features 4 So I can have fun using its features
5 5
6 -@selenium 6 + @selenium
7 Scenario: successfull registration 7 Scenario: successfull registration
8 Given I am on the homepage 8 Given I am on the homepage
9 When I follow "Login" 9 When I follow "Login"
@@ -29,10 +29,20 @@ Feature: signup @@ -29,10 +29,20 @@ Feature: signup
29 And I press "Log in" 29 And I press "Log in"
30 Then I should be logged in as "josesilva" 30 Then I should be logged in as "josesilva"
31 31
  32 + @selenium
  33 + Scenario: show error message if username is already used
  34 + Given the following users
  35 + | login |
  36 + | josesilva |
  37 + When I go to signup page
  38 + And I fill in "Username" with "josesilva"
  39 + And I fill in "e-Mail" with "josesilva1"
  40 + Then I should see "This login name is unavailable"
  41 +
32 Scenario: be redirected if user goes to signup page and is logged 42 Scenario: be redirected if user goes to signup page and is logged
33 Given the following users 43 Given the following users
34 | login | name | 44 | login | name |
35 - | joaosilva | Joao Silva | 45 + | joaosilva | joao silva |
36 Given I am logged in as "joaosilva" 46 Given I am logged in as "joaosilva"
37 And I go to signup page 47 And I go to signup page
38 Then I should be on joaosilva's control panel 48 Then I should be on joaosilva's control panel
@@ -60,3 +70,183 @@ Feature: signup @@ -60,3 +70,183 @@ Feature: signup
60 And I fill in "Name" with "" 70 And I fill in "Name" with ""
61 When I press "Save" 71 When I press "Save"
62 Then I should see "Name can't be blank" 72 Then I should see "Name can't be blank"
  73 +
  74 + @selenium
  75 + Scenario: user should stay on same page after signup
  76 + Given the environment is configured to stay on the same page after signup
  77 + And feature "skip_new_user_email_confirmation" is enabled on environment
  78 + And I am on /search/people
  79 + When I follow "Sign up"
  80 + And I fill in the following within ".no-boxes":
  81 + | e-Mail | josesilva@example.com |
  82 + | Username | josesilva |
  83 + | Password | secret |
  84 + | Password confirmation | secret |
  85 + | Full name | José da Silva |
  86 + And wait for the captcha signup time
  87 + And I press "Create my account"
  88 + Then I should be on /search/people
  89 +
  90 + @selenium
  91 + Scenario: user should go to his homepage after signup
  92 + Given the environment is configured to redirect to profile homepage after signup
  93 + And feature "skip_new_user_email_confirmation" is enabled on environment
  94 + And I am on /search/people
  95 + When I follow "Sign up"
  96 + And I fill in the following within ".no-boxes":
  97 + | e-Mail | josesilva@example.com |
  98 + | Username | josesilva |
  99 + | Password | secret |
  100 + | Password confirmation | secret |
  101 + | Full name | José da Silva |
  102 + And wait for the captcha signup time
  103 + And I press "Create my account"
  104 + Then I should be on josesilva's profile
  105 +
  106 + @selenium
  107 + Scenario: user should go to his control panel after signup
  108 + Given the environment is configured to redirect to profile control panel after signup
  109 + And feature "skip_new_user_email_confirmation" is enabled on environment
  110 + And I am on /search/people
  111 + When I follow "Sign up"
  112 + And I fill in the following within ".no-boxes":
  113 + | e-Mail | josesilva@example.com |
  114 + | Username | josesilva |
  115 + | Password | secret |
  116 + | Password confirmation | secret |
  117 + | Full name | José da Silva |
  118 + And wait for the captcha signup time
  119 + And I press "Create my account"
  120 + Then I should be on josesilva's control panel
  121 +
  122 + @selenium
  123 + Scenario: user should go to his profile page after signup
  124 + Given the environment is configured to redirect to user profile page after signup
  125 + And feature "skip_new_user_email_confirmation" is enabled on environment
  126 + And I am on /search/people
  127 + When I follow "Sign up"
  128 + And I fill in the following within ".no-boxes":
  129 + | e-Mail | josesilva@example.com |
  130 + | Username | josesilva |
  131 + | Password | secret |
  132 + | Password confirmation | secret |
  133 + | Full name | José da Silva |
  134 + And wait for the captcha signup time
  135 + And I press "Create my account"
  136 + Then I should be on josesilva's profile
  137 +
  138 + @selenium
  139 + Scenario: user should go to the environment's homepage after signup
  140 + Given the environment is configured to redirect to site homepage after signup
  141 + And feature "skip_new_user_email_confirmation" is enabled on environment
  142 + And I am on /search/people
  143 + When I follow "Sign up"
  144 + And I fill in the following within ".no-boxes":
  145 + | e-Mail | josesilva@example.com |
  146 + | Username | josesilva |
  147 + | Password | secret |
  148 + | Password confirmation | secret |
  149 + | Full name | José da Silva |
  150 + And wait for the captcha signup time
  151 + And I press "Create my account"
  152 + Then I should be on the homepage
  153 +
  154 + @selenium
  155 + Scenario: user should stay on same page after following confirmation link
  156 + Given the environment is configured to stay on the same page after login
  157 + And feature "skip_new_user_email_confirmation" is disabled on environment
  158 + And I am on /search/people
  159 + When I follow "Sign up"
  160 + And I fill in the following within ".no-boxes":
  161 + | e-Mail | josesilva@example.com |
  162 + | Username | josesilva |
  163 + | Password | secret |
  164 + | Password confirmation | secret |
  165 + | Full name | José da Silva |
  166 + And wait for the captcha signup time
  167 + And I press "Create my account"
  168 + And I go to josesilva's confirmation URL
  169 + And I fill in "Username" with "josesilva"
  170 + And I fill in "Password" with "secret"
  171 + And I press "Log in"
  172 + Then I should be on /search/people
  173 +
  174 + @selenium
  175 + Scenario: user should go to his homepage after following confirmation link
  176 + Given the environment is configured to redirect to profile homepage after login
  177 + And feature "skip_new_user_email_confirmation" is disabled on environment
  178 + And I am on /search/people
  179 + When I follow "Sign up"
  180 + And I fill in the following within ".no-boxes":
  181 + | e-Mail | josesilva@example.com |
  182 + | Username | josesilva |
  183 + | Password | secret |
  184 + | Password confirmation | secret |
  185 + | Full name | José da Silva |
  186 + And wait for the captcha signup time
  187 + And I press "Create my account"
  188 + And I go to josesilva's confirmation URL
  189 + And I fill in "Username" with "josesilva"
  190 + And I fill in "Password" with "secret"
  191 + And I press "Log in"
  192 + Then I should be on /profile/josesilva
  193 +
  194 + @selenium
  195 + Scenario: user should go to his control panel after following confirmation link
  196 + Given the environment is configured to redirect to profile control panel after login
  197 + And feature "skip_new_user_email_confirmation" is disabled on environment
  198 + And I am on /search/people
  199 + When I follow "Sign up"
  200 + And I fill in the following within ".no-boxes":
  201 + | e-Mail | josesilva@example.com |
  202 + | Username | josesilva |
  203 + | Password | secret |
  204 + | Password confirmation | secret |
  205 + | Full name | José da Silva |
  206 + And wait for the captcha signup time
  207 + And I press "Create my account"
  208 + And I go to josesilva's confirmation URL
  209 + And I fill in "Username" with "josesilva"
  210 + And I fill in "Password" with "secret"
  211 + And I press "Log in"
  212 + Then I should be on /myprofile/josesilva
  213 +
  214 + @selenium
  215 + Scenario: user should go to his profile page after following confirmation link
  216 + Given the environment is configured to redirect to user profile page after login
  217 + And feature "skip_new_user_email_confirmation" is disabled on environment
  218 + And I am on /search/people
  219 + When I follow "Sign up"
  220 + And I fill in the following within ".no-boxes":
  221 + | e-Mail | josesilva@example.com |
  222 + | Username | josesilva |
  223 + | Password | secret |
  224 + | Password confirmation | secret |
  225 + | Full name | José da Silva |
  226 + And wait for the captcha signup time
  227 + And I press "Create my account"
  228 + And I go to josesilva's confirmation URL
  229 + And I fill in "Username" with "josesilva"
  230 + And I fill in "Password" with "secret"
  231 + And I press "Log in"
  232 + Then I should be on /profile/josesilva
  233 +
  234 + @selenium
  235 + Scenario: user should go to the environment homepage after following confirmation link
  236 + Given the environment is configured to redirect to site homepage after login
  237 + And feature "skip_new_user_email_confirmation" is disabled on environment
  238 + And I am on /search/people
  239 + When I follow "Sign up"
  240 + And I fill in the following within ".no-boxes":
  241 + | e-Mail | josesilva@example.com |
  242 + | Username | josesilva |
  243 + | Password | secret |
  244 + | Password confirmation | secret |
  245 + | Full name | José da Silva |
  246 + And wait for the captcha signup time
  247 + And I press "Create my account"
  248 + And I go to josesilva's confirmation URL
  249 + And I fill in "Username" with "josesilva"
  250 + And I fill in "Password" with "secret"
  251 + And I press "Log in"
  252 + Then I should be on the homepage
features/step_definitions/noosfero_steps.rb
@@ -732,6 +732,24 @@ Given /^the profile (.*) is configured to (.*) after login$/ do |profile, option @@ -732,6 +732,24 @@ Given /^the profile (.*) is configured to (.*) after login$/ do |profile, option
732 profile.save 732 profile.save
733 end 733 end
734 734
  735 +Given /^the environment is configured to (.*) after signup$/ do |option|
  736 + redirection = case option
  737 + when 'stay on the same page'
  738 + 'keep_on_same_page'
  739 + when 'redirect to site homepage'
  740 + 'site_homepage'
  741 + when 'redirect to user profile page'
  742 + 'user_profile_page'
  743 + when 'redirect to profile homepage'
  744 + 'user_homepage'
  745 + when 'redirect to profile control panel'
  746 + 'user_control_panel'
  747 + end
  748 + environment = Environment.default
  749 + environment.redirection_after_signup = redirection
  750 + environment.save
  751 +end
  752 +
735 When /^wait for the captcha signup time$/ do 753 When /^wait for the captcha signup time$/ do
736 environment = Environment.default 754 environment = Environment.default
737 sleep environment.min_signup_delay + 1 755 sleep environment.min_signup_delay + 1
features/support/paths.rb
@@ -111,6 +111,10 @@ module NavigationHelpers @@ -111,6 +111,10 @@ module NavigationHelpers
111 when /the user data path/ 111 when /the user data path/
112 '/account/user_data' 112 '/account/user_data'
113 113
  114 + when /^(.+)'s confirmation URL/
  115 + user = User[$1]
  116 + "/account/activate?activation_code=#{user.activation_code}&redirection=" + (user.return_to.nil? ? 'false' : 'true')
  117 +
114 when /^(.+)'s members page/ 118 when /^(.+)'s members page/
115 '/profile/%s/members' % profile_identifier($1) 119 '/profile/%s/members' % profile_identifier($1)
116 120
lib/activities_counter_cache_job.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class ActivitiesCounterCacheJob
  2 + def perform
  3 + person_activities_counts = ActiveRecord::Base.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= '#{ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db)}') AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")
  4 + organization_activities_counts = ActiveRecord::Base.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= '#{ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db)}') AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")
  5 + activities_counts = person_activities_counts.entries + organization_activities_counts.entries
  6 + activities_counts.each do |count|
  7 + ActiveRecord::Base.connection.execute("UPDATE profiles SET activities_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
  8 + end
  9 + Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, -3, 1.day.from_now)
  10 + end
  11 +end
lib/acts_as_having_settings.rb
@@ -14,6 +14,17 @@ module ActsAsHavingSettings @@ -14,6 +14,17 @@ module ActsAsHavingSettings
14 def #{settings_field} 14 def #{settings_field}
15 self[:#{settings_field}] ||= Hash.new 15 self[:#{settings_field}] ||= Hash.new
16 end 16 end
  17 +
  18 + def setting_changed?(setting_field)
  19 + setting_field = setting_field.to_sym
  20 + changed_settings = self.changes['#{settings_field}']
  21 + return false if changed_settings.nil?
  22 +
  23 + old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field]
  24 + new_setting_value = changed_settings.last[setting_field]
  25 + old_setting_value != new_setting_value
  26 + end
  27 +
17 before_save :symbolize_settings_keys 28 before_save :symbolize_settings_keys
18 private 29 private
19 def symbolize_settings_keys 30 def symbolize_settings_keys
@@ -36,11 +47,9 @@ module ActsAsHavingSettings @@ -36,11 +47,9 @@ module ActsAsHavingSettings
36 val.nil? ? (#{default}.is_a?(String) ? gettext(#{default}) : #{default}) : val 47 val.nil? ? (#{default}.is_a?(String) ? gettext(#{default}) : #{default}) : val
37 end 48 end
38 def #{setting}=(value) 49 def #{setting}=(value)
39 -  
40 - #UPGRADE Leandro: I add this line to save the serialize attribute  
41 - send(self.class.settings_field.to_s + '_will_change!')  
42 -  
43 - send(self.class.settings_field)[:#{setting}] = self.class.acts_as_having_settings_type_cast(value, #{data_type.inspect}) 50 + h = send(self.class.settings_field).clone
  51 + h[:#{setting}] = self.class.acts_as_having_settings_type_cast(value, #{data_type.inspect})
  52 + send(self.class.settings_field.to_s + '=', h)
44 end 53 end
45 CODE 54 CODE
46 end 55 end
lib/feed_handler.rb
@@ -51,7 +51,6 @@ class FeedHandler @@ -51,7 +51,6 @@ class FeedHandler
51 end 51 end
52 52
53 def process(container) 53 def process(container)
54 - Rails.logger.info("Processing %s with id = %d" % [container.class.name, container.id])  
55 begin 54 begin
56 container.class.transaction do 55 container.class.transaction do
57 if container.update_errors > FeedHandler.max_errors && container.fetched_at < (Time.now - FeedHandler.disabled_period) 56 if container.update_errors > FeedHandler.max_errors && container.fetched_at < (Time.now - FeedHandler.disabled_period)
lib/feed_updater.rb
@@ -24,8 +24,8 @@ class FeedUpdater @@ -24,8 +24,8 @@ class FeedUpdater
24 environment = Environment.default 24 environment = Environment.default
25 25
26 recipients NOOSFERO_CONF['exception_recipients'] 26 recipients NOOSFERO_CONF['exception_recipients']
27 - from environment.contact_email  
28 - reply_to environment.contact_email 27 + from environment.noreply_email
  28 + reply_to environment.noreply_email
29 subject "[#{environment.name}] Feed-updater: #{error.message}" 29 subject "[#{environment.name}] Feed-updater: #{error.message}"
30 body render(:text => " 30 body render(:text => "
31 Container: 31 Container:
lib/file_presenter.rb
@@ -13,6 +13,10 @@ class FilePresenter @@ -13,6 +13,10 @@ class FilePresenter
13 klass.accepts?(f) ? klass.new(f) : f 13 klass.accepts?(f) ? klass.new(f) : f
14 end 14 end
15 15
  16 + def self.base_class
  17 + Article
  18 + end
  19 +
16 def initialize(f) 20 def initialize(f)
17 @file = f 21 @file = f
18 end 22 end
@@ -31,6 +35,10 @@ class FilePresenter @@ -31,6 +35,10 @@ class FilePresenter
31 self 35 self
32 end 36 end
33 37
  38 + def kind_of?(klass)
  39 + @file.kind_of?(klass)
  40 + end
  41 +
34 # This method must be overridden in subclasses. 42 # This method must be overridden in subclasses.
35 # 43 #
36 # If the class accepts the file, return a number that represents the 44 # If the class accepts the file, return a number that represents the
@@ -42,8 +50,17 @@ class FilePresenter @@ -42,8 +50,17 @@ class FilePresenter
42 nil 50 nil
43 end 51 end
44 52
  53 + def download?(view=nil)
  54 + false
  55 + end
  56 +
45 def short_description 57 def short_description
46 - _("File (%s)") % content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '') 58 + file_type = if content_type.present?
  59 + content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '')
  60 + else
  61 + _('Unknown')
  62 + end
  63 + _("File (%s)") % file_type
47 end 64 end
48 65
49 # Define the css classes to style the page fragment with the file related 66 # Define the css classes to style the page fragment with the file related
lib/noosfero.rb
@@ -4,7 +4,7 @@ require &#39;fast_gettext&#39; @@ -4,7 +4,7 @@ require &#39;fast_gettext&#39;
4 4
5 module Noosfero 5 module Noosfero
6 PROJECT = 'noosfero' 6 PROJECT = 'noosfero'
7 - VERSION = '0.46.1' 7 + VERSION = '0.47.0~rc1'
8 8
9 def self.pattern_for_controllers_in_directory(dir) 9 def self.pattern_for_controllers_in_directory(dir)
10 disjunction = controllers_in_directory(dir).join('|') 10 disjunction = controllers_in_directory(dir).join('|')
lib/noosfero/action_tracker_ext.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +Rails.configuration.to_prepare do
  2 + ActionTracker::Record.module_eval do
  3 + extend CacheCounterHelper
  4 +
  5 + after_create do |record|
  6 + update_cache_counter(:activities_count, record.user, 1)
  7 + if record.target.kind_of?(Organization)
  8 + update_cache_counter(:activities_count, record.target, 1)
  9 + end
  10 + end
  11 +
  12 + after_destroy do |record|
  13 + if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
  14 + update_cache_counter(:activities_count, record.user, -1)
  15 + if record.target.kind_of?(Organization)
  16 + update_cache_counter(:activities_count, record.target, -1)
  17 + end
  18 + end
  19 + end
  20 + end
  21 +end
lib/noosfero/i18n.rb
@@ -6,9 +6,15 @@ class Object @@ -6,9 +6,15 @@ class Object
6 alias :ngettext :n_ 6 alias :ngettext :n_
7 end 7 end
8 8
  9 +
  10 +custom_locale_dir = Rails.root.join('custom_locales', Rails.env)
  11 +repos = []
  12 +if File.exists?(custom_locale_dir)
  13 + repos << FastGettext::TranslationRepository.build('environment', :type => 'po', :path => custom_locale_dir)
  14 +end
  15 +
9 # translations in place? 16 # translations in place?
10 locale_dir = Rails.root.join('locale') 17 locale_dir = Rails.root.join('locale')
11 -repos = []  
12 if File.exists?(locale_dir) 18 if File.exists?(locale_dir)
13 repos << FastGettext::TranslationRepository.build('noosfero', :type => 'mo', :path => locale_dir) 19 repos << FastGettext::TranslationRepository.build('noosfero', :type => 'mo', :path => locale_dir)
14 repos << FastGettext::TranslationRepository.build('iso_3166', :type => 'mo', :path => locale_dir) 20 repos << FastGettext::TranslationRepository.build('iso_3166', :type => 'mo', :path => locale_dir)
lib/noosfero/plugin.rb
@@ -389,6 +389,12 @@ class Noosfero::Plugin @@ -389,6 +389,12 @@ class Noosfero::Plugin
389 [] 389 []
390 end 390 end
391 391
  392 + # -> Adds adicional content to article
  393 + # returns = lambda block that creates html code
  394 + def article_extra_contents(article)
  395 + nil
  396 + end
  397 +
392 # -> Adds fields to the signup form 398 # -> Adds fields to the signup form
393 # returns = lambda block that creates html code 399 # returns = lambda block that creates html code
394 def signup_extra_contents 400 def signup_extra_contents
lib/noosfero/role_assignment_ext.rb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +Rails.configuration.to_prepare do
  2 + RoleAssignment.module_eval do
  3 + extend CacheCounterHelper
  4 +
  5 + after_create do |role_assignment|
  6 + accessor = role_assignment.accessor
  7 + resource = role_assignment.resource
  8 + if resource.kind_of?(Organization)
  9 + #FIXME This will only work as long as the role_assignment associations
  10 + #happen only between profiles, due to the polymorphic column type.
  11 + if resource.role_assignments.where(:accessor_id => accessor.id).count == 1
  12 + update_cache_counter(:members_count, resource, 1)
  13 + end
  14 + end
  15 + end
  16 +
  17 + after_destroy do |role_assignment|
  18 + accessor = role_assignment.accessor
  19 + resource = role_assignment.resource
  20 + if resource.kind_of?(Organization)
  21 + #FIXME This will only work as long as the role_assignment associations
  22 + #happen only between profiles, due to the polymorphic column type.
  23 + if resource.role_assignments.where(:accessor_id => accessor.id).count == 0
  24 + update_cache_counter(:members_count, resource, -1)
  25 + end
  26 + end
  27 + end
  28 + end
  29 +end
lib/tasks/plugins_tests.rake
@@ -25,51 +25,87 @@ def plugin_disabled_warning(plugin) @@ -25,51 +25,87 @@ def plugin_disabled_warning(plugin)
25 puts "E: you should enable #{plugin} plugin before running it's tests!" 25 puts "E: you should enable #{plugin} plugin before running it's tests!"
26 end 26 end
27 27
28 -def run_tests(name, files_glob)  
29 - files = Dir.glob(files_glob)  
30 - if files.empty?  
31 - puts "I: no tests to run (#{name})" 28 +def task2ext(task)
  29 + (task == :selenium || task == :cucumber) ? :feature : :rb
  30 +end
  31 +
  32 +def task2profile(task, plugin)
  33 + if task == :cucumber
  34 + return plugin
  35 + elsif task == :selenium
  36 + return "#{plugin}_selenium"
32 else 37 else
33 - sh 'testrb', '-Itest', *files 38 + return 'default'
34 end 39 end
35 end 40 end
36 41
37 -def run_cucumber(name, profile, files_glob)  
38 - files = Dir.glob(files_glob)  
39 - if files.empty?  
40 - puts "I: no tests to run #{name}" 42 +def filename2plugin(filename)
  43 + filename.split('/')[1]
  44 +end
  45 +
  46 +def task2folder(task)
  47 + result = case task.to_sym
  48 + when :units
  49 + :unit
  50 + when :functionals
  51 + :functional
  52 + when :integration
  53 + :integration
  54 + when :cucumber
  55 + :features
  56 + when :selenium
  57 + :features
  58 + end
  59 +
  60 + return result
  61 +end
  62 +
  63 +def run_test(name, files)
  64 + files = Array(files)
  65 + plugin = filename2plugin(files.first)
  66 + if name == :cucumber || name == :selenium
  67 + run_cucumber task2_profile(name, plugin), files
41 else 68 else
42 - sh 'xvfb-run', 'ruby', '-S', 'cucumber', '--profile', profile.to_s, '--format', ENV['CUCUMBER_FORMAT'] || 'progress' , *files 69 + run_testrb files
43 end 70 end
44 end 71 end
45 72
46 -def plugin_test_task(name, plugin, files_glob)  
47 - desc "Run #{name} tests for #{plugin_name(plugin)}"  
48 - task name => 'db:test:plugins:prepare' do |t|  
49 - if plugin_enabled?(plugin)  
50 - run_tests t.name, files_glob  
51 - else  
52 - plugin_disabled_warning(plugin) 73 +def run_testrb(files)
  74 + sh 'testrb', '-Itest', *files
  75 +end
  76 +
  77 +def run_cucumber(profile, files)
  78 + sh 'xvfb-run', 'ruby', '-S', 'cucumber', '--profile', profile.to_s, '--format', ENV['CUCUMBER_FORMAT'] || 'progress' , *files
  79 +end
  80 +
  81 +def custom_run(name, files, run=:individually)
  82 + case run
  83 + when :all
  84 + run_test name, files
  85 + when :individually
  86 + files.each do |file|
  87 + run_test name, file
53 end 88 end
  89 + when :by_plugin
54 end 90 end
55 end 91 end
56 92
57 -def plugin_cucumber_task(name, plugin, files_glob)  
58 - desc "Run #{name} tests for #{plugin_name(plugin)}"  
59 - task name => 'db:test:plugins:prepare' do |t|  
60 - if plugin_enabled?(plugin)  
61 - run_cucumber t.name, plugin, files_glob  
62 - else  
63 - plugin_disabled_warning(plugin)  
64 - end 93 +def run_tests(name, plugins, run=:individually)
  94 + plugins = Array(plugins)
  95 + glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}"
  96 + files = Dir.glob(glob)
  97 + if files.empty?
  98 + puts "I: no tests to run #{name}"
  99 + else
  100 + custom_run(name, files, run)
65 end 101 end
66 end 102 end
67 103
68 -def plugin_selenium_task(name, plugin, files_glob) 104 +def plugin_test_task(name, plugin, run=:individually)
69 desc "Run #{name} tests for #{plugin_name(plugin)}" 105 desc "Run #{name} tests for #{plugin_name(plugin)}"
70 task name => 'db:test:plugins:prepare' do |t| 106 task name => 'db:test:plugins:prepare' do |t|
71 if plugin_enabled?(plugin) 107 if plugin_enabled?(plugin)
72 - run_cucumber t.name, "#{plugin}_selenium", files_glob 108 + run_tests(name, plugin, run)
73 else 109 else
74 plugin_disabled_warning(plugin) 110 plugin_disabled_warning(plugin)
75 end 111 end
@@ -98,28 +134,28 @@ namespace :test do @@ -98,28 +134,28 @@ namespace :test do
98 namespace :noosfero_plugins do 134 namespace :noosfero_plugins do
99 all_plugins.each do |plugin| 135 all_plugins.each do |plugin|
100 namespace plugin do 136 namespace plugin do
101 - plugin_test_task :units, plugin, "plugins/#{plugin}/test/unit/**/*.rb"  
102 - plugin_test_task :functionals, plugin, "plugins/#{plugin}/test/functional/**/*.rb"  
103 - plugin_test_task :integration, plugin, "plugins/#{plugin}/test/integration/**/*.rb"  
104 - plugin_cucumber_task :cucumber, plugin, "plugins/#{plugin}/features/**/*.feature"  
105 - plugin_selenium_task :selenium, plugin, "plugins/#{plugin}/features/**/*.feature" 137 + plugin_test_task :units, plugin
  138 + plugin_test_task :functionals, plugin
  139 + plugin_test_task :integration, plugin
  140 + plugin_test_task :cucumber, plugin
  141 + plugin_test_task :selenium, plugin
106 end 142 end
107 143
108 test_sequence_task(plugin, plugin, "#{plugin}:units", "#{plugin}:functionals", "#{plugin}:integration", "#{plugin}:cucumber", "#{plugin}:selenium") 144 test_sequence_task(plugin, plugin, "#{plugin}:units", "#{plugin}:functionals", "#{plugin}:integration", "#{plugin}:cucumber", "#{plugin}:selenium")
109 end 145 end
110 146
111 - { :units => :unit , :functionals => :functional , :integration => :integration }.each do |taskname,folder| 147 + [:units, :functionals, :integration].each do |taskname|
112 task taskname => 'db:test:plugins:prepare' do |t| 148 task taskname => 'db:test:plugins:prepare' do |t|
113 - run_tests t.name, "plugins/{#{enabled_plugins.join(',')}}/test/#{folder}/**/*.rb" 149 + run_tests taskname, enabled_plugins
114 end 150 end
115 end 151 end
116 152
117 task :cucumber => 'db:test:plugins:prepare' do |t| 153 task :cucumber => 'db:test:plugins:prepare' do |t|
118 - run_cucumber t.name, :default, "plugins/{#{enabled_plugins.join(',')}}/test/features/**/*.features" 154 + run_tests :cucumber, enabled_plugins
119 end 155 end
120 156
121 task :selenium => 'db:test:plugins:prepare' do |t| 157 task :selenium => 'db:test:plugins:prepare' do |t|
122 - run_cucumber t.name, :selenium, "plugins/{#{enabled_plugins.join(',')}}/test/features/**/*.features" 158 + run_tests :selenium, enabled_plugins
123 end 159 end
124 160
125 task :temp_enable_all_plugins do 161 task :temp_enable_all_plugins do
lib/tasks/release.rake
@@ -146,8 +146,8 @@ EOF @@ -146,8 +146,8 @@ EOF
146 version_name = new_version = ask(version_question) 146 version_name = new_version = ask(version_question)
147 147
148 if release_kind == 'test' 148 if release_kind == 'test'
149 - timestamp = Time.now.strftime('%Y%m%d%H%M%S')  
150 - version_name += "~rc#{timestamp}" 149 + rc_version = ask('RC version', Time.now.strftime('%Y%m%d%H%M%S'))
  150 + version_name += "~rc#{rc_version}"
151 end 151 end
152 release_message = ask("Release message") 152 release_message = ask("Release message")
153 153
@@ -218,6 +218,9 @@ EOF @@ -218,6 +218,9 @@ EOF
218 task :release, :release_kind do |t, args| 218 task :release, :release_kind do |t, args|
219 release_kind = args[:release_kind] || 'stable' 219 release_kind = args[:release_kind] || 'stable'
220 220
  221 + puts "==> Updating authors..."
  222 + Rake::Task['noosfero:authors'].invoke
  223 +
221 Rake::Task['noosfero:set_version'].invoke(release_kind) 224 Rake::Task['noosfero:set_version'].invoke(release_kind)
222 225
223 puts "==> Checking tags..." 226 puts "==> Checking tags..."
@@ -232,9 +235,6 @@ EOF @@ -232,9 +235,6 @@ EOF
232 commit_changes(['public/500.html', 'public/503.html'], 'Updating public error pages') 235 commit_changes(['public/500.html', 'public/503.html'], 'Updating public error pages')
233 end 236 end
234 237
235 - puts "==> Updating authors..."  
236 - Rake::Task['noosfero:authors'].invoke  
237 -  
238 puts "==> Checking repository..." 238 puts "==> Checking repository..."
239 Rake::Task['noosfero:check_repo'].invoke 239 Rake::Task['noosfero:check_repo'].invoke
240 240
plugins/anti_spam/lib/anti_spam_plugin/wrapper.rb
@@ -2,9 +2,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator @@ -2,9 +2,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator
2 include Rakismet::Model 2 include Rakismet::Model
3 3
4 @@wrappers = [] 4 @@wrappers = []
  5 + cattr_accessor :wrappers
5 6
6 def self.wrap(object) 7 def self.wrap(object)
7 - wrapper = @@wrappers.find { |wrapper| wrapper.wraps?(object) } 8 + wrapper = wrappers.find { |wrapper| wrapper.wraps?(object) }
8 wrapper ? wrapper.new(object) : object 9 wrapper ? wrapper.new(object) : object
9 end 10 end
10 11
@@ -13,6 +14,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator @@ -13,6 +14,10 @@ class AntiSpamPlugin::Wrapper &lt; SimpleDelegator
13 end 14 end
14 15
15 def self.inherited(child) 16 def self.inherited(child)
16 - @@wrappers << child 17 + wrappers << child
17 end 18 end
18 end 19 end
  20 +
  21 +Dir.glob(File.join(AntiSpamPlugin.root_path, 'lib', 'anti_spam_plugin', '*_wrapper.rb')) do |file|
  22 + load(file)
  23 +end
plugins/comment_group/test/functional/comment_group_plugin_profile_controller_test.rb
@@ -36,10 +36,10 @@ class CommentGroupPluginProfileControllerTest &lt; ActionController::TestCase @@ -36,10 +36,10 @@ class CommentGroupPluginProfileControllerTest &lt; ActionController::TestCase
36 end 36 end
37 37
38 should 'show first page comments only' do 38 should 'show first page comments only' do
39 - comment1 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'secondpage', :group_id => 0)  
40 - comment2 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 1', :group_id => 0)  
41 - comment3 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 2', :group_id => 0)  
42 - comment4 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :body => 'firstpage 3', :group_id => 0) 39 + comment1 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now, :body => 'secondpage', :group_id => 0)
  40 + comment2 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 1.day, :body => 'firstpage 1', :group_id => 0)
  41 + comment3 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 2.days, :body => 'firstpage 2', :group_id => 0)
  42 + comment4 = fast_create(Comment, :source_id => article, :author_id => profile, :title => 'a comment', :created_at => Time.now - 3.days, :body => 'firstpage 3', :group_id => 0)
43 xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0 43 xhr :get, :view_comments, :profile => @profile.identifier, :article_id => article.id, :group_id => 0
44 assert_match /firstpage 1/, @response.body 44 assert_match /firstpage 1/, @response.body
45 assert_match /firstpage 2/, @response.body 45 assert_match /firstpage 2/, @response.body
plugins/community_track/lib/community_track_plugin/track_card_list_block.rb
@@ -12,4 +12,8 @@ class CommunityTrackPlugin::TrackCardListBlock &lt; CommunityTrackPlugin::TrackList @@ -12,4 +12,8 @@ class CommunityTrackPlugin::TrackCardListBlock &lt; CommunityTrackPlugin::TrackList
12 'track_card' 12 'track_card'
13 end 13 end
14 14
  15 + def embedable?
  16 + true
  17 + end
  18 +
15 end 19 end
plugins/community_track/test/functional/community_track_plugin_content_viewer_controller_test.rb
@@ -10,7 +10,7 @@ end @@ -10,7 +10,7 @@ end
10 class ContentViewerControllerTest < ActionController::TestCase 10 class ContentViewerControllerTest < ActionController::TestCase
11 11
12 def setup 12 def setup
13 - @profile = fast_create(Community) 13 + @profile = Community.create!(:name => 'Sample community', :identifier => 'sample-community')
14 @track = create_track('track', @profile) 14 @track = create_track('track', @profile)
15 @step = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today, :tool_type => TinyMceArticle.name) 15 @step = CommunityTrackPlugin::Step.create!(:name => 'step1', :body => 'body', :profile => @profile, :parent => @track, :published => false, :end_date => Date.today, :start_date => Date.today, :tool_type => TinyMceArticle.name)
16 16
@@ -87,43 +87,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -87,43 +87,35 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
87 end 87 end
88 88
89 should 'render a div with block id for track list block' do 89 should 'render a div with block id for track list block' do
90 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
91 - @block = create(CommunityTrackPlugin::TrackListBlock, :box => box)  
92 - @profile.boxes << box 90 + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => @profile.boxes.last)
93 get :view_page, @step.url 91 get :view_page, @step.url
94 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" } 92 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" }
95 end 93 end
96 94
97 should 'render a div with block id for track card list block' do 95 should 'render a div with block id for track card list block' do
98 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
99 - @block = create(CommunityTrackPlugin::TrackCardListBlock, :box => box)  
100 - @profile.boxes << box 96 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
101 get :view_page, @step.url 97 get :view_page, @step.url
102 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" } 98 assert_tag :tag => 'div', :attributes => { :class => 'track_list', :id => "track_list_#{@block.id}" }
103 end 99 end
104 100
105 should 'render tracks in track list block' do 101 should 'render tracks in track list block' do
106 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
107 - @block = create(CommunityTrackPlugin::TrackListBlock, :box => box)  
108 - @profile.boxes << box 102 + @block = CommunityTrackPlugin::TrackListBlock.create!(:box => @profile.boxes.last)
109 get :view_page, @step.url 103 get :view_page, @step.url
  104 + file = File.open('result.html', 'w+')
  105 + file.write(@response.body)
  106 + file.close
110 assert_tag :tag => 'div', :attributes => { :class => "item category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'steps' }, :descendant => { :tag => 'span', :attributes => { :class => "step #{@block.status_class(@step)}" } } } 107 assert_tag :tag => 'div', :attributes => { :class => "item category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'steps' }, :descendant => { :tag => 'span', :attributes => { :class => "step #{@block.status_class(@step)}" } } }
111 end 108 end
112 109
113 should 'render tracks in track card list block' do 110 should 'render tracks in track card list block' do
114 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
115 - @block = create(CommunityTrackPlugin::TrackCardListBlock, :box => box)  
116 - @profile.boxes << box 111 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
117 get :view_page, @step.url 112 get :view_page, @step.url
118 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_content' } } 113 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_content' } }
119 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_stats' } } 114 assert_tag :tag => 'div', :attributes => { :class => "item_card category_#{@track.category_name}" }, :descendant => { :tag => 'div', :attributes => { :class => 'track_stats' } }
120 end 115 end
121 116
122 should 'render link to display more tracks in track list block' do 117 should 'render link to display more tracks in track list block' do
123 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
124 - @block = create(CommunityTrackPlugin::TrackCardListBlock, :box => box)  
125 - @profile.boxes << box  
126 - 118 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
127 (@block.limit+1).times { |i| create_track("track#{i}", @profile) } 119 (@block.limit+1).times { |i| create_track("track#{i}", @profile) }
128 120
129 get :view_page, @step.url 121 get :view_page, @step.url
@@ -131,9 +123,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -131,9 +123,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
131 end 123 end
132 124
133 should 'render link to show all tracks in track list block' do 125 should 'render link to show all tracks in track list block' do
134 - box = fast_create(Box, :owner_id => @profile.id, :owner_type => @profile.class.name, :position => 1)  
135 - @block = create(CommunityTrackPlugin::TrackCardListBlock, :box => box)  
136 - @profile.boxes << box 126 + @block = CommunityTrackPlugin::TrackCardListBlock.create!(:box => @profile.boxes.last)
137 @block.more_another_page = true 127 @block.more_another_page = true
138 @block.save! 128 @block.save!
139 129
plugins/context_content/views/blocks/_more.html.erb
1 <% if contents.total_pages > 1 %> 1 <% if contents.total_pages > 1 %>
2 - <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.previous_page, :article_id => article_id }, :html => {:class => "button icon-button icon-left #{contents.previous_page ? '':'disabled'}".strip}, :condition => "#{!contents.previous_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'left'});" )%>  
3 - <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.next_page, :article_id => article_id }, :html => {:class => "button icon-button icon-right #{contents.next_page ? '':'disabled'}".strip}, :condition => "#{!contents.next_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'right'});" )%> 2 + <%= link_to_remote(nil, :url => {:profile => block.owner.identifier, :id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.previous_page, :article_id => article_id }, :html => {:class => "button icon-button icon-left #{contents.previous_page ? '':'disabled'}".strip}, :condition => "#{!contents.previous_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'left'});" )%>
  3 + <%= link_to_remote(nil, :url => {:profile => block.owner.identifier, :id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.next_page, :article_id => article_id }, :html => {:class => "button icon-button icon-right #{contents.next_page ? '':'disabled'}".strip}, :condition => "#{!contents.next_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'right'});" )%>
4 <% end %> 4 <% end %>
plugins/display_content/lib/display_content_block.rb
@@ -63,9 +63,12 @@ class DisplayContentBlock &lt; Block @@ -63,9 +63,12 @@ class DisplayContentBlock &lt; Block
63 63
64 VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum'] 64 VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum']
65 65
  66 + include Noosfero::Plugin::HotSpot
  67 +
66 def articles_of_parent(parent = nil) 68 def articles_of_parent(parent = nil)
67 return [] if self.holder.nil? 69 return [] if self.holder.nil?
68 - holder.articles.find(:all, :conditions => {:type => VALID_CONTENT, :parent_id => (parent.nil? ? nil : parent)}) 70 + types = VALID_CONTENT + plugins.dispatch(:content_types).map(&:name)
  71 + holder.articles.find(:all, :conditions => {:type => types, :parent_id => (parent.nil? ? nil : parent)})
69 end 72 end
70 73
71 def content(args={}) 74 def content(args={})
plugins/display_content/test/unit/display_content_block_test.rb
@@ -238,6 +238,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -238,6 +238,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
238 block.nodes= [a1.id, a2.id, a3.id] 238 block.nodes= [a1.id, a2.id, a3.id]
239 box = mock() 239 box = mock()
240 box.stubs(:owner).returns(profile) 240 box.stubs(:owner).returns(profile)
  241 + box.stubs(:environment).returns(Environment.default)
241 block.stubs(:box).returns(box) 242 block.stubs(:box).returns(box)
242 assert_equal [], [a1, a2] - block.articles_of_parent 243 assert_equal [], [a1, a2] - block.articles_of_parent
243 assert_equal [], block.articles_of_parent - [a1, a2] 244 assert_equal [], block.articles_of_parent - [a1, a2]
@@ -253,6 +254,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -253,6 +254,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
253 block = DisplayContentBlock.new 254 block = DisplayContentBlock.new
254 box = mock() 255 box = mock()
255 box.stubs(:owner).returns(profile) 256 box.stubs(:owner).returns(profile)
  257 + box.stubs(:environment).returns(Environment.default)
256 block.stubs(:box).returns(box) 258 block.stubs(:box).returns(box)
257 assert_equal [], [a3] - block.articles_of_parent(a2) 259 assert_equal [], [a3] - block.articles_of_parent(a2)
258 assert_equal [], block.articles_of_parent(a2) - [a3] 260 assert_equal [], block.articles_of_parent(a2) - [a3]
@@ -270,6 +272,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -270,6 +272,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
270 box = mock() 272 box = mock()
271 block.stubs(:box).returns(box) 273 block.stubs(:box).returns(box)
272 box.stubs(:owner).returns(environment) 274 box.stubs(:owner).returns(environment)
  275 + box.stubs(:environment).returns(Environment.default)
273 environment.stubs(:portal_community).returns(profile) 276 environment.stubs(:portal_community).returns(profile)
274 277
275 assert_equal [], [a1, a2] - block.articles_of_parent 278 assert_equal [], [a1, a2] - block.articles_of_parent
@@ -288,6 +291,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -288,6 +291,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
288 box = mock() 291 box = mock()
289 block.stubs(:box).returns(box) 292 block.stubs(:box).returns(box)
290 box.stubs(:owner).returns(environment) 293 box.stubs(:owner).returns(environment)
  294 + box.stubs(:environment).returns(Environment.default)
291 environment.stubs(:portal_community).returns(profile) 295 environment.stubs(:portal_community).returns(profile)
292 296
293 assert_equal [], [a3] - block.articles_of_parent(a2) 297 assert_equal [], [a3] - block.articles_of_parent(a2)
@@ -301,6 +305,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -301,6 +305,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
301 box = mock() 305 box = mock()
302 block.stubs(:box).returns(box) 306 block.stubs(:box).returns(box)
303 box.stubs(:owner).returns(environment) 307 box.stubs(:owner).returns(environment)
  308 + box.stubs(:environment).returns(Environment.default)
304 309
305 assert_equal [], block.articles_of_parent() 310 assert_equal [], block.articles_of_parent()
306 end 311 end
@@ -316,6 +321,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -316,6 +321,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
316 block = DisplayContentBlock.new 321 block = DisplayContentBlock.new
317 box = mock() 322 box = mock()
318 box.stubs(:owner).returns(profile) 323 box.stubs(:owner).returns(profile)
  324 + box.stubs(:environment).returns(Environment.default)
319 block.stubs(:box).returns(box) 325 block.stubs(:box).returns(box)
320 assert_equal [], [a2] - block.articles_of_parent 326 assert_equal [], [a2] - block.articles_of_parent
321 assert_equal [], block.articles_of_parent - [a2] 327 assert_equal [], block.articles_of_parent - [a2]
@@ -334,6 +340,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -334,6 +340,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
334 block = DisplayContentBlock.new 340 block = DisplayContentBlock.new
335 box = mock() 341 box = mock()
336 box.stubs(:owner).returns(profile) 342 box.stubs(:owner).returns(profile)
  343 + box.stubs(:environment).returns(Environment.default)
337 block.stubs(:box).returns(box) 344 block.stubs(:box).returns(box)
338 assert_equal [a1], block.articles_of_parent 345 assert_equal [a1], block.articles_of_parent
339 end 346 end
@@ -528,4 +535,28 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -528,4 +535,28 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
528 assert_equivalent [f1.id, a1.id, a2.id, a3.id], block.nodes 535 assert_equivalent [f1.id, a1.id, a2.id, a3.id], block.nodes
529 end 536 end
530 537
  538 + should "test should return plugins articles in articles of parent method" do
  539 + class PluginArticle < Article; end
  540 +
  541 + class Plugin1 < Noosfero::Plugin
  542 + def content_types
  543 + [PluginArticle]
  544 + end
  545 + end
  546 +
  547 + profile = create_user('testuser').person
  548 + Article.delete_all
  549 + a1 = fast_create(PluginArticle, :name => 'test article 1', :profile_id => profile.id)
  550 +
  551 + env = fast_create(Environment)
  552 + env.enable_plugin(Plugin1)
  553 +
  554 + block = DisplayContentBlock.new
  555 + box = mock()
  556 + box.stubs(:owner).returns(profile)
  557 + box.stubs(:environment).returns(env)
  558 + block.stubs(:box).returns(box)
  559 + assert_equal [a1], block.articles_of_parent
  560 + end
  561 +
531 end 562 end
plugins/mark_comment_as_read/controllers/mark_comment_as_read_plugin_profile_controller.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class MarkCommentAsReadPluginProfileController < ProfileController
  2 +
  3 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  4 +
  5 + def mark_as_read
  6 + comment = Comment.find(params[:id])
  7 + comment.mark_as_read(user)
  8 + render :text => {'ok' => true}.to_json, :content_type => 'application/json'
  9 + end
  10 +
  11 + def mark_as_not_read
  12 + comment = Comment.find(params[:id])
  13 + comment.mark_as_not_read(user)
  14 + render :text => {'ok' => true}.to_json, :content_type => 'application/json'
  15 + end
  16 +
  17 +end
plugins/mark_comment_as_read/db/migrate/20130509184338_create_mark_comment_as_read_plugin.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class CreateMarkCommentAsReadPlugin < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :mark_comment_as_read_plugin do |t|
  4 + t.integer :comment_id
  5 + t.integer :person_id
  6 + end
  7 + add_index :mark_comment_as_read_plugin, [:comment_id, :person_id], :unique => true
  8 + end
  9 +
  10 + def self.down
  11 + drop_table :mark_comment_as_read_plugin
  12 + end
  13 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin.rb 0 → 100644
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +require_dependency 'mark_comment_as_read_plugin/ext/comment'
  2 +
  3 +class MarkCommentAsReadPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "MarkCommentAsReadPlugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("Provide a button to mark a comment as read.")
  11 + end
  12 +
  13 + def js_files
  14 + 'mark_comment_as_read.js'
  15 + end
  16 +
  17 + def stylesheet?
  18 + true
  19 + end
  20 +
  21 + def comment_actions(comment)
  22 + lambda do
  23 + [{:link => link_to_function(_('Mark as not read'), 'toggle_comment_read(this, %s, false);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_not_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-not-read-#{comment.id}")},
  24 + {:link => link_to_function(_('Mark as read'), 'toggle_comment_read(this, %s, true);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-read-#{comment.id}")}] if user
  25 + end
  26 + end
  27 +
  28 + def check_comment_actions(comment)
  29 + lambda do
  30 + if user
  31 + comment.marked_as_read?(user) ? "#comment-action-mark-as-not-read-#{comment.id}" : "#comment-action-mark-as-read-#{comment.id}"
  32 + end
  33 + end
  34 + end
  35 +
  36 + def article_extra_contents(article)
  37 + lambda do
  38 + if user
  39 + ids = article.comments.marked_as_read(user).collect { |comment| comment.id}
  40 + "<script type=\"text/javascript\">mark_comments_as_read(#{ids.to_json});</script>" if !ids.empty?
  41 + end
  42 + end
  43 + end
  44 +
  45 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/ext/comment.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require_dependency 'comment'
  2 +
  3 +class Comment
  4 +
  5 + has_many :read_comments, :class_name => 'MarkCommentAsReadPlugin::ReadComments'
  6 + has_many :people, :through => :read_comments
  7 +
  8 + def mark_as_read(person)
  9 + people << person
  10 + end
  11 +
  12 + def mark_as_not_read(person)
  13 + people.delete(person)
  14 + end
  15 +
  16 + def marked_as_read?(person)
  17 + person && people.find(:first, :conditions => {:id => person.id})
  18 + end
  19 +
  20 + def self.marked_as_read(person)
  21 + find(:all, :joins => [:read_comments], :conditions => {:author_id => person.id})
  22 + end
  23 +
  24 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/read_comments.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class MarkCommentAsReadPlugin::ReadComments < Noosfero::Plugin::ActiveRecord
  2 + set_table_name 'mark_comment_as_read_plugin'
  3 + belongs_to :comment
  4 + belongs_to :person
  5 +
  6 + validates_presence_of :comment, :person
  7 +end
plugins/mark_comment_as_read/public/mark_comment_as_read.js 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +function mark_comments_as_read(comments) {
  2 + jQuery(document).ready(function($) {
  3 + for(var i=0; i<comments.length; i++) {
  4 + $comment = jQuery('#comment-'+comments[i]);
  5 + $comment.find('.comment-content').first().addClass('comment-mark-read');
  6 + }
  7 + });
  8 +}
  9 +
  10 +function toggle_comment_read(button, url, mark) {
  11 + var $ = jQuery;
  12 + var $button = $(button);
  13 + $button.addClass('comment-button-loading');
  14 + $.post(url, function(data) {
  15 + if (data.ok) {
  16 + var $comment = $button.closest('.article-comment');
  17 + var $content = $comment.find('.comment-content').first();
  18 + if(mark)
  19 + $content.addClass('comment-mark-read');
  20 + else
  21 + $content.removeClass('comment-mark-read');
  22 + $button.hide();
  23 + $button.removeClass('comment-button-loading');
  24 + return;
  25 + }
  26 + });
  27 +}
  28 +
plugins/mark_comment_as_read/public/style.css 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +.article-comments-list .comment-mark-read .comment-text, .article-comments-list .comment-mark-read h4, .article-comments-list .comment-mark-read .comment-picture {
  2 + opacity: 0.2;
  3 +}
plugins/mark_comment_as_read/test/functional/mark_comment_as_read_plugin_profile_controller_test.rb 0 → 100644
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/mark_comment_as_read_plugin_profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class MarkCommentAsReadPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class MarkCommentAsReadPluginProfileControllerTest < ActionController::TestCase
  8 + def setup
  9 + @controller = MarkCommentAsReadPluginProfileController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 + @profile = create_user('profile').person
  13 + @article = TinyMceArticle.create!(:profile => @profile, :name => 'An article')
  14 + @comment = Comment.new(:source => @article, :author => @profile, :body => 'test')
  15 + @comment.save!
  16 + login_as(@profile.identifier)
  17 + environment = Environment.default
  18 + environment.enable_plugin(MarkCommentAsReadPlugin)
  19 + self.stubs(:user).returns(@profile)
  20 + end
  21 +
  22 + attr_reader :profile, :comment
  23 +
  24 + should 'mark comment as read' do
  25 + xhr :post, :mark_as_read, :profile => profile.identifier, :id => comment.id
  26 + assert_match /\{\"ok\":true\}/, @response.body
  27 + end
  28 +
  29 + should 'mark comment as not read' do
  30 + xhr :post, :mark_as_not_read, :profile => profile.identifier, :id => comment.id
  31 + assert_match /\{\"ok\":true\}/, @response.body
  32 + end
  33 +end
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_plugin/comment_test.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +require File.dirname(__FILE__) + '/../../../../../test/test_helper'
  2 +
  3 +class MarkCommentAsReadPlugin::CommentTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @person = create_user('user').person
  7 + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article')
  8 + @comment = Comment.create!(:title => 'title', :body => 'body', :author_id => @person.id, :source => @article)
  9 + end
  10 +
  11 + should 'mark comment as read' do
  12 + assert !@comment.marked_as_read?(@person)
  13 + @comment.mark_as_read(@person)
  14 + assert @comment.marked_as_read?(@person)
  15 + end
  16 +
  17 + should 'do not mark a comment as read again' do
  18 + @comment.mark_as_read(@person)
  19 + assert_raise ActiveRecord::StatementInvalid do
  20 + @comment.mark_as_read(@person)
  21 + end
  22 + end
  23 +
  24 + should 'mark comment as not read' do
  25 + @comment.mark_as_read(@person)
  26 + assert @comment.marked_as_read?(@person)
  27 + @comment.mark_as_not_read(@person)
  28 + assert !@comment.marked_as_read?(@person)
  29 + end
  30 +
  31 + should 'return comments marked as read for a user' do
  32 + person2 = create_user('user2').person
  33 + @comment.mark_as_read(@person)
  34 + assert_equal [], @article.comments.marked_as_read(@person) - [@comment]
  35 + assert_equal [], @article.comments.marked_as_read(person2)
  36 + end
  37 +
  38 +end
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_test.rb 0 → 100644
@@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class MarkCommentAsReadPluginTest < ActiveSupport::TestCase
  4 +
  5 + include ActionView::Helpers::TagHelper
  6 + include NoosferoTestHelper
  7 +
  8 + def setup
  9 + @plugin = MarkCommentAsReadPlugin.new
  10 + @person = create_user('user').person
  11 + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article')
  12 + @comment = Comment.create!(:source => @article, :author => @person, :body => 'test')
  13 + self.stubs(:user).returns(@person)
  14 + self.stubs(:profile).returns(@person)
  15 + end
  16 +
  17 + attr_reader :plugin, :comment
  18 +
  19 + should 'show link when person is logged in' do
  20 + action = @plugin.comment_actions(@comment)
  21 + link = self.instance_eval(&action)
  22 + assert link
  23 + end
  24 +
  25 + should 'do not show link when person is not logged in' do
  26 + self.stubs(:user).returns(nil)
  27 + action = @plugin.comment_actions(@comment)
  28 + link = self.instance_eval(&action)
  29 + assert !link
  30 + end
  31 +
  32 + should 'return actions when comment is not read' do
  33 + action = @plugin.comment_actions(@comment)
  34 + links = self.instance_eval(&action)
  35 + assert_equal 2, links.size
  36 + end
  37 +
  38 + should 'return actions when comment is read' do
  39 + @comment.mark_as_read(@person)
  40 + action = @plugin.comment_actions(@comment)
  41 + links = self.instance_eval(&action)
  42 + assert_equal 2, links.size
  43 + end
  44 +
  45 + should 'do not return any id when user is not logged in' do
  46 + self.stubs(:user).returns(nil)
  47 + action = @plugin.check_comment_actions(@comment)
  48 + id = self.instance_eval(&action)
  49 + assert !id
  50 + end
  51 +
  52 + should 'return id of mark as not read link when comment is read' do
  53 + @comment.mark_as_read(@person)
  54 + action = @plugin.check_comment_actions(@comment)
  55 + id = self.instance_eval(&action)
  56 + assert_equal "#comment-action-mark-as-not-read-#{@comment.id}", id
  57 + end
  58 +
  59 + should 'return id of mark as read link when comment is not read' do
  60 + action = @plugin.check_comment_actions(@comment)
  61 + id = self.instance_eval(&action)
  62 + assert_equal "#comment-action-mark-as-read-#{@comment.id}", id
  63 + end
  64 +
  65 + should 'return javascript to mark comment as read' do
  66 + @comment.mark_as_read(@person)
  67 + content = @plugin.article_extra_contents(@article)
  68 + assert self.instance_eval(&content)
  69 + end
  70 +
  71 + should 'do not return extra content if comment is not marked as read' do
  72 + content = @plugin.article_extra_contents(@article)
  73 + assert !self.instance_eval(&content)
  74 + end
  75 +
  76 + should 'do not return extra content if user is not logged in' do
  77 + @comment.mark_as_read(@person)
  78 + self.stubs(:user).returns(nil)
  79 + content = @plugin.article_extra_contents(@article)
  80 + assert !self.instance_eval(&content)
  81 + end
  82 +
  83 + def link_to_function(content, url, options = {})
  84 + link_to(content, url, options)
  85 + end
  86 +
  87 +end
plugins/pg_search/lib/ext/active_record.rb
@@ -2,11 +2,9 @@ require_dependency &#39;active_record&#39; @@ -2,11 +2,9 @@ require_dependency &#39;active_record&#39;
2 2
3 class ActiveRecord::Base 3 class ActiveRecord::Base
4 def self.pg_search_plugin_search(query) 4 def self.pg_search_plugin_search(query)
5 - query.gsub!(/\|/,' ')  
6 - formatted_query = query.split.map{|w| w += ":*"}.join('|')  
7 - 5 + filtered_query = query.gsub(/[\|\(\)\\\/\s\[\]'"*%&!:]/,' ').split.map{|w| w += ":*"}.join('|')
8 if defined?(self::SEARCHABLE_FIELDS) 6 if defined?(self::SEARCHABLE_FIELDS)
9 - where("to_tsvector('simple', #{pg_search_plugin_fields}) @@ to_tsquery('#{formatted_query}')") 7 + where("to_tsvector('simple', #{pg_search_plugin_fields}) @@ to_tsquery('#{filtered_query}')")
10 else 8 else
11 raise "No searchable fields defined for #{self.name}" 9 raise "No searchable fields defined for #{self.name}"
12 end 10 end
plugins/pg_search/test/unit/pg_search_plugin_test.rb
@@ -21,6 +21,11 @@ class PgSearchPluginTest &lt; ActiveSupport::TestCase @@ -21,6 +21,11 @@ class PgSearchPluginTest &lt; ActiveSupport::TestCase
21 assert_includes search(Profile, 'admin deb'), profile2 21 assert_includes search(Profile, 'admin deb'), profile2
22 end 22 end
23 23
  24 + should 'locate profile escaping special characters' do
  25 + profile = fast_create(Profile, :name => 'John', :identifier => 'waterfall')
  26 + assert_includes search(Profile, ') ( /\/\/\/\/\ o_o oOo o_o /\/\/\/\/\ ) ((tx waterfall)'), profile
  27 + end
  28 +
24 # TODO This feature is available only on Postgresql 9.0 29 # TODO This feature is available only on Postgresql 9.0
25 # http://www.postgresql.org/docs/9.0/static/unaccent.html 30 # http://www.postgresql.org/docs/9.0/static/unaccent.html
26 # should 'ignore accents' do 31 # should 'ignore accents' do
plugins/recent_content/test/unit/recent_content_block_test.rb
@@ -61,9 +61,9 @@ class RecentContentBlockTest &lt; ActiveSupport::TestCase @@ -61,9 +61,9 @@ class RecentContentBlockTest &lt; ActiveSupport::TestCase
61 61
62 root = fast_create(Blog, :name => 'test-blog', :profile_id => profile.id) 62 root = fast_create(Blog, :name => 'test-blog', :profile_id => profile.id)
63 63
64 - a1 = fast_create(TextileArticle, :name => 'article #1', :profile_id => profile.id, :parent_id => root.id)  
65 - a2 = fast_create(TextileArticle, :name => 'article #2', :profile_id => profile.id, :parent_id => root.id)  
66 - a3 = fast_create(TextileArticle, :name => 'article #3', :profile_id => profile.id, :parent_id => root.id) 64 + a1 = fast_create(TextileArticle, :name => 'article #1', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now - 2.days)
  65 + a2 = fast_create(TextileArticle, :name => 'article #2', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now - 1.days)
  66 + a3 = fast_create(TextileArticle, :name => 'article #3', :profile_id => profile.id, :parent_id => root.id, :created_at => Time.now)
67 67
68 block = RecentContentBlock.new 68 block = RecentContentBlock.new
69 block.stubs(:holder).returns(profile) 69 block.stubs(:holder).returns(profile)
plugins/relevant_content/lib/ext/article.rb 0 → 100644
@@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
  1 +require_dependency 'article'
  2 +
  3 +class Article
  4 +
  5 + named_scope :relevant_content, :conditions => ["articles.published = true and (articles.type != 'UploadedFile' and articles.type != 'Blog' and articles.type != 'RssFeed') OR articles.type is NULL"]
  6 +
  7 + def self.articles_columns
  8 + Article.column_names.map {|c| "articles.#{c}"} .join(",")
  9 + end
  10 +
  11 + def self.most_accessed(owner, limit = nil)
  12 + conditions = owner.kind_of?(Environment) ? ["hits > 0"] : ["profile_id = ? and hits > 0", owner.id]
  13 + result = Article.relevant_content.find(
  14 + :all,
  15 + :order => 'hits desc',
  16 + :limit => limit,
  17 + :conditions => conditions)
  18 + result.paginate({:page => 1, :per_page => limit})
  19 + end
  20 +
  21 + def self.most_commented_relevant_content(owner, limit)
  22 + conditions = owner.kind_of?(Environment) ? ["comments_count > 0"] : ["profile_id = ? and comments_count > 0", owner.id]
  23 + result = Article.relevant_content.find(
  24 + :all,
  25 + :order => 'comments_count desc',
  26 + :limit => limit,
  27 + :conditions => conditions)
  28 + result.paginate({:page => 1, :per_page => limit})
  29 + end
  30 +
  31 + def self.more_positive_votes(owner, limit = nil)
  32 + conditions = owner.kind_of?(Environment) ? {'votes.voteable_type' => 'Article'} : ["profile_id = ? and votes.voteable_type = ? ", owner.id, 'Article']
  33 + result = Article.relevant_content.find(
  34 + :all,
  35 + :order => 'sum(vote) desc',
  36 + :group => 'voteable_id, ' + articles_columns,
  37 + :limit => limit,
  38 + :having => ['sum(vote) > 0'],
  39 + :conditions => conditions,
  40 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  41 + result.paginate({:page => 1, :per_page => limit})
  42 + end
  43 +
  44 + def self.more_negative_votes(owner, limit = nil)
  45 + conditions = owner.kind_of?(Environment) ? {'votes.voteable_type' => 'Article'} : ["profile_id = ? and votes.voteable_type = 'Article' ", owner.id]
  46 + result = Article.relevant_content.find(
  47 + :all,
  48 + :order => 'sum(vote) asc',
  49 + :group => 'voteable_id, ' + articles_columns,
  50 + :limit => limit,
  51 + :having => ['sum(vote) < 0'],
  52 + :conditions => conditions,
  53 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id'
  54 + )
  55 + result.paginate({:page => 1, :per_page => limit})
  56 + end
  57 +
  58 + def self.most_liked(owner, limit = nil)
  59 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article' and vote > 0"] : ["votes.voteable_type = 'Article' and vote > 0 and profile_id = ? ", owner.id]
  60 + result = Article.relevant_content.find(
  61 + :all,
  62 + :select => articles_columns,
  63 + :order => 'count(voteable_id) desc',
  64 + :group => 'voteable_id, ' + articles_columns,
  65 + :limit => limit,
  66 + :conditions => conditions,
  67 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  68 + result.paginate({:page => 1, :per_page => limit})
  69 + end
  70 +
  71 + def self.most_disliked(owner, limit = nil)
  72 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article' and vote < 0"] : ["votes.voteable_type = 'Article' and vote < 0 and profile_id = ? ", owner.id]
  73 + result = Article.relevant_content.find(
  74 + :all,
  75 + :order => 'count(voteable_id) desc',
  76 + :group => 'voteable_id, ' + articles_columns,
  77 + :limit => limit,
  78 + :conditions => conditions,
  79 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  80 + result.paginate({:page => 1, :per_page => limit})
  81 + end
  82 +
  83 + def self.most_voted(owner, limit = nil)
  84 + conditions = owner.kind_of?(Environment) ? ["votes.voteable_type = 'Article'"] : ["votes.voteable_type = 'Article' and profile_id = ? ", owner.id]
  85 + result = Article.relevant_content.find(
  86 + :all,
  87 + :select => articles_columns,
  88 + :order => 'count(voteable_id) desc',
  89 + :group => 'voteable_id, ' + articles_columns,
  90 + :limit => limit,
  91 + :conditions => conditions,
  92 + :joins => 'INNER JOIN votes ON articles.id = votes.voteable_id')
  93 + result.paginate({:page => 1, :per_page => limit})
  94 + end
  95 +end
plugins/relevant_content/lib/relevant_content_plugin.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +class RelevantContentPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "Relevant Content Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A plugin that lists the most accessed, most commented, most liked and most disliked contents.")
  9 + end
  10 +
  11 + def self.extra_blocks
  12 + {
  13 + RelevantContentPlugin::RelevantContentBlock => {}
  14 + }
  15 + end
  16 +
  17 + def stylesheet?
  18 + true
  19 + end
  20 +
  21 +end
plugins/relevant_content/lib/relevant_content_plugin/relevant_content_block.rb 0 → 100644
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +class RelevantContentPlugin::RelevantContentBlock < Block
  2 + def self.description
  3 + _('Relevant content')
  4 + end
  5 +
  6 + def default_title
  7 + _('Relevant content')
  8 + end
  9 +
  10 + def help
  11 + _('This block lists the most popular content.')
  12 + end
  13 +
  14 + settings_items :limit, :type => :integer, :default => 5
  15 + settings_items :show_most_read, :type => :boolean, :default => 1
  16 + settings_items :show_most_commented, :type => :boolean, :default => 1
  17 + settings_items :show_most_liked, :type => :boolean, :default => 1
  18 + settings_items :show_most_disliked, :type => :boolean, :default => 0
  19 + settings_items :show_most_voted, :type => :boolean, :default => 1
  20 +
  21 + include ActionController::UrlWriter
  22 + def content(args={})
  23 +
  24 + content = block_title(title)
  25 +
  26 + if self.show_most_read
  27 + docs = Article.most_accessed(owner, self.limit)
  28 + if !docs.blank?
  29 + subcontent = ""
  30 + subcontent += content_tag(:span, _("Most read articles"), :class=>"title mread") + "\n"
  31 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  32 + content += content_tag(:div, subcontent, :class=>"block mread") + "\n"
  33 + end
  34 + end
  35 +
  36 + if self.show_most_commented
  37 + docs = Article.most_commented_relevant_content(owner, self.limit)
  38 + if !docs.blank?
  39 + subcontent = ""
  40 + subcontent += content_tag(:span, _("Most commented articles"), :class=>"title mcommented") + "\n"
  41 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  42 + content += content_tag(:div, subcontent, :class=>"block mcommented") + "\n"
  43 + end
  44 + end
  45 +
  46 + if owner.kind_of?(Environment)
  47 + env = owner
  48 + else
  49 + env = owner.environment
  50 + end
  51 +
  52 + if env.plugin_enabled?(VotePlugin)
  53 + if self.show_most_liked
  54 + docs = Article.more_positive_votes(owner, self.limit)
  55 + if !docs.blank?
  56 + subcontent = ""
  57 + subcontent += content_tag(:span, _("Most liked articles"), :class=>"title mliked") + "\n"
  58 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  59 + content += content_tag(:div, subcontent, :class=>"block mliked") + "\n"
  60 + end
  61 + end
  62 + if self.show_most_disliked
  63 + docs = Article.more_negative_votes(owner, self.limit)
  64 + if !docs.blank?
  65 + subcontent = ""
  66 + subcontent += content_tag(:span, _("Most disliked articles"), :class=>"title mdisliked") + "\n"
  67 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  68 + content += content_tag(:div, subcontent, :class=>"block mdisliked") + "\n"
  69 + end
  70 + end
  71 +
  72 + if self.show_most_voted
  73 + docs = Article.most_voted(owner, self.limit)
  74 + if !docs.blank?
  75 + subcontent = ""
  76 + subcontent += content_tag(:span, _("Most voted articles"), :class=>"title mvoted") + "\n"
  77 + subcontent += content_tag(:ul, docs.map {|item| content_tag('li', link_to(h(item.title), item.url))}.join("\n"))
  78 + content += content_tag(:div, subcontent, :class=>"block mvoted") + "\n"
  79 + end
  80 + end
  81 + end
  82 + return content
  83 + end
  84 +
  85 + def timeout
  86 + 4.hours
  87 + end
  88 +
  89 + def self.expire_on
  90 + { :profile => [:article], :environment => [:article] }
  91 + end
  92 +
  93 +end
0 \ No newline at end of file 94 \ No newline at end of file
plugins/relevant_content/public/style.css 0 → 100644
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +#content .relevant-content-plugin_relevant-content-block {
  2 + padding: 10px 0px 10px 10px;
  3 + word-wrap: break-word;
  4 +}
  5 +
  6 +.relevant-content-plugin_relevant-content-block ul {
  7 + margin: 0px;
  8 + padding: 0px 0px 0px 20px;
  9 +}
  10 +.relevant-content-plugin_relevant-content-block li {
  11 + margin: 0px;
  12 + padding: 0px;
  13 + list-style: none
  14 +}
  15 +.relevant-content-plugin_relevant-content-block a {
  16 + text-decoration: none;
  17 +}
  18 +.relevant-content-plugin_relevant-content-block .block-footer-content {
  19 + font-size: 10px;
  20 +}
  21 +.relevant-content-plugin_relevant-content-block .block-footer-content a:hover {
  22 + text-decoration: underline;
  23 +}
  24 +
  25 +.relevant-content-plugin_relevant-content-block p {
  26 + text-align:center;
  27 +}
  28 +
  29 +.relevant-content-plugin_relevant-content-block p.like{
  30 + background-image: url('images/positive-hand.png');
  31 + background-repeat: no-repeat;
  32 + min-width: 50px;
  33 + text-align:center;
  34 +}
  35 +
  36 +.relevant-content-plugin_relevant-content-block p.dislike{
  37 + background-image: url('images/negative-hand.png');
  38 + background-repeat: no-repeat;
  39 + min-width: 50px;
  40 + text-align:center;
  41 +}
  42 +
  43 +
  44 +.relevant-content-plugin_relevant-content-block {
  45 + //overflow: hidden;
  46 + display: block;
  47 + width: 100%;
  48 +}
  49 +
  50 +
  51 +.relevant-content-cover img {
  52 + width: 100%;
  53 +}
  54 +
  55 +.relevant-content-plugin_relevant-content-block span.title {
  56 + display: block;
  57 + margin: 20px 0px 0px;
  58 + padding: 0px 0px 0px 20px;
  59 +}
  60 +
  61 +.relevant-content-plugin_relevant-content-block span.title.mread {
  62 +
  63 +}
  64 +
  65 +.relevant-content-plugin_relevant-content-block span.title.mcommented {
  66 +
  67 +}
  68 +
  69 +.relevant-content-plugin_relevant-content-block span.title.mliked {
  70 +
  71 +}
  72 +
  73 +.relevant-content-plugin_relevant-content-block span.title.mdisliked {
  74 +
  75 +}
  76 +
  77 +.relevant-content-plugin_relevant-content-block span.title.mvoted {
  78 +
  79 +}
plugins/relevant_content/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/relevant_content/test/unit/article.rb 0 → 100644
@@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +require 'comment_controller'
  4 +# Re-raise errors caught by the controller.
  5 +class CommentController; def rescue_action(e) raise e end; end
  6 +
  7 +class RelevantContentBlockTest < ActiveSupport::TestCase
  8 +
  9 + include AuthenticatedTestHelper
  10 + fixtures :users, :environments
  11 +
  12 + def setup
  13 + @controller = CommentController.new
  14 + @request = ActionController::TestRequest.new
  15 + @response = ActionController::TestResponse.new
  16 + @profile = create_user('testinguser').person
  17 + @environment = @profile.environment
  18 + end
  19 + attr_reader :profile, :environment
  20 +
  21 + def enable_vote_plugin
  22 + enabled = false
  23 + environment=Environment.default
  24 + if Noosfero::Plugin.all.include?('VotePlugin')
  25 + if not environment.enabled_plugins.include?(:vote)
  26 + environment.enable_plugin(Vote)
  27 + environment.save!
  28 + end
  29 + enabled = true
  30 + end
  31 + enabled
  32 + end
  33 +
  34 + should 'list most commented articles' do
  35 + Article.delete_all
  36 + a1 = create(TextileArticle, :name => "art 1", :profile_id => profile.id)
  37 + a2 = create(TextileArticle, :name => "art 2", :profile_id => profile.id)
  38 + a3 = create(TextileArticle, :name => "art 3", :profile_id => profile.id)
  39 +
  40 + 2.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => a2).save! }
  41 + 4.times { Comment.create(:title => 'test', :body => 'asdsad', :author => profile, :source => a3).save! }
  42 +
  43 + # should respect the order (more commented comes first)
  44 + assert_equal a3.name, profile.articles.most_commented_relevant_content(Environment.default, 3).first.name
  45 + # It is a2 instead of a1 since it does not list articles without comments
  46 + assert_equal a2.name, profile.articles.most_commented_relevant_content(Environment.default, 3).last.name
  47 + end
  48 +
  49 +
  50 + should 'find the most voted' do
  51 + if not enable_vote_plugin
  52 + return
  53 + end
  54 + article = fast_create(Article, {:name=>'2 votes'})
  55 + 2.times{
  56 + person = fast_create(Person)
  57 + person.vote_for(article)
  58 + }
  59 + article = fast_create(Article, {:name=>'10 votes'})
  60 + 10.times{
  61 + person = fast_create(Person)
  62 + person.vote_for(article)
  63 + }
  64 + article = fast_create(Article, {:name=>'5 votes'})
  65 + 5.times{
  66 + person = fast_create(Person)
  67 + person.vote_for(article)
  68 + }
  69 + articles = Article.most_voted(Environment.default, 5)
  70 + assert_equal '10 votes', articles.first.name
  71 + assert_equal '2 votes', articles.last.name
  72 + end
  73 +
  74 + should 'list the most postive' do
  75 + if not enable_vote_plugin
  76 + return
  77 + end
  78 + article = fast_create(Article, {:name=>'23 votes for 20 votes against'})
  79 + 20.times{
  80 + person = fast_create(Person)
  81 + person.vote_against(article)
  82 + }
  83 + 23.times{
  84 + person = fast_create(Person)
  85 + person.vote_for(article)
  86 + }
  87 + article = fast_create(Article, {:name=>'10 votes for 5 votes against'})
  88 + 10.times{
  89 + person = fast_create(Person)
  90 + person.vote_for(article)
  91 + }
  92 + 5.times{
  93 + person = fast_create(Person)
  94 + person.vote_against(article)
  95 + }
  96 + article = fast_create(Article, {:name=>'2 votes against'})
  97 + 2.times{
  98 + person = fast_create(Person)
  99 + person.vote_against(article)
  100 + }
  101 +
  102 + article = fast_create(Article, {:name=>'7 votes for'})
  103 + 7.times{
  104 + person = fast_create(Person)
  105 + person.vote_for(article)
  106 + }
  107 + articles = Article.more_positive_votes(Environment.default, 5)
  108 + assert_equal '7 votes for', articles.first.name
  109 + assert_equal '23 votes for 20 votes against', articles.last.name
  110 + end
  111 +
  112 + should 'list the most negative' do
  113 + if not enable_vote_plugin
  114 + return
  115 + end
  116 + article = fast_create(Article, {:name=>'23 votes for 29 votes against'})
  117 + 29.times{
  118 + person = fast_create(Person)
  119 + person.vote_against(article)
  120 + }
  121 + 23.times{
  122 + person = fast_create(Person)
  123 + person.vote_for(article)
  124 + }
  125 + article = fast_create(Article, {:name=>'10 votes for 15 votes against'})
  126 + 10.times{
  127 + person = fast_create(Person)
  128 + person.vote_for(article)
  129 + }
  130 + 15.times{
  131 + person = fast_create(Person)
  132 + person.vote_against(article)
  133 + }
  134 + article = fast_create(Article, {:name=>'2 votes against'})
  135 + 2.times{
  136 + person = fast_create(Person)
  137 + person.vote_against(article)
  138 + }
  139 + article = fast_create(Article, {:name=>'7 votes for'})
  140 + 7.times{
  141 + person = fast_create(Person)
  142 + person.vote_for(article)
  143 + }
  144 + articles = Article.more_negative_votes(Environment.default, 5)
  145 + assert_equal '23 votes for 29 votes against', articles.first.name
  146 + assert_equal '2 votes against', articles.last.name
  147 + end
  148 +end
0 \ No newline at end of file 149 \ No newline at end of file
plugins/relevant_content/test/unit/relevant_content_block_test.rb 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +require 'comment_controller'
  4 +# Re-raise errors caught by the controller.
  5 +class CommentController; def rescue_action(e) raise e end; end
  6 +
  7 +class RelevantContentBlockTest < ActiveSupport::TestCase
  8 +
  9 + include AuthenticatedTestHelper
  10 + fixtures :users, :environments
  11 +
  12 + def setup
  13 + @controller = CommentController.new
  14 + @request = ActionController::TestRequest.new
  15 + @response = ActionController::TestResponse.new
  16 +
  17 + @profile = create_user('testinguser').person
  18 + @environment = @profile.environment
  19 + end
  20 + attr_reader :profile, :environment
  21 +
  22 + should 'have a default title' do
  23 + relevant_content_block = RelevantContentPlugin::RelevantContentBlock.new
  24 + block = Block.new
  25 + assert_not_equal block.default_title, relevant_content_block.default_title
  26 + end
  27 +
  28 + should 'have a help tooltip' do
  29 + relevant_content_block = RelevantContentPlugin::RelevantContentBlock.new
  30 + block = Block.new
  31 + assert_not_equal "", relevant_content_block.help
  32 + end
  33 +
  34 + should 'describe itself' do
  35 + assert_not_equal Block.description, RelevantContentPlugin::RelevantContentBlock.description
  36 + end
  37 +
  38 + should 'is editable' do
  39 + block = RelevantContentPlugin::RelevantContentBlock.new
  40 + assert block.editable?
  41 + end
  42 +
  43 + should 'expire' do
  44 + assert_equal RelevantContentPlugin::RelevantContentBlock.expire_on, {:environment=>[:article], :profile=>[:article]}
  45 + end
  46 +
  47 +end
plugins/relevant_content/test/unit/relevant_content_plugin_test.rb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class RelevantContentPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = RelevantContentPlugin.new
  7 + end
  8 +
  9 + should 'be a noosfero plugin' do
  10 + assert_kind_of Noosfero::Plugin, @plugin
  11 + end
  12 +
  13 + should 'have name' do
  14 + assert_equal 'Relevant Content Plugin', RelevantContentPlugin.plugin_name
  15 + end
  16 +
  17 + should 'have description' do
  18 + assert_equal _("A plugin that lists the most accessed, most commented, most liked and most disliked contents."), RelevantContentPlugin.plugin_description
  19 + end
  20 +
  21 + should 'have stylesheet' do
  22 + assert @plugin.stylesheet?
  23 + end
  24 +
  25 + should "return RelevantContentBlock in extra_blocks class method" do
  26 + assert RelevantContentPlugin.extra_blocks.keys.include?(RelevantContentPlugin::RelevantContentBlock)
  27 + end
  28 +
  29 +end
plugins/relevant_content/views/box_organizer/relevant_content_plugin/_relevant_content_block.rhtml 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +<div id='edit-relevant-content-block'>
  2 + <%= labelled_form_field _('Limit of items per category'), text_field(:block, :limit, :size => 3) %>
  3 + <%= labelled_check_box _('Display most accessed content'), "block[show_most_read]", 1 ,@block.show_most_read %><BR>
  4 + <%= labelled_check_box _('Display most commented content'), "block[show_most_commented]", 1 ,@block.show_most_commented %><BR>
  5 + <%= labelled_check_box _('Display most liked content'), "block[show_most_liked]", 1 ,@block.show_most_liked %><BR>
  6 + <%= labelled_check_box _('Display most voted content'), "block[show_most_voted]", 1 ,@block.show_most_voted %><BR>
  7 + <%= labelled_check_box _('Display most disliked content'), "block[show_most_disliked]", 1 , @block.show_most_disliked %><BR>
  8 +</div>
0 \ No newline at end of file 9 \ No newline at end of file
plugins/relevant_content/views/environment_design/relevant_content_plugin 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../box_organizer/relevant_content_plugin
0 \ No newline at end of file 2 \ No newline at end of file
plugins/relevant_content/views/profile_design/relevant_content_plugin 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../box_organizer/relevant_content_plugin
0 \ No newline at end of file 2 \ No newline at end of file
plugins/send_email/controllers/send_email_plugin_base_controller.rb
@@ -3,7 +3,7 @@ module SendEmailPluginBaseController @@ -3,7 +3,7 @@ module SendEmailPluginBaseController
3 if request.post? 3 if request.post?
4 @context_url = profile ? profile.url : {:host => environment.default_hostname, :controller => 'home'} 4 @context_url = profile ? profile.url : {:host => environment.default_hostname, :controller => 'home'}
5 @mail = SendEmailPlugin::Mail.new( 5 @mail = SendEmailPlugin::Mail.new(
6 - :from => environment.contact_email, 6 + :from => environment.noreply_email,
7 :to => params[:to], 7 :to => params[:to],
8 :message => params[:message], 8 :message => params[:message],
9 :environment => environment, 9 :environment => environment,
plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
1 <h1> <%= _('Basket options') %> </h1> 1 <h1> <%= _('Basket options') %> </h1>
2 2
3 <%= form_for(:settings, @settings, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %> 3 <%= form_for(:settings, @settings, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %>
4 - <%= labelled_form_field(_('Enabled?'), f.check_box(:enabled)) %>  
5 - <%= labelled_form_field(_('Delivery?'), f.check_box(:delivery)) %> 4 + <%= labelled_form_field(_('Enable shopping basket'), f.check_box(:enabled)) %>
  5 + <%= labelled_form_field(_('Enable delivery fields on orders'), f.check_box(:delivery)) %>
6 <% display_delivery_settings = @settings.delivery ? 'auto' : 'none' %> 6 <% display_delivery_settings = @settings.delivery ? 'auto' : 'none' %>
7 <fieldset id='delivery_settings' style="display: <%= display_delivery_settings %>"><legend><%=_('Delivery')%></legend> 7 <fieldset id='delivery_settings' style="display: <%= display_delivery_settings %>"><legend><%=_('Delivery')%></legend>
8 <table> 8 <table>
@@ -33,8 +33,8 @@ @@ -33,8 +33,8 @@
33 </tr> 33 </tr>
34 </table> 34 </table>
35 35
36 - <%= labelled_form_field(_('Free delivery price:'), f.text_field(:free_delivery_price)) %>  
37 - <%= content_tag('small', _('Empty stands for no free delivery price.')) %> 36 + <%= labelled_form_field(_("Order's minimum price for free delivery:"), f.text_field(:free_delivery_price)) %>
  37 + <%= content_tag('small', _('Leave empty to always charge the delivery.')) %>
38 </fieldset> 38 </fieldset>
39 <br style='clear: both'/> 39 <br style='clear: both'/>
40 <br style='clear: both'/> 40 <br style='clear: both'/>
plugins/spaminator/lib/spaminator_plugin/mailer.rb
@@ -4,7 +4,7 @@ class SpaminatorPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -4,7 +4,7 @@ class SpaminatorPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
4 def inactive_person_notification(person) 4 def inactive_person_notification(person)
5 mail( 5 mail(
6 :to => person.email, 6 :to => person.email,
7 - :from => "#{person.environment.name} <#{person.environment.contact_email}>", 7 + :from => "#{person.environment.name} <#{person.environment.noreply_email}>",
8 :subject => _("[%s] You must reactivate your account.") % person.environment.name, 8 :subject => _("[%s] You must reactivate your account.") % person.environment.name,
9 :content_type => 'text/html', 9 :content_type => 'text/html',
10 :body => {:person => person, 10 :body => {:person => person,
plugins/spaminator/test/unit/spaminator_plugin/mailer_test.rb
@@ -14,7 +14,7 @@ class SpaminatorPlugin::MailerTest &lt; ActiveSupport::TestCase @@ -14,7 +14,7 @@ class SpaminatorPlugin::MailerTest &lt; ActiveSupport::TestCase
14 attr_accessor :environment, :settings 14 attr_accessor :environment, :settings
15 15
16 should 'be able to send a inactive person notification message' do 16 should 'be able to send a inactive person notification message' do
17 - environment.contact_email = 'no-reply@noosfero.org' 17 + environment.noreply_email = 'no-reply@noosfero.org'
18 environment.save 18 environment.save
19 19
20 person = create_user('spammer').person 20 person = create_user('spammer').person
plugins/statistics/README 0 → 100644
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +README - Statistics (Statistics Plugin)
  2 +================================
  3 +
  4 +Statistics is a plugin to allow the user adds a block where you could see statistics of it's context.
  5 +
  6 +The Statistics block will be available for all layout columns of communities, peole, enterprises and environments.
  7 +
  8 +INSTALL
  9 +=======
  10 +
  11 +Enable Plugin
  12 +-------------
  13 +
  14 +Also, you need to enable Statistics Plugin at you Noosfero:
  15 +
  16 +cd <your_noosfero_dir>
  17 +./script/noosfero-plugins enable statistics
  18 +
  19 +Active Plugin
  20 +-------------
  21 +
  22 +As a Noosfero administrator user, go to administrator panel:
  23 +
  24 +- Click on "Enable/disable plugins" option
  25 +- Click on "Statistics Plugin" check-box
  26 +
  27 +Running Statistics tests
  28 +--------------------
  29 +
  30 +$ rake test:noosfero_plugins:statistics
  31 +
  32 +
  33 +Get Involved
  34 +============
  35 +
  36 +If you found any bug and/or want to collaborate, please send an e-mail to eduardo.edington@gmail.com
  37 +
  38 +LICENSE
  39 +=======
  40 +
  41 +Copyright (c) The Author developers.
  42 +
  43 +See Noosfero license.
  44 +
  45 +
  46 +AUTHORS
  47 +=======
  48 +
  49 + Eduardo Tourinho Edington (eduardo.edington at gmail.com)
  50 +
  51 +ACKNOWLEDGMENTS
  52 +===============
  53 +
  54 +The author has been supported by Serpro
plugins/statistics/lib/statistics_block.rb 0 → 100644
@@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
  1 +class StatisticsBlock < Block
  2 +
  3 + settings_items :community_counter, :default => false
  4 + settings_items :user_counter, :default => true
  5 + settings_items :enterprise_counter, :default => false
  6 + settings_items :category_counter, :default => false
  7 + settings_items :tag_counter, :default => true
  8 + settings_items :comment_counter, :default => true
  9 + settings_items :hit_counter, :default => false
  10 + settings_items :templates_ids_counter, Hash, :default => {}
  11 +
  12 + USER_COUNTERS = [:community_counter, :user_counter, :enterprise_counter, :tag_counter, :comment_counter, :hit_counter]
  13 + COMMUNITY_COUNTERS = [:user_counter, :tag_counter, :comment_counter, :hit_counter]
  14 + ENTERPRISE_COUNTERS = [:user_counter, :tag_counter, :comment_counter, :hit_counter]
  15 +
  16 + def self.description
  17 + _('Statistics')
  18 + end
  19 +
  20 + def default_title
  21 + _('Statistics for %s') % owner.name
  22 + end
  23 +
  24 + def is_visible? counter
  25 + value = self.send(counter)
  26 + value == '1' || value == true
  27 + end
  28 +
  29 + def is_counter_available? counter
  30 + if owner.kind_of?(Environment)
  31 + true
  32 + elsif owner.kind_of?(Person)
  33 + USER_COUNTERS.include?(counter)
  34 + elsif owner.kind_of?(Community)
  35 + COMMUNITY_COUNTERS.include?(counter)
  36 + elsif owner.kind_of?(Enterprise)
  37 + ENTERPRISE_COUNTERS.include?(counter)
  38 + end
  39 +
  40 + end
  41 +
  42 + def help
  43 + _('This block presents some statistics about your context.')
  44 + end
  45 +
  46 + def timeout
  47 + 60.minutes
  48 + end
  49 +
  50 + def environment
  51 + if owner.kind_of?(Environment)
  52 + owner
  53 + elsif owner.kind_of?(Profile)
  54 + owner.environment
  55 + else
  56 + nil
  57 + end
  58 + end
  59 +
  60 + def templates
  61 + Community.templates(environment)
  62 + end
  63 +
  64 + def is_template_counter_active? template_id
  65 + self.templates_ids_counter[template_id.to_s].to_s == 'true'
  66 + end
  67 +
  68 + def template_counter_count(template_id)
  69 + owner.communities.visible.count(:conditions => {:template_id => template_id})
  70 + end
  71 +
  72 + def users
  73 + if owner.kind_of?(Environment)
  74 + owner.people.visible.count
  75 + elsif owner.kind_of?(Organization)
  76 + owner.members.visible.count
  77 + elsif owner.kind_of?(Person)
  78 + owner.friends.visible.count
  79 + else
  80 + 0
  81 + end
  82 + end
  83 +
  84 + def enterprises
  85 + if owner.kind_of?(Environment) || owner.kind_of?(Person)
  86 + owner.enterprises.visible.count
  87 + else
  88 + 0
  89 + end
  90 + end
  91 +
  92 + def communities
  93 + if owner.kind_of?(Environment) || owner.kind_of?(Person)
  94 + owner.communities.visible.count
  95 + else
  96 + 0
  97 + end
  98 + end
  99 +
  100 + def categories
  101 + if owner.kind_of?(Environment) then
  102 + owner.categories.count
  103 + else
  104 + 0
  105 + end
  106 + end
  107 +
  108 + def tags
  109 + if owner.kind_of?(Environment) then
  110 + owner.tag_counts.count
  111 + elsif owner.kind_of?(Profile) then
  112 + owner.article_tags.count
  113 + else
  114 + 0
  115 + end
  116 + end
  117 +
  118 + def comments
  119 + if owner.kind_of?(Environment) then
  120 + owner.profiles.joins(:articles).sum(:comments_count).to_i
  121 + elsif owner.kind_of?(Profile) then
  122 + owner.articles.sum(:comments_count)
  123 + else
  124 + 0
  125 + end
  126 + end
  127 +
  128 + def hits
  129 + if owner.kind_of?(Environment) then
  130 + owner.profiles.joins(:articles).sum(:hits).to_i
  131 + elsif owner.kind_of?(Profile) then
  132 + owner.articles.sum(:hits)
  133 + else
  134 + 0
  135 + end
  136 + end
  137 +
  138 + def content(args={})
  139 + block = self
  140 +
  141 + lambda do
  142 + render :file => 'statistics_block', :locals => { :block => block }
  143 + end
  144 + end
  145 +
  146 +end
plugins/statistics/lib/statistics_plugin.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +require_dependency File.dirname(__FILE__) + '/statistics_block'
  2 +
  3 +class StatisticsPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "Statistics Plugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("A plugin that adds a block where you can see statistics of it's context.")
  11 + end
  12 +
  13 + def self.extra_blocks
  14 + {
  15 + StatisticsBlock => {}
  16 + }
  17 + end
  18 +
  19 +end
plugins/statistics/test/functional/statistics_plugin_environment_design_controller_test.rb 0 → 100644
@@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class EnvironmentDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class EnvironmentDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = EnvironmentDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @environment.add_admin(user.person)
  21 +
  22 + StatisticsBlock.delete_all
  23 + @box1 = Box.create!(:owner => @environment)
  24 + @environment.boxes = [@box1]
  25 +
  26 + @block = StatisticsBlock.new
  27 + @block.box = @box1
  28 + @block.save!
  29 +
  30 + login_as(user.login)
  31 + end
  32 +
  33 + attr_accessor :block
  34 +
  35 + should 'be able to edit StatisticsBlock' do
  36 + get :edit, :id => @block.id
  37 + assert_tag :tag => 'input', :attributes => { :id => 'block_title' }
  38 + end
  39 +
  40 + should 'be able to save StatisticsBlock' do
  41 + get :edit, :id => @block.id
  42 + post :save, :id => @block.id, :block => {:title => 'Statistics' }
  43 + @block.reload
  44 + assert_equal 'Statistics', @block.title
  45 + end
  46 +
  47 + should 'be able to uncheck core counters' do
  48 + @block.user_counter = true
  49 + @block.community_counter = true
  50 + @block.enterprise_counter = true
  51 + @block.category_counter = true
  52 + @block.tag_counter = true
  53 + @block.comment_counter = true
  54 + @block.hit_counter = true
  55 + @block.save!
  56 + get :edit, :id => @block.id
  57 + post :save, :id => @block.id, :block => {:user_counter => '0', :community_counter => '0', :enterprise_counter => '0',
  58 + :category_counter => '0', :tag_counter => '0', :comment_counter => '0', :hit_counter => '0' }
  59 + @block.reload
  60 + any_checked = @block.is_visible?('user_counter') ||
  61 + @block.is_visible?('community_counter') ||
  62 + @block.is_visible?('enterprise_counter') ||
  63 + @block.is_visible?('category_counter') ||
  64 + @block.is_visible?('tag_counter') ||
  65 + @block.is_visible?('comment_counter') ||
  66 + @block.is_visible?('hit_counter')
  67 + assert_equal false, any_checked
  68 +
  69 + end
  70 +
  71 + should 'be able to check core counters' do
  72 + @block.user_counter = false
  73 + @block.community_counter = false
  74 + @block.enterprise_counter = false
  75 + @block.category_counter = false
  76 + @block.tag_counter = false
  77 + @block.comment_counter = false
  78 + @block.hit_counter = false
  79 + @block.save!
  80 + get :edit, :id => @block.id
  81 + post :save, :id => @block.id, :block => {:user_counter => '1', :community_counter => '1', :enterprise_counter => '1',
  82 + :category_counter => '1', :tag_counter => '1', :comment_counter => '1', :hit_counter => '1' }
  83 + @block.reload
  84 + all_checked = @block.is_visible?('user_counter') &&
  85 + @block.is_visible?('community_counter') &&
  86 + @block.is_visible?('enterprise_counter') &&
  87 + @block.is_visible?('category_counter') &&
  88 + @block.is_visible?('tag_counter') &&
  89 + @block.is_visible?('comment_counter') &&
  90 + @block.is_visible?('hit_counter')
  91 + assert all_checked
  92 +
  93 + end
  94 +
  95 + should 'be able to check template counters' do
  96 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  97 + @block.templates_ids_counter = {template.id.to_s => 'false'}
  98 + @block.save!
  99 + get :edit, :id => @block.id
  100 + post :save, :id => @block.id, :block => {:templates_ids_counter => {template.id.to_s => 'true'}}
  101 + @block.reload
  102 +
  103 + assert @block.is_template_counter_active?(template.id)
  104 + end
  105 +
  106 + should 'be able to uncheck template counters' do
  107 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  108 + @block.templates_ids_counter = {template.id.to_s => 'true'}
  109 + @block.save!
  110 + get :edit, :id => @block.id
  111 + post :save, :id => @block.id, :block => {:templates_ids_counter => {template.id.to_s => 'false'}}
  112 + @block.reload
  113 +
  114 + assert_equal false, @block.is_template_counter_active?(template.id)
  115 + end
  116 +
  117 + should 'input user counter be checked by default' do
  118 + get :edit, :id => @block.id
  119 +
  120 + assert_tag :input, :attributes => {:id => 'block_user_counter', :checked => 'checked'}
  121 + end
  122 +
  123 + should 'not input community counter be checked by default' do
  124 + get :edit, :id => @block.id
  125 +
  126 + assert_tag :input, :attributes => {:id => 'block_community_counter'}
  127 + assert_no_tag :input, :attributes => {:id => 'block_community_counter', :checked => 'checked'}
  128 + end
  129 +
  130 + should 'not input enterprise counter be checked by default' do
  131 + get :edit, :id => @block.id
  132 +
  133 + assert_tag :input, :attributes => {:id => 'block_enterprise_counter'}
  134 + assert_no_tag :input, :attributes => {:id => 'block_enterprise_counter', :checked => 'checked'}
  135 + end
  136 +
  137 + should 'not input category counter be checked by default' do
  138 + get :edit, :id => @block.id
  139 +
  140 + assert_tag :input, :attributes => {:id => 'block_category_counter'}
  141 + assert_no_tag :input, :attributes => {:id => 'block_category_counter', :checked => 'checked'}
  142 + end
  143 +
  144 + should 'input tag counter be checked by default' do
  145 + get :edit, :id => @block.id
  146 +
  147 + assert_tag :input, :attributes => {:id => 'block_tag_counter', :checked => 'checked'}
  148 + end
  149 +
  150 + should 'input comment counter be checked by default' do
  151 + get :edit, :id => @block.id
  152 +
  153 + assert_tag :input, :attributes => {:id => 'block_comment_counter', :checked => 'checked'}
  154 + end
  155 +
  156 + should 'input hit counter not be checked by default' do
  157 + get :edit, :id => @block.id
  158 +
  159 + assert_no_tag :input, :attributes => {:id => 'block_hit_counter', :checked => 'checked'}
  160 + end
  161 +end
plugins/statistics/test/functional/statistics_plugin_home_controller_test.rb 0 → 100644
@@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class HomeController; def rescue_action(e) raise e end; end
  5 +
  6 +class HomeControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = HomeController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @environment.add_admin(user.person)
  21 +
  22 + StatisticsBlock.delete_all
  23 + @box1 = Box.create!(:owner => @environment)
  24 + @environment.boxes = [@box1]
  25 +
  26 + @block = StatisticsBlock.new
  27 + @block.box = @box1
  28 + @block.save!
  29 +
  30 + login_as(user.login)
  31 + end
  32 +
  33 + attr_accessor :block
  34 +
  35 + should 'display statistics-block-data class in environment block edition' do
  36 + get :index
  37 +
  38 + assert_tag :div, :attributes => {:class => 'statistics-block-data'}
  39 + end
  40 +
  41 + should 'display users class in statistics-block-data block' do
  42 + get :index
  43 +
  44 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'users'} }
  45 + end
  46 +
  47 + should 'not display users class in statistics-block-data block' do
  48 + @block.user_counter = false
  49 + @block.save!
  50 + get :index
  51 +
  52 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'users'} }
  53 + end
  54 +
  55 + should 'display communities class in statistics-block-data block' do
  56 + @block.community_counter = true
  57 + @block.save!
  58 + get :index
  59 +
  60 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'communities'} }
  61 + end
  62 +
  63 + should 'not display communities class in statistics-block-data block' do
  64 + get :index
  65 +
  66 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'communities'} }
  67 + end
  68 +
  69 + should 'display enterprises class in statistics-block-data block' do
  70 + @block.enterprise_counter = true
  71 + @block.save!
  72 + get :index
  73 +
  74 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'enterprises'} }
  75 + end
  76 +
  77 + should 'not display enterprises class in statistics-block-data block' do
  78 + get :index
  79 +
  80 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'enterprises'} }
  81 + end
  82 +
  83 + should 'display categories class in statistics-block-data block' do
  84 + @block.category_counter = true
  85 + @block.save!
  86 + get :index
  87 +
  88 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'categories'} }
  89 + end
  90 +
  91 + should 'not display categories class in statistics-block-data block' do
  92 + get :index
  93 +
  94 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'categories'} }
  95 + end
  96 +
  97 + should 'display tags class in statistics-block-data block' do
  98 + get :index
  99 +
  100 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'tags'} }
  101 + end
  102 +
  103 + should 'not display tags class in statistics-block-data block' do
  104 + @block.tag_counter = false
  105 + @block.save!
  106 + get :index
  107 +
  108 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'tags'} }
  109 + end
  110 +
  111 + should 'display comments class in statistics-block-data block' do
  112 + get :index
  113 +
  114 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'comments'} }
  115 + end
  116 +
  117 + should 'not display comments class in statistics-block-data block' do
  118 + @block.comment_counter = false
  119 + @block.save!
  120 + get :index
  121 +
  122 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'comments'} }
  123 + end
  124 +
  125 + should 'display hits class in statistics-block-data block' do
  126 + @block.hit_counter = true
  127 + @block.save!
  128 + get :index
  129 +
  130 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'hits'} }
  131 + end
  132 +
  133 + should 'not display hits class in statistics-block-data block' do
  134 + get :index
  135 +
  136 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'hits'} }
  137 + end
  138 +
  139 + should 'display template name in class in statistics-block-data block' do
  140 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  141 + @block.templates_ids_counter = {template.id.to_s => 'true'}
  142 + @block.save!
  143 + get :index
  144 +
  145 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'councils'} }
  146 + end
  147 +end
plugins/statistics/test/functional/statistics_plugin_profile_design_controller_test.rb 0 → 100644
@@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class ProfileDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class ProfileDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = ProfileDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @person = user.person
  21 + @environment.add_admin(@person)
  22 +
  23 + StatisticsBlock.delete_all
  24 + @box1 = Box.create!(:owner => @person)
  25 + @environment.boxes = [@box1]
  26 +
  27 + @block = StatisticsBlock.new
  28 + @block.box = @box1
  29 + @block.save!
  30 +
  31 + login_as(user.login)
  32 + end
  33 +
  34 + attr_accessor :block
  35 +
  36 + should 'be able to edit StatisticsBlock' do
  37 + get :edit, :id => @block.id, :profile => @person.identifier
  38 + assert_tag :tag => 'input', :attributes => { :id => 'block_title' }
  39 + end
  40 +
  41 + should 'be able to save StatisticsBlock' do
  42 + get :edit, :id => @block.id, :profile => @person.identifier
  43 + post :save, :id => @block.id, :block => {:title => 'Statistics' }, :profile => @person.identifier
  44 + @block.reload
  45 + assert_equal 'Statistics', @block.title
  46 + end
  47 +
  48 + should 'be able to uncheck core counters' do
  49 + @block.user_counter = true
  50 + @block.tag_counter = true
  51 + @block.comment_counter = true
  52 + @block.hit_counter = true
  53 + @block.save!
  54 + get :edit, :id => @block.id, :profile => @person.identifier
  55 + post :save, :id => @block.id, :block => {:user_counter => '0', :tag_counter => '0', :comment_counter => '0', :hit_counter => '0' }, :profile => @person.identifier
  56 + @block.reload
  57 + any_checked = @block.is_visible?('user_counter') ||
  58 + @block.is_visible?('tag_counter') ||
  59 + @block.is_visible?('comment_counter') ||
  60 + @block.is_visible?('hit_counter')
  61 + assert_equal false, any_checked
  62 + end
  63 +
  64 + should 'be able to check core counters' do
  65 + @block.user_counter = false
  66 + @block.community_counter = false
  67 + @block.enterprise_counter = false
  68 + @block.category_counter = false
  69 + @block.tag_counter = false
  70 + @block.comment_counter = false
  71 + @block.hit_counter = false
  72 + @block.save!
  73 + get :edit, :id => @block.id, :profile => @person.identifier
  74 + post :save, :id => @block.id, :block => {:user_counter => '1',
  75 + :tag_counter => '1', :comment_counter => '1', :hit_counter => '1' }, :profile => @person.identifier
  76 + @block.reload
  77 + all_checked = @block.is_visible?('user_counter') &&
  78 + @block.is_visible?('tag_counter') &&
  79 + @block.is_visible?('comment_counter') &&
  80 + @block.is_visible?('hit_counter')
  81 + assert all_checked
  82 +
  83 + end
  84 +
  85 +end
plugins/statistics/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/statistics/test/unit/statistics_block_test.rb 0 → 100644
@@ -0,0 +1,336 @@ @@ -0,0 +1,336 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +class StatisticsBlockTest < ActiveSupport::TestCase
  3 +
  4 + ['user_counter', 'tag_counter', 'comment_counter'].map do |counter|
  5 + should "#{counter} be true by default" do
  6 + b = StatisticsBlock.new
  7 + assert b.is_visible?(counter)
  8 + end
  9 + end
  10 +
  11 + ['community_counter', 'enterprise_counter', 'category_counter', 'hit_counter'].map do |counter|
  12 + should "#{counter} be false by default" do
  13 + b = StatisticsBlock.new
  14 + assert !b.is_visible?(counter)
  15 + end
  16 + end
  17 +
  18 + should 'inherit from Block' do
  19 + assert_kind_of Block, StatisticsBlock.new
  20 + end
  21 +
  22 + should 'provide a default title' do
  23 + block = StatisticsBlock.new
  24 +
  25 + owner = mock
  26 + owner.expects(:name).returns('my environment')
  27 + block.expects(:owner).returns(owner)
  28 + assert_equal 'Statistics for my environment', block.title
  29 + end
  30 +
  31 + should 'describe itself' do
  32 + assert_not_equal StatisticsBlock.description, Block.description
  33 + end
  34 +
  35 + should 'is_visible? return true if setting is true' do
  36 + b = StatisticsBlock.new
  37 + b.community_counter = true
  38 + assert b.is_visible?('community_counter')
  39 + end
  40 +
  41 + should 'is_visible? return false if setting is false' do
  42 + b = StatisticsBlock.new
  43 + b.community_counter = false
  44 + assert !b.is_visible?('community_counter')
  45 + end
  46 +
  47 + should 'templates return the Community templates of the Environment' do
  48 + b = StatisticsBlock.new
  49 + e = fast_create(Environment)
  50 +
  51 + t1 = fast_create(Community, :is_template => true, :environment_id => e.id)
  52 + t2 = fast_create(Community, :is_template => true, :environment_id => e.id)
  53 + fast_create(Community, :is_template => false)
  54 +
  55 + b.expects(:owner).at_least_once.returns(e)
  56 +
  57 + t = b.templates
  58 + assert_equal [], [t1,t2] - t
  59 + assert_equal [], t - [t1,t2]
  60 + end
  61 +
  62 + should 'users return the amount of users of the Environment' do
  63 + b = StatisticsBlock.new
  64 + e = fast_create(Environment)
  65 +
  66 + fast_create(Person, :environment_id => e.id)
  67 + fast_create(Person, :environment_id => e.id)
  68 + fast_create(Person, :visible => false, :environment_id => e.id)
  69 +
  70 + b.expects(:owner).at_least_once.returns(e)
  71 +
  72 + assert_equal 2, b.users
  73 + end
  74 +
  75 + should 'users return the amount of members of the community' do
  76 + b = StatisticsBlock.new
  77 +
  78 + c1 = fast_create(Community)
  79 + c1.add_member(fast_create(Person))
  80 + c1.add_member(fast_create(Person))
  81 + c1.add_member(fast_create(Person))
  82 + c1.add_member(fast_create(Person, :visible => false))
  83 + c1.add_member(fast_create(Person, :visible => false))
  84 +
  85 + b.expects(:owner).at_least_once.returns(c1)
  86 + assert_equal 3, b.users
  87 + end
  88 +
  89 + should 'users return the amount of friends of the person' do
  90 + b = StatisticsBlock.new
  91 +
  92 + p1 = fast_create(Person)
  93 + p1.add_friend(fast_create(Person))
  94 + p1.add_friend(fast_create(Person))
  95 + p1.add_friend(fast_create(Person))
  96 + p1.add_friend(fast_create(Person, :visible => false))
  97 + p1.add_friend(fast_create(Person, :visible => false))
  98 +
  99 + b.expects(:owner).at_least_once.returns(p1)
  100 + assert_equal 3, b.users
  101 + end
  102 +
  103 + should 'communities return the amount of communities of the Environment' do
  104 + b = StatisticsBlock.new
  105 + e = fast_create(Environment)
  106 +
  107 + fast_create(Community, :environment_id => e.id)
  108 + fast_create(Community, :environment_id => e.id)
  109 + fast_create(Community, :visible => false, :environment_id => e.id)
  110 +
  111 + b.expects(:owner).at_least_once.returns(e)
  112 +
  113 + assert_equal 2, b.communities
  114 + end
  115 +
  116 + should 'enterprises return the amount of enterprises of the Environment' do
  117 + b = StatisticsBlock.new
  118 + e = fast_create(Environment)
  119 +
  120 + fast_create(Enterprise, :environment_id => e.id)
  121 + fast_create(Enterprise, :environment_id => e.id)
  122 + fast_create(Enterprise, :visible => false, :environment_id => e.id)
  123 +
  124 + b.expects(:owner).at_least_once.returns(e)
  125 +
  126 + assert_equal 2, b.enterprises
  127 + end
  128 +
  129 + should 'categories return the amount of categories of the Environment' do
  130 + b = StatisticsBlock.new
  131 + e = fast_create(Environment)
  132 +
  133 + fast_create(Category, :environment_id => e.id)
  134 + fast_create(Category, :environment_id => e.id)
  135 +
  136 + b.expects(:owner).at_least_once.returns(e)
  137 +
  138 + assert_equal 2, b.categories
  139 + end
  140 +
  141 + should 'tags return the amount of tags of the Environment' do
  142 + b = StatisticsBlock.new
  143 + e = fast_create(Environment)
  144 +
  145 + p1 = fast_create(Person, :environment_id => e.id)
  146 + a1 = fast_create(Article, :profile_id => p1.id)
  147 + t1 = fast_create(Tag, :name => 'T1')
  148 + t2 = fast_create(Tag, :name => 'T2')
  149 + a1.tags << t1
  150 + a1.tags << t2
  151 + a2 = fast_create(Article, :profile_id => p1.id)
  152 + t3 = fast_create(Tag, :name => 'T3')
  153 + t4 = fast_create(Tag, :name => 'T4')
  154 + a2.tags << t3
  155 + a2.tags << t4
  156 +
  157 + b.expects(:owner).at_least_once.returns(e)
  158 +
  159 + assert_equal 4, b.tags
  160 + end
  161 +
  162 + should 'tags return the amount of tags of the community' do
  163 + b = StatisticsBlock.new
  164 + e = fast_create(Environment)
  165 +
  166 + c1 = fast_create(Community, :environment_id => e.id)
  167 + a1 = fast_create(Article, :profile_id => c1.id)
  168 + t1 = fast_create(Tag, :name => 'T1')
  169 + t2 = fast_create(Tag, :name => 'T2')
  170 + a1.tags << t1
  171 + a1.tags << t2
  172 + a2 = fast_create(Article, :profile_id => c1.id)
  173 + t3 = fast_create(Tag, :name => 'T3')
  174 + t4 = fast_create(Tag, :name => 'T4')
  175 + a2.tags << t3
  176 + a2.tags << t4
  177 +
  178 + b.expects(:owner).at_least_once.returns(c1)
  179 +
  180 + assert_equal 4, b.tags
  181 + end
  182 +
  183 + should 'tags return the amount of tags of the profile (person)' do
  184 + b = StatisticsBlock.new
  185 + e = fast_create(Environment)
  186 +
  187 + p1 = fast_create(Person, :environment_id => e.id)
  188 + a1 = fast_create(Article, :profile_id => p1.id)
  189 + t1 = fast_create(Tag, :name => 'T1')
  190 + t2 = fast_create(Tag, :name => 'T2')
  191 + a1.tags << t1
  192 + a1.tags << t2
  193 + a2 = fast_create(Article, :profile_id => p1.id)
  194 + t3 = fast_create(Tag, :name => 'T3')
  195 + t4 = fast_create(Tag, :name => 'T4')
  196 + a2.tags << t3
  197 + a2.tags << t4
  198 +
  199 + b.expects(:owner).at_least_once.returns(p1)
  200 +
  201 + assert_equal 4, b.tags
  202 + end
  203 +
  204 + should 'comments return the amount of comments of the Environment' do
  205 + b = StatisticsBlock.new
  206 + e = fast_create(Environment)
  207 +
  208 + p1 = fast_create(Person, :environment_id => e.id)
  209 + a1 = fast_create(Article, :profile_id => p1.id)
  210 +
  211 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  212 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  213 +
  214 + a2 = fast_create(Article, :profile_id => p1.id)
  215 + Comment.create!(:source => a2, :body => 'C3', :author_id => 1)
  216 + Comment.create!(:source => a2, :body => 'C4', :author_id => 1)
  217 +
  218 + b.expects(:owner).at_least_once.returns(e)
  219 +
  220 + assert_equal 4, b.comments
  221 + end
  222 +
  223 + should 'comments return the amount of comments of the community' do
  224 + b = StatisticsBlock.new
  225 + e = Environment.default
  226 +
  227 + c1 = fast_create(Community, :environment_id => e.id)
  228 + a1 = fast_create(Article, :profile_id => c1.id)
  229 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  230 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  231 +
  232 + a2 = fast_create(Article, :profile_id => c1.id)
  233 + Comment.create!(:source => a2, :body => 'C3', :author_id => 1)
  234 + Comment.create!(:source => a2, :body => 'C4', :author_id => 1)
  235 +
  236 + b.expects(:owner).at_least_once.returns(c1)
  237 +
  238 + assert_equal 4, b.comments
  239 + end
  240 +
  241 + should 'comments return the amount of comments of the profile (person)' do
  242 + b = StatisticsBlock.new
  243 + e = fast_create(Environment)
  244 +
  245 + p1 = fast_create(Person, :environment_id => e.id)
  246 + a1 = fast_create(Article, :profile_id => p1.id)
  247 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  248 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  249 +
  250 + a2 = fast_create(Article, :profile_id => p1.id)
  251 + Comment.create!(:source => a1, :body => 'C3', :author_id => 1)
  252 + Comment.create!(:source => a1, :body => 'C4', :author_id => 1)
  253 +
  254 + b.expects(:owner).at_least_once.returns(p1)
  255 +
  256 + assert_equal 4, b.comments
  257 + end
  258 +
  259 + should 'hits return the amount of hits of the Environment' do
  260 + b = StatisticsBlock.new
  261 + e = fast_create(Environment)
  262 +
  263 + p1 = fast_create(Person, :environment_id => e.id)
  264 + a1 = fast_create(Article, :profile_id => p1.id, :hits => 2)
  265 + a2 = fast_create(Article, :profile_id => p1.id, :hits => 5)
  266 +
  267 + b.expects(:owner).at_least_once.returns(e)
  268 +
  269 + assert_equal 7, b.hits
  270 + end
  271 +
  272 + should 'hits return the amount of hits of the community' do
  273 + b = StatisticsBlock.new
  274 + e = fast_create(Environment)
  275 +
  276 + c1 = fast_create(Community, :environment_id => e.id)
  277 + a1 = fast_create(Article, :profile_id => c1.id, :hits => 2)
  278 + a2 = fast_create(Article, :profile_id => c1.id, :hits => 5)
  279 +
  280 + b.expects(:owner).at_least_once.returns(c1)
  281 +
  282 + assert_equal 7, b.hits
  283 + end
  284 +
  285 + should 'hits return the amount of hits of the profile (person)' do
  286 + b = StatisticsBlock.new
  287 + e = fast_create(Environment)
  288 +
  289 + p1 = fast_create(Person, :environment_id => e.id)
  290 + a1 = fast_create(Article, :profile_id => p1.id, :hits => 2)
  291 + a2 = fast_create(Article, :profile_id => p1.id, :hits => 5)
  292 +
  293 + b.expects(:owner).at_least_once.returns(p1)
  294 +
  295 + assert_equal 7, b.hits
  296 + end
  297 +
  298 + should 'is_counter_available? return true for all counters if owner is environment' do
  299 + b = StatisticsBlock.new
  300 + e = fast_create(Environment)
  301 +
  302 + b.expects(:owner).at_least_once.returns(e)
  303 +
  304 + assert b.is_counter_available?(:user_counter)
  305 + end
  306 +
  307 + should 'is_template_counter_active? return true if setting is true' do
  308 + b = StatisticsBlock.new
  309 + b.templates_ids_counter = {'1' => 'true'}
  310 + assert b.is_template_counter_active?(1)
  311 + end
  312 +
  313 + should 'is_template_counter_active? return false if setting is false' do
  314 + b = StatisticsBlock.new
  315 + b.templates_ids_counter = {'1' => 'false'}
  316 + assert !b.is_template_counter_active?(1)
  317 + end
  318 +
  319 + should 'template_counter_count return the amount of communities of the Environment using a template' do
  320 + b = StatisticsBlock.new
  321 + e = fast_create(Environment)
  322 +
  323 + t1 = fast_create(Community, :is_template => true, :environment_id => e.id)
  324 + t2 = fast_create(Community, :is_template => true, :environment_id => e.id)
  325 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => true)
  326 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => true)
  327 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => false)
  328 +
  329 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t2.id, :visible => true)
  330 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t2.id, :visible => false)
  331 +
  332 + b.expects(:owner).at_least_once.returns(e)
  333 +
  334 + assert_equal 2, b.template_counter_count(t1.id)
  335 + end
  336 +end
plugins/statistics/test/unit/statistics_plugin_test.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class StatisticsPluginTest < ActiveSupport::TestCase
  4 +
  5 + should "return StatisticsBlock in extra_mlocks class method" do
  6 + assert StatisticsPlugin.extra_blocks.keys.include?(StatisticsBlock)
  7 + end
  8 +
  9 +end
plugins/statistics/views/box_organizer/_statistics_block.rhtml 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<%= labelled_form_field check_box(:block, :user_counter) + _('Show user counter'), '' %>
  2 +
  3 +<% if @block.is_counter_available?(:community_counter) %>
  4 +<%= labelled_form_field check_box(:block, :community_counter) + _('Show community counter'), '' %>
  5 +<% end %>
  6 +
  7 +<% if @block.is_counter_available?(:enterprise_counter) %>
  8 +<%= labelled_form_field check_box(:block, :enterprise_counter) + _('Show enterprise counter'), '' %>
  9 +<% end %>
  10 +
  11 +<% if @block.is_counter_available?(:category_counter) %>
  12 +<%= labelled_form_field check_box(:block, :category_counter) + _('Show category counter'), '' %>
  13 +<% end %>
  14 +
  15 +<% if @block.is_counter_available?(:tag_counter) %>
  16 +<%= labelled_form_field check_box(:block, :tag_counter) + _('Show tag counter'), '' %>
  17 +<% end %>
  18 +
  19 +<% if @block.is_counter_available?(:comment_counter) %>
  20 +<%= labelled_form_field check_box(:block, :comment_counter) + _('Show comment counter'), '' %>
  21 +<% end %>
  22 +
  23 +<% if @block.is_counter_available?(:hit_counter) %>
  24 +<%= labelled_form_field check_box(:block, :hit_counter) + _('Show hit counter'), '' %>
  25 +<% end %>
  26 +
  27 +<% if @block.is_counter_available?(:templates_ids_counter) %>
  28 +<% @block.templates.map do |item|%>
  29 + <%= hidden_field_tag("block[templates_ids_counter][#{item.id}]", false)%>
  30 + <%= labelled_form_field check_box_tag("block[templates_ids_counter][#{item.id}]", true, @block.is_template_counter_active?(item.id)) + _("Show counter for communities with template %s" % item.name), '' %>
  31 +<% end %>
  32 +<% end %>
plugins/statistics/views/environment_design 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +box_organizer
0 \ No newline at end of file 2 \ No newline at end of file
plugins/statistics/views/profile_design 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +box_organizer
0 \ No newline at end of file 2 \ No newline at end of file
plugins/statistics/views/statistics_block.rhtml 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +<h3 class="block-title">
  2 + <span><%=block.title%></span>
  3 +</h3>
  4 +<div class="statistics-block-data">
  5 + <ul>
  6 + <% if block.is_visible?('user_counter') %>
  7 + <li class="users"><span class="amount"><%= block.users%> </span><span class="label"><%= _('users')%></span></li>
  8 + <% end %>
  9 + <% if block.is_visible?('enterprise_counter') && !block.environment.enabled?('disable_asset_enterprises') %>
  10 + <li class="enterprises"><span class="amount"><%= block.enterprises%> </span><span class="label"><%= _('enterprises')%></span></li>
  11 + <% end %>
  12 + <% if block.is_visible?('community_counter') %>
  13 + <li class="communities"><span class="amount"><%= block.communities%> </span><span class="label"><%= _('communities')%></span></li>
  14 + <% end %>
  15 + <% if block.is_visible?('category_counter') %>
  16 + <li class="categories"><span class="amount"><%= block.categories%> </span><span class="label"><%= _('categories')%></span></li>
  17 + <% end %>
  18 + <% if block.is_visible?('tag_counter') %>
  19 + <li class="tags"><span class="amount"><%= block.tags%> </span><span class="label"><%= _('tags')%></span></li>
  20 + <% end %>
  21 + <% if block.is_visible?('comment_counter') %>
  22 + <li class="comments"><span class="amount"><%= block.comments%> </span><span class="label"><%= _('comments')%></span></li>
  23 + <% end %>
  24 + <% if block.is_visible?('hit_counter') %>
  25 + <li class="hits"><span class="amount"><%= block.hits%> </span><span class="label"><%= _('hits')%></span></li>
  26 + <% end %>
  27 +
  28 + <% if block.owner.kind_of?(Environment) then %>
  29 + <% block.templates.each do |item| %>
  30 + <% if block.is_template_counter_active? item.id %>
  31 + <li class="<%= item.name.to_slug%>"><span class="amount"><%= block.template_counter_count(item.id)%> </span><span class="label"><%= item.name%></span></li>
  32 + <% end %>
  33 + <% end %>
  34 + <% end %>
  35 + </ul>
  36 +</div>
plugins/tolerance_time/lib/tolerance_time_plugin/publication.rb
@@ -5,8 +5,7 @@ class ToleranceTimePlugin::Publication &lt; Noosfero::Plugin::ActiveRecord @@ -5,8 +5,7 @@ class ToleranceTimePlugin::Publication &lt; Noosfero::Plugin::ActiveRecord
5 5
6 class << self 6 class << self
7 def find_by_target(target) 7 def find_by_target(target)
8 - kind = target.kind_of?(Article) ? 'Article' : 'Comment'  
9 - find_by_target_id_and_target_type(target.id, kind) 8 + find_by_target_id_and_target_type(target.id, target.class.base_class.name)
10 end 9 end
11 end 10 end
12 11
plugins/variables/doc/variables.textile 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +h1. Variables Plugin
  2 +
  3 +A set of simple variables to be used in a macro context.
  4 +
  5 +h2. Usage
  6 +
  7 +* Create a HTML content using RawHTMLBlock, TinyMceArticle or other
  8 + article with HTML support
  9 +* Add a HTML div tag with css class "macro" (see Example)
  10 +* Add inner that div tag the variable desired, like {profile}
  11 +
  12 +h2. Usage with TinyMceArticle
  13 +
  14 +The Noosfero's macros add a extra button in toolbar of the editor
  15 +to use macros in a single way, that way this plugin add a option
  16 +called "Variables" under this option.
  17 +
  18 +h2. Supported variables
  19 +
  20 +* {profile} - will be replaced by the identifier of the profile
  21 +* {name} - will be replaced by the name of the profile
  22 +
  23 +h2. Example
  24 +
  25 +<pre>
  26 +<div class="macro" data-macro="variables_plugin/profile">
  27 + the identifier of the profile = {profile}
  28 + the name of the profile = {name}
  29 +</div>
  30 +</pre>
  31 +
  32 +h2. Info
  33 +
  34 +This plugin was inspired by the solution proposed by the Serpro in
  35 +the merge-request #419 on the Gitorious:
  36 +
  37 +* https://gitorious.org/noosfero/noosfero/merge_requests/419
  38 +
  39 +And improved by the guys from the UnB.
plugins/variables/lib/variables_plugin.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class VariablesPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "Variables Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A set of simple variables to be used in a macro context")
  9 + end
  10 +
  11 +end
  12 +
  13 +require_dependency 'variables_plugin/macros/profile'
plugins/variables/lib/variables_plugin/macros/profile.rb 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +ActionView::Base.sanitized_allowed_attributes += ['data-macro']
  2 +
  3 +class VariablesPlugin::Profile < Noosfero::Plugin::Macro
  4 +
  5 + def self.configuration
  6 + {
  7 + :title => _('Variables'),
  8 + :skip_dialog => false,
  9 + :generator => method(:macro_default_generator),
  10 + :params => [
  11 + {
  12 + :name => 'variable',
  13 + :label => _('Select the desired variable'),
  14 + :type => 'select',
  15 + :values => ['{profile}', '{name}']
  16 + }
  17 + ],
  18 + }
  19 + end
  20 +
  21 + def self.macro_default_generator(macro)
  22 + "
  23 + '<div class=\"macro mceNonEditable\" data-macro=\"#{macro.identifier}\">'
  24 + + jQuery('*[name=variable]', dialog).val()
  25 + + '</div>';
  26 + "
  27 + end
  28 +
  29 + def parse(params, inner_html, source)
  30 + if context.profile
  31 + inner_html.gsub!(/\{profile\}/, context.profile.identifier)
  32 + inner_html.gsub!(/\{name\}/, context.profile.name)
  33 + end
  34 + inner_html
  35 + end
  36 +
  37 +end
plugins/variables/test/unit/profile_test.rb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +class ProfileTest < ActiveSupport::TestCase
  2 +
  3 + def setup
  4 + @macro = VariablesPlugin::Profile.new
  5 + @macro.context = mock()
  6 + @profile = fast_create(Community)
  7 + @macro.context.stubs(:profile).returns(@profile)
  8 + end
  9 +
  10 + attr_reader :macro, :profile
  11 +
  12 + should 'have a configuration' do
  13 + assert VariablesPlugin::Profile.configuration
  14 + end
  15 +
  16 + should 'substitute the {profile} variable by the profile idenfifier' do
  17 + html = 'the profile identifier is {profile}'
  18 + content = macro.parse({}, html, profile)
  19 + assert_equal "the profile identifier is #{profile.identifier}", content
  20 + end
  21 +
  22 + should 'substitute the {name} variable by the profile name' do
  23 + html = 'the profile name is {name}'
  24 + content = macro.parse({}, html, profile)
  25 + assert_equal "the profile name is #{profile.name}", content
  26 + end
  27 +
  28 + should 'do not change the content if the variable is not supported' do
  29 + html = 'the variable {unsupported} is not supported'
  30 + content = macro.parse({}, html, profile)
  31 + assert_equal html, content
  32 + end
  33 +
  34 + should 'do nothing out of profile context' do
  35 + macro.context.stubs(:profile).returns(nil)
  36 + html = 'there is no {support} out of profile context'
  37 + content = macro.parse({}, html, profile)
  38 + assert_equal html, content
  39 + end
  40 +
  41 +end
plugins/variables/test/unit/variables_plugin_test.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +require 'test_helper'
  2 +
  3 +class VariablesPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + @plugin = VariablesPlugin.new
  8 + end
  9 +
  10 + attr_reader :environment, :plugin
  11 +
  12 + should 'have a name' do
  13 + assert_not_equal Noosfero::Plugin.plugin_name, VariablesPlugin::plugin_name
  14 + end
  15 +
  16 + should 'describe yourself' do
  17 + assert_not_equal Noosfero::Plugin.plugin_description, VariablesPlugin::plugin_description
  18 + end
  19 +
  20 +end
po/eo/noosfero.po
@@ -7,7 +7,7 @@ msgid &quot;&quot; @@ -7,7 +7,7 @@ msgid &quot;&quot;
7 msgstr "" 7 msgstr ""
8 "Project-Id-Version: noosfero 0.45.2\n" 8 "Project-Id-Version: noosfero 0.45.2\n"
9 "POT-Creation-Date: 2014-01-17 18:26-0000\n" 9 "POT-Creation-Date: 2014-01-17 18:26-0000\n"
10 -"PO-Revision-Date: 2011-03-30 20:52-0300\n" 10 +"PO-Revision-Date: 2014-03-25 15:35+0000\n"
11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Language-Team: LANGUAGE <LL@li.org>\n" 12 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language: eo\n" 13 "Language: eo\n"
@@ -107,7 +107,7 @@ msgstr &quot;&quot; @@ -107,7 +107,7 @@ msgstr &quot;&quot;
107 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:25 107 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:25
108 #: app/views/profile/_private_profile.rhtml:10 108 #: app/views/profile/_private_profile.rhtml:10
109 msgid "Join" 109 msgid "Join"
110 -msgstr "" 110 +msgstr "Eniri"
111 111
112 #: app/helpers/application_helper.rb:554 112 #: app/helpers/application_helper.rb:554
113 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:4 113 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:4
@@ -291,7 +291,7 @@ msgstr &quot;&quot; @@ -291,7 +291,7 @@ msgstr &quot;&quot;
291 291
292 #: app/helpers/application_helper.rb:1118 292 #: app/helpers/application_helper.rb:1118
293 msgid "See all" 293 msgid "See all"
294 -msgstr "" 294 +msgstr "Vidi ĉiujn"
295 295
296 #: app/helpers/application_helper.rb:1121 296 #: app/helpers/application_helper.rb:1121
297 msgid "<span>Manage</span> %s" 297 msgid "<span>Manage</span> %s"
@@ -678,11 +678,11 @@ msgstr &quot;&quot; @@ -678,11 +678,11 @@ msgstr &quot;&quot;
678 678
679 #: app/helpers/forum_helper.rb:14 app/helpers/blog_helper.rb:23 679 #: app/helpers/forum_helper.rb:14 app/helpers/blog_helper.rb:23
680 msgid "&laquo; Newer posts" 680 msgid "&laquo; Newer posts"
681 -msgstr "" 681 +msgstr "&laquo; Pli freŝaj afiŝoj"
682 682
683 #: app/helpers/forum_helper.rb:15 app/helpers/blog_helper.rb:24 683 #: app/helpers/forum_helper.rb:15 app/helpers/blog_helper.rb:24
684 msgid "Older posts &raquo;" 684 msgid "Older posts &raquo;"
685 -msgstr "" 685 +msgstr "Malpli freŝaj afiŝoj &raquo"
686 686
687 #: app/helpers/forum_helper.rb:18 687 #: app/helpers/forum_helper.rb:18
688 msgid "Discussion topic" 688 msgid "Discussion topic"
@@ -763,63 +763,63 @@ msgstr &quot;&quot; @@ -763,63 +763,63 @@ msgstr &quot;&quot;
763 #: app/helpers/dates_helper.rb:7 app/helpers/forms_helper.rb:172 763 #: app/helpers/dates_helper.rb:7 app/helpers/forms_helper.rb:172
764 #: plugins/display_content/lib/display_content_block.rb:4 764 #: plugins/display_content/lib/display_content_block.rb:4
765 msgid "January" 765 msgid "January"
766 -msgstr "" 766 +msgstr "Januaro"
767 767
768 #: app/helpers/dates_helper.rb:8 app/helpers/forms_helper.rb:172 768 #: app/helpers/dates_helper.rb:8 app/helpers/forms_helper.rb:172
769 #: plugins/display_content/lib/display_content_block.rb:5 769 #: plugins/display_content/lib/display_content_block.rb:5
770 msgid "February" 770 msgid "February"
771 -msgstr "" 771 +msgstr "Februaro"
772 772
773 #: app/helpers/dates_helper.rb:9 app/helpers/forms_helper.rb:172 773 #: app/helpers/dates_helper.rb:9 app/helpers/forms_helper.rb:172
774 #: plugins/display_content/lib/display_content_block.rb:6 774 #: plugins/display_content/lib/display_content_block.rb:6
775 msgid "March" 775 msgid "March"
776 -msgstr "" 776 +msgstr "Marto"
777 777
778 #: app/helpers/dates_helper.rb:10 app/helpers/forms_helper.rb:172 778 #: app/helpers/dates_helper.rb:10 app/helpers/forms_helper.rb:172
779 #: plugins/display_content/lib/display_content_block.rb:7 779 #: plugins/display_content/lib/display_content_block.rb:7
780 msgid "April" 780 msgid "April"
781 -msgstr "" 781 +msgstr "Aprilo"
782 782
783 #: app/helpers/dates_helper.rb:11 app/helpers/forms_helper.rb:172 783 #: app/helpers/dates_helper.rb:11 app/helpers/forms_helper.rb:172
784 #: app/helpers/forms_helper.rb:173 784 #: app/helpers/forms_helper.rb:173
785 #: plugins/display_content/lib/display_content_block.rb:8 785 #: plugins/display_content/lib/display_content_block.rb:8
786 msgid "May" 786 msgid "May"
787 -msgstr "" 787 +msgstr "Majo"
788 788
789 #: app/helpers/dates_helper.rb:12 app/helpers/forms_helper.rb:172 789 #: app/helpers/dates_helper.rb:12 app/helpers/forms_helper.rb:172
790 #: plugins/display_content/lib/display_content_block.rb:9 790 #: plugins/display_content/lib/display_content_block.rb:9
791 msgid "June" 791 msgid "June"
792 -msgstr "" 792 +msgstr "Junio"
793 793
794 #: app/helpers/dates_helper.rb:13 app/helpers/forms_helper.rb:172 794 #: app/helpers/dates_helper.rb:13 app/helpers/forms_helper.rb:172
795 #: plugins/display_content/lib/display_content_block.rb:10 795 #: plugins/display_content/lib/display_content_block.rb:10
796 msgid "July" 796 msgid "July"
797 -msgstr "" 797 +msgstr "Julio"
798 798
799 #: app/helpers/dates_helper.rb:14 app/helpers/forms_helper.rb:172 799 #: app/helpers/dates_helper.rb:14 app/helpers/forms_helper.rb:172
800 #: plugins/display_content/lib/display_content_block.rb:11 800 #: plugins/display_content/lib/display_content_block.rb:11
801 msgid "August" 801 msgid "August"
802 -msgstr "" 802 +msgstr "Aŭgusto"
803 803
804 #: app/helpers/dates_helper.rb:15 app/helpers/forms_helper.rb:172 804 #: app/helpers/dates_helper.rb:15 app/helpers/forms_helper.rb:172
805 #: plugins/display_content/lib/display_content_block.rb:12 805 #: plugins/display_content/lib/display_content_block.rb:12
806 msgid "September" 806 msgid "September"
807 -msgstr "" 807 +msgstr "Septembro"
808 808
809 #: app/helpers/dates_helper.rb:16 app/helpers/forms_helper.rb:172 809 #: app/helpers/dates_helper.rb:16 app/helpers/forms_helper.rb:172
810 #: plugins/display_content/lib/display_content_block.rb:13 810 #: plugins/display_content/lib/display_content_block.rb:13
811 msgid "October" 811 msgid "October"
812 -msgstr "" 812 +msgstr "Oktobro"
813 813
814 #: app/helpers/dates_helper.rb:17 app/helpers/forms_helper.rb:172 814 #: app/helpers/dates_helper.rb:17 app/helpers/forms_helper.rb:172
815 #: plugins/display_content/lib/display_content_block.rb:14 815 #: plugins/display_content/lib/display_content_block.rb:14
816 msgid "November" 816 msgid "November"
817 -msgstr "" 817 +msgstr "Novembro"
818 818
819 #: app/helpers/dates_helper.rb:18 app/helpers/forms_helper.rb:172 819 #: app/helpers/dates_helper.rb:18 app/helpers/forms_helper.rb:172
820 #: plugins/display_content/lib/display_content_block.rb:15 820 #: plugins/display_content/lib/display_content_block.rb:15
821 msgid "December" 821 msgid "December"
822 -msgstr "" 822 +msgstr "Decembro"
823 823
824 #: app/helpers/dates_helper.rb:28 824 #: app/helpers/dates_helper.rb:28
825 #: plugins/display_content/lib/display_content_block.rb:153 825 #: plugins/display_content/lib/display_content_block.rb:153
@@ -834,7 +834,7 @@ msgstr &quot;&quot; @@ -834,7 +834,7 @@ msgstr &quot;&quot;
834 #: app/helpers/dates_helper.rb:31 834 #: app/helpers/dates_helper.rb:31
835 #: plugins/display_content/lib/display_content_block.rb:156 835 #: plugins/display_content/lib/display_content_block.rb:156
836 msgid "%{month_name} %{day}, %{year}" 836 msgid "%{month_name} %{day}, %{year}"
837 -msgstr "" 837 +msgstr "La %{day}-a de %{month_name} %{year}"
838 838
839 #: app/helpers/dates_helper.rb:31 839 #: app/helpers/dates_helper.rb:31
840 #: plugins/display_content/lib/display_content_block.rb:156 840 #: plugins/display_content/lib/display_content_block.rb:156
@@ -8043,7 +8043,7 @@ msgstr &quot;&quot; @@ -8043,7 +8043,7 @@ msgstr &quot;&quot;
8043 8043
8044 #: app/views/account/index_anonymous.rhtml:10 8044 #: app/views/account/index_anonymous.rhtml:10
8045 msgid "Sign up." 8045 msgid "Sign up."
8046 -msgstr "" 8046 +msgstr "Aliĝi"
8047 8047
8048 #: app/views/account/index_anonymous.rhtml:11 8048 #: app/views/account/index_anonymous.rhtml:11
8049 msgid "" 8049 msgid ""
po/es/noosfero.po
@@ -7,7 +7,7 @@ msgid &quot;&quot; @@ -7,7 +7,7 @@ msgid &quot;&quot;
7 msgstr "" 7 msgstr ""
8 "Project-Id-Version: noosfero 0.45.2\n" 8 "Project-Id-Version: noosfero 0.45.2\n"
9 "POT-Creation-Date: 2014-01-17 18:26-0000\n" 9 "POT-Creation-Date: 2014-01-17 18:26-0000\n"
10 -"PO-Revision-Date: 2013-01-03 18:39-0300\n" 10 +"PO-Revision-Date: 2014-03-25 14:55+0000\n"
11 "Last-Translator: Luis David Aguilar Carlos <ludwig9003@gmail.com>,Freddy " 11 "Last-Translator: Luis David Aguilar Carlos <ludwig9003@gmail.com>,Freddy "
12 "Martín Hernández Facio <fmhf14@gmail.com>, Pedro Alonzo Ramírez Tovar <pedro." 12 "Martín Hernández Facio <fmhf14@gmail.com>, Pedro Alonzo Ramírez Tovar <pedro."
13 "alonzo709@gmail.com>\n" 13 "alonzo709@gmail.com>\n"
@@ -292,7 +292,6 @@ msgid &quot;Next&quot; @@ -292,7 +292,6 @@ msgid &quot;Next&quot;
292 msgstr "Siguiente" 292 msgstr "Siguiente"
293 293
294 #: app/helpers/application_helper.rb:1118 294 #: app/helpers/application_helper.rb:1118
295 -#, fuzzy  
296 msgid "See all" 295 msgid "See all"
297 msgstr "Ver todos" 296 msgstr "Ver todos"
298 297
@@ -690,11 +689,11 @@ msgstr &quot;Configurar foro&quot; @@ -690,11 +689,11 @@ msgstr &quot;Configurar foro&quot;
690 689
691 #: app/helpers/forum_helper.rb:14 app/helpers/blog_helper.rb:23 690 #: app/helpers/forum_helper.rb:14 app/helpers/blog_helper.rb:23
692 msgid "&laquo; Newer posts" 691 msgid "&laquo; Newer posts"
693 -msgstr "&laquo; Entradas recientes" 692 +msgstr "&laquo; Noticias más nuevas"
694 693
695 #: app/helpers/forum_helper.rb:15 app/helpers/blog_helper.rb:24 694 #: app/helpers/forum_helper.rb:15 app/helpers/blog_helper.rb:24
696 msgid "Older posts &raquo;" 695 msgid "Older posts &raquo;"
697 -msgstr "Entradas antiguas &raquo;" 696 +msgstr "Noticias más viejas &raquo;"
698 697
699 #: app/helpers/forum_helper.rb:18 698 #: app/helpers/forum_helper.rb:18
700 msgid "Discussion topic" 699 msgid "Discussion topic"
@@ -841,15 +840,13 @@ msgstr &quot;%{day} de %{month} %{year}&quot; @@ -841,15 +840,13 @@ msgstr &quot;%{day} de %{month} %{year}&quot;
841 840
842 #: app/helpers/dates_helper.rb:28 app/helpers/dates_helper.rb:40 841 #: app/helpers/dates_helper.rb:28 app/helpers/dates_helper.rb:40
843 #: plugins/display_content/lib/display_content_block.rb:153 842 #: plugins/display_content/lib/display_content_block.rb:153
844 -#, fuzzy  
845 msgid "%{month}/%{day}" 843 msgid "%{month}/%{day}"
846 -msgstr "%{day} de %{month} %{year}" 844 +msgstr "%{day}/%{month}"
847 845
848 #: app/helpers/dates_helper.rb:31 846 #: app/helpers/dates_helper.rb:31
849 #: plugins/display_content/lib/display_content_block.rb:156 847 #: plugins/display_content/lib/display_content_block.rb:156
850 -#, fuzzy  
851 msgid "%{month_name} %{day}, %{year}" 848 msgid "%{month_name} %{day}, %{year}"
852 -msgstr "%{day} de %{month} %{year}" 849 +msgstr "%{day} de %{month} de %{year}"
853 850
854 # LAs cadenas de este tipo NO se traducen 851 # LAs cadenas de este tipo NO se traducen
855 #: app/helpers/dates_helper.rb:31 852 #: app/helpers/dates_helper.rb:31
@@ -877,21 +874,19 @@ msgstr &quot;%{month} %{year}&quot; @@ -877,21 +874,19 @@ msgstr &quot;%{month} %{year}&quot;
877 874
878 #: app/helpers/dates_helper.rb:53 875 #: app/helpers/dates_helper.rb:53
879 msgid "%{day} %{month} %{year}, %{hour}:%{minutes}" 876 msgid "%{day} %{month} %{year}, %{hour}:%{minutes}"
880 -msgstr "%{day} %{month} %{year}, %{hour}:%{minutes}" 877 +msgstr "%{day} de %{month} de %{year}, %{hour}:%{minutes}"
881 878
882 #: app/helpers/dates_helper.rb:65 879 #: app/helpers/dates_helper.rb:65
883 -#, fuzzy  
884 msgid "from %{month} %{day1} to %{day2}, %{year}" 880 msgid "from %{month} %{day1} to %{day2}, %{year}"
885 -msgstr "%{day} de %{month} %{year}" 881 +msgstr "de %{day1} para %{day2} de %{month} de %{year}"
886 882
887 #: app/helpers/dates_helper.rb:72 883 #: app/helpers/dates_helper.rb:72
888 -#, fuzzy  
889 msgid "from %{date1} to %{date2}, %{year}" 884 msgid "from %{date1} to %{date2}, %{year}"
890 -msgstr "Por %{author} el %{date}" 885 +msgstr "de %{date1} para %{date2} de %{year}"
891 886
892 #: app/helpers/dates_helper.rb:79 887 #: app/helpers/dates_helper.rb:79
893 msgid "from %{date1} to %{date2}" 888 msgid "from %{date1} to %{date2}"
894 -msgstr "Por %{author} el %{date}" 889 +msgstr "de %{date1} para %{date2}"
895 890
896 #: app/helpers/dates_helper.rb:89 app/helpers/forms_helper.rb:163 891 #: app/helpers/dates_helper.rb:89 app/helpers/forms_helper.rb:163
897 msgid "Sun" 892 msgid "Sun"
po/it/noosfero.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: noosfero 0.45.2\n" 9 "Project-Id-Version: noosfero 0.45.2\n"
10 "POT-Creation-Date: 2014-01-17 18:26-0000\n" 10 "POT-Creation-Date: 2014-01-17 18:26-0000\n"
11 -"PO-Revision-Date: 2012-06-05 10:27-0300\n" 11 +"PO-Revision-Date: 2014-03-25 15:39+0000\n"
12 "Last-Translator: Daniela Feitosa <danielafeitosa@colivre.coop.br>\n" 12 "Last-Translator: Daniela Feitosa <danielafeitosa@colivre.coop.br>\n"
13 "Language-Team: LANGUAGE TEAM <LL@li.org>\n" 13 "Language-Team: LANGUAGE TEAM <LL@li.org>\n"
14 "Language: it\n" 14 "Language: it\n"
@@ -109,7 +109,7 @@ msgstr &quot;&quot; @@ -109,7 +109,7 @@ msgstr &quot;&quot;
109 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:25 109 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:25
110 #: app/views/profile/_private_profile.rhtml:10 110 #: app/views/profile/_private_profile.rhtml:10
111 msgid "Join" 111 msgid "Join"
112 -msgstr "" 112 +msgstr "Accedere"
113 113
114 #: app/helpers/application_helper.rb:554 114 #: app/helpers/application_helper.rb:554
115 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:4 115 #: app/views/blocks/profile_info_actions/_join_leave_community.rhtml:4
@@ -752,63 +752,63 @@ msgstr &quot;&quot; @@ -752,63 +752,63 @@ msgstr &quot;&quot;
752 #: app/helpers/dates_helper.rb:7 app/helpers/forms_helper.rb:172 752 #: app/helpers/dates_helper.rb:7 app/helpers/forms_helper.rb:172
753 #: plugins/display_content/lib/display_content_block.rb:4 753 #: plugins/display_content/lib/display_content_block.rb:4
754 msgid "January" 754 msgid "January"
755 -msgstr "" 755 +msgstr "gennaio"
756 756
757 #: app/helpers/dates_helper.rb:8 app/helpers/forms_helper.rb:172 757 #: app/helpers/dates_helper.rb:8 app/helpers/forms_helper.rb:172
758 #: plugins/display_content/lib/display_content_block.rb:5 758 #: plugins/display_content/lib/display_content_block.rb:5
759 msgid "February" 759 msgid "February"
760 -msgstr "" 760 +msgstr "febbraio"
761 761
762 #: app/helpers/dates_helper.rb:9 app/helpers/forms_helper.rb:172 762 #: app/helpers/dates_helper.rb:9 app/helpers/forms_helper.rb:172
763 #: plugins/display_content/lib/display_content_block.rb:6 763 #: plugins/display_content/lib/display_content_block.rb:6
764 msgid "March" 764 msgid "March"
765 -msgstr "" 765 +msgstr "marzo"
766 766
767 #: app/helpers/dates_helper.rb:10 app/helpers/forms_helper.rb:172 767 #: app/helpers/dates_helper.rb:10 app/helpers/forms_helper.rb:172
768 #: plugins/display_content/lib/display_content_block.rb:7 768 #: plugins/display_content/lib/display_content_block.rb:7
769 msgid "April" 769 msgid "April"
770 -msgstr "" 770 +msgstr "aprile"
771 771
772 #: app/helpers/dates_helper.rb:11 app/helpers/forms_helper.rb:172 772 #: app/helpers/dates_helper.rb:11 app/helpers/forms_helper.rb:172
773 #: app/helpers/forms_helper.rb:173 773 #: app/helpers/forms_helper.rb:173
774 #: plugins/display_content/lib/display_content_block.rb:8 774 #: plugins/display_content/lib/display_content_block.rb:8
775 msgid "May" 775 msgid "May"
776 -msgstr "" 776 +msgstr "maggio"
777 777
778 #: app/helpers/dates_helper.rb:12 app/helpers/forms_helper.rb:172 778 #: app/helpers/dates_helper.rb:12 app/helpers/forms_helper.rb:172
779 #: plugins/display_content/lib/display_content_block.rb:9 779 #: plugins/display_content/lib/display_content_block.rb:9
780 msgid "June" 780 msgid "June"
781 -msgstr "" 781 +msgstr "giugno"
782 782
783 #: app/helpers/dates_helper.rb:13 app/helpers/forms_helper.rb:172 783 #: app/helpers/dates_helper.rb:13 app/helpers/forms_helper.rb:172
784 #: plugins/display_content/lib/display_content_block.rb:10 784 #: plugins/display_content/lib/display_content_block.rb:10
785 msgid "July" 785 msgid "July"
786 -msgstr "" 786 +msgstr "luglio"
787 787
788 #: app/helpers/dates_helper.rb:14 app/helpers/forms_helper.rb:172 788 #: app/helpers/dates_helper.rb:14 app/helpers/forms_helper.rb:172
789 #: plugins/display_content/lib/display_content_block.rb:11 789 #: plugins/display_content/lib/display_content_block.rb:11
790 msgid "August" 790 msgid "August"
791 -msgstr "" 791 +msgstr "agosto"
792 792
793 #: app/helpers/dates_helper.rb:15 app/helpers/forms_helper.rb:172 793 #: app/helpers/dates_helper.rb:15 app/helpers/forms_helper.rb:172
794 #: plugins/display_content/lib/display_content_block.rb:12 794 #: plugins/display_content/lib/display_content_block.rb:12
795 msgid "September" 795 msgid "September"
796 -msgstr "" 796 +msgstr "settembre"
797 797
798 #: app/helpers/dates_helper.rb:16 app/helpers/forms_helper.rb:172 798 #: app/helpers/dates_helper.rb:16 app/helpers/forms_helper.rb:172
799 #: plugins/display_content/lib/display_content_block.rb:13 799 #: plugins/display_content/lib/display_content_block.rb:13
800 msgid "October" 800 msgid "October"
801 -msgstr "" 801 +msgstr "ottobre"
802 802
803 #: app/helpers/dates_helper.rb:17 app/helpers/forms_helper.rb:172 803 #: app/helpers/dates_helper.rb:17 app/helpers/forms_helper.rb:172
804 #: plugins/display_content/lib/display_content_block.rb:14 804 #: plugins/display_content/lib/display_content_block.rb:14
805 msgid "November" 805 msgid "November"
806 -msgstr "" 806 +msgstr "novembre"
807 807
808 #: app/helpers/dates_helper.rb:18 app/helpers/forms_helper.rb:172 808 #: app/helpers/dates_helper.rb:18 app/helpers/forms_helper.rb:172
809 #: plugins/display_content/lib/display_content_block.rb:15 809 #: plugins/display_content/lib/display_content_block.rb:15
810 msgid "December" 810 msgid "December"
811 -msgstr "" 811 +msgstr "dicembre"
812 812
813 #: app/helpers/dates_helper.rb:28 813 #: app/helpers/dates_helper.rb:28
814 #: plugins/display_content/lib/display_content_block.rb:153 814 #: plugins/display_content/lib/display_content_block.rb:153
@@ -823,7 +823,7 @@ msgstr &quot;&quot; @@ -823,7 +823,7 @@ msgstr &quot;&quot;
823 #: app/helpers/dates_helper.rb:31 823 #: app/helpers/dates_helper.rb:31
824 #: plugins/display_content/lib/display_content_block.rb:156 824 #: plugins/display_content/lib/display_content_block.rb:156
825 msgid "%{month_name} %{day}, %{year}" 825 msgid "%{month_name} %{day}, %{year}"
826 -msgstr "" 826 +msgstr "%{day} %{month_name} %{year}"
827 827
828 #: app/helpers/dates_helper.rb:31 828 #: app/helpers/dates_helper.rb:31
829 #: plugins/display_content/lib/display_content_block.rb:156 829 #: plugins/display_content/lib/display_content_block.rb:156
@@ -8016,7 +8016,7 @@ msgstr &quot;&quot; @@ -8016,7 +8016,7 @@ msgstr &quot;&quot;
8016 8016
8017 #: app/views/account/index_anonymous.rhtml:10 8017 #: app/views/account/index_anonymous.rhtml:10
8018 msgid "Sign up." 8018 msgid "Sign up."
8019 -msgstr "" 8019 +msgstr "Registro"
8020 8020
8021 #: app/views/account/index_anonymous.rhtml:11 8021 #: app/views/account/index_anonymous.rhtml:11
8022 msgid "" 8022 msgid ""
po/pt/noosfero.po
@@ -2875,6 +2875,30 @@ msgstr &quot;Artigo de texto com linguagem de marcação Textile&quot; @@ -2875,6 +2875,30 @@ msgstr &quot;Artigo de texto com linguagem de marcação Textile&quot;
2875 msgid "Accessible alternative for visually impaired users." 2875 msgid "Accessible alternative for visually impaired users."
2876 msgstr "Alternativa acessível para usuários com deficiência visual." 2876 msgstr "Alternativa acessível para usuários com deficiência visual."
2877 2877
  2878 +#: app/models/layout_template.rb
  2879 +msgid "Left Bar"
  2880 +msgstr "Uma barra à esquerda"
  2881 +
  2882 +#: app/models/layout_template.rb
  2883 +msgid "2 Left Bars"
  2884 +msgstr "Duas barras à esquerda"
  2885 +
  2886 +#: app/models/layout_template.rb
  2887 +msgid "Left and Bottom Bar"
  2888 +msgstr "Uma barra à esquerda e outra ao final"
  2889 +
  2890 +#: app/models/layout_template.rb
  2891 +msgid "Right Bar"
  2892 +msgstr "Uma barra à direita"
  2893 +
  2894 +#: app/models/layout_template.rb
  2895 +msgid "Default"
  2896 +msgstr "Padrão"
  2897 +
  2898 +#: app/models/layout_template.rb
  2899 +msgid "No Sidebars"
  2900 +msgstr "Nenhuma barra lateral"
  2901 +
2878 #: app/models/login_block.rb:4 2902 #: app/models/login_block.rb:4
2879 msgid "Login/logout" 2903 msgid "Login/logout"
2880 msgstr "Login/Sair" 2904 msgstr "Login/Sair"
@@ -7219,8 +7243,8 @@ msgstr &quot;Funcionalidade&quot; @@ -7219,8 +7243,8 @@ msgstr &quot;Funcionalidade&quot;
7219 7243
7220 #: app/views/features/index.rhtml:16 7244 #: app/views/features/index.rhtml:16
7221 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:4 7245 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:4
7222 -msgid "Enabled?"  
7223 -msgstr "Habilitada?" 7246 +msgid "Enable shopping basket"
  7247 +msgstr "Habilitar cesto de compras"
7224 7248
7225 #: app/views/features/index.rhtml:27 7249 #: app/views/features/index.rhtml:27
7226 msgid "Configure features" 7250 msgid "Configure features"
@@ -12462,8 +12486,8 @@ msgid &quot;Basket options&quot; @@ -12462,8 +12486,8 @@ msgid &quot;Basket options&quot;
12462 msgstr "Opções do cesto" 12486 msgstr "Opções do cesto"
12463 12487
12464 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:5 12488 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:5
12465 -msgid "Delivery?"  
12466 -msgstr "Entrega?" 12489 +msgid "Enable delivery fields on orders"
  12490 +msgstr "Ativar campos de entrega para pedidos"
12467 12491
12468 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:10 12492 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:10
12469 msgid "Option" 12493 msgid "Option"
@@ -12480,12 +12504,12 @@ msgid &quot;ADD NEW OPTION&quot; @@ -12480,12 +12504,12 @@ msgid &quot;ADD NEW OPTION&quot;
12480 msgstr "ADCIONAR NOVA OPÇÂO" 12504 msgstr "ADCIONAR NOVA OPÇÂO"
12481 12505
12482 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:36 12506 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:36
12483 -msgid "Free delivery price:"  
12484 -msgstr "Preço de entrega grátis:" 12507 +msgid "Order's minimum price for free delivery:"
  12508 +msgstr "Preço mínimo do pedido para entrega grátis:"
12485 12509
12486 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:37 12510 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:37
12487 -msgid "Empty stands for no free delivery price."  
12488 -msgstr "Vazio significa sem preço de frete grátis." 12511 +msgid "Leave empty to always charge the delivery."
  12512 +msgstr "Deixe vazio para sempre cobrar a entrega."
12489 12513
12490 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/reports.html.erb:1 12514 #: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/reports.html.erb:1
12491 msgid "Purchase Reports" 12515 msgid "Purchase Reports"
public/designs/icons/tango/style.css
1 /******************SMALL ICONS********************/ 1 /******************SMALL ICONS********************/
  2 +.icon-embed { background-image: url(Tango/16x16/apps/utilities-terminal.png) }
2 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) } 3 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) }
3 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) } 4 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) }
4 .icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) } 5 .icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) }
public/designs/templates/leftbottom/config.yml
1 -name: "Left and Bottom bar" 1 +name: "Left and Bottom Bar"
2 title: "Style 2 columns and a box at bottom of content" 2 title: "Style 2 columns and a box at bottom of content"
3 description: "A theme with 2 columns and a box below the content" 3 description: "A theme with 2 columns and a box below the content"
4 number_of_boxes: 3 4 number_of_boxes: 3
public/designs/templates/nosidebars/config.yml
1 -name: "No Side Bars" 1 +name: "No Sidebars"
2 title: "No sidebars, only content" 2 title: "No sidebars, only content"
3 description: "A template without sidebars, only content" 3 description: "A template without sidebars, only content"
4 number_of_boxes: 1 4 number_of_boxes: 1
public/designs/themes/base/style.css
@@ -1275,6 +1275,11 @@ hr.pre-posts, hr.sep-posts { @@ -1275,6 +1275,11 @@ hr.pre-posts, hr.sep-posts {
1275 padding-right: 9px; 1275 padding-right: 9px;
1276 } 1276 }
1277 1277
  1278 +.comment-order {
  1279 + float: right;
  1280 + display: block;
  1281 +}
  1282 +
1278 .comment-from-owner .comment-created-at { 1283 .comment-from-owner .comment-created-at {
1279 color: #333; 1284 color: #333;
1280 } 1285 }
public/images/drag-and-drop.png 0 → 100644

1.11 KB

public/javascripts/city_state_validation.js 0 → 100644
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
  1 +(function($){
  2 + autoCompleteStateCity($);
  3 + $('[id$="_country"]').change(function(){
  4 + autoCompleteStateCity($);
  5 + })
  6 +})(jQuery);
  7 +
  8 +function autoCompleteStateCity($) {
  9 + var country_selected = $('[id$="_country"] option:selected').val()
  10 + if(country_selected == "BR")
  11 + {
  12 + $('#state_field').autocomplete({
  13 + source : function(request, response){
  14 + $.ajax({
  15 + type: "GET",
  16 + url: '/account/search_state',
  17 + data: {state_name: request.term},
  18 + success: function(result){
  19 + response(result);
  20 + },
  21 + error: function(ajax, stat, errorThrown) {
  22 + console.log('Link not found : ' + errorThrown);
  23 + }
  24 + });
  25 + },
  26 +
  27 + minLength: 3
  28 + });
  29 +
  30 + $('#city_field').autocomplete({
  31 + source : function(request, response){
  32 + $.ajax({
  33 + type: "GET",
  34 + url: '/account/search_cities',
  35 + data: {city_name: request.term, state_name: $("#state_field").val()},
  36 + success: function(result){
  37 + response(result);
  38 + },
  39 + error: function(ajax, stat, errorThrown) {
  40 + console.log('Link not found : ' + errorThrown);
  41 + }
  42 + });
  43 + },
  44 +
  45 + minLength: 3
  46 + });
  47 + }
  48 + else
  49 + {
  50 + if ($('#state_field').data('autocomplete')) {
  51 + $('#state_field').autocomplete("destroy");
  52 + $('#state_field').removeData('autocomplete');
  53 + }
  54 +
  55 + if ($('#city_field').data('autocomplete')) {
  56 + $('#city_field').autocomplete("destroy");
  57 + $('#city_field').removeData('autocomplete');
  58 + }
  59 + }
  60 +}
public/javascripts/comment_order.js 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +function send_order(order, url) {
  2 + open_loading(DEFAULT_LOADING_MESSAGE);
  3 +
  4 + jQuery.ajax({
  5 + url:url,
  6 + data: {"comment_order":order},
  7 + success: function(response) {
  8 + close_loading();
  9 + jQuery(".article-comments-list").html(response);
  10 + },
  11 + error: function() { close_loading() }
  12 + });
  13 +}
  14 +
  15 +
  16 +jQuery(document).ready(function(){
  17 + jQuery("#comment_order").change(function(){
  18 + var url = jQuery("#page_url").val();
  19 + send_order(this.value, url);
  20 + });
  21 +});
0 \ No newline at end of file 22 \ No newline at end of file
public/javascripts/edit-link-list.js 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +function send_ajax(source_url) {
  2 + jQuery(".link-address").autocomplete({
  3 + source : function(request, response){
  4 + jQuery.ajax({
  5 + type: "GET",
  6 + url: source_url,
  7 + data: {query: request.term},
  8 + success: function(result){
  9 + response(result);
  10 + },
  11 + error: function(ajax, stat, errorThrown) {
  12 + console.log('Link not found : ' + errorThrown);
  13 + }
  14 + });
  15 + },
  16 +
  17 + minLength: 3
  18 + });
  19 +}
  20 +
  21 +function new_link_action(){
  22 + send_ajax(jQuery("#page_url").val());
  23 +
  24 + jQuery(".delete-link-list-row").click(function(){
  25 + jQuery(this).parent().parent().remove();
  26 + return false;
  27 + });
  28 +
  29 + jQuery(document).scrollTop(jQuery('#dropable-link-list').scrollTop());
  30 +}
  31 +
  32 +jQuery(document).ready(function(){
  33 + new_link_action();
  34 +
  35 + jQuery("#dropable-link-list").sortable({
  36 + revert: true,
  37 + axis: "y"
  38 + });
  39 +});
0 \ No newline at end of file 40 \ No newline at end of file
public/javascripts/manage-fields.js 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +function update_active(name_active, name_required, name_signup) {
  2 + var required = jQuery("input[name='" + name_required + "']")[1]
  3 + var signup = jQuery("input[name='" + name_signup + "']")[1]
  4 + var active = jQuery("input[name='" + name_active + "']")[1]
  5 +
  6 + if(required.checked || signup.checked)
  7 + active.checked = true
  8 +}
  9 +
  10 +function active_action(obj_active, name_required, name_signup) {
  11 + var required = jQuery("input[name='" + name_required + "']")[0]
  12 + var signup = jQuery("input[name='" + name_signup + "']")[0]
  13 +
  14 + required.disabled = signup.disabled = !obj_active.checked
  15 +}
  16 +
  17 +function required_action(name_active, name_required, name_signup) {
  18 + var obj_required = jQuery("input[name='" + name_required + "']")[1]
  19 +
  20 + if(obj_required.checked) {
  21 + jQuery("input[name='" + name_signup + "']")[0].checked = true
  22 + jQuery("input[name='" + name_signup + "']")[1].checked = true
  23 + }
  24 +
  25 + update_active(name_active, name_required, name_signup)
  26 +}
  27 +
  28 +function signup_action(name_active, name_required, name_signup) {
  29 + var obj_signup = jQuery("input[name='" + name_signup + "']")[1]
  30 +
  31 + if(!obj_signup.checked) {
  32 + jQuery("input[name='" + name_required + "']")[0].checked = false
  33 + jQuery("input[name='" + name_required + "']")[1].checked = false
  34 + }
  35 +
  36 + update_active(name_active, name_required, name_signup)
  37 +}
  38 +
  39 +
  40 +jQuery(document).ready(function(){
  41 + function check_fields(check, table_id, start) {
  42 + var checkboxes = jQuery("#" + table_id + " tbody tr td input[type='checkbox']")
  43 + for (var i = start; i < checkboxes.length; i+=3) {
  44 + checkboxes[i].checked = check
  45 + }
  46 + }
  47 +
  48 + function verify_checked(fields_id){
  49 + var checkboxes = jQuery("#" + fields_id + "_fields_conf tbody tr td input[type='checkbox']")
  50 + for (var i = 2; i >= 0; i--) {
  51 + var allchecked = true
  52 + for (var j = i+3; j < checkboxes.length; j+=3) {
  53 + if(!checkboxes[j].checked) {
  54 + allchecked = false
  55 + break
  56 + }
  57 + }
  58 +
  59 + var checkbox = jQuery(checkboxes[i+3]).attr("id").split("_")
  60 + jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", allchecked)
  61 + }
  62 + }
  63 +
  64 + function check_all(fields_id) {
  65 + jQuery("#" + fields_id + "_active").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 0)})
  66 + jQuery("#" + fields_id + "_required").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 1)})
  67 + jQuery("#" + fields_id +"_signup").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 2)})
  68 + verify_checked(fields_id)
  69 + }
  70 +
  71 + check_all("person")
  72 + check_all("enterprise")
  73 + check_all("community")
  74 +
  75 + jQuery("input[type='checkbox']").click(function (){
  76 + var checkbox = jQuery(this).attr("id").split("_")
  77 + verify_checked(checkbox.first())
  78 +
  79 + if(this.checked == false) {
  80 + jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", false)
  81 + }
  82 + })
  83 +})
public/javascripts/sign_up_password_rate.js 0 → 100644
@@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
  1 +// This jQuery plugin is written by firas kassem [2007.04.05] and was modified to fit noosfero
  2 +// Firas Kassem phiras.wordpress.com || phiras at gmail {dot} com
  3 +// for more information : http://phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
  4 +
  5 +var blankPass = -1
  6 +var shortPass = 0
  7 +var badPass = 1
  8 +var goodPass = 2
  9 +var strongPass = 3
  10 +
  11 +
  12 +function passwordStrength(password,username)
  13 +{
  14 + score = 0
  15 +
  16 + if(password.length == 0) return blankPass
  17 +
  18 + //password < 4
  19 + if (password.length < 4 ) { return shortPass }
  20 +
  21 + //password == username
  22 + if (password.toLowerCase()==username.toLowerCase()) badPass
  23 +
  24 + //password length
  25 + score += password.length * 4
  26 + score += ( checkRepetition(1,password).length - password.length ) * 1
  27 + score += ( checkRepetition(2,password).length - password.length ) * 1
  28 + score += ( checkRepetition(3,password).length - password.length ) * 1
  29 + score += ( checkRepetition(4,password).length - password.length ) * 1
  30 +
  31 + //password has 3 numbers
  32 + if (password.match(/(.*[0-9].*[0-9].*[0-9])/)) score += 5
  33 +
  34 + //password has 2 sybols
  35 + if (password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)) score += 5
  36 +
  37 + //password has Upper and Lower chars
  38 + if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) score += 10
  39 +
  40 + //password has number and chars
  41 + if (password.match(/([a-zA-Z])/) && password.match(/([0-9])/)) score += 15
  42 + //
  43 + //password has number and symbol
  44 + if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([0-9])/)) score += 15
  45 +
  46 + //password has char and symbol
  47 + if (password.match(/([!,@,#,$,%,^,&,*,?,_,~])/) && password.match(/([a-zA-Z])/)) score += 15
  48 +
  49 + //password is just a nubers or chars
  50 + if (password.match(/^\w+$/) || password.match(/^\d+$/) ) score -= 10
  51 +
  52 + //verifing 0 < score < 100
  53 + if ( score < 0 ) score = 0
  54 + if ( score > 100 ) score = 100
  55 +
  56 + if (score < 34 ) return badPass
  57 + if (score < 68 ) return goodPass
  58 + return strongPass
  59 +}
  60 +
  61 +function checkRepetition(pLen,str)
  62 +{
  63 + res = ""
  64 + for ( i=0; i<str.length ; i++ )
  65 + {
  66 + repeated=true
  67 + for (j=0;j < pLen && (j+i+pLen) < str.length;j++)
  68 + repeated=repeated && (str.charAt(j+i)==str.charAt(j+i+pLen))
  69 + if (j<pLen) repeated=false
  70 + if (repeated)
  71 + {
  72 + i+=pLen-1
  73 + repeated=false
  74 + }
  75 + else
  76 + {
  77 + res+=str.charAt(i)
  78 + }
  79 + }
  80 + return res
  81 +}
  82 +
  83 +jQuery(document).ready(function() {
  84 + jQuery('#user_pw').keyup(function()
  85 + {
  86 + var result = passwordStrength(jQuery('#user_pw').val(),jQuery('#user_login').val())
  87 + if(result == blankPass)
  88 + {
  89 + showRateField('#result-blank')
  90 + } else
  91 + if(result == shortPass)
  92 + {
  93 + showRateField('#result-short')
  94 + } else
  95 + if( result == badPass )
  96 + {
  97 + showRateField('#result-bad')
  98 + } else
  99 + if( result == goodPass )
  100 + {
  101 + showRateField('#result-good')
  102 + } else
  103 + if( result == strongPass )
  104 + {
  105 + showRateField('#result-strong')
  106 + }
  107 +
  108 + })
  109 +})
  110 +
  111 +function showRateField(validation)
  112 +{
  113 + jQuery('#result-blank').addClass('hidden')
  114 + jQuery('#result-short').addClass('hidden')
  115 + jQuery('#result-bad').addClass('hidden')
  116 + jQuery('#result-good').addClass('hidden')
  117 + jQuery('#result-strong').addClass('hidden')
  118 +
  119 + jQuery(validation).removeClass('hidden')
  120 +
  121 +}
0 \ No newline at end of file 122 \ No newline at end of file
public/javascripts/signup_form.js 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +function verifyLoginLoad() {
  2 + jQuery('#user_login').removeClass('available unavailable valid validated invalid checking').addClass('checking');
  3 + jQuery('#url-check').html(jQuery('#checking-message').html());
  4 +}
  5 +
  6 +function verifyLoginAjax(value) {
  7 + verifyLoginLoad();
  8 +
  9 + jQuery.get(
  10 + "/account/check_valid_name",
  11 + {'identifier': encodeURIComponent(value)},
  12 + function(request){
  13 + jQuery('#user_login').removeClass('checking');
  14 + jQuery("#url-check").html(request);
  15 + }
  16 + );
  17 +}
  18 +
  19 +jQuery(document).ready(function(){
  20 + jQuery("#user_login").blur(function(){
  21 + verifyLoginAjax(this.value);
  22 + });
  23 +});
public/stylesheets/application.css
@@ -354,21 +354,32 @@ div.pending-tasks { @@ -354,21 +354,32 @@ div.pending-tasks {
354 margin-bottom: 1px; 354 margin-bottom: 1px;
355 } 355 }
356 /* * * category ajax selector * * */ 356 /* * * category ajax selector * * */
357 - 357 +#category-ajax-selector .category-helper-label {
  358 + font-size: 16px;
  359 + color: rgb(158, 158, 158);
  360 + padding: 5px 0px;
  361 +}
358 #category-ajax-selector { 362 #category-ajax-selector {
359 border: 1px solid #AAA; 363 border: 1px solid #AAA;
360 - background: #EEE;  
361 - padding: 15px 0px 15px 20px;  
362 - margin: 30px 0px 0px 0px; 364 + padding: 3px 10px 10px 10px;
  365 + margin: 0px 0px 0px 0px;
363 position: relative; 366 position: relative;
364 - font-size: 18px; 367 + font-size: 10px;
  368 + background-color: #fcfcf9;
365 } 369 }
366 #category-ajax-selector a { 370 #category-ajax-selector a {
367 - font-size: 14px; 371 + font-size: 12px;
368 } 372 }
369 -#category-ajax-selector h3 {  
370 - margin: 10px 0px;  
371 - font-size: 14px; 373 +#selected-categories {
  374 + padding-bottom: 5px;
  375 +}
  376 +#selected-categories .label {
  377 + font-size: 16px;
  378 + margin-bottom: 10px;
  379 + margin-top: 5px;
  380 +}
  381 +.selected-category {
  382 + padding: 2px 0;
372 } 383 }
373 #category-ajax-selector .box-title { 384 #category-ajax-selector .box-title {
374 position: absolute; 385 position: absolute;
@@ -384,25 +395,32 @@ div.pending-tasks { @@ -384,25 +395,32 @@ div.pending-tasks {
384 .msie6 #category-ajax-selector .box-title { 395 .msie6 #category-ajax-selector .box-title {
385 top: -29px; 396 top: -29px;
386 } 397 }
387 -#category-ajax-selector .select-subcategory-link { 398 +#category-ajax-selector .select-subcategory-link,
  399 +.select-subcategory-link {
388 border: 1px solid #BBB; 400 border: 1px solid #BBB;
389 padding: 1px 3px; 401 padding: 1px 3px;
390 margin: 0px 1px; 402 margin: 0px 1px;
391 text-decoration: none; 403 text-decoration: none;
392 white-space: nowrap; 404 white-space: nowrap;
393 - font-size: 11px; 405 + font-size: 12px;
  406 + line-height: 20px;
  407 + border-radius: 3px;
  408 +}
  409 +#category-ajax-selector .selected-category .select-subcategory-link {
  410 + border: 0;
394 } 411 }
395 -#category-ajax-selector .select-subcategory-link:hover { 412 +#category-ajax-selector .select-subcategory-link:hover,
  413 +.select-subcategory-link:hover {
396 background-color: black; 414 background-color: black;
397 } 415 }
398 #category-ajax-selector .button { 416 #category-ajax-selector .button {
399 - display: block;  
400 - position: absolute;  
401 top: 4px; 417 top: 4px;
402 right: 2px; 418 right: 2px;
403 } 419 }
404 -#category-ajax-selector .icon-save {  
405 - right: 25px; 420 +#category-ajax-selector hr {
  421 + border: 0;
  422 + border-bottom: 1px solid #EEE;
  423 + margin-top: 15px;
406 } 424 }
407 #profile-header, #profile-footer { 425 #profile-header, #profile-footer {
408 clear: both; 426 clear: both;
@@ -1841,20 +1859,70 @@ a.button.disabled, input.disabled { @@ -1841,20 +1859,70 @@ a.button.disabled, input.disabled {
1841 text-decoration: none; 1859 text-decoration: none;
1842 } 1860 }
1843 /* ==> blocks/link-list-block.css <<= */ 1861 /* ==> blocks/link-list-block.css <<= */
1844 -  
1845 #edit-link-list-block { 1862 #edit-link-list-block {
1846 - width: 820px; 1863 + width: 620px;
  1864 + position: relative;
  1865 + left: -24px;
1847 } 1866 }
1848 -  
1849 -#edit-link-list-block table {  
1850 - width: auto;  
1851 - margin-bottom: 10px; 1867 +.link-list-header {
  1868 + width: 98%;
  1869 + height: 25px;
  1870 + padding: 10px 1px 10px 10px;
  1871 + margin-bottom: 5px;
  1872 + cursor: pointer;
1852 } 1873 }
1853 -#edit-link-list-block table .cel-address {  
1854 - width: 220px; 1874 +.link-list-header li {
  1875 + list-style-type: none;
  1876 + display: inline;
  1877 + font-weight: bold;
  1878 + font-size: 14px;
  1879 + text-align: center;
1855 } 1880 }
1856 -#edit-link-list-block table .cel-address input {  
1857 - width: 100%; 1881 +#dropable-link-list {
  1882 + padding-left: 23px;
  1883 + margin-top: -12px;
  1884 +}
  1885 +#dropable-link-list li {
  1886 + list-style-type: none;
  1887 +}
  1888 +.link-list-row {
  1889 + line-height: 25px;
  1890 + margin-bottom: 5px;
  1891 + padding: 10px 1px 10px 10px;
  1892 + cursor: pointer;
  1893 + width: 97%;
  1894 +}
  1895 +.link-list-row:hover {
  1896 + background: #ddd url(/images/drag-and-drop.png) no-repeat;
  1897 + background-position: 98% 15px;
  1898 +}
  1899 +.link-list-row li {
  1900 + list-style-type: none;
  1901 + display: inline;
  1902 + margin-left: 5px;
  1903 +}
  1904 +.link-list-row li div {
  1905 + float: left;
  1906 + margin-top: 4px;
  1907 +}
  1908 +.link-list-row li a {
  1909 + line-height: 27px !important;
  1910 + padding-right: 5px;
  1911 +}
  1912 +.link-list-icon {
  1913 + margin-left: 14px;
  1914 +}
  1915 +.link-list-name {
  1916 + margin-left: 40px;
  1917 +}
  1918 +.link-list-address {
  1919 + margin-left: 90px;
  1920 +}
  1921 +.link-list-target {
  1922 + margin-left: 77px;
  1923 +}
  1924 +.new_link_row li {
  1925 + margin-left: 7px;
1858 } 1926 }
1859 #content .link-list-block { 1927 #content .link-list-block {
1860 padding: 10px 0px 10px 10px; 1928 padding: 10px 0px 10px 10px;
@@ -3543,9 +3611,10 @@ div#article-parent { @@ -3543,9 +3611,10 @@ div#article-parent {
3543 } 3611 }
3544 #agenda .agenda-calendar { 3612 #agenda .agenda-calendar {
3545 width: 50%; 3613 width: 50%;
  3614 + display: inline-block;
3546 } 3615 }
3547 #agenda td, #agenda th { 3616 #agenda td, #agenda th {
3548 - padding: 15px; 3617 + padding: 10px;
3549 padding-right: 0px; 3618 padding-right: 0px;
3550 } 3619 }
3551 #agenda .agenda-calendar .previous-month td, #agenda .agenda-calendar .previous-month th, #agenda .agenda-calendar .next-month td, #agenda .agenda-calendar .next-month th { 3620 #agenda .agenda-calendar .previous-month td, #agenda .agenda-calendar .previous-month th, #agenda .agenda-calendar .next-month td, #agenda .agenda-calendar .next-month th {
@@ -3603,26 +3672,25 @@ div#article-parent { @@ -3603,26 +3672,25 @@ div#article-parent {
3603 vertical-align: middle; 3672 vertical-align: middle;
3604 } 3673 }
3605 #agenda .agenda-calendar .current-month caption { 3674 #agenda .agenda-calendar .current-month caption {
3606 - margin-bottom: 10px; 3675 + margin: 10px 0px;
3607 } 3676 }
3608 #agenda #events-of-the-day { 3677 #agenda #events-of-the-day {
3609 - position: absolute;  
3610 - left: 50%;  
3611 width: 45%; 3678 width: 45%;
3612 - top: 0px;  
3613 height: 100%; 3679 height: 100%;
3614 padding-left: 20px; 3680 padding-left: 20px;
  3681 + display: inline-block;
  3682 + vertical-align: top;
3615 } 3683 }
3616 #agenda #events-of-the-day #agenda-items { 3684 #agenda #events-of-the-day #agenda-items {
3617 display: block; 3685 display: block;
3618 overflow: auto; 3686 overflow: auto;
3619 overflow-x: hidden; 3687 overflow-x: hidden;
3620 - height: 80%; 3688 + height: 250px;
3621 background: white; 3689 background: white;
3622 border: none; 3690 border: none;
3623 } 3691 }
3624 #agenda-toolbar { 3692 #agenda-toolbar {
3625 - float: right; 3693 + text-align: right;
3626 font-variant: normal; 3694 font-variant: normal;
3627 font-weight: normal; 3695 font-weight: normal;
3628 } 3696 }
@@ -3645,6 +3713,9 @@ h1#agenda-title { @@ -3645,6 +3713,9 @@ h1#agenda-title {
3645 display: block; 3713 display: block;
3646 margin-top: 10px; 3714 margin-top: 10px;
3647 } 3715 }
  3716 +#agenda .pagination {
  3717 + margin-top: 15px;
  3718 +}
3648 /* ==> public/stylesheets/controller_favorite_enterprises.css <== */ 3719 /* ==> public/stylesheets/controller_favorite_enterprises.css <== */
3649 3720
3650 /* ==> @import url(manage_contacts_list.css); <== */ 3721 /* ==> @import url(manage_contacts_list.css); <== */
@@ -4196,6 +4267,11 @@ h1#agenda-title { @@ -4196,6 +4267,11 @@ h1#agenda-title {
4196 display: block; 4267 display: block;
4197 float: left; 4268 float: left;
4198 } 4269 }
  4270 +
  4271 +.actions .members-buttons-cell {
  4272 + width : 100px
  4273 +}
  4274 +
4199 .controller-profile_members .msie6 .button-bar a { 4275 .controller-profile_members .msie6 .button-bar a {
4200 position: relative; 4276 position: relative;
4201 } 4277 }
@@ -5964,8 +6040,14 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -5964,8 +6040,14 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5964 text-align: right; 6040 text-align: right;
5965 } 6041 }
5966 6042
  6043 +#url-check .suggested_usernames,
  6044 +#url-check .suggested_usernames a {
  6045 + color: #005000;
  6046 +}
  6047 +
5967 #email-check, 6048 #email-check,
5968 #fake-check, 6049 #fake-check,
  6050 +#password-rate,
5969 #password-check { 6051 #password-check {
5970 margin: -2px 16px -5px 13px; 6052 margin: -2px 16px -5px 13px;
5971 text-align: right; 6053 text-align: right;
@@ -5974,10 +6056,20 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -5974,10 +6056,20 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5974 6056
5975 #email-check p, 6057 #email-check p,
5976 #fake-check p, 6058 #fake-check p,
  6059 +#password-rate p,
5977 #password-check p { 6060 #password-check p {
5978 margin: 0; 6061 margin: 0;
5979 } 6062 }
5980 6063
  6064 +#password-rate {
  6065 + font-weight:bold;
  6066 +}
  6067 +
  6068 +.hidden {
  6069 + visibility: hidden;
  6070 + display: none;
  6071 +}
  6072 +
5981 .available { 6073 .available {
5982 color: #88BD00; 6074 color: #88BD00;
5983 } 6075 }
@@ -5991,6 +6083,7 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -5991,6 +6083,7 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
5991 } 6083 }
5992 6084
5993 #email-check p, 6085 #email-check p,
  6086 +#password-rate p,
5994 #password-check p, 6087 #password-check p,
5995 #url-check p { 6088 #url-check p {
5996 margin: 0; 6089 margin: 0;
@@ -6488,3 +6581,31 @@ ul.article-versions li { @@ -6488,3 +6581,31 @@ ul.article-versions li {
6488 font-size: 13px; 6581 font-size: 13px;
6489 padding: 3px 0px; 6582 padding: 3px 0px;
6490 } 6583 }
  6584 +
  6585 +/* * * Admin manage fields * * */
  6586 +
  6587 +.controller-features .manage-fields-batch-actions,
  6588 +.controller-features .manage-fields-batch-actions:hover {
  6589 + border-bottom:solid 2px #000;
  6590 + background-color: #EEE;
  6591 +}
  6592 +
  6593 +.controller-features .manage-fields-batch-actions td {
  6594 + font-style: italic;
  6595 +}
  6596 +
  6597 +#signup-form #result-short {
  6598 + color: red;
  6599 +}
  6600 +
  6601 +#signup-form #result-bad {
  6602 + color: #825A2C;
  6603 +}
  6604 +
  6605 +#signup-form #result-good {
  6606 + color: #32CD32;
  6607 +}
  6608 +
  6609 +#signup-form #result-strong {
  6610 + color: green;
  6611 +}
test/functional/account_controller_test.rb
@@ -8,7 +8,6 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -8,7 +8,6 @@ class AccountControllerTest &lt; ActionController::TestCase
8 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead 8 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9 # Then, you can remove it from this and the units test. 9 # Then, you can remove it from this and the units test.
10 include AuthenticatedTestHelper 10 include AuthenticatedTestHelper
11 -  
12 all_fixtures 11 all_fixtures
13 12
14 def teardown 13 def teardown
@@ -17,8 +16,8 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -17,8 +16,8 @@ class AccountControllerTest &lt; ActionController::TestCase
17 16
18 def setup 17 def setup
19 @controller = AccountController.new 18 @controller = AccountController.new
20 - @request = ActionController::TestRequest.new  
21 - @response = ActionController::TestResponse.new 19 + @request = ActionController::TestRequest.new
  20 + @response = ActionController::TestResponse.new
22 disable_signup_bot_check 21 disable_signup_bot_check
23 end 22 end
24 23
@@ -646,21 +645,28 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -646,21 +645,28 @@ class AccountControllerTest &lt; ActionController::TestCase
646 assert_redirected_to :controller => 'home', :action => 'index' 645 assert_redirected_to :controller => 'home', :action => 'index'
647 end 646 end
648 647
649 - should 'check_url is available on environment' do 648 + should 'check_valid_name is available on environment' do
650 env = fast_create(Environment, :name => 'Environment test') 649 env = fast_create(Environment, :name => 'Environment test')
651 @controller.expects(:environment).returns(env).at_least_once 650 @controller.expects(:environment).returns(env).at_least_once
652 profile = create_user('mylogin').person 651 profile = create_user('mylogin').person
653 - get :check_url, :identifier => 'mylogin' 652 + get :check_valid_name, :identifier => 'mylogin'
654 assert_equal 'validated', assigns(:status_class) 653 assert_equal 'validated', assigns(:status_class)
655 end 654 end
656 655
657 should 'check if url is not available on environment' do 656 should 'check if url is not available on environment' do
658 @controller.expects(:environment).returns(Environment.default).at_least_once 657 @controller.expects(:environment).returns(Environment.default).at_least_once
659 profile = create_user('mylogin').person 658 profile = create_user('mylogin').person
660 - get :check_url, :identifier => 'mylogin' 659 + get :check_valid_name, :identifier => 'mylogin'
661 assert_equal 'invalid', assigns(:status_class) 660 assert_equal 'invalid', assigns(:status_class)
662 end 661 end
663 662
  663 + should 'suggest a list with three possible usernames' do
  664 + profile = create_user('mylogin').person
  665 + get :check_valid_name, :identifier => 'mylogin'
  666 +
  667 + assert_equal 3, assigns(:suggested_usernames).uniq.size
  668 + end
  669 +
664 should 'check if e-mail is available on environment' do 670 should 'check if e-mail is available on environment' do
665 env = fast_create(Environment, :name => 'Environment test') 671 env = fast_create(Environment, :name => 'Environment test')
666 @controller.expects(:environment).returns(env).at_least_once 672 @controller.expects(:environment).returns(env).at_least_once
@@ -689,6 +695,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -689,6 +695,7 @@ class AccountControllerTest &lt; ActionController::TestCase
689 {:test => 5} 695 {:test => 5}
690 end 696 end
691 end 697 end
  698 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
692 699
693 e = User.find_by_login('ze').environment 700 e = User.find_by_login('ze').environment
694 e.enable_plugin(Plugin1.name) 701 e.enable_plugin(Plugin1.name)
@@ -779,6 +786,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -779,6 +786,7 @@ class AccountControllerTest &lt; ActionController::TestCase
779 proc {"<strong>Plugin2 text</strong>"} 786 proc {"<strong>Plugin2 text</strong>"}
780 end 787 end
781 end 788 end
  789 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
782 790
783 Environment.default.enable_plugin(Plugin1.name) 791 Environment.default.enable_plugin(Plugin1.name)
784 Environment.default.enable_plugin(Plugin2.name) 792 Environment.default.enable_plugin(Plugin2.name)
@@ -795,6 +803,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -795,6 +803,7 @@ class AccountControllerTest &lt; ActionController::TestCase
795 User.new(:login => 'testuser') 803 User.new(:login => 'testuser')
796 end 804 end
797 end 805 end
  806 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
798 Environment.default.enable_plugin(Plugin1.name) 807 Environment.default.enable_plugin(Plugin1.name)
799 808
800 post :login, :user => {:login => "testuser"} 809 post :login, :user => {:login => "testuser"}
@@ -809,6 +818,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -809,6 +818,7 @@ class AccountControllerTest &lt; ActionController::TestCase
809 nil 818 nil
810 end 819 end
811 end 820 end
  821 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
812 Environment.default.enable_plugin(Plugin1.name) 822 Environment.default.enable_plugin(Plugin1.name)
813 post :login, :user => {:login => 'johndoe', :password => 'test'} 823 post :login, :user => {:login => 'johndoe', :password => 'test'}
814 assert session[:user] 824 assert session[:user]
@@ -822,6 +832,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -822,6 +832,7 @@ class AccountControllerTest &lt; ActionController::TestCase
822 false 832 false
823 end 833 end
824 end 834 end
  835 + Noosfero::Plugin.stubs(:all).returns([TestRegistrationPlugin.name])
825 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new]) 836 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
826 837
827 post :signup, :user => { :login => 'testuser', :password => '123456', :password_confirmation => '123456', :email => 'testuser@example.com' } 838 post :signup, :user => { :login => 'testuser', :password => '123456', :password_confirmation => '123456', :email => 'testuser@example.com' }
@@ -840,6 +851,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -840,6 +851,7 @@ class AccountControllerTest &lt; ActionController::TestCase
840 true 851 true
841 end 852 end
842 end 853 end
  854 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
843 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new]) 855 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
844 856
845 get :login 857 get :login
@@ -853,6 +865,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -853,6 +865,7 @@ class AccountControllerTest &lt; ActionController::TestCase
853 false 865 false
854 end 866 end
855 end 867 end
  868 + Noosfero::Plugin.stubs(:all).returns([TestRegistrationPlugin.name])
856 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new]) 869 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestRegistrationPlugin.new])
857 870
858 #Redirect on get action 871 #Redirect on get action
@@ -876,6 +889,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -876,6 +889,7 @@ class AccountControllerTest &lt; ActionController::TestCase
876 true 889 true
877 end 890 end
878 end 891 end
  892 + Noosfero::Plugin.stubs(:all).returns([Plugin1.new, Plugin2.new])
879 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new]) 893 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
880 894
881 get :login 895 get :login
@@ -894,6 +908,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -894,6 +908,7 @@ class AccountControllerTest &lt; ActionController::TestCase
894 proc {"<strong>Plugin2 text</strong>"} 908 proc {"<strong>Plugin2 text</strong>"}
895 end 909 end
896 end 910 end
  911 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
897 912
898 Environment.default.enable_plugin(Plugin1.name) 913 Environment.default.enable_plugin(Plugin1.name)
899 Environment.default.enable_plugin(Plugin2.name) 914 Environment.default.enable_plugin(Plugin2.name)
@@ -917,6 +932,30 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -917,6 +932,30 @@ class AccountControllerTest &lt; ActionController::TestCase
917 assert @response.body.blank? 932 assert @response.body.blank?
918 end 933 end
919 934
  935 + should "Search for state" do
  936 + create_state_and_city
  937 +
  938 + xhr :get, :search_state, :state_name=>"Rio Grande"
  939 +
  940 + json_response = ActiveSupport::JSON.decode(@response.body)
  941 + label = json_response[0]['label']
  942 +
  943 + assert_equal label, "Rio Grande do Sul"
  944 + end
  945 +
  946 + should "Search for city" do
  947 + create_state_and_city
  948 +
  949 + xhr :get, :search_cities, :state_name=>"Rio Grande do Sul", :city_name=>"Lavras"
  950 +
  951 + json_response = ActiveSupport::JSON.decode(@response.body)
  952 + label = json_response[0]['label']
  953 + category = json_response[0]['category']
  954 +
  955 + assert_equal category, "Rio Grande do Sul"
  956 + assert_equal label, "Lavras do Sul"
  957 + end
  958 +
920 protected 959 protected
921 def new_user(options = {}, extra_options ={}) 960 def new_user(options = {}, extra_options ={})
922 data = {:profile_data => person_data} 961 data = {:profile_data => person_data}
@@ -945,4 +984,18 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -945,4 +984,18 @@ class AccountControllerTest &lt; ActionController::TestCase
945 environment.min_signup_delay = 0 984 environment.min_signup_delay = 0
946 environment.save! 985 environment.save!
947 end 986 end
  987 +
  988 + def create_state_and_city
  989 + city = 'Lavras do Sul'
  990 + state = 'Rio Grande do Sul'
  991 +
  992 + parent_region = fast_create(NationalRegion, :name => state,
  993 + :national_region_code => '43',
  994 + :national_region_type_id => NationalRegionType::STATE)
  995 +
  996 + fast_create(NationalRegion, :name => city,
  997 + :national_region_code => '431150',
  998 + :national_region_type_id => NationalRegionType::CITY,
  999 + :parent_national_region_code => parent_region.national_region_code)
  1000 + end
948 end 1001 end
test/functional/application_controller_test.rb
@@ -234,7 +234,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -234,7 +234,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
234 get :index 234 get :index
235 235
236 assert_tag :tag => 'div', :attributes => { :id => 'theme-test-panel' }, :descendant => { 236 assert_tag :tag => 'div', :attributes => { :id => 'theme-test-panel' }, :descendant => {
237 - :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/edit/my-test-theme'} 237 + :tag => 'a', :attributes => { :href => '/myprofile/testinguser/profile_themes/edit/my-test-theme'}
238 } 238 }
239 #{ :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/stop_test/my-test-theme'} } 239 #{ :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/stop_test/my-test-theme'} }
240 end 240 end
@@ -253,7 +253,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -253,7 +253,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
253 assert_no_tag :tag => 'a', :content => /Category 2/ 253 assert_no_tag :tag => 'a', :content => /Category 2/
254 end 254 end
255 255
256 - should 'show name of article as title of page' do 256 + should 'show name of article as title of page without environment' do
257 p = create_user('test_user').person 257 p = create_user('test_user').person
258 a = p.articles.create!(:name => 'test article') 258 a = p.articles.create!(:name => 'test article')
259 259
@@ -261,17 +261,22 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -261,17 +261,22 @@ class ApplicationControllerTest &lt; ActionController::TestCase
261 @controller.instance_variable_set('@page', a) 261 @controller.instance_variable_set('@page', a)
262 262
263 get :index 263 get :index
264 - assert_tag 'title', :content => 'test article - ' + p.name + ' - ' + p.environment.name 264 + assert_tag 'title', :content => 'test article - ' + p.name
265 end 265 end
266 266
267 - should 'diplay name of profile in the title' do 267 + should 'diplay name of profile in the title without environment' do
268 p = create_user('test_user').person 268 p = create_user('test_user').person
269 p.name = 'Some Test User' 269 p.name = 'Some Test User'
270 p.save! 270 p.save!
271 @controller.instance_variable_set('@profile', p) 271 @controller.instance_variable_set('@profile', p)
272 272
273 get :index, :profile => p.identifier 273 get :index, :profile => p.identifier
274 - assert_tag 'title', :content => p.name + ' - ' + p.environment.name 274 + assert_tag 'title', :content => p.name
  275 + end
  276 +
  277 + should 'display environment name in title when profile and page are not defined' do
  278 + get :index
  279 + assert_tag 'title', :content => assigns(:environment).name
275 end 280 end
276 281
277 should 'display menu links for my environment when logged in other environment' do 282 should 'display menu links for my environment when logged in other environment' do
@@ -314,7 +319,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -314,7 +319,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
314 end 319 end
315 320
316 should 'set html lang as the article language if an article is present and has a language' do 321 should 'set html lang as the article language if an article is present and has a language' do
317 - a = fast_create(Article, :name => 'test article', :language => 'fr') 322 + p = create_user('test_user').person
  323 + a = fast_create(Article, :name => 'test article', :language => 'fr', :profile_id => p.id )
318 @controller.instance_variable_set('@page', a) 324 @controller.instance_variable_set('@page', a)
319 FastGettext.stubs(:locale).returns('es') 325 FastGettext.stubs(:locale).returns('es')
320 get :index 326 get :index
@@ -328,7 +334,9 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -328,7 +334,9 @@ class ApplicationControllerTest &lt; ActionController::TestCase
328 end 334 end
329 335
330 should 'set html lang as locale if page has no language' do 336 should 'set html lang as locale if page has no language' do
331 - a = fast_create(Article, :name => 'test article', :language => nil) 337 + p = create_user('test_user').person
  338 + a = fast_create(Article, :name => 'test article', :language => nil, :profile_id => p.id )
  339 +
332 @controller.instance_variable_set('@page', a) 340 @controller.instance_variable_set('@page', a)
333 FastGettext.stubs(:locale).returns('es') 341 FastGettext.stubs(:locale).returns('es')
334 get :index 342 get :index
@@ -356,6 +364,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -356,6 +364,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
356 end 364 end
357 plugin2_path = '/plugin2/style.css' 365 plugin2_path = '/plugin2/style.css'
358 366
  367 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
  368 +
359 environment = Environment.default 369 environment = Environment.default
360 environment.enable_plugin(Plugin1.name) 370 environment.enable_plugin(Plugin1.name)
361 environment.enable_plugin(Plugin2.name) 371 environment.enable_plugin(Plugin2.name)
@@ -390,6 +400,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -390,6 +400,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
390 plugin2_path2 = '/plugin2/'+js2 400 plugin2_path2 = '/plugin2/'+js2
391 plugin2_path3 = '/plugin2/'+js3 401 plugin2_path3 = '/plugin2/'+js3
392 402
  403 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
  404 +
393 environment = Environment.default 405 environment = Environment.default
394 environment.enable_plugin(Plugin1.name) 406 environment.enable_plugin(Plugin1.name)
395 environment.enable_plugin(Plugin2.name) 407 environment.enable_plugin(Plugin2.name)
@@ -418,6 +430,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -418,6 +430,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
418 end 430 end
419 end 431 end
420 432
  433 + Noosfero::Plugin.stubs(:all).returns([TestBodyBeginning1Plugin.name, TestBodyBeginning2Plugin.name])
  434 +
421 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestBodyBeginning1Plugin.new, TestBodyBeginning2Plugin.new]) 435 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestBodyBeginning1Plugin.new, TestBodyBeginning2Plugin.new])
422 436
423 get :index 437 get :index
@@ -442,6 +456,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -442,6 +456,8 @@ class ApplicationControllerTest &lt; ActionController::TestCase
442 end 456 end
443 end 457 end
444 458
  459 + Noosfero::Plugin.stubs(:all).returns([TestHeadEnding1Plugin.name, TestHeadEnding2Plugin.name])
  460 +
445 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestHeadEnding1Plugin.new, TestHeadEnding2Plugin.new]) 461 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestHeadEnding1Plugin.new, TestHeadEnding2Plugin.new])
446 462
447 get :index 463 get :index
@@ -506,6 +522,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -506,6 +522,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
506 :block => lambda {} } 522 :block => lambda {} }
507 end 523 end
508 end 524 end
  525 + Noosfero::Plugin.stubs(:all).returns([FilterPlugin.name])
509 526
510 Noosfero::Plugin.load_plugin_filters(FilterPlugin) 527 Noosfero::Plugin.load_plugin_filters(FilterPlugin)
511 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([FilterPlugin.new]) 528 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([FilterPlugin.new])
@@ -525,6 +542,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -525,6 +542,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
525 :block => proc {'plugin block called'} } 542 :block => proc {'plugin block called'} }
526 end 543 end
527 end 544 end
  545 + Noosfero::Plugin.stubs(:all).returns([OtherFilterPlugin.name])
528 546
529 Noosfero::Plugin.load_plugin_filters(OtherFilterPlugin) 547 Noosfero::Plugin.load_plugin_filters(OtherFilterPlugin)
530 environment1 = fast_create(Environment, :name => 'test environment') 548 environment1 = fast_create(Environment, :name => 'test environment')
@@ -539,4 +557,18 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -539,4 +557,18 @@ class ApplicationControllerTest &lt; ActionController::TestCase
539 assert_equal nil, @controller.application_controller_test_other_filter_plugin_filter_plugin 557 assert_equal nil, @controller.application_controller_test_other_filter_plugin_filter_plugin
540 end 558 end
541 559
  560 + should 'display meta tags for social media' do
  561 + get :index
  562 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:card', :value => 'summary' }
  563 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:title', :content => assigns(:environment).name }
  564 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:description', :content => assigns(:environment).name }
  565 + assert_no_tag :tag => 'meta', :attributes => { :name => 'twitter:image' }
  566 + assert_tag :tag => 'meta', :attributes => { :property => 'og:type', :content => 'website' }
  567 + assert_tag :tag => 'meta', :attributes => { :property => 'og:url', :content => assigns(:environment).top_url }
  568 + assert_tag :tag => 'meta', :attributes => { :property => 'og:title', :content => assigns(:environment).name }
  569 + assert_tag :tag => 'meta', :attributes => { :property => 'og:site_name', :content => assigns(:environment).name }
  570 + assert_tag :tag => 'meta', :attributes => { :property => 'og:description', :content => assigns(:environment).name }
  571 + assert_no_tag :tag => 'meta', :attributes => { :property => 'article:published_time' }
  572 + assert_no_tag :tag => 'meta', :attributes => { :property => 'og:image' }
  573 + end
542 end 574 end
test/functional/catalog_controller_test.rb
@@ -91,6 +91,7 @@ class CatalogControllerTest &lt; ActionController::TestCase @@ -91,6 +91,7 @@ class CatalogControllerTest &lt; ActionController::TestCase
91 proc {"<span id='plugin2'>This is Plugin2 speaking!</span>"} 91 proc {"<span id='plugin2'>This is Plugin2 speaking!</span>"}
92 end 92 end
93 end 93 end
  94 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
94 95
95 product = fast_create(Product, :profile_id => @enterprise.id) 96 product = fast_create(Product, :profile_id => @enterprise.id)
96 environment = Environment.default 97 environment = Environment.default
test/functional/cms_controller_test.rb
@@ -445,24 +445,23 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -445,24 +445,23 @@ class CmsControllerTest &lt; ActionController::TestCase
445 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/ 445 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/
446 end 446 end
447 447
448 - should 'display link for selecting categories' do  
449 - # FIXME  
450 - assert true  
451 - #env = Environment.default  
452 - #top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!  
453 - #c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!  
454 - #c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!  
455 - #c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!  
456 -  
457 - #article = Article.new(:name => 'test')  
458 - #article.profile = profile  
459 - #article.save!  
460 -  
461 - #get :edit, :profile => profile.identifier, :id => article.id  
462 -  
463 - #[c1,c2,c3].each do |item|  
464 - # assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }  
465 - #end 448 + should 'display link for selecting top categories' do
  449 + env = Environment.default
  450 + top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!
  451 + top2 = env.categories.build(:display_in_menu => true, :name => 'Top-Level category 2'); top2.save!
  452 + c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!
  453 + c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!
  454 + c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!
  455 +
  456 + article = Article.new(:name => 'test')
  457 + article.profile = profile
  458 + article.save!
  459 +
  460 + get :edit, :profile => profile.identifier, :id => article.id
  461 +
  462 + [top, top2].each do |item|
  463 + assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }
  464 + end
466 end 465 end
467 466
468 should 'be able to associate articles with categories' do 467 should 'be able to associate articles with categories' do
test/functional/content_viewer_controller_test.rb
@@ -72,9 +72,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -72,9 +72,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
72 get :view_page, :profile => 'someone', :page => [ '500.html' ] 72 get :view_page, :profile => 'someone', :page => [ '500.html' ]
73 73
74 assert_response :success 74 assert_response :success
75 - assert_match /^text\/html/, @response.headers['Content-Type']  
76 - assert @response.headers['Content-Disposition'].present?  
77 - assert_match /attachment/, @response.headers['Content-Disposition'] 75 + assert_match /#{html.public_filename}/, @response.body
78 end 76 end
79 77
80 should 'produce a download-link when article is not text/html' do 78 should 'produce a download-link when article is not text/html' do
@@ -577,14 +575,6 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -577,14 +575,6 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
577 assert_template 'view_page' 575 assert_template 'view_page'
578 end 576 end
579 577
580 - should 'download data for image when not view' do  
581 - file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile)  
582 - get :view_page, :profile => profile.identifier, :page => file.path  
583 -  
584 - assert_response :success  
585 - assert_template nil  
586 - end  
587 -  
588 should "display 'Upload files' when create children of image gallery" do 578 should "display 'Upload files' when create children of image gallery" do
589 login_as(profile.identifier) 579 login_as(profile.identifier)
590 f = Gallery.create!(:name => 'gallery', :profile => profile) 580 f = Gallery.create!(:name => 'gallery', :profile => profile)
@@ -741,16 +731,6 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -741,16 +731,6 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
741 assert_tag :tag => 'li', :attributes => {:title => 'my img title', :class => 'image-gallery-item'}, :child => {:tag => 'span', :content => 'my img title'} 731 assert_tag :tag => 'li', :attributes => {:title => 'my img title', :class => 'image-gallery-item'}, :child => {:tag => 'span', :content => 'my img title'}
742 end 732 end
743 733
744 - should 'not allow html on title of the images' do  
745 - login_as(profile.identifier)  
746 - folder = fast_create(Gallery, :profile_id => profile.id)  
747 - file = UploadedFile.create!(:title => '<b>my img title</b>', :profile => profile, :parent => folder, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))  
748 -  
749 - get :view_page, :profile => profile.identifier, :page => folder.path  
750 -  
751 - assert_tag :tag => 'li', :attributes => {:title => 'my img title', :class => 'image-gallery-item'}, :child => {:tag => 'span', :content => 'my img title'}  
752 - end  
753 -  
754 should 'allow publisher owner view private articles' do 734 should 'allow publisher owner view private articles' do
755 c = Community.create!(:name => 'test_com') 735 c = Community.create!(:name => 'test_com')
756 u = create_user_with_permission('test_user', 'publish_content', c) 736 u = create_user_with_permission('test_user', 'publish_content', c)
@@ -1209,6 +1189,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1209,6 +1189,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1209 class Plugin2 < Noosfero::Plugin 1189 class Plugin2 < Noosfero::Plugin
1210 def content_remove_edit(content); false; end 1190 def content_remove_edit(content); false; end
1211 end 1191 end
  1192 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1212 1193
1213 environment.enable_plugin(Plugin1.name) 1194 environment.enable_plugin(Plugin1.name)
1214 environment.enable_plugin(Plugin2.name) 1195 environment.enable_plugin(Plugin2.name)
@@ -1225,6 +1206,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1225,6 +1206,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1225 class Plugin2 < Noosfero::Plugin 1206 class Plugin2 < Noosfero::Plugin
1226 def content_expire_edit(content); nil; end 1207 def content_expire_edit(content); nil; end
1227 end 1208 end
  1209 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1228 1210
1229 environment.enable_plugin(Plugin1.name) 1211 environment.enable_plugin(Plugin1.name)
1230 environment.enable_plugin(Plugin2.name) 1212 environment.enable_plugin(Plugin2.name)
@@ -1270,6 +1252,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1270,6 +1252,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1270 } 1252 }
1271 end 1253 end
1272 end 1254 end
  1255 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1273 1256
1274 Environment.default.enable_plugin(Plugin1.name) 1257 Environment.default.enable_plugin(Plugin1.name)
1275 Environment.default.enable_plugin(Plugin2.name) 1258 Environment.default.enable_plugin(Plugin2.name)
@@ -1294,6 +1277,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1294,6 +1277,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1294 scope.where(:referrer => 'kernel.org') 1277 scope.where(:referrer => 'kernel.org')
1295 end 1278 end
1296 end 1279 end
  1280 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1297 1281
1298 Environment.default.enable_plugin(Plugin1) 1282 Environment.default.enable_plugin(Plugin1)
1299 Environment.default.enable_plugin(Plugin2) 1283 Environment.default.enable_plugin(Plugin2)
@@ -1351,6 +1335,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1351,6 +1335,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1351 } 1335 }
1352 end 1336 end
1353 end 1337 end
  1338 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
1354 1339
1355 Environment.default.enable_plugin(Plugin1.name) 1340 Environment.default.enable_plugin(Plugin1.name)
1356 Environment.default.enable_plugin(Plugin2.name) 1341 Environment.default.enable_plugin(Plugin2.name)
@@ -1365,8 +1350,47 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -1365,8 +1350,47 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
1365 1350
1366 should 'display link to download of non-recognized file types on its page' do 1351 should 'display link to download of non-recognized file types on its page' do
1367 file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'bin/unknown'), :profile => profile) 1352 file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'bin/unknown'), :profile => profile)
1368 - get :view_page, file.url.merge(:view=>:true)  
1369 - assert_match /this is a sample text file/, @response.body 1353 + get :view_page, file.url
  1354 + assert_match /#{file.public_filename}/, @response.body
  1355 + end
  1356 +
  1357 + should 'not count hit from bots' do
  1358 + article = fast_create(Article, :profile_id => profile.id)
  1359 + assert_no_difference article, :hits do
  1360 + @request.env['HTTP_USER_AGENT'] = 'bot'
  1361 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1362 + @request.env['HTTP_USER_AGENT'] = 'spider'
  1363 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1364 + @request.env['HTTP_USER_AGENT'] = 'crawler'
  1365 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1366 + @request.env['HTTP_USER_AGENT'] = '(http://some-crawler.com)'
  1367 + get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
  1368 + article.reload
  1369 + end
  1370 + end
  1371 +
  1372 + should 'add meta tags with article info' do
  1373 + a = TinyMceArticle.create(:name => 'Article to be shared', :body => 'This article should be shared with all social networks', :profile => profile)
  1374 +
  1375 + get :view_page, :profile => profile.identifier, :page => [ a.name.to_slug ]
  1376 +
  1377 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:title', :content => /#{a.name} - #{a.profile.name}/ }
  1378 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:description', :content => a.body }
  1379 + assert_no_tag :tag => 'meta', :attributes => { :name => 'twitter:image' }
  1380 + assert_tag :tag => 'meta', :attributes => { :property => 'og:type', :content => 'article' }
  1381 + assert_tag :tag => 'meta', :attributes => { :property => 'og:url', :content => /\/#{profile.identifier}\/#{a.name.to_slug}/ }
  1382 + assert_tag :tag => 'meta', :attributes => { :property => 'og:title', :content => /#{a.name} - #{a.profile.name}/ }
  1383 + assert_tag :tag => 'meta', :attributes => { :property => 'og:site_name', :content => a.profile.name }
  1384 + assert_tag :tag => 'meta', :attributes => { :property => 'og:description', :content => a.body }
  1385 + assert_no_tag :tag => 'meta', :attributes => { :property => 'og:image' }
  1386 + end
  1387 +
  1388 + should 'add meta tags with article images' do
  1389 + a = TinyMceArticle.create(:name => 'Article to be shared with images', :body => 'This article should be shared with all social networks <img src="/images/x.png" />', :profile => profile)
  1390 +
  1391 + get :view_page, :profile => profile.identifier, :page => [ a.name.to_slug ]
  1392 + assert_tag :tag => 'meta', :attributes => { :name => 'twitter:image', :content => /\/images\/x.png/ }
  1393 + assert_tag :tag => 'meta', :attributes => { :property => 'og:image', :content => /\/images\/x.png/ }
1370 end 1394 end
1371 1395
1372 end 1396 end
test/functional/embed_controller_test.rb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class EmbedControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + login_as(create_admin_user(Environment.default))
  7 + @block = LoginBlock.create!
  8 + @block.class.any_instance.stubs(:embedable?).returns(true)
  9 + @environment = Environment.default
  10 + @environment.boxes.create!
  11 + @environment.boxes.first.blocks << @block
  12 + end
  13 +
  14 + should 'be able to get embed block' do
  15 + get :block, :id => @block.id
  16 + assert_tag :tag => 'div', :attributes => { :id => "block-#{@block.id}" }
  17 + end
  18 +
  19 + should 'display error message when not found block' do
  20 + Block.delete_all
  21 + get :block, :id => 1
  22 + assert_tag :tag => 'div', :attributes => { :id => "not-found" }
  23 + end
  24 +
  25 + should 'display error message when block is not visible/public' do
  26 + @block.display = 'never'
  27 + assert @block.save
  28 + get :block, :id => @block.id
  29 + assert_tag :tag => 'div', :attributes => { :id => "unavailable" }
  30 + end
  31 +
  32 + should 'display error message when block is not embedable' do
  33 + @block.class.any_instance.stubs(:embedable?).returns(false)
  34 + get :block, :id => @block.id
  35 + assert_tag :tag => 'div', :attributes => { :id => "unavailable" }
  36 + end
  37 +
  38 +
  39 +end
test/functional/enterprise_registration_controller_test.rb
@@ -193,6 +193,7 @@ class EnterpriseRegistrationControllerTest &lt; ActionController::TestCase @@ -193,6 +193,7 @@ class EnterpriseRegistrationControllerTest &lt; ActionController::TestCase
193 {'plugin2' => 'Plugin 2'} 193 {'plugin2' => 'Plugin 2'}
194 end 194 end
195 end 195 end
  196 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
196 197
197 environment = Environment.default 198 environment = Environment.default
198 environment.enable_plugin(Plugin1.name) 199 environment.enable_plugin(Plugin1.name)
test/functional/environment_design_controller_test.rb
@@ -6,6 +6,8 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end @@ -6,6 +6,8 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end
6 6
7 class EnvironmentDesignControllerTest < ActionController::TestCase 7 class EnvironmentDesignControllerTest < ActionController::TestCase
8 8
  9 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  10 + # the Noosfero core soon, see ActionItem3045
9 ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 11 ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
10 12
11 def setup 13 def setup
@@ -83,6 +85,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -83,6 +85,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
83 assert_tag :tag => 'p', :attributes => { :id => 'no_portal_community' } 85 assert_tag :tag => 'p', :attributes => { :id => 'no_portal_community' }
84 end 86 end
85 87
  88 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  89 + # the Noosfero core soon, see ActionItem3045
86 should 'be able to edit EnvironmentStatisticsBlock' do 90 should 'be able to edit EnvironmentStatisticsBlock' do
87 login_as(create_admin_user(Environment.default)) 91 login_as(create_admin_user(Environment.default))
88 b = EnvironmentStatisticsBlock.create! 92 b = EnvironmentStatisticsBlock.create!
@@ -366,4 +370,47 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -366,4 +370,47 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
366 assert @controller.instance_variable_get('@side_block_types').include?(CustomBlock8) 370 assert @controller.instance_variable_get('@side_block_types').include?(CustomBlock8)
367 end 371 end
368 372
  373 + should 'clone a block' do
  374 + login_as(create_admin_user(Environment.default))
  375 + block = TagsBlock.create!
  376 + assert_difference TagsBlock, :count, 1 do
  377 + post :clone_block, :id => block.id
  378 + assert_response :redirect
  379 + end
  380 + end
  381 +
  382 + should 'return a list of paths from portal related to the words used in the query search' do
  383 + env = Environment.default
  384 + login_as(create_admin_user(env))
  385 + community = fast_create(Community, :environment_id => env)
  386 + env.portal_community = community
  387 + env.enable('use_portal_community')
  388 + env.save
  389 + @controller.stubs(:boxes_holder).returns(env)
  390 + article1 = fast_create(Article, :profile_id => community.id, :name => "Some thing")
  391 + article2 = fast_create(Article, :profile_id => community.id, :name => "Some article")
  392 + article3 = fast_create(Article, :profile_id => community.id, :name => "Not an article")
  393 +
  394 + xhr :get, :search_autocomplete, :query => 'Some'
  395 +
  396 + json_response = ActiveSupport::JSON.decode(@response.body)
  397 +
  398 + assert_response :success
  399 + assert_equal json_response.include?("/{portal}/"+article1.path), true
  400 + assert_equal json_response.include?("/{portal}/"+article2.path), true
  401 + assert_equal json_response.include?("/{portal}/"+article3.path), false
  402 + end
  403 +
  404 + should 'return empty if portal not configured' do
  405 + env = Environment.default
  406 + login_as(create_admin_user(env))
  407 +
  408 + xhr :get, :search_autocomplete, :query => 'Some'
  409 +
  410 + json_response = ActiveSupport::JSON.decode(@response.body)
  411 +
  412 + assert_response :success
  413 + assert_equal json_response, []
  414 + end
  415 +
369 end 416 end
test/functional/events_controller_test.rb
@@ -38,4 +38,20 @@ class EventsControllerTest &lt; ActionController::TestCase @@ -38,4 +38,20 @@ class EventsControllerTest &lt; ActionController::TestCase
38 assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{next_month.year}/#{next_month.month}"}, :content => next_month_name 38 assert_tag :tag =>'a', :attributes => {:href => "/profile/#{profile.identifier}/events/#{next_month.year}/#{next_month.month}"}, :content => next_month_name
39 end 39 end
40 40
  41 + should 'see the events paginated' do
  42 + 30.times do |i|
  43 + profile.events << Event.new(:name => "Lesson #{i}", :start_date => Date.today)
  44 + end
  45 + get :events, :profile => profile.identifier
  46 + assert_equal 20, assigns(:events).count
  47 + end
  48 +
  49 + should 'show events of specific day' do
  50 + profile.events << Event.new(:name => 'Joao Birthday', :start_date => Date.new(2009, 10, 28))
  51 +
  52 + get :events_by_day, :profile => profile.identifier, :year => 2009, :month => 10, :day => 28
  53 +
  54 + assert_tag :tag => 'a', :content => /Joao Birthday/
  55 + end
  56 +
41 end 57 end
test/functional/friends_controller_test.rb
@@ -68,6 +68,7 @@ class FriendsControllerTest &lt; ActionController::TestCase @@ -68,6 +68,7 @@ class FriendsControllerTest &lt; ActionController::TestCase
68 false 68 false
69 end 69 end
70 end 70 end
  71 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
71 72
72 e = profile.environment 73 e = profile.environment
73 e.enable_plugin(Plugin1.name) 74 e.enable_plugin(Plugin1.name)
test/functional/home_controller_test.rb
@@ -107,6 +107,7 @@ class HomeControllerTest &lt; ActionController::TestCase @@ -107,6 +107,7 @@ class HomeControllerTest &lt; ActionController::TestCase
107 proc {"<a href='plugin2'>Plugin2 link</a>"} 107 proc {"<a href='plugin2'>Plugin2 link</a>"}
108 end 108 end
109 end 109 end
  110 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
110 111
111 Environment.default.enable_plugin(Plugin1) 112 Environment.default.enable_plugin(Plugin1)
112 Environment.default.enable_plugin(Plugin2) 113 Environment.default.enable_plugin(Plugin2)
@@ -129,6 +130,7 @@ class HomeControllerTest &lt; ActionController::TestCase @@ -129,6 +130,7 @@ class HomeControllerTest &lt; ActionController::TestCase
129 true 130 true
130 end 131 end
131 end 132 end
  133 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
132 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new]) 134 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new])
133 135
134 get :index 136 get :index
test/functional/invite_controller_test.rb
@@ -7,6 +7,7 @@ class InviteControllerTest &lt; ActionController::TestCase @@ -7,6 +7,7 @@ class InviteControllerTest &lt; ActionController::TestCase
7 @friend = create_user('thefriend').person 7 @friend = create_user('thefriend').person
8 @community = fast_create(Community) 8 @community = fast_create(Community)
9 login_as ('testuser') 9 login_as ('testuser')
  10 + Delayed::Job.destroy_all
10 end 11 end
11 attr_accessor :profile, :friend, :community 12 attr_accessor :profile, :friend, :community
12 13
@@ -230,7 +231,8 @@ class InviteControllerTest &lt; ActionController::TestCase @@ -230,7 +231,8 @@ class InviteControllerTest &lt; ActionController::TestCase
230 231
231 contact_list = ContactList.create 232 contact_list = ContactList.create
232 post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id 233 post :select_friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :contact_list => contact_list.id
233 - assert_equal 'pt', Delayed::Job.first.payload_object.locale 234 + job = Delayed::Job.where("handler LIKE '%InvitationJob%'").first
  235 + assert_equal 'pt', job.payload_object.locale
234 end 236 end
235 237
236 private 238 private
test/functional/memberships_controller_test.rb
@@ -234,6 +234,7 @@ class MembershipsControllerTest &lt; ActionController::TestCase @@ -234,6 +234,7 @@ class MembershipsControllerTest &lt; ActionController::TestCase
234 {'plugin2' => 'Plugin 2'} 234 {'plugin2' => 'Plugin 2'}
235 end 235 end
236 end 236 end
  237 + Noosfero::Plugin.stubs(:all).returns([Plugin1.name, Plugin2.name])
237 238
238 environment = Environment.default 239 environment = Environment.default
239 environment.enable_plugin(Plugin1.name) 240 environment.enable_plugin(Plugin1.name)
test/functional/plugins_controller_test.rb
@@ -47,7 +47,7 @@ class PluginsControllerTest &lt; ActionController::TestCase @@ -47,7 +47,7 @@ class PluginsControllerTest &lt; ActionController::TestCase
47 end 47 end
48 end 48 end
49 49
50 - Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s,Plugin2.to_s]) 50 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
51 51
52 get :index 52 get :index
53 53
test/functional/profile_controller_test.rb
@@ -766,21 +766,25 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -766,21 +766,25 @@ class ProfileControllerTest &lt; ActionController::TestCase
766 p1= fast_create(Person) 766 p1= fast_create(Person)
767 p2= fast_create(Person) 767 p2= fast_create(Person)
768 assert !p1.is_a_friend?(p2) 768 assert !p1.is_a_friend?(p2)
  769 +
769 p3= fast_create(Person) 770 p3= fast_create(Person)
770 p3.add_friend(p1) 771 p3.add_friend(p1)
771 assert p3.is_a_friend?(p1) 772 assert p3.is_a_friend?(p1)
772 - ActionTracker::Record.destroy_all 773 +
  774 + ActionTracker::Record.delete_all
  775 +
773 UserStampSweeper.any_instance.stubs(:current_user).returns(p1) 776 UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
774 - create(Scrap, defaults_for_scrap(:sender => p1, :receiver => p1)) 777 + create(Scrap,defaults_for_scrap(:sender => p1, :receiver => p1))
775 a1 = ActionTracker::Record.last 778 a1 = ActionTracker::Record.last
  779 +
776 UserStampSweeper.any_instance.stubs(:current_user).returns(p2) 780 UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
777 create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) 781 create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3))
778 a2 = ActionTracker::Record.last 782 a2 = ActionTracker::Record.last
  783 +
779 UserStampSweeper.any_instance.stubs(:current_user).returns(p3) 784 UserStampSweeper.any_instance.stubs(:current_user).returns(p3)
780 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1)) 785 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1))
781 a3 = ActionTracker::Record.last 786 a3 = ActionTracker::Record.last
782 787
783 -  
784 @controller.stubs(:logged_in?).returns(true) 788 @controller.stubs(:logged_in?).returns(true)
785 user = mock() 789 user = mock()
786 user.stubs(:person).returns(p3) 790 user.stubs(:person).returns(p3)
@@ -790,24 +794,29 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -790,24 +794,29 @@ class ProfileControllerTest &lt; ActionController::TestCase
790 794
791 process_delayed_job_queue 795 process_delayed_job_queue
792 get :index, :profile => p1.identifier 796 get :index, :profile => p1.identifier
793 - assert_not_nil assigns(:network_activities)  
794 - assert_equivalent [a1,a3], assigns(:network_activities) 797 +
  798 + assert_equivalent [a1,a3].map(&:id), assigns(:network_activities).map(&:id)
795 end 799 end
796 800
797 should 'the network activity be visible only to profile followers' do 801 should 'the network activity be visible only to profile followers' do
798 p1= fast_create(Person) 802 p1= fast_create(Person)
799 p2= fast_create(Person) 803 p2= fast_create(Person)
800 assert !p1.is_a_friend?(p2) 804 assert !p1.is_a_friend?(p2)
  805 +
801 p3= fast_create(Person) 806 p3= fast_create(Person)
802 p3.add_friend(p1) 807 p3.add_friend(p1)
803 assert p3.is_a_friend?(p1) 808 assert p3.is_a_friend?(p1)
804 - ActionTracker::Record.destroy_all 809 +
  810 + ActionTracker::Record.delete_all
  811 +
805 UserStampSweeper.any_instance.stubs(:current_user).returns(p1) 812 UserStampSweeper.any_instance.stubs(:current_user).returns(p1)
806 create(Scrap, defaults_for_scrap(:sender => p1, :receiver => p1)) 813 create(Scrap, defaults_for_scrap(:sender => p1, :receiver => p1))
807 a1 = ActionTracker::Record.last 814 a1 = ActionTracker::Record.last
  815 +
808 UserStampSweeper.any_instance.stubs(:current_user).returns(p2) 816 UserStampSweeper.any_instance.stubs(:current_user).returns(p2)
809 create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3)) 817 create(Scrap, defaults_for_scrap(:sender => p2, :receiver => p3))
810 a2 = ActionTracker::Record.last 818 a2 = ActionTracker::Record.last
  819 +
811 UserStampSweeper.any_instance.stubs(:current_user).returns(p3) 820 UserStampSweeper.any_instance.stubs(:current_user).returns(p3)
812 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1)) 821 create(Scrap, defaults_for_scrap(:sender => p3, :receiver => p1))
813 a3 = ActionTracker::Record.last 822 a3 = ActionTracker::Record.last
@@ -817,8 +826,9 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -817,8 +826,9 @@ class ProfileControllerTest &lt; ActionController::TestCase
817 user.stubs(:person).returns(p2) 826 user.stubs(:person).returns(p2)
818 user.stubs(:login).returns('some') 827 user.stubs(:login).returns('some')
819 @controller.stubs(:current_user).returns(user) 828 @controller.stubs(:current_user).returns(user)
  829 +
820 get :index, :profile => p1.identifier 830 get :index, :profile => p1.identifier
821 - assert_equal [], assigns(:network_activities) 831 + assert assigns(:network_activities).blank?
822 832
823 user = mock() 833 user = mock()
824 user.stubs(:person).returns(p3) 834 user.stubs(:person).returns(p3)
@@ -826,6 +836,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -826,6 +836,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
826 @controller.stubs(:current_user).returns(user) 836 @controller.stubs(:current_user).returns(user)
827 Person.any_instance.stubs(:follows?).returns(true) 837 Person.any_instance.stubs(:follows?).returns(true)
828 process_delayed_job_queue 838 process_delayed_job_queue
  839 +
829 get :index, :profile => p3.identifier 840 get :index, :profile => p3.identifier
830 assert_equivalent [a1,a3], assigns(:network_activities) 841 assert_equivalent [a1,a3], assigns(:network_activities)
831 end 842 end
@@ -1241,6 +1252,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -1241,6 +1252,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
1241 {:title => 'Plugin2 tab', :id => 'plugin2_tab', :content => proc { 'Content from plugin2.' }} 1252 {:title => 'Plugin2 tab', :id => 'plugin2_tab', :content => proc { 'Content from plugin2.' }}
1242 end 1253 end
1243 end 1254 end
  1255 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
1244 1256
1245 e = profile.environment 1257 e = profile.environment
1246 e.enable_plugin(Plugin1.name) 1258 e.enable_plugin(Plugin1.name)
test/functional/profile_design_controller_test.rb
@@ -173,7 +173,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -173,7 +173,8 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
173 should 'have options to display blocks' do 173 should 'have options to display blocks' do
174 get :edit, :profile => 'designtestuser', :id => @b1.id 174 get :edit, :profile => 'designtestuser', :id => @b1.id
175 %w[always home_page_only except_home_page never].each do |option| 175 %w[always home_page_only except_home_page never].each do |option|
176 - assert_tag :input, :attributes => { :type => 'radio', :value => option} 176 + assert_tag :select, :attributes => {:name => 'block[display]'},
  177 + :descendant => {:tag => 'option', :attributes => {:value => option}}
177 end 178 end
178 end 179 end
179 180
@@ -302,24 +303,42 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -302,24 +303,42 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
302 303
303 should 'not edit main block with never option' do 304 should 'not edit main block with never option' do
304 get :edit, :profile => 'designtestuser', :id => @b4.id 305 get :edit, :profile => 'designtestuser', :id => @b4.id
305 - assert_no_tag :input, :attributes => { :type => 'radio', :value => 'never'} 306 + assert_no_tag :select, :attributes => {:name => 'block[display]'},
  307 + :descendant => {:tag => 'option', :attributes => {:value => 'never'}}
306 end 308 end
307 309
308 should 'not edit main block with home_page_only option' do 310 should 'not edit main block with home_page_only option' do
309 get :edit, :profile => 'designtestuser', :id => @b4.id 311 get :edit, :profile => 'designtestuser', :id => @b4.id
310 - assert_no_tag :input, :attributes => { :type => 'radio', :value => 'home_page_only'} 312 + assert_no_tag :select, :attributes => {:name => 'block[display]'},
  313 + :descendant => {:tag => 'option', :attributes => {:value => 'home_page_only'}}
311 end 314 end
312 315
313 should 'edit main block with always option' do 316 should 'edit main block with always option' do
314 get :edit, :profile => 'designtestuser', :id => @b4.id 317 get :edit, :profile => 'designtestuser', :id => @b4.id
315 - assert_tag :input, :attributes => { :type => 'radio', :value => 'always'} 318 + assert_tag :select, :attributes => {:name => 'block[display]'},
  319 + :descendant => {:tag => 'option', :attributes => {:value => 'always'}}
316 end 320 end
317 321
318 should 'edit main block with except_home_page option' do 322 should 'edit main block with except_home_page option' do
319 get :edit, :profile => 'designtestuser', :id => @b4.id 323 get :edit, :profile => 'designtestuser', :id => @b4.id
320 - assert_tag :input, :attributes => { :type => 'radio', :value => 'except_home_page'} 324 + assert_tag :select, :attributes => {:name=> 'block[display]'},
  325 + :descendant => {:tag => 'option', :attributes => {:value => 'except_home_page'}}
321 end 326 end
322 327
  328 + should 'return a list of paths related to the words used in the query search' do
  329 + article1 = fast_create(Article, :profile_id => @profile.id, :name => "Some thing")
  330 + article2 = fast_create(Article, :profile_id => @profile.id, :name => "Some article")
  331 + article3 = fast_create(Article, :profile_id => @profile.id, :name => "Not an article")
  332 +
  333 + xhr :get, :search_autocomplete, :profile => 'designtestuser' , :query => 'Some'
  334 +
  335 + json_response = ActiveSupport::JSON.decode(@response.body)
  336 +
  337 + assert_response :success
  338 + assert_equal json_response.include?("/{profile}/"+article1.path), true
  339 + assert_equal json_response.include?("/{profile}/"+article2.path), true
  340 + assert_equal json_response.include?("/{profile}/"+article3.path), false
  341 + end
323 342
324 ###################################################### 343 ######################################################
325 # END - tests for BoxOrganizerController features 344 # END - tests for BoxOrganizerController features
@@ -739,7 +758,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -739,7 +758,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
739 should 'clone a block' do 758 should 'clone a block' do
740 block = create(ProfileImageBlock, :box => profile.boxes.first) 759 block = create(ProfileImageBlock, :box => profile.boxes.first)
741 assert_difference 'ProfileImageBlock.count', 1 do 760 assert_difference 'ProfileImageBlock.count', 1 do
742 - post :clone, :id => block.id, :profile => profile.identifier 761 + post :clone_block, :id => block.id, :profile => profile.identifier
743 assert_response :redirect 762 assert_response :redirect
744 end 763 end
745 end 764 end
test/functional/profile_editor_controller_test.rb
@@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
73 get :edit, :profile => profile.identifier 73 get :edit, :profile => profile.identifier
74 assert_response :success 74 assert_response :success
75 assert_template 'edit' 75 assert_template 'edit'
76 - assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]', :value => cat2.id} 76 + assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]'}
  77 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
77 end 78 end
78 79
79 should 'save categorization of profile' do 80 should 'save categorization of profile' do
@@ -237,7 +238,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -237,7 +238,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
237 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent_id => cat1.id) 238 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent_id => cat1.id)
238 person = create_user('testuser').person 239 person = create_user('testuser').person
239 get :edit, :profile => 'testuser' 240 get :edit, :profile => 'testuser'
240 - assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'profile_data[category_ids][]', :value => cat2.id} 241 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
241 end 242 end
242 243
243 should 'render edit template' do 244 should 'render edit template' do
@@ -868,6 +869,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -868,6 +869,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
868 {:title => "Plugin2 button", :icon => 'plugin2_icon', :url => 'plugin2_url'} 869 {:title => "Plugin2 button", :icon => 'plugin2_icon', :url => 'plugin2_url'}
869 end 870 end
870 end 871 end
  872 + Noosfero::Plugin.stubs(:all).returns([TestControlPanelButtons1.to_s, TestControlPanelButtons2.to_s])
871 873
872 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestControlPanelButtons1.new, TestControlPanelButtons2.new]) 874 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestControlPanelButtons1.new, TestControlPanelButtons2.new])
873 875
@@ -883,6 +885,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -883,6 +885,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
883 "<input id='field_added_by_plugin' value='value_of_field_added_by_plugin'/>" 885 "<input id='field_added_by_plugin' value='value_of_field_added_by_plugin'/>"
884 end 886 end
885 end 887 end
  888 + Noosfero::Plugin.stubs(:all).returns([TestProfileEditPlugin.to_s])
886 889
887 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestProfileEditPlugin.new]) 890 Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([TestProfileEditPlugin.new])
888 891
@@ -911,6 +914,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -911,6 +914,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
911 proc {"<strong>Plugin2 text</strong>"} 914 proc {"<strong>Plugin2 text</strong>"}
912 end 915 end
913 end 916 end
  917 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
914 918
915 Environment.default.enable_plugin(Plugin1) 919 Environment.default.enable_plugin(Plugin1)
916 Environment.default.enable_plugin(Plugin2) 920 Environment.default.enable_plugin(Plugin2)
@@ -932,6 +936,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -932,6 +936,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
932 proc {"<strong>Plugin2 text</strong>"} 936 proc {"<strong>Plugin2 text</strong>"}
933 end 937 end
934 end 938 end
  939 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
935 940
936 Environment.default.enable_plugin(Plugin1) 941 Environment.default.enable_plugin(Plugin1)
937 Environment.default.enable_plugin(Plugin2) 942 Environment.default.enable_plugin(Plugin2)
test/functional/search_controller_test.rb
@@ -76,14 +76,14 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -76,14 +76,14 @@ class SearchControllerTest &lt; ActionController::TestCase
76 assert_includes assigns(:searches)[:articles][:results], art 76 assert_includes assigns(:searches)[:articles][:results], art
77 end 77 end
78 78
79 - should 'redirect contents to articles' do 79 + should 'redirect contents to articles' do
80 person = fast_create(Person) 80 person = fast_create(Person)
81 art = create_article_with_optional_category('an article to be found', person) 81 art = create_article_with_optional_category('an article to be found', person)
82 82
83 get 'contents', :query => 'article found' 83 get 'contents', :query => 'article found'
84 - # full description to avoid deprecation warning 84 + # full description to avoid deprecation warning
85 assert_redirected_to :controller => :search, :action => :articles, :query => 'article found' 85 assert_redirected_to :controller => :search, :action => :articles, :query => 'article found'
86 - end 86 + end
87 87
88 # 'assets' outside any category 88 # 'assets' outside any category
89 should 'list articles in general' do 89 should 'list articles in general' do
@@ -167,6 +167,7 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -167,6 +167,7 @@ class SearchControllerTest &lt; ActionController::TestCase
167 proc {"<span id='plugin2'>This is Plugin2 speaking!</span>"} 167 proc {"<span id='plugin2'>This is Plugin2 speaking!</span>"}
168 end 168 end
169 end 169 end
  170 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
170 171
171 enterprise = fast_create(Enterprise) 172 enterprise = fast_create(Enterprise)
172 prod_cat = fast_create(ProductCategory) 173 prod_cat = fast_create(ProductCategory)
@@ -193,6 +194,7 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -193,6 +194,7 @@ class SearchControllerTest &lt; ActionController::TestCase
193 return { :name => _('Property2'), :content => proc { link_to(product.name, '/plugin2') } } 194 return { :name => _('Property2'), :content => proc { link_to(product.name, '/plugin2') } }
194 end 195 end
195 end 196 end
  197 + Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin2.to_s])
196 enterprise = fast_create(Enterprise) 198 enterprise = fast_create(Enterprise)
197 prod_cat = fast_create(ProductCategory) 199 prod_cat = fast_create(ProductCategory)
198 product = fast_create(Product, {:profile_id => enterprise.id, :name => "produto1", :product_category_id => prod_cat.id}, :search => true) 200 product = fast_create(Product, {:profile_id => enterprise.id, :name => "produto1", :product_category_id => prod_cat.id}, :search => true)
@@ -261,10 +263,10 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -261,10 +263,10 @@ class SearchControllerTest &lt; ActionController::TestCase
261 263
262 should 'render specific action when only one asset is enabled' do 264 should 'render specific action when only one asset is enabled' do
263 environment = Environment.default 265 environment = Environment.default
264 - # article is not disabled 266 + # article is not disabled
265 [:enterprises, :people, :communities, :products, :events].select do |key, name| 267 [:enterprises, :people, :communities, :products, :events].select do |key, name|
266 - environment.enable('disable_asset_' + key.to_s)  
267 - end 268 + environment.enable('disable_asset_' + key.to_s)
  269 + end
268 environment.save! 270 environment.save!
269 @controller.stubs(:environment).returns(environment) 271 @controller.stubs(:environment).returns(environment)
270 272
@@ -276,25 +278,25 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -276,25 +278,25 @@ class SearchControllerTest &lt; ActionController::TestCase
276 assert !assigns(:searches).has_key?(:communities) 278 assert !assigns(:searches).has_key?(:communities)
277 assert !assigns(:searches).has_key?(:products) 279 assert !assigns(:searches).has_key?(:products)
278 assert !assigns(:searches).has_key?(:events) 280 assert !assigns(:searches).has_key?(:events)
279 - end 281 + end
280 282
281 should 'search all enabled assets in general search' do 283 should 'search all enabled assets in general search' do
282 ent1 = create_profile_with_optional_category(Enterprise, 'test enterprise') 284 ent1 = create_profile_with_optional_category(Enterprise, 'test enterprise')
283 prod_cat = create(ProductCategory, :name => 'pctest', :environment => Environment.default) 285 prod_cat = create(ProductCategory, :name => 'pctest', :environment => Environment.default)
284 prod = ent1.products.create!(:name => 'test product', :product_category => prod_cat) 286 prod = ent1.products.create!(:name => 'test product', :product_category => prod_cat)
285 - art = create(Article, :name => 'test article', :profile_id => fast_create(Person).id)  
286 - per = create(Person, :name => 'test person', :identifier => 'test-person', :user_id => fast_create(User).id)  
287 - com = Community.create!(:name => 'test community')  
288 - eve = create(Event, :name => 'test event', :profile_id => fast_create(Person).id) 287 + art = create(Article, :name => 'test article', :profile_id => fast_create(Person).id)
  288 + per = create(Person, :name => 'test person', :identifier => 'test-person', :user_id => fast_create(User).id)
  289 + com = create(Community, :name => 'test community')
  290 + eve = create(Event, :name => 'test event', :profile_id => fast_create(Person).id)
289 291
290 get :index, :query => 'test' 292 get :index, :query => 'test'
291 293
292 [:articles, :enterprises, :people, :communities, :products, :events].select do |key, name| 294 [:articles, :enterprises, :people, :communities, :products, :events].select do |key, name|
293 - !assigns(:environment).enabled?('disable_asset_' + key.to_s)  
294 - end.each do |asset|  
295 - assert !assigns(:searches)[asset][:results].empty?  
296 - end  
297 - end 295 + !assigns(:environment).enabled?('disable_asset_' + key.to_s)
  296 + end.each do |asset|
  297 + assert !assigns(:searches)[asset][:results].empty?
  298 + end
  299 + end
298 300
299 should 'display category image while in directory' do 301 should 'display category image while in directory' do
300 parent = Category.create!(:name => 'category1', :environment => Environment.default) 302 parent = Category.create!(:name => 'category1', :environment => Environment.default)
@@ -320,8 +322,8 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -320,8 +322,8 @@ class SearchControllerTest &lt; ActionController::TestCase
320 person = create_user('someone').person 322 person = create_user('someone').person
321 ten_days_ago = Date.today - 10.day 323 ten_days_ago = Date.today - 10.day
322 324
323 - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)  
324 - ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month) 325 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
  326 + ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
325 327
326 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year 328 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year
327 assert_equal [ev1], assigns(:events) 329 assert_equal [ev1], assigns(:events)
@@ -331,7 +333,7 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -331,7 +333,7 @@ class SearchControllerTest &lt; ActionController::TestCase
331 person = create_user('someone').person 333 person = create_user('someone').person
332 ten_days_ago = Date.today - 10.day 334 ten_days_ago = Date.today - 10.day
333 335
334 - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago) 336 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => ten_days_ago)
335 ev2 = create_event(person, :name => 'event 2', :start_date => ten_days_ago) 337 ev2 = create_event(person, :name => 'event 2', :start_date => ten_days_ago)
336 338
337 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year, :category_path => @category.path.split('/') 339 get :events, :day => ten_days_ago.day, :month => ten_days_ago.month, :year => ten_days_ago.year, :category_path => @category.path.split('/')
@@ -341,8 +343,8 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -341,8 +343,8 @@ class SearchControllerTest &lt; ActionController::TestCase
341 343
342 should 'return events of today when no date specified' do 344 should 'return events of today when no date specified' do
343 person = create_user('someone').person 345 person = create_user('someone').person
344 - ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => Date.today)  
345 - ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month) 346 + ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], :start_date => Date.today)
  347 + ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], :start_date => Date.today - 2.month)
346 348
347 get :events 349 get :events
348 350
@@ -353,9 +355,9 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -353,9 +355,9 @@ class SearchControllerTest &lt; ActionController::TestCase
353 person = create_user('someone').person 355 person = create_user('someone').person
354 356
355 ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id], 357 ev1 = create_event(person, :name => 'event 1', :category_ids => [@category.id],
356 - :start_date => Date.today + 2.month) 358 + :start_date => Date.today + 2.month)
357 ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id], 359 ev2 = create_event(person, :name => 'event 2', :category_ids => [@category.id],
358 - :start_date => Date.today + 2.day) 360 + :start_date => Date.today + 2.day)
359 361
360 get :events 362 get :events
361 363
@@ -374,6 +376,15 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -374,6 +376,15 @@ class SearchControllerTest &lt; ActionController::TestCase
374 assert_equal [ 'upcoming event 1' ], assigns(:searches)[:events][:results].map(&:name) 376 assert_equal [ 'upcoming event 1' ], assigns(:searches)[:events][:results].map(&:name)
375 end 377 end
376 378
  379 + should 'see the events paginated' do
  380 + person = create_user('testuser').person
  381 + 30.times do |i|
  382 + create_event(person, :name => "Event #{i}", :start_date => Date.today)
  383 + end
  384 + get :events
  385 + assert_equal 20, assigns(:events).count
  386 + end
  387 +
377 %w[ people enterprises articles events communities products ].each do |asset| 388 %w[ people enterprises articles events communities products ].each do |asset|
378 should "render asset-specific template when searching for #{asset}" do 389 should "render asset-specific template when searching for #{asset}" do
379 get "#{asset}" 390 get "#{asset}"
@@ -427,8 +438,8 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -427,8 +438,8 @@ class SearchControllerTest &lt; ActionController::TestCase
427 end 438 end
428 439
429 should 'show link to article asset in the see all foot link of the articles block in the category page' do 440 should 'show link to article asset in the see all foot link of the articles block in the category page' do
430 - (1..SearchController::MULTIPLE_SEARCH_LIMIT+1).each do |i|  
431 - a = create_user("test#{i}").person.articles.create!(:name => "article #{i} to be found") 441 + (1..SearchController::MULTIPLE_SEARCH_LIMIT+1).each do |i|
  442 + a = create_user("test#{i}").person.articles.create!(:name => "article #{i} to be found")
432 ArticleCategorization.add_category_to_article(@category, a) 443 ArticleCategorization.add_category_to_article(@category, a)
433 end 444 end
434 445
@@ -553,9 +564,9 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -553,9 +564,9 @@ class SearchControllerTest &lt; ActionController::TestCase
553 c2 = create(Community, :name => 'Testing community 2') 564 c2 = create(Community, :name => 'Testing community 2')
554 c3 = create(Community, :name => 'Testing community 3') 565 c3 = create(Community, :name => 'Testing community 3')
555 ActionTracker::Record.delete_all 566 ActionTracker::Record.delete_all
556 - fast_create(ActionTracker::Record, :target_id => c1, :user_type => 'Profile', :user_id => person, :created_at => Time.now)  
557 - fast_create(ActionTracker::Record, :target_id => c2, :user_type => 'Profile', :user_id => person, :created_at => Time.now)  
558 - fast_create(ActionTracker::Record, :target_id => c2, :user_type => 'Profile', :user_id => person, :created_at => Time.now) 567 + ActionTracker::Record.create!(:target => c1, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
  568 + ActionTracker::Record.create!(:target => c2, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
  569 + ActionTracker::Record.create!(:target => c2, :user => person, :created_at => Time.now, :verb => 'leave_scrap')
559 get :communities, :filter => 'more_active' 570 get :communities, :filter => 'more_active'
560 assert_equal [c2,c1,c3] , assigns(:searches)[:communities][:results] 571 assert_equal [c2,c1,c3] , assigns(:searches)[:communities][:results]
561 end 572 end
@@ -574,55 +585,55 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -574,55 +585,55 @@ class SearchControllerTest &lt; ActionController::TestCase
574 assert_not_includes assigns(:searches)[:communities][:results], p1 585 assert_not_includes assigns(:searches)[:communities][:results], p1
575 end 586 end
576 587
577 - should 'keep old urls working' do  
578 - get :assets, :asset => 'articles' 588 + should 'keep old urls working' do
  589 + get :assets, :asset => 'articles'
579 assert_redirected_to :controller => :search, :action => :articles 590 assert_redirected_to :controller => :search, :action => :articles
580 - get :assets, :asset => 'people' 591 + get :assets, :asset => 'people'
581 assert_redirected_to :controller => :search, :action => :people 592 assert_redirected_to :controller => :search, :action => :people
582 - get :assets, :asset => 'communities' 593 + get :assets, :asset => 'communities'
583 assert_redirected_to :controller => :search, :action => :communities 594 assert_redirected_to :controller => :search, :action => :communities
584 - get :assets, :asset => 'products' 595 + get :assets, :asset => 'products'
585 assert_redirected_to :controller => :search, :action => :products 596 assert_redirected_to :controller => :search, :action => :products
586 - get :assets, :asset => 'enterprises' 597 + get :assets, :asset => 'enterprises'
587 assert_redirected_to :controller => :search, :action => :enterprises 598 assert_redirected_to :controller => :search, :action => :enterprises
588 - get :assets, :asset => 'events' 599 + get :assets, :asset => 'events'
589 assert_redirected_to :controller => :search, :action => :events 600 assert_redirected_to :controller => :search, :action => :events
590 - end 601 + end
591 602
592 - should 'show tag cloud' do  
593 - @controller.stubs(:is_cache_expired?).returns(true) 603 + should 'show tag cloud' do
  604 + @controller.stubs(:is_cache_expired?).returns(true)
594 a = create(Article, :name => 'my article', :profile_id => fast_create(Person).id) 605 a = create(Article, :name => 'my article', :profile_id => fast_create(Person).id)
595 a.tag_list = ['one', 'two'] 606 a.tag_list = ['one', 'two']
596 - a.save_tags 607 + a.save_tags
597 608
598 - get :tags 609 + get :tags
599 610
600 - assert assigns(:tags)["two"] = 1  
601 - assert assigns(:tags)["one"] = 1  
602 - end 611 + assert assigns(:tags)["two"] = 1
  612 + assert assigns(:tags)["one"] = 1
  613 + end
603 614
604 should 'show tagged content' do 615 should 'show tagged content' do
605 - @controller.stubs(:is_cache_expired?).returns(true) 616 + @controller.stubs(:is_cache_expired?).returns(true)
606 a = Article.create!(:name => 'my article', :profile => fast_create(Person)) 617 a = Article.create!(:name => 'my article', :profile => fast_create(Person))
607 a2 = Article.create!(:name => 'my article 2', :profile => fast_create(Person)) 618 a2 = Article.create!(:name => 'my article 2', :profile => fast_create(Person))
608 a.tag_list = ['one', 'two'] 619 a.tag_list = ['one', 'two']
609 a2.tag_list = ['two', 'three'] 620 a2.tag_list = ['two', 'three']
610 - a.save_tags 621 + a.save_tags
611 a2.save_tags 622 a2.save_tags
612 623
613 - get :tag, :tag => 'two' 624 + get :tag, :tag => 'two'
614 625
615 assert_equivalent [a, a2], assigns(:searches)[:tag][:results] 626 assert_equivalent [a, a2], assigns(:searches)[:tag][:results]
616 627
617 - get :tag, :tag => 'one' 628 + get :tag, :tag => 'one'
618 629
619 assert_equivalent [a], assigns(:searches)[:tag][:results] 630 assert_equivalent [a], assigns(:searches)[:tag][:results]
620 end 631 end
621 632
622 should 'not show assets from other environments' do 633 should 'not show assets from other environments' do
623 other_env = Environment.create!(:name => 'Another environment') 634 other_env = Environment.create!(:name => 'Another environment')
624 - p1 = create(Person, :name => 'Hildebrando', :identifier => 'hild', :user_id => fast_create(User).id, :environment_id => other_env.id)  
625 - p2 = create(Person, :name => 'Adamastor', :identifier => 'adam', :user_id => fast_create(User).id) 635 + p1 = create(Person, :name => 'Hildebrando', :identifier => 'hild', :user_id => fast_create(User).id, :environment_id => other_env.id)
  636 + p2 = create(Person, :name => 'Adamastor', :identifier => 'adam', :user_id => fast_create(User).id)
626 art1 = create(Article, :name => 'my article', :profile_id => p1.id) 637 art1 = create(Article, :name => 'my article', :profile_id => p1.id)
627 art2 = create(Article, :name => 'my article', :profile_id => p2.id) 638 art2 = create(Article, :name => 'my article', :profile_id => p2.id)
628 639
@@ -633,9 +644,9 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -633,9 +644,9 @@ class SearchControllerTest &lt; ActionController::TestCase
633 644
634 should 'order articles by more recent' do 645 should 'order articles by more recent' do
635 Article.destroy_all 646 Article.destroy_all
636 - art1 = create(Article, :name => 'review C', :profile_id => fast_create(Person).id, :created_at => Time.now-1.days)  
637 - art2 = create(Article, :name => 'review A', :profile_id => fast_create(Person).id, :created_at => Time.now)  
638 - art3 = create(Article, :name => 'review B', :profile_id => fast_create(Person).id, :created_at => Time.now-2.days) 647 + art1 = create(Article, :name => 'review C', :profile_id => fast_create(Person).id, :created_at => Time.now-1.days)
  648 + art2 = create(Article, :name => 'review A', :profile_id => fast_create(Person).id, :created_at => Time.now)
  649 + art3 = create(Article, :name => 'review B', :profile_id => fast_create(Person).id, :created_at => Time.now-2.days)
639 650
640 get :articles, :filter => :more_recent 651 get :articles, :filter => :more_recent
641 652
test/functional/users_controller_test.rb
@@ -133,4 +133,20 @@ class UsersControllerTest &lt; ActionController::TestCase @@ -133,4 +133,20 @@ class UsersControllerTest &lt; ActionController::TestCase
133 assert_equal 'name;email', @response.body.split("\n")[0] 133 assert_equal 'name;email', @response.body.split("\n")[0]
134 end 134 end
135 135
  136 + should 'be able to remove a person' do
  137 + person = fast_create(Person, :environment_id => environment.id)
  138 + assert_difference Person, :count, -1 do
  139 + post :destroy_user, :id => person.id
  140 + end
  141 + end
  142 +
  143 + should 'not crash if user does not exist' do
  144 + person = fast_create(Person)
  145 +
  146 + assert_no_difference Person, :count do
  147 + post :destroy_user, :id => 99999
  148 + end
  149 + assert_redirected_to :action => 'index'
  150 + end
  151 +
136 end 152 end
test/integration/routing_test.rb
@@ -268,5 +268,8 @@ class RoutingTest &lt; ActionController::IntegrationTest @@ -268,5 +268,8 @@ class RoutingTest &lt; ActionController::IntegrationTest
268 assert_routing('http://www.example.com/work/free-software/versions', :controller => 'content_viewer', :action => 'article_versions', :page => 'work/free-software') 268 assert_routing('http://www.example.com/work/free-software/versions', :controller => 'content_viewer', :action => 'article_versions', :page => 'work/free-software')
269 end 269 end
270 270
  271 + should 'have route to get HTML code of Blocks to embed' do
  272 + assert_routing('/embed/block/12345', :controller => 'embed', :action => 'block', :id => '12345')
  273 + end
271 274
272 end 275 end
test/test_helper.rb
@@ -184,7 +184,7 @@ class ActiveSupport::TestCase @@ -184,7 +184,7 @@ class ActiveSupport::TestCase
184 if reference.first == value 184 if reference.first == value
185 reference.shift 185 reference.shift
186 else 186 else
187 - assert false, "'#{value}' was found before it should be on: #{original.inspect}" 187 + assert false, "'#{value.inspect}' was found before it should be on: #{original.inspect}"
188 end 188 end
189 end 189 end
190 end 190 end
test/unit/account_helper_test.rb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class AccountHelperTest < ActiveSupport::TestCase
  4 +
  5 + include AccountHelper
  6 + include ActionView::Helpers::TagHelper
  7 +
  8 + should 'not suggest usernames if username is empty' do
  9 + assert_equal '', suggestion_based_on_username
  10 + end
  11 +
  12 + should 'suggest valid usernames' do
  13 + ze = create_user('ze').person
  14 + stubs(:environment).returns(ze.environment)
  15 + suggestions = suggestion_based_on_username('ze')
  16 + suggestions.each do |suggestion|
  17 + assert_equal true, Person.is_available?(suggestion, ze.environment)
  18 + end
  19 + end
  20 +
  21 +end
test/unit/action_tracker_ext_test.rb 0 → 100644
@@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ActionTrackerExtTest < ActiveSupport::TestCase
  4 + should 'increase person activities_count on new activity' do
  5 + person = fast_create(Person)
  6 + assert_difference person, :activities_count, 1 do
  7 + ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  8 + person.reload
  9 + end
  10 + end
  11 +
  12 + should 'decrease person activities_count on activity removal' do
  13 + person = fast_create(Person)
  14 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  15 + person.reload
  16 + assert_difference person, :activities_count, -1 do
  17 + record.destroy
  18 + person.reload
  19 + end
  20 + end
  21 +
  22 + should 'not decrease person activities_count on activity removal after the recent delay' do
  23 + person = fast_create(Person)
  24 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
  25 + record.created_at = record.created_at - ActionTracker::Record::RECENT_DELAY.days - 1.day
  26 + record.save!
  27 + person.reload
  28 + assert_no_difference person, :activities_count do
  29 + record.destroy
  30 + person.reload
  31 + end
  32 + end
  33 +
  34 + should 'increase organization activities_count on new activity' do
  35 + person = fast_create(Person)
  36 + organization = fast_create(Organization)
  37 + assert_difference organization, :activities_count, 1 do
  38 + ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
  39 + organization.reload
  40 + end
  41 + end
  42 +
  43 + should 'decrease organization activities_count on activity removal' do
  44 + person = fast_create(Person)
  45 + organization = fast_create(Organization)
  46 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
  47 + organization.reload
  48 + assert_difference organization, :activities_count, -1 do
  49 + record.destroy
  50 + organization.reload
  51 + end
  52 + end
  53 +
  54 + should 'not decrease organization activities_count on activity removal after the recent delay' do
  55 + person = fast_create(Person)
  56 + organization = fast_create(Organization)
  57 + record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization, :created_at => (ActionTracker::Record::RECENT_DELAY + 1).days.ago
  58 + organization.reload
  59 + assert_no_difference organization, :activities_count do
  60 + record.destroy
  61 + organization.reload
  62 + end
  63 + end
  64 +end
test/unit/activities_counter_cache_job_test.rb 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ActivitiesCounterCacheJobTest < ActiveSupport::TestCase
  4 +
  5 + should 'correctly update the person activities counter cache' do
  6 + person = create_user('person').person
  7 + ActionTracker::Record.create!(:user => person, :verb => 'create_article')
  8 + ActionTracker::Record.create!(:user => person, :verb => 'create_article')
  9 + person.reload
  10 + assert_equal 2, person.activities_count
  11 +
  12 + person.activities_count = 0
  13 + person.save!
  14 + job = ActivitiesCounterCacheJob.new
  15 + job.perform
  16 + person.reload
  17 + assert_equal 2, person.activities_count
  18 + end
  19 +
  20 + should 'correctly update the organization activities counter cache' do
  21 + person = create_user('person').person
  22 + organization = Organization.create!(:name => 'Organization1', :identifier => 'organization1')
  23 + ActionTracker::Record.create!(:user => person, :verb => 'create_article', :target => organization)
  24 + ActionTracker::Record.create!(:user => person, :verb => 'create_article', :target => organization)
  25 + organization.reload
  26 + assert_equal 2, organization.activities_count
  27 +
  28 + organization.activities_count = 0
  29 + organization.save!
  30 + job = ActivitiesCounterCacheJob.new
  31 + job.perform
  32 + organization.reload
  33 + assert_equal 2, organization.activities_count
  34 + end
  35 +
  36 +end
test/unit/acts_as_having_settings_test.rb
@@ -80,4 +80,38 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase @@ -80,4 +80,38 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
80 assert obj.save 80 assert obj.save
81 end 81 end
82 82
  83 + should 'setting_changed be true if a setting passed as parameter was changed' do
  84 + obj = TestClass.new
  85 + obj.flag = true
  86 + assert obj.setting_changed? 'flag'
  87 + end
  88 +
  89 + should 'setting_changed be false if a setting passed as parameter was not changed' do
  90 + obj = TestClass.new
  91 + assert !obj.setting_changed?('flag')
  92 + end
  93 +
  94 + should 'setting_changed be false if a setting passed as parameter was changed with the same value' do
  95 + obj = TestClass.new
  96 + obj.flag = true
  97 + obj.save
  98 + obj.flag = true
  99 + assert !obj.setting_changed?('flag')
  100 + end
  101 +
  102 + should 'setting_changed be false if a setting passed as parameter was not changed but another setting is changed' do
  103 + obj = TestClass.new(:name => 'some name')
  104 + obj.save
  105 + obj.name = 'antoher nme'
  106 + assert !obj.setting_changed?('flag')
  107 + end
  108 +
  109 + should 'setting_changed be true for all changed fields' do
  110 + obj = TestClass.new(:name => 'some name', :flag => false)
  111 + obj.save
  112 + obj.name = 'another nme'
  113 + obj.flag = true
  114 + assert obj.setting_changed?('flag')
  115 + assert obj.setting_changed?('name')
  116 + end
83 end 117 end
test/unit/application_helper_test.rb
@@ -452,6 +452,22 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -452,6 +452,22 @@ class ApplicationHelperTest &lt; ActionView::TestCase
452 assert_match(/Community nick/, page_title) 452 assert_match(/Community nick/, page_title)
453 end 453 end
454 454
  455 + should 'not display environment name if is a profile' do
  456 + stubs(:environment).returns(Environment.default)
  457 + @controller = ApplicationController.new
  458 +
  459 + c = fast_create(Community, :name => 'Community for tests', :nickname => 'Community nick', :identifier => 'test_comm')
  460 + stubs(:profile).returns(c)
  461 + assert_equal c.short_name, page_title
  462 + end
  463 +
  464 + should 'display only environment if no profile and page' do
  465 + stubs(:environment).returns(Environment.default)
  466 + @controller = ApplicationController.new
  467 +
  468 + assert_equal Environment.default.name, page_title
  469 + end
  470 +
455 should 'gravatar default parameter' do 471 should 'gravatar default parameter' do
456 profile = mock 472 profile = mock
457 profile.stubs(:theme).returns('some-theme') 473 profile.stubs(:theme).returns('some-theme')
@@ -646,6 +662,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -646,6 +662,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase
646 should 'parse macros' do 662 should 'parse macros' do
647 class Plugin1 < Noosfero::Plugin 663 class Plugin1 < Noosfero::Plugin
648 end 664 end
  665 + Noosfero::Plugin.stubs(:all).returns(['ApplicationHelperTest::Plugin1'])
649 666
650 class Plugin1::Macro1 < Noosfero::Plugin::Macro 667 class Plugin1::Macro1 < Noosfero::Plugin::Macro
651 def parse(params, inner_html, source) 668 def parse(params, inner_html, source)
test/unit/article_test.rb
@@ -1632,10 +1632,10 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1632,10 +1632,10 @@ class ArticleTest &lt; ActiveSupport::TestCase
1632 1632
1633 should 'not allow all community members to edit by default' do 1633 should 'not allow all community members to edit by default' do
1634 community = fast_create(Community) 1634 community = fast_create(Community)
1635 - admin = create_user('community-admin').person  
1636 - member = create_user.person  
1637 - 1635 + admin = fast_create(Person)
  1636 + member = fast_create(Person)
1638 community.add_admin(admin) 1637 community.add_admin(admin)
  1638 + community.reload
1639 community.add_member(member) 1639 community.add_member(member)
1640 a = build(Article, :profile => community) 1640 a = build(Article, :profile => community)
1641 1641
test/unit/block_test.rb
@@ -222,4 +222,66 @@ class BlockTest &lt; ActiveSupport::TestCase @@ -222,4 +222,66 @@ class BlockTest &lt; ActiveSupport::TestCase
222 assert block.visible?(2) 222 assert block.visible?(2)
223 assert !block.visible?(3) 223 assert !block.visible?(3)
224 end 224 end
  225 +
  226 + should 'not be embedable by default' do
  227 + assert !Block.new.embedable?
  228 + end
  229 +
  230 + should 'generate embed code' do
  231 + b = Block.new
  232 + b.stubs(:url_for).returns('http://myblogtest.com/embed/block/1')
  233 + assert_equal "<iframe class=\"embed block block\" frameborder=\"0\" height=\"768\" src=\"http://myblogtest.com/embed/block/1\" width=\"1024\"></iframe>", b.embed_code.call
  234 + end
  235 +
  236 + should 'default value for display_user is all' do
  237 + block = Block.new
  238 + assert_equal 'all', block.display_user
  239 + end
  240 +
  241 + should 'display block to not logged users for display_user = all' do
  242 + block = Block.new
  243 + assert block.display_to_user?(nil)
  244 + end
  245 +
  246 + should 'display block to logged users for display_user = all' do
  247 + block = Block.new
  248 + assert block.display_to_user?(User.new)
  249 + end
  250 +
  251 + should 'display block to logged users for display_user = logged' do
  252 + block = Block.new
  253 + block.display_user = 'logged'
  254 + assert block.display_to_user?(User.new)
  255 + end
  256 +
  257 + should 'do not display block to logged users for display_user = not_logged' do
  258 + block = Block.new
  259 + block.display_user = 'not_logged'
  260 + assert !block.display_to_user?(User.new)
  261 + end
  262 +
  263 + should 'do not display block to not logged users for display_user = logged' do
  264 + block = Block.new
  265 + block.display_user = 'logged'
  266 + assert !block.display_to_user?(nil)
  267 + end
  268 +
  269 + should 'display block to not logged users for display_user = not_logged' do
  270 + block = Block.new
  271 + block.display_user = 'not_logged'
  272 + assert block.display_to_user?(nil)
  273 + end
  274 +
  275 + should 'not be visible if display_to_user? is false' do
  276 + block = Block.new
  277 + block.expects(:display_to_user?).once.returns(false)
  278 + assert !block.visible?({})
  279 + end
  280 +
  281 + should 'accept user as parameter on cache_key without change its value' do
  282 + person = fast_create(Person)
  283 + block = Block.new
  284 + assert_equal block.cache_key('en'), block.cache_key('en', person)
  285 + end
  286 +
225 end 287 end
test/unit/box_test.rb
@@ -33,6 +33,8 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -33,6 +33,8 @@ class BoxTest &lt; ActiveSupport::TestCase
33 assert blocks.include?('categories-block') 33 assert blocks.include?('categories-block')
34 assert blocks.include?('communities-block') 34 assert blocks.include?('communities-block')
35 assert blocks.include?('enterprises-block') 35 assert blocks.include?('enterprises-block')
  36 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  37 + # the Noosfero core soon, see ActionItem3045
36 assert blocks.include?('environment-statistics-block') 38 assert blocks.include?('environment-statistics-block')
37 assert blocks.include?('fans-block') 39 assert blocks.include?('fans-block')
38 assert blocks.include?('favorite-enterprises-block') 40 assert blocks.include?('favorite-enterprises-block')
@@ -65,6 +67,8 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -65,6 +67,8 @@ class BoxTest &lt; ActiveSupport::TestCase
65 assert blocks.include?('communities-block') 67 assert blocks.include?('communities-block')
66 assert blocks.include?('disabled-enterprise-message-block') 68 assert blocks.include?('disabled-enterprise-message-block')
67 assert blocks.include?('enterprises-block') 69 assert blocks.include?('enterprises-block')
  70 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  71 + # the Noosfero core soon, see ActionItem3045
68 assert blocks.include?('environment-statistics-block') 72 assert blocks.include?('environment-statistics-block')
69 assert blocks.include?('fans-block') 73 assert blocks.include?('fans-block')
70 assert blocks.include?('favorite-enterprises-block') 74 assert blocks.include?('favorite-enterprises-block')
test/unit/boxes_helper_test.rb
@@ -53,6 +53,7 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -53,6 +53,7 @@ class BoxesHelperTest &lt; ActionView::TestCase
53 expects(:display_block).with(b, '') 53 expects(:display_block).with(b, '')
54 stubs(:request).returns(request) 54 stubs(:request).returns(request)
55 stubs(:block_target).returns('') 55 stubs(:block_target).returns('')
  56 + stubs(:user).returns(nil)
56 expects(:locale).returns('en') 57 expects(:locale).returns('en')
57 with_box_decorator self do 58 with_box_decorator self do
58 display_box_content(box, '') 59 display_box_content(box, '')
@@ -72,6 +73,7 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -72,6 +73,7 @@ class BoxesHelperTest &lt; ActionView::TestCase
72 box.save! 73 box.save!
73 expects(:display_block).with(b, '').never 74 expects(:display_block).with(b, '').never
74 stubs(:request).returns(request) 75 stubs(:request).returns(request)
  76 + stubs(:user).returns(nil)
75 stubs(:block_target).returns('') 77 stubs(:block_target).returns('')
76 expects(:locale).returns('en') 78 expects(:locale).returns('en')
77 display_box_content(box, '') 79 display_box_content(box, '')
@@ -110,8 +112,9 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -110,8 +112,9 @@ class BoxesHelperTest &lt; ActionView::TestCase
110 request.expects(:path).returns('/') 112 request.expects(:path).returns('/')
111 request.expects(:params).returns({}) 113 request.expects(:params).returns({})
112 stubs(:request).returns(request) 114 stubs(:request).returns(request)
  115 + stubs(:user).returns(nil)
113 expects(:locale).returns('en') 116 expects(:locale).returns('en')
114 - box_decorator.expects(:select_blocks).with([], {:article => nil, :request_path => '/', :locale => 'en', :params => {}}).returns([]) 117 + box_decorator.expects(:select_blocks).with([], {:article => nil, :request_path => '/', :locale => 'en', :params => {}, :user => nil}).returns([])
115 118
116 display_box_content(box, '') 119 display_box_content(box, '')
117 end 120 end
test/unit/comment_test.rb
@@ -468,8 +468,8 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -468,8 +468,8 @@ class CommentTest &lt; ActiveSupport::TestCase
468 end 468 end
469 end 469 end
470 470
471 -  
472 should 'delegate spam detection to plugins' do 471 should 'delegate spam detection to plugins' do
  472 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::EverythingIsSpam'])
473 Environment.default.enable_plugin(EverythingIsSpam) 473 Environment.default.enable_plugin(EverythingIsSpam)
474 474
475 c1 = create_comment 475 c1 = create_comment
@@ -495,6 +495,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -495,6 +495,7 @@ class CommentTest &lt; ActiveSupport::TestCase
495 end 495 end
496 496
497 should 'notify plugins of comments being marked as spam' do 497 should 'notify plugins of comments being marked as spam' do
  498 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::SpamNotification'])
498 Environment.default.enable_plugin(SpamNotification) 499 Environment.default.enable_plugin(SpamNotification)
499 500
500 c = create_comment 501 c = create_comment
@@ -506,6 +507,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -506,6 +507,7 @@ class CommentTest &lt; ActiveSupport::TestCase
506 end 507 end
507 508
508 should 'notify plugins of comments being marked as ham' do 509 should 'notify plugins of comments being marked as ham' do
  510 + Noosfero::Plugin.stubs(:all).returns(['CommentTest::SpamNotification'])
509 Environment.default.enable_plugin(SpamNotification) 511 Environment.default.enable_plugin(SpamNotification)
510 512
511 c = create_comment 513 c = create_comment
test/unit/community_test.rb
@@ -216,8 +216,8 @@ class CommunityTest &lt; ActiveSupport::TestCase @@ -216,8 +216,8 @@ class CommunityTest &lt; ActiveSupport::TestCase
216 community = fast_create(Community) 216 community = fast_create(Community)
217 community.closed = true 217 community.closed = true
218 community.save 218 community.save
219 -  
220 community.add_member(fast_create(Person)) 219 community.add_member(fast_create(Person))
  220 + community.reload
221 221
222 community.stubs(:notification_emails).returns(['sample@example.org']) 222 community.stubs(:notification_emails).returns(['sample@example.org'])
223 223
test/unit/contact_sender_test.rb
@@ -16,7 +16,7 @@ class ContactSenderTest &lt; ActiveSupport::TestCase @@ -16,7 +16,7 @@ class ContactSenderTest &lt; ActiveSupport::TestCase
16 ent.contact_email = 'contact@invalid.com' 16 ent.contact_email = 'contact@invalid.com'
17 c = build(Contact, :dest => ent) 17 c = build(Contact, :dest => ent)
18 response = Contact::Sender.notification(c).deliver 18 response = Contact::Sender.notification(c).deliver
19 - assert_equal Environment.default.contact_email, response.from.first.to_s 19 + assert_equal Environment.default.noreply_email, response.from.first.to_s
20 assert_equal "[#{ent.name}] #{c.subject}", response.subject 20 assert_equal "[#{ent.name}] #{c.subject}", response.subject
21 end 21 end
22 22
@@ -27,7 +27,7 @@ class ContactSenderTest &lt; ActiveSupport::TestCase @@ -27,7 +27,7 @@ class ContactSenderTest &lt; ActiveSupport::TestCase
27 response = Contact::Sender.notification(c).deliver 27 response = Contact::Sender.notification(c).deliver
28 assert_includes response.to, c.dest.contact_email 28 assert_includes response.to, c.dest.contact_email
29 end 29 end
30 - 30 +
31 should 'deliver mail to admins of enterprise' do 31 should 'deliver mail to admins of enterprise' do
32 admin = create_user('admin_test').person 32 admin = create_user('admin_test').person
33 ent = Environment.default.enterprises.create!(:name => 'my enterprise', :identifier => 'myent') 33 ent = Environment.default.enterprises.create!(:name => 'my enterprise', :identifier => 'myent')
test/unit/contact_test.rb
@@ -44,11 +44,14 @@ class ContactTest &lt; ActiveSupport::TestCase @@ -44,11 +44,14 @@ class ContactTest &lt; ActiveSupport::TestCase
44 assert !c.deliver 44 assert !c.deliver
45 end 45 end
46 46
47 - should 'use sender name and environment contact_email on from' do 47 + should 'use sender name and environment noreply_email on from' do
48 ent = fast_create(Enterprise, :name => 'my enterprise', :identifier => 'myent') 48 ent = fast_create(Enterprise, :name => 'my enterprise', :identifier => 'myent')
  49 + env = ent.environment
  50 + env.noreply_email = 'noreply@sample.org'
  51 + env.save!
49 c = Contact.new(:name => 'john', :email => 'john@invalid.com', :subject => 'hi', :message => 'hi, all', :dest => ent) 52 c = Contact.new(:name => 'john', :email => 'john@invalid.com', :subject => 'hi', :message => 'hi, all', :dest => ent)
50 email = c.deliver 53 email = c.deliver
51 - assert_equal "#{c.name} <#{ent.environment.contact_email}>", email['from'].to_s 54 + assert_equal "#{c.name} <#{ent.environment.noreply_email}>", email['from'].to_s
52 end 55 end
53 56
54 should 'add dest name on subject' do 57 should 'add dest name on subject' do
test/unit/content_viewer_helper_test.rb
@@ -89,38 +89,6 @@ class ContentViewerHelperTest &lt; ActionView::TestCase @@ -89,38 +89,6 @@ class ContentViewerHelperTest &lt; ActionView::TestCase
89 assert_no_match /feed/, result 89 assert_no_match /feed/, result
90 end 90 end
91 91
92 - should 'generate facebook addthis url for article' do  
93 - Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')  
94 - [TextileArticle, Blog, Folder, Gallery, UploadedFile, Forum, Event, TextArticle, TinyMceArticle].each do |model|  
95 - a = build(model, :body => 'Some text here.', :profile => profile)  
96 - assert_equal "http://www.facebook.com/sharer.php?s=100&p[title]=#{a.name.gsub(' ','+')}&p[summary]=Some+text+here.&p[url]=http%3A%2F%2Fnoosfero.org%2Fblog_helper_test%2F#{a.slug}&p[images][0]=", addthis_facebook_url(a)  
97 - end  
98 - end  
99 -  
100 - should 'generate facebook addthis url without body' do  
101 - Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')  
102 - a = build(TinyMceArticle, :body => nil, :profile => profile)  
103 - assert_equal "http://www.facebook.com/sharer.php?s=100&p[title]=#{a.name.gsub(' ','+')}&p[summary]=&p[url]=http%3A%2F%2Fnoosfero.org%2Fblog_helper_test%2F#{a.slug}&p[images][0]=", addthis_facebook_url(a)  
104 - end  
105 -  
106 - should 'generate facebook addthis url without tags in body' do  
107 - Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')  
108 - a = build(TinyMceArticle, :body => '<p>This <b class="bold">is</b> a test</p>', :profile => profile)  
109 - assert_equal "http://www.facebook.com/sharer.php?s=100&p[title]=#{a.name.gsub(' ','+')}&p[summary]=This+is+a+test&p[url]=http%3A%2F%2Fnoosfero.org%2Fblog_helper_test%2F#{a.slug}&p[images][0]=", addthis_facebook_url(a)  
110 - end  
111 -  
112 - should 'generate facebook addthis url with truncated body' do  
113 - Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')  
114 - a = build(TinyMceArticle, :body => 'test' * 76, :profile => profile)  
115 - assert_equal "http://www.facebook.com/sharer.php?s=100&p[title]=#{a.name.gsub(' ','+')}&p[summary]=#{'test' * 74}t...&p[url]=http%3A%2F%2Fnoosfero.org%2Fblog_helper_test%2F#{a.slug}&p[images][0]=", addthis_facebook_url(a)  
116 - end  
117 -  
118 - should 'generate facebook addthis url for tinymce article with images' do  
119 - Environment.any_instance.stubs(:default_hostname).returns('noosfero.org')  
120 - a = build(TinyMceArticle, :body => '<p>This <b class="bold">is</b> a <img src="/images/x.png" />test</p>', :profile => profile)  
121 - assert_equal "http://www.facebook.com/sharer.php?s=100&p[title]=#{a.name.gsub(' ','+')}&p[summary]=This+is+a+test&p[url]=http%3A%2F%2Fnoosfero.org%2Fblog_helper_test%2F#{a.slug}&p[images][0]=http%3A%2F%2Fnoosfero.org%2Fimages%2Fx.png", addthis_facebook_url(a)  
122 - end  
123 -  
124 should 'theme provides addthis custom icon' do 92 should 'theme provides addthis custom icon' do
125 stubs(:session).returns({:theme => 'base'}) 93 stubs(:session).returns({:theme => 'base'})
126 File.expects(:exists?).with(anything).returns(true) 94 File.expects(:exists?).with(anything).returns(true)
test/unit/enterprise_test.rb
@@ -101,6 +101,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase @@ -101,6 +101,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
101 enterprise = fast_create(Enterprise) 101 enterprise = fast_create(Enterprise)
102 member = fast_create(Person) 102 member = fast_create(Person)
103 enterprise.add_member(member) 103 enterprise.add_member(member)
  104 + enterprise.reload
104 105
105 person = fast_create(Person) 106 person = fast_create(Person)
106 enterprise.stubs(:notification_emails).returns(['sample@example.org']) 107 enterprise.stubs(:notification_emails).returns(['sample@example.org'])
test/unit/environment_mailing_test.rb
@@ -50,7 +50,7 @@ class EnvironmentMailingTest &lt; ActiveSupport::TestCase @@ -50,7 +50,7 @@ class EnvironmentMailingTest &lt; ActiveSupport::TestCase
50 mailing = new_mailing(environment).tap do |m| 50 mailing = new_mailing(environment).tap do |m|
51 m.person = person_1 51 m.person = person_1
52 end 52 end
53 - assert_equal "#{environment.name} <#{environment.contact_email}>", mailing.generate_from 53 + assert_equal "#{environment.name} <#{environment.noreply_email}>", mailing.generate_from
54 end 54 end
55 55
56 should 'deliver mailing to each recipient after create' do 56 should 'deliver mailing to each recipient after create' do
test/unit/environment_statistics_block_test.rb
  1 +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  2 +# the Noosfero core soon, see ActionItem3045
  3 +
1 require File.dirname(__FILE__) + '/../test_helper' 4 require File.dirname(__FILE__) + '/../test_helper'
2 5
3 class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase 6 class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase
@@ -36,7 +39,7 @@ class EnvironmentStatisticsBlockTest &lt; ActiveSupport::TestCase @@ -36,7 +39,7 @@ class EnvironmentStatisticsBlockTest &lt; ActiveSupport::TestCase
36 assert_match(/2 users/, content) 39 assert_match(/2 users/, content)
37 assert_match(/One community/, content) 40 assert_match(/One community/, content)
38 end 41 end
39 - 42 +
40 should 'generate statistics including private profiles' do 43 should 'generate statistics including private profiles' do
41 env = create(Environment) 44 env = create(Environment)
42 user1 = create_user('testuser1', :environment_id => env.id) 45 user1 = create_user('testuser1', :environment_id => env.id)
test/unit/environment_test.rb
@@ -1219,6 +1219,27 @@ class EnvironmentTest &lt; ActiveSupport::TestCase @@ -1219,6 +1219,27 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
1219 end 1219 end
1220 end 1220 end
1221 1221
  1222 + should 'return a Hash on signup redirection options' do
  1223 + assert_kind_of Hash, Environment.signup_redirection_options
  1224 + end
  1225 +
  1226 + should 'respond to redirection after signup' do
  1227 + assert_respond_to Environment.new, :redirection_after_signup
  1228 + end
  1229 +
  1230 + should 'allow only environment signup redirection options' do
  1231 + environment = fast_create(Environment)
  1232 + environment.redirection_after_signup = 'invalid_option'
  1233 + environment.save
  1234 + assert environment.errors.invalid?(:redirection_after_signup)
  1235 +
  1236 + Environment.signup_redirection_options.keys.each do |redirection|
  1237 + environment.redirection_after_signup = redirection
  1238 + environment.save
  1239 + assert !environment.errors.invalid?(:redirection_after_signup)
  1240 + end
  1241 + end
  1242 +
1222 should 'respond to signup_welcome_text' do 1243 should 'respond to signup_welcome_text' do
1223 assert_respond_to Environment.new, :signup_welcome_text 1244 assert_respond_to Environment.new, :signup_welcome_text
1224 end 1245 end
test/unit/file_presenter_test.rb
@@ -58,4 +58,20 @@ class FilePresenterTest &lt; ActiveSupport::TestCase @@ -58,4 +58,20 @@ class FilePresenterTest &lt; ActiveSupport::TestCase
58 end 58 end
59 end 59 end
60 60
  61 + should 'pass kind_of? to the encapsulated file' do
  62 + f = FilePresenter.for(UploadedFile.new)
  63 + assert f.kind_of?(UploadedFile)
  64 + end
  65 +
  66 + should 'not crash with uploaded_file short description without content_type' do
  67 + f = FilePresenter.for(UploadedFile.new)
  68 + assert_nothing_raised do
  69 + f.short_description
  70 + end
  71 + end
  72 +
  73 + should 'show unknown type when file doesn\'t have a content_type' do
  74 + f = FilePresenter.for(UploadedFile.new)
  75 + assert_match /Unknown/, f.short_description
  76 + end
61 end 77 end
test/unit/forgot_password_helper_test.rb
@@ -22,6 +22,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase @@ -22,6 +22,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
22 {:field => 'f3', :name => 'F3', :model => 'person'}] 22 {:field => 'f3', :name => 'F3', :model => 'person'}]
23 end 23 end
24 end 24 end
  25 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
25 26
26 environment.enable_plugin(Plugin1) 27 environment.enable_plugin(Plugin1)
27 environment.enable_plugin(Plugin2) 28 environment.enable_plugin(Plugin2)
@@ -43,6 +44,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase @@ -43,6 +44,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
43 {:field => 'f3', :name => 'F3', :model => 'person'}] 44 {:field => 'f3', :name => 'F3', :model => 'person'}]
44 end 45 end
45 end 46 end
  47 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
46 48
47 environment.enable_plugin(Plugin1) 49 environment.enable_plugin(Plugin1)
48 environment.enable_plugin(Plugin2) 50 environment.enable_plugin(Plugin2)
@@ -64,6 +66,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase @@ -64,6 +66,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
64 {:field => 'f3', :name => 'F3', :model => 'user'}] 66 {:field => 'f3', :name => 'F3', :model => 'user'}]
65 end 67 end
66 end 68 end
  69 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
67 70
68 environment.enable_plugin(Plugin1) 71 environment.enable_plugin(Plugin1)
69 environment.enable_plugin(Plugin2) 72 environment.enable_plugin(Plugin2)
@@ -85,6 +88,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase @@ -85,6 +88,7 @@ class ForgotPasswordHelperTest &lt; ActionView::TestCase
85 {:field => 'f3', :name => 'F3', :model => 'user'}] 88 {:field => 'f3', :name => 'F3', :model => 'user'}]
86 end 89 end
87 end 90 end
  91 + Noosfero::Plugin.stubs(:all).returns(['ForgotPasswordHelperTest::Plugin1', 'ForgotPasswordHelperTest::Plugin2'])
88 92
89 environment.enable_plugin(Plugin1) 93 environment.enable_plugin(Plugin1)
90 environment.enable_plugin(Plugin2) 94 environment.enable_plugin(Plugin2)
test/unit/link_list_block_test.rb
@@ -39,6 +39,32 @@ class LinkListBlockTest &lt; ActiveSupport::TestCase @@ -39,6 +39,32 @@ class LinkListBlockTest &lt; ActiveSupport::TestCase
39 assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/test_profile/address'} 39 assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/test_profile/address'}
40 end 40 end
41 41
  42 + should 'replace {portal} with environment portal identifier' do
  43 + env = Environment.default
  44 + env.enable('use_portal_community')
  45 + portal = fast_create(Community, :identifier => 'portal-community', :environment_id => env.id)
  46 + env.portal_community = portal
  47 + env.save
  48 +
  49 + stubs(:environment).returns(env)
  50 + l = LinkListBlock.new(:links => [{:name => 'categ', :address => '/{portal}/address'}])
  51 + l.stubs(:owner).returns(env)
  52 + assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/portal-community/address'}
  53 + end
  54 +
  55 + should 'not change address if no {portal} there' do
  56 + env = Environment.default
  57 + env.enable('use_portal_community')
  58 + portal = fast_create(Community, :identifier => 'portal-community', :environment_id => env.id)
  59 + env.portal_community = portal
  60 + env.save
  61 +
  62 + stubs(:environment).returns(env)
  63 + l = LinkListBlock.new(:links => [{:name => 'categ', :address => '/address'}])
  64 + l.stubs(:owner).returns(env)
  65 + assert_tag_in_string l.content, :tag => 'a', :attributes => {:href => '/address'}
  66 + end
  67 +
42 should 'display options for icons' do 68 should 'display options for icons' do
43 l = LinkListBlock.new 69 l = LinkListBlock.new
44 l.icons_options.each do |option| 70 l.icons_options.each do |option|
test/unit/macros_helper_test.rb
@@ -28,6 +28,7 @@ class MacrosHelperTest &lt; ActionView::TestCase @@ -28,6 +28,7 @@ class MacrosHelperTest &lt; ActionView::TestCase
28 end 28 end
29 29
30 def setup 30 def setup
  31 + Noosfero::Plugin.stubs(:all).returns(['MacrosHelperTest::Plugin1'])
31 @environment = Environment.default 32 @environment = Environment.default
32 @environment.enable_plugin(Plugin1) 33 @environment.enable_plugin(Plugin1)
33 @plugins = Noosfero::Plugin::Manager.new(@environment, self) 34 @plugins = Noosfero::Plugin::Manager.new(@environment, self)
@@ -129,4 +130,27 @@ class MacrosHelperTest &lt; ActionView::TestCase @@ -129,4 +130,27 @@ class MacrosHelperTest &lt; ActionView::TestCase
129 assert_equal 'macro_generator', macro_generator(Plugin1::Macro) 130 assert_equal 'macro_generator', macro_generator(Plugin1::Macro)
130 end 131 end
131 132
  133 + should 'get macro default generator' do
  134 + class Plugin1::Macro < Noosfero::Plugin::Macro
  135 + def self.configuration
  136 + { :params => [] }
  137 + end
  138 + end
  139 + assert_nothing_raised NoMethodError do
  140 + assert macro_generator(Plugin1::Macro)
  141 + end
  142 + end
  143 +
  144 + should 'can use a code reference as macro generator' do
  145 + class Plugin1::Macro < Noosfero::Plugin::Macro
  146 + def self.configuration
  147 + { :params => [], :generator => method(:macro_generator_method) }
  148 + end
  149 + def self.macro_generator_method(macro)
  150 + "macro generator method return"
  151 + end
  152 + end
  153 + assert_equal "macro generator method return", macro_generator(Plugin1::Macro)
  154 + end
  155 +
132 end 156 end
test/unit/mailing_test.rb
@@ -74,7 +74,7 @@ class MailingTest &lt; ActiveSupport::TestCase @@ -74,7 +74,7 @@ class MailingTest &lt; ActiveSupport::TestCase
74 should 'display name and email on generate_from' do 74 should 'display name and email on generate_from' do
75 person = Person['user_one'] 75 person = Person['user_one']
76 mailing = build(Mailing, :source => environment, :person => person) 76 mailing = build(Mailing, :source => environment, :person => person)
77 - assert_equal "#{environment.name} <#{environment.contact_email}>", mailing.generate_from 77 + assert_equal "#{environment.name} <#{environment.noreply_email}>", mailing.generate_from
78 end 78 end
79 79
80 should 'generate subject' do 80 should 'generate subject' do
test/unit/members_block_test.rb
@@ -35,4 +35,28 @@ class MembersBlockTest &lt; ActiveSupport::TestCase @@ -35,4 +35,28 @@ class MembersBlockTest &lt; ActiveSupport::TestCase
35 assert_same list, block.profiles 35 assert_same list, block.profiles
36 end 36 end
37 37
  38 + should 'use logged-in to compose cache key' do
  39 + person = fast_create(Person)
  40 + community = fast_create(Community)
  41 + block = MembersBlock.create
  42 + block.expects(:owner).returns(community)
  43 +
  44 + assert_match(/-logged-in/,block.cache_key('en', person))
  45 + end
  46 +
  47 + should 'use logged-in and member to compose cache key for members' do
  48 + person = fast_create(Person)
  49 + community = fast_create(Community)
  50 + community.add_member person
  51 + block = MembersBlock.create
  52 + block.expects(:owner).returns(community)
  53 +
  54 + assert_match(/-logged-in-member/,block.cache_key('en', person))
  55 + end
  56 +
  57 + should 'not change block cache key if user is nil' do
  58 + block = MembersBlock.new
  59 + assert_equal block.cache_key('en'), block.cache_key('en', nil)
  60 + end
  61 +
38 end 62 end
test/unit/organization_mailing_test.rb
@@ -42,7 +42,7 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase @@ -42,7 +42,7 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase
42 42
43 should 'display name and email on generate_from' do 43 should 'display name and email on generate_from' do
44 mailing = build(OrganizationMailing, :source => community, :person => person) 44 mailing = build(OrganizationMailing, :source => community, :person => person)
45 - assert_equal "#{person.name} <#{community.environment.contact_email}>", mailing.generate_from 45 + assert_equal "#{person.name} <#{community.environment.noreply_email}>", mailing.generate_from
46 end 46 end
47 47
48 should 'generate subject' do 48 should 'generate subject' do
@@ -61,19 +61,22 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase @@ -61,19 +61,22 @@ class OrganizationMailingTest &lt; ActiveSupport::TestCase
61 end 61 end
62 62
63 should 'deliver mailing to each member after create' do 63 should 'deliver mailing to each member after create' do
64 - create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person) 64 + mailing = create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person)
  65 + community.reload
65 process_delayed_job_queue 66 process_delayed_job_queue
66 - assert_equal community.members.compact.count, ActionMailer::Base.deliveries.count 67 + assert_equal 2, ActionMailer::Base.deliveries.count
67 end 68 end
68 69
69 should 'deliver mailing when there are many mailings created' do 70 should 'deliver mailing when there are many mailings created' do
70 50.times { create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person) } 71 50.times { create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person) }
  72 + community.reload
71 process_delayed_job_queue 73 process_delayed_job_queue
72 - assert_equal 50*community.members.compact.count, ActionMailer::Base.deliveries.count 74 + assert_equal 50*community.members_count, ActionMailer::Base.deliveries.count
73 end 75 end
74 76
75 should 'create mailing sent to each recipient after delivering mailing' do 77 should 'create mailing sent to each recipient after delivering mailing' do
76 mailing = create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person) 78 mailing = create(OrganizationMailing, :source => community, :subject => 'Hello', :body => 'We have some news', :person => person)
  79 + community.reload
77 assert_difference 'MailingSent.count', 2 do 80 assert_difference 'MailingSent.count', 2 do
78 process_delayed_job_queue 81 process_delayed_job_queue
79 end 82 end
test/unit/organization_test.rb
@@ -302,18 +302,17 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -302,18 +302,17 @@ class OrganizationTest &lt; ActiveSupport::TestCase
302 end 302 end
303 303
304 should 'find more popular organizations' do 304 should 'find more popular organizations' do
305 - Organization.delete_all  
306 o1 = fast_create(Organization) 305 o1 = fast_create(Organization)
307 o2 = fast_create(Organization) 306 o2 = fast_create(Organization)
308 307
309 p1 = fast_create(Person) 308 p1 = fast_create(Person)
310 p2 = fast_create(Person) 309 p2 = fast_create(Person)
311 o1.add_member(p1) 310 o1.add_member(p1)
312 - assert_equal [o1,o2] , Organization.more_popular 311 + assert_order [o1,o2] , Organization.more_popular
313 312
314 o2.add_member(p1) 313 o2.add_member(p1)
315 o2.add_member(p2) 314 o2.add_member(p2)
316 - assert_equal [o2,o1] , Organization.more_popular 315 + assert_order [o2,o1] , Organization.more_popular
317 end 316 end
318 317
319 should 'list organizations that have no members in more popular list' do 318 should 'list organizations that have no members in more popular list' do
@@ -331,6 +330,7 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -331,6 +330,7 @@ class OrganizationTest &lt; ActiveSupport::TestCase
331 person = fast_create(Person) 330 person = fast_create(Person)
332 organization = fast_create(Organization) 331 organization = fast_create(Organization)
333 organization.add_member(person) 332 organization.add_member(person)
  333 + organization.reload
334 334
335 assert_equal "one member", organization.more_popular_label 335 assert_equal "one member", organization.more_popular_label
336 end 336 end
@@ -342,47 +342,30 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -342,47 +342,30 @@ class OrganizationTest &lt; ActiveSupport::TestCase
342 342
343 organization.add_member(person1) 343 organization.add_member(person1)
344 organization.add_member(person2) 344 organization.add_member(person2)
  345 + organization.reload
345 assert_equal "2 members", organization.more_popular_label 346 assert_equal "2 members", organization.more_popular_label
346 347
347 person3 = fast_create(Person) 348 person3 = fast_create(Person)
348 organization.add_member(person3) 349 organization.add_member(person3)
  350 + organization.reload
349 assert_equal "3 members", organization.more_popular_label 351 assert_equal "3 members", organization.more_popular_label
350 end 352 end
351 353
352 should 'find more active organizations' do 354 should 'find more active organizations' do
353 person = fast_create(Person) 355 person = fast_create(Person)
354 - Organization.destroy_all  
355 p1 = fast_create(Organization) 356 p1 = fast_create(Organization)
356 p2 = fast_create(Organization) 357 p2 = fast_create(Organization)
357 p3 = fast_create(Organization) 358 p3 = fast_create(Organization)
358 359
359 ActionTracker::Record.destroy_all 360 ActionTracker::Record.destroy_all
360 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p1.id)  
361 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p2.id)  
362 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p2.id)  
363 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id)  
364 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id)  
365 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => Time.now, :target_id => p3.id) 361 + ActionTracker::Record.create!(:user => person, :target => p1, :verb => 'leave_scrap')
  362 + ActionTracker::Record.create!(:user => person, :target => p2, :verb => 'leave_scrap')
  363 + ActionTracker::Record.create!(:user => person, :target => p2, :verb => 'leave_scrap')
  364 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
  365 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
  366 + ActionTracker::Record.create!(:user => person, :target => p3, :verb => 'leave_scrap')
366 367
367 - assert_equal [p3,p2,p1] , Organization.more_active  
368 - end  
369 -  
370 - should 'more active profile take in consideration only actions created only in the recent delay interval' do  
371 - ActionTracker::Record.destroy_all  
372 - recent_delay = ActionTracker::Record::RECENT_DELAY.days.ago  
373 -  
374 - person = fast_create(Person)  
375 - Organization.destroy_all  
376 - p1 = fast_create(Organization)  
377 - p2 = fast_create(Organization)  
378 -  
379 - ActionTracker::Record.destroy_all  
380 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p1.id)  
381 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p1.id)  
382 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay, :target_id => p2.id)  
383 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => person, :created_at => recent_delay - 1.day, :target_id => p2.id)  
384 -  
385 - assert_equal [p1,p2] , Organization.more_active 368 + assert_order [p3,p2,p1] , Organization.more_active
386 end 369 end
387 370
388 should 'list profiles that have no actions in more active list' do 371 should 'list profiles that have no actions in more active list' do
@@ -422,4 +405,24 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -422,4 +405,24 @@ class OrganizationTest &lt; ActiveSupport::TestCase
422 assert !organization.visible 405 assert !organization.visible
423 end 406 end
424 407
  408 + should 'increase members_count on new membership' do
  409 + member = fast_create(Person)
  410 + organization = fast_create(Organization)
  411 + assert_difference organization, :members_count, 1 do
  412 + organization.add_member(member)
  413 + organization.reload
  414 + end
  415 + end
  416 +
  417 + should 'decrease members_count on membership removal' do
  418 + member = fast_create(Person)
  419 + organization = fast_create(Organization)
  420 + organization.add_member(member)
  421 + organization.reload
  422 + assert_difference organization, :members_count, -1 do
  423 + organization.remove_member(member)
  424 + organization.reload
  425 + end
  426 + end
  427 +
425 end 428 end
test/unit/person_notifier_helper_test.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class PersonNotifierHelperTest < ActiveSupport::TestCase
  4 +
  5 + include PersonNotifierHelper
  6 + include ActionView::Helpers::TagHelper
  7 +
  8 + def setup
  9 + @profile = mock
  10 + @env = Environment.new
  11 + end
  12 + attr_reader :profile, :env
  13 +
  14 + should 'append top url of environment at image path' do
  15 + profile.expects(:environment).returns(env).at_least_once
  16 + assert_match /src="http:\/\/localhost\/image.png"/, image_tag("/image.png")
  17 + end
  18 +
  19 + should 'return original path if do not have an environment' do
  20 + profile.expects(:environment).returns(nil).at_least_once
  21 + assert_match /src="\/image.png"/, image_tag("/image.png")
  22 + end
  23 +
  24 +end
test/unit/person_notifier_test.rb 0 → 100644
@@ -0,0 +1,213 @@ @@ -0,0 +1,213 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class PersonNotifierTest < ActiveSupport::TestCase
  4 + FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
  5 + CHARSET = "utf-8"
  6 +
  7 + def setup
  8 + ActionMailer::Base.delivery_method = :test
  9 + ActionMailer::Base.perform_deliveries = true
  10 + ActionMailer::Base.deliveries = []
  11 + Person.destroy_all
  12 + @admin = create_user('adminuser').person
  13 + @member = create_user('member').person
  14 + @admin.notification_time = 24
  15 + @member.notification_time = 24
  16 + @admin.save!
  17 + @member.save!
  18 + @community = fast_create(Community)
  19 + @community.add_member(@admin)
  20 + @article = fast_create(TextileArticle, :name => 'Article test', :profile_id => @community.id, :notify_comments => false)
  21 + Delayed::Job.delete_all
  22 + notify
  23 + ActionMailer::Base.deliveries = []
  24 + end
  25 +
  26 + should 'deliver mail to community members' do
  27 + @community.add_member(@member)
  28 + notify
  29 + sent = ActionMailer::Base.deliveries.first
  30 + assert_equal [@member.email], sent.to
  31 + end
  32 +
  33 + should 'do not send mail if do not have notifications' do
  34 + @community.add_member(@member)
  35 + ActionTracker::Record.delete_all
  36 + notify
  37 + assert ActionMailer::Base.deliveries.empty?
  38 + end
  39 +
  40 + should 'do not send mail to people not joined to community' do
  41 + Comment.create!(:author => @admin, :title => 'test comment 2', :body => 'body 2!', :source => @article)
  42 + notify
  43 + assert ActionMailer::Base.deliveries.blank?
  44 + end
  45 +
  46 + should 'display author name in delivered mail' do
  47 + @community.add_member(@member)
  48 + Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article)
  49 + notify
  50 + sent = ActionMailer::Base.deliveries.first
  51 + assert_match /#{@admin.name}/, sent.body
  52 + end
  53 +
  54 + should 'do not include comment created before last notification' do
  55 + @community.add_member(@member)
  56 + ActionTracker::Record.delete_all
  57 + comment = Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article )
  58 + @member.last_notification = DateTime.now + 1.day
  59 + notify
  60 + assert ActionMailer::Base.deliveries.empty?
  61 + end
  62 +
  63 + should 'update last notification date' do
  64 + Comment.create!(:author => @admin, :title => 'test comment 2', :body => 'body 2!', :source => @article)
  65 + @community.add_member(@member)
  66 + initial_notification = @member.last_notification
  67 + notify
  68 + assert @member.last_notification > initial_notification
  69 + end
  70 +
  71 + should 'reschedule after notification' do
  72 + Comment.create!(:author => @admin, :title => 'test comment 2', :body => 'body 2!', :source => @article)
  73 + @community.add_member(@member)
  74 + assert PersonNotifier::NotifyJob.find(@member.id).blank?
  75 + notify
  76 + assert PersonNotifier::NotifyJob.find(@member.id)
  77 + end
  78 +
  79 + should 'schedule next mail at notification time' do
  80 + @member.notification_time = 12
  81 + @member.notifier.schedule_next_notification_mail
  82 + assert_equal @member.notification_time, DateTime.now.hour - Delayed::Job.first.run_at.hour
  83 + end
  84 +
  85 + should 'do not schedule duplicated notification mail' do
  86 + @member.notification_time = 12
  87 + @member.notifier.schedule_next_notification_mail
  88 + @member.notifier.schedule_next_notification_mail
  89 + assert_equal 1, Delayed::Job.count
  90 + end
  91 +
  92 + should 'do not schedule next mail if notification time is zero' do
  93 + @member.notification_time = 0
  94 + @member.notifier.schedule_next_notification_mail
  95 + assert_equal 0, Delayed::Job.count
  96 + end
  97 +
  98 + should 'schedule next notifications for all person with notification time greater than zero' do
  99 + @member.notification_time = 1
  100 + @admin.notification_time = 0
  101 + @admin.save!
  102 + @member.save!
  103 + Delayed::Job.delete_all
  104 + PersonNotifier.schedule_all_next_notification_mail
  105 + process_delayed_job_queue
  106 + assert_equal 1, Delayed::Job.count
  107 + end
  108 +
  109 + should 'do not create duplicated job' do
  110 + PersonNotifier.schedule_all_next_notification_mail
  111 + PersonNotifier.schedule_all_next_notification_mail
  112 + assert_equal 1, Delayed::Job.count
  113 + end
  114 +
  115 + should 'schedule after update and set a valid notification time' do
  116 + @member.notification_time = 0
  117 + @member.save!
  118 + assert_equal 0, Delayed::Job.count
  119 + @member.notification_time = 12
  120 + @member.save!
  121 + assert_equal 1, Delayed::Job.count
  122 + end
  123 +
  124 + should 'reschedule with changed notification time' do
  125 + @member.notification_time = 2
  126 + @member.save!
  127 + assert_equal 1, Delayed::Job.count
  128 + @member.notification_time = 12
  129 + @member.save!
  130 + assert_equal 1, Delayed::Job.count
  131 + assert_equal @member.notification_time, DateTime.now.hour - Delayed::Job.first.run_at.hour
  132 + end
  133 +
  134 + should 'display error message if fail to render a notificiation' do
  135 + @community.add_member(@member)
  136 + Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article)
  137 + ActionTracker::Record.any_instance.stubs(:verb).returns("some_invalid_verb")
  138 + notify
  139 + sent = ActionMailer::Base.deliveries.first
  140 + assert_match /cannot render notification for some_invalid_verb/, sent.body
  141 + end
  142 +
  143 + ActionTrackerConfig.verb_names.each do |verb|
  144 + should "render notification for verb #{verb}" do
  145 + action = mock()
  146 + action.stubs(:verb).returns(verb)
  147 + action.stubs(:user).returns(@member)
  148 + action.stubs(:created_at).returns(DateTime.now)
  149 + action.stubs(:target).returns(fast_create(Forum))
  150 + action.stubs(:comments_count).returns(0)
  151 + action.stubs(:comments).returns([])
  152 + action.stubs(:params).returns({'name' => 'home', 'url' => '/', 'lead' => ''})
  153 + action.stubs(:get_url).returns('')
  154 +
  155 + notifications = []
  156 + notifications.stubs(:find).returns([action])
  157 + Person.any_instance.stubs(:tracked_notifications).returns(notifications)
  158 +
  159 + notify
  160 + sent = ActionMailer::Base.deliveries.first
  161 + assert_no_match /cannot render notification for #{verb}/, sent.body
  162 + end
  163 + end
  164 +
  165 + should 'exists? method in NotifyAllJob return false if there is no instance of this class created' do
  166 + Delayed::Job.enqueue(PersonNotifier::NotifyJob.new)
  167 + assert !PersonNotifier::NotifyAllJob.exists?
  168 + end
  169 +
  170 + should 'exists? method in NotifyAllJob return false if there is no jobs created' do
  171 + assert !PersonNotifier::NotifyAllJob.exists?
  172 + end
  173 +
  174 + should 'exists? method in NotifyAllJob return true if there is at least one instance of this class' do
  175 + Delayed::Job.enqueue(PersonNotifier::NotifyAllJob.new)
  176 + assert PersonNotifier::NotifyAllJob.exists?
  177 + end
  178 +
  179 + should 'perform create NotifyJob for all users with notification_time' do
  180 + Delayed::Job.enqueue(PersonNotifier::NotifyAllJob.new)
  181 + process_delayed_job_queue
  182 + assert_equal 2, Delayed::Job.count
  183 + end
  184 +
  185 + should 'perform create NotifyJob for all users with notification_time defined greater than zero' do
  186 + @member.notification_time = 1
  187 + @admin.notification_time = 0
  188 + @admin.save!
  189 + @member.save!
  190 + Delayed::Job.delete_all
  191 + Delayed::Job.enqueue(PersonNotifier::NotifyAllJob.new)
  192 + process_delayed_job_queue
  193 + assert_equal 1, Delayed::Job.count
  194 + end
  195 +
  196 + should 'NotifyJob failed jobs create a new NotifyJob on permanent failure' do
  197 + Delayed::Job.enqueue(PersonNotifier::NotifyJob.new(@member.id))
  198 +
  199 + PersonNotifier.any_instance.stubs(:notify).raises('error')
  200 +
  201 + process_delayed_job_queue
  202 + jobs = Delayed::Job.all
  203 +
  204 + assert 1, jobs.select{|j| j.failed?}.size
  205 + assert 1, jobs.select{|j| !j.failed?}.size
  206 + end
  207 +
  208 + def notify
  209 + process_delayed_job_queue
  210 + @member.notifier.notify
  211 + end
  212 +
  213 +end
test/unit/person_test.rb
@@ -405,15 +405,14 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -405,15 +405,14 @@ class PersonTest &lt; ActiveSupport::TestCase
405 405
406 should 'not allow simple member to view group pending tasks' do 406 should 'not allow simple member to view group pending tasks' do
407 community = fast_create(Community) 407 community = fast_create(Community)
  408 + admin = fast_create(Person)
  409 + community.add_member(admin)
408 member = fast_create(Person) 410 member = fast_create(Person)
  411 + community.reload
409 community.add_member(member) 412 community.add_member(member)
410 -  
411 community.tasks << Task.new 413 community.tasks << Task.new
412 414
413 - person = fast_create(Person)  
414 - community.add_member(person)  
415 -  
416 - assert_not_includes Person.with_pending_tasks, person 415 + assert_not_includes Person.with_pending_tasks, member
417 end 416 end
418 417
419 should 'person has organization pending tasks' do 418 should 'person has organization pending tasks' do
@@ -643,16 +642,18 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -643,16 +642,18 @@ class PersonTest &lt; ActiveSupport::TestCase
643 end 642 end
644 643
645 should 'find more popular people' do 644 should 'find more popular people' do
  645 + extend CacheCounterHelper
  646 +
646 Person.delete_all 647 Person.delete_all
647 p1 = fast_create(Person) 648 p1 = fast_create(Person)
648 p2 = fast_create(Person) 649 p2 = fast_create(Person)
649 p3 = fast_create(Person) 650 p3 = fast_create(Person)
650 651
651 - p1.add_friend(p2)  
652 - p2.add_friend(p1)  
653 - p2.add_friend(p3)  
654 - assert_equal p2, Person.more_popular.all[0]  
655 - assert_equal p1, Person.more_popular.all[1] 652 + update_cache_counter(:friends_count, p1, 1)
  653 + update_cache_counter(:friends_count, p2, 2)
  654 + update_cache_counter(:friends_count, p3, 3)
  655 +
  656 + assert_order [p3, p2, p1], Person.more_popular
656 end 657 end
657 658
658 should 'list people that have no friends in more popular list' do 659 should 'list people that have no friends in more popular list' do
@@ -892,6 +893,7 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -892,6 +893,7 @@ class PersonTest &lt; ActiveSupport::TestCase
892 p1 = fast_create(Person) 893 p1 = fast_create(Person)
893 p2 = fast_create(Person) 894 p2 = fast_create(Person)
894 p3 = fast_create(Person) 895 p3 = fast_create(Person)
  896 + p4 = fast_create(Person)
895 897
896 community.add_member(p1) 898 community.add_member(p1)
897 assert p1.is_member_of?(community) 899 assert p1.is_member_of?(community)
@@ -902,14 +904,15 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -902,14 +904,15 @@ class PersonTest &lt; ActiveSupport::TestCase
902 904
903 action_tracker = fast_create(ActionTracker::Record, :verb => 'create_article') 905 action_tracker = fast_create(ActionTracker::Record, :verb => 'create_article')
904 action_tracker.target = community 906 action_tracker.target = community
  907 + action_tracker.user = p4
905 action_tracker.save! 908 action_tracker.save!
906 ActionTrackerNotification.delete_all 909 ActionTrackerNotification.delete_all
907 - assert_difference 'ActionTrackerNotification.count', 3 do 910 + assert_difference 'ActionTrackerNotification.count', 4 do
908 Person.notify_activity(action_tracker) 911 Person.notify_activity(action_tracker)
909 process_delayed_job_queue 912 process_delayed_job_queue
910 end 913 end
911 ActionTrackerNotification.all.map{|a|a.profile}.map do |profile| 914 ActionTrackerNotification.all.map{|a|a.profile}.map do |profile|
912 - assert [community,p1,p3].include?(profile) 915 + assert [community,p1,p3,p4].include?(profile)
913 end 916 end
914 end 917 end
915 918
@@ -1012,9 +1015,9 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1012,9 +1015,9 @@ class PersonTest &lt; ActiveSupport::TestCase
1012 1015
1013 should 'the community specific notification created when a member joins community could not be propagated to members' do 1016 should 'the community specific notification created when a member joins community could not be propagated to members' do
1014 ActionTracker::Record.delete_all 1017 ActionTracker::Record.delete_all
1015 - p1 = create_user('test_user').person  
1016 - p2 = create_user('test_user').person  
1017 - p3 = create_user('test_user').person 1018 + p1 = create_user('p1').person
  1019 + p2 = create_user('p2').person
  1020 + p3 = create_user('p3').person
1018 c = fast_create(Community, :name => "Foo") 1021 c = fast_create(Community, :name => "Foo")
1019 c.add_member(p1) 1022 c.add_member(p1)
1020 process_delayed_job_queue 1023 process_delayed_job_queue
@@ -1134,30 +1137,14 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1134,30 +1137,14 @@ class PersonTest &lt; ActiveSupport::TestCase
1134 p3 = fast_create(Person) 1137 p3 = fast_create(Person)
1135 1138
1136 ActionTracker::Record.destroy_all 1139 ActionTracker::Record.destroy_all
1137 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => Time.now)  
1138 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => Time.now)  
1139 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => Time.now)  
1140 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now)  
1141 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now)  
1142 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p3, :created_at => Time.now) 1140 + ActionTracker::Record.create!(:user => p1, :verb => 'leave_scrap')
  1141 + ActionTracker::Record.create!(:user => p2, :verb => 'leave_scrap')
  1142 + ActionTracker::Record.create!(:user => p2, :verb => 'leave_scrap')
  1143 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
  1144 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
  1145 + ActionTracker::Record.create!(:user => p3, :verb => 'leave_scrap')
1143 1146
1144 - assert_equal [p3,p2,p1] , Person.more_active  
1145 - end  
1146 -  
1147 - should 'more active profile take in consideration only actions created only in the recent delay interval' do  
1148 - Person.delete_all  
1149 - ActionTracker::Record.destroy_all  
1150 - recent_delay = ActionTracker::Record::RECENT_DELAY.days.ago  
1151 -  
1152 - p1 = fast_create(Person)  
1153 - p2 = fast_create(Person)  
1154 -  
1155 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => recent_delay)  
1156 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p1, :created_at => recent_delay)  
1157 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => recent_delay)  
1158 - fast_create(ActionTracker::Record, :user_type => 'Profile', :user_id => p2, :created_at => recent_delay - 1.day)  
1159 -  
1160 - assert_equal [p1,p2], Person.more_active 1147 + assert_order [p3,p2,p1] , Person.more_active
1161 end 1148 end
1162 1149
1163 should 'list profiles that have no actions in more active list' do 1150 should 'list profiles that have no actions in more active list' do
@@ -1269,6 +1256,7 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1269,6 +1256,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1269 false 1256 false
1270 end 1257 end
1271 end 1258 end
  1259 + Noosfero::Plugin.stubs(:all).returns(['PersonTest::Plugin1', 'PersonTest::Plugin2'])
1272 1260
1273 e = Environment.default 1261 e = Environment.default
1274 e.enable_plugin(Plugin1.name) 1262 e.enable_plugin(Plugin1.name)
@@ -1415,6 +1403,17 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1415,6 +1403,17 @@ class PersonTest &lt; ActiveSupport::TestCase
1415 assert_equal person.activities, [] 1403 assert_equal person.activities, []
1416 end 1404 end
1417 1405
  1406 + should 'person notifier be PersonNotifier class' do
  1407 + p = Person.new
  1408 + assert p.notifier.kind_of?(PersonNotifier)
  1409 + end
  1410 +
  1411 + should 'reschedule next notification after update' do
  1412 + p = fast_create(Person, :user_id => fast_create(User).id)
  1413 + PersonNotifier.any_instance.expects(:reschedule_next_notification_mail).once
  1414 + assert p.update_attribute(:name, 'Person name changed')
  1415 + end
  1416 +
1418 should 'merge memberships of plugins to original memberships' do 1417 should 'merge memberships of plugins to original memberships' do
1419 class Plugin1 < Noosfero::Plugin 1418 class Plugin1 < Noosfero::Plugin
1420 def person_memberships(person) 1419 def person_memberships(person)
@@ -1427,6 +1426,7 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1427,6 +1426,7 @@ class PersonTest &lt; ActiveSupport::TestCase
1427 Profile.memberships_of(Person.find_by_identifier('person2')) 1426 Profile.memberships_of(Person.find_by_identifier('person2'))
1428 end 1427 end
1429 end 1428 end
  1429 + Noosfero::Plugin.stubs(:all).returns(['PersonTest::Plugin1', 'PersonTest::Plugin2'])
1430 1430
1431 Environment.default.enable_plugin(Plugin1) 1431 Environment.default.enable_plugin(Plugin1)
1432 Environment.default.enable_plugin(Plugin2) 1432 Environment.default.enable_plugin(Plugin2)
@@ -1447,4 +1447,30 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -1447,4 +1447,30 @@ class PersonTest &lt; ActiveSupport::TestCase
1447 assert_equal 3, original_person.memberships.count 1447 assert_equal 3, original_person.memberships.count
1448 end 1448 end
1449 1449
  1450 + should 'increase friends_count on new friendship' do
  1451 + person = create_user('person').person
  1452 + friend = create_user('friend').person
  1453 + assert_difference person, :friends_count, 1 do
  1454 + assert_difference friend, :friends_count, 1 do
  1455 + person.add_friend(friend)
  1456 + friend.reload
  1457 + end
  1458 + person.reload
  1459 + end
  1460 + end
  1461 +
  1462 + should 'decrease friends_count on friendship removal' do
  1463 + person = create_user('person').person
  1464 + friend = create_user('friend').person
  1465 + person.add_friend(friend)
  1466 + friend.reload
  1467 + person.reload
  1468 + assert_difference person, :friends_count, -1 do
  1469 + assert_difference friend, :friends_count, -1 do
  1470 + person.remove_friend(friend)
  1471 + friend.reload
  1472 + end
  1473 + person.reload
  1474 + end
  1475 + end
1450 end 1476 end
test/unit/plugin_manager_test.rb
@@ -26,6 +26,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -26,6 +26,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
26 class Plugin2 < Noosfero::Plugin; end; 26 class Plugin2 < Noosfero::Plugin; end;
27 class Plugin3 < Noosfero::Plugin; end; 27 class Plugin3 < Noosfero::Plugin; end;
28 class Plugin4 < Noosfero::Plugin; end; 28 class Plugin4 < Noosfero::Plugin; end;
  29 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3', 'PluginManagerTest::Plugin4'])
29 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s]) 30 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s])
30 Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s]) 31 Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s])
31 results = plugins.enabled_plugins.map { |instance| instance.class.to_s } 32 results = plugins.enabled_plugins.map { |instance| instance.class.to_s }
@@ -51,6 +52,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -51,6 +52,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
51 'Plugin 2 action.' 52 'Plugin 2 action.'
52 end 53 end
53 end 54 end
  55 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
54 56
55 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s]) 57 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s])
56 58
@@ -83,6 +85,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -83,6 +85,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
83 'Plugin 3 action.' 85 'Plugin 3 action.'
84 end 86 end
85 end 87 end
  88 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
86 89
87 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin3.to_s]) 90 environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin3.to_s])
88 p1 = Plugin1.new 91 p1 = Plugin1.new
@@ -107,6 +110,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -107,6 +110,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
107 'Plugin3' 110 'Plugin3'
108 end 111 end
109 end 112 end
  113 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
110 114
111 environment.enable_plugin(Plugin1.name) 115 environment.enable_plugin(Plugin1.name)
112 environment.enable_plugin(Plugin2.name) 116 environment.enable_plugin(Plugin2.name)
@@ -134,6 +138,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -134,6 +138,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
134 true 138 true
135 end 139 end
136 end 140 end
  141 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
137 142
138 environment.enable_plugin(Plugin1.name) 143 environment.enable_plugin(Plugin1.name)
139 environment.enable_plugin(Plugin2.name) 144 environment.enable_plugin(Plugin2.name)
@@ -162,6 +167,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -162,6 +167,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
162 true 167 true
163 end 168 end
164 end 169 end
  170 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2', 'PluginManagerTest::Plugin3'])
165 171
166 environment.enable_plugin(Plugin1.name) 172 environment.enable_plugin(Plugin1.name)
167 environment.enable_plugin(Plugin2.name) 173 environment.enable_plugin(Plugin2.name)
@@ -178,6 +184,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -178,6 +184,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
178 [Macro1, Macro2] 184 [Macro1, Macro2]
179 end 185 end
180 end 186 end
  187 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1'])
181 188
182 class Plugin1::Macro1 < Noosfero::Plugin::Macro 189 class Plugin1::Macro1 < Noosfero::Plugin::Macro
183 def convert(macro, source) 190 def convert(macro, source)
@@ -212,6 +219,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -212,6 +219,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
212 [v1 * v, v2 * v] 219 [v1 * v, v2 * v]
213 end 220 end
214 end 221 end
  222 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
215 223
216 environment.enable_plugin(Plugin1) 224 environment.enable_plugin(Plugin1)
217 environment.enable_plugin(Plugin2) 225 environment.enable_plugin(Plugin2)
@@ -231,6 +239,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -231,6 +239,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
231 value * 5 239 value * 5
232 end 240 end
233 end 241 end
  242 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
234 243
235 environment.enable_plugin(Plugin1) 244 environment.enable_plugin(Plugin1)
236 environment.enable_plugin(Plugin2) 245 environment.enable_plugin(Plugin2)
@@ -252,6 +261,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -252,6 +261,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
252 [v1 * v, v2 * v, 666] 261 [v1 * v, v2 * v, 666]
253 end 262 end
254 end 263 end
  264 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
255 265
256 environment.enable_plugin(Plugin1) 266 environment.enable_plugin(Plugin1)
257 environment.enable_plugin(Plugin2) 267 environment.enable_plugin(Plugin2)
@@ -273,6 +283,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase @@ -273,6 +283,7 @@ class PluginManagerTest &lt; ActiveSupport::TestCase
273 numbers.reject {|n| n<=5} 283 numbers.reject {|n| n<=5}
274 end 284 end
275 end 285 end
  286 + Noosfero::Plugin.stubs(:all).returns(['PluginManagerTest::Plugin1', 'PluginManagerTest::Plugin2'])
276 287
277 environment.enable_plugin(Plugin1) 288 environment.enable_plugin(Plugin1)
278 environment.enable_plugin(Plugin2) 289 environment.enable_plugin(Plugin2)
test/unit/plugin_test.rb
@@ -9,15 +9,9 @@ class PluginTest &lt; ActiveSupport::TestCase @@ -9,15 +9,9 @@ class PluginTest &lt; ActiveSupport::TestCase
9 9
10 include Noosfero::Plugin::HotSpot 10 include Noosfero::Plugin::HotSpot
11 11
12 - should 'keep the list of all loaded subclasses' do  
13 - class Plugin1 < Noosfero::Plugin  
14 - end  
15 -  
16 - class Plugin2 < Noosfero::Plugin  
17 - end  
18 -  
19 - assert_includes Noosfero::Plugin.all, Plugin1.to_s  
20 - assert_includes Noosfero::Plugin.all, Plugin2.to_s 12 + should 'keep the list of all available plugins' do
  13 + assert File.directory?(File.join(Rails.root, 'plugins', 'foo'))
  14 + assert_includes Noosfero::Plugin.all, 'FooPlugin'
21 end 15 end
22 16
23 should 'returns url to plugin management if plugin has admin_controller' do 17 should 'returns url to plugin management if plugin has admin_controller' do
@@ -496,4 +490,29 @@ class PluginTest &lt; ActiveSupport::TestCase @@ -496,4 +490,29 @@ class PluginTest &lt; ActiveSupport::TestCase
496 end 490 end
497 end 491 end
498 492
  493 + should 'comment_actions be nil if the comment is nil' do
  494 + class SomePlugin < Noosfero::Plugin; end
  495 + plugin = SomePlugin.new
  496 + assert_nil plugin.comment_actions(nil)
  497 + end
  498 +
  499 + should 'comment_actions be nil by default' do
  500 + class SomePlugin < Noosfero::Plugin; end
  501 + plugin = SomePlugin.new
  502 + assert_nil plugin.comment_actions(Comment.new)
  503 + end
  504 +
  505 + should 'check_comment_actions be an empty array if the comment is nil' do
  506 + class SomePlugin < Noosfero::Plugin; end
  507 + plugin = SomePlugin.new
  508 + assert_equal [], plugin.check_comment_actions(nil)
  509 + end
  510 +
  511 +
  512 + should 'check_comment_actions be an empty array by default' do
  513 + class SomePlugin < Noosfero::Plugin; end
  514 + plugin = SomePlugin.new
  515 + assert_equal [], plugin.check_comment_actions(Comment.new)
  516 + end
  517 +
499 end 518 end
test/unit/profile_test.rb
@@ -364,7 +364,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -364,7 +364,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
364 t2 = c.tasks.build; t2.save!; t2.finish 364 t2 = c.tasks.build; t2.save!; t2.finish
365 t3 = c.tasks.build; t3.save!; t3.finish 365 t3 = c.tasks.build; t3.save!; t3.finish
366 366
367 - assert_equal [t2, t3], c.tasks.finished 367 + assert_equivalent [t2, t3], c.tasks.finished
368 end 368 end
369 369
370 should 'responds to categories' do 370 should 'responds to categories' do
@@ -1689,6 +1689,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1689,6 +1689,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1689 person = fast_create(Person) 1689 person = fast_create(Person)
1690 community = fast_create(Community) 1690 community = fast_create(Community)
1691 community.add_member(person) 1691 community.add_member(person)
  1692 + community.reload
1692 1693
1693 assert_equal 1, community.members_count 1694 assert_equal 1, community.members_count
1694 end 1695 end
@@ -1812,6 +1813,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1812,6 +1813,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1812 Person.members_of(Community.find_by_identifier('community2')) 1813 Person.members_of(Community.find_by_identifier('community2'))
1813 end 1814 end
1814 end 1815 end
  1816 + Noosfero::Plugin.stubs(:all).returns(['ProfileTest::Plugin1', 'ProfileTest::Plugin2'])
1815 Environment.default.enable_plugin(Plugin1) 1817 Environment.default.enable_plugin(Plugin1)
1816 Environment.default.enable_plugin(Plugin2) 1818 Environment.default.enable_plugin(Plugin2)
1817 1819
@@ -1824,6 +1826,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1824,6 +1826,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1824 original_community.add_member(original_member) 1826 original_community.add_member(original_member)
1825 community1.add_member(plugin1_member) 1827 community1.add_member(plugin1_member)
1826 community2.add_member(plugin2_member) 1828 community2.add_member(plugin2_member)
  1829 + original_community.reload
1827 1830
1828 assert_includes original_community.members, original_member 1831 assert_includes original_community.members, original_member
1829 assert_includes original_community.members, plugin1_member 1832 assert_includes original_community.members, plugin1_member
@@ -1968,6 +1971,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1968,6 +1971,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1968 end 1971 end
1969 1972
1970 environment = Environment.default 1973 environment = Environment.default
  1974 + Noosfero::Plugin.stubs(:all).returns(['ProfileTest::Plugin1'])
1971 environment.enable_plugin(Plugin1) 1975 environment.enable_plugin(Plugin1)
1972 plugins = Noosfero::Plugin::Manager.new(environment, self) 1976 plugins = Noosfero::Plugin::Manager.new(environment, self)
1973 p = fast_create(Profile) 1977 p = fast_create(Profile)
test/unit/role_assignment_ext_test.rb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class RoleAssignmentExtTest < ActiveSupport::TestCase
  4 + should 'increase organization members_count only on the first role_assignment' do
  5 + role1 = Role.create!(:name => 'role1')
  6 + role2 = Role.create!(:name => 'role2')
  7 + member = create_user('person').person
  8 + organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
  9 + assert_difference organization, :members_count, 1 do
  10 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
  11 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  12 + organization.reload
  13 + end
  14 + end
  15 +
  16 + should 'decrease organization members_count only on the last role_assignment' do
  17 + role1 = Role.create!(:name => 'role1')
  18 + role2 = Role.create!(:name => 'role2')
  19 + member = create_user('person').person
  20 + organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
  21 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
  22 + RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  23 + organization.reload
  24 + assert_difference organization, :members_count, -1 do
  25 + organization.role_assignments.destroy_all
  26 + organization.reload
  27 + end
  28 + end
  29 +end
test/unit/suggest_article_test.rb
@@ -7,6 +7,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -7,6 +7,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
7 ActionMailer::Base.perform_deliveries = true 7 ActionMailer::Base.perform_deliveries = true
8 ActionMailer::Base.deliveries = [] 8 ActionMailer::Base.deliveries = []
9 @profile = create_user('test_user').person 9 @profile = create_user('test_user').person
  10 + Noosfero::Plugin.stubs(:all).returns(['SuggestArticleTest::EverythingIsSpam', 'SuggestArticleTest::SpamNotification'])
10 end 11 end
11 attr_reader :profile 12 attr_reader :profile
12 13
test/unit/tags_helper_test.rb
@@ -21,12 +21,14 @@ class TagsHelperTest &lt; ActiveSupport::TestCase @@ -21,12 +21,14 @@ class TagsHelperTest &lt; ActiveSupport::TestCase
21 21
22 should 'order tags alphabetically with special characters' do 22 should 'order tags alphabetically with special characters' do
23 result = tag_cloud( 23 result = tag_cloud(
24 - { 'aula'=>9, 'área'=>2, 'area'=>2, 'avião'=>2, 'armário'=>2,  
25 - 'A'=>1, 'Á'=>1, 'AB'=>1, 'ÁA'=>1 }, 24 + { 'area'=>9, 'área'=>2, 'base'=>2, 'báse' => 3,
  25 + 'A'=>1, 'Á'=>1, 'zebra'=>1, 'zebrá'=>1 },
26 :id, 26 :id,
27 { :host=>'noosfero.org', :controller=>'test', :action=>'tag' } 27 { :host=>'noosfero.org', :controller=>'test', :action=>'tag' }
28 ) 28 )
29 - assert_equal %w(A Á ÁA AB area área armário aula avião).join("\n"), result 29 + result = result.split("\n")
  30 + assert_order ['Á', 'área', 'báse', 'zebrá'], result
  31 + assert_order ['A', 'area', 'base', 'zebra'], result
30 end 32 end
31 33
32 end 34 end
test/unit/task_mailer_test.rb
@@ -22,7 +22,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -22,7 +22,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
22 requestor.expects(:name).returns('my name') 22 requestor.expects(:name).returns('my name')
23 23
24 environment = mock() 24 environment = mock()
25 - environment.expects(:contact_email).returns('sender@example.com') 25 + environment.expects(:noreply_email).returns('sender@example.com')
26 environment.expects(:default_hostname).returns('example.com') 26 environment.expects(:default_hostname).returns('example.com')
27 environment.expects(:name).returns('example').at_least_once 27 environment.expects(:name).returns('example').at_least_once
28 28
@@ -45,7 +45,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -45,7 +45,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
45 requestor.expects(:name).returns('my name') 45 requestor.expects(:name).returns('my name')
46 46
47 environment = mock() 47 environment = mock()
48 - environment.expects(:contact_email).returns('sender@example.com') 48 + environment.expects(:noreply_email).returns('sender@example.com')
49 environment.expects(:default_hostname).returns('example.com') 49 environment.expects(:default_hostname).returns('example.com')
50 environment.expects(:name).returns('example').at_least_once 50 environment.expects(:name).returns('example').at_least_once
51 51
@@ -69,7 +69,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -69,7 +69,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
69 requestor.expects(:name).returns('my name') 69 requestor.expects(:name).returns('my name')
70 70
71 environment = mock() 71 environment = mock()
72 - environment.expects(:contact_email).returns('sender@example.com') 72 + environment.expects(:noreply_email).returns('sender@example.com')
73 environment.expects(:default_hostname).returns('example.com') 73 environment.expects(:default_hostname).returns('example.com')
74 environment.expects(:name).returns('example').at_least_once 74 environment.expects(:name).returns('example').at_least_once
75 75
@@ -105,7 +105,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -105,7 +105,7 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
105 requestor.stubs(:public_profile_url).returns('requestor_path') 105 requestor.stubs(:public_profile_url).returns('requestor_path')
106 106
107 environment = mock() 107 environment = mock()
108 - environment.expects(:contact_email).returns('sender@example.com') 108 + environment.expects(:noreply_email).returns('sender@example.com')
109 environment.expects(:default_hostname).returns('example.com') 109 environment.expects(:default_hostname).returns('example.com')
110 environment.expects(:name).returns('example').at_least_once 110 environment.expects(:name).returns('example').at_least_once
111 111
@@ -124,11 +124,11 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -124,11 +124,11 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
124 assert !ActionMailer::Base.deliveries.empty? 124 assert !ActionMailer::Base.deliveries.empty?
125 end 125 end
126 126
127 - should 'use environment name and contact email' do 127 + should 'use environment name and no-reply email' do
128 task = mock 128 task = mock
129 environment = mock 129 environment = mock
130 environment.expects(:name).returns('My name') 130 environment.expects(:name).returns('My name')
131 - environment.expects(:contact_email).returns('email@example.com') 131 + environment.expects(:noreply_email).returns('email@example.com')
132 132
133 task.expects(:environment).returns(environment).at_least_once 133 task.expects(:environment).returns(environment).at_least_once
134 134
test/unit/text_article_test.rb
@@ -38,4 +38,51 @@ class TextArticleTest &lt; ActiveSupport::TestCase @@ -38,4 +38,51 @@ class TextArticleTest &lt; ActiveSupport::TestCase
38 assert_equal Blog.icon_name, TextArticle.icon_name(article) 38 assert_equal Blog.icon_name, TextArticle.icon_name(article)
39 end 39 end
40 40
  41 + should 'change image path to relative' do
  42 + person = create_user('testuser').person
  43 + article = TextArticle.new(:profile => person, :name => 'test')
  44 + env = Environment.default
  45 + article.body = "<img src=\"http://#{env.default_hostname}/test.png\" />"
  46 + article.save!
  47 + assert_equal "<img src=\"/test.png\" />", article.body
  48 + end
  49 +
  50 + should 'change link to relative path' do
  51 + person = create_user('testuser').person
  52 + article = TextArticle.new(:profile => person, :name => 'test')
  53 + env = Environment.default
  54 + article.body = "<a href=\"http://#{env.default_hostname}/test\">test</a>"
  55 + article.save!
  56 + assert_equal "<a href=\"/test\">test</a>", article.body
  57 + end
  58 +
  59 + should 'change image path to relative for domain with https' do
  60 + person = create_user('testuser').person
  61 + article = TextArticle.new(:profile => person, :name => 'test')
  62 + env = Environment.default
  63 + article.body = "<img src=\"https://#{env.default_hostname}/test.png\" />"
  64 + article.save!
  65 + assert_equal "<img src=\"/test.png\" />", article.body
  66 + end
  67 +
  68 + should 'change image path to relative for domain with port' do
  69 + person = create_user('testuser').person
  70 + article = TextArticle.new(:profile => person, :name => 'test')
  71 + env = Environment.default
  72 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />"
  73 + article.save!
  74 + assert_equal "<img src=\"/test.png\" />", article.body
  75 + end
  76 +
  77 + should 'change image path to relative for domain with www' do
  78 + person = create_user('testuser').person
  79 + article = TextArticle.new(:profile => person, :name => 'test')
  80 + env = Environment.default
  81 + env.force_www = true
  82 + env.save!
  83 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />"
  84 + article.save!
  85 + assert_equal "<img src=\"/test.png\" />", article.body
  86 + end
  87 +
41 end 88 end
test/unit/theme_test.rb
@@ -191,4 +191,22 @@ class ThemeTest &lt; ActiveSupport::TestCase @@ -191,4 +191,22 @@ class ThemeTest &lt; ActiveSupport::TestCase
191 assert ! Theme.new('test').public 191 assert ! Theme.new('test').public
192 end 192 end
193 193
  194 + should 'not crash with nil or invalid owner_type' do
  195 + profile = fast_create(Profile)
  196 + Theme.stubs(:system_themes_dir).returns(TMP_THEMES_DIR)
  197 +
  198 + t1 = Theme.new('t1').save
  199 + t1.send(:write_config)
  200 + t2 = Theme.new('t2', {:owner_type => nil}).save
  201 + t2.send(:write_config)
  202 + t3 = Theme.new('t3', {:owner_type => 'InvalidClass'}).save
  203 + t3.send(:write_config)
  204 +
  205 + assert_nothing_raised do
  206 + themes = Theme.approved_themes(profile)
  207 + assert_not_includes themes, t1
  208 + assert_not_includes themes, t2
  209 + assert_not_includes themes, t3
  210 + end
  211 + end
194 end 212 end
test/unit/uploaded_file_test.rb
@@ -31,6 +31,13 @@ class UploadedFileTest &lt; ActiveSupport::TestCase @@ -31,6 +31,13 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
31 assert_equal 'test.txt', file.name 31 assert_equal 'test.txt', file.name
32 end 32 end
33 33
  34 + should 'not set filename on name if name is already set' do
  35 + file = UploadedFile.new
  36 + file.name = "Some name"
  37 + file.filename = 'test.txt'
  38 + assert_equal 'Some name', file.name
  39 + end
  40 +
34 should 'provide file content as data' do 41 should 'provide file content as data' do
35 file = UploadedFile.new 42 file = UploadedFile.new
36 file.expects(:full_filename).returns('myfilename') 43 file.expects(:full_filename).returns('myfilename')
@@ -121,23 +128,13 @@ class UploadedFileTest &lt; ActiveSupport::TestCase @@ -121,23 +128,13 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
121 assert_equal 'my title', build(UploadedFile, :title => 'my title').title 128 assert_equal 'my title', build(UploadedFile, :title => 'my title').title
122 end 129 end
123 130
124 - should 'limit title to 140 characters' do  
125 - upload = UploadedFile.new  
126 -  
127 - upload.title = '+' * 61; upload.valid?  
128 - assert upload.errors[:title]  
129 -  
130 - upload.title = '+' * 60; upload.valid?  
131 - assert_blank upload.errors[:title]  
132 - end  
133 -  
134 should 'always provide a display title' do 131 should 'always provide a display title' do
135 upload = build(UploadedFile, :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain')) 132 upload = build(UploadedFile, :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'))
136 - assert_equal 'test.txt', upload.display_title 133 + assert_equal 'test.txt', upload.title
137 upload.title = 'My text file' 134 upload.title = 'My text file'
138 - assert_equal 'My text file', upload.display_title 135 + assert_equal 'My text file', upload.title
139 upload.title = '' 136 upload.title = ''
140 - assert_equal 'test.txt', upload.display_title 137 + assert_equal 'test.txt', upload.title
141 end 138 end
142 139
143 should 'use name as title by default' do 140 should 'use name as title by default' do
@@ -327,6 +324,7 @@ class UploadedFileTest &lt; ActiveSupport::TestCase @@ -327,6 +324,7 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
327 end 324 end
328 325
329 should 'group trackers activity of image\'s upload' do 326 should 'group trackers activity of image\'s upload' do
  327 + ActionTracker::Record.delete_all
330 gallery = fast_create(Gallery, :profile_id => profile.id) 328 gallery = fast_create(Gallery, :profile_id => profile.id)
331 329
332 image1 = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile) 330 image1 = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile)
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb
@@ -5,8 +5,8 @@ Delayed::Worker.module_eval do @@ -5,8 +5,8 @@ Delayed::Worker.module_eval do
5 environment = Environment.default 5 environment = Environment.default
6 6
7 recipients NOOSFERO_CONF['exception_recipients'] 7 recipients NOOSFERO_CONF['exception_recipients']
8 - from environment.contact_email  
9 - reply_to environment.contact_email 8 + from environment.noreply_email
  9 + reply_to environment.noreply_email
10 subject "[#{environment.name}] DelayedJob ##{job.id}: #{error.message}" 10 subject "[#{environment.name}] DelayedJob ##{job.id}: #{error.message}"
11 body render(:text => " 11 body render(:text => "
12 Job: 12 Job: